the linking step doesn't mind Windows' 8K command line limit anymore
This commit is contained in:
parent
77272ceb3c
commit
46820b94a6
1 changed files with 47 additions and 27 deletions
|
|
@ -652,13 +652,13 @@ proc compileCFile(conf: ConfigRef; list: CFileList, script: var Rope, cmds: var
|
||||||
add(script, compileCmd)
|
add(script, compileCmd)
|
||||||
add(script, "\n")
|
add(script, "\n")
|
||||||
|
|
||||||
proc getLinkCmd(conf: ConfigRef; projectfile: AbsoluteFile, objfiles: string; base: AbsoluteDir): string =
|
proc getLinkCmd(conf: ConfigRef; projectfile: AbsoluteFile, objfiles: string): string =
|
||||||
if optGenStaticLib in conf.globalOptions:
|
if optGenStaticLib in conf.globalOptions:
|
||||||
var libname: string
|
var libname: string
|
||||||
if not conf.outFile.isEmpty:
|
if not conf.outFile.isEmpty:
|
||||||
libname = conf.outFile.string.expandTilde
|
libname = conf.outFile.string.expandTilde
|
||||||
if not libname.isAbsolute():
|
if not libname.isAbsolute():
|
||||||
libname = base.string / libname
|
libname = getCurrentDir() / libname
|
||||||
else:
|
else:
|
||||||
libname = (libNameTmpl(conf) % splitFile(conf.projectName).name)
|
libname = (libNameTmpl(conf) % splitFile(conf.projectName).name)
|
||||||
result = CC[conf.cCompiler].buildLib % ["libfile", quoteShell(libname),
|
result = CC[conf.cCompiler].buildLib % ["libfile", quoteShell(libname),
|
||||||
|
|
@ -683,11 +683,11 @@ proc getLinkCmd(conf: ConfigRef; projectfile: AbsoluteFile, objfiles: string; ba
|
||||||
builddll = ""
|
builddll = ""
|
||||||
if not conf.outFile.isEmpty:
|
if not conf.outFile.isEmpty:
|
||||||
exefile = conf.outFile.string.expandTilde
|
exefile = conf.outFile.string.expandTilde
|
||||||
|
if not exefile.isAbsolute():
|
||||||
|
exefile = getCurrentDir() / exefile
|
||||||
if not noAbsolutePaths(conf):
|
if not noAbsolutePaths(conf):
|
||||||
if not exefile.isAbsolute():
|
if not exefile.isAbsolute():
|
||||||
exefile = string(splitFile(projectfile).dir / RelativeFile(exefile))
|
exefile = string(splitFile(projectfile).dir / RelativeFile(exefile))
|
||||||
if not exefile.isAbsolute():
|
|
||||||
exefile = base.string / exefile
|
|
||||||
when false:
|
when false:
|
||||||
if optCDebug in conf.globalOptions:
|
if optCDebug in conf.globalOptions:
|
||||||
writeDebugInfo(exefile.changeFileExt("ndb"))
|
writeDebugInfo(exefile.changeFileExt("ndb"))
|
||||||
|
|
@ -763,12 +763,31 @@ proc execCmdsInParallel(conf: ConfigRef; cmds: seq[string]; prettyCb: proc (idx:
|
||||||
rawMessage(conf, errGenerated, "execution of an external program failed: '$1'" %
|
rawMessage(conf, errGenerated, "execution of an external program failed: '$1'" %
|
||||||
cmds.join())
|
cmds.join())
|
||||||
|
|
||||||
proc minimizeObjfileNameLen(fullObjName: AbsoluteFile, conf: ConfigRef): string =
|
proc linkViaResponseFile(conf: ConfigRef; cmd: string) =
|
||||||
# For OSes with command line length limitations we try to use relative
|
# Extracting the linker.exe here is a bit hacky but the best solution
|
||||||
# paths over absolute ones:
|
# given ``buildLib``'s design.
|
||||||
result = relativeTo(fullObjName, getNimcacheDir(conf)).string
|
var i = 0
|
||||||
if result.len >= fullObjName.string.len:
|
var last = 0
|
||||||
result = fullObjName.string
|
if cmd.len > 0 and cmd[0] == '"':
|
||||||
|
inc i
|
||||||
|
while i < cmd.len and cmd[i] != '"': inc i
|
||||||
|
last = i
|
||||||
|
inc i
|
||||||
|
else:
|
||||||
|
while i < cmd.len and cmd[i] != ' ': inc i
|
||||||
|
last = i
|
||||||
|
while i < cmd.len and cmd[i] == ' ': inc i
|
||||||
|
let linkerArgs = conf.projectName & "_" & "linkerArgs.txt"
|
||||||
|
let args = cmd.substr(i)
|
||||||
|
# GCC's response files don't support backslashes. Junk.
|
||||||
|
if conf.cCompiler == ccGcc:
|
||||||
|
writeFile(linkerArgs, args.replace('\\', '/'))
|
||||||
|
else:
|
||||||
|
writeFile(linkerArgs, args)
|
||||||
|
try:
|
||||||
|
execLinkCmd(conf, cmd.substr(0, last) & " @" & linkerArgs)
|
||||||
|
finally:
|
||||||
|
removeFile(linkerArgs)
|
||||||
|
|
||||||
proc callCCompiler*(conf: ConfigRef; projectfile: AbsoluteFile) =
|
proc callCCompiler*(conf: ConfigRef; projectfile: AbsoluteFile) =
|
||||||
var
|
var
|
||||||
|
|
@ -790,24 +809,25 @@ proc callCCompiler*(conf: ConfigRef; projectfile: AbsoluteFile) =
|
||||||
if optNoLinking notin conf.globalOptions:
|
if optNoLinking notin conf.globalOptions:
|
||||||
# call the linker:
|
# call the linker:
|
||||||
var objfiles = ""
|
var objfiles = ""
|
||||||
let oldCwd = getCurrentDir()
|
for it in conf.externalToLink:
|
||||||
try:
|
let objFile = if noAbsolutePaths(conf): it.extractFilename else: it
|
||||||
setCurrentDir(getNimcacheDir(conf).string)
|
add(objfiles, ' ')
|
||||||
for it in conf.externalToLink:
|
add(objfiles, quoteShell(
|
||||||
let objFile = if noAbsolutePaths(conf): it.extractFilename else: it
|
addFileExt(objFile, CC[conf.cCompiler].objExt)))
|
||||||
add(objfiles, ' ')
|
for x in conf.toCompile:
|
||||||
let fullObjName = AbsoluteFile addFileExt(objFile, CC[conf.cCompiler].objExt)
|
let objFile = if noAbsolutePaths(conf): x.obj.extractFilename else: x.obj.string
|
||||||
add(objfiles, quoteShell(minimizeObjfileNameLen(fullObjName, conf)))
|
add(objfiles, ' ')
|
||||||
for x in conf.toCompile:
|
add(objfiles, quoteShell(objFile))
|
||||||
let objFile = if noAbsolutePaths(conf): x.obj.extractFilename.AbsoluteFile else: x.obj
|
|
||||||
add(objfiles, ' ')
|
|
||||||
add(objfiles, quoteShell(minimizeObjfileNameLen(objFile, conf)))
|
|
||||||
|
|
||||||
linkCmd = getLinkCmd(conf, projectfile, objfiles, AbsoluteDir oldCwd)
|
linkCmd = getLinkCmd(conf, projectfile, objfiles)
|
||||||
if optCompileOnly notin conf.globalOptions:
|
if optCompileOnly notin conf.globalOptions:
|
||||||
|
if defined(windows) and linkCmd.len > 8_000:
|
||||||
|
# Windows's command line limit is about 8K (don't laugh...) so C compilers on
|
||||||
|
# Windows support a feature where the command line can be passed via ``@linkcmd``
|
||||||
|
# to them.
|
||||||
|
linkViaResponseFile(conf, linkCmd)
|
||||||
|
else:
|
||||||
execLinkCmd(conf, linkCmd)
|
execLinkCmd(conf, linkCmd)
|
||||||
finally:
|
|
||||||
setCurrentDir(oldCwd)
|
|
||||||
else:
|
else:
|
||||||
linkCmd = ""
|
linkCmd = ""
|
||||||
if optGenScript in conf.globalOptions:
|
if optGenScript in conf.globalOptions:
|
||||||
|
|
@ -877,7 +897,7 @@ proc writeJsonBuildInstructions*(conf: ConfigRef; projectfile: AbsoluteFile) =
|
||||||
linkfiles(conf, f, buf, objfiles, conf.toCompile, conf.externalToLink)
|
linkfiles(conf, f, buf, objfiles, conf.toCompile, conf.externalToLink)
|
||||||
|
|
||||||
lit "],\L\"linkcmd\": "
|
lit "],\L\"linkcmd\": "
|
||||||
str getLinkCmd(conf, projectfile, objfiles, AbsoluteDir getCurrentDir())
|
str getLinkCmd(conf, projectfile, objfiles)
|
||||||
lit "\L}\L"
|
lit "\L}\L"
|
||||||
close(f)
|
close(f)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue