New algorithm for locating and loading nimrod config files.

Some new options added to the compiler (see news.txt for details)
This commit is contained in:
Zahary Karadjov
2011-11-25 17:19:01 +02:00
parent ed9c7761c4
commit c617479c68
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":
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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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:
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 getUserConfigPath(filename: string): string =
result = joinPath(getConfigDir(), filename)
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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View File

@@ -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
@@ -85,6 +86,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
@@ -94,6 +104,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
@@ -110,7 +123,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``,