.compile pragma supports patterns and actions
This commit is contained in:
parent
0e16d43196
commit
03a1c3b077
4 changed files with 141 additions and 102 deletions
|
|
@ -849,15 +849,15 @@ proc addIntTypes(result: var Rope) {.inline.} =
|
||||||
addf(result, "#define NIM_INTBITS $1" & tnl, [
|
addf(result, "#define NIM_INTBITS $1" & tnl, [
|
||||||
platform.CPU[targetCPU].intSize.rope])
|
platform.CPU[targetCPU].intSize.rope])
|
||||||
|
|
||||||
proc getCopyright(cfile: string): Rope =
|
proc getCopyright(cfile: Cfile): Rope =
|
||||||
if optCompileOnly in gGlobalOptions:
|
if optCompileOnly in gGlobalOptions:
|
||||||
result = ("/* Generated by Nim Compiler v$1 */$N" &
|
result = ("/* Generated by Nim Compiler v$1 */$N" &
|
||||||
"/* (c) 2017 Andreas Rumpf */$N" &
|
"/* (c) " & CompileDate.substr(0, 3) & " Andreas Rumpf */$N" &
|
||||||
"/* The generated code is subject to the original license. */$N") %
|
"/* The generated code is subject to the original license. */$N") %
|
||||||
[rope(VersionAsString)]
|
[rope(VersionAsString)]
|
||||||
else:
|
else:
|
||||||
result = ("/* Generated by Nim Compiler v$1 */$N" &
|
result = ("/* Generated by Nim Compiler v$1 */$N" &
|
||||||
"/* (c) 2017 Andreas Rumpf */$N" &
|
"/* (c) " & CompileDate.substr(0, 3) & " Andreas Rumpf */$N" &
|
||||||
"/* The generated code is subject to the original license. */$N" &
|
"/* The generated code is subject to the original license. */$N" &
|
||||||
"/* Compiled for: $2, $3, $4 */$N" &
|
"/* Compiled for: $2, $3, $4 */$N" &
|
||||||
"/* Command for C compiler:$n $5 */$N") %
|
"/* Command for C compiler:$n $5 */$N") %
|
||||||
|
|
@ -867,7 +867,7 @@ proc getCopyright(cfile: string): Rope =
|
||||||
rope(extccomp.CC[extccomp.cCompiler].name),
|
rope(extccomp.CC[extccomp.cCompiler].name),
|
||||||
rope(getCompileCFileCmd(cfile))]
|
rope(getCompileCFileCmd(cfile))]
|
||||||
|
|
||||||
proc getFileHeader(cfile: string): Rope =
|
proc getFileHeader(cfile: Cfile): Rope =
|
||||||
result = getCopyright(cfile)
|
result = getCopyright(cfile)
|
||||||
addIntTypes(result)
|
addIntTypes(result)
|
||||||
|
|
||||||
|
|
@ -1096,7 +1096,7 @@ proc genInitCode(m: BModule) =
|
||||||
[(i.ord - '0'.ord).rope, el]
|
[(i.ord - '0'.ord).rope, el]
|
||||||
add(m.s[cfsInitProc], ex)
|
add(m.s[cfsInitProc], ex)
|
||||||
|
|
||||||
proc genModule(m: BModule, cfile: string): Rope =
|
proc genModule(m: BModule, cfile: Cfile): Rope =
|
||||||
result = getFileHeader(cfile)
|
result = getFileHeader(cfile)
|
||||||
result.add(genMergeInfo(m))
|
result.add(genMergeInfo(m))
|
||||||
|
|
||||||
|
|
@ -1227,7 +1227,11 @@ proc myOpen(graph: ModuleGraph; module: PSym; cache: IdentCache): PPassContext =
|
||||||
incl g.generatedHeader.flags, isHeaderFile
|
incl g.generatedHeader.flags, isHeaderFile
|
||||||
|
|
||||||
proc writeHeader(m: BModule) =
|
proc writeHeader(m: BModule) =
|
||||||
var result = getCopyright(m.filename)
|
var result = ("/* Generated by Nim Compiler v$1 */$N" &
|
||||||
|
"/* (c) " & CompileDate.substr(0, 3) & " Andreas Rumpf */$N" &
|
||||||
|
"/* The generated code is subject to the original license. */$N") %
|
||||||
|
[rope(VersionAsString)]
|
||||||
|
|
||||||
var guard = "__$1__" % [m.filename.splitFile.name.rope]
|
var guard = "__$1__" % [m.filename.splitFile.name.rope]
|
||||||
result.addf("#ifndef $1$n#define $1$n", [guard])
|
result.addf("#ifndef $1$n#define $1$n", [guard])
|
||||||
addIntTypes(result)
|
addIntTypes(result)
|
||||||
|
|
@ -1281,20 +1285,19 @@ proc finishModule(m: BModule) =
|
||||||
dec(m.g.forwardedProcsCounter, i)
|
dec(m.g.forwardedProcsCounter, i)
|
||||||
setLen(m.forwardedProcs, 0)
|
setLen(m.forwardedProcs, 0)
|
||||||
|
|
||||||
proc shouldRecompile(code: Rope, cfile: string): bool =
|
proc shouldRecompile(code: Rope, cfile: Cfile): bool =
|
||||||
result = true
|
result = true
|
||||||
if optForceFullMake notin gGlobalOptions:
|
if optForceFullMake notin gGlobalOptions:
|
||||||
var objFile = toObjFile(cfile)
|
if not equalsFile(code, cfile.cname):
|
||||||
|
|
||||||
if not equalsFile(code, cfile):
|
|
||||||
if isDefined("nimdiff"):
|
if isDefined("nimdiff"):
|
||||||
copyFile(cfile, cfile & ".backup")
|
copyFile(cfile.cname, cfile.cname & ".backup")
|
||||||
echo "diff ", cfile, ".backup ", cfile
|
echo "diff ", cfile.cname, ".backup ", cfile.cname
|
||||||
writeRope(code, cfile)
|
writeRope(code, cfile.cname)
|
||||||
return
|
return
|
||||||
if existsFile(objFile) and os.fileNewer(objFile, cfile): result = false
|
if existsFile(cfile.obj) and os.fileNewer(cfile.obj, cfile.cname):
|
||||||
|
result = false
|
||||||
else:
|
else:
|
||||||
writeRope(code, cfile)
|
writeRope(code, cfile.cname)
|
||||||
|
|
||||||
# We need 2 different logics here: pending modules (including
|
# We need 2 different logics here: pending modules (including
|
||||||
# 'nim__dat') may require file merging for the combination of dead code
|
# 'nim__dat') may require file merging for the combination of dead code
|
||||||
|
|
@ -1304,8 +1307,7 @@ proc shouldRecompile(code: Rope, cfile: string): bool =
|
||||||
|
|
||||||
proc writeModule(m: BModule, pending: bool) =
|
proc writeModule(m: BModule, pending: bool) =
|
||||||
# generate code for the init statements of the module:
|
# generate code for the init statements of the module:
|
||||||
var cfile = getCFile(m)
|
let cfile = getCFile(m)
|
||||||
var cfilenoext = changeFileExt(cfile, "")
|
|
||||||
|
|
||||||
if not m.fromCache or optForceFullMake in gGlobalOptions:
|
if not m.fromCache or optForceFullMake in gGlobalOptions:
|
||||||
genInitCode(m)
|
genInitCode(m)
|
||||||
|
|
@ -1315,42 +1317,45 @@ proc writeModule(m: BModule, pending: bool) =
|
||||||
add(m.s[cfsProcHeaders], m.g.mainModProcs)
|
add(m.s[cfsProcHeaders], m.g.mainModProcs)
|
||||||
generateThreadVarsSize(m)
|
generateThreadVarsSize(m)
|
||||||
|
|
||||||
var code = genModule(m, cfile)
|
var cf = Cfile(cname: cfile, obj: completeCFilePath(toObjFile(cfile)), flags: {})
|
||||||
|
var code = genModule(m, cf)
|
||||||
when hasTinyCBackend:
|
when hasTinyCBackend:
|
||||||
if gCmd == cmdRun:
|
if gCmd == cmdRun:
|
||||||
tccgen.compileCCode($code)
|
tccgen.compileCCode($code)
|
||||||
return
|
return
|
||||||
|
|
||||||
if shouldRecompile(code, cfile):
|
if not shouldRecompile(code, cf): cf.flags = {CfileFlag.Cached}
|
||||||
addFileToCompile(cfile)
|
addFileToCompile(cf)
|
||||||
elif pending and mergeRequired(m) and sfMainModule notin m.module.flags:
|
elif pending and mergeRequired(m) and sfMainModule notin m.module.flags:
|
||||||
|
let cf = Cfile(cname: cfile, obj: completeCFilePath(toObjFile(cfile)), flags: {})
|
||||||
mergeFiles(cfile, m)
|
mergeFiles(cfile, m)
|
||||||
genInitCode(m)
|
genInitCode(m)
|
||||||
finishTypeDescriptions(m)
|
finishTypeDescriptions(m)
|
||||||
var code = genModule(m, cfile)
|
var code = genModule(m, cf)
|
||||||
writeRope(code, cfile)
|
writeRope(code, cfile)
|
||||||
addFileToCompile(cfile)
|
addFileToCompile(cf)
|
||||||
elif not existsFile(toObjFile(cfilenoext)):
|
else:
|
||||||
# Consider: first compilation compiles ``system.nim`` and produces
|
# Consider: first compilation compiles ``system.nim`` and produces
|
||||||
# ``system.c`` but then compilation fails due to an error. This means
|
# ``system.c`` but then compilation fails due to an error. This means
|
||||||
# that ``system.o`` is missing, so we need to call the C compiler for it:
|
# that ``system.o`` is missing, so we need to call the C compiler for it:
|
||||||
addFileToCompile(cfile)
|
var cf = Cfile(cname: cfile, obj: completeCFilePath(toObjFile(cfile)), flags: {})
|
||||||
|
if not existsFile(cf.obj): cf.flags = {CfileFlag.Cached}
|
||||||
addFileToLink(cfilenoext)
|
addFileToCompile(cf)
|
||||||
|
|
||||||
proc updateCachedModule(m: BModule) =
|
proc updateCachedModule(m: BModule) =
|
||||||
let cfile = getCFile(m)
|
let cfile = getCFile(m)
|
||||||
let cfilenoext = changeFileExt(cfile, "")
|
var cf = Cfile(cname: cfile, obj: completeCFilePath(toObjFile(cfile)), flags: {})
|
||||||
|
|
||||||
if mergeRequired(m) and sfMainModule notin m.module.flags:
|
if mergeRequired(m) and sfMainModule notin m.module.flags:
|
||||||
mergeFiles(cfile, m)
|
mergeFiles(cfile, m)
|
||||||
genInitCode(m)
|
genInitCode(m)
|
||||||
finishTypeDescriptions(m)
|
finishTypeDescriptions(m)
|
||||||
var code = genModule(m, cfile)
|
|
||||||
writeRope(code, cfile)
|
|
||||||
addFileToCompile(cfile)
|
|
||||||
|
|
||||||
addFileToLink(cfilenoext)
|
var code = genModule(m, cf)
|
||||||
|
writeRope(code, cfile)
|
||||||
|
else:
|
||||||
|
cf.flags = {CfileFlag.Cached}
|
||||||
|
addFileToCompile(cf)
|
||||||
|
|
||||||
proc myClose(b: PPassContext, n: PNode): PNode =
|
proc myClose(b: PPassContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
|
|
|
||||||
|
|
@ -193,9 +193,7 @@ proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass,
|
||||||
proc processCompile(filename: string) =
|
proc processCompile(filename: string) =
|
||||||
var found = findFile(filename)
|
var found = findFile(filename)
|
||||||
if found == "": found = filename
|
if found == "": found = filename
|
||||||
var trunc = changeFileExt(found, "")
|
|
||||||
extccomp.addExternalFileToCompile(found)
|
extccomp.addExternalFileToCompile(found)
|
||||||
extccomp.addFileToLink(completeCFilePath(trunc, false))
|
|
||||||
|
|
||||||
proc testCompileOptionArg*(switch, arg: string, info: TLineInfo): bool =
|
proc testCompileOptionArg*(switch, arg: string, info: TLineInfo): bool =
|
||||||
case switch.normalize
|
case switch.normalize
|
||||||
|
|
@ -370,7 +368,7 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
|
||||||
if pass in {passCmd2, passPP}: processCompile(arg)
|
if pass in {passCmd2, passPP}: processCompile(arg)
|
||||||
of "link":
|
of "link":
|
||||||
expectArg(switch, arg, pass, info)
|
expectArg(switch, arg, pass, info)
|
||||||
if pass in {passCmd2, passPP}: addFileToLink(arg)
|
if pass in {passCmd2, passPP}: addExternalFileToLink(arg)
|
||||||
of "debuginfo":
|
of "debuginfo":
|
||||||
expectNoArg(switch, arg, pass, info)
|
expectNoArg(switch, arg, pass, info)
|
||||||
incl(gGlobalOptions, optCDebug)
|
incl(gGlobalOptions, optCDebug)
|
||||||
|
|
|
||||||
|
|
@ -379,11 +379,23 @@ const
|
||||||
proc libNameTmpl(): string {.inline.} =
|
proc libNameTmpl(): string {.inline.} =
|
||||||
result = if targetOS == osWindows: "$1.lib" else: "lib$1.a"
|
result = if targetOS == osWindows: "$1.lib" else: "lib$1.a"
|
||||||
|
|
||||||
|
type
|
||||||
|
CfileFlag* {.pure.} = enum
|
||||||
|
Cached, ## no need to recompile this time
|
||||||
|
External ## file was introduced via .compile pragma
|
||||||
|
|
||||||
|
Cfile* = object
|
||||||
|
cname*, obj*: string
|
||||||
|
flags*: set[CFileFlag]
|
||||||
|
CfileList = seq[Cfile]
|
||||||
|
|
||||||
var
|
var
|
||||||
toLink, toCompile, externalToCompile: TLinkedList
|
externalToLink: TLinkedList # files to link in addition to the file
|
||||||
|
# we compiled
|
||||||
linkOptions: string = ""
|
linkOptions: string = ""
|
||||||
compileOptions: string = ""
|
compileOptions: string = ""
|
||||||
ccompilerpath: string = ""
|
ccompilerpath: string = ""
|
||||||
|
toCompile: CfileList = @[]
|
||||||
|
|
||||||
proc nameToCC*(name: string): TSystemCC =
|
proc nameToCC*(name: string): TSystemCC =
|
||||||
## Returns the kind of compiler referred to by `name`, or ccNone
|
## Returns the kind of compiler referred to by `name`, or ccNone
|
||||||
|
|
@ -452,22 +464,24 @@ proc completeCFilePath*(cfile: string, createSubDir: bool = true): string =
|
||||||
|
|
||||||
proc toObjFile*(filename: string): string =
|
proc toObjFile*(filename: string): string =
|
||||||
# Object file for compilation
|
# Object file for compilation
|
||||||
|
#if filename.endsWith(".cpp"):
|
||||||
|
# result = changeFileExt(filename, "cpp." & CC[cCompiler].objExt)
|
||||||
|
#else:
|
||||||
result = changeFileExt(filename, CC[cCompiler].objExt)
|
result = changeFileExt(filename, CC[cCompiler].objExt)
|
||||||
|
|
||||||
proc addFileToCompile*(filename: string) =
|
proc addFileToCompile*(cf: Cfile) =
|
||||||
appendStr(toCompile, filename)
|
toCompile.add(cf)
|
||||||
|
|
||||||
proc resetCompilationLists* =
|
proc resetCompilationLists* =
|
||||||
initLinkedList(toCompile)
|
toCompile.setLen 0
|
||||||
## XXX: we must associate these with their originating module
|
## XXX: we must associate these with their originating module
|
||||||
# when the module is loaded/unloaded it adds/removes its items
|
# when the module is loaded/unloaded it adds/removes its items
|
||||||
# That's because we still need to hash check the external files
|
# That's because we still need to hash check the external files
|
||||||
# Maybe we can do that in checkDep on the other hand?
|
# Maybe we can do that in checkDep on the other hand?
|
||||||
initLinkedList(externalToCompile)
|
initLinkedList(externalToLink)
|
||||||
initLinkedList(toLink)
|
|
||||||
|
|
||||||
proc addFileToLink*(filename: string) =
|
proc addExternalFileToLink*(filename: string) =
|
||||||
prependStr(toLink, filename)
|
prependStr(externalToLink, filename)
|
||||||
# BUGFIX: was ``appendStr``
|
# BUGFIX: was ``appendStr``
|
||||||
|
|
||||||
proc execWithEcho(cmd: string, msg = hintExecuting): int =
|
proc execWithEcho(cmd: string, msg = hintExecuting): int =
|
||||||
|
|
@ -505,8 +519,6 @@ proc noAbsolutePaths: bool {.inline.} =
|
||||||
# `optGenMapping` is included here for niminst.
|
# `optGenMapping` is included here for niminst.
|
||||||
result = gGlobalOptions * {optGenScript, optGenMapping} != {}
|
result = gGlobalOptions * {optGenScript, optGenMapping} != {}
|
||||||
|
|
||||||
var fileCounter: int
|
|
||||||
|
|
||||||
proc add(s: var string, many: openArray[string]) =
|
proc add(s: var string, many: openArray[string]) =
|
||||||
s.add many.join
|
s.add many.join
|
||||||
|
|
||||||
|
|
@ -553,9 +565,9 @@ proc getLinkerExe(compiler: TSystemCC): string =
|
||||||
elif gMixedMode and gCmd != cmdCompileToCpp: CC[compiler].cppCompiler
|
elif gMixedMode and gCmd != cmdCompileToCpp: CC[compiler].cppCompiler
|
||||||
else: compiler.getCompilerExe
|
else: compiler.getCompilerExe
|
||||||
|
|
||||||
proc getCompileCFileCmd*(cfilename: string, isExternal = false): string =
|
proc getCompileCFileCmd*(cfile: Cfile): string =
|
||||||
var c = cCompiler
|
var c = cCompiler
|
||||||
if cfilename.endswith(".asm"):
|
if cfile.cname.endswith(".asm"):
|
||||||
var customAssembler = getConfigVar("assembler")
|
var customAssembler = getConfigVar("assembler")
|
||||||
if customAssembler.len > 0:
|
if customAssembler.len > 0:
|
||||||
c = nameToCC(customAssembler)
|
c = nameToCC(customAssembler)
|
||||||
|
|
@ -570,7 +582,7 @@ proc getCompileCFileCmd*(cfilename: string, isExternal = false): string =
|
||||||
elif c notin cValidAssemblers:
|
elif c notin cValidAssemblers:
|
||||||
rawMessage(errExternalAssemblerNotValid, customAssembler)
|
rawMessage(errExternalAssemblerNotValid, customAssembler)
|
||||||
|
|
||||||
var options = cFileSpecificOptions(cfilename)
|
var options = cFileSpecificOptions(cfile.cname)
|
||||||
var exe = getConfigVar(c, ".exe")
|
var exe = getConfigVar(c, ".exe")
|
||||||
if exe.len == 0: exe = c.getCompilerExe
|
if exe.len == 0: exe = c.getCompilerExe
|
||||||
|
|
||||||
|
|
@ -592,40 +604,48 @@ proc getCompileCFileCmd*(cfilename: string, isExternal = false): string =
|
||||||
includeCmd = ""
|
includeCmd = ""
|
||||||
compilePattern = c.getCompilerExe
|
compilePattern = c.getCompilerExe
|
||||||
|
|
||||||
var cfile = if noAbsolutePaths(): extractFilename(cfilename)
|
var cf = if noAbsolutePaths(): extractFilename(cfile.cname)
|
||||||
else: cfilename
|
else: cfile.cname
|
||||||
var objfile = if not isExternal or noAbsolutePaths():
|
|
||||||
toObjFile(cfile)
|
var objfile =
|
||||||
else:
|
if cfile.obj.len == 0:
|
||||||
completeCFilePath(toObjFile(cfile))
|
if not cfile.flags.contains(CfileFlag.External) or noAbsolutePaths():
|
||||||
|
toObjFile(cf)
|
||||||
|
else:
|
||||||
|
completeCFilePath(toObjFile(cf))
|
||||||
|
elif noAbsolutePaths():
|
||||||
|
extractFilename(cfile.obj)
|
||||||
|
else:
|
||||||
|
cfile.obj
|
||||||
|
|
||||||
objfile = quoteShell(objfile)
|
objfile = quoteShell(objfile)
|
||||||
cfile = quoteShell(cfile)
|
cf = quoteShell(cf)
|
||||||
result = quoteShell(compilePattern % [
|
result = quoteShell(compilePattern % [
|
||||||
"file", cfile, "objfile", objfile, "options", options,
|
"file", cf, "objfile", objfile, "options", options,
|
||||||
"include", includeCmd, "nim", getPrefixDir(),
|
"include", includeCmd, "nim", getPrefixDir(),
|
||||||
"nim", getPrefixDir(), "lib", libpath])
|
"nim", getPrefixDir(), "lib", libpath])
|
||||||
add(result, ' ')
|
add(result, ' ')
|
||||||
addf(result, CC[c].compileTmpl, [
|
addf(result, CC[c].compileTmpl, [
|
||||||
"file", cfile, "objfile", objfile,
|
"file", cf, "objfile", objfile,
|
||||||
"options", options, "include", includeCmd,
|
"options", options, "include", includeCmd,
|
||||||
"nim", quoteShell(getPrefixDir()),
|
"nim", quoteShell(getPrefixDir()),
|
||||||
"nim", quoteShell(getPrefixDir()),
|
"nim", quoteShell(getPrefixDir()),
|
||||||
"lib", quoteShell(libpath)])
|
"lib", quoteShell(libpath)])
|
||||||
|
|
||||||
proc footprint(filename: string): SecureHash =
|
proc footprint(cfile: Cfile): SecureHash =
|
||||||
result = secureHash(
|
result = secureHash(
|
||||||
$secureHashFile(filename) &
|
$secureHashFile(cfile.cname) &
|
||||||
platform.OS[targetOS].name &
|
platform.OS[targetOS].name &
|
||||||
platform.CPU[targetCPU].name &
|
platform.CPU[targetCPU].name &
|
||||||
extccomp.CC[extccomp.cCompiler].name &
|
extccomp.CC[extccomp.cCompiler].name &
|
||||||
getCompileCFileCmd(filename, true))
|
getCompileCFileCmd(cfile))
|
||||||
|
|
||||||
proc externalFileChanged(filename: string): bool =
|
proc externalFileChanged(cfile: Cfile): bool =
|
||||||
if gCmd notin {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToLLVM}:
|
if gCmd notin {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToLLVM}:
|
||||||
return false
|
return false
|
||||||
|
|
||||||
var hashFile = toGeneratedFile(filename.withPackageName, "sha1")
|
var hashFile = toGeneratedFile(cfile.cname.withPackageName, "sha1")
|
||||||
var currentHash = footprint(filename)
|
var currentHash = footprint(cfile)
|
||||||
var f: File
|
var f: File
|
||||||
if open(f, hashFile, fmRead):
|
if open(f, hashFile, fmRead):
|
||||||
let oldHash = parseSecureHash(f.readLine())
|
let oldHash = parseSecureHash(f.readLine())
|
||||||
|
|
@ -639,23 +659,29 @@ proc externalFileChanged(filename: string): bool =
|
||||||
close(f)
|
close(f)
|
||||||
|
|
||||||
proc addExternalFileToCompile*(filename: string) =
|
proc addExternalFileToCompile*(filename: string) =
|
||||||
if optForceFullMake in gGlobalOptions or externalFileChanged(filename):
|
let c = Cfile(cname: filename,
|
||||||
appendStr(externalToCompile, filename)
|
obj: toObjFile(completeCFilePath(changeFileExt(filename, ""), false)),
|
||||||
|
flags: {CfileFlag.External})
|
||||||
|
if optForceFullMake in gGlobalOptions or externalFileChanged(c):
|
||||||
|
toCompile.add(c)
|
||||||
|
|
||||||
proc compileCFile(list: TLinkedList, script: var Rope, cmds: var TStringSeq,
|
proc addExternalFileToCompile*(c: Cfile) =
|
||||||
prettyCmds: var TStringSeq, isExternal: bool) =
|
if optForceFullMake in gGlobalOptions or externalFileChanged(c):
|
||||||
var it = PStrEntry(list.head)
|
toCompile.add(c)
|
||||||
while it != nil:
|
|
||||||
inc(fileCounter) # call the C compiler for the .c file:
|
proc compileCFile(list: CFileList, script: var Rope, cmds: var TStringSeq,
|
||||||
var compileCmd = getCompileCFileCmd(it.data, isExternal)
|
prettyCmds: var TStringSeq) =
|
||||||
|
for it in list:
|
||||||
|
# call the C compiler for the .c file:
|
||||||
|
if it.flags.contains(CfileFlag.Cached): continue
|
||||||
|
var compileCmd = getCompileCFileCmd(it)
|
||||||
if optCompileOnly notin gGlobalOptions:
|
if optCompileOnly notin gGlobalOptions:
|
||||||
add(cmds, compileCmd)
|
add(cmds, compileCmd)
|
||||||
let (dir, name, ext) = splitFile(it.data)
|
let (_, name, _) = splitFile(it.cname)
|
||||||
add(prettyCmds, "CC: " & name)
|
add(prettyCmds, "CC: " & name)
|
||||||
if optGenScript in gGlobalOptions:
|
if optGenScript in gGlobalOptions:
|
||||||
add(script, compileCmd)
|
add(script, compileCmd)
|
||||||
add(script, tnl)
|
add(script, tnl)
|
||||||
it = PStrEntry(it.next)
|
|
||||||
|
|
||||||
proc getLinkCmd(projectfile, objfiles: string): string =
|
proc getLinkCmd(projectfile, objfiles: string): string =
|
||||||
if optGenStaticLib in gGlobalOptions:
|
if optGenStaticLib in gGlobalOptions:
|
||||||
|
|
@ -712,7 +738,6 @@ proc callCCompiler*(projectfile: string) =
|
||||||
if gGlobalOptions * {optCompileOnly, optGenScript} == {optCompileOnly}:
|
if gGlobalOptions * {optCompileOnly, optGenScript} == {optCompileOnly}:
|
||||||
return # speed up that call if only compiling and no script shall be
|
return # speed up that call if only compiling and no script shall be
|
||||||
# generated
|
# generated
|
||||||
fileCounter = 0
|
|
||||||
#var c = cCompiler
|
#var c = cCompiler
|
||||||
var script: Rope = nil
|
var script: Rope = nil
|
||||||
var cmds: TStringSeq = @[]
|
var cmds: TStringSeq = @[]
|
||||||
|
|
@ -725,8 +750,7 @@ proc callCCompiler*(projectfile: string) =
|
||||||
rawMessage(errGenerated, "execution of an external compiler program '" &
|
rawMessage(errGenerated, "execution of an external compiler program '" &
|
||||||
cmds[idx] & "' failed with exit code: " & $exitCode & "\n\n" &
|
cmds[idx] & "' failed with exit code: " & $exitCode & "\n\n" &
|
||||||
p.outputStream.readAll.strip)
|
p.outputStream.readAll.strip)
|
||||||
compileCFile(toCompile, script, cmds, prettyCmds, false)
|
compileCFile(toCompile, script, cmds, prettyCmds)
|
||||||
compileCFile(externalToCompile, script, cmds, prettyCmds, true)
|
|
||||||
if optCompileOnly notin gGlobalOptions:
|
if optCompileOnly notin gGlobalOptions:
|
||||||
if gNumberOfProcessors == 0: gNumberOfProcessors = countProcessors()
|
if gNumberOfProcessors == 0: gNumberOfProcessors = countProcessors()
|
||||||
var res = 0
|
var res = 0
|
||||||
|
|
@ -748,7 +772,7 @@ proc callCCompiler*(projectfile: string) =
|
||||||
rawMessage(errExecutionOfProgramFailed, cmds.join())
|
rawMessage(errExecutionOfProgramFailed, cmds.join())
|
||||||
if optNoLinking notin gGlobalOptions:
|
if optNoLinking notin gGlobalOptions:
|
||||||
# call the linker:
|
# call the linker:
|
||||||
var it = PStrEntry(toLink.head)
|
var it = PStrEntry(externalToLink.head)
|
||||||
var objfiles = ""
|
var objfiles = ""
|
||||||
while it != nil:
|
while it != nil:
|
||||||
let objFile = if noAbsolutePaths(): it.data.extractFilename else: it.data
|
let objFile = if noAbsolutePaths(): it.data.extractFilename else: it.data
|
||||||
|
|
@ -756,6 +780,9 @@ proc callCCompiler*(projectfile: string) =
|
||||||
add(objfiles, quoteShell(
|
add(objfiles, quoteShell(
|
||||||
addFileExt(objFile, CC[cCompiler].objExt)))
|
addFileExt(objFile, CC[cCompiler].objExt)))
|
||||||
it = PStrEntry(it.next)
|
it = PStrEntry(it.next)
|
||||||
|
for x in toCompile:
|
||||||
|
add(objfiles, ' ')
|
||||||
|
add(objfiles, x.obj)
|
||||||
|
|
||||||
linkCmd = getLinkCmd(projectfile, objfiles)
|
linkCmd = getLinkCmd(projectfile, objfiles)
|
||||||
if optCompileOnly notin gGlobalOptions:
|
if optCompileOnly notin gGlobalOptions:
|
||||||
|
|
@ -780,16 +807,17 @@ proc writeJsonBuildInstructions*(projectfile: string) =
|
||||||
else:
|
else:
|
||||||
f.write escapeJson(x)
|
f.write escapeJson(x)
|
||||||
|
|
||||||
proc cfiles(f: File; buf: var string; list: TLinkedList, isExternal: bool) =
|
proc cfiles(f: File; buf: var string; list: CfileList, isExternal: bool) =
|
||||||
var it = PStrEntry(list.head)
|
var i = 0
|
||||||
while it != nil:
|
for it in list:
|
||||||
let compileCmd = getCompileCFileCmd(it.data, isExternal)
|
if CfileFlag.Cached in it.flags: continue
|
||||||
|
let compileCmd = getCompileCFileCmd(it)
|
||||||
lit "["
|
lit "["
|
||||||
str it.data
|
str it.cname
|
||||||
lit ", "
|
lit ", "
|
||||||
str compileCmd
|
str compileCmd
|
||||||
it = PStrEntry(it.next)
|
inc i
|
||||||
if it == nil:
|
if i == list.len:
|
||||||
lit "]\L"
|
lit "]\L"
|
||||||
else:
|
else:
|
||||||
lit "],\L"
|
lit "],\L"
|
||||||
|
|
@ -816,28 +844,24 @@ proc writeJsonBuildInstructions*(projectfile: string) =
|
||||||
if open(f, jsonFile, fmWrite):
|
if open(f, jsonFile, fmWrite):
|
||||||
lit "{\"compile\":[\L"
|
lit "{\"compile\":[\L"
|
||||||
cfiles(f, buf, toCompile, false)
|
cfiles(f, buf, toCompile, false)
|
||||||
lit "],\L\"extcompile\":[\L"
|
|
||||||
cfiles(f, buf, externalToCompile, true)
|
|
||||||
lit "],\L\"link\":[\L"
|
lit "],\L\"link\":[\L"
|
||||||
var objfiles = ""
|
var objfiles = ""
|
||||||
linkfiles(f, buf, objfiles, toLink)
|
# XXX add every file here that is to link
|
||||||
|
linkfiles(f, buf, objfiles, externalToLink)
|
||||||
|
|
||||||
lit "],\L\"linkcmd\": "
|
lit "],\L\"linkcmd\": "
|
||||||
str getLinkCmd(projectfile, objfiles)
|
str getLinkCmd(projectfile, objfiles)
|
||||||
lit "\L}\L"
|
lit "\L}\L"
|
||||||
close(f)
|
close(f)
|
||||||
|
|
||||||
proc genMappingFiles(list: TLinkedList): Rope =
|
proc genMappingFiles(list: CFileList): Rope =
|
||||||
var it = PStrEntry(list.head)
|
for it in list:
|
||||||
while it != nil:
|
addf(result, "--file:r\"$1\"$N", [rope(it.cname)])
|
||||||
addf(result, "--file:r\"$1\"$N", [rope(it.data)])
|
|
||||||
it = PStrEntry(it.next)
|
|
||||||
|
|
||||||
proc writeMapping*(gSymbolMapping: Rope) =
|
proc writeMapping*(gSymbolMapping: Rope) =
|
||||||
if optGenMapping notin gGlobalOptions: return
|
if optGenMapping notin gGlobalOptions: return
|
||||||
var code = rope("[C_Files]\n")
|
var code = rope("[C_Files]\n")
|
||||||
add(code, genMappingFiles(toCompile))
|
add(code, genMappingFiles(toCompile))
|
||||||
add(code, genMappingFiles(externalToCompile))
|
|
||||||
add(code, "\n[C_Compiler]\nFlags=")
|
add(code, "\n[C_Compiler]\nFlags=")
|
||||||
add(code, strutils.escape(getCompileOptions()))
|
add(code, strutils.escape(getCompileOptions()))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -402,29 +402,41 @@ proc relativeFile(c: PContext; n: PNode; ext=""): string =
|
||||||
if result.len == 0: result = s
|
if result.len == 0: result = s
|
||||||
|
|
||||||
proc processCompile(c: PContext, n: PNode) =
|
proc processCompile(c: PContext, n: PNode) =
|
||||||
var s = expectStrLit(c, n)
|
|
||||||
var found = parentDir(n.info.toFullPath) / s
|
proc getStrLit(c: PContext, n: PNode; i: int): string =
|
||||||
if '*' in found:
|
n.sons[i] = c.semConstExpr(c, n.sons[i])
|
||||||
|
case n.sons[i].kind
|
||||||
|
of nkStrLit, nkRStrLit, nkTripleStrLit:
|
||||||
|
shallowCopy(result, n.sons[i].strVal)
|
||||||
|
else:
|
||||||
|
localError(n.info, errStringLiteralExpected)
|
||||||
|
result = ""
|
||||||
|
|
||||||
|
let it = if n.kind == nkExprColonExpr: n.sons[1] else: n
|
||||||
|
if it.kind == nkPar and it.len == 2:
|
||||||
|
let s = getStrLit(c, it, 0)
|
||||||
|
let dest = getStrLit(c, it, 1)
|
||||||
|
var found = parentDir(n.info.toFullPath) / s
|
||||||
for f in os.walkFiles(found):
|
for f in os.walkFiles(found):
|
||||||
let trunc = f.changeFileExt("")
|
let nameOnly = extractFilename(f)
|
||||||
extccomp.addExternalFileToCompile(f)
|
extccomp.addExternalFileToCompile(Cfile(cname: f,
|
||||||
extccomp.addFileToLink(completeCFilePath(trunc, false))
|
obj: dest % nameOnly, flags: {CfileFlag.External}))
|
||||||
else:
|
else:
|
||||||
|
let s = expectStrLit(c, n)
|
||||||
|
var found = parentDir(n.info.toFullPath) / s
|
||||||
if not fileExists(found):
|
if not fileExists(found):
|
||||||
if isAbsolute(s): found = s
|
if isAbsolute(s): found = s
|
||||||
else:
|
else:
|
||||||
found = findFile(s)
|
found = findFile(s)
|
||||||
if found.len == 0: found = s
|
if found.len == 0: found = s
|
||||||
let trunc = found.changeFileExt("")
|
|
||||||
extccomp.addExternalFileToCompile(found)
|
extccomp.addExternalFileToCompile(found)
|
||||||
extccomp.addFileToLink(completeCFilePath(trunc, false))
|
|
||||||
|
|
||||||
proc processCommonLink(c: PContext, n: PNode, feature: TLinkFeature) =
|
proc processCommonLink(c: PContext, n: PNode, feature: TLinkFeature) =
|
||||||
let found = relativeFile(c, n, CC[cCompiler].objExt)
|
let found = relativeFile(c, n, CC[cCompiler].objExt)
|
||||||
case feature
|
case feature
|
||||||
of linkNormal: extccomp.addFileToLink(found)
|
of linkNormal: extccomp.addExternalFileToLink(found)
|
||||||
of linkSys:
|
of linkSys:
|
||||||
extccomp.addFileToLink(libpath / completeCFilePath(found, false))
|
extccomp.addExternalFileToLink(libpath / completeCFilePath(found, false))
|
||||||
else: internalError(n.info, "processCommonLink")
|
else: internalError(n.info, "processCommonLink")
|
||||||
|
|
||||||
proc pragmaBreakpoint(c: PContext, n: PNode) =
|
proc pragmaBreakpoint(c: PContext, n: PNode) =
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue