Merge branch 'master' of github.com:Araq/Nimrod

This commit is contained in:
Araq 2011-11-26 10:49:48 +01:00
commit 840979b45c
14 changed files with 587 additions and 389 deletions

View file

@ -244,6 +244,10 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
of "out", "o": of "out", "o":
expectArg(switch, arg, pass, info) expectArg(switch, arg, pass, info)
options.outFile = arg options.outFile = arg
of "mainmodule", "m":
expectArg(switch, arg, pass, info)
projectName = arg
projectFullPath = projectPath/projectName
of "define", "d": of "define", "d":
expectArg(switch, arg, pass, info) expectArg(switch, arg, pass, info)
DefineSymbol(arg) DefineSymbol(arg)
@ -335,13 +339,22 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
case arg.normalize case arg.normalize
of "gui": of "gui":
incl(gGlobalOptions, optGenGuiApp) incl(gGlobalOptions, optGenGuiApp)
defineSymbol("executable")
defineSymbol("guiapp") defineSymbol("guiapp")
of "console": of "console":
excl(gGlobalOptions, optGenGuiApp) excl(gGlobalOptions, optGenGuiApp)
defineSymbol("executable")
defineSymbol("consoleapp")
of "lib": of "lib":
incl(gGlobalOptions, optGenDynLib) incl(gGlobalOptions, optGenDynLib)
excl(gGlobalOptions, optGenGuiApp) excl(gGlobalOptions, optGenGuiApp)
defineSymbol("library") defineSymbol("library")
defineSymbol("dll")
of "staticlib":
incl(gGlobalOptions, optGenStaticLib)
excl(gGlobalOptions, optGenGuiApp)
defineSymbol("library")
defineSymbol("staticlib")
else: LocalError(info, errGuiConsoleOrLibExpectedButXFound, arg) else: LocalError(info, errGuiConsoleOrLibExpectedButXFound, arg)
of "passc", "t": of "passc", "t":
expectArg(switch, arg, pass, info) expectArg(switch, arg, pass, info)
@ -349,12 +362,24 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
of "passl", "l": of "passl", "l":
expectArg(switch, arg, pass, info) expectArg(switch, arg, pass, info)
if pass in {passCmd2, passPP}: extccomp.addLinkOption(arg) if pass in {passCmd2, passPP}: extccomp.addLinkOption(arg)
of "cincludes":
expectArg(switch, arg, pass, info)
if pass in {passCmd2, passPP}: cIncludes.add arg
of "clibdir":
expectArg(switch, arg, pass, info)
if pass in {passCmd2, passPP}: cLibs.add arg
of "clib":
expectArg(switch, arg, pass, info)
if pass in {passCmd2, passPP}: cLinkedLibs.add arg
of "index": of "index":
expectArg(switch, arg, pass, info) expectArg(switch, arg, pass, info)
if pass in {passCmd2, passPP}: gIndexFile = arg if pass in {passCmd2, passPP}: gIndexFile = arg
of "import": of "import":
expectArg(switch, arg, pass, info) expectArg(switch, arg, pass, info)
options.addImplicitMod(arg) if pass in {passCmd2, passPP}: implicitImports.add arg
of "include":
expectArg(switch, arg, pass, info)
if pass in {passCmd2, passPP}: implicitIncludes.add arg
of "listcmd": of "listcmd":
expectNoArg(switch, arg, pass, info) expectNoArg(switch, arg, pass, info)
incl(gGlobalOptions, optListCmd) incl(gGlobalOptions, optListCmd)
@ -405,6 +430,9 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
of "skipprojcfg": of "skipprojcfg":
expectNoArg(switch, arg, pass, info) expectNoArg(switch, arg, pass, info)
incl(gGlobalOptions, optSkipProjConfigFile) incl(gGlobalOptions, optSkipProjConfigFile)
of "skipusercfg":
expectNoArg(switch, arg, pass, info)
incl(gGlobalOptions, optSkipUserConfigFile)
of "genscript": of "genscript":
expectNoArg(switch, arg, pass, info) expectNoArg(switch, arg, pass, info)
incl(gGlobalOptions, optGenScript) incl(gGlobalOptions, optGenScript)

View file

@ -15,9 +15,9 @@ import
ast, astalgo, strutils, hashes, options, nversion, msgs, os, ropes, idents, ast, astalgo, strutils, hashes, options, nversion, msgs, os, ropes, idents,
wordrecg, math, syntaxes, renderer, lexer, rst, times, highlite wordrecg, math, syntaxes, renderer, lexer, rst, times, highlite
proc CommandDoc*(filename: string) proc CommandDoc*()
proc CommandRst2Html*(filename: string) proc CommandRst2Html*()
proc CommandRst2TeX*(filename: string) proc CommandRst2TeX*()
# implementation # implementation
type type
@ -870,14 +870,14 @@ proc writeOutput(d: PDoc, filename, outExt: string) =
else: else:
writeRope(content, getOutFile(filename, outExt)) writeRope(content, getOutFile(filename, outExt))
proc CommandDoc(filename: string) = proc CommandDoc =
var ast = parseFile(addFileExt(filename, nimExt)) var ast = parseFile(addFileExt(projectFullPath, nimExt))
if ast == nil: return if ast == nil: return
var d = newDocumentor(filename) var d = newDocumentor(projectFullPath)
initIndexFile(d) initIndexFile(d)
d.hasToc = true d.hasToc = true
generateDoc(d, ast) generateDoc(d, ast)
writeOutput(d, filename, HtmlExt) writeOutput(d, projectFullPath, HtmlExt)
generateIndex(d) generateIndex(d)
proc CommandRstAux(filename, outExt: string) = proc CommandRstAux(filename, outExt: string) =
@ -889,9 +889,10 @@ proc CommandRstAux(filename, outExt: string) =
writeOutput(d, filename, outExt) writeOutput(d, filename, outExt)
generateIndex(d) generateIndex(d)
proc CommandRst2Html(filename: string) = proc CommandRst2Html =
CommandRstAux(filename, HtmlExt) CommandRstAux(projectFullPath, HtmlExt)
proc CommandRst2TeX(filename: string) = proc CommandRst2TeX =
splitter = "\\-" splitter = "\\-"
CommandRstAux(filename, TexExt) CommandRstAux(projectFullPath, TexExt)

View file

@ -32,18 +32,29 @@ type
compileTmpl: string, # the compile command template compileTmpl: string, # the compile command template
buildGui: string, # command to build a GUI application buildGui: string, # command to build a GUI application
buildDll: string, # command to build a shared library buildDll: string, # command to build a shared library
buildLib: string, # command to build a static library
linkerExe: string, # the linker's executable linkerExe: string, # the linker's executable
linkTmpl: string, # command to link files to produce an exe linkTmpl: string, # command to link files to produce an exe
includeCmd: string, # command to add an include dir includeCmd: string, # command to add an include dir
linkDirCmd: string, # command to add a lib dir
linkLibCmd: string, # command to link an external library
debug: string, # flags for debug build debug: string, # flags for debug build
pic: string, # command for position independent code pic: string, # command for position independent code
# used on some platforms # used on some platforms
asmStmtFrmt: string, # format of ASM statement asmStmtFrmt: string, # format of ASM statement
props: TInfoCCProps] # properties of the C compiler props: TInfoCCProps] # properties of the C compiler
const
CC*: array[succ(low(TSystemCC))..high(TSystemCC), TInfoCC] = [ # Configuration settings for various compilers.
(name: "gcc", # When adding new compilers, the cmake sources could be a good reference:
# http://cmake.org/gitweb?p=cmake.git;a=tree;f=Modules/Platform;
template compiler(name: expr, settings: stmt):stmt =
proc name: TInfoCC {.compileTime.} = settings
compiler gcc:
result = (
name: "gcc",
objExt: "o", objExt: "o",
optSpeed: " -O3 -ffast-math ", optSpeed: " -O3 -ffast-math ",
optSize: " -Os -ffast-math ", optSize: " -Os -ffast-math ",
@ -51,104 +62,47 @@ const
compileTmpl: "-c $options $include -o $objfile $file", compileTmpl: "-c $options $include -o $objfile $file",
buildGui: " -mwindows", buildGui: " -mwindows",
buildDll: " -shared", buildDll: " -shared",
buildLib: "ar rcs $libfile $objfiles",
linkerExe: "gcc", linkerExe: "gcc",
linkTmpl: "$buildgui $builddll -o $exefile $objfiles $options", linkTmpl: "$buildgui $builddll -o $exefile $objfiles $options",
includeCmd: " -I", includeCmd: " -I",
linkDirCmd: " -L",
linkLibCmd: " -l$1",
debug: "", debug: "",
pic: "-fPIC", pic: "-fPIC",
asmStmtFrmt: "asm($1);$n", asmStmtFrmt: "asm($1);$n",
props: {hasSwitchRange, hasComputedGoto, hasCpp}), props: {hasSwitchRange, hasComputedGoto, hasCpp})
(name: "llvm_gcc",
objExt: "o", compiler gpp:
optSpeed: " -O3 -ffast-math ", result = gcc()
optSize: " -Os -ffast-math ",
compilerExe: "llvm-gcc", result.name = "gpp"
compileTmpl: "-c $options $include -o $objfile $file", result.compilerExe = "g++"
buildGui: " -mwindows", result.linkerExe = "g++"
buildDll: " -shared",
linkerExe: "llvm-gcc", result.debug.add " -g " # XXX: Why is this default for g++, but not for gcc?
linkTmpl: "$buildgui $builddll -o $exefile $objfiles $options",
includeCmd: " -I", result.buildDll = " -mdll" # XXX: Hmm, I'm keeping this from the previos version,
debug: "", # but my gcc doesn't even have such an option (is this mingw?)
pic: "-fPIC",
asmStmtFrmt: "asm($1);$n", compiler llvmGcc:
props: {hasSwitchRange, hasComputedGoto, hasCpp}), result = gcc()
(name: "clang",
objExt: "o", result.name = "llvm_gcc"
optSpeed: " -O3 -ffast-math ", result.compilerExe = "llvm-gcc"
optSize: " -Os -ffast-math ", result.buildLib = "llvm-ar rcs $libfile $objfiles"
compilerExe: "clang", result.linkerExe = "llvm-gcc"
compileTmpl: "-c $options $include -o $objfile $file",
buildGui: " -mwindows", compiler clang:
buildDll: " -shared", result = llvmGcc()
linkerExe: "clang",
linkTmpl: "$buildgui $builddll -o $exefile $objfiles $options", result.name = "clang"
includeCmd: " -I", result.compilerExe = "clang"
debug: "", result.linkerExe = "clang"
pic: "-fPIC",
asmStmtFrmt: "asm($1);$n", compiler vcc:
props: {hasSwitchRange, hasComputedGoto, hasCpp}), result = (
(name: "lcc", name: "vcc",
objExt: "obj",
optSpeed: " -O -p6 ",
optSize: " -O -p6 ",
compilerExe: "lcc",
compileTmpl: "$options $include -Fo$objfile $file",
buildGui: " -subsystem windows",
buildDll: " -dll",
linkerExe: "lcclnk",
linkTmpl: "$options $buildgui $builddll -O $exefile $objfiles",
includeCmd: " -I",
debug: " -g5 ",
pic: "",
asmStmtFrmt: "_asm{$n$1$n}$n",
props: {}),
(name: "bcc",
objExt: "obj",
optSpeed: " -O2 -6 ",
optSize: " -O1 -6 ",
compilerExe: "bcc32",
compileTmpl: "-c $options $include -o$objfile $file",
buildGui: " -tW",
buildDll: " -tWD",
linkerExe: "bcc32",
linkTmpl: "$options $buildgui $builddll -e$exefile $objfiles",
includeCmd: " -I",
debug: "",
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
props: {hasCpp}),
(name: "dmc",
objExt: "obj",
optSpeed: " -ff -o -6 ",
optSize: " -ff -o -6 ",
compilerExe: "dmc",
compileTmpl: "-c $options $include -o$objfile $file",
buildGui: " -L/exet:nt/su:windows",
buildDll: " -WD",
linkerExe: "dmc",
linkTmpl: "$options $buildgui $builddll -o$exefile $objfiles",
includeCmd: " -I",
debug: " -g ",
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
props: {hasCpp}),
(name: "wcc",
objExt: "obj",
optSpeed: " -ox -on -6 -d0 -fp6 -zW ",
optSize: "",
compilerExe: "wcl386",
compileTmpl: "-c $options $include -fo=$objfile $file",
buildGui: " -bw",
buildDll: " -bd",
linkerExe: "wcl386",
linkTmpl: "$options $buildgui $builddll -fe=$exefile $objfiles ",
includeCmd: " -i=",
debug: " -d2 ",
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
props: {hasCpp}),
(name: "vcc",
objExt: "obj", objExt: "obj",
optSpeed: " /Ogityb2 /G7 /arch:SSE2 ", optSpeed: " /Ogityb2 /G7 /arch:SSE2 ",
optSize: " /O1 /G7 ", optSize: " /O1 /G7 ",
@ -156,14 +110,115 @@ const
compileTmpl: "/c $options $include /Fo$objfile $file", compileTmpl: "/c $options $include /Fo$objfile $file",
buildGui: " /link /SUBSYSTEM:WINDOWS ", buildGui: " /link /SUBSYSTEM:WINDOWS ",
buildDll: " /LD", buildDll: " /LD",
buildLib: "lib /OUT:$libfile $objfiles",
linkerExe: "cl", linkerExe: "cl",
linkTmpl: "$options $builddll /Fe$exefile $objfiles $buildgui", linkTmpl: "$options $builddll /Fe$exefile $objfiles $buildgui",
includeCmd: " /I", includeCmd: " /I",
linkDirCmd: " /LIBPATH:",
linkLibCmd: " $1.lib",
debug: " /GZ /Zi ", debug: " /GZ /Zi ",
pic: "", pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n", asmStmtFrmt: "__asm{$n$1$n}$n",
props: {hasCpp, hasAssume}), props: {hasCpp, hasAssume})
(name: "tcc",
compiler icc:
# Intel compilers try to imitate the native ones (gcc and msvc)
when defined(windows):
result = vcc()
else:
result = gcc()
result.name = "icc"
result.compilerExe = "icc"
result.linkerExe = "icc"
compiler lcc:
result = (
name: "lcc",
objExt: "obj",
optSpeed: " -O -p6 ",
optSize: " -O -p6 ",
compilerExe: "lcc",
compileTmpl: "$options $include -Fo$objfile $file",
buildGui: " -subsystem windows",
buildDll: " -dll",
buildLib: "", # XXX: not supported yet
linkerExe: "lcclnk",
linkTmpl: "$options $buildgui $builddll -O $exefile $objfiles",
includeCmd: " -I",
linkDirCmd: "", # XXX: not supported yet
linkLibCmd: "", # XXX: not supported yet
debug: " -g5 ",
pic: "",
asmStmtFrmt: "_asm{$n$1$n}$n",
props: {})
compiler bcc:
result = (
name: "bcc",
objExt: "obj",
optSpeed: " -O2 -6 ",
optSize: " -O1 -6 ",
compilerExe: "bcc32",
compileTmpl: "-c $options $include -o$objfile $file",
buildGui: " -tW",
buildDll: " -tWD",
buildLib: "", # XXX: not supported yet
linkerExe: "bcc32",
linkTmpl: "$options $buildgui $builddll -e$exefile $objfiles",
includeCmd: " -I",
linkDirCmd: "", # XXX: not supported yet
linkLibCmd: "", # XXX: not supported yet
debug: "",
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
props: {hasCpp})
compiler dmc:
result = (
name: "dmc",
objExt: "obj",
optSpeed: " -ff -o -6 ",
optSize: " -ff -o -6 ",
compilerExe: "dmc",
compileTmpl: "-c $options $include -o$objfile $file",
buildGui: " -L/exet:nt/su:windows",
buildDll: " -WD",
buildLib: "", # XXX: not supported yet
linkerExe: "dmc",
linkTmpl: "$options $buildgui $builddll -o$exefile $objfiles",
includeCmd: " -I",
linkDirCmd: "", # XXX: not supported yet
linkLibCmd: "", # XXX: not supported yet
debug: " -g ",
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
props: {hasCpp})
compiler wcc:
result = (
name: "wcc",
objExt: "obj",
optSpeed: " -ox -on -6 -d0 -fp6 -zW ",
optSize: "",
compilerExe: "wcl386",
compileTmpl: "-c $options $include -fo=$objfile $file",
buildGui: " -bw",
buildDll: " -bd",
buildLib: "", # XXX: not supported yet
linkerExe: "wcl386",
linkTmpl: "$options $buildgui $builddll -fe=$exefile $objfiles ",
includeCmd: " -i=",
linkDirCmd: "", # XXX: not supported yet
linkLibCmd: "", # XXX: not supported yet
debug: " -d2 ",
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
props: {hasCpp})
compiler tcc:
result = (
name: "tcc",
objExt: "o", objExt: "o",
optSpeed: "", optSpeed: "",
optSize: "", optSize: "",
@ -171,14 +226,21 @@ const
compileTmpl: "-c $options $include -o $objfile $file", compileTmpl: "-c $options $include -o $objfile $file",
buildGui: "UNAVAILABLE!", buildGui: "UNAVAILABLE!",
buildDll: " -shared", buildDll: " -shared",
buildLib: "", # XXX: not supported yet
linkerExe: "tcc", linkerExe: "tcc",
linkTmpl: "-o $exefile $options $buildgui $builddll $objfiles", linkTmpl: "-o $exefile $options $buildgui $builddll $objfiles",
includeCmd: " -I", includeCmd: " -I",
linkDirCmd: "", # XXX: not supported yet
linkLibCmd: "", # XXX: not supported yet
debug: " -g ", debug: " -g ",
pic: "", pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n", asmStmtFrmt: "__asm{$n$1$n}$n",
props: {hasSwitchRange, hasComputedGoto}), props: {hasSwitchRange, hasComputedGoto})
(name: "pcc", # Pelles C
compiler pcc:
# Pelles C
result = (
name: "pcc",
objExt: "obj", objExt: "obj",
optSpeed: " -Ox ", optSpeed: " -Ox ",
optSize: " -Os ", optSize: " -Os ",
@ -186,14 +248,20 @@ const
compileTmpl: "-c $options $include -Fo$objfile $file", compileTmpl: "-c $options $include -Fo$objfile $file",
buildGui: " -SUBSYSTEM:WINDOWS", buildGui: " -SUBSYSTEM:WINDOWS",
buildDll: " -DLL", buildDll: " -DLL",
buildLib: "", # XXX: not supported yet
linkerExe: "cc", linkerExe: "cc",
linkTmpl: "$options $buildgui $builddll -OUT:$exefile $objfiles", linkTmpl: "$options $buildgui $builddll -OUT:$exefile $objfiles",
includeCmd: " -I", includeCmd: " -I",
linkDirCmd: "", # XXX: not supported yet
linkLibCmd: "", # XXX: not supported yet
debug: " -Zi ", debug: " -Zi ",
pic: "", pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n", asmStmtFrmt: "__asm{$n$1$n}$n",
props: {}), props: {})
(name: "ucc",
compiler ucc:
result = (
name: "ucc",
objExt: "o", objExt: "o",
optSpeed: " -O3 ", optSpeed: " -O3 ",
optSize: " -O1 ", optSize: " -O1 ",
@ -201,54 +269,53 @@ const
compileTmpl: "-c $options $include -o $objfile $file", compileTmpl: "-c $options $include -o $objfile $file",
buildGui: "", buildGui: "",
buildDll: " -shared ", buildDll: " -shared ",
buildLib: "", # XXX: not supported yet
linkerExe: "cc", linkerExe: "cc",
linkTmpl: "-o $exefile $buildgui $builddll $objfiles $options", linkTmpl: "-o $exefile $buildgui $builddll $objfiles $options",
includeCmd: " -I", includeCmd: " -I",
linkDirCmd: "", # XXX: not supported yet
linkLibCmd: "", # XXX: not supported yet
debug: "", debug: "",
pic: "", pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n", asmStmtFrmt: "__asm{$n$1$n}$n",
props: {}), props: {})
(name: "icc",
objExt: "o",
optSpeed: " -O3 ",
optSize: " -Os ",
compilerExe: "icc",
compileTmpl: "-c $options $include -o $objfile $file",
buildGui: " -mwindows",
buildDll: " -mdll",
linkerExe: "icc",
linkTmpl: "$options $buildgui $builddll -o $exefile $objfiles",
includeCmd: " -I",
debug: "",
pic: "-fPIC",
asmStmtFrmt: "asm($1);$n",
props: {hasSwitchRange, hasComputedGoto, hasCpp}),
(name: "gpp",
objExt: "o",
optSpeed: " -O3 -ffast-math ",
optSize: " -Os -ffast-math ",
compilerExe: "g++",
compileTmpl: "-c $options $include -o $objfile $file",
buildGui: " -mwindows",
buildDll: " -mdll",
linkerExe: "g++",
linkTmpl: "$buildgui $builddll -o $exefile $objfiles $options",
includeCmd: " -I",
debug: " -g ",
pic: "-fPIC",
asmStmtFrmt: "asm($1);$n",
props: {hasSwitchRange, hasComputedGoto, hasCpp})]
var ccompiler*: TSystemCC = ccGcc # the used compiler const
CC*: array[succ(low(TSystemCC))..high(TSystemCC), TInfoCC] = [
gcc(),
llvmGcc(),
clang(),
lcc(),
bcc(),
dmc(),
wcc(),
vcc(),
tcc(),
pcc(),
ucc(),
icc(),
gpp() ]
const const
hExt* = "h" hExt* = "h"
var cExt*: string = "c" # extension of generated C/C++ files var
cCompiler* = ccGcc # the used compiler
cExt* = "c" # extension of generated C/C++ files
# (can be changed to .cpp later) # (can be changed to .cpp later)
cIncludes*: seq[string] = @[] # list of directories to search for included files
cLibs*: seq[string] = @[] # list of directories to search for lib files
cLinkedLibs*: seq[string] = @[] # list of libraries to link
# implementation # implementation
when defined(windows):
var libNameTmpl = "$1.lib"
else:
var libNameTmpl = "lib$1.a"
var var
toLink, toCompile, externalToCompile: TLinkedList toLink, toCompile, externalToCompile: TLinkedList
linkOptions: string = "" linkOptions: string = ""
@ -363,6 +430,11 @@ const
var fileCounter: int var fileCounter: int
proc add(s: var string, many: openarray[string]) =
# XXX: is there something like C++'s reserve?
# We can use it here to avoid multiple reallocations
for x in items(many): s.add x
proc getCompileCFileCmd*(cfilename: string, isExternal: bool = false): string = proc getCompileCFileCmd*(cfilename: string, isExternal: bool = false): string =
var var
cfile, objfile, options, includeCmd, compilePattern, key, trunk, exe: string cfile, objfile, options, includeCmd, compilePattern, key, trunk, exe: string
@ -396,6 +468,10 @@ proc getCompileCFileCmd*(cfilename: string, isExternal: bool = false): string =
includeCmd = cc[c].includeCmd # this is more complex than needed, but includeCmd = cc[c].includeCmd # this is more complex than needed, but
# a workaround of a FPC bug... # a workaround of a FPC bug...
add(includeCmd, quoteIfContainsWhite(libpath)) add(includeCmd, quoteIfContainsWhite(libpath))
for includeDir in items(cIncludes):
includeCmd.add cc[c].includeCmd, includeDir.quoteIfContainsWhite
compilePattern = JoinPath(ccompilerpath, exe) compilePattern = JoinPath(ccompilerpath, exe)
else: else:
includeCmd = "" includeCmd = ""
@ -455,6 +531,20 @@ proc CallCCompiler*(projectfile: string) =
if res != 0: rawMessage(errExecutionOfProgramFailed, []) if res != 0: rawMessage(errExecutionOfProgramFailed, [])
if optNoLinking notin gGlobalOptions: if optNoLinking notin gGlobalOptions:
# call the linker: # call the linker:
var it = PStrEntry(toLink.head)
var objfiles = ""
while it != nil:
add(objfiles, ' ')
if targetOS == platform.hostOS:
add(objfiles, quoteIfContainsWhite(addFileExt(it.data, cc[ccompiler].objExt)))
else:
add(objfiles, quoteIfContainsWhite(addFileExt(it.data, cc[ccompiler].objExt)))
it = PStrEntry(it.next)
if optGenStaticLib in gGlobalOptions:
linkcmd = cc[c].buildLib % ["libfile", (libNameTmpl % projectName), "objfiles", objfiles]
if optCompileOnly notin gGlobalOptions: execExternalProgram(linkCmd)
else:
var linkerExe = getConfigVar(cc[c].name & ".linkerexe") var linkerExe = getConfigVar(cc[c].name & ".linkerexe")
if len(linkerExe) == 0: linkerExe = cc[c].linkerExe if len(linkerExe) == 0: linkerExe = cc[c].linkerExe
if targetOS == osWindows: linkerExe = addFileExt(linkerExe, "exe") if targetOS == osWindows: linkerExe = addFileExt(linkerExe, "exe")
@ -472,25 +562,21 @@ proc CallCCompiler*(projectfile: string) =
if targetOS == platform.hostOS: if targetOS == platform.hostOS:
exefile = joinPath(splitFile(projectFile).dir, exefile) exefile = joinPath(splitFile(projectFile).dir, exefile)
exefile = quoteIfContainsWhite(exefile) exefile = quoteIfContainsWhite(exefile)
var it = PStrEntry(toLink.head) for linkedLib in items(cLinkedLibs):
var objfiles = "" linkOptions.add(cc[c].linkLibCmd % linkedLib.quoteIfContainsWhite)
while it != nil: for libDir in items(cLibs):
add(objfiles, ' ') linkOptions.add cc[c].linkDirCmd, libDir.quoteIfContainsWhite
if targetOS == platform.hostOS:
add(objfiles, quoteIfContainsWhite(addFileExt(it.data, cc[ccompiler].objExt)))
else:
add(objfiles, quoteIfContainsWhite(addFileExt(it.data, cc[ccompiler].objExt)))
it = PStrEntry(it.next)
linkCmd = quoteIfContainsWhite(linkCmd % ["builddll", builddll, linkCmd = quoteIfContainsWhite(linkCmd % ["builddll", builddll,
"buildgui", buildgui, "options", linkOptions, "objfiles", objfiles, "buildgui", buildgui, "options", linkOptions, "objfiles", objfiles,
"exefile", exefile, "nimrod", getPrefixDir(), "lib", libpath]) "exefile", exefile, "nimrod", getPrefixDir(), "lib", libpath])
add(linkCmd, ' ') linkCmd.add ' '
addf(linkCmd, cc[c].linkTmpl, ["builddll", builddll, addf(linkCmd, cc[c].linkTmpl, ["builddll", builddll,
"buildgui", buildgui, "options", linkOptions, "buildgui", buildgui, "options", linkOptions,
"objfiles", objfiles, "exefile", exefile, "objfiles", objfiles, "exefile", exefile,
"nimrod", quoteIfContainsWhite(getPrefixDir()), "nimrod", quoteIfContainsWhite(getPrefixDir()),
"lib", quoteIfContainsWhite(libpath)]) "lib", quoteIfContainsWhite(libpath)])
if not (optCompileOnly in gGlobalOptions): execExternalProgram(linkCmd) if optCompileOnly notin gGlobalOptions: execExternalProgram(linkCmd)
else: else:
linkCmd = "" linkCmd = ""
if optGenScript in gGlobalOptions: if optGenScript in gGlobalOptions:

View file

@ -23,7 +23,7 @@ const
when has_LLVM_Backend: when has_LLVM_Backend:
import llvmgen import llvmgen
proc MainCommand*(cmd, filename: string) proc MainCommand*()
# ------------------ module handling ----------------------------------------- # ------------------ module handling -----------------------------------------
@ -81,57 +81,56 @@ proc CompileModule(filename: string, flags: TSymFlags): PSym =
result.id = getID() result.id = getID()
processModule(result, f, nil, rd) processModule(result, f, nil, rd)
proc CompileProject(filename: string) = proc CompileProject(projectFile = projectFullPath) =
discard CompileModule(options.libpath / addFileExt("system", nimExt), discard CompileModule(options.libpath / "system", {sfSystemModule})
{sfSystemModule}) discard CompileModule(projectFile, {sfMainModule})
discard CompileModule(addFileExt(filename, nimExt), {sfMainModule})
proc semanticPasses() = proc semanticPasses =
registerPass(verbosePass()) registerPass(verbosePass())
registerPass(sem.semPass()) registerPass(sem.semPass())
registerPass(transf.transfPass()) registerPass(transf.transfPass())
proc CommandGenDepend(filename: string) = proc CommandGenDepend =
semanticPasses() semanticPasses()
registerPass(genDependPass()) registerPass(genDependPass())
registerPass(cleanupPass()) registerPass(cleanupPass())
compileProject(filename) compileProject()
generateDot(filename) generateDot(projectFullPath)
execExternalProgram("dot -Tpng -o" & changeFileExt(filename, "png") & ' ' & execExternalProgram("dot -Tpng -o" & changeFileExt(projectFullPath, "png") & ' ' &
changeFileExt(filename, "dot")) changeFileExt(projectFullPath, "dot"))
proc CommandCheck(filename: string) = proc CommandCheck =
msgs.gErrorMax = high(int) # do not stop after first error msgs.gErrorMax = high(int) # do not stop after first error
semanticPasses() # use an empty backend for semantic checking only semanticPasses() # use an empty backend for semantic checking only
registerPass(rodwrite.rodwritePass()) registerPass(rodwrite.rodwritePass())
compileProject(filename) compileProject(mainCommandArg())
proc CommandCompileToC(filename: string) = proc CommandCompileToC =
semanticPasses() semanticPasses()
registerPass(cgen.cgenPass()) registerPass(cgen.cgenPass())
registerPass(rodwrite.rodwritePass()) registerPass(rodwrite.rodwritePass())
#registerPass(cleanupPass()) #registerPass(cleanupPass())
compileProject(filename) compileProject()
if gCmd != cmdRun: if gCmd != cmdRun:
extccomp.CallCCompiler(changeFileExt(filename, "")) extccomp.CallCCompiler(changeFileExt(projectFullPath, ""))
when has_LLVM_Backend: when has_LLVM_Backend:
proc CommandCompileToLLVM(filename: string) = proc CommandCompileToLLVM =
semanticPasses() semanticPasses()
registerPass(llvmgen.llvmgenPass()) registerPass(llvmgen.llvmgenPass())
registerPass(rodwrite.rodwritePass()) registerPass(rodwrite.rodwritePass())
#registerPass(cleanupPass()) #registerPass(cleanupPass())
compileProject(filename) compileProject()
proc CommandCompileToEcmaScript(filename: string) = proc CommandCompileToEcmaScript =
incl(gGlobalOptions, optSafeCode) incl(gGlobalOptions, optSafeCode)
setTarget(osEcmaScript, cpuEcmaScript) setTarget(osEcmaScript, cpuEcmaScript)
initDefines() initDefines()
semanticPasses() semanticPasses()
registerPass(ecmasgenPass()) registerPass(ecmasgenPass())
compileProject(filename) compileProject()
proc CommandInteractive() = proc CommandInteractive =
msgs.gErrorMax = high(int) # do not stop after first error msgs.gErrorMax = high(int) # do not stop after first error
incl(gGlobalOptions, optSafeCode) incl(gGlobalOptions, optSafeCode)
#setTarget(osNimrodVM, cpuNimrodVM) #setTarget(osNimrodVM, cpuNimrodVM)
@ -140,20 +139,22 @@ proc CommandInteractive() =
registerPass(verbosePass()) registerPass(verbosePass())
registerPass(sem.semPass()) registerPass(sem.semPass())
registerPass(evals.evalPass()) # load system module: registerPass(evals.evalPass()) # load system module:
discard CompileModule(options.libpath / addFileExt("system", nimExt), discard CompileModule(options.libpath /"system", {sfSystemModule})
{sfSystemModule}) if commandArgs.len > 0:
discard CompileModule(mainCommandArg(), {})
else:
var m = newModule("stdin") var m = newModule("stdin")
m.id = getID() m.id = getID()
incl(m.flags, sfMainModule) incl(m.flags, sfMainModule)
processModule(m, "stdin", LLStreamOpenStdIn(), nil) processModule(m, "stdin", LLStreamOpenStdIn(), nil)
proc CommandPretty(filename: string) = proc CommandPretty =
var module = parseFile(addFileExt(filename, NimExt)) var module = parseFile(addFileExt(mainCommandArg(), NimExt))
if module != nil: if module != nil:
renderModule(module, getOutFile(filename, "pretty." & NimExt)) renderModule(module, getOutFile(mainCommandArg(), "pretty." & NimExt))
proc CommandScan(filename: string) = proc CommandScan =
var f = addFileExt(filename, nimExt) var f = addFileExt(mainCommandArg(), nimExt)
var stream = LLStreamOpen(f, fmRead) var stream = LLStreamOpen(f, fmRead)
if stream != nil: if stream != nil:
var var
@ -169,107 +170,107 @@ proc CommandScan(filename: string) =
else: else:
rawMessage(errCannotOpenFile, f) rawMessage(errCannotOpenFile, f)
proc CommandSuggest(filename: string) = proc CommandSuggest =
msgs.gErrorMax = high(int) # do not stop after first error msgs.gErrorMax = high(int) # do not stop after first error
semanticPasses() semanticPasses()
registerPass(rodwrite.rodwritePass()) registerPass(rodwrite.rodwritePass())
compileProject(filename) compileProject()
proc WantFile(filename: string) = proc wantMainModule =
if filename.len == 0: if projectFullPath.len == 0:
Fatal(newLineInfo("command line", 1, 1), errCommandExpectsFilename) Fatal(newLineInfo("command line", 1, 1), errCommandExpectsFilename)
proc MainCommand(cmd, filename: string) = proc MainCommand =
appendStr(searchPaths, options.libpath) appendStr(searchPaths, options.libpath)
if filename.len != 0: if projectFullPath.len != 0:
# current path is always looked first for modules # current path is dalways looked first for modules
prependStr(searchPaths, splitFile(filename).dir) prependStr(searchPaths, projectPath)
setID(100) setID(100)
passes.gIncludeFile = syntaxes.parseFile passes.gIncludeFile = syntaxes.parseFile
passes.gImportModule = importModule passes.gImportModule = importModule
case cmd.normalize case command.normalize
of "c", "cc", "compile", "compiletoc": of "c", "cc", "compile", "compiletoc":
# compile means compileToC currently # compile means compileToC currently
gCmd = cmdCompileToC gCmd = cmdCompileToC
wantFile(filename) wantMainModule()
CommandCompileToC(filename) CommandCompileToC()
of "cpp", "compiletocpp": of "cpp", "compiletocpp":
extccomp.cExt = ".cpp" extccomp.cExt = ".cpp"
gCmd = cmdCompileToCpp gCmd = cmdCompileToCpp
wantFile(filename) wantMainModule()
DefineSymbol("cpp") DefineSymbol("cpp")
CommandCompileToC(filename) CommandCompileToC()
of "objc", "compiletooc": of "objc", "compiletooc":
extccomp.cExt = ".m" extccomp.cExt = ".m"
gCmd = cmdCompileToOC gCmd = cmdCompileToOC
wantFile(filename) wantMainModule()
DefineSymbol("objc") DefineSymbol("objc")
CommandCompileToC(filename) CommandCompileToC()
of "run": of "run":
gCmd = cmdRun gCmd = cmdRun
wantFile(filename) wantMainModule()
when hasTinyCBackend: when hasTinyCBackend:
extccomp.setCC("tcc") extccomp.setCC("tcc")
CommandCompileToC(filename) CommandCompileToC()
else: else:
rawMessage(errInvalidCommandX, cmd) rawMessage(errInvalidCommandX, command)
of "js", "compiletoecmascript": of "js", "compiletoecmascript":
gCmd = cmdCompileToEcmaScript gCmd = cmdCompileToEcmaScript
wantFile(filename) wantMainModule()
CommandCompileToEcmaScript(filename) CommandCompileToEcmaScript()
of "compiletollvm": of "compiletollvm":
gCmd = cmdCompileToLLVM gCmd = cmdCompileToLLVM
wantFile(filename) wantMainModule()
when has_LLVM_Backend: when has_LLVM_Backend:
CommandCompileToLLVM(filename) CommandCompileToLLVM()
else: else:
rawMessage(errInvalidCommandX, cmd) rawMessage(errInvalidCommandX, command)
of "pretty": of "pretty":
gCmd = cmdPretty gCmd = cmdPretty
wantFile(filename) wantMainModule()
CommandPretty(filename) CommandPretty()
of "doc": of "doc":
gCmd = cmdDoc gCmd = cmdDoc
LoadSpecialConfig(DocConfig) LoadConfigs(DocConfig)
wantFile(filename) wantMainModule()
CommandDoc(filename) CommandDoc()
of "rst2html": of "rst2html":
gCmd = cmdRst2html gCmd = cmdRst2html
LoadSpecialConfig(DocConfig) LoadConfigs(DocConfig)
wantFile(filename) wantMainModule()
CommandRst2Html(filename) CommandRst2Html()
of "rst2tex": of "rst2tex":
gCmd = cmdRst2tex gCmd = cmdRst2tex
LoadSpecialConfig(DocTexConfig) LoadConfigs(DocTexConfig)
wantFile(filename) wantMainModule()
CommandRst2TeX(filename) CommandRst2TeX()
of "gendepend": of "gendepend":
gCmd = cmdGenDepend gCmd = cmdGenDepend
wantFile(filename) wantMainModule()
CommandGenDepend(filename) CommandGenDepend()
of "dump": of "dump":
gCmd = cmdDump gCmd = cmdDump
condsyms.ListSymbols() condsyms.ListSymbols()
for it in iterSearchPath(): MsgWriteln(it) for it in iterSearchPath(): MsgWriteln(it)
of "check": of "check":
gCmd = cmdCheck gCmd = cmdCheck
wantFile(filename) wantMainModule()
CommandCheck(filename) CommandCheck()
of "parse": of "parse":
gCmd = cmdParse gCmd = cmdParse
wantFile(filename) wantMainModule()
discard parseFile(addFileExt(filename, nimExt)) discard parseFile(addFileExt(projectFullPath, nimExt))
of "scan": of "scan":
gCmd = cmdScan gCmd = cmdScan
wantFile(filename) wantMainModule()
CommandScan(filename) CommandScan()
MsgWriteln("Beware: Indentation tokens depend on the parser\'s state!") MsgWriteln("Beware: Indentation tokens depend on the parser\'s state!")
of "i": of "i":
gCmd = cmdInteractive gCmd = cmdInteractive
CommandInteractive() CommandInteractive()
of "idetools": of "idetools":
gCmd = cmdIdeTools gCmd = cmdIdeTools
wantFile(filename) wantMainModule()
CommandSuggest(filename) CommandSuggest()
else: rawMessage(errInvalidCommandX, cmd) else: rawMessage(errInvalidCommandX, command)

View file

@ -392,6 +392,7 @@ type
ERecoverableError* = object of EInvalidValue ERecoverableError* = object of EInvalidValue
proc newLineInfo*(filename: string, line, col: int): TLineInfo
proc raiseRecoverableError*() {.noinline, noreturn.} = proc raiseRecoverableError*() {.noinline, noreturn.} =
raise newException(ERecoverableError, "") raise newException(ERecoverableError, "")
@ -420,6 +421,7 @@ proc UnknownLineInfo*(): TLineInfo =
var var
filenames: seq[tuple[filename: string, fullpath: string]] = @[] filenames: seq[tuple[filename: string, fullpath: string]] = @[]
msgContext: seq[TLineInfo] = @[] msgContext: seq[TLineInfo] = @[]
gCmdLineInfo* = newLineInfo("command line", -1, -1)
proc pushInfoContext*(info: TLineInfo) = proc pushInfoContext*(info: TLineInfo) =
msgContext.add(info) msgContext.add(info)

View file

@ -205,20 +205,16 @@ proc readConfigFile(filename: string) =
closeLexer(L) closeLexer(L)
if gVerbosity >= 1: rawMessage(hintConf, filename) if gVerbosity >= 1: rawMessage(hintConf, filename)
proc getConfigPath(filename: string): string = proc getUserConfigPath(filename: string): string =
# try local configuration file:
result = joinPath(getConfigDir(), filename) result = joinPath(getConfigDir(), filename)
if not ExistsFile(result):
proc getSystemConfigPath(filename: string): string =
# try standard configuration file (installation did not distribute files # try standard configuration file (installation did not distribute files
# the UNIX way) # the UNIX way)
result = joinPath([getPrefixDir(), "config", filename]) result = joinPath([getPrefixDir(), "config", filename])
if not ExistsFile(result): result = "/etc/" & filename if not ExistsFile(result): result = "/etc/" & filename
proc LoadSpecialConfig*(configfilename: string) = proc LoadConfigs*(cfg = "nimrod.cfg") =
if optSkipConfigFile notin gGlobalOptions:
readConfigFile(getConfigPath(configfilename))
proc LoadConfig*(project: string) =
# set default value (can be overwritten): # set default value (can be overwritten):
if libpath == "": if libpath == "":
# choose default libpath: # choose default libpath:
@ -226,8 +222,14 @@ proc LoadConfig*(project: string) =
if (prefix == "/usr"): libpath = "/usr/lib/nimrod" if (prefix == "/usr"): libpath = "/usr/lib/nimrod"
elif (prefix == "/usr/local"): libpath = "/usr/local/lib/nimrod" elif (prefix == "/usr/local"): libpath = "/usr/local/lib/nimrod"
else: libpath = joinPath(prefix, "lib") else: libpath = joinPath(prefix, "lib")
LoadSpecialConfig("nimrod.cfg") # read project config file:
if optSkipProjConfigFile notin gGlobalOptions and project != "": if optSkipConfigFile notin gGlobalOptions:
var conffile = changeFileExt(project, "cfg") readConfigFile getSystemConfigPath(cfg)
if existsFile(conffile): readConfigFile(conffile)
if optSkipUserConfigFile notin gGlobalOptions:
readConfigFile getUserConfigPath(cfg)
if optSkipProjConfigFile notin gGlobalOptions and projectPath != "":
for dir in parentDirs(projectPath, fromRoot = true):
readConfigFile(dir/cfg)

View file

@ -20,9 +20,8 @@ when hasTinyCBackend:
var var
arguments: string = "" # the arguments to be passed to the program that arguments: string = "" # the arguments to be passed to the program that
# should be run # should be run
cmdLineInfo: TLineInfo
proc ProcessCmdLine(pass: TCmdLinePass, command, filename: var string) = proc ProcessCmdLine(pass: TCmdLinePass) =
var p = parseopt.initOptParser() var p = parseopt.initOptParser()
while true: while true:
parseopt.next(p) parseopt.next(p)
@ -35,15 +34,19 @@ proc ProcessCmdLine(pass: TCmdLinePass, command, filename: var string) =
if bracketLe >= 0: if bracketLe >= 0:
var key = substr(p.key, 0, bracketLe - 1) var key = substr(p.key, 0, bracketLe - 1)
var val = substr(p.key, bracketLe + 1) & ':' & p.val var val = substr(p.key, bracketLe + 1) & ':' & p.val
ProcessSwitch(key, val, pass, cmdLineInfo) ProcessSwitch(key, val, pass, gCmdLineInfo)
else: else:
ProcessSwitch(p.key, p.val, pass, cmdLineInfo) ProcessSwitch(p.key, p.val, pass, gCmdLineInfo)
of cmdArgument: of cmdArgument:
if command == "": if pass == passCmd1:
command = p.key if options.command == "":
elif filename == "": options.command = p.key
filename = unixToNativePath(p.key) # BUGFIX for portable build scripts else:
break options.commandArgs.add p.key
if options.projectName == "":
options.projectName = unixToNativePath(p.key) # BUGFIX for portable build scripts
if pass == passCmd2: if pass == passCmd2:
arguments = cmdLineRest(p) arguments = cmdLineRest(p)
if optRun notin gGlobalOptions and arguments != "": if optRun notin gGlobalOptions and arguments != "":
@ -62,26 +65,23 @@ proc HandleCmdLine() =
writeCommandLineUsage() writeCommandLineUsage()
else: else:
# Process command line arguments: # Process command line arguments:
var command = "" ProcessCmdLine(passCmd1)
var filename = "" if projectName != "":
ProcessCmdLine(passCmd1, command, filename)
if filename != "":
var fullpath: string
try: try:
fullPath = expandFilename(filename) projectFullPath = expandFilename(projectName)
except EOS: except EOS:
fullpath = filename projectFullPath = projectName
var p = splitFile(fullPath) var p = splitFile(projectFullPath)
options.projectPath = p.dir projectPath = p.dir
options.projectName = p.name projectName = p.name
nimconf.LoadConfig(filename) # load the right config file else:
projectPath = getCurrentDir()
LoadConfigs() # load all config files
# now process command line arguments again, because some options in the # now process command line arguments again, because some options in the
# command line can overwite the config file's settings # command line can overwite the config file's settings
extccomp.initVars() extccomp.initVars()
command = "" ProcessCmdLine(passCmd2)
filename = "" MainCommand()
ProcessCmdLine(passCmd2, command, filename)
MainCommand(command, filename)
if gVerbosity >= 2: echo(GC_getStatistics()) if gVerbosity >= 2: echo(GC_getStatistics())
if msgs.gErrorCounter == 0: if msgs.gErrorCounter == 0:
when hasTinyCBackend: when hasTinyCBackend:
@ -91,11 +91,10 @@ proc HandleCmdLine() =
rawMessage(hintSuccessX, [$gLinesCompiled, rawMessage(hintSuccessX, [$gLinesCompiled,
formatFloat(epochTime() - start, ffDecimal, 3)]) formatFloat(epochTime() - start, ffDecimal, 3)])
if optRun in gGlobalOptions: if optRun in gGlobalOptions:
var ex = quoteIfContainsWhite(changeFileExt(filename, "").prependCurDir) var ex = quoteIfContainsWhite(changeFileExt(projectName, "").prependCurDir)
execExternalProgram(ex & ' ' & arguments) execExternalProgram(ex & ' ' & arguments)
#GC_disableMarkAndSweep() #GC_disableMarkAndSweep()
cmdLineInfo = newLineInfo("command line", -1, -1)
condsyms.InitDefines() condsyms.InitDefines()
HandleCmdLine() HandleCmdLine()
quit(options.gExitcode) quit(options.gExitcode)

View file

@ -33,6 +33,7 @@ type # please make sure we have under 32 options
optSafeCode, # only allow safe code optSafeCode, # only allow safe code
optCDebug, # turn on debugging information optCDebug, # turn on debugging information
optGenDynLib, # generate a dynamic library optGenDynLib, # generate a dynamic library
optGenStaticLib, # generate a static library
optGenGuiApp, # generate a GUI application optGenGuiApp, # generate a GUI application
optGenScript, # generate a script file to compile the *.c files optGenScript, # generate a script file to compile the *.c files
optGenMapping, # generate a mapping file optGenMapping, # generate a mapping file
@ -40,6 +41,7 @@ type # please make sure we have under 32 options
optSymbolFiles, # use symbol files for speeding up compilation optSymbolFiles, # use symbol files for speeding up compilation
optSkipConfigFile, # skip the general config file optSkipConfigFile, # skip the general config file
optSkipProjConfigFile, # skip the project's config file optSkipProjConfigFile, # skip the project's config file
optSkipUserConfigFile, # skip the users's config file
optNoMain, # do not generate a "main" proc optNoMain, # do not generate a "main" proc
optThreads, # support for multi-threading optThreads, # support for multi-threading
optStdout, # output to stdout optStdout, # output to stdout
@ -98,11 +100,24 @@ const
var var
gConfigVars* = newStringTable(modeStyleInsensitive) gConfigVars* = newStringTable(modeStyleInsensitive)
libpath* = "" libpath* = ""
projectPath* = "" projectName* = "" # holds a name like `nimrod'
projectName* = "" projectPath* = "" # holds a path like /home/alice/projects/nimrod/compiler/
projectFullPath* = "" # projectPath/projectName
nimcacheDir* = "" nimcacheDir* = ""
command* = "" # the main command (e.g. cc, check, scan, etc)
commandArgs*: seq[string] = @[] # any arguments after the main command
gKeepComments*: bool = true # whether the parser needs to keep comments gKeepComments*: bool = true # whether the parser needs to keep comments
gImplicitMods*: TStringSeq = @[] # modules that are to be implicitly imported implicitImports*: seq[string] = @[] # modules that are to be implicitly imported
implicitIncludes*: seq[string] = @[] # modules that are to be implicitly included
proc mainCommandArg*: string =
## This is intended for commands like check or parse
## which will work on the main project file unless
## explicitly given a specific file argument
if commandArgs.len > 0:
result = commandArgs[0]
else:
result = projectName
proc existsConfigVar*(key: string): bool = proc existsConfigVar*(key: string): bool =
result = hasKey(gConfigVars, key) result = hasKey(gConfigVars, key)
@ -117,11 +132,6 @@ proc getOutFile*(filename, ext: string): string =
if options.outFile != "": result = options.outFile if options.outFile != "": result = options.outFile
else: result = changeFileExt(filename, ext) else: result = changeFileExt(filename, ext)
proc addImplicitMod*(filename: string) =
var length = len(gImplicitMods)
setlen(gImplicitMods, length + 1)
gImplicitMods[length] = filename
proc getPrefixDir*(): string = proc getPrefixDir*(): string =
## gets the application directory ## gets the application directory
result = SplitPath(getAppDir()).head result = SplitPath(getAppDir()).head

View file

@ -151,10 +151,24 @@ proc processModule(module: PSym, filename: string, stream: PLLStream,
s = stream s = stream
while true: while true:
openParsers(p, filename, s) openParsers(p, filename, s)
if sfSystemModule notin module.flags:
template processImplicits(implicits, nodeKind: expr): stmt =
for module in items(implicits):
var importStmt = newNodeI(nodeKind, gCmdLineInfo)
var str = newStrNode(nkStrLit, module)
str.info = gCmdLineInfo
importStmt.addSon str
processTopLevelStmt importStmt, a
processImplicits implicitImports, nkImportStmt
processImplicits implicitIncludes, nkIncludeStmt
while true: while true:
var n = parseTopLevelStmt(p) var n = parseTopLevelStmt(p)
if n.kind == nkEmpty: break if n.kind == nkEmpty: break
processTopLevelStmt(n, a) processTopLevelStmt(n, a)
closeParsers(p) closeParsers(p)
if s.kind != llsStdIn: break if s.kind != llsStdIn: break
closePasses(a) closePasses(a)

View file

@ -288,6 +288,8 @@ proc magicCall(m: PSym, n: PNode): PNode =
proc getAppType(n: PNode): PNode = proc getAppType(n: PNode): PNode =
if gGlobalOptions.contains(optGenDynLib): if gGlobalOptions.contains(optGenDynLib):
result = newStrNodeT("lib", n) result = newStrNodeT("lib", n)
elif gGlobalOptions.contains(optGenStaticLib):
result = newStrNodeT("staticlib", n)
elif gGlobalOptions.contains(optGenGuiApp): elif gGlobalOptions.contains(optGenGuiApp):
result = newStrNodeT("gui", n) result = newStrNodeT("gui", n)
else: else:

View file

@ -17,6 +17,7 @@ Advanced commands:
--context list possible invokation context --context list possible invokation context
Advanced options: Advanced options:
-m, --mainmodule:FILE set the project main module
-o, --out:FILE set the output filename -o, --out:FILE set the output filename
--stdout output to stdout --stdout output to stdout
-w, --warnings:on|off turn all warnings on|off -w, --warnings:on|off turn all warnings on|off
@ -25,6 +26,8 @@ Advanced options:
--hint[X]:on|off turn specific hint X on|off --hint[X]:on|off turn specific hint X on|off
--recursivePath:PATH add a path and all of its subdirectories --recursivePath:PATH add a path and all of its subdirectories
--lib:PATH set the system library path --lib:PATH set the system library path
--import:PATH add an automatically imported module
--include:PATH add an automatically included module
--nimcache:PATH set the path used for generated files --nimcache:PATH set the path used for generated files
-c, --compileOnly compile only; do not assemble or link -c, --compileOnly compile only; do not assemble or link
--noLinking compile but do not link --noLinking compile but do not link
@ -37,6 +40,10 @@ Advanced options:
--debugger:on|off turn Embedded Nimrod Debugger on|off --debugger:on|off turn Embedded Nimrod Debugger on|off
-t, --passc:OPTION pass an option to the C compiler -t, --passc:OPTION pass an option to the C compiler
-l, --passl:OPTION pass an option to the linker -l, --passl:OPTION pass an option to the linker
--cincludes:DIR modify the C compiler header search path
--clibdir:DIR modify the linker library search path
--clib:LIBNAME link an additional C library
(you should omit platform-specific extensions)
--genMapping generate a mapping file containing --genMapping generate a mapping file containing
(Nimrod, mangled) identifier pairs (Nimrod, mangled) identifier pairs
--lineDir:on|off generation of #line directive on|off --lineDir:on|off generation of #line directive on|off
@ -46,6 +53,7 @@ Advanced options:
--symbolFiles:on|off turn symbol files on|off (experimental) --symbolFiles:on|off turn symbol files on|off (experimental)
--skipCfg do not read the general configuration file --skipCfg do not read the general configuration file
--skipProjCfg do not read the project's configuration file --skipProjCfg do not read the project's configuration file
--skipUserCfg do not read the user's configuration file
--gc:refc|boehm|none use Nimrod's native GC|Boehm GC|no GC --gc:refc|boehm|none use Nimrod's native GC|Boehm GC|no GC
--index:FILE use FILE to generate a documentation index file --index:FILE use FILE to generate a documentation index file
--putenv:key=value set an environment variable --putenv:key=value set an environment variable

View file

@ -28,7 +28,8 @@ Options:
--infChecks:on|off turn Inf checks on|off --infChecks:on|off turn Inf checks on|off
--deadCodeElim:on|off whole program dead code elimination on|off --deadCodeElim:on|off whole program dead code elimination on|off
--opt:none|speed|size optimize not at all or for speed|size --opt:none|speed|size optimize not at all or for speed|size
--app:console|gui|lib generate a console|GUI application|dynamic library --app:console|gui|lib|staticlib
generate a console app|GUI app|DLL|static library
-r, --run run the compiled program with given arguments -r, --run run the compiled program with given arguments
--advanced show advanced command line switches --advanced show advanced command line switches
-h, --help show this help -h, --help show this help

View file

@ -408,6 +408,36 @@ proc parentDir*(path: string): string {.
else: else:
result = path result = path
proc isRootDir*(path: string): bool {.
noSideEffect, rtl, extern: "nos$1".} =
## Checks whether a given `path` is a root directory
var p = parentDir(path)
result = p == path or p.len == 0
iterator parentDirs*(path: string, fromRoot = false, inclusive = true): string =
## Walks over all parent directories of a given `path`
##
## If `fromRoot` is set, the traversal will start from the file system root
## diretory. If `inclusive` is set, the original argument will be included
## in the traversal.
##
## Relative paths won't be expanded by this proc. Instead, it will traverse
## only the directories appearing in the relative path.
if not fromRoot:
var current = path
if inclusive: yield path
while true:
if current.isRootDir: break
current = current.parentDir
yield current
else:
for i in countup(0, path.len - 2): # ignore the last /
# deal with non-normalized paths such as /foo//bar//baz
if path[i] in {dirsep, altsep} and (i == 0 or path[i-1] notin {dirsep, altsep}):
yield path.substr(0, i)
if inclusive: yield path
proc `/../` * (head, tail: string): string {.noSideEffect.} = proc `/../` * (head, tail: string): string {.noSideEffect.} =
## The same as ``parentDir(head) / tail`` ## The same as ``parentDir(head) / tail``
return parentDir(head) / tail return parentDir(head) / tail
@ -522,7 +552,7 @@ proc cmpPaths*(pathA, pathB: string): int {.
result = cmpIgnoreCase(pathA, pathB) result = cmpIgnoreCase(pathA, pathB)
proc isAbsolute*(path: string): bool {.rtl, noSideEffect, extern: "nos$1".} = proc isAbsolute*(path: string): bool {.rtl, noSideEffect, extern: "nos$1".} =
## Checks whether a given path is absolute. ## Checks whether a given `path` is absolute.
## ##
## on Windows, network paths are considered absolute too. ## on Windows, network paths are considered absolute too.
when doslike: when doslike:

View file

@ -46,6 +46,7 @@ Changes affecting backwards compatibility
raise hooks. raise hooks.
- Changed exception handling/error reporting for ``os.removeFile`` and - Changed exception handling/error reporting for ``os.removeFile`` and
``os.removeDir``. ``os.removeDir``.
- The algorithm for searching and loading configuration files have been changed
- Operators now have diffent precedence rules: Assignment-like operators - Operators now have diffent precedence rules: Assignment-like operators
(like ``*=``) are now special-cased. (like ``*=``) are now special-cased.
- The fields in ``TStream`` have been renamed to have an ``Impl`` suffix - The fields in ``TStream`` have been renamed to have an ``Impl`` suffix
@ -89,6 +90,15 @@ Compiler Additions
and Objective C somewhat easier. and Objective C somewhat easier.
- Added a ``--nimcache:PATH`` configuration option for control over the output - Added a ``--nimcache:PATH`` configuration option for control over the output
directory for generated code. directory for generated code.
- Added ``--cincludes:dir``, ``--clibdir:lib`` configuration options for
modifying the C compiler's header/library search path in cross-platform way.
- Added ``--clib:lib`` configuration options for specifying additional
C libraries to be linked.
- Added ``--mainmodule:file`` configuration options for specifying the main
project file. This is intended to be used in project configuration files to
allow commands like ``nimrod c`` or ``nimrod check`` to be executed anywhere
within the project's directory structure
- Added a ``--app:staticlib`` option for creating static libraries
- Added a ``--tlsEmulation:on|off`` switch for control over thread local - Added a ``--tlsEmulation:on|off`` switch for control over thread local
storage emulation. storage emulation.
- The compiler and standard library now support a *taint mode*. Input strings - The compiler and standard library now support a *taint mode*. Input strings
@ -98,6 +108,9 @@ Compiler Additions
- The compiler now supports the compilation cache via ``--symbolFiles:on``. - The compiler now supports the compilation cache via ``--symbolFiles:on``.
This potentially speeds up compilations by an order of magnitude, but is This potentially speeds up compilations by an order of magnitude, but is
still highly experimental! still highly experimental!
- Added ``--import:file`` and ``--include:file`` configuration options
for specifying modules that will be automatically imported/incluced.
- ``nimrod i`` can now optionally be given a module to execute.
Library Additions Library Additions
@ -114,7 +127,8 @@ Library Additions
- Added ``system.running`` for threads. - Added ``system.running`` for threads.
- Added ``system.program_result``. - Added ``system.program_result``.
- Added ``xmltree.innerText``. - Added ``xmltree.innerText``.
- Added ``os.isAbsolute``, ``os.dynLibFormat``. - Added ``os.isAbsolute``, ``os.dynLibFormat``, ``os.isRootDir``,
``os.parentDirs``.
- Added ``parseutils.interpolatedFragments``. - Added ``parseutils.interpolatedFragments``.
- Added ``macros.treeRepr``, ``macros.lispRepr``, ``macros.dumpTree``, - Added ``macros.treeRepr``, ``macros.lispRepr``, ``macros.dumpTree``,
``macros.dumpLisp``, ``macros.parseExpr``, ``macros.parseStmt``, ``macros.dumpLisp``, ``macros.parseExpr``, ``macros.parseStmt``,