summary refs log tree commit diff stats
path: root/compiler/extccomp.nim
diff options
context:
space:
mode:
authorZahary Karadjov <zahary@gmail.com>2011-11-25 17:19:01 +0200
committerZahary Karadjov <zahary@gmail.com>2011-11-25 17:29:55 +0200
commitc617479c6848e07f25f92fd33b3397d65683812e (patch)
tree8d147e84c3f7e424c542bc444d8bb0d1d1bd0d78 /compiler/extccomp.nim
parented9c7761c4e37ec22ebd81acf16e3137d064cfc9 (diff)
downloadNim-c617479c6848e07f25f92fd33b3397d65683812e.tar.gz
New algorithm for locating and loading nimrod config files.
Some new options added to the compiler (see news.txt for details)
Diffstat (limited to 'compiler/extccomp.nim')
-rwxr-xr-xcompiler/extccomp.nim550
1 files changed, 318 insertions, 232 deletions
diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim
index a6dfe7367..9184b3368 100755
--- a/compiler/extccomp.nim
+++ b/compiler/extccomp.nim
@@ -32,223 +32,290 @@ type
     compileTmpl: string, # the compile command template
     buildGui: string,    # command to build a GUI application
     buildDll: string,    # command to build a shared library
+    buildLib: string,    # command to build a static library
     linkerExe: string,   # the linker's executable
     linkTmpl: string,    # command to link files to produce an exe
     includeCmd: string,  # command to add an include dir
+    linkDirCmd: string,  # command to add a lib dir
+    linkLibCmd: string,  # command to link an external library
     debug: string,       # flags for debug build
     pic: string,         # command for position independent code
                          # used on some platforms
     asmStmtFrmt: string, # format of ASM statement
     props: TInfoCCProps] # properties of the C compiler
 
+
+# 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;
+
+template compiler(name: expr, settings: stmt):stmt =
+  proc name: TInfoCC {.compileTime.} = settings
+
+compiler gcc:
+  result = (
+    name: "gcc",
+    objExt: "o",
+    optSpeed: " -O3 -ffast-math ",
+    optSize: " -Os -ffast-math ",
+    compilerExe: "gcc",
+    compileTmpl: "-c $options $include -o $objfile $file",
+    buildGui: " -mwindows",
+    buildDll: " -shared",
+    buildLib: "ar rcs $libfile $objfiles",
+    linkerExe: "gcc",
+    linkTmpl: "$buildgui $builddll -o $exefile $objfiles $options",
+    includeCmd: " -I",
+    linkDirCmd: " -L",
+    linkLibCmd: " -l$1",
+    debug: "",
+    pic: "-fPIC",
+    asmStmtFrmt: "asm($1);$n",
+    props: {hasSwitchRange, hasComputedGoto, hasCpp})
+    
+compiler gpp:
+  result = gcc()
+  
+  result.name = "gpp"
+  result.compilerExe = "g++"
+  result.linkerExe = "g++"  
+  
+  result.debug.add " -g " # XXX: Why is this default for g++, but not for gcc?
+
+  result.buildDll = " -mdll" # XXX: Hmm, I'm keeping this from the previos version, 
+                             # but my gcc doesn't even have such an option (is this mingw?)
+
+compiler llvmGcc:
+  result = gcc()
+  
+  result.name = "llvm_gcc"
+  result.compilerExe = "llvm-gcc"
+  result.buildLib = "llvm-ar rcs $libfile $objfiles"
+  result.linkerExe = "llvm-gcc"
+
+compiler clang:
+  result = llvmGcc()
+
+  result.name = "clang"
+  result.compilerExe = "clang"
+  result.linkerExe = "clang"
+
+compiler vcc:
+  result = (
+    name: "vcc",
+    objExt: "obj",
+    optSpeed: " /Ogityb2 /G7 /arch:SSE2 ",
+    optSize: " /O1 /G7 ",
+    compilerExe: "cl",
+    compileTmpl: "/c $options $include /Fo$objfile $file",
+    buildGui: " /link /SUBSYSTEM:WINDOWS ",
+    buildDll: " /LD",
+    buildLib: "lib /OUT:$libfile $objfiles",
+    linkerExe: "cl",
+    linkTmpl: "$options $builddll /Fe$exefile $objfiles $buildgui",
+    includeCmd: " /I",
+    linkDirCmd: " /LIBPATH:",
+    linkLibCmd: " $1.lib",
+    debug: " /GZ /Zi ",
+    pic: "",
+    asmStmtFrmt: "__asm{$n$1$n}$n",
+    props: {hasCpp, hasAssume})
+
+compiler icc:
+  # Intel compilers try to imitate the native ones (gcc and msvc)
+  when defined(windows):
+    result = vcc()
+  else:
+    result = gcc()
+
+  result.name = "icc"
+  result.compilerExe = "icc"
+  result.linkerExe = "icc"
+
+compiler lcc:
+  result = (
+    name: "lcc",
+    objExt: "obj",
+    optSpeed: " -O -p6 ",
+    optSize: " -O -p6 ",
+    compilerExe: "lcc",
+    compileTmpl: "$options $include -Fo$objfile $file",
+    buildGui: " -subsystem windows",
+    buildDll: " -dll",
+    buildLib: "", # XXX: not supported yet
+    linkerExe: "lcclnk",
+    linkTmpl: "$options $buildgui $builddll -O $exefile $objfiles",
+    includeCmd: " -I",
+    linkDirCmd: "", # XXX: not supported yet
+    linkLibCmd: "", # XXX: not supported yet
+    debug: " -g5 ",
+    pic: "",
+    asmStmtFrmt: "_asm{$n$1$n}$n",
+    props: {})
+
+compiler bcc:
+  result = (
+    name: "bcc",
+    objExt: "obj",
+    optSpeed: " -O2 -6 ",
+    optSize: " -O1 -6 ",
+    compilerExe: "bcc32",
+    compileTmpl: "-c $options $include -o$objfile $file",
+    buildGui: " -tW",
+    buildDll: " -tWD",
+    buildLib: "", # XXX: not supported yet
+    linkerExe: "bcc32",
+    linkTmpl: "$options $buildgui $builddll -e$exefile $objfiles",
+    includeCmd: " -I",
+    linkDirCmd: "", # XXX: not supported yet
+    linkLibCmd: "", # XXX: not supported yet
+    debug: "",
+    pic: "",
+    asmStmtFrmt: "__asm{$n$1$n}$n",
+    props: {hasCpp})
+
+compiler dmc:
+  result = (
+    name: "dmc",
+    objExt: "obj",
+    optSpeed: " -ff -o -6 ",
+    optSize: " -ff -o -6 ",
+    compilerExe: "dmc",
+    compileTmpl: "-c $options $include -o$objfile $file",
+    buildGui: " -L/exet:nt/su:windows",
+    buildDll: " -WD",
+    buildLib: "", # XXX: not supported yet
+    linkerExe: "dmc",
+    linkTmpl: "$options $buildgui $builddll -o$exefile $objfiles",
+    includeCmd: " -I",
+    linkDirCmd: "", # XXX: not supported yet
+    linkLibCmd: "", # XXX: not supported yet
+    debug: " -g ",
+    pic: "",
+    asmStmtFrmt: "__asm{$n$1$n}$n",
+    props: {hasCpp})
+
+compiler wcc:
+  result = (
+    name: "wcc",
+    objExt: "obj",
+    optSpeed: " -ox -on -6 -d0 -fp6 -zW ",
+    optSize: "",
+    compilerExe: "wcl386",
+    compileTmpl: "-c $options $include -fo=$objfile $file",
+    buildGui: " -bw",
+    buildDll: " -bd",
+    buildLib: "", # XXX: not supported yet
+    linkerExe: "wcl386",
+    linkTmpl: "$options $buildgui $builddll -fe=$exefile $objfiles ",
+    includeCmd: " -i=",
+    linkDirCmd: "", # XXX: not supported yet
+    linkLibCmd: "", # XXX: not supported yet
+    debug: " -d2 ",
+    pic: "",
+    asmStmtFrmt: "__asm{$n$1$n}$n",
+    props: {hasCpp})
+
+compiler tcc:
+  result = (
+    name: "tcc",
+    objExt: "o",
+    optSpeed: "",
+    optSize: "",
+    compilerExe: "tcc",
+    compileTmpl: "-c $options $include -o $objfile $file",
+    buildGui: "UNAVAILABLE!",
+    buildDll: " -shared",
+    buildLib: "", # XXX: not supported yet
+    linkerExe: "tcc",
+    linkTmpl: "-o $exefile $options $buildgui $builddll $objfiles",
+    includeCmd: " -I",
+    linkDirCmd: "", # XXX: not supported yet
+    linkLibCmd: "", # XXX: not supported yet
+    debug: " -g ",
+    pic: "",
+    asmStmtFrmt: "__asm{$n$1$n}$n",
+    props: {hasSwitchRange, hasComputedGoto})
+
+compiler pcc:
+  # Pelles C
+  result = (
+    name: "pcc",
+    objExt: "obj",
+    optSpeed: " -Ox ",
+    optSize: " -Os ",
+    compilerExe: "cc",
+    compileTmpl: "-c $options $include -Fo$objfile $file",
+    buildGui: " -SUBSYSTEM:WINDOWS",
+    buildDll: " -DLL",
+    buildLib: "", # XXX: not supported yet
+    linkerExe: "cc",
+    linkTmpl: "$options $buildgui $builddll -OUT:$exefile $objfiles",
+    includeCmd: " -I",
+    linkDirCmd: "", # XXX: not supported yet
+    linkLibCmd: "", # XXX: not supported yet
+    debug: " -Zi ",
+    pic: "",
+    asmStmtFrmt: "__asm{$n$1$n}$n",
+    props: {})
+
+compiler ucc:
+  result = (
+    name: "ucc",
+    objExt: "o",
+    optSpeed: " -O3 ",
+    optSize: " -O1 ",
+    compilerExe: "cc",
+    compileTmpl: "-c $options $include -o $objfile $file",
+    buildGui: "",
+    buildDll: " -shared ",
+    buildLib: "", # XXX: not supported yet
+    linkerExe: "cc",
+    linkTmpl: "-o $exefile $buildgui $builddll $objfiles $options",
+    includeCmd: " -I",
+    linkDirCmd: "", # XXX: not supported yet
+    linkLibCmd: "", # XXX: not supported yet
+    debug: "",
+    pic: "",
+    asmStmtFrmt: "__asm{$n$1$n}$n",
+    props: {})
+
 const 
   CC*: array[succ(low(TSystemCC))..high(TSystemCC), TInfoCC] = [
-    (name: "gcc", 
-     objExt: "o", 
-     optSpeed: " -O3 -ffast-math ", 
-     optSize: " -Os -ffast-math ", 
-     compilerExe: "gcc", 
-     compileTmpl: "-c $options $include -o $objfile $file", 
-     buildGui: " -mwindows", 
-     buildDll: " -shared", 
-     linkerExe: "gcc", 
-     linkTmpl: "$buildgui $builddll -o $exefile $objfiles $options", 
-     includeCmd: " -I", 
-     debug: "", 
-     pic: "-fPIC", 
-     asmStmtFrmt: "asm($1);$n", 
-     props: {hasSwitchRange, hasComputedGoto, hasCpp}), 
-    (name: "llvm_gcc", 
-     objExt: "o", 
-     optSpeed: " -O3 -ffast-math ", 
-     optSize: " -Os -ffast-math ", 
-     compilerExe: "llvm-gcc", 
-     compileTmpl: "-c $options $include -o $objfile $file", 
-     buildGui: " -mwindows", 
-     buildDll: " -shared", 
-     linkerExe: "llvm-gcc", 
-     linkTmpl: "$buildgui $builddll -o $exefile $objfiles $options", 
-     includeCmd: " -I", 
-     debug: "", 
-     pic: "-fPIC", 
-     asmStmtFrmt: "asm($1);$n", 
-     props: {hasSwitchRange, hasComputedGoto, hasCpp}), 
-    (name: "clang", 
-     objExt: "o", 
-     optSpeed: " -O3 -ffast-math ", 
-     optSize: " -Os -ffast-math ", 
-     compilerExe: "clang", 
-     compileTmpl: "-c $options $include -o $objfile $file", 
-     buildGui: " -mwindows", 
-     buildDll: " -shared", 
-     linkerExe: "clang", 
-     linkTmpl: "$buildgui $builddll -o $exefile $objfiles $options", 
-     includeCmd: " -I", 
-     debug: "", 
-     pic: "-fPIC", 
-     asmStmtFrmt: "asm($1);$n", 
-     props: {hasSwitchRange, hasComputedGoto, hasCpp}), 
-    (name: "lcc", 
-     objExt: "obj", 
-     optSpeed: " -O -p6 ", 
-     optSize: " -O -p6 ", 
-     compilerExe: "lcc", 
-     compileTmpl: "$options $include -Fo$objfile $file", 
-     buildGui: " -subsystem windows", 
-     buildDll: " -dll", 
-     linkerExe: "lcclnk", 
-     linkTmpl: "$options $buildgui $builddll -O $exefile $objfiles", 
-     includeCmd: " -I", 
-     debug: " -g5 ", 
-     pic: "", 
-     asmStmtFrmt: "_asm{$n$1$n}$n", 
-     props: {}), 
-    (name: "bcc", 
-     objExt: "obj", 
-     optSpeed: " -O2 -6 ", 
-     optSize: " -O1 -6 ", 
-     compilerExe: "bcc32", 
-     compileTmpl: "-c $options $include -o$objfile $file", 
-     buildGui: " -tW", 
-     buildDll: " -tWD", 
-     linkerExe: "bcc32", 
-     linkTmpl: "$options $buildgui $builddll -e$exefile $objfiles", 
-     includeCmd: " -I", 
-     debug: "", 
-     pic: "", 
-     asmStmtFrmt: "__asm{$n$1$n}$n", 
-     props: {hasCpp}), 
-    (name: "dmc", 
-     objExt: "obj", 
-     optSpeed: " -ff -o -6 ", 
-     optSize: " -ff -o -6 ", 
-     compilerExe: "dmc", 
-     compileTmpl: "-c $options $include -o$objfile $file", 
-     buildGui: " -L/exet:nt/su:windows", 
-     buildDll: " -WD", 
-     linkerExe: "dmc", 
-     linkTmpl: "$options $buildgui $builddll -o$exefile $objfiles", 
-     includeCmd: " -I", 
-     debug: " -g ", 
-     pic: "", 
-     asmStmtFrmt: "__asm{$n$1$n}$n", 
-     props: {hasCpp}), 
-    (name: "wcc", 
-     objExt: "obj", 
-     optSpeed: " -ox -on -6 -d0 -fp6 -zW ", 
-     optSize: "", 
-     compilerExe: "wcl386", 
-     compileTmpl: "-c $options $include -fo=$objfile $file", 
-     buildGui: " -bw", 
-     buildDll: " -bd", 
-     linkerExe: "wcl386", 
-     linkTmpl: "$options $buildgui $builddll -fe=$exefile $objfiles ", 
-     includeCmd: " -i=", 
-     debug: " -d2 ", 
-     pic: "", 
-     asmStmtFrmt: "__asm{$n$1$n}$n", 
-     props: {hasCpp}), 
-    (name: "vcc", 
-     objExt: "obj", 
-     optSpeed: " /Ogityb2 /G7 /arch:SSE2 ", 
-     optSize: " /O1 /G7 ", 
-     compilerExe: "cl", 
-     compileTmpl: "/c $options $include /Fo$objfile $file", 
-     buildGui: " /link /SUBSYSTEM:WINDOWS ", 
-     buildDll: " /LD", 
-     linkerExe: "cl", 
-     linkTmpl: "$options $builddll /Fe$exefile $objfiles $buildgui", 
-     includeCmd: " /I", 
-     debug: " /GZ /Zi ", 
-     pic: "", 
-     asmStmtFrmt: "__asm{$n$1$n}$n", 
-     props: {hasCpp, hasAssume}), 
-    (name: "tcc", 
-     objExt: "o", 
-     optSpeed: "", 
-     optSize: "", 
-     compilerExe: "tcc", 
-     compileTmpl: "-c $options $include -o $objfile $file", 
-     buildGui: "UNAVAILABLE!", 
-     buildDll: " -shared", 
-     linkerExe: "tcc", 
-     linkTmpl: "-o $exefile $options $buildgui $builddll $objfiles", 
-     includeCmd: " -I", 
-     debug: " -g ", 
-     pic: "", 
-     asmStmtFrmt: "__asm{$n$1$n}$n", 
-     props: {hasSwitchRange, hasComputedGoto}), 
-    (name: "pcc", # Pelles C
-     objExt: "obj", 
-     optSpeed: " -Ox ", 
-     optSize: " -Os ", 
-     compilerExe: "cc", 
-     compileTmpl: "-c $options $include -Fo$objfile $file", 
-     buildGui: " -SUBSYSTEM:WINDOWS", 
-     buildDll: " -DLL", 
-     linkerExe: "cc", 
-     linkTmpl: "$options $buildgui $builddll -OUT:$exefile $objfiles", 
-     includeCmd: " -I", 
-     debug: " -Zi ", 
-     pic: "", 
-     asmStmtFrmt: "__asm{$n$1$n}$n", 
-     props: {}), 
-    (name: "ucc", 
-     objExt: "o", 
-     optSpeed: " -O3 ", 
-     optSize: " -O1 ", 
-     compilerExe: "cc", 
-     compileTmpl: "-c $options $include -o $objfile $file", 
-     buildGui: "", 
-     buildDll: " -shared ", 
-     linkerExe: "cc", 
-     linkTmpl: "-o $exefile $buildgui $builddll $objfiles $options", 
-     includeCmd: " -I", 
-     debug: "", 
-     pic: "", 
-     asmStmtFrmt: "__asm{$n$1$n}$n", 
-     props: {}), 
-    (name: "icc", 
-     objExt: "o", 
-     optSpeed: " -O3 ", 
-     optSize: " -Os ", 
-     compilerExe: "icc", 
-     compileTmpl: "-c $options $include -o $objfile $file", 
-     buildGui: " -mwindows", 
-     buildDll: " -mdll", 
-     linkerExe: "icc", 
-     linkTmpl: "$options $buildgui $builddll -o $exefile $objfiles", 
-     includeCmd: " -I", 
-     debug: "", 
-     pic: "-fPIC", 
-     asmStmtFrmt: "asm($1);$n", 
-     props: {hasSwitchRange, hasComputedGoto, hasCpp}), 
-    (name: "gpp", 
-     objExt: "o", 
-     optSpeed: " -O3 -ffast-math ", 
-     optSize: " -Os -ffast-math ", 
-     compilerExe: "g++", 
-     compileTmpl: "-c $options $include -o $objfile $file", 
-     buildGui: " -mwindows", 
-     buildDll: " -mdll", 
-     linkerExe: "g++", 
-     linkTmpl: "$buildgui $builddll -o $exefile $objfiles $options", 
-     includeCmd: " -I", 
-     debug: " -g ", 
-     pic: "-fPIC", 
-     asmStmtFrmt: "asm($1);$n", 
-     props: {hasSwitchRange, hasComputedGoto, hasCpp})]
-
-var ccompiler*: TSystemCC = ccGcc # the used compiler
+    gcc(),
+    llvmGcc(),
+    clang(),
+    lcc(),
+    bcc(),
+    dmc(),
+    wcc(),
+    vcc(),
+    tcc(),
+    pcc(),
+    ucc(),
+    icc(),
+    gpp() ]
 
 const               
   hExt* = "h"
 
-var cExt*: string = "c" # extension of generated C/C++ files
-                        # (can be changed to .cpp later)
+var
+  cCompiler* = ccGcc # the used compiler
+
+  cExt* = "c" # extension of generated C/C++ files
+              # (can be changed to .cpp later)
+  
+  cIncludes*: seq[string] = @[] # list of directories to search for included files
+  cLibs*: seq[string] = @[] # list of directories to search for lib files
+  cLinkedLibs*: seq[string] = @[] # list of libraries to link
 
 # implementation
 
+when defined(windows):
+  var libNameTmpl = "$1.lib"
+else:
+  var libNameTmpl = "lib$1.a"
+
 var 
   toLink, toCompile, externalToCompile: TLinkedList
   linkOptions: string = ""
@@ -363,6 +430,11 @@ const
 
 var fileCounter: int
 
+proc add(s: var string, many: openarray[string]) =
+  # XXX: is there something like C++'s reserve?
+  # We can use it here to avoid multiple reallocations
+  for x in items(many): s.add x
+
 proc getCompileCFileCmd*(cfilename: string, isExternal: bool = false): string = 
   var 
     cfile, objfile, options, includeCmd, compilePattern, key, trunk, exe: string
@@ -396,6 +468,10 @@ proc getCompileCFileCmd*(cfilename: string, isExternal: bool = false): string =
     includeCmd = cc[c].includeCmd # this is more complex than needed, but
                                   # a workaround of a FPC bug...
     add(includeCmd, quoteIfContainsWhite(libpath))
+
+    for includeDir in items(cIncludes):
+      includeCmd.add cc[c].includeCmd, includeDir.quoteIfContainsWhite
+
     compilePattern = JoinPath(ccompilerpath, exe)
   else: 
     includeCmd = ""
@@ -453,47 +529,57 @@ proc CallCCompiler*(projectfile: string) =
       res = execProcesses(cmds, {poUseShell, poParentStreams}, 
                           gNumberOfProcessors)
     if res != 0: rawMessage(errExecutionOfProgramFailed, [])
-  if optNoLinking notin gGlobalOptions: 
+  if optNoLinking notin gGlobalOptions:
     # call the linker:
-    var linkerExe = getConfigVar(cc[c].name & ".linkerexe")
-    if len(linkerExe) == 0: linkerExe = cc[c].linkerExe
-    if targetOS == osWindows: linkerExe = addFileExt(linkerExe, "exe")
-    if (platform.hostOS != targetOS): linkCmd = quoteIfContainsWhite(linkerExe)
-    else: linkCmd = quoteIfContainsWhite(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 targetOS == platform.hostOS: 
-      exefile = joinPath(splitFile(projectFile).dir, exefile)
-    exefile = quoteIfContainsWhite(exefile)
     var it = PStrEntry(toLink.head)
     var objfiles = ""
-    while it != nil: 
+    while it != nil:
       add(objfiles, ' ')
-      if targetOS == platform.hostOS: 
+      if targetOS == platform.hostOS:
         add(objfiles, quoteIfContainsWhite(addFileExt(it.data, cc[ccompiler].objExt)))
-      else: 
+      else:
         add(objfiles, quoteIfContainsWhite(addFileExt(it.data, cc[ccompiler].objExt)))
       it = PStrEntry(it.next)
-    linkCmd = quoteIfContainsWhite(linkCmd % ["builddll", builddll, 
-        "buildgui", buildgui, "options", linkOptions, "objfiles", objfiles, 
-        "exefile", exefile, "nimrod", getPrefixDir(), "lib", libpath])
-    add(linkCmd, ' ')
-    addf(linkCmd, cc[c].linkTmpl, ["builddll", builddll, 
-        "buildgui", buildgui, "options", linkOptions, 
-        "objfiles", objfiles, "exefile", exefile, 
-        "nimrod", quoteIfContainsWhite(getPrefixDir()), 
-        "lib", quoteIfContainsWhite(libpath)])
-    if not (optCompileOnly in gGlobalOptions): execExternalProgram(linkCmd)
-  else: 
+
+    if optGenStaticLib in gGlobalOptions:
+      linkcmd = cc[c].buildLib % ["libfile", (libNameTmpl % projectName), "objfiles", objfiles]
+      if optCompileOnly notin gGlobalOptions: execExternalProgram(linkCmd)
+    else:
+      var linkerExe = getConfigVar(cc[c].name & ".linkerexe")
+      if len(linkerExe) == 0: linkerExe = cc[c].linkerExe
+      if targetOS == osWindows: linkerExe = addFileExt(linkerExe, "exe")
+      if (platform.hostOS != targetOS): linkCmd = quoteIfContainsWhite(linkerExe)
+      else: linkCmd = quoteIfContainsWhite(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 targetOS == platform.hostOS:
+        exefile = joinPath(splitFile(projectFile).dir, exefile)
+      exefile = quoteIfContainsWhite(exefile)
+      for linkedLib in items(cLinkedLibs):
+        linkOptions.add(cc[c].linkLibCmd % linkedLib.quoteIfContainsWhite)
+      for libDir in items(cLibs):
+        linkOptions.add cc[c].linkDirCmd, libDir.quoteIfContainsWhite
+
+      linkCmd = quoteIfContainsWhite(linkCmd % ["builddll", builddll,
+          "buildgui", buildgui, "options", linkOptions, "objfiles", objfiles,
+          "exefile", exefile, "nimrod", getPrefixDir(), "lib", libpath])
+      linkCmd.add ' '
+      addf(linkCmd, cc[c].linkTmpl, ["builddll", builddll,
+          "buildgui", buildgui, "options", linkOptions,
+          "objfiles", objfiles, "exefile", exefile,
+          "nimrod", quoteIfContainsWhite(getPrefixDir()),
+          "lib", quoteIfContainsWhite(libpath)])
+      if optCompileOnly notin gGlobalOptions: execExternalProgram(linkCmd)
+  else:
     linkCmd = ""
-  if optGenScript in gGlobalOptions: 
+  if optGenScript in gGlobalOptions:
     app(script, linkCmd)
     app(script, tnl)
     generateScript(projectFile, script)