Nim compiler generates nimcache/proj.json for easier interop with external build tools

This commit is contained in:
Araq
2016-12-14 01:27:44 +01:00
parent 30df922409
commit aedafb9978
2 changed files with 104 additions and 43 deletions

View File

@@ -657,14 +657,56 @@ proc compileCFile(list: TLinkedList, script: var Rope, cmds: var TStringSeq,
add(script, tnl)
it = PStrEntry(it.next)
proc getLinkCmd(projectfile, objfiles: string): string =
if optGenStaticLib in gGlobalOptions:
let name = splitFile(gProjectName).name
result = CC[cCompiler].buildLib % ["libfile", (libNameTmpl() % name),
"objfiles", objfiles]
else:
var linkerExe = getConfigVar(cCompiler, ".linkerexe")
if len(linkerExe) == 0: linkerExe = cCompiler.getLinkerExe
if needsExeExt(): linkerExe = addFileExt(linkerExe, "exe")
if noAbsolutePaths(): result = quoteShell(linkerExe)
else: result = quoteShell(joinPath(ccompilerpath, linkerExe))
let buildgui = if optGenGuiApp in gGlobalOptions: CC[cCompiler].buildGui
else: ""
var exefile, builddll: string
if optGenDynLib in gGlobalOptions:
exefile = platform.OS[targetOS].dllFrmt % splitFile(projectfile).name
builddll = CC[cCompiler].buildDll
else:
exefile = splitFile(projectfile).name & platform.OS[targetOS].exeExt
builddll = ""
if options.outFile.len > 0:
exefile = options.outFile.expandTilde
if not exefile.isAbsolute():
exefile = getCurrentDir() / exefile
if not noAbsolutePaths():
if not exefile.isAbsolute():
exefile = joinPath(splitFile(projectfile).dir, exefile)
if optCDebug in gGlobalOptions:
writeDebugInfo(exefile.changeFileExt("ndb"))
exefile = quoteShell(exefile)
let linkOptions = getLinkOptions() & " " &
getConfigVar(cCompiler, ".options.linker")
result = quoteShell(result % ["builddll", builddll,
"buildgui", buildgui, "options", linkOptions, "objfiles", objfiles,
"exefile", exefile, "nim", getPrefixDir(), "lib", libpath])
result.add ' '
addf(result, CC[cCompiler].linkTmpl, ["builddll", builddll,
"buildgui", buildgui, "options", linkOptions,
"objfiles", objfiles, "exefile", exefile,
"nim", quoteShell(getPrefixDir()),
"lib", quoteShell(libpath)])
proc callCCompiler*(projectfile: string) =
var
linkCmd, buildgui, builddll: string
linkCmd, buildgui: string
if gGlobalOptions * {optCompileOnly, optGenScript} == {optCompileOnly}:
return # speed up that call if only compiling and no script shall be
# generated
fileCounter = 0
var c = cCompiler
#var c = cCompiler
var script: Rope = nil
var cmds: TStringSeq = @[]
var prettyCmds: TStringSeq = @[]
@@ -708,46 +750,7 @@ proc callCCompiler*(projectfile: string) =
addFileExt(objFile, CC[cCompiler].objExt)))
it = PStrEntry(it.next)
if optGenStaticLib in gGlobalOptions:
let name = splitFile(gProjectName).name
linkCmd = CC[c].buildLib % ["libfile", (libNameTmpl() % name),
"objfiles", objfiles]
else:
var linkerExe = getConfigVar(c, ".linkerexe")
if len(linkerExe) == 0: linkerExe = c.getLinkerExe
if needsExeExt(): linkerExe = addFileExt(linkerExe, "exe")
if noAbsolutePaths(): linkCmd = quoteShell(linkerExe)
else: linkCmd = quoteShell(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
builddll = CC[c].buildDll
else:
exefile = splitFile(projectfile).name & platform.OS[targetOS].exeExt
builddll = ""
if options.outFile.len > 0:
exefile = options.outFile.expandTilde
if not exefile.isAbsolute():
exefile = getCurrentDir() / exefile
if not noAbsolutePaths():
if not exefile.isAbsolute():
exefile = joinPath(splitFile(projectfile).dir, exefile)
if optCDebug in gGlobalOptions:
writeDebugInfo(exefile.changeFileExt("ndb"))
exefile = quoteShell(exefile)
let linkOptions = getLinkOptions() & " " &
getConfigVar(cCompiler, ".options.linker")
linkCmd = quoteShell(linkCmd % ["builddll", builddll,
"buildgui", buildgui, "options", linkOptions, "objfiles", objfiles,
"exefile", exefile, "nim", getPrefixDir(), "lib", libpath])
linkCmd.add ' '
addf(linkCmd, CC[c].linkTmpl, ["builddll", builddll,
"buildgui", buildgui, "options", linkOptions,
"objfiles", objfiles, "exefile", exefile,
"nim", quoteShell(getPrefixDir()),
"lib", quoteShell(libpath)])
linkCmd = getLinkCmd(projectfile, objfiles)
if optCompileOnly notin gGlobalOptions:
execExternalProgram(linkCmd,
if optListCmd in gGlobalOptions or gVerbosity > 1: hintExecuting else: hintLinking)
@@ -758,6 +761,62 @@ proc callCCompiler*(projectfile: string) =
add(script, tnl)
generateScript(projectfile, script)
from json import escapeJson
proc writeJsonBuildInstructions*(projectfile: string) =
template lit(x: untyped) = f.write x
template str(x: untyped) =
buf.setLen 0
escapeJson(x, buf)
f.write buf
proc cfiles(f: File; buf: var string; list: TLinkedList, isExternal: bool) =
var it = PStrEntry(list.head)
while it != nil:
let compileCmd = getCompileCFileCmd(it.data, isExternal)
lit "["
str it.data
lit ", "
str compileCmd
it = PStrEntry(it.next)
if it == nil:
lit "]\L"
else:
lit "],\L"
proc linkfiles(f: File; buf, objfiles: var string; toLink: TLinkedList) =
var it = PStrEntry(toLink.head)
while it != nil:
let objfile = addFileExt(it.data, CC[cCompiler].objExt)
str objfile
add(objfiles, ' ')
add(objfiles, quoteShell(objfile))
it = PStrEntry(it.next)
if it == nil:
lit "\L"
else:
lit ",\L"
var buf = newStringOfCap(50)
let file = projectfile.splitFile.name
let jsonFile = toGeneratedFile(file, "json")
var f: File
if open(f, jsonFile, fmWrite):
lit "{\"compile\":[\L"
cfiles(f, buf, toCompile, false)
lit "],\L\"extcompile\":[\L"
cfiles(f, buf, externalToCompile, true)
lit "],\L\"link\":[\L"
var objfiles = ""
linkfiles(f, buf, objfiles, toLink)
lit "],\L\"linkcmd\": "
str getLinkCmd(projectfile, objfiles)
lit "\L}\L"
close(f)
proc genMappingFiles(list: TLinkedList): Rope =
var it = PStrEntry(list.head)
while it != nil:

View File

@@ -66,7 +66,9 @@ proc commandCompileToC(graph: ModuleGraph; cache: IdentCache) =
compileProject(graph, cache)
cgenWriteModules()
if gCmd != cmdRun:
extccomp.callCCompiler(changeFileExt(gProjectFull, ""))
let proj = changeFileExt(gProjectFull, "")
extccomp.callCCompiler(proj)
extccomp.writeJsonBuildInstructions(proj)
proc commandCompileToJS(graph: ModuleGraph; cache: IdentCache) =
#incl(gGlobalOptions, optSafeCode)