diff options
author | Araq <rumpf_a@web.de> | 2011-11-26 10:49:48 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2011-11-26 10:49:48 +0100 |
commit | 840979b45caea47c97c3eaac145841464ab5e5b1 (patch) | |
tree | e362829bad55797efc0542993a8303b412022560 | |
parent | f7f0c90ffe11952472ef6246c90c32d0e65c6b5f (diff) | |
parent | c617479c6848e07f25f92fd33b3397d65683812e (diff) | |
download | Nim-840979b45caea47c97c3eaac145841464ab5e5b1.tar.gz |
Merge branch 'master' of github.com:Araq/Nimrod
-rwxr-xr-x | compiler/commands.nim | 38 | ||||
-rwxr-xr-x | compiler/docgen.nim | 23 | ||||
-rwxr-xr-x | compiler/extccomp.nim | 550 | ||||
-rwxr-xr-x | compiler/main.nim | 157 | ||||
-rwxr-xr-x | compiler/msgs.nim | 6 | ||||
-rwxr-xr-x | compiler/nimconf.nim | 38 | ||||
-rwxr-xr-x | compiler/nimrod.nim | 55 | ||||
-rwxr-xr-x | compiler/options.nim | 26 | ||||
-rwxr-xr-x | compiler/passes.nim | 14 | ||||
-rwxr-xr-x | compiler/semfold.nim | 6 | ||||
-rwxr-xr-x | doc/advopt.txt | 10 | ||||
-rwxr-xr-x | doc/basicopt.txt | 3 | ||||
-rwxr-xr-x | lib/pure/os.nim | 32 | ||||
-rwxr-xr-x | web/news.txt | 16 |
14 files changed, 586 insertions, 388 deletions
diff --git a/compiler/commands.nim b/compiler/commands.nim index cf172111a..c6e00265f 100755 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -244,6 +244,10 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) = of "out", "o": expectArg(switch, arg, pass, info) options.outFile = arg + of "mainmodule", "m": + expectArg(switch, arg, pass, info) + projectName = arg + projectFullPath = projectPath/projectName of "define", "d": expectArg(switch, arg, pass, info) DefineSymbol(arg) @@ -333,15 +337,24 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) = of "app": expectArg(switch, arg, pass, info) case arg.normalize - of "gui": + of "gui": incl(gGlobalOptions, optGenGuiApp) + defineSymbol("executable") defineSymbol("guiapp") - of "console": + of "console": excl(gGlobalOptions, optGenGuiApp) - of "lib": + defineSymbol("executable") + defineSymbol("consoleapp") + of "lib": incl(gGlobalOptions, optGenDynLib) excl(gGlobalOptions, optGenGuiApp) defineSymbol("library") + defineSymbol("dll") + of "staticlib": + incl(gGlobalOptions, optGenStaticLib) + excl(gGlobalOptions, optGenGuiApp) + defineSymbol("library") + defineSymbol("staticlib") else: LocalError(info, errGuiConsoleOrLibExpectedButXFound, arg) of "passc", "t": expectArg(switch, arg, pass, info) @@ -349,12 +362,24 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) = of "passl", "l": expectArg(switch, arg, pass, info) 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": expectArg(switch, arg, pass, info) if pass in {passCmd2, passPP}: gIndexFile = arg - of "import": + of "import": 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": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optListCmd) @@ -405,6 +430,9 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) = of "skipprojcfg": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optSkipProjConfigFile) + of "skipusercfg": + expectNoArg(switch, arg, pass, info) + incl(gGlobalOptions, optSkipUserConfigFile) of "genscript": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optGenScript) diff --git a/compiler/docgen.nim b/compiler/docgen.nim index 411f93115..e76545c22 100755 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -15,9 +15,9 @@ import ast, astalgo, strutils, hashes, options, nversion, msgs, os, ropes, idents, wordrecg, math, syntaxes, renderer, lexer, rst, times, highlite -proc CommandDoc*(filename: string) -proc CommandRst2Html*(filename: string) -proc CommandRst2TeX*(filename: string) +proc CommandDoc*() +proc CommandRst2Html*() +proc CommandRst2TeX*() # implementation type @@ -870,14 +870,14 @@ proc writeOutput(d: PDoc, filename, outExt: string) = else: writeRope(content, getOutFile(filename, outExt)) -proc CommandDoc(filename: string) = - var ast = parseFile(addFileExt(filename, nimExt)) +proc CommandDoc = + var ast = parseFile(addFileExt(projectFullPath, nimExt)) if ast == nil: return - var d = newDocumentor(filename) + var d = newDocumentor(projectFullPath) initIndexFile(d) d.hasToc = true generateDoc(d, ast) - writeOutput(d, filename, HtmlExt) + writeOutput(d, projectFullPath, HtmlExt) generateIndex(d) proc CommandRstAux(filename, outExt: string) = @@ -889,9 +889,10 @@ proc CommandRstAux(filename, outExt: string) = writeOutput(d, filename, outExt) generateIndex(d) -proc CommandRst2Html(filename: string) = - CommandRstAux(filename, HtmlExt) +proc CommandRst2Html = + CommandRstAux(projectFullPath, HtmlExt) -proc CommandRst2TeX(filename: string) = +proc CommandRst2TeX = splitter = "\\-" - CommandRstAux(filename, TexExt) + CommandRstAux(projectFullPath, TexExt) + diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index a6dfe7367..9184b3368 100755 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -32,223 +32,290 @@ type compileTmpl: string, # the compile command template buildGui: string, # command to build a GUI application buildDll: string, # command to build a shared library + buildLib: string, # command to build a static library linkerExe: string, # the linker's executable linkTmpl: string, # command to link files to produce an exe 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 pic: string, # command for position independent code # used on some platforms asmStmtFrmt: string, # format of ASM statement props: TInfoCCProps] # properties of the C compiler + +# Configuration settings for various compilers. +# 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", + optSpeed: " -O3 -ffast-math ", + optSize: " -Os -ffast-math ", + compilerExe: "gcc", + compileTmpl: "-c $options $include -o $objfile $file", + buildGui: " -mwindows", + buildDll: " -shared", + buildLib: "ar rcs $libfile $objfiles", + linkerExe: "gcc", + linkTmpl: "$buildgui $builddll -o $exefile $objfiles $options", + includeCmd: " -I", + linkDirCmd: " -L", + linkLibCmd: " -l$1", + debug: "", + pic: "-fPIC", + asmStmtFrmt: "asm($1);$n", + props: {hasSwitchRange, hasComputedGoto, hasCpp}) + +compiler gpp: + result = gcc() + + result.name = "gpp" + result.compilerExe = "g++" + result.linkerExe = "g++" + + result.debug.add " -g " # XXX: Why is this default for g++, but not for gcc? + + result.buildDll = " -mdll" # XXX: Hmm, I'm keeping this from the previos version, + # but my gcc doesn't even have such an option (is this mingw?) + +compiler llvmGcc: + result = gcc() + + result.name = "llvm_gcc" + result.compilerExe = "llvm-gcc" + result.buildLib = "llvm-ar rcs $libfile $objfiles" + result.linkerExe = "llvm-gcc" + +compiler clang: + result = llvmGcc() + + result.name = "clang" + result.compilerExe = "clang" + result.linkerExe = "clang" + +compiler vcc: + result = ( + name: "vcc", + objExt: "obj", + optSpeed: " /Ogityb2 /G7 /arch:SSE2 ", + optSize: " /O1 /G7 ", + compilerExe: "cl", + compileTmpl: "/c $options $include /Fo$objfile $file", + buildGui: " /link /SUBSYSTEM:WINDOWS ", + buildDll: " /LD", + buildLib: "lib /OUT:$libfile $objfiles", + linkerExe: "cl", + linkTmpl: "$options $builddll /Fe$exefile $objfiles $buildgui", + includeCmd: " /I", + linkDirCmd: " /LIBPATH:", + linkLibCmd: " $1.lib", + debug: " /GZ /Zi ", + pic: "", + asmStmtFrmt: "__asm{$n$1$n}$n", + props: {hasCpp, hasAssume}) + +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", + optSpeed: "", + optSize: "", + compilerExe: "tcc", + compileTmpl: "-c $options $include -o $objfile $file", + buildGui: "UNAVAILABLE!", + buildDll: " -shared", + buildLib: "", # XXX: not supported yet + linkerExe: "tcc", + linkTmpl: "-o $exefile $options $buildgui $builddll $objfiles", + includeCmd: " -I", + linkDirCmd: "", # XXX: not supported yet + linkLibCmd: "", # XXX: not supported yet + debug: " -g ", + pic: "", + asmStmtFrmt: "__asm{$n$1$n}$n", + props: {hasSwitchRange, hasComputedGoto}) + +compiler pcc: + # Pelles C + result = ( + name: "pcc", + objExt: "obj", + optSpeed: " -Ox ", + optSize: " -Os ", + compilerExe: "cc", + compileTmpl: "-c $options $include -Fo$objfile $file", + buildGui: " -SUBSYSTEM:WINDOWS", + buildDll: " -DLL", + buildLib: "", # XXX: not supported yet + linkerExe: "cc", + linkTmpl: "$options $buildgui $builddll -OUT:$exefile $objfiles", + includeCmd: " -I", + linkDirCmd: "", # XXX: not supported yet + linkLibCmd: "", # XXX: not supported yet + debug: " -Zi ", + pic: "", + asmStmtFrmt: "__asm{$n$1$n}$n", + props: {}) + +compiler ucc: + result = ( + name: "ucc", + objExt: "o", + optSpeed: " -O3 ", + optSize: " -O1 ", + compilerExe: "cc", + compileTmpl: "-c $options $include -o $objfile $file", + buildGui: "", + buildDll: " -shared ", + buildLib: "", # XXX: not supported yet + linkerExe: "cc", + linkTmpl: "-o $exefile $buildgui $builddll $objfiles $options", + includeCmd: " -I", + linkDirCmd: "", # XXX: not supported yet + linkLibCmd: "", # XXX: not supported yet + debug: "", + pic: "", + asmStmtFrmt: "__asm{$n$1$n}$n", + props: {}) + const CC*: array[succ(low(TSystemCC))..high(TSystemCC), TInfoCC] = [ - (name: "gcc", - objExt: "o", - optSpeed: " -O3 -ffast-math ", - optSize: " -Os -ffast-math ", - compilerExe: "gcc", - compileTmpl: "-c $options $include -o $objfile $file", - buildGui: " -mwindows", - buildDll: " -shared", - linkerExe: "gcc", - linkTmpl: "$buildgui $builddll -o $exefile $objfiles $options", - includeCmd: " -I", - debug: "", - pic: "-fPIC", - asmStmtFrmt: "asm($1);$n", - props: {hasSwitchRange, hasComputedGoto, hasCpp}), - (name: "llvm_gcc", - objExt: "o", - optSpeed: " -O3 -ffast-math ", - optSize: " -Os -ffast-math ", - compilerExe: "llvm-gcc", - compileTmpl: "-c $options $include -o $objfile $file", - buildGui: " -mwindows", - buildDll: " -shared", - linkerExe: "llvm-gcc", - linkTmpl: "$buildgui $builddll -o $exefile $objfiles $options", - includeCmd: " -I", - debug: "", - pic: "-fPIC", - asmStmtFrmt: "asm($1);$n", - props: {hasSwitchRange, hasComputedGoto, hasCpp}), - (name: "clang", - objExt: "o", - optSpeed: " -O3 -ffast-math ", - optSize: " -Os -ffast-math ", - compilerExe: "clang", - compileTmpl: "-c $options $include -o $objfile $file", - buildGui: " -mwindows", - buildDll: " -shared", - linkerExe: "clang", - linkTmpl: "$buildgui $builddll -o $exefile $objfiles $options", - includeCmd: " -I", - debug: "", - pic: "-fPIC", - asmStmtFrmt: "asm($1);$n", - props: {hasSwitchRange, hasComputedGoto, hasCpp}), - (name: "lcc", - 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", - optSpeed: " /Ogityb2 /G7 /arch:SSE2 ", - optSize: " /O1 /G7 ", - compilerExe: "cl", - compileTmpl: "/c $options $include /Fo$objfile $file", - buildGui: " /link /SUBSYSTEM:WINDOWS ", - buildDll: " /LD", - linkerExe: "cl", - linkTmpl: "$options $builddll /Fe$exefile $objfiles $buildgui", - includeCmd: " /I", - debug: " /GZ /Zi ", - pic: "", - asmStmtFrmt: "__asm{$n$1$n}$n", - props: {hasCpp, hasAssume}), - (name: "tcc", - objExt: "o", - optSpeed: "", - optSize: "", - compilerExe: "tcc", - compileTmpl: "-c $options $include -o $objfile $file", - buildGui: "UNAVAILABLE!", - buildDll: " -shared", - linkerExe: "tcc", - linkTmpl: "-o $exefile $options $buildgui $builddll $objfiles", - includeCmd: " -I", - debug: " -g ", - pic: "", - asmStmtFrmt: "__asm{$n$1$n}$n", - props: {hasSwitchRange, hasComputedGoto}), - (name: "pcc", # Pelles C - objExt: "obj", - optSpeed: " -Ox ", - optSize: " -Os ", - compilerExe: "cc", - compileTmpl: "-c $options $include -Fo$objfile $file", - buildGui: " -SUBSYSTEM:WINDOWS", - buildDll: " -DLL", - linkerExe: "cc", - linkTmpl: "$options $buildgui $builddll -OUT:$exefile $objfiles", - includeCmd: " -I", - debug: " -Zi ", - pic: "", - asmStmtFrmt: "__asm{$n$1$n}$n", - props: {}), - (name: "ucc", - objExt: "o", - optSpeed: " -O3 ", - optSize: " -O1 ", - compilerExe: "cc", - compileTmpl: "-c $options $include -o $objfile $file", - buildGui: "", - buildDll: " -shared ", - linkerExe: "cc", - linkTmpl: "-o $exefile $buildgui $builddll $objfiles $options", - includeCmd: " -I", - debug: "", - pic: "", - asmStmtFrmt: "__asm{$n$1$n}$n", - 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 + gcc(), + llvmGcc(), + clang(), + lcc(), + bcc(), + dmc(), + wcc(), + vcc(), + tcc(), + pcc(), + ucc(), + icc(), + gpp() ] const hExt* = "h" -var cExt*: string = "c" # extension of generated C/C++ files - # (can be changed to .cpp later) +var + cCompiler* = ccGcc # the used compiler + + cExt* = "c" # extension of generated C/C++ files + # (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 +when defined(windows): + var libNameTmpl = "$1.lib" +else: + var libNameTmpl = "lib$1.a" + var toLink, toCompile, externalToCompile: TLinkedList linkOptions: string = "" @@ -363,6 +430,11 @@ const 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 = var 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 # a workaround of a FPC bug... add(includeCmd, quoteIfContainsWhite(libpath)) + + for includeDir in items(cIncludes): + includeCmd.add cc[c].includeCmd, includeDir.quoteIfContainsWhite + compilePattern = JoinPath(ccompilerpath, exe) else: includeCmd = "" @@ -453,47 +529,57 @@ proc CallCCompiler*(projectfile: string) = res = execProcesses(cmds, {poUseShell, poParentStreams}, gNumberOfProcessors) if res != 0: rawMessage(errExecutionOfProgramFailed, []) - if optNoLinking notin gGlobalOptions: + if optNoLinking notin gGlobalOptions: # call the linker: - var linkerExe = getConfigVar(cc[c].name & ".linkerexe") - if len(linkerExe) == 0: linkerExe = cc[c].linkerExe - if targetOS == osWindows: linkerExe = addFileExt(linkerExe, "exe") - if (platform.hostOS != targetOS): linkCmd = quoteIfContainsWhite(linkerExe) - else: linkCmd = quoteIfContainsWhite(JoinPath(ccompilerpath, linkerExe)) - if optGenGuiApp in gGlobalOptions: buildGui = cc[c].buildGui - else: buildGui = "" - var exefile: string - if optGenDynLib in gGlobalOptions: - exefile = `%`(platform.os[targetOS].dllFrmt, [splitFile(projectFile).name]) - buildDll = cc[c].buildDll - else: - exefile = splitFile(projectFile).name & platform.os[targetOS].exeExt - buildDll = "" - if targetOS == platform.hostOS: - exefile = joinPath(splitFile(projectFile).dir, exefile) - exefile = quoteIfContainsWhite(exefile) var it = PStrEntry(toLink.head) var objfiles = "" - while it != nil: + while it != nil: add(objfiles, ' ') - if targetOS == platform.hostOS: + if targetOS == platform.hostOS: add(objfiles, quoteIfContainsWhite(addFileExt(it.data, cc[ccompiler].objExt))) - else: + else: add(objfiles, quoteIfContainsWhite(addFileExt(it.data, cc[ccompiler].objExt))) it = PStrEntry(it.next) - linkCmd = quoteIfContainsWhite(linkCmd % ["builddll", builddll, - "buildgui", buildgui, "options", linkOptions, "objfiles", objfiles, - "exefile", exefile, "nimrod", getPrefixDir(), "lib", libpath]) - add(linkCmd, ' ') - addf(linkCmd, cc[c].linkTmpl, ["builddll", builddll, - "buildgui", buildgui, "options", linkOptions, - "objfiles", objfiles, "exefile", exefile, - "nimrod", quoteIfContainsWhite(getPrefixDir()), - "lib", quoteIfContainsWhite(libpath)]) - if not (optCompileOnly in gGlobalOptions): execExternalProgram(linkCmd) - else: + + 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") + if len(linkerExe) == 0: linkerExe = cc[c].linkerExe + if targetOS == osWindows: linkerExe = addFileExt(linkerExe, "exe") + if (platform.hostOS != targetOS): linkCmd = quoteIfContainsWhite(linkerExe) + else: linkCmd = quoteIfContainsWhite(JoinPath(ccompilerpath, linkerExe)) + if optGenGuiApp in gGlobalOptions: buildGui = cc[c].buildGui + else: buildGui = "" + var exefile: string + if optGenDynLib in gGlobalOptions: + exefile = `%`(platform.os[targetOS].dllFrmt, [splitFile(projectFile).name]) + buildDll = cc[c].buildDll + else: + exefile = splitFile(projectFile).name & platform.os[targetOS].exeExt + buildDll = "" + if targetOS == platform.hostOS: + exefile = joinPath(splitFile(projectFile).dir, exefile) + exefile = quoteIfContainsWhite(exefile) + for linkedLib in items(cLinkedLibs): + linkOptions.add(cc[c].linkLibCmd % linkedLib.quoteIfContainsWhite) + for libDir in items(cLibs): + linkOptions.add cc[c].linkDirCmd, libDir.quoteIfContainsWhite + + linkCmd = quoteIfContainsWhite(linkCmd % ["builddll", builddll, + "buildgui", buildgui, "options", linkOptions, "objfiles", objfiles, + "exefile", exefile, "nimrod", getPrefixDir(), "lib", libpath]) + linkCmd.add ' ' + addf(linkCmd, cc[c].linkTmpl, ["builddll", builddll, + "buildgui", buildgui, "options", linkOptions, + "objfiles", objfiles, "exefile", exefile, + "nimrod", quoteIfContainsWhite(getPrefixDir()), + "lib", quoteIfContainsWhite(libpath)]) + if optCompileOnly notin gGlobalOptions: execExternalProgram(linkCmd) + else: linkCmd = "" - if optGenScript in gGlobalOptions: + if optGenScript in gGlobalOptions: app(script, linkCmd) app(script, tnl) generateScript(projectFile, script) diff --git a/compiler/main.nim b/compiler/main.nim index 7a0d016ce..94c115912 100755 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -23,7 +23,7 @@ const when has_LLVM_Backend: import llvmgen -proc MainCommand*(cmd, filename: string) +proc MainCommand*() # ------------------ module handling ----------------------------------------- @@ -68,7 +68,7 @@ proc importModule(filename: string): PSym = elif sfSystemModule in result.flags: LocalError(result.info, errAttemptToRedefine, result.Name.s) -proc CompileModule(filename: string, flags: TSymFlags): PSym = +proc CompileModule(filename: string, flags: TSymFlags): PSym = var rd: PRodReader = nil var f = addFileExt(filename, nimExt) result = newModule(filename) @@ -81,57 +81,56 @@ proc CompileModule(filename: string, flags: TSymFlags): PSym = result.id = getID() processModule(result, f, nil, rd) -proc CompileProject(filename: string) = - discard CompileModule(options.libpath / addFileExt("system", nimExt), - {sfSystemModule}) - discard CompileModule(addFileExt(filename, nimExt), {sfMainModule}) +proc CompileProject(projectFile = projectFullPath) = + discard CompileModule(options.libpath / "system", {sfSystemModule}) + discard CompileModule(projectFile, {sfMainModule}) -proc semanticPasses() = +proc semanticPasses = registerPass(verbosePass()) registerPass(sem.semPass()) registerPass(transf.transfPass()) -proc CommandGenDepend(filename: string) = +proc CommandGenDepend = semanticPasses() registerPass(genDependPass()) registerPass(cleanupPass()) - compileProject(filename) - generateDot(filename) - execExternalProgram("dot -Tpng -o" & changeFileExt(filename, "png") & ' ' & - changeFileExt(filename, "dot")) + compileProject() + generateDot(projectFullPath) + execExternalProgram("dot -Tpng -o" & changeFileExt(projectFullPath, "png") & ' ' & + changeFileExt(projectFullPath, "dot")) -proc CommandCheck(filename: string) = +proc CommandCheck = msgs.gErrorMax = high(int) # do not stop after first error semanticPasses() # use an empty backend for semantic checking only registerPass(rodwrite.rodwritePass()) - compileProject(filename) + compileProject(mainCommandArg()) -proc CommandCompileToC(filename: string) = +proc CommandCompileToC = semanticPasses() registerPass(cgen.cgenPass()) registerPass(rodwrite.rodwritePass()) #registerPass(cleanupPass()) - compileProject(filename) + compileProject() if gCmd != cmdRun: - extccomp.CallCCompiler(changeFileExt(filename, "")) + extccomp.CallCCompiler(changeFileExt(projectFullPath, "")) when has_LLVM_Backend: - proc CommandCompileToLLVM(filename: string) = + proc CommandCompileToLLVM = semanticPasses() registerPass(llvmgen.llvmgenPass()) registerPass(rodwrite.rodwritePass()) #registerPass(cleanupPass()) - compileProject(filename) + compileProject() -proc CommandCompileToEcmaScript(filename: string) = +proc CommandCompileToEcmaScript = incl(gGlobalOptions, optSafeCode) setTarget(osEcmaScript, cpuEcmaScript) initDefines() semanticPasses() registerPass(ecmasgenPass()) - compileProject(filename) + compileProject() -proc CommandInteractive() = +proc CommandInteractive = msgs.gErrorMax = high(int) # do not stop after first error incl(gGlobalOptions, optSafeCode) #setTarget(osNimrodVM, cpuNimrodVM) @@ -140,20 +139,22 @@ proc CommandInteractive() = registerPass(verbosePass()) registerPass(sem.semPass()) registerPass(evals.evalPass()) # load system module: - discard CompileModule(options.libpath / addFileExt("system", nimExt), - {sfSystemModule}) - var m = newModule("stdin") - m.id = getID() - incl(m.flags, sfMainModule) - processModule(m, "stdin", LLStreamOpenStdIn(), nil) + discard CompileModule(options.libpath /"system", {sfSystemModule}) + if commandArgs.len > 0: + discard CompileModule(mainCommandArg(), {}) + else: + var m = newModule("stdin") + m.id = getID() + incl(m.flags, sfMainModule) + processModule(m, "stdin", LLStreamOpenStdIn(), nil) -proc CommandPretty(filename: string) = - var module = parseFile(addFileExt(filename, NimExt)) +proc CommandPretty = + var module = parseFile(addFileExt(mainCommandArg(), NimExt)) if module != nil: - renderModule(module, getOutFile(filename, "pretty." & NimExt)) + renderModule(module, getOutFile(mainCommandArg(), "pretty." & NimExt)) -proc CommandScan(filename: string) = - var f = addFileExt(filename, nimExt) +proc CommandScan = + var f = addFileExt(mainCommandArg(), nimExt) var stream = LLStreamOpen(f, fmRead) if stream != nil: var @@ -169,107 +170,107 @@ proc CommandScan(filename: string) = else: rawMessage(errCannotOpenFile, f) -proc CommandSuggest(filename: string) = +proc CommandSuggest = msgs.gErrorMax = high(int) # do not stop after first error semanticPasses() registerPass(rodwrite.rodwritePass()) - compileProject(filename) + compileProject() -proc WantFile(filename: string) = - if filename.len == 0: +proc wantMainModule = + if projectFullPath.len == 0: Fatal(newLineInfo("command line", 1, 1), errCommandExpectsFilename) -proc MainCommand(cmd, filename: string) = +proc MainCommand = appendStr(searchPaths, options.libpath) - if filename.len != 0: - # current path is always looked first for modules - prependStr(searchPaths, splitFile(filename).dir) + if projectFullPath.len != 0: + # current path is dalways looked first for modules + prependStr(searchPaths, projectPath) setID(100) passes.gIncludeFile = syntaxes.parseFile passes.gImportModule = importModule - case cmd.normalize + case command.normalize of "c", "cc", "compile", "compiletoc": # compile means compileToC currently gCmd = cmdCompileToC - wantFile(filename) - CommandCompileToC(filename) + wantMainModule() + CommandCompileToC() of "cpp", "compiletocpp": extccomp.cExt = ".cpp" gCmd = cmdCompileToCpp - wantFile(filename) + wantMainModule() DefineSymbol("cpp") - CommandCompileToC(filename) + CommandCompileToC() of "objc", "compiletooc": extccomp.cExt = ".m" gCmd = cmdCompileToOC - wantFile(filename) + wantMainModule() DefineSymbol("objc") - CommandCompileToC(filename) + CommandCompileToC() of "run": gCmd = cmdRun - wantFile(filename) + wantMainModule() when hasTinyCBackend: extccomp.setCC("tcc") - CommandCompileToC(filename) + CommandCompileToC() else: - rawMessage(errInvalidCommandX, cmd) + rawMessage(errInvalidCommandX, command) of "js", "compiletoecmascript": gCmd = cmdCompileToEcmaScript - wantFile(filename) - CommandCompileToEcmaScript(filename) + wantMainModule() + CommandCompileToEcmaScript() of "compiletollvm": gCmd = cmdCompileToLLVM - wantFile(filename) + wantMainModule() when has_LLVM_Backend: - CommandCompileToLLVM(filename) + CommandCompileToLLVM() else: - rawMessage(errInvalidCommandX, cmd) + rawMessage(errInvalidCommandX, command) of "pretty": gCmd = cmdPretty - wantFile(filename) - CommandPretty(filename) + wantMainModule() + CommandPretty() of "doc": gCmd = cmdDoc - LoadSpecialConfig(DocConfig) - wantFile(filename) - CommandDoc(filename) + LoadConfigs(DocConfig) + wantMainModule() + CommandDoc() of "rst2html": gCmd = cmdRst2html - LoadSpecialConfig(DocConfig) - wantFile(filename) - CommandRst2Html(filename) + LoadConfigs(DocConfig) + wantMainModule() + CommandRst2Html() of "rst2tex": gCmd = cmdRst2tex - LoadSpecialConfig(DocTexConfig) - wantFile(filename) - CommandRst2TeX(filename) + LoadConfigs(DocTexConfig) + wantMainModule() + CommandRst2TeX() of "gendepend": gCmd = cmdGenDepend - wantFile(filename) - CommandGenDepend(filename) + wantMainModule() + CommandGenDepend() of "dump": gCmd = cmdDump condsyms.ListSymbols() for it in iterSearchPath(): MsgWriteln(it) of "check": gCmd = cmdCheck - wantFile(filename) - CommandCheck(filename) + wantMainModule() + CommandCheck() of "parse": gCmd = cmdParse - wantFile(filename) - discard parseFile(addFileExt(filename, nimExt)) + wantMainModule() + discard parseFile(addFileExt(projectFullPath, nimExt)) of "scan": gCmd = cmdScan - wantFile(filename) - CommandScan(filename) + wantMainModule() + CommandScan() MsgWriteln("Beware: Indentation tokens depend on the parser\'s state!") of "i": gCmd = cmdInteractive CommandInteractive() of "idetools": gCmd = cmdIdeTools - wantFile(filename) - CommandSuggest(filename) - else: rawMessage(errInvalidCommandX, cmd) + wantMainModule() + CommandSuggest() + else: rawMessage(errInvalidCommandX, command) diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 63204459a..a1fd73c88 100755 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -377,7 +377,7 @@ const warnMax* = pred(hintSuccess) hintMin* = hintSuccess hintMax* = high(TMsgKind) - + type TNoteKind* = range[warnMin..hintMax] # "notes" are warnings or hints TNoteKinds* = set[TNoteKind] @@ -392,6 +392,7 @@ type ERecoverableError* = object of EInvalidValue +proc newLineInfo*(filename: string, line, col: int): TLineInfo proc raiseRecoverableError*() {.noinline, noreturn.} = raise newException(ERecoverableError, "") @@ -401,7 +402,7 @@ var gHintCounter*: int = 0 gWarnCounter*: int = 0 gErrorMax*: int = 1 # stop after gErrorMax errors - + # this format is understood by many text editors: it is the same that # Borland and Freepascal use const @@ -420,6 +421,7 @@ proc UnknownLineInfo*(): TLineInfo = var filenames: seq[tuple[filename: string, fullpath: string]] = @[] msgContext: seq[TLineInfo] = @[] + gCmdLineInfo* = newLineInfo("command line", -1, -1) proc pushInfoContext*(info: TLineInfo) = msgContext.add(info) diff --git a/compiler/nimconf.nim b/compiler/nimconf.nim index baffe350c..18bbe6cb4 100755 --- a/compiler/nimconf.nim +++ b/compiler/nimconf.nim @@ -204,21 +204,17 @@ proc readConfigFile(filename: string) = if len(condStack) > 0: lexMessage(L, errTokenExpected, "@end") closeLexer(L) if gVerbosity >= 1: rawMessage(hintConf, filename) - -proc getConfigPath(filename: string): string = - # try local configuration file: + +proc getUserConfigPath(filename: string): string = result = joinPath(getConfigDir(), filename) - if not ExistsFile(result): - # try standard configuration file (installation did not distribute files - # the UNIX way) - result = joinPath([getPrefixDir(), "config", filename]) - if not ExistsFile(result): result = "/etc/" & filename -proc LoadSpecialConfig*(configfilename: string) = - if optSkipConfigFile notin gGlobalOptions: - readConfigFile(getConfigPath(configfilename)) - -proc LoadConfig*(project: string) = +proc getSystemConfigPath(filename: string): string = + # try standard configuration file (installation did not distribute files + # the UNIX way) + result = joinPath([getPrefixDir(), "config", filename]) + if not ExistsFile(result): result = "/etc/" & filename + +proc LoadConfigs*(cfg = "nimrod.cfg") = # set default value (can be overwritten): if libpath == "": # choose default libpath: @@ -226,8 +222,14 @@ proc LoadConfig*(project: string) = if (prefix == "/usr"): libpath = "/usr/lib/nimrod" elif (prefix == "/usr/local"): libpath = "/usr/local/lib/nimrod" else: libpath = joinPath(prefix, "lib") - LoadSpecialConfig("nimrod.cfg") # read project config file: - if optSkipProjConfigFile notin gGlobalOptions and project != "": - var conffile = changeFileExt(project, "cfg") - if existsFile(conffile): readConfigFile(conffile) - + + if optSkipConfigFile notin gGlobalOptions: + readConfigFile getSystemConfigPath(cfg) + + if optSkipUserConfigFile notin gGlobalOptions: + readConfigFile getUserConfigPath(cfg) + + if optSkipProjConfigFile notin gGlobalOptions and projectPath != "": + for dir in parentDirs(projectPath, fromRoot = true): + readConfigFile(dir/cfg) + diff --git a/compiler/nimrod.nim b/compiler/nimrod.nim index a8a273cc4..87a9b1a75 100755 --- a/compiler/nimrod.nim +++ b/compiler/nimrod.nim @@ -20,9 +20,8 @@ when hasTinyCBackend: var arguments: string = "" # the arguments to be passed to the program that # should be run - cmdLineInfo: TLineInfo -proc ProcessCmdLine(pass: TCmdLinePass, command, filename: var string) = +proc ProcessCmdLine(pass: TCmdLinePass) = var p = parseopt.initOptParser() while true: parseopt.next(p) @@ -35,15 +34,19 @@ proc ProcessCmdLine(pass: TCmdLinePass, command, filename: var string) = if bracketLe >= 0: var key = substr(p.key, 0, bracketLe - 1) var val = substr(p.key, bracketLe + 1) & ':' & p.val - ProcessSwitch(key, val, pass, cmdLineInfo) + ProcessSwitch(key, val, pass, gCmdLineInfo) else: - ProcessSwitch(p.key, p.val, pass, cmdLineInfo) + ProcessSwitch(p.key, p.val, pass, gCmdLineInfo) of cmdArgument: - if command == "": - command = p.key - elif filename == "": - filename = unixToNativePath(p.key) # BUGFIX for portable build scripts - break + if pass == passCmd1: + if options.command == "": + options.command = p.key + else: + options.commandArgs.add p.key + + if options.projectName == "": + options.projectName = unixToNativePath(p.key) # BUGFIX for portable build scripts + if pass == passCmd2: arguments = cmdLineRest(p) if optRun notin gGlobalOptions and arguments != "": @@ -55,33 +58,30 @@ proc prependCurDir(f: string): string = else: result = "./" & f else: result = f - + proc HandleCmdLine() = var start = epochTime() if paramCount() == 0: writeCommandLineUsage() else: # Process command line arguments: - var command = "" - var filename = "" - ProcessCmdLine(passCmd1, command, filename) - if filename != "": - var fullpath: string + ProcessCmdLine(passCmd1) + if projectName != "": try: - fullPath = expandFilename(filename) - except EOS: - fullpath = filename - var p = splitFile(fullPath) - options.projectPath = p.dir - options.projectName = p.name - nimconf.LoadConfig(filename) # load the right config file + projectFullPath = expandFilename(projectName) + except EOS: + projectFullPath = projectName + var p = splitFile(projectFullPath) + projectPath = p.dir + projectName = p.name + else: + projectPath = getCurrentDir() + LoadConfigs() # load all config files # now process command line arguments again, because some options in the # command line can overwite the config file's settings extccomp.initVars() - command = "" - filename = "" - ProcessCmdLine(passCmd2, command, filename) - MainCommand(command, filename) + ProcessCmdLine(passCmd2) + MainCommand() if gVerbosity >= 2: echo(GC_getStatistics()) if msgs.gErrorCounter == 0: when hasTinyCBackend: @@ -91,11 +91,10 @@ proc HandleCmdLine() = rawMessage(hintSuccessX, [$gLinesCompiled, formatFloat(epochTime() - start, ffDecimal, 3)]) if optRun in gGlobalOptions: - var ex = quoteIfContainsWhite(changeFileExt(filename, "").prependCurDir) + var ex = quoteIfContainsWhite(changeFileExt(projectName, "").prependCurDir) execExternalProgram(ex & ' ' & arguments) #GC_disableMarkAndSweep() -cmdLineInfo = newLineInfo("command line", -1, -1) condsyms.InitDefines() HandleCmdLine() quit(options.gExitcode) diff --git a/compiler/options.nim b/compiler/options.nim index 640daf808..8820b1803 100755 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -33,6 +33,7 @@ type # please make sure we have under 32 options optSafeCode, # only allow safe code optCDebug, # turn on debugging information optGenDynLib, # generate a dynamic library + optGenStaticLib, # generate a static library optGenGuiApp, # generate a GUI application optGenScript, # generate a script file to compile the *.c files 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 optSkipConfigFile, # skip the general config file optSkipProjConfigFile, # skip the project's config file + optSkipUserConfigFile, # skip the users's config file optNoMain, # do not generate a "main" proc optThreads, # support for multi-threading optStdout, # output to stdout @@ -98,11 +100,24 @@ const var gConfigVars* = newStringTable(modeStyleInsensitive) libpath* = "" - projectPath* = "" - projectName* = "" + projectName* = "" # holds a name like `nimrod' + projectPath* = "" # holds a path like /home/alice/projects/nimrod/compiler/ + projectFullPath* = "" # projectPath/projectName 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 - 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 = result = hasKey(gConfigVars, key) @@ -117,11 +132,6 @@ proc getOutFile*(filename, ext: string): string = if options.outFile != "": result = options.outFile else: result = changeFileExt(filename, ext) -proc addImplicitMod*(filename: string) = - var length = len(gImplicitMods) - setlen(gImplicitMods, length + 1) - gImplicitMods[length] = filename - proc getPrefixDir*(): string = ## gets the application directory result = SplitPath(getAppDir()).head diff --git a/compiler/passes.nim b/compiler/passes.nim index 1ce5ad2d3..e24f82927 100755 --- a/compiler/passes.nim +++ b/compiler/passes.nim @@ -151,10 +151,24 @@ proc processModule(module: PSym, filename: string, stream: PLLStream, s = stream while true: 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: var n = parseTopLevelStmt(p) if n.kind == nkEmpty: break processTopLevelStmt(n, a) + closeParsers(p) if s.kind != llsStdIn: break closePasses(a) diff --git a/compiler/semfold.nim b/compiler/semfold.nim index f1c92cdc3..bda3e3891 100755 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -285,14 +285,16 @@ proc magicCall(m: PSym, n: PNode): PNode = b = nil result = evalOp(s.magic, n, a, b, c) -proc getAppType(n: PNode): PNode = +proc getAppType(n: PNode): PNode = if gGlobalOptions.contains(optGenDynLib): result = newStrNodeT("lib", n) + elif gGlobalOptions.contains(optGenStaticLib): + result = newStrNodeT("staticlib", n) elif gGlobalOptions.contains(optGenGuiApp): result = newStrNodeT("gui", n) else: result = newStrNodeT("console", n) - + proc foldConv*(n, a: PNode): PNode = case skipTypes(n.typ, abstractRange).kind of tyInt..tyInt64: diff --git a/doc/advopt.txt b/doc/advopt.txt index 1022a9136..c7dee653f 100755 --- a/doc/advopt.txt +++ b/doc/advopt.txt @@ -14,9 +14,10 @@ Advanced commands: --track:FILE,LINE,COL track a file/cursor position --suggest suggest all possible symbols at position --def list all possible symbols at position - --context list possible invokation context + --context list possible invokation context Advanced options: + -m, --mainmodule:FILE set the project main module -o, --out:FILE set the output filename --stdout output to stdout -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 --recursivePath:PATH add a path and all of its subdirectories --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 -c, --compileOnly compile only; do not assemble or link --noLinking compile but do not link @@ -37,6 +40,10 @@ Advanced options: --debugger:on|off turn Embedded Nimrod Debugger on|off -t, --passc:OPTION pass an option to the C compiler -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 (Nimrod, mangled) identifier pairs --lineDir:on|off generation of #line directive on|off @@ -46,6 +53,7 @@ Advanced options: --symbolFiles:on|off turn symbol files on|off (experimental) --skipCfg do not read the general 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 --index:FILE use FILE to generate a documentation index file --putenv:key=value set an environment variable diff --git a/doc/basicopt.txt b/doc/basicopt.txt index dd9e50ec2..b7bb77f75 100755 --- a/doc/basicopt.txt +++ b/doc/basicopt.txt @@ -28,7 +28,8 @@ Options: --infChecks:on|off turn Inf checks on|off --deadCodeElim:on|off whole program dead code elimination on|off --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 --advanced show advanced command line switches -h, --help show this help diff --git a/lib/pure/os.nim b/lib/pure/os.nim index c7e3dccb4..626fbc7eb 100755 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -408,6 +408,36 @@ proc parentDir*(path: string): string {. else: 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.} = ## The same as ``parentDir(head) / tail`` return parentDir(head) / tail @@ -522,7 +552,7 @@ proc cmpPaths*(pathA, pathB: string): int {. result = cmpIgnoreCase(pathA, pathB) 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. when doslike: diff --git a/web/news.txt b/web/news.txt index 1affafc1e..511591592 100755 --- a/web/news.txt +++ b/web/news.txt @@ -46,6 +46,7 @@ Changes affecting backwards compatibility raise hooks. - Changed exception handling/error reporting for ``os.removeFile`` and ``os.removeDir``. +- The algorithm for searching and loading configuration files have been changed - Operators now have diffent precedence rules: Assignment-like operators (like ``*=``) are now special-cased. - The fields in ``TStream`` have been renamed to have an ``Impl`` suffix @@ -89,6 +90,15 @@ Compiler Additions and Objective C somewhat easier. - Added a ``--nimcache:PATH`` configuration option for control over the output 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 storage emulation. - 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``. This potentially speeds up compilations by an order of magnitude, but is 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 @@ -114,7 +127,8 @@ Library Additions - Added ``system.running`` for threads. - Added ``system.program_result``. - Added ``xmltree.innerText``. -- Added ``os.isAbsolute``, ``os.dynLibFormat``. +- Added ``os.isAbsolute``, ``os.dynLibFormat``, ``os.isRootDir``, + ``os.parentDirs``. - Added ``parseutils.interpolatedFragments``. - Added ``macros.treeRepr``, ``macros.lispRepr``, ``macros.dumpTree``, ``macros.dumpLisp``, ``macros.parseExpr``, ``macros.parseStmt``, |