cleaned up configuration file handling and documented the new behaviour

This commit is contained in:
Araq 2011-11-30 00:53:41 +01:00
commit fc9fdc2b9d
19 changed files with 157 additions and 152 deletions

View file

@ -862,7 +862,7 @@ proc newModule(module: PSym, filename: string): BModule =
proc registerTypeInfoModule() = proc registerTypeInfoModule() =
const moduleName = "nim__dat" const moduleName = "nim__dat"
var s = NewSym(skModule, getIdent(moduleName), nil) var s = NewSym(skModule, getIdent(moduleName), nil)
gNimDat = rawNewModule(s, (options.projectPath / moduleName) & ".nim") gNimDat = rawNewModule(s, (options.gProjectPath / moduleName) & ".nim")
gNimDat.PreventStackTrace = true gNimDat.PreventStackTrace = true
addPendingModule(gNimDat) addPendingModule(gNimDat)
appff(mainModProcs, "N_NOINLINE(void, $1)(void);$n", appff(mainModProcs, "N_NOINLINE(void, $1)(void);$n",

View file

@ -37,37 +37,28 @@ proc getCommandLineDesc(): string =
result = (HelpMessage % [VersionAsString, platform.os[platform.hostOS].name, result = (HelpMessage % [VersionAsString, platform.os[platform.hostOS].name,
cpu[platform.hostCPU].name]) & Usage cpu[platform.hostCPU].name]) & Usage
var
helpWritten: bool # BUGFIX 19
versionWritten: bool
advHelpWritten: bool
proc HelpOnError(pass: TCmdLinePass) = proc HelpOnError(pass: TCmdLinePass) =
if (pass == passCmd1) and not helpWritten: if pass == passCmd1:
# BUGFIX 19
MsgWriteln(getCommandLineDesc()) MsgWriteln(getCommandLineDesc())
helpWritten = true
quit(0) quit(0)
proc writeAdvancedUsage(pass: TCmdLinePass) = proc writeAdvancedUsage(pass: TCmdLinePass) =
if (pass == passCmd1) and not advHelpWritten: if pass == passCmd1:
# BUGFIX 19
MsgWriteln(`%`(HelpMessage, [VersionAsString, MsgWriteln(`%`(HelpMessage, [VersionAsString,
platform.os[platform.hostOS].name, platform.os[platform.hostOS].name,
cpu[platform.hostCPU].name]) & AdvancedUsage) cpu[platform.hostCPU].name]) & AdvancedUsage)
advHelpWritten = true
helpWritten = true
quit(0) quit(0)
proc writeVersionInfo(pass: TCmdLinePass) = proc writeVersionInfo(pass: TCmdLinePass) =
if (pass == passCmd1) and not versionWritten: if pass == passCmd1:
versionWritten = true
helpWritten = true
MsgWriteln(`%`(HelpMessage, [VersionAsString, MsgWriteln(`%`(HelpMessage, [VersionAsString,
platform.os[platform.hostOS].name, platform.os[platform.hostOS].name,
cpu[platform.hostCPU].name])) cpu[platform.hostCPU].name]))
quit(0) quit(0)
var
helpWritten: bool
proc writeCommandLineUsage() = proc writeCommandLineUsage() =
if not helpWritten: if not helpWritten:
MsgWriteln(getCommandLineDesc()) MsgWriteln(getCommandLineDesc())
@ -197,8 +188,8 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool =
proc processPath(path: string): string = proc processPath(path: string): string =
result = UnixToNativePath(path % ["nimrod", getPrefixDir(), "lib", libpath, result = UnixToNativePath(path % ["nimrod", getPrefixDir(), "lib", libpath,
"home", removeTrailingDirSep(os.getHomeDir()), "home", removeTrailingDirSep(os.getHomeDir()),
"projectname", options.projectName, "projectname", options.gProjectName,
"projectpath", options.projectPath]) "projectpath", options.gProjectPath])
proc addPath(path: string, info: TLineInfo) = proc addPath(path: string, info: TLineInfo) =
if not contains(options.searchPaths, path): if not contains(options.searchPaths, path):
@ -246,8 +237,8 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
options.outFile = arg options.outFile = arg
of "mainmodule", "m": of "mainmodule", "m":
expectArg(switch, arg, pass, info) expectArg(switch, arg, pass, info)
projectName = arg gProjectName = arg
projectFullPath = projectPath/projectName gProjectFull = gProjectPath / gProjectName
of "define", "d": of "define", "d":
expectArg(switch, arg, pass, info) expectArg(switch, arg, pass, info)
DefineSymbol(arg) DefineSymbol(arg)
@ -433,6 +424,9 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
of "skipusercfg": of "skipusercfg":
expectNoArg(switch, arg, pass, info) expectNoArg(switch, arg, pass, info)
incl(gGlobalOptions, optSkipUserConfigFile) incl(gGlobalOptions, optSkipUserConfigFile)
of "skipparentcfg":
expectNoArg(switch, arg, pass, info)
incl(gGlobalOptions, optSkipParentConfigFiles)
of "genscript": of "genscript":
expectNoArg(switch, arg, pass, info) expectNoArg(switch, arg, pass, info)
incl(gGlobalOptions, optGenScript) incl(gGlobalOptions, optGenScript)

View file

@ -865,13 +865,13 @@ proc writeOutput(d: PDoc, filename, outExt: string) =
writeRope(content, getOutFile(filename, outExt)) writeRope(content, getOutFile(filename, outExt))
proc CommandDoc = proc CommandDoc =
var ast = parseFile(addFileExt(projectFullPath, nimExt)) var ast = parseFile(addFileExt(gProjectFull, nimExt))
if ast == nil: return if ast == nil: return
var d = newDocumentor(projectFullPath) var d = newDocumentor(gProjectFull)
initIndexFile(d) initIndexFile(d)
d.hasToc = true d.hasToc = true
generateDoc(d, ast) generateDoc(d, ast)
writeOutput(d, projectFullPath, HtmlExt) writeOutput(d, gProjectFull, HtmlExt)
generateIndex(d) generateIndex(d)
proc CommandRstAux(filename, outExt: string) = proc CommandRstAux(filename, outExt: string) =
@ -884,9 +884,9 @@ proc CommandRstAux(filename, outExt: string) =
generateIndex(d) generateIndex(d)
proc CommandRst2Html = proc CommandRst2Html =
CommandRstAux(projectFullPath, HtmlExt) CommandRstAux(gProjectFull, HtmlExt)
proc CommandRst2TeX = proc CommandRst2TeX =
splitter = "\\-" splitter = "\\-"
CommandRstAux(projectFullPath, TexExt) CommandRstAux(gProjectFull, TexExt)

View file

@ -305,16 +305,14 @@ var
cExt* = "c" # extension of generated C/C++ files cExt* = "c" # extension of generated C/C++ files
# (can be changed to .cpp later) # (can be changed to .cpp later)
cIncludes*: seq[string] = @[] # list of directories to search for included files cIncludes*: seq[string] = @[] # directories to search for included files
cLibs*: seq[string] = @[] # list of directories to search for lib files cLibs*: seq[string] = @[] # directories to search for lib files
cLinkedLibs*: seq[string] = @[] # list of libraries to link cLinkedLibs*: seq[string] = @[] # libraries to link
# implementation # implementation
when defined(windows): proc libNameTmpl(): string {.inline.} =
var libNameTmpl = "$1.lib" result = if targetOS == osWindows: "$1.lib" else: "lib$1.a"
else:
var libNameTmpl = "lib$1.a"
var var
toLink, toCompile, externalToCompile: TLinkedList toLink, toCompile, externalToCompile: TLinkedList
@ -431,43 +429,41 @@ const
var fileCounter: int var fileCounter: int
proc add(s: var string, many: openarray[string]) = proc add(s: var string, many: openarray[string]) =
# XXX: is there something like C++'s reserve? s.add many.join
# We can use it here to avoid multiple reallocations
for x in items(many): s.add x
proc getCompileCFileCmd*(cfilename: string, isExternal: bool = false): string = proc CFileSpecificOptions(cfilename: string): string =
var result = compileOptions
cfile, objfile, options, includeCmd, compilePattern, key, trunk, exe: string var trunk = splitFile(cfilename).name
var c = ccompiler
options = compileOptions
trunk = splitFile(cfilename).name
if optCDebug in gGlobalOptions: if optCDebug in gGlobalOptions:
key = trunk & ".debug" var key = trunk & ".debug"
if existsConfigVar(key): addOpt(options, getConfigVar(key)) if existsConfigVar(key): addOpt(result, getConfigVar(key))
else: addOpt(options, getDebug(c)) else: addOpt(result, getDebug(ccompiler))
if (optOptimizeSpeed in gOptions): if optOptimizeSpeed in gOptions:
#if ((fileCounter >= specialFileA) and (fileCounter <= specialFileB)) then var key = trunk & ".speed"
key = trunk & ".speed" if existsConfigVar(key): addOpt(result, getConfigVar(key))
if existsConfigVar(key): addOpt(options, getConfigVar(key)) else: addOpt(result, getOptSpeed(ccompiler))
else: addOpt(options, getOptSpeed(c)) elif optOptimizeSize in gOptions:
elif optOptimizeSize in gOptions: var key = trunk & ".size"
key = trunk & ".size" if existsConfigVar(key): addOpt(result, getConfigVar(key))
if existsConfigVar(key): addOpt(options, getConfigVar(key)) else: addOpt(result, getOptSize(ccompiler))
else: addOpt(options, getOptSize(c)) var key = trunk & ".always"
key = trunk & ".always" if existsConfigVar(key): addOpt(result, getConfigVar(key))
if existsConfigVar(key): addOpt(options, getConfigVar(key))
exe = cc[c].compilerExe proc getCompileCFileCmd*(cfilename: string, isExternal = false): string =
key = cc[c].name & ".exe" var c = ccompiler
var options = CFileSpecificOptions(cfilename)
var exe = cc[c].compilerExe
var key = cc[c].name & ".exe"
if existsConfigVar(key): exe = getConfigVar(key) if existsConfigVar(key): exe = getConfigVar(key)
if targetOS == osWindows: exe = addFileExt(exe, "exe") if targetOS == osWindows: exe = addFileExt(exe, "exe")
if optGenDynLib in gGlobalOptions and if optGenDynLib in gGlobalOptions and
ospNeedsPIC in platform.OS[targetOS].props: ospNeedsPIC in platform.OS[targetOS].props:
add(options, ' ' & cc[c].pic) add(options, ' ' & cc[c].pic)
var includeCmd, compilePattern: string
if targetOS == platform.hostOS: if targetOS == platform.hostOS:
# compute include paths: # compute include paths:
includeCmd = cc[c].includeCmd # this is more complex than needed, but includeCmd = cc[c].includeCmd & quoteIfContainsWhite(libpath)
# a workaround of a FPC bug...
add(includeCmd, quoteIfContainsWhite(libpath))
for includeDir in items(cIncludes): for includeDir in items(cIncludes):
includeCmd.add cc[c].includeCmd, includeDir.quoteIfContainsWhite includeCmd.add cc[c].includeCmd, includeDir.quoteIfContainsWhite
@ -476,15 +472,17 @@ proc getCompileCFileCmd*(cfilename: string, isExternal: bool = false): string =
else: else:
includeCmd = "" includeCmd = ""
compilePattern = cc[c].compilerExe compilePattern = cc[c].compilerExe
if targetOS == platform.hostOS: cfile = cfilename
else: cfile = extractFileName(cfilename) # XXX fix the grammar finally, we need multi-line if expressions:
if not isExternal or targetOS != platform.hostOS: objfile = toObjFile(cfile) var cfile = if targetOS == platform.hostOS: cfilename else: extractFileName(
else: objfile = completeCFilePath(toObjFile(cfile)) cfilename)
var objfile = if not isExternal or targetOS != platform.hostOS: toObjFile(
cfile) else: completeCFilePath(toObjFile(cfile))
cfile = quoteIfContainsWhite(AddFileExt(cfile, cExt)) cfile = quoteIfContainsWhite(AddFileExt(cfile, cExt))
objfile = quoteIfContainsWhite(objfile) objfile = quoteIfContainsWhite(objfile)
result = quoteIfContainsWhite(`%`(compilePattern, ["file", cfile, "objfile", result = quoteIfContainsWhite(compilePattern % [
objfile, "options", options, "include", includeCmd, "nimrod", "file", cfile, "objfile", objfile, "options", options,
getPrefixDir(), "lib", libpath])) "include", includeCmd, "nimrod", getPrefixDir(), "lib", libpath])
add(result, ' ') add(result, ' ')
addf(result, cc[c].compileTmpl, [ addf(result, cc[c].compileTmpl, [
"file", cfile, "objfile", objfile, "file", cfile, "objfile", objfile,
@ -498,9 +496,9 @@ proc CompileCFile(list: TLinkedList, script: var PRope, cmds: var TStringSeq,
while it != nil: while it != nil:
inc(fileCounter) # call the C compiler for the .c file: inc(fileCounter) # call the C compiler for the .c file:
var compileCmd = getCompileCFileCmd(it.data, isExternal) var compileCmd = getCompileCFileCmd(it.data, isExternal)
if not (optCompileOnly in gGlobalOptions): if optCompileOnly notin gGlobalOptions:
add(cmds, compileCmd) add(cmds, compileCmd)
if (optGenScript in gGlobalOptions): if optGenScript in gGlobalOptions:
app(script, compileCmd) app(script, compileCmd)
app(script, tnl) app(script, tnl)
it = PStrEntry(it.next) it = PStrEntry(it.next)
@ -522,7 +520,7 @@ proc CallCCompiler*(projectfile: string) =
var res = 0 var res = 0
if gNumberOfProcessors <= 1: if gNumberOfProcessors <= 1:
for i in countup(0, high(cmds)): res = max(execCmd(cmds[i]), res) for i in countup(0, high(cmds)): res = max(execCmd(cmds[i]), res)
elif (optListCmd in gGlobalOptions) or (gVerbosity > 0): elif optListCmd in gGlobalOptions or gVerbosity > 0:
res = execProcesses(cmds, {poEchoCmd, poUseShell, poParentStreams}, res = execProcesses(cmds, {poEchoCmd, poUseShell, poParentStreams},
gNumberOfProcessors) gNumberOfProcessors)
else: else:
@ -535,26 +533,25 @@ proc CallCCompiler*(projectfile: string) =
var objfiles = "" var objfiles = ""
while it != nil: while it != nil:
add(objfiles, ' ') add(objfiles, ' ')
if targetOS == platform.hostOS: add(objfiles, quoteIfContainsWhite(
add(objfiles, quoteIfContainsWhite(addFileExt(it.data, cc[ccompiler].objExt))) addFileExt(it.data, cc[ccompiler].objExt)))
else:
add(objfiles, quoteIfContainsWhite(addFileExt(it.data, cc[ccompiler].objExt)))
it = PStrEntry(it.next) it = PStrEntry(it.next)
if optGenStaticLib in gGlobalOptions: if optGenStaticLib in gGlobalOptions:
linkcmd = cc[c].buildLib % ["libfile", (libNameTmpl % projectName), "objfiles", objfiles] linkcmd = cc[c].buildLib % ["libfile", (libNameTmpl() % gProjectName),
"objfiles", objfiles]
if optCompileOnly notin gGlobalOptions: execExternalProgram(linkCmd) if optCompileOnly notin gGlobalOptions: execExternalProgram(linkCmd)
else: else:
var linkerExe = getConfigVar(cc[c].name & ".linkerexe") var linkerExe = getConfigVar(cc[c].name & ".linkerexe")
if len(linkerExe) == 0: linkerExe = cc[c].linkerExe if len(linkerExe) == 0: linkerExe = cc[c].linkerExe
if targetOS == osWindows: linkerExe = addFileExt(linkerExe, "exe") if targetOS == osWindows: linkerExe = addFileExt(linkerExe, "exe")
if (platform.hostOS != targetOS): linkCmd = quoteIfContainsWhite(linkerExe) if platform.hostOS != targetOS: linkCmd = quoteIfContainsWhite(linkerExe)
else: linkCmd = quoteIfContainsWhite(JoinPath(ccompilerpath, linkerExe)) else: linkCmd = quoteIfContainsWhite(JoinPath(ccompilerpath, linkerExe))
if optGenGuiApp in gGlobalOptions: buildGui = cc[c].buildGui if optGenGuiApp in gGlobalOptions: buildGui = cc[c].buildGui
else: buildGui = "" else: buildGui = ""
var exefile: string var exefile: string
if optGenDynLib in gGlobalOptions: if optGenDynLib in gGlobalOptions:
exefile = `%`(platform.os[targetOS].dllFrmt, [splitFile(projectFile).name]) exefile = platform.os[targetOS].dllFrmt % [splitFile(projectFile).name]
buildDll = cc[c].buildDll buildDll = cc[c].buildDll
else: else:
exefile = splitFile(projectFile).name & platform.os[targetOS].exeExt exefile = splitFile(projectFile).name & platform.os[targetOS].exeExt
@ -596,4 +593,5 @@ proc writeMapping*(gSymbolMapping: PRope) =
app(code, genMappingFiles(toCompile)) app(code, genMappingFiles(toCompile))
app(code, genMappingFiles(externalToCompile)) app(code, genMappingFiles(externalToCompile))
appf(code, "[Symbols]$n$1", [gSymbolMapping]) appf(code, "[Symbols]$n$1", [gSymbolMapping])
WriteRope(code, joinPath(projectPath, "mapping.txt")) WriteRope(code, joinPath(gProjectPath, "mapping.txt"))

View file

@ -81,7 +81,7 @@ proc CompileModule(filename: string, flags: TSymFlags): PSym =
result.id = getID() result.id = getID()
processModule(result, f, nil, rd) processModule(result, f, nil, rd)
proc CompileProject(projectFile = projectFullPath) = proc CompileProject(projectFile = gProjectFull) =
discard CompileModule(options.libpath / "system", {sfSystemModule}) discard CompileModule(options.libpath / "system", {sfSystemModule})
discard CompileModule(projectFile, {sfMainModule}) discard CompileModule(projectFile, {sfMainModule})
@ -95,9 +95,9 @@ proc CommandGenDepend =
registerPass(genDependPass()) registerPass(genDependPass())
registerPass(cleanupPass()) registerPass(cleanupPass())
compileProject() compileProject()
generateDot(projectFullPath) generateDot(gProjectFull)
execExternalProgram("dot -Tpng -o" & changeFileExt(projectFullPath, "png") & execExternalProgram("dot -Tpng -o" & changeFileExt(gProjectFull, "png") &
' ' & changeFileExt(projectFullPath, "dot")) ' ' & changeFileExt(gProjectFull, "dot"))
proc CommandCheck = proc CommandCheck =
msgs.gErrorMax = high(int) # do not stop after first error msgs.gErrorMax = high(int) # do not stop after first error
@ -112,7 +112,7 @@ proc CommandCompileToC =
#registerPass(cleanupPass()) #registerPass(cleanupPass())
compileProject() compileProject()
if gCmd != cmdRun: if gCmd != cmdRun:
extccomp.CallCCompiler(changeFileExt(projectFullPath, "")) extccomp.CallCCompiler(changeFileExt(gProjectFull, ""))
when has_LLVM_Backend: when has_LLVM_Backend:
proc CommandCompileToLLVM = proc CommandCompileToLLVM =
@ -177,14 +177,14 @@ proc CommandSuggest =
compileProject() compileProject()
proc wantMainModule = proc wantMainModule =
if projectFullPath.len == 0: if gProjectFull.len == 0:
Fatal(newLineInfo("command line", 1, 1), errCommandExpectsFilename) Fatal(newLineInfo("command line", 1, 1), errCommandExpectsFilename)
proc MainCommand = proc MainCommand =
appendStr(searchPaths, options.libpath) appendStr(searchPaths, options.libpath)
if projectFullPath.len != 0: if gProjectFull.len != 0:
# current path is dalways looked first for modules # current path is always looked first for modules
prependStr(searchPaths, projectPath) prependStr(searchPaths, gProjectPath)
setID(100) setID(100)
passes.gIncludeFile = syntaxes.parseFile passes.gIncludeFile = syntaxes.parseFile
passes.gImportModule = importModule passes.gImportModule = importModule
@ -259,7 +259,7 @@ proc MainCommand =
of "parse": of "parse":
gCmd = cmdParse gCmd = cmdParse
wantMainModule() wantMainModule()
discard parseFile(addFileExt(projectFullPath, nimExt)) discard parseFile(addFileExt(gProjectFull, nimExt))
of "scan": of "scan":
gCmd = cmdScan gCmd = cmdScan
wantMainModule() wantMainModule()

View file

@ -96,7 +96,7 @@ type
errUser, errUser,
warnCannotOpenFile, warnCannotOpenFile,
warnOctalEscape, warnXIsNeverRead, warnXmightNotBeenInit, warnOctalEscape, warnXIsNeverRead, warnXmightNotBeenInit,
warnDeprecated, warnDeprecated, warnConfigDeprecated,
warnSmallLshouldNotBeUsed, warnUnknownMagic, warnRedefinitionOfLabel, warnSmallLshouldNotBeUsed, warnUnknownMagic, warnRedefinitionOfLabel,
warnUnknownSubstitutionX, warnLanguageXNotSupported, warnCommentXIgnored, warnUnknownSubstitutionX, warnLanguageXNotSupported, warnCommentXIgnored,
warnXisPassedToProcVar, warnDerefDeprecated, warnAnalysisLoophole, warnXisPassedToProcVar, warnDerefDeprecated, warnAnalysisLoophole,
@ -328,6 +328,7 @@ const
warnXIsNeverRead: "\'$1\' is never read [XIsNeverRead]", warnXIsNeverRead: "\'$1\' is never read [XIsNeverRead]",
warnXmightNotBeenInit: "\'$1\' might not have been initialized [XmightNotBeenInit]", warnXmightNotBeenInit: "\'$1\' might not have been initialized [XmightNotBeenInit]",
warnDeprecated: "\'$1\' is deprecated [Deprecated]", warnDeprecated: "\'$1\' is deprecated [Deprecated]",
warnConfigDeprecated: "config file '$1' is deprecated [ConfigDeprecated]",
warnSmallLshouldNotBeUsed: "\'l\' should not be used as an identifier; may look like \'1\' (one) [SmallLshouldNotBeUsed]", warnSmallLshouldNotBeUsed: "\'l\' should not be used as an identifier; may look like \'1\' (one) [SmallLshouldNotBeUsed]",
warnUnknownMagic: "unknown magic \'$1\' might crash the compiler [UnknownMagic]", warnUnknownMagic: "unknown magic \'$1\' might crash the compiler [UnknownMagic]",
warnRedefinitionOfLabel: "redefinition of label \'$1\' [RedefinitionOfLabel]", warnRedefinitionOfLabel: "redefinition of label \'$1\' [RedefinitionOfLabel]",
@ -356,9 +357,10 @@ const
hintUser: "$1 [User]"] hintUser: "$1 [User]"]
const const
WarningsToStr*: array[0..16, string] = ["CannotOpenFile", "OctalEscape", WarningsToStr*: array[0..17, string] = ["CannotOpenFile", "OctalEscape",
"XIsNeverRead", "XmightNotBeenInit", "XIsNeverRead", "XmightNotBeenInit",
"Deprecated", "SmallLshouldNotBeUsed", "UnknownMagic", "Deprecated", "ConfigDeprecated",
"SmallLshouldNotBeUsed", "UnknownMagic",
"RedefinitionOfLabel", "UnknownSubstitutionX", "LanguageXNotSupported", "RedefinitionOfLabel", "UnknownSubstitutionX", "LanguageXNotSupported",
"CommentXIgnored", "XisPassedToProcVar", "DerefDeprecated", "CommentXIgnored", "XisPassedToProcVar", "DerefDeprecated",
"AnalysisLoophole", "DifferentHeaps", "WriteToForeignHeap", "User"] "AnalysisLoophole", "DifferentHeaps", "WriteToForeignHeap", "User"]
@ -443,7 +445,7 @@ proc includeFilename*(f: string): int =
filenames.add((filename: f, fullpath: fullpath)) filenames.add((filename: f, fullpath: fullpath))
proc newLineInfo*(filename: string, line, col: int): TLineInfo = proc newLineInfo(filename: string, line, col: int): TLineInfo =
result.fileIndex = includeFilename(filename) result.fileIndex = includeFilename(filename)
result.line = int16(line) result.line = int16(line)
result.col = int16(col) result.col = int16(col)

View file

@ -189,14 +189,14 @@ proc parseAssignment(L: var TLexer, tok: var TToken) =
confTok(L, tok) confTok(L, tok)
processSwitch(s, val, passPP, info) processSwitch(s, val, passPP, info)
proc readConfigFile(filename: string) = proc readConfigFile(filename: string) =
var var
L: TLexer L: TLexer
tok: TToken tok: TToken
stream: PLLStream stream: PLLStream
initToken(tok)
stream = LLStreamOpen(filename, fmRead) stream = LLStreamOpen(filename, fmRead)
if stream != nil: if stream != nil:
initToken(tok)
openLexer(L, filename, stream) openLexer(L, filename, stream)
tok.tokType = tkEof # to avoid a pointless warning tok.tokType = tkEof # to avoid a pointless warning
confTok(L, tok) # read in the first token confTok(L, tok) # read in the first token
@ -214,7 +214,7 @@ proc getSystemConfigPath(filename: string): string =
result = joinPath([getPrefixDir(), "config", filename]) result = joinPath([getPrefixDir(), "config", filename])
if not ExistsFile(result): result = "/etc/" & filename if not ExistsFile(result): result = "/etc/" & filename
proc LoadConfigs*(cfg = "nimrod.cfg") = proc LoadConfigs*(cfg: string) =
# set default value (can be overwritten): # set default value (can be overwritten):
if libpath == "": if libpath == "":
# choose default libpath: # choose default libpath:
@ -224,12 +224,21 @@ proc LoadConfigs*(cfg = "nimrod.cfg") =
else: libpath = joinPath(prefix, "lib") else: libpath = joinPath(prefix, "lib")
if optSkipConfigFile notin gGlobalOptions: if optSkipConfigFile notin gGlobalOptions:
readConfigFile getSystemConfigPath(cfg) readConfigFile(getSystemConfigPath(cfg))
if optSkipUserConfigFile notin gGlobalOptions: if optSkipUserConfigFile notin gGlobalOptions:
readConfigFile getUserConfigPath(cfg) readConfigFile(getUserConfigPath(cfg))
if optSkipProjConfigFile notin gGlobalOptions and projectPath != "": var pd = if gProjectPath.len > 0: gProjectPath else: getCurrentDir()
for dir in parentDirs(projectPath, fromRoot = true): if optSkipParentConfigFiles notin gGlobalOptions:
readConfigFile(dir/cfg) for dir in parentDirs(pd, fromRoot=true, inclusive=false):
readConfigFile(dir / cfg)
if optSkipProjConfigFile notin gGlobalOptions and gProjectName.len != 0:
readConfigFile(pd / cfg)
var conffile = changeFileExt(gProjectFull, "cfg")
if conffile != pd / cfg and existsFile(conffile):
readConfigFile(conffile)
rawMessage(warnConfigDeprecated, conffile)

View file

@ -44,9 +44,9 @@ proc ProcessCmdLine(pass: TCmdLinePass) =
else: else:
options.commandArgs.add p.key options.commandArgs.add p.key
if options.projectName == "": if options.gProjectName == "":
# support UNIX style filenames anywhere for portable build scripts: # support UNIX style filenames anywhere for portable build scripts:
options.projectName = unixToNativePath(p.key) options.gProjectName = unixToNativePath(p.key)
arguments = cmdLineRest(p) arguments = cmdLineRest(p)
if pass == passCmd2: if pass == passCmd2:
@ -64,20 +64,20 @@ proc HandleCmdLine() =
var start = epochTime() var start = epochTime()
if paramCount() == 0: if paramCount() == 0:
writeCommandLineUsage() writeCommandLineUsage()
else: else:
# Process command line arguments: # Process command line arguments:
ProcessCmdLine(passCmd1) ProcessCmdLine(passCmd1)
if projectName != "": if gProjectName != "":
try: try:
projectFullPath = expandFilename(projectName) gProjectFull = expandFilename(gProjectName)
except EOS: except EOS:
projectFullPath = projectName gProjectFull = gProjectName
var p = splitFile(projectFullPath) var p = splitFile(gProjectFull)
projectPath = p.dir gProjectPath = p.dir
projectName = p.name gProjectName = p.name
else: else:
projectPath = getCurrentDir() gProjectPath = getCurrentDir()
LoadConfigs() # load all config files LoadConfigs(DefaultConfig) # load all config files
# now process command line arguments again, because some options in the # now process command line arguments again, because some options in the
# command line can overwite the config file's settings # command line can overwite the config file's settings
extccomp.initVars() extccomp.initVars()
@ -91,9 +91,9 @@ proc HandleCmdLine() =
if gCmd notin {cmdInterpret, cmdRun}: if gCmd notin {cmdInterpret, cmdRun}:
rawMessage(hintSuccessX, [$gLinesCompiled, rawMessage(hintSuccessX, [$gLinesCompiled,
formatFloat(epochTime() - start, ffDecimal, 3)]) formatFloat(epochTime() - start, ffDecimal, 3)])
if optRun in gGlobalOptions: if optRun in gGlobalOptions:
var ex = quoteIfContainsWhite( var ex = quoteIfContainsWhite(
changeFileExt(projectFullPath, "").prependCurDir) changeFileExt(gProjectFull, "").prependCurDir)
execExternalProgram(ex & ' ' & arguments) execExternalProgram(ex & ' ' & arguments)
#GC_disableMarkAndSweep() #GC_disableMarkAndSweep()

View file

@ -42,6 +42,7 @@ type # please make sure we have under 32 options
optSkipConfigFile, # skip the general config file optSkipConfigFile, # skip the general config file
optSkipProjConfigFile, # skip the project's config file optSkipProjConfigFile, # skip the project's config file
optSkipUserConfigFile, # skip the users's config file optSkipUserConfigFile, # skip the users's config file
optSkipParentConfigFiles, # skip parent dir's config files
optNoMain, # do not generate a "main" proc optNoMain, # do not generate a "main" proc
optThreads, # support for multi-threading optThreads, # support for multi-threading
optStdout, # output to stdout optStdout, # output to stdout
@ -93,6 +94,7 @@ const
HtmlExt* = "html" HtmlExt* = "html"
TexExt* = "tex" TexExt* = "tex"
IniExt* = "ini" IniExt* = "ini"
DefaultConfig* = "nimrod.cfg"
DocConfig* = "nimdoc.cfg" DocConfig* = "nimdoc.cfg"
DocTexConfig* = "nimdoc.tex.cfg" DocTexConfig* = "nimdoc.tex.cfg"
@ -100,9 +102,9 @@ const
var var
gConfigVars* = newStringTable(modeStyleInsensitive) gConfigVars* = newStringTable(modeStyleInsensitive)
libpath* = "" libpath* = ""
projectName* = "" # holds a name like `nimrod' gProjectName* = "" # holds a name like 'nimrod'
projectPath* = "" # holds a path like /home/alice/projects/nimrod/compiler/ gProjectPath* = "" # holds a path like /home/alice/projects/nimrod/compiler/
projectFullPath* = "" # projectPath/projectName gProjectFull* = "" # projectPath/projectName
nimcacheDir* = "" nimcacheDir* = ""
command* = "" # the main command (e.g. cc, check, scan, etc) command* = "" # the main command (e.g. cc, check, scan, etc)
commandArgs*: seq[string] = @[] # any arguments after the main command commandArgs*: seq[string] = @[] # any arguments after the main command
@ -117,7 +119,7 @@ proc mainCommandArg*: string =
if commandArgs.len > 0: if commandArgs.len > 0:
result = commandArgs[0] result = commandArgs[0]
else: else:
result = projectName result = gProjectName
proc existsConfigVar*(key: string): bool = proc existsConfigVar*(key: string): bool =
result = hasKey(gConfigVars, key) result = hasKey(gConfigVars, key)
@ -136,7 +138,7 @@ proc getPrefixDir*(): string =
## gets the application directory ## gets the application directory
result = SplitPath(getAppDir()).head result = SplitPath(getAppDir()).head
proc shortenDir(dir: string): string = proc shortenDir*(dir: string): string =
## returns the interesting part of a dir ## returns the interesting part of a dir
var prefix = getPrefixDir() & dirSep var prefix = getPrefixDir() & dirSep
if startsWith(dir, prefix): if startsWith(dir, prefix):
@ -144,9 +146,8 @@ proc shortenDir(dir: string): string =
prefix = getCurrentDir() & dirSep prefix = getCurrentDir() & dirSep
if startsWith(dir, prefix): if startsWith(dir, prefix):
return substr(dir, len(prefix)) return substr(dir, len(prefix))
prefix = projectPath & dirSep #writeln(output, prefix); prefix = gProjectPath & dirSep
#writeln(output, dir); if startsWith(dir, prefix):
if startsWith(dir, prefix):
return substr(dir, len(prefix)) return substr(dir, len(prefix))
result = dir result = dir
@ -157,7 +158,7 @@ proc removeTrailingDirSep*(path: string): string =
result = path result = path
proc getGeneratedPath: string = proc getGeneratedPath: string =
result = if nimcacheDir.len > 0: nimcacheDir else: projectPath.shortenDir / result = if nimcacheDir.len > 0: nimcacheDir else: gProjectPath.shortenDir /
genSubDir genSubDir
proc toGeneratedFile*(path, ext: string): string = proc toGeneratedFile*(path, ext: string): string =

View file

@ -836,7 +836,7 @@ proc handleSymbolFile(module: PSym, filename: string): PRodReader =
if optSymbolFiles notin gGlobalOptions: if optSymbolFiles notin gGlobalOptions:
module.id = getID() module.id = getID()
return nil return nil
idgen.loadMaxIds(options.projectPath / options.projectName) idgen.loadMaxIds(options.gProjectPath / options.gProjectName)
discard checkDep(filename) discard checkDep(filename)
var idx = getModuleIdx(filename) var idx = getModuleIdx(filename)

View file

@ -576,7 +576,7 @@ proc myClose(c: PPassContext, n: PNode): PNode =
result = process(c, n) result = process(c, n)
var w = PRodWriter(c) var w = PRodWriter(c)
writeRod(w) writeRod(w)
idgen.saveMaxIds(options.projectPath / options.projectName) idgen.saveMaxIds(options.gProjectPath / options.gProjectName)
proc rodwritePass(): TPass = proc rodwritePass(): TPass =
initPass(result) initPass(result)

View file

@ -52,8 +52,9 @@ Advanced options:
--taintMode:on|off turn taint mode on|off --taintMode:on|off turn taint mode on|off
--symbolFiles:on|off turn symbol files on|off (experimental) --symbolFiles:on|off turn symbol files on|off (experimental)
--skipCfg do not read the general configuration file --skipCfg do not read the general configuration file
--skipProjCfg do not read the project's configuration file
--skipUserCfg do not read the user's configuration file --skipUserCfg do not read the user's configuration file
--skipParentCfg do not read the parent dirs' configuration files
--skipProjCfg do not read the project's configuration file
--gc:refc|boehm|none use Nimrod's native GC|Boehm GC|no GC --gc:refc|boehm|none use Nimrod's native GC|Boehm GC|no GC
--index:FILE use FILE to generate a documentation index file --index:FILE use FILE to generate a documentation index file
--putenv:key=value set an environment variable --putenv:key=value set an environment variable

View file

@ -37,25 +37,21 @@ Advanced command line switches are:
.. include:: advopt.txt .. include:: advopt.txt
Configuration file Configuration files
------------------ -------------------
The default configuration file is ``nimrod.cfg``. The ``nimrod`` executable
looks for it in the following directories (in this order):
1. ``/home/$user/.config/nimrod.cfg`` (UNIX) or ``%APPDATA%/nimrod.cfg`` (Windows)
2. ``$nimrod/config/nimrod.cfg`` (UNIX), ``%NIMROD%/config/nimrod.cfg`` (Windows)
3. ``/etc/nimrod.cfg`` (UNIX)
The search stops as soon as a configuration file has been found. The reading
of ``nimrod.cfg`` can be suppressed by the ``--skipCfg`` command line option.
**Note:** The *project file name* is the name of the ``.nim`` file that is **Note:** The *project file name* is the name of the ``.nim`` file that is
passed as a command line argument to the compiler. passed as a command line argument to the compiler.
All configuration files have the name ``nimrod.cfg``. The ``nimrod``
executable processes configuration files in the following directories
(in this order; later files overwrite previous settings):
1) ``$nimrod/config/nimrod.cfg``, ``/etc/nimrod.cfg`` (UNIX) or ``%NIMROD%/config/nimrod.cfg`` (Windows). This file can be skipped with the ``--skipCfg`` command line option.
2) ``/home/$user/.config/nimrod.cfg`` (UNIX) or ``%APPDATA%/nimrod.cfg`` (Windows). This file can be skipped with the ``--skipUserCfg`` command line option.
3) ``$parentDir/nimrod.cfg`` where ``$parentDir`` stands for any parent directory of the project file's path. These files can be skipped with the ``--skipParentCfg`` command line option.
4) ``$projectDir/nimrod.cfg`` where ``$projectDir`` stands for the project file's path. This file can be skipped with the ``--skipProjCfg`` command line option.
Configuration settings can be overwritten individually in a project specific
configuration file that is read automatically. This specific file has to
be in the same directory as the project and be of the same name, except
that its extension should be ``.cfg``.
Command line settings have priority over configuration file settings. Command line settings have priority over configuration file settings.

View file

@ -140,3 +140,6 @@ proc rejectSpecialTests(r: var TResults, options: string) =
proc compileSpecialTests(r: var TResults, options: string) = proc compileSpecialTests(r: var TResults, options: string) =
compileRodFiles(r, options) compileRodFiles(r, options)
compileSingleTest(r, "compiler/c2nim/c2nim.nim", options)
compileSingleTest(r, "compiler/pas2nim/pas2nim.nim", options)

View file

@ -1,11 +1,10 @@
version 0.8.14 version 0.8.14
============== ==============
- bug: compiler uses full file names again
- implicit invokation of `items`/`pairs` seems nice
- warning for implicit openArray -> varargs convention - warning for implicit openArray -> varargs convention
- implement explicit varargs; **but** ``len(varargs)`` problem remains! - implement explicit varargs; **but** ``len(varargs)`` problem remains!
--> solve by implicit conversion from varargs to openarray --> solve by implicit conversion from varargs to openarray
- implicit invokation of `items`/`pairs` seems nice
version 0.9.0 version 0.9.0
============= =============

View file

@ -91,13 +91,13 @@ Compiler Additions
directory for generated code. directory for generated code.
- Added ``--cincludes:dir``, ``--clibdir:lib`` configuration options for - Added ``--cincludes:dir``, ``--clibdir:lib`` configuration options for
modifying the C compiler's header/library search path in cross-platform way. modifying the C compiler's header/library search path in cross-platform way.
- Added ``--clib:lib`` configuration options for specifying additional - Added ``--clib:lib`` configuration option for specifying additional
C libraries to be linked. C libraries to be linked.
- Added ``--mainmodule:file`` configuration options for specifying the main - Added ``--mainmodule:file`` configuration options for specifying the main
project file. This is intended to be used in project configuration files to 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 allow commands like ``nimrod c`` or ``nimrod check`` to be executed anywhere
within the project's directory structure within the project's directory structure.
- Added a ``--app:staticlib`` option for creating static libraries - Added a ``--app:staticlib`` option for creating static libraries.
- Added a ``--tlsEmulation:on|off`` switch for control over thread local - Added a ``--tlsEmulation:on|off`` switch for control over thread local
storage emulation. storage emulation.
- The compiler and standard library now support a *taint mode*. Input strings - The compiler and standard library now support a *taint mode*. Input strings

View file

@ -34,7 +34,7 @@ interpretation you will have to look harder.
Why yet another programming language? Why yet another programming language?
------------------------------------- -------------------------------------
Nimrod is one of the very few *programmable* strongly typed languages, and Nimrod is one of the very few *programmable* statically typed languages, and
one of the even fewer that will produce native binaries that require no one of the even fewer that will produce native binaries that require no
runtime or interpreter. runtime or interpreter.
@ -49,12 +49,14 @@ license of Nimrod to the BSD license.
How stable is Nimrod? How stable is Nimrod?
--------------------- ---------------------
The compiler is in development and some important features are still missing. The compiler is in development and some important features are still missing.
However, the compiler is quite stable already: It is able to compile itself However, the compiler is quite stable already: It is able to compile itself
and a substantial body of other code. Until version 1.0.0 is released, and a substantial body of other code. Until version 1.0.0 is released,
incompatibilities with older versions of the compiler will be introduced. The incompatibilities with older versions of the compiler will be introduced. The
semantic details of overloading, macros/templates/generics and iterators semantic details of overloading, macros/templates/generics and iterators
and their interactions are subject to change. and their interactions are subject to change. Changes to the syntax
are also planned; gone will be the distinction between expressions and
statements.
How fast is Nimrod? How fast is Nimrod?