mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-15 23:54:19 +00:00
cleaned up configuration file handling and documented the new behaviour
This commit is contained in:
@@ -862,7 +862,7 @@ proc newModule(module: PSym, filename: string): BModule =
|
||||
proc registerTypeInfoModule() =
|
||||
const moduleName = "nim__dat"
|
||||
var s = NewSym(skModule, getIdent(moduleName), nil)
|
||||
gNimDat = rawNewModule(s, (options.projectPath / moduleName) & ".nim")
|
||||
gNimDat = rawNewModule(s, (options.gProjectPath / moduleName) & ".nim")
|
||||
gNimDat.PreventStackTrace = true
|
||||
addPendingModule(gNimDat)
|
||||
appff(mainModProcs, "N_NOINLINE(void, $1)(void);$n",
|
||||
|
||||
@@ -37,37 +37,28 @@ proc getCommandLineDesc(): string =
|
||||
result = (HelpMessage % [VersionAsString, platform.os[platform.hostOS].name,
|
||||
cpu[platform.hostCPU].name]) & Usage
|
||||
|
||||
var
|
||||
helpWritten: bool # BUGFIX 19
|
||||
versionWritten: bool
|
||||
advHelpWritten: bool
|
||||
|
||||
proc HelpOnError(pass: TCmdLinePass) =
|
||||
if (pass == passCmd1) and not helpWritten:
|
||||
# BUGFIX 19
|
||||
if pass == passCmd1:
|
||||
MsgWriteln(getCommandLineDesc())
|
||||
helpWritten = true
|
||||
quit(0)
|
||||
|
||||
proc writeAdvancedUsage(pass: TCmdLinePass) =
|
||||
if (pass == passCmd1) and not advHelpWritten:
|
||||
# BUGFIX 19
|
||||
if pass == passCmd1:
|
||||
MsgWriteln(`%`(HelpMessage, [VersionAsString,
|
||||
platform.os[platform.hostOS].name,
|
||||
cpu[platform.hostCPU].name]) & AdvancedUsage)
|
||||
advHelpWritten = true
|
||||
helpWritten = true
|
||||
quit(0)
|
||||
|
||||
proc writeVersionInfo(pass: TCmdLinePass) =
|
||||
if (pass == passCmd1) and not versionWritten:
|
||||
versionWritten = true
|
||||
helpWritten = true
|
||||
if pass == passCmd1:
|
||||
MsgWriteln(`%`(HelpMessage, [VersionAsString,
|
||||
platform.os[platform.hostOS].name,
|
||||
cpu[platform.hostCPU].name]))
|
||||
quit(0)
|
||||
|
||||
var
|
||||
helpWritten: bool
|
||||
|
||||
proc writeCommandLineUsage() =
|
||||
if not helpWritten:
|
||||
MsgWriteln(getCommandLineDesc())
|
||||
@@ -197,8 +188,8 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool =
|
||||
proc processPath(path: string): string =
|
||||
result = UnixToNativePath(path % ["nimrod", getPrefixDir(), "lib", libpath,
|
||||
"home", removeTrailingDirSep(os.getHomeDir()),
|
||||
"projectname", options.projectName,
|
||||
"projectpath", options.projectPath])
|
||||
"projectname", options.gProjectName,
|
||||
"projectpath", options.gProjectPath])
|
||||
|
||||
proc addPath(path: string, info: TLineInfo) =
|
||||
if not contains(options.searchPaths, path):
|
||||
@@ -246,8 +237,8 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||
options.outFile = arg
|
||||
of "mainmodule", "m":
|
||||
expectArg(switch, arg, pass, info)
|
||||
projectName = arg
|
||||
projectFullPath = projectPath/projectName
|
||||
gProjectName = arg
|
||||
gProjectFull = gProjectPath / gProjectName
|
||||
of "define", "d":
|
||||
expectArg(switch, arg, pass, info)
|
||||
DefineSymbol(arg)
|
||||
@@ -433,6 +424,9 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||
of "skipusercfg":
|
||||
expectNoArg(switch, arg, pass, info)
|
||||
incl(gGlobalOptions, optSkipUserConfigFile)
|
||||
of "skipparentcfg":
|
||||
expectNoArg(switch, arg, pass, info)
|
||||
incl(gGlobalOptions, optSkipParentConfigFiles)
|
||||
of "genscript":
|
||||
expectNoArg(switch, arg, pass, info)
|
||||
incl(gGlobalOptions, optGenScript)
|
||||
|
||||
@@ -865,13 +865,13 @@ proc writeOutput(d: PDoc, filename, outExt: string) =
|
||||
writeRope(content, getOutFile(filename, outExt))
|
||||
|
||||
proc CommandDoc =
|
||||
var ast = parseFile(addFileExt(projectFullPath, nimExt))
|
||||
var ast = parseFile(addFileExt(gProjectFull, nimExt))
|
||||
if ast == nil: return
|
||||
var d = newDocumentor(projectFullPath)
|
||||
var d = newDocumentor(gProjectFull)
|
||||
initIndexFile(d)
|
||||
d.hasToc = true
|
||||
generateDoc(d, ast)
|
||||
writeOutput(d, projectFullPath, HtmlExt)
|
||||
writeOutput(d, gProjectFull, HtmlExt)
|
||||
generateIndex(d)
|
||||
|
||||
proc CommandRstAux(filename, outExt: string) =
|
||||
@@ -884,9 +884,9 @@ proc CommandRstAux(filename, outExt: string) =
|
||||
generateIndex(d)
|
||||
|
||||
proc CommandRst2Html =
|
||||
CommandRstAux(projectFullPath, HtmlExt)
|
||||
CommandRstAux(gProjectFull, HtmlExt)
|
||||
|
||||
proc CommandRst2TeX =
|
||||
splitter = "\\-"
|
||||
CommandRstAux(projectFullPath, TexExt)
|
||||
CommandRstAux(gProjectFull, TexExt)
|
||||
|
||||
|
||||
@@ -305,16 +305,14 @@ var
|
||||
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
|
||||
cIncludes*: seq[string] = @[] # directories to search for included files
|
||||
cLibs*: seq[string] = @[] # directories to search for lib files
|
||||
cLinkedLibs*: seq[string] = @[] # libraries to link
|
||||
|
||||
# implementation
|
||||
|
||||
when defined(windows):
|
||||
var libNameTmpl = "$1.lib"
|
||||
else:
|
||||
var libNameTmpl = "lib$1.a"
|
||||
proc libNameTmpl(): string {.inline.} =
|
||||
result = if targetOS == osWindows: "$1.lib" else: "lib$1.a"
|
||||
|
||||
var
|
||||
toLink, toCompile, externalToCompile: TLinkedList
|
||||
@@ -431,43 +429,41 @@ 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
|
||||
s.add many.join
|
||||
|
||||
proc getCompileCFileCmd*(cfilename: string, isExternal: bool = false): string =
|
||||
var
|
||||
cfile, objfile, options, includeCmd, compilePattern, key, trunk, exe: string
|
||||
var c = ccompiler
|
||||
options = compileOptions
|
||||
trunk = splitFile(cfilename).name
|
||||
proc CFileSpecificOptions(cfilename: string): string =
|
||||
result = compileOptions
|
||||
var trunk = splitFile(cfilename).name
|
||||
if optCDebug in gGlobalOptions:
|
||||
key = trunk & ".debug"
|
||||
if existsConfigVar(key): addOpt(options, getConfigVar(key))
|
||||
else: addOpt(options, getDebug(c))
|
||||
if (optOptimizeSpeed in gOptions):
|
||||
#if ((fileCounter >= specialFileA) and (fileCounter <= specialFileB)) then
|
||||
key = trunk & ".speed"
|
||||
if existsConfigVar(key): addOpt(options, getConfigVar(key))
|
||||
else: addOpt(options, getOptSpeed(c))
|
||||
elif optOptimizeSize in gOptions:
|
||||
key = trunk & ".size"
|
||||
if existsConfigVar(key): addOpt(options, getConfigVar(key))
|
||||
else: addOpt(options, getOptSize(c))
|
||||
key = trunk & ".always"
|
||||
if existsConfigVar(key): addOpt(options, getConfigVar(key))
|
||||
exe = cc[c].compilerExe
|
||||
key = cc[c].name & ".exe"
|
||||
var key = trunk & ".debug"
|
||||
if existsConfigVar(key): addOpt(result, getConfigVar(key))
|
||||
else: addOpt(result, getDebug(ccompiler))
|
||||
if optOptimizeSpeed in gOptions:
|
||||
var key = trunk & ".speed"
|
||||
if existsConfigVar(key): addOpt(result, getConfigVar(key))
|
||||
else: addOpt(result, getOptSpeed(ccompiler))
|
||||
elif optOptimizeSize in gOptions:
|
||||
var key = trunk & ".size"
|
||||
if existsConfigVar(key): addOpt(result, getConfigVar(key))
|
||||
else: addOpt(result, getOptSize(ccompiler))
|
||||
var key = trunk & ".always"
|
||||
if existsConfigVar(key): addOpt(result, getConfigVar(key))
|
||||
|
||||
proc getCompileCFileCmd*(cfilename: string, isExternal = false): string =
|
||||
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 targetOS == osWindows: exe = addFileExt(exe, "exe")
|
||||
if optGenDynLib in gGlobalOptions and
|
||||
ospNeedsPIC in platform.OS[targetOS].props:
|
||||
add(options, ' ' & cc[c].pic)
|
||||
|
||||
var includeCmd, compilePattern: string
|
||||
if targetOS == platform.hostOS:
|
||||
# compute include paths:
|
||||
includeCmd = cc[c].includeCmd # this is more complex than needed, but
|
||||
# a workaround of a FPC bug...
|
||||
add(includeCmd, quoteIfContainsWhite(libpath))
|
||||
includeCmd = cc[c].includeCmd & quoteIfContainsWhite(libpath)
|
||||
|
||||
for includeDir in items(cIncludes):
|
||||
includeCmd.add cc[c].includeCmd, includeDir.quoteIfContainsWhite
|
||||
@@ -476,15 +472,17 @@ proc getCompileCFileCmd*(cfilename: string, isExternal: bool = false): string =
|
||||
else:
|
||||
includeCmd = ""
|
||||
compilePattern = cc[c].compilerExe
|
||||
if targetOS == platform.hostOS: cfile = cfilename
|
||||
else: cfile = extractFileName(cfilename)
|
||||
if not isExternal or targetOS != platform.hostOS: objfile = toObjFile(cfile)
|
||||
else: objfile = completeCFilePath(toObjFile(cfile))
|
||||
|
||||
# XXX fix the grammar finally, we need multi-line if expressions:
|
||||
var cfile = if targetOS == platform.hostOS: cfilename else: extractFileName(
|
||||
cfilename)
|
||||
var objfile = if not isExternal or targetOS != platform.hostOS: toObjFile(
|
||||
cfile) else: completeCFilePath(toObjFile(cfile))
|
||||
cfile = quoteIfContainsWhite(AddFileExt(cfile, cExt))
|
||||
objfile = quoteIfContainsWhite(objfile)
|
||||
result = quoteIfContainsWhite(`%`(compilePattern, ["file", cfile, "objfile",
|
||||
objfile, "options", options, "include", includeCmd, "nimrod",
|
||||
getPrefixDir(), "lib", libpath]))
|
||||
result = quoteIfContainsWhite(compilePattern % [
|
||||
"file", cfile, "objfile", objfile, "options", options,
|
||||
"include", includeCmd, "nimrod", getPrefixDir(), "lib", libpath])
|
||||
add(result, ' ')
|
||||
addf(result, cc[c].compileTmpl, [
|
||||
"file", cfile, "objfile", objfile,
|
||||
@@ -498,9 +496,9 @@ proc CompileCFile(list: TLinkedList, script: var PRope, cmds: var TStringSeq,
|
||||
while it != nil:
|
||||
inc(fileCounter) # call the C compiler for the .c file:
|
||||
var compileCmd = getCompileCFileCmd(it.data, isExternal)
|
||||
if not (optCompileOnly in gGlobalOptions):
|
||||
if optCompileOnly notin gGlobalOptions:
|
||||
add(cmds, compileCmd)
|
||||
if (optGenScript in gGlobalOptions):
|
||||
if optGenScript in gGlobalOptions:
|
||||
app(script, compileCmd)
|
||||
app(script, tnl)
|
||||
it = PStrEntry(it.next)
|
||||
@@ -522,7 +520,7 @@ proc CallCCompiler*(projectfile: string) =
|
||||
var res = 0
|
||||
if gNumberOfProcessors <= 1:
|
||||
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},
|
||||
gNumberOfProcessors)
|
||||
else:
|
||||
@@ -535,26 +533,25 @@ proc CallCCompiler*(projectfile: string) =
|
||||
var objfiles = ""
|
||||
while it != nil:
|
||||
add(objfiles, ' ')
|
||||
if targetOS == platform.hostOS:
|
||||
add(objfiles, quoteIfContainsWhite(addFileExt(it.data, cc[ccompiler].objExt)))
|
||||
else:
|
||||
add(objfiles, quoteIfContainsWhite(addFileExt(it.data, cc[ccompiler].objExt)))
|
||||
add(objfiles, quoteIfContainsWhite(
|
||||
addFileExt(it.data, cc[ccompiler].objExt)))
|
||||
it = PStrEntry(it.next)
|
||||
|
||||
if optGenStaticLib in gGlobalOptions:
|
||||
linkcmd = cc[c].buildLib % ["libfile", (libNameTmpl % projectName), "objfiles", objfiles]
|
||||
linkcmd = cc[c].buildLib % ["libfile", (libNameTmpl() % gProjectName),
|
||||
"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)
|
||||
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])
|
||||
exefile = platform.os[targetOS].dllFrmt % [splitFile(projectFile).name]
|
||||
buildDll = cc[c].buildDll
|
||||
else:
|
||||
exefile = splitFile(projectFile).name & platform.os[targetOS].exeExt
|
||||
@@ -596,4 +593,5 @@ proc writeMapping*(gSymbolMapping: PRope) =
|
||||
app(code, genMappingFiles(toCompile))
|
||||
app(code, genMappingFiles(externalToCompile))
|
||||
appf(code, "[Symbols]$n$1", [gSymbolMapping])
|
||||
WriteRope(code, joinPath(projectPath, "mapping.txt"))
|
||||
WriteRope(code, joinPath(gProjectPath, "mapping.txt"))
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ proc CompileModule(filename: string, flags: TSymFlags): PSym =
|
||||
result.id = getID()
|
||||
processModule(result, f, nil, rd)
|
||||
|
||||
proc CompileProject(projectFile = projectFullPath) =
|
||||
proc CompileProject(projectFile = gProjectFull) =
|
||||
discard CompileModule(options.libpath / "system", {sfSystemModule})
|
||||
discard CompileModule(projectFile, {sfMainModule})
|
||||
|
||||
@@ -95,9 +95,9 @@ proc CommandGenDepend =
|
||||
registerPass(genDependPass())
|
||||
registerPass(cleanupPass())
|
||||
compileProject()
|
||||
generateDot(projectFullPath)
|
||||
execExternalProgram("dot -Tpng -o" & changeFileExt(projectFullPath, "png") &
|
||||
' ' & changeFileExt(projectFullPath, "dot"))
|
||||
generateDot(gProjectFull)
|
||||
execExternalProgram("dot -Tpng -o" & changeFileExt(gProjectFull, "png") &
|
||||
' ' & changeFileExt(gProjectFull, "dot"))
|
||||
|
||||
proc CommandCheck =
|
||||
msgs.gErrorMax = high(int) # do not stop after first error
|
||||
@@ -112,7 +112,7 @@ proc CommandCompileToC =
|
||||
#registerPass(cleanupPass())
|
||||
compileProject()
|
||||
if gCmd != cmdRun:
|
||||
extccomp.CallCCompiler(changeFileExt(projectFullPath, ""))
|
||||
extccomp.CallCCompiler(changeFileExt(gProjectFull, ""))
|
||||
|
||||
when has_LLVM_Backend:
|
||||
proc CommandCompileToLLVM =
|
||||
@@ -177,14 +177,14 @@ proc CommandSuggest =
|
||||
compileProject()
|
||||
|
||||
proc wantMainModule =
|
||||
if projectFullPath.len == 0:
|
||||
if gProjectFull.len == 0:
|
||||
Fatal(newLineInfo("command line", 1, 1), errCommandExpectsFilename)
|
||||
|
||||
proc MainCommand =
|
||||
appendStr(searchPaths, options.libpath)
|
||||
if projectFullPath.len != 0:
|
||||
# current path is dalways looked first for modules
|
||||
prependStr(searchPaths, projectPath)
|
||||
if gProjectFull.len != 0:
|
||||
# current path is always looked first for modules
|
||||
prependStr(searchPaths, gProjectPath)
|
||||
setID(100)
|
||||
passes.gIncludeFile = syntaxes.parseFile
|
||||
passes.gImportModule = importModule
|
||||
@@ -259,7 +259,7 @@ proc MainCommand =
|
||||
of "parse":
|
||||
gCmd = cmdParse
|
||||
wantMainModule()
|
||||
discard parseFile(addFileExt(projectFullPath, nimExt))
|
||||
discard parseFile(addFileExt(gProjectFull, nimExt))
|
||||
of "scan":
|
||||
gCmd = cmdScan
|
||||
wantMainModule()
|
||||
|
||||
@@ -96,7 +96,7 @@ type
|
||||
errUser,
|
||||
warnCannotOpenFile,
|
||||
warnOctalEscape, warnXIsNeverRead, warnXmightNotBeenInit,
|
||||
warnDeprecated,
|
||||
warnDeprecated, warnConfigDeprecated,
|
||||
warnSmallLshouldNotBeUsed, warnUnknownMagic, warnRedefinitionOfLabel,
|
||||
warnUnknownSubstitutionX, warnLanguageXNotSupported, warnCommentXIgnored,
|
||||
warnXisPassedToProcVar, warnDerefDeprecated, warnAnalysisLoophole,
|
||||
@@ -328,6 +328,7 @@ const
|
||||
warnXIsNeverRead: "\'$1\' is never read [XIsNeverRead]",
|
||||
warnXmightNotBeenInit: "\'$1\' might not have been initialized [XmightNotBeenInit]",
|
||||
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]",
|
||||
warnUnknownMagic: "unknown magic \'$1\' might crash the compiler [UnknownMagic]",
|
||||
warnRedefinitionOfLabel: "redefinition of label \'$1\' [RedefinitionOfLabel]",
|
||||
@@ -356,9 +357,10 @@ const
|
||||
hintUser: "$1 [User]"]
|
||||
|
||||
const
|
||||
WarningsToStr*: array[0..16, string] = ["CannotOpenFile", "OctalEscape",
|
||||
WarningsToStr*: array[0..17, string] = ["CannotOpenFile", "OctalEscape",
|
||||
"XIsNeverRead", "XmightNotBeenInit",
|
||||
"Deprecated", "SmallLshouldNotBeUsed", "UnknownMagic",
|
||||
"Deprecated", "ConfigDeprecated",
|
||||
"SmallLshouldNotBeUsed", "UnknownMagic",
|
||||
"RedefinitionOfLabel", "UnknownSubstitutionX", "LanguageXNotSupported",
|
||||
"CommentXIgnored", "XisPassedToProcVar", "DerefDeprecated",
|
||||
"AnalysisLoophole", "DifferentHeaps", "WriteToForeignHeap", "User"]
|
||||
@@ -443,7 +445,7 @@ proc includeFilename*(f: string): int =
|
||||
|
||||
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.line = int16(line)
|
||||
result.col = int16(col)
|
||||
|
||||
@@ -189,14 +189,14 @@ proc parseAssignment(L: var TLexer, tok: var TToken) =
|
||||
confTok(L, tok)
|
||||
processSwitch(s, val, passPP, info)
|
||||
|
||||
proc readConfigFile(filename: string) =
|
||||
var
|
||||
proc readConfigFile(filename: string) =
|
||||
var
|
||||
L: TLexer
|
||||
tok: TToken
|
||||
stream: PLLStream
|
||||
initToken(tok)
|
||||
stream = LLStreamOpen(filename, fmRead)
|
||||
if stream != nil:
|
||||
if stream != nil:
|
||||
initToken(tok)
|
||||
openLexer(L, filename, stream)
|
||||
tok.tokType = tkEof # to avoid a pointless warning
|
||||
confTok(L, tok) # read in the first token
|
||||
@@ -214,7 +214,7 @@ proc getSystemConfigPath(filename: string): string =
|
||||
result = joinPath([getPrefixDir(), "config", filename])
|
||||
if not ExistsFile(result): result = "/etc/" & filename
|
||||
|
||||
proc LoadConfigs*(cfg = "nimrod.cfg") =
|
||||
proc LoadConfigs*(cfg: string) =
|
||||
# set default value (can be overwritten):
|
||||
if libpath == "":
|
||||
# choose default libpath:
|
||||
@@ -224,12 +224,21 @@ proc LoadConfigs*(cfg = "nimrod.cfg") =
|
||||
else: libpath = joinPath(prefix, "lib")
|
||||
|
||||
if optSkipConfigFile notin gGlobalOptions:
|
||||
readConfigFile getSystemConfigPath(cfg)
|
||||
readConfigFile(getSystemConfigPath(cfg))
|
||||
|
||||
if optSkipUserConfigFile notin gGlobalOptions:
|
||||
readConfigFile getUserConfigPath(cfg)
|
||||
readConfigFile(getUserConfigPath(cfg))
|
||||
|
||||
if optSkipProjConfigFile notin gGlobalOptions and projectPath != "":
|
||||
for dir in parentDirs(projectPath, fromRoot = true):
|
||||
readConfigFile(dir/cfg)
|
||||
var pd = if gProjectPath.len > 0: gProjectPath else: getCurrentDir()
|
||||
if optSkipParentConfigFiles notin gGlobalOptions:
|
||||
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)
|
||||
|
||||
|
||||
@@ -44,9 +44,9 @@ proc ProcessCmdLine(pass: TCmdLinePass) =
|
||||
else:
|
||||
options.commandArgs.add p.key
|
||||
|
||||
if options.projectName == "":
|
||||
if options.gProjectName == "":
|
||||
# support UNIX style filenames anywhere for portable build scripts:
|
||||
options.projectName = unixToNativePath(p.key)
|
||||
options.gProjectName = unixToNativePath(p.key)
|
||||
arguments = cmdLineRest(p)
|
||||
|
||||
if pass == passCmd2:
|
||||
@@ -64,20 +64,20 @@ proc HandleCmdLine() =
|
||||
var start = epochTime()
|
||||
if paramCount() == 0:
|
||||
writeCommandLineUsage()
|
||||
else:
|
||||
else:
|
||||
# Process command line arguments:
|
||||
ProcessCmdLine(passCmd1)
|
||||
if projectName != "":
|
||||
if gProjectName != "":
|
||||
try:
|
||||
projectFullPath = expandFilename(projectName)
|
||||
gProjectFull = expandFilename(gProjectName)
|
||||
except EOS:
|
||||
projectFullPath = projectName
|
||||
var p = splitFile(projectFullPath)
|
||||
projectPath = p.dir
|
||||
projectName = p.name
|
||||
gProjectFull = gProjectName
|
||||
var p = splitFile(gProjectFull)
|
||||
gProjectPath = p.dir
|
||||
gProjectName = p.name
|
||||
else:
|
||||
projectPath = getCurrentDir()
|
||||
LoadConfigs() # load all config files
|
||||
gProjectPath = getCurrentDir()
|
||||
LoadConfigs(DefaultConfig) # 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()
|
||||
@@ -91,9 +91,9 @@ proc HandleCmdLine() =
|
||||
if gCmd notin {cmdInterpret, cmdRun}:
|
||||
rawMessage(hintSuccessX, [$gLinesCompiled,
|
||||
formatFloat(epochTime() - start, ffDecimal, 3)])
|
||||
if optRun in gGlobalOptions:
|
||||
if optRun in gGlobalOptions:
|
||||
var ex = quoteIfContainsWhite(
|
||||
changeFileExt(projectFullPath, "").prependCurDir)
|
||||
changeFileExt(gProjectFull, "").prependCurDir)
|
||||
execExternalProgram(ex & ' ' & arguments)
|
||||
|
||||
#GC_disableMarkAndSweep()
|
||||
|
||||
@@ -42,6 +42,7 @@ type # please make sure we have under 32 options
|
||||
optSkipConfigFile, # skip the general config file
|
||||
optSkipProjConfigFile, # skip the project's config file
|
||||
optSkipUserConfigFile, # skip the users's config file
|
||||
optSkipParentConfigFiles, # skip parent dir's config files
|
||||
optNoMain, # do not generate a "main" proc
|
||||
optThreads, # support for multi-threading
|
||||
optStdout, # output to stdout
|
||||
@@ -93,6 +94,7 @@ const
|
||||
HtmlExt* = "html"
|
||||
TexExt* = "tex"
|
||||
IniExt* = "ini"
|
||||
DefaultConfig* = "nimrod.cfg"
|
||||
DocConfig* = "nimdoc.cfg"
|
||||
DocTexConfig* = "nimdoc.tex.cfg"
|
||||
|
||||
@@ -100,9 +102,9 @@ const
|
||||
var
|
||||
gConfigVars* = newStringTable(modeStyleInsensitive)
|
||||
libpath* = ""
|
||||
projectName* = "" # holds a name like `nimrod'
|
||||
projectPath* = "" # holds a path like /home/alice/projects/nimrod/compiler/
|
||||
projectFullPath* = "" # projectPath/projectName
|
||||
gProjectName* = "" # holds a name like 'nimrod'
|
||||
gProjectPath* = "" # holds a path like /home/alice/projects/nimrod/compiler/
|
||||
gProjectFull* = "" # projectPath/projectName
|
||||
nimcacheDir* = ""
|
||||
command* = "" # the main command (e.g. cc, check, scan, etc)
|
||||
commandArgs*: seq[string] = @[] # any arguments after the main command
|
||||
@@ -117,7 +119,7 @@ proc mainCommandArg*: string =
|
||||
if commandArgs.len > 0:
|
||||
result = commandArgs[0]
|
||||
else:
|
||||
result = projectName
|
||||
result = gProjectName
|
||||
|
||||
proc existsConfigVar*(key: string): bool =
|
||||
result = hasKey(gConfigVars, key)
|
||||
@@ -136,7 +138,7 @@ proc getPrefixDir*(): string =
|
||||
## gets the application directory
|
||||
result = SplitPath(getAppDir()).head
|
||||
|
||||
proc shortenDir(dir: string): string =
|
||||
proc shortenDir*(dir: string): string =
|
||||
## returns the interesting part of a dir
|
||||
var prefix = getPrefixDir() & dirSep
|
||||
if startsWith(dir, prefix):
|
||||
@@ -144,9 +146,8 @@ proc shortenDir(dir: string): string =
|
||||
prefix = getCurrentDir() & dirSep
|
||||
if startsWith(dir, prefix):
|
||||
return substr(dir, len(prefix))
|
||||
prefix = projectPath & dirSep #writeln(output, prefix);
|
||||
#writeln(output, dir);
|
||||
if startsWith(dir, prefix):
|
||||
prefix = gProjectPath & dirSep
|
||||
if startsWith(dir, prefix):
|
||||
return substr(dir, len(prefix))
|
||||
result = dir
|
||||
|
||||
@@ -157,7 +158,7 @@ proc removeTrailingDirSep*(path: string): string =
|
||||
result = path
|
||||
|
||||
proc getGeneratedPath: string =
|
||||
result = if nimcacheDir.len > 0: nimcacheDir else: projectPath.shortenDir /
|
||||
result = if nimcacheDir.len > 0: nimcacheDir else: gProjectPath.shortenDir /
|
||||
genSubDir
|
||||
|
||||
proc toGeneratedFile*(path, ext: string): string =
|
||||
|
||||
@@ -836,7 +836,7 @@ proc handleSymbolFile(module: PSym, filename: string): PRodReader =
|
||||
if optSymbolFiles notin gGlobalOptions:
|
||||
module.id = getID()
|
||||
return nil
|
||||
idgen.loadMaxIds(options.projectPath / options.projectName)
|
||||
idgen.loadMaxIds(options.gProjectPath / options.gProjectName)
|
||||
|
||||
discard checkDep(filename)
|
||||
var idx = getModuleIdx(filename)
|
||||
|
||||
@@ -576,7 +576,7 @@ proc myClose(c: PPassContext, n: PNode): PNode =
|
||||
result = process(c, n)
|
||||
var w = PRodWriter(c)
|
||||
writeRod(w)
|
||||
idgen.saveMaxIds(options.projectPath / options.projectName)
|
||||
idgen.saveMaxIds(options.gProjectPath / options.gProjectName)
|
||||
|
||||
proc rodwritePass(): TPass =
|
||||
initPass(result)
|
||||
|
||||
@@ -52,8 +52,9 @@ Advanced options:
|
||||
--taintMode:on|off turn taint mode on|off
|
||||
--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
|
||||
--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
|
||||
--index:FILE use FILE to generate a documentation index file
|
||||
--putenv:key=value set an environment variable
|
||||
|
||||
@@ -37,25 +37,21 @@ Advanced command line switches are:
|
||||
.. include:: advopt.txt
|
||||
|
||||
|
||||
Configuration file
|
||||
------------------
|
||||
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.
|
||||
Configuration files
|
||||
-------------------
|
||||
|
||||
**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.
|
||||
|
||||
|
||||
@@ -140,3 +140,6 @@ proc rejectSpecialTests(r: var TResults, options: string) =
|
||||
proc compileSpecialTests(r: var TResults, options: string) =
|
||||
compileRodFiles(r, options)
|
||||
|
||||
compileSingleTest(r, "compiler/c2nim/c2nim.nim", options)
|
||||
compileSingleTest(r, "compiler/pas2nim/pas2nim.nim", options)
|
||||
|
||||
|
||||
3
todo.txt
3
todo.txt
@@ -1,11 +1,10 @@
|
||||
version 0.8.14
|
||||
==============
|
||||
|
||||
- bug: compiler uses full file names again
|
||||
- implicit invokation of `items`/`pairs` seems nice
|
||||
- warning for implicit openArray -> varargs convention
|
||||
- implement explicit varargs; **but** ``len(varargs)`` problem remains!
|
||||
--> solve by implicit conversion from varargs to openarray
|
||||
- implicit invokation of `items`/`pairs` seems nice
|
||||
|
||||
version 0.9.0
|
||||
=============
|
||||
|
||||
@@ -91,13 +91,13 @@ Compiler Additions
|
||||
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
|
||||
- Added ``--clib:lib`` configuration option 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
|
||||
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
|
||||
|
||||
@@ -34,7 +34,7 @@ interpretation you will have to look harder.
|
||||
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
|
||||
runtime or interpreter.
|
||||
|
||||
@@ -49,12 +49,14 @@ license of Nimrod to the BSD license.
|
||||
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
|
||||
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
|
||||
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?
|
||||
|
||||
Reference in New Issue
Block a user