This commit is contained in:
Araq
2015-04-23 23:49:10 +02:00
parent a7a2fa63aa
commit c8bebe92e2
3 changed files with 96 additions and 155 deletions

View File

@@ -319,7 +319,7 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
undefSymbol(arg)
of "symbol":
expectArg(switch, arg, pass, info)
declareSymbol(arg)
# deprecated, do nothing
of "compile":
expectArg(switch, arg, pass, info)
if pass in {passCmd2, passPP}: processCompile(arg)
@@ -488,7 +488,6 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
if theOS == osNone: localError(info, errUnknownOS, arg)
elif theOS != platform.hostOS:
setTarget(theOS, targetCPU)
condsyms.initDefines()
of "cpu":
expectArg(switch, arg, pass, info)
if pass in {passCmd1, passPP}:
@@ -496,7 +495,6 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
if cpu == cpuNone: localError(info, errUnknownCPU, arg)
elif cpu != platform.hostCPU:
setTarget(targetOS, cpu)
condsyms.initDefines()
of "run", "r":
expectNoArg(switch, arg, pass, info)
incl(gGlobalOptions, optRun)

View File

@@ -9,71 +9,69 @@
# This module handles the conditional symbols.
import
import
strtabs, platform, strutils, idents
# We need to use a PStringTable here as defined symbols are always guaranteed
# We need to use a StringTableRef here as defined symbols are always guaranteed
# to be style insensitive. Otherwise hell would break lose.
var gSymbols: StringTableRef
proc defineSymbol*(symbol: string) =
const
catNone = "false"
proc defineSymbol*(symbol: string) =
gSymbols[symbol] = "true"
proc declareSymbol*(symbol: string) =
gSymbols[symbol] = "unknown"
proc undefSymbol*(symbol: string) =
gSymbols[symbol] = catNone
proc undefSymbol*(symbol: string) =
gSymbols[symbol] = "false"
proc isDefined*(symbol: string): bool =
proc isDefined*(symbol: string): bool =
if gSymbols.hasKey(symbol):
result = gSymbols[symbol] == "true"
result = gSymbols[symbol] != catNone
elif cmpIgnoreStyle(symbol, CPU[targetCPU].name) == 0:
result = true
elif cmpIgnoreStyle(symbol, platform.OS[targetOS].name) == 0:
result = true
else:
case symbol.normalize
of "x86": result = targetCPU == cpuI386
of "itanium": result = targetCPU == cpuIa64
of "x8664": result = targetCPU == cpuAmd64
of "posix", "unix":
result = targetOS in {osLinux, osMorphos, osSkyos, osIrix, osPalmos,
osQnx, osAtari, osAix,
osHaiku, osVxWorks, osSolaris, osNetbsd,
osFreebsd, osOpenbsd, osMacosx}
of "bsd":
result = targetOS in {osNetbsd, osFreebsd, osOpenbsd}
of "emulatedthreadvars":
result = platform.OS[targetOS].props.contains(ospLacksThreadVars)
of "msdos": result = targetOS == osDos
of "mswindows", "win32": result = targetOS == osWindows
of "macintosh": result = targetOS in {osMacos, osMacosx}
of "sunos": result = targetOS == osSolaris
of "littleendian": result = CPU[targetCPU].endian == platform.littleEndian
of "bigendian": result = CPU[targetCPU].endian == platform.bigEndian
of "cpu8": result = CPU[targetCPU].bit == 8
of "cpu16": result = CPU[targetCPU].bit == 16
of "cpu32": result = CPU[targetCPU].bit == 32
of "cpu64": result = CPU[targetCPU].bit == 64
of "nimrawsetjmp":
result = targetOS in {osSolaris, osNetbsd, osFreebsd, osOpenbsd, osMacosx}
else: discard
proc isDefined*(symbol: PIdent): bool = isDefined(symbol.s)
proc isDeclared*(symbol: PIdent): bool = gSymbols.hasKey(symbol.s)
iterator definedSymbolNames*: string =
for key, val in pairs(gSymbols):
if val == "true": yield key
if val != catNone: yield key
proc countDefinedSymbols*(): int =
proc countDefinedSymbols*(): int =
result = 0
for key, val in pairs(gSymbols):
if val == "true": inc(result)
if val != catNone: inc(result)
# For ease of bootstrapping, we keep them here and not in the global config
# file for now:
const
additionalSymbols = """
x86 itanium x8664
msdos mswindows win32 unix posix sunos bsd macintosh RISCOS hpux
mac
hppa hp9000 hp9000s300 hp9000s700 hp9000s800 hp9000s820 ELATE sparcv9
ecmascript js nimrodvm nimffi nimdoc cpp objc
gcc llvmgcc clang lcc bcc dmc wcc vcc tcc pcc ucc icl
boehmgc gcmarkandsweep gcgenerational nogc gcUseBitvectors
endb profiler
executable guiapp consoleapp library dll staticlib
quick
release debug
useWinAnsi useFork useNimRtl useMalloc useRealtimeGC ssl memProfiler
nodejs kwin nimfix
usesysassert usegcassert tinyC useFFI
useStdoutAsStdmsg createNimRtl
booting fulldebug corruption nimsuperops noSignalHandler useGnuReadline
noCaas noDocGen noBusyWaiting nativeStackTrace useNodeIds selftest
reportMissedDeadlines avoidTimeMachine useClone ignoreAllocationSize
debugExecProcesses pcreDll useLipzipSrc
preventDeadlocks UNICODE winUnicode trackGcHeaders posixRealtime
nimStdSetjmp nimRawSetjmp nimSigSetjmp
""".split
proc initDefines*() =
proc initDefines*() =
gSymbols = newStringTable(modeStyleInsensitive)
defineSymbol("nimrod") # 'nimrod' is always defined
# for bootstrapping purposes and old code:
@@ -90,58 +88,3 @@ proc initDefines*() =
defineSymbol("nimalias")
defineSymbol("nimlocks")
defineSymbol("nimnode")
# add platform specific symbols:
for c in low(CPU)..high(CPU):
declareSymbol("cpu" & $CPU[c].bit)
declareSymbol(normalize(EndianToStr[CPU[c].endian]))
declareSymbol(CPU[c].name)
for o in low(platform.OS)..high(platform.OS):
declareSymbol(platform.OS[o].name)
for a in additionalSymbols:
declareSymbol(a)
# -----------------------------------------------------------
case targetCPU
of cpuI386: defineSymbol("x86")
of cpuIa64: defineSymbol("itanium")
of cpuAmd64: defineSymbol("x8664")
else: discard
case targetOS
of osDos:
defineSymbol("msdos")
of osWindows:
defineSymbol("mswindows")
defineSymbol("win32")
of osLinux, osMorphos, osSkyos, osIrix, osPalmos, osQnx, osAtari, osAix,
osHaiku, osVxWorks:
# these are all 'unix-like'
defineSymbol("unix")
defineSymbol("posix")
of osSolaris:
defineSymbol("sunos")
defineSymbol("unix")
defineSymbol("posix")
of osNetbsd, osFreebsd, osOpenbsd:
defineSymbol("unix")
defineSymbol("bsd")
defineSymbol("posix")
of osMacos:
defineSymbol("macintosh")
of osMacosx:
defineSymbol("macintosh")
defineSymbol("unix")
defineSymbol("posix")
else: discard
defineSymbol("cpu" & $CPU[targetCPU].bit)
defineSymbol(normalize(EndianToStr[CPU[targetCPU].endian]))
defineSymbol(CPU[targetCPU].name)
defineSymbol(platform.OS[targetOS].name)
declareSymbol("emulatedthreadvars")
if platform.OS[targetOS].props.contains(ospLacksThreadVars):
defineSymbol("emulatedthreadvars")
case targetOS
of osSolaris, osNetbsd, osFreebsd, osOpenbsd, osMacosx:
defineSymbol("nimRawSetjmp")
else: discard

View File

@@ -15,9 +15,9 @@
import
lists, ropes, os, strutils, osproc, platform, condsyms, options, msgs, crc
type
TSystemCC* = enum
ccNone, ccGcc, ccLLVM_Gcc, ccCLang, ccLcc, ccBcc, ccDmc, ccWcc, ccVcc,
type
TSystemCC* = enum
ccNone, ccGcc, ccLLVM_Gcc, ccCLang, ccLcc, ccBcc, ccDmc, ccWcc, ccVcc,
ccTcc, ccPcc, ccUcc, ccIcl
TInfoCCProp* = enum # properties of the C compiler:
hasSwitchRange, # CC allows ranges in switch statements (GNU C)
@@ -54,7 +54,7 @@ type
props: TInfoCCProps] # properties of the C compiler
# Configuration settings for various compilers.
# 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;
@@ -136,7 +136,7 @@ compiler icl:
result = vcc()
else:
result = gcc()
result.name = "icl"
result.compilerExe = "icl"
result.linkerExe = "icl"
@@ -317,7 +317,7 @@ compiler ucc:
packedPragma: "", # XXX: not supported yet
props: {})
const
const
CC*: array[succ(low(TSystemCC))..high(TSystemCC), TInfoCC] = [
gcc(),
llvmGcc(),
@@ -346,7 +346,7 @@ var
proc libNameTmpl(): string {.inline.} =
result = if targetOS == osWindows: "$1.lib" else: "lib$1.a"
var
var
toLink, toCompile, externalToCompile: TLinkedList
linkOptions: string = ""
compileOptions: string = ""
@@ -355,8 +355,8 @@ var
proc nameToCC*(name: string): TSystemCC =
## Returns the kind of compiler referred to by `name`, or ccNone
## if the name doesn't refer to any known compiler.
for i in countup(succ(ccNone), high(TSystemCC)):
if cmpIgnoreStyle(name, CC[i].name) == 0:
for i in countup(succ(ccNone), high(TSystemCC)):
if cmpIgnoreStyle(name, CC[i].name) == 0:
return i
result = ccNone
@@ -375,8 +375,8 @@ proc getConfigVar(c: TSystemCC, suffix: string): string =
if (platform.hostOS != targetOS or platform.hostCPU != targetCPU) and
optCompileOnly notin gGlobalOptions:
let fullCCname = platform.CPU[targetCPU].name & '.' &
platform.OS[targetOS].name & '.' &
let fullCCname = platform.CPU[targetCPU].name & '.' &
platform.OS[targetOS].name & '.' &
CC[c].name & fullSuffix
result = getConfigVar(fullCCname)
if result.len == 0:
@@ -385,7 +385,7 @@ proc getConfigVar(c: TSystemCC, suffix: string): string =
else:
result = getConfigVar(CC[c].name & fullSuffix)
proc setCC*(ccname: string) =
proc setCC*(ccname: string) =
cCompiler = nameToCC(ccname)
if cCompiler == ccNone: rawMessage(errUnknownCcompiler, ccname)
compileOptions = getConfigVar(cCompiler, ".options.always")
@@ -394,18 +394,18 @@ proc setCC*(ccname: string) =
for i in countup(low(CC), high(CC)): undefSymbol(CC[i].name)
defineSymbol(CC[cCompiler].name)
proc addOpt(dest: var string, src: string) =
proc addOpt(dest: var string, src: string) =
if len(dest) == 0 or dest[len(dest)-1] != ' ': add(dest, " ")
add(dest, src)
proc addLinkOption*(option: string) =
addOpt(linkOptions, option)
proc addCompileOption*(option: string) =
if strutils.find(compileOptions, option, 0) < 0:
proc addCompileOption*(option: string) =
if strutils.find(compileOptions, option, 0) < 0:
addOpt(compileOptions, option)
proc initVars*() =
proc initVars*() =
# we need to define the symbol here, because ``CC`` may have never been set!
for i in countup(low(CC), high(CC)): undefSymbol(CC[i].name)
defineSymbol(CC[cCompiler].name)
@@ -414,10 +414,10 @@ proc initVars*() =
if len(ccompilerpath) == 0:
ccompilerpath = getConfigVar(cCompiler, ".path")
proc completeCFilePath*(cfile: string, createSubDir: bool = true): string =
proc completeCFilePath*(cfile: string, createSubDir: bool = true): string =
result = completeGeneratedFilePath(cfile, createSubDir)
proc toObjFile*(filename: string): string =
proc toObjFile*(filename: string): string =
# Object file for compilation
result = changeFileExt(filename, CC[cCompiler].objExt)
@@ -449,22 +449,22 @@ proc execExternalProgram*(cmd: string, prettyCmd = "") =
if execWithEcho(cmd, prettyCmd) != 0:
rawMessage(errExecutionOfProgramFailed, "")
proc generateScript(projectFile: string, script: Rope) =
proc generateScript(projectFile: string, script: Rope) =
let (dir, name, ext) = splitFile(projectFile)
writeRope(script, dir / addFileExt("compile_" & name,
writeRope(script, dir / addFileExt("compile_" & name,
platform.OS[targetOS].scriptExt))
proc getOptSpeed(c: TSystemCC): string =
proc getOptSpeed(c: TSystemCC): string =
result = getConfigVar(c, ".options.speed")
if result == "":
result = CC[c].optSpeed # use default settings from this file
proc getDebug(c: TSystemCC): string =
proc getDebug(c: TSystemCC): string =
result = getConfigVar(c, ".options.debug")
if result == "":
result = CC[c].debug # use default settings from this file
proc getOptSize(c: TSystemCC): string =
proc getOptSize(c: TSystemCC): string =
result = getConfigVar(c, ".options.size")
if result == "":
result = CC[c].optSize # use default settings from this file
@@ -476,7 +476,7 @@ proc noAbsolutePaths: bool {.inline.} =
# `optGenMapping` is included here for niminst.
result = gGlobalOptions * {optGenScript, optGenMapping} != {}
const
const
specialFileA = 42
specialFileB = 42
@@ -488,7 +488,7 @@ proc add(s: var string, many: openArray[string]) =
proc cFileSpecificOptions(cfilename: string): string =
result = compileOptions
var trunk = splitFile(cfilename).name
if optCDebug in gGlobalOptions:
if optCDebug in gGlobalOptions:
var key = trunk & ".debug"
if existsConfigVar(key): addOpt(result, getConfigVar(key))
else: addOpt(result, getDebug(cCompiler))
@@ -528,17 +528,17 @@ proc getLinkerExe(compiler: TSystemCC): string =
elif gMixedMode and gCmd != cmdCompileToCpp: CC[compiler].cppCompiler
else: compiler.getCompilerExe
proc getCompileCFileCmd*(cfilename: string, isExternal = false): string =
proc getCompileCFileCmd*(cfilename: string, isExternal = false): string =
var c = cCompiler
var options = cFileSpecificOptions(cfilename)
var exe = getConfigVar(c, ".exe")
if exe.len == 0: exe = c.getCompilerExe
if needsExeExt(): 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 not noAbsolutePaths():
# compute include paths:
@@ -551,7 +551,7 @@ proc getCompileCFileCmd*(cfilename: string, isExternal = false): string =
else:
includeCmd = ""
compilePattern = c.getCompilerExe
var cfile = if noAbsolutePaths(): extractFilename(cfilename)
else: cfilename
var objfile = if not isExternal or noAbsolutePaths():
@@ -580,14 +580,14 @@ proc footprint(filename: string): TCrc32 =
extccomp.CC[extccomp.cCompiler].name ><
getCompileCFileCmd(filename, true)
proc externalFileChanged(filename: string): bool =
proc externalFileChanged(filename: string): bool =
if gCmd notin {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToLLVM}:
return false
var crcFile = toGeneratedFile(filename.withPackageName, "crc")
var currentCrc = int(footprint(filename))
var f: File
if open(f, crcFile, fmRead):
if open(f, crcFile, fmRead):
var line = newStringOfCap(40)
if not f.readLine(line): line = "0"
close(f)
@@ -595,7 +595,7 @@ proc externalFileChanged(filename: string): bool =
result = oldCrc != currentCrc
else:
result = true
if result:
if result:
if open(f, crcFile, fmWrite):
f.writeln($currentCrc)
close(f)
@@ -607,22 +607,22 @@ proc addExternalFileToCompile*(filename: string) =
proc compileCFile(list: TLinkedList, script: var Rope, cmds: var TStringSeq,
prettyCmds: var TStringSeq, isExternal: bool) =
var it = PStrEntry(list.head)
while it != nil:
while it != nil:
inc(fileCounter) # call the C compiler for the .c file:
var compileCmd = getCompileCFileCmd(it.data, isExternal)
if optCompileOnly notin gGlobalOptions:
if optCompileOnly notin gGlobalOptions:
add(cmds, compileCmd)
let (dir, name, ext) = splitFile(it.data)
add(prettyCmds, "CC: " & name)
if optGenScript in gGlobalOptions:
if optGenScript in gGlobalOptions:
add(script, compileCmd)
add(script, tnl)
it = PStrEntry(it.next)
proc callCCompiler*(projectfile: string) =
var
var
linkCmd, buildgui, builddll: string
if gGlobalOptions * {optCompileOnly, optGenScript} == {optCompileOnly}:
if gGlobalOptions * {optCompileOnly, optGenScript} == {optCompileOnly}:
return # speed up that call if only compiling and no script shall be
# generated
fileCounter = 0
@@ -634,11 +634,11 @@ proc callCCompiler*(projectfile: string) =
echo prettyCmds[idx]
compileCFile(toCompile, script, cmds, prettyCmds, false)
compileCFile(externalToCompile, script, cmds, prettyCmds, true)
if optCompileOnly notin gGlobalOptions:
if optCompileOnly notin gGlobalOptions:
if gNumberOfProcessors == 0: gNumberOfProcessors = countProcessors()
var res = 0
if gNumberOfProcessors <= 1:
for i in countup(0, high(cmds)):
if gNumberOfProcessors <= 1:
for i in countup(0, high(cmds)):
res = execWithEcho(cmds[i])
if res != 0: rawMessage(errExecutionOfProgramFailed, [])
elif optListCmd in gGlobalOptions or gVerbosity > 1:
@@ -685,13 +685,13 @@ proc callCCompiler*(projectfile: string) =
else:
exefile = splitFile(projectfile).name & platform.OS[targetOS].exeExt
builddll = ""
if options.outFile.len > 0:
if options.outFile.len > 0:
exefile = options.outFile.expandTilde
if not noAbsolutePaths():
if not exefile.isAbsolute():
exefile = joinPath(splitFile(projectfile).dir, exefile)
exefile = quoteShell(exefile)
let linkOptions = getLinkOptions() & " " &
let linkOptions = getLinkOptions() & " " &
getConfigVar(cCompiler, ".options.linker")
linkCmd = quoteShell(linkCmd % ["builddll", builddll,
"buildgui", buildgui, "options", linkOptions, "objfiles", objfiles,
@@ -714,26 +714,26 @@ proc callCCompiler*(projectfile: string) =
add(script, tnl)
generateScript(projectfile, script)
proc genMappingFiles(list: TLinkedList): Rope =
proc genMappingFiles(list: TLinkedList): Rope =
var it = PStrEntry(list.head)
while it != nil:
while it != nil:
addf(result, "--file:r\"$1\"$N", [rope(it.data)])
it = PStrEntry(it.next)
proc writeMapping*(gSymbolMapping: Rope) =
if optGenMapping notin gGlobalOptions: return
proc writeMapping*(gSymbolMapping: Rope) =
if optGenMapping notin gGlobalOptions: return
var code = rope("[C_Files]\n")
add(code, genMappingFiles(toCompile))
add(code, genMappingFiles(externalToCompile))
add(code, "\n[C_Compiler]\nFlags=")
add(code, strutils.escape(getCompileOptions()))
add(code, "\n[Linker]\nFlags=")
add(code, strutils.escape(getLinkOptions() & " " &
add(code, strutils.escape(getLinkOptions() & " " &
getConfigVar(cCompiler, ".options.linker")))
add(code, "\n[Environment]\nlibpath=")
add(code, strutils.escape(libpath))
addf(code, "\n[Symbols]$n$1", [gSymbolMapping])
writeRope(code, joinPath(gProjectPath, "mapping.txt"))