compiler refactoring; use typesafe path handing; docgen: render symbols between modules
This commit is contained in:
parent
b5730ec01f
commit
86556ebfdb
45 changed files with 816 additions and 504 deletions
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
import
|
||||
ropes, os, strutils, osproc, platform, condsyms, options, msgs,
|
||||
lineinfos, std / sha1, streams
|
||||
lineinfos, std / sha1, streams, pathutils
|
||||
|
||||
type
|
||||
TInfoCCProp* = enum # properties of the C compiler:
|
||||
|
|
@ -429,12 +429,13 @@ proc initVars*(conf: ConfigRef) =
|
|||
if len(conf.ccompilerpath) == 0:
|
||||
conf.ccompilerpath = getConfigVar(conf, conf.cCompiler, ".path")
|
||||
|
||||
proc completeCFilePath*(conf: ConfigRef; cfile: string, createSubDir: bool = true): string =
|
||||
proc completeCFilePath*(conf: ConfigRef; cfile: AbsoluteFile,
|
||||
createSubDir: bool = true): AbsoluteFile =
|
||||
result = completeGeneratedFilePath(conf, cfile, createSubDir)
|
||||
|
||||
proc toObjFile*(conf: ConfigRef; filename: string): string =
|
||||
proc toObjFile*(conf: ConfigRef; filename: AbsoluteFile): AbsoluteFile =
|
||||
# Object file for compilation
|
||||
result = filename & "." & CC[conf.cCompiler].objExt
|
||||
result = AbsoluteFile(filename.string & "." & CC[conf.cCompiler].objExt)
|
||||
|
||||
proc addFileToCompile*(conf: ConfigRef; cf: Cfile) =
|
||||
conf.toCompile.add(cf)
|
||||
|
|
@ -447,8 +448,8 @@ proc resetCompilationLists*(conf: ConfigRef) =
|
|||
# Maybe we can do that in checkDep on the other hand?
|
||||
conf.externalToLink.setLen 0
|
||||
|
||||
proc addExternalFileToLink*(conf: ConfigRef; filename: string) =
|
||||
conf.externalToLink.insert(filename, 0)
|
||||
proc addExternalFileToLink*(conf: ConfigRef; filename: AbsoluteFile) =
|
||||
conf.externalToLink.insert(filename.string, 0)
|
||||
|
||||
proc execWithEcho(conf: ConfigRef; cmd: string, msg = hintExecuting): int =
|
||||
rawMessage(conf, msg, cmd)
|
||||
|
|
@ -459,14 +460,15 @@ proc execExternalProgram*(conf: ConfigRef; cmd: string, msg = hintExecuting) =
|
|||
rawMessage(conf, errGenerated, "execution of an external program failed: '$1'" %
|
||||
cmd)
|
||||
|
||||
proc generateScript(conf: ConfigRef; projectFile: string, script: Rope) =
|
||||
let (dir, name, ext) = splitFile(projectFile)
|
||||
let filename = getNimcacheDir(conf) / addFileExt("compile_" & name,
|
||||
platform.OS[conf.target.targetOS].scriptExt)
|
||||
proc generateScript(conf: ConfigRef; projectFile: AbsoluteFile, script: Rope) =
|
||||
let (_, name, _) = splitFile(projectFile)
|
||||
let filename = getNimcacheDir(conf) / RelativeFile(addFileExt("compile_" & name,
|
||||
platform.OS[conf.target.targetOS].scriptExt))
|
||||
if writeRope(script, filename):
|
||||
copyFile(conf.libpath / "nimbase.h", getNimcacheDir(conf) / "nimbase.h")
|
||||
copyFile(conf.libpath / RelativeFile"nimbase.h",
|
||||
getNimcacheDir(conf) / RelativeFile"nimbase.h")
|
||||
else:
|
||||
rawMessage(conf, errGenerated, "could not write to file: " & filename)
|
||||
rawMessage(conf, errGenerated, "could not write to file: " & filename.string)
|
||||
|
||||
proc getOptSpeed(conf: ConfigRef; c: TSystemCC): string =
|
||||
result = getConfigVar(conf, c, ".options.speed")
|
||||
|
|
@ -490,7 +492,7 @@ proc noAbsolutePaths(conf: ConfigRef): bool {.inline.} =
|
|||
# `optGenMapping` is included here for niminst.
|
||||
result = conf.globalOptions * {optGenScript, optGenMapping} != {}
|
||||
|
||||
proc cFileSpecificOptions(conf: ConfigRef; cfilename: string): string =
|
||||
proc cFileSpecificOptions(conf: ConfigRef; cfilename: AbsoluteFile): string =
|
||||
result = conf.compileOptions
|
||||
for option in conf.compileOptionsCmd:
|
||||
if strutils.find(result, option, 0) < 0:
|
||||
|
|
@ -513,7 +515,7 @@ proc cFileSpecificOptions(conf: ConfigRef; cfilename: string): string =
|
|||
if existsConfigVar(conf, key): addOpt(result, getConfigVar(conf, key))
|
||||
|
||||
proc getCompileOptions(conf: ConfigRef): string =
|
||||
result = cFileSpecificOptions(conf, "__dummy__")
|
||||
result = cFileSpecificOptions(conf, AbsoluteFile"__dummy__")
|
||||
|
||||
proc getLinkOptions(conf: ConfigRef): string =
|
||||
result = conf.linkOptions & " " & conf.linkOptionsCmd & " "
|
||||
|
|
@ -526,8 +528,8 @@ proc needsExeExt(conf: ConfigRef): bool {.inline.} =
|
|||
result = (optGenScript in conf.globalOptions and conf.target.targetOS == osWindows) or
|
||||
(conf.target.hostOS == osWindows)
|
||||
|
||||
proc getCompilerExe(conf: ConfigRef; compiler: TSystemCC; cfile: string): string =
|
||||
result = if conf.cmd == cmdCompileToCpp and not cfile.endsWith(".c"):
|
||||
proc getCompilerExe(conf: ConfigRef; compiler: TSystemCC; cfile: AbsoluteFile): string =
|
||||
result = if conf.cmd == cmdCompileToCpp and not cfile.string.endsWith(".c"):
|
||||
CC[compiler].cppCompiler
|
||||
else:
|
||||
CC[compiler].compilerExe
|
||||
|
|
@ -539,7 +541,7 @@ proc getCompilerExe(conf: ConfigRef; compiler: TSystemCC; cfile: string): string
|
|||
proc getLinkerExe(conf: ConfigRef; compiler: TSystemCC): string =
|
||||
result = if CC[compiler].linkerExe.len > 0: CC[compiler].linkerExe
|
||||
elif optMixedMode in conf.globalOptions and conf.cmd != cmdCompileToCpp: CC[compiler].cppCompiler
|
||||
else: getCompilerExe(conf, compiler, "")
|
||||
else: getCompilerExe(conf, compiler, AbsoluteFile"")
|
||||
|
||||
proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile): string =
|
||||
var c = conf.cCompiler
|
||||
|
|
@ -565,43 +567,42 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile): string =
|
|||
includeCmd = ""
|
||||
compilePattern = getCompilerExe(conf, c, cfile.cname)
|
||||
|
||||
var cf = if noAbsolutePaths(conf): extractFilename(cfile.cname)
|
||||
var cf = if noAbsolutePaths(conf): AbsoluteFile extractFilename(cfile.cname.string)
|
||||
else: cfile.cname
|
||||
|
||||
var objfile =
|
||||
if cfile.obj.len == 0:
|
||||
if cfile.obj.isEmpty:
|
||||
if not cfile.flags.contains(CfileFlag.External) or noAbsolutePaths(conf):
|
||||
toObjFile(conf, cf)
|
||||
toObjFile(conf, cf).string
|
||||
else:
|
||||
completeCFilePath(conf, toObjFile(conf, cf))
|
||||
completeCFilePath(conf, toObjFile(conf, cf)).string
|
||||
elif noAbsolutePaths(conf):
|
||||
extractFilename(cfile.obj)
|
||||
extractFilename(cfile.obj.string)
|
||||
else:
|
||||
cfile.obj
|
||||
cfile.obj.string
|
||||
|
||||
# D files are required by nintendo switch libs for
|
||||
# compilation. They are basically a list of all includes.
|
||||
let dfile = objfile.changeFileExt(".d").quoteShell()
|
||||
|
||||
objfile = quoteShell(objfile)
|
||||
cf = quoteShell(cf)
|
||||
let cfsh = quoteShell(cf)
|
||||
result = quoteShell(compilePattern % [
|
||||
"dfile", dfile,
|
||||
"file", cf, "objfile", objfile, "options", options,
|
||||
"include", includeCmd, "nim", getPrefixDir(conf),
|
||||
"nim", getPrefixDir(conf), "lib", conf.libpath])
|
||||
"file", cfsh, "objfile", objfile, "options", options,
|
||||
"include", includeCmd, "nim", getPrefixDir(conf).string,
|
||||
"lib", conf.libpath.string])
|
||||
add(result, ' ')
|
||||
addf(result, CC[c].compileTmpl, [
|
||||
"dfile", dfile,
|
||||
"file", cf, "objfile", objfile,
|
||||
"file", cfsh, "objfile", objfile,
|
||||
"options", options, "include", includeCmd,
|
||||
"nim", quoteShell(getPrefixDir(conf)),
|
||||
"nim", quoteShell(getPrefixDir(conf)),
|
||||
"lib", quoteShell(conf.libpath)])
|
||||
|
||||
proc footprint(conf: ConfigRef; cfile: Cfile): SecureHash =
|
||||
result = secureHash(
|
||||
$secureHashFile(cfile.cname) &
|
||||
$secureHashFile(cfile.cname.string) &
|
||||
platform.OS[conf.target.targetOS].name &
|
||||
platform.CPU[conf.target.targetCPU].name &
|
||||
extccomp.CC[conf.cCompiler].name &
|
||||
|
|
@ -614,14 +615,14 @@ proc externalFileChanged(conf: ConfigRef; cfile: Cfile): bool =
|
|||
var hashFile = toGeneratedFile(conf, conf.withPackageName(cfile.cname), "sha1")
|
||||
var currentHash = footprint(conf, cfile)
|
||||
var f: File
|
||||
if open(f, hashFile, fmRead):
|
||||
if open(f, hashFile.string, fmRead):
|
||||
let oldHash = parseSecureHash(f.readLine())
|
||||
close(f)
|
||||
result = oldHash != currentHash
|
||||
else:
|
||||
result = true
|
||||
if result:
|
||||
if open(f, hashFile, fmWrite):
|
||||
if open(f, hashFile.string, fmWrite):
|
||||
f.writeLine($currentHash)
|
||||
close(f)
|
||||
|
||||
|
|
@ -630,7 +631,7 @@ proc addExternalFileToCompile*(conf: ConfigRef; c: var Cfile) =
|
|||
c.flags.incl CfileFlag.Cached
|
||||
conf.toCompile.add(c)
|
||||
|
||||
proc addExternalFileToCompile*(conf: ConfigRef; filename: string) =
|
||||
proc addExternalFileToCompile*(conf: ConfigRef; filename: AbsoluteFile) =
|
||||
var c = Cfile(cname: filename,
|
||||
obj: toObjFile(conf, completeCFilePath(conf, filename, false)),
|
||||
flags: {CfileFlag.External})
|
||||
|
|
@ -650,11 +651,11 @@ proc compileCFile(conf: ConfigRef; list: CFileList, script: var Rope, cmds: var
|
|||
add(script, compileCmd)
|
||||
add(script, "\n")
|
||||
|
||||
proc getLinkCmd(conf: ConfigRef; projectfile, objfiles: string): string =
|
||||
proc getLinkCmd(conf: ConfigRef; projectfile: AbsoluteFile, objfiles: string): string =
|
||||
if optGenStaticLib in conf.globalOptions:
|
||||
var libname: string
|
||||
if conf.outFile.len > 0:
|
||||
libname = conf.outFile.expandTilde
|
||||
if not conf.outFile.isEmpty:
|
||||
libname = conf.outFile.string.expandTilde
|
||||
if not libname.isAbsolute():
|
||||
libname = getCurrentDir() / libname
|
||||
else:
|
||||
|
|
@ -679,13 +680,13 @@ proc getLinkCmd(conf: ConfigRef; projectfile, objfiles: string): string =
|
|||
else:
|
||||
exefile = splitFile(projectfile).name & platform.OS[conf.target.targetOS].exeExt
|
||||
builddll = ""
|
||||
if conf.outFile.len > 0:
|
||||
exefile = conf.outFile.expandTilde
|
||||
if not conf.outFile.isEmpty:
|
||||
exefile = conf.outFile.string.expandTilde
|
||||
if not exefile.isAbsolute():
|
||||
exefile = getCurrentDir() / exefile
|
||||
if not noAbsolutePaths(conf):
|
||||
if not exefile.isAbsolute():
|
||||
exefile = joinPath(splitFile(projectfile).dir, exefile)
|
||||
exefile = string(splitFile(projectfile).dir / RelativeFile(exefile))
|
||||
when false:
|
||||
if optCDebug in conf.globalOptions:
|
||||
writeDebugInfo(exefile.changeFileExt("ndb"))
|
||||
|
|
@ -693,7 +694,7 @@ proc getLinkCmd(conf: ConfigRef; projectfile, objfiles: string): string =
|
|||
|
||||
# Map files are required by Nintendo Switch compilation. They are a list
|
||||
# of all function calls in the library and where they come from.
|
||||
let mapfile = quoteShell(getNimcacheDir(conf) / splitFile(projectFile).name & ".map")
|
||||
let mapfile = quoteShell(getNimcacheDir(conf) / RelativeFile(splitFile(projectFile).name & ".map"))
|
||||
|
||||
let linkOptions = getLinkOptions(conf) & " " &
|
||||
getConfigVar(conf, conf.cCompiler, ".options.linker")
|
||||
|
|
@ -703,7 +704,7 @@ proc getLinkCmd(conf: ConfigRef; projectfile, objfiles: string): string =
|
|||
result = quoteShell(result % ["builddll", builddll,
|
||||
"mapfile", mapfile,
|
||||
"buildgui", buildgui, "options", linkOptions, "objfiles", objfiles,
|
||||
"exefile", exefile, "nim", getPrefixDir(conf), "lib", conf.libpath])
|
||||
"exefile", exefile, "nim", getPrefixDir(conf).string, "lib", conf.libpath.string])
|
||||
result.add ' '
|
||||
addf(result, linkTmpl, ["builddll", builddll,
|
||||
"mapfile", mapfile,
|
||||
|
|
@ -761,7 +762,7 @@ proc execCmdsInParallel(conf: ConfigRef; cmds: seq[string]; prettyCb: proc (idx:
|
|||
rawMessage(conf, errGenerated, "execution of an external program failed: '$1'" %
|
||||
cmds.join())
|
||||
|
||||
proc callCCompiler*(conf: ConfigRef; projectfile: string) =
|
||||
proc callCCompiler*(conf: ConfigRef; projectfile: AbsoluteFile) =
|
||||
var
|
||||
linkCmd: string
|
||||
if conf.globalOptions * {optCompileOnly, optGenScript} == {optCompileOnly}:
|
||||
|
|
@ -787,7 +788,7 @@ proc callCCompiler*(conf: ConfigRef; projectfile: string) =
|
|||
add(objfiles, quoteShell(
|
||||
addFileExt(objFile, CC[conf.cCompiler].objExt)))
|
||||
for x in conf.toCompile:
|
||||
let objFile = if noAbsolutePaths(conf): x.obj.extractFilename else: x.obj
|
||||
let objFile = if noAbsolutePaths(conf): x.obj.extractFilename else: x.obj.string
|
||||
add(objfiles, ' ')
|
||||
add(objfiles, quoteShell(objFile))
|
||||
|
||||
|
|
@ -804,7 +805,7 @@ proc callCCompiler*(conf: ConfigRef; projectfile: string) =
|
|||
#from json import escapeJson
|
||||
import json
|
||||
|
||||
proc writeJsonBuildInstructions*(conf: ConfigRef; projectfile: string) =
|
||||
proc writeJsonBuildInstructions*(conf: ConfigRef; projectfile: AbsoluteFile) =
|
||||
template lit(x: untyped) = f.write x
|
||||
template str(x: untyped) =
|
||||
when compiles(escapeJson(x, buf)):
|
||||
|
|
@ -821,7 +822,7 @@ proc writeJsonBuildInstructions*(conf: ConfigRef; projectfile: string) =
|
|||
let compileCmd = getCompileCFileCmd(conf, it)
|
||||
if pastStart: lit "],\L"
|
||||
lit "["
|
||||
str it.cname
|
||||
str it.cname.string
|
||||
lit ", "
|
||||
str compileCmd
|
||||
pastStart = true
|
||||
|
|
@ -851,11 +852,10 @@ proc writeJsonBuildInstructions*(conf: ConfigRef; projectfile: string) =
|
|||
|
||||
var buf = newStringOfCap(50)
|
||||
|
||||
let file = projectfile.splitFile.name
|
||||
let jsonFile = toGeneratedFile(conf, file, "json")
|
||||
let jsonFile = toGeneratedFile(conf, projectfile, "json")
|
||||
|
||||
var f: File
|
||||
if open(f, jsonFile, fmWrite):
|
||||
if open(f, jsonFile.string, fmWrite):
|
||||
lit "{\"compile\":[\L"
|
||||
cfiles(conf, f, buf, conf.toCompile, false)
|
||||
lit "],\L\"link\":[\L"
|
||||
|
|
@ -868,11 +868,10 @@ proc writeJsonBuildInstructions*(conf: ConfigRef; projectfile: string) =
|
|||
lit "\L}\L"
|
||||
close(f)
|
||||
|
||||
proc runJsonBuildInstructions*(conf: ConfigRef; projectfile: string) =
|
||||
let file = projectfile.splitFile.name
|
||||
let jsonFile = toGeneratedFile(conf, file, "json")
|
||||
proc runJsonBuildInstructions*(conf: ConfigRef; projectfile: AbsoluteFile) =
|
||||
let jsonFile = toGeneratedFile(conf, projectfile, "json")
|
||||
try:
|
||||
let data = json.parseFile(jsonFile)
|
||||
let data = json.parseFile(jsonFile.string)
|
||||
let toCompile = data["compile"]
|
||||
doAssert toCompile.kind == JArray
|
||||
var cmds: TStringSeq = @[]
|
||||
|
|
@ -896,11 +895,11 @@ proc runJsonBuildInstructions*(conf: ConfigRef; projectfile: string) =
|
|||
except:
|
||||
when declared(echo):
|
||||
echo getCurrentException().getStackTrace()
|
||||
quit "error evaluating JSON file: " & jsonFile
|
||||
quit "error evaluating JSON file: " & jsonFile.string
|
||||
|
||||
proc genMappingFiles(conf: ConfigRef; list: CFileList): Rope =
|
||||
for it in list:
|
||||
addf(result, "--file:r\"$1\"$N", [rope(it.cname)])
|
||||
addf(result, "--file:r\"$1\"$N", [rope(it.cname.string)])
|
||||
|
||||
proc writeMapping*(conf: ConfigRef; symbolMapping: Rope) =
|
||||
if optGenMapping notin conf.globalOptions: return
|
||||
|
|
@ -914,9 +913,9 @@ proc writeMapping*(conf: ConfigRef; symbolMapping: Rope) =
|
|||
getConfigVar(conf, conf.cCompiler, ".options.linker")))
|
||||
|
||||
add(code, "\n[Environment]\nlibpath=")
|
||||
add(code, strutils.escape(conf.libpath))
|
||||
add(code, strutils.escape(conf.libpath.string))
|
||||
|
||||
addf(code, "\n[Symbols]$n$1", [symbolMapping])
|
||||
let filename = joinPath(conf.projectPath, "mapping.txt")
|
||||
let filename = conf.projectPath / RelativeFile"mapping.txt"
|
||||
if not writeRope(code, filename):
|
||||
rawMessage(conf, errGenerated, "could not write to file: " & filename)
|
||||
rawMessage(conf, errGenerated, "could not write to file: " & filename.string)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue