summary refs log tree commit diff stats
path: root/compiler/extccomp.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/extccomp.nim')
-rw-r--r--compiler/extccomp.nim183
1 files changed, 101 insertions, 82 deletions
diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim
index ad9c38904..26f0318ee 100644
--- a/compiler/extccomp.nim
+++ b/compiler/extccomp.nim
@@ -15,9 +15,9 @@
 import
   lists, ropes, os, strutils, osproc, platform, condsyms, options, msgs, crc
 
-type 
-  TSystemCC* = enum 
-    ccNone, ccGcc, ccLLVM_Gcc, ccCLang, ccLcc, ccBcc, ccDmc, ccWcc, ccVcc, 
+type
+  TSystemCC* = enum
+    ccNone, ccGcc, ccLLVM_Gcc, ccCLang, ccLcc, ccBcc, ccDmc, ccWcc, ccVcc,
     ccTcc, ccPcc, ccUcc, ccIcl
   TInfoCCProp* = enum         # properties of the C compiler:
     hasSwitchRange,           # CC allows ranges in switch statements (GNU C)
@@ -54,7 +54,7 @@ type
     props: TInfoCCProps] # properties of the C compiler
 
 
-# Configuration settings for various compilers. 
+# 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;
 
@@ -136,7 +136,7 @@ compiler icl:
     result = vcc()
   else:
     result = gcc()
-    
+
   result.name = "icl"
   result.compilerExe = "icl"
   result.linkerExe = "icl"
@@ -317,7 +317,7 @@ compiler ucc:
     packedPragma: "", # XXX: not supported yet
     props: {})
 
-const 
+const
   CC*: array[succ(low(TSystemCC))..high(TSystemCC), TInfoCC] = [
     gcc(),
     llvmGcc(),
@@ -332,7 +332,6 @@ const
     ucc(),
     icl()]
 
-const
   hExt* = ".h"
 
 var
@@ -347,7 +346,7 @@ var
 proc libNameTmpl(): string {.inline.} =
   result = if targetOS == osWindows: "$1.lib" else: "lib$1.a"
 
-var 
+var
   toLink, toCompile, externalToCompile: TLinkedList
   linkOptions: string = ""
   compileOptions: string = ""
@@ -356,19 +355,28 @@ var
 proc nameToCC*(name: string): TSystemCC =
   ## Returns the kind of compiler referred to by `name`, or ccNone
   ## if the name doesn't refer to any known compiler.
-  for i in countup(succ(ccNone), high(TSystemCC)): 
-    if cmpIgnoreStyle(name, CC[i].name) == 0: 
+  for i in countup(succ(ccNone), high(TSystemCC)):
+    if cmpIgnoreStyle(name, CC[i].name) == 0:
       return i
   result = ccNone
 
 proc getConfigVar(c: TSystemCC, suffix: string): string =
   # use ``cpu.os.cc`` for cross compilation, unless ``--compileOnly`` is given
   # for niminst support
-  let fullSuffix = (if gCmd == cmdCompileToCpp: ".cpp" & suffix else: suffix)
+  let fullSuffix =
+    if gCmd == cmdCompileToCpp:
+      ".cpp" & suffix
+    elif gCmd == cmdCompileToOC:
+      ".objc" & suffix
+    elif gCmd == cmdCompileToJS:
+      ".js" & suffix
+    else:
+      suffix
+
   if (platform.hostOS != targetOS or platform.hostCPU != targetCPU) and
       optCompileOnly notin gGlobalOptions:
-    let fullCCname = platform.CPU[targetCPU].name & '.' & 
-                     platform.OS[targetOS].name & '.' & 
+    let fullCCname = platform.CPU[targetCPU].name & '.' &
+                     platform.OS[targetOS].name & '.' &
                      CC[c].name & fullSuffix
     result = getConfigVar(fullCCname)
     if result.len == 0:
@@ -377,39 +385,39 @@ proc getConfigVar(c: TSystemCC, suffix: string): string =
   else:
     result = getConfigVar(CC[c].name & fullSuffix)
 
-proc setCC*(ccname: string) = 
+proc setCC*(ccname: string) =
   cCompiler = nameToCC(ccname)
   if cCompiler == ccNone: rawMessage(errUnknownCcompiler, ccname)
   compileOptions = getConfigVar(cCompiler, ".options.always")
-  linkOptions = getConfigVar(cCompiler, ".options.linker")
+  linkOptions = ""
   ccompilerpath = getConfigVar(cCompiler, ".path")
   for i in countup(low(CC), high(CC)): undefSymbol(CC[i].name)
   defineSymbol(CC[cCompiler].name)
 
-proc addOpt(dest: var string, src: string) = 
+proc addOpt(dest: var string, src: string) =
   if len(dest) == 0 or dest[len(dest)-1] != ' ': add(dest, " ")
   add(dest, src)
 
-proc addLinkOption*(option: string) = 
-  if find(linkOptions, option, 0) < 0: addOpt(linkOptions, option)
+proc addLinkOption*(option: string) =
+  addOpt(linkOptions, option)
 
-proc addCompileOption*(option: string) = 
-  if strutils.find(compileOptions, option, 0) < 0: 
+proc addCompileOption*(option: string) =
+  if strutils.find(compileOptions, option, 0) < 0:
     addOpt(compileOptions, option)
 
-proc initVars*() = 
+proc initVars*() =
   # we need to define the symbol here, because ``CC`` may have never been set!
   for i in countup(low(CC), high(CC)): undefSymbol(CC[i].name)
   defineSymbol(CC[cCompiler].name)
   addCompileOption(getConfigVar(cCompiler, ".options.always"))
-  addLinkOption(getConfigVar(cCompiler, ".options.linker"))
+  #addLinkOption(getConfigVar(cCompiler, ".options.linker"))
   if len(ccompilerpath) == 0:
     ccompilerpath = getConfigVar(cCompiler, ".path")
 
-proc completeCFilePath*(cfile: string, createSubDir: bool = true): string = 
+proc completeCFilePath*(cfile: string, createSubDir: bool = true): string =
   result = completeGeneratedFilePath(cfile, createSubDir)
 
-proc toObjFile*(filename: string): string = 
+proc toObjFile*(filename: string): string =
   # Object file for compilation
   result = changeFileExt(filename, CC[cCompiler].objExt)
 
@@ -429,30 +437,34 @@ proc addFileToLink*(filename: string) =
   prependStr(toLink, filename)
   # BUGFIX: was ``appendStr``
 
-proc execExternalProgram*(cmd: string, prettyCmd = "") =
+proc execWithEcho(cmd: string, prettyCmd = ""): int =
   if optListCmd in gGlobalOptions or gVerbosity > 0:
     if prettyCmd != "":
       msgWriteln(prettyCmd)
     else:
       msgWriteln(cmd)
-  if execCmd(cmd) != 0: rawMessage(errExecutionOfProgramFailed, "")
+  result = execCmd(cmd)
 
-proc generateScript(projectFile: string, script: PRope) = 
+proc execExternalProgram*(cmd: string, prettyCmd = "") =
+  if execWithEcho(cmd, prettyCmd) != 0:
+    rawMessage(errExecutionOfProgramFailed, "")
+
+proc generateScript(projectFile: string, script: Rope) =
   let (dir, name, ext) = splitFile(projectFile)
-  writeRope(script, dir / addFileExt("compile_" & name, 
+  writeRope(script, dir / addFileExt("compile_" & name,
                                      platform.OS[targetOS].scriptExt))
 
-proc getOptSpeed(c: TSystemCC): string = 
+proc getOptSpeed(c: TSystemCC): string =
   result = getConfigVar(c, ".options.speed")
   if result == "":
     result = CC[c].optSpeed   # use default settings from this file
 
-proc getDebug(c: TSystemCC): string = 
+proc getDebug(c: TSystemCC): string =
   result = getConfigVar(c, ".options.debug")
   if result == "":
     result = CC[c].debug      # use default settings from this file
 
-proc getOptSize(c: TSystemCC): string = 
+proc getOptSize(c: TSystemCC): string =
   result = getConfigVar(c, ".options.size")
   if result == "":
     result = CC[c].optSize    # use default settings from this file
@@ -464,7 +476,7 @@ proc noAbsolutePaths: bool {.inline.} =
   # `optGenMapping` is included here for niminst.
   result = gGlobalOptions * {optGenScript, optGenMapping} != {}
 
-const 
+const
   specialFileA = 42
   specialFileB = 42
 
@@ -476,7 +488,7 @@ proc add(s: var string, many: openArray[string]) =
 proc cFileSpecificOptions(cfilename: string): string =
   result = compileOptions
   var trunk = splitFile(cfilename).name
-  if optCDebug in gGlobalOptions: 
+  if optCDebug in gGlobalOptions:
     var key = trunk & ".debug"
     if existsConfigVar(key): addOpt(result, getConfigVar(key))
     else: addOpt(result, getDebug(cCompiler))
@@ -516,17 +528,17 @@ proc getLinkerExe(compiler: TSystemCC): string =
            elif gMixedMode and gCmd != cmdCompileToCpp: CC[compiler].cppCompiler
            else: compiler.getCompilerExe
 
-proc getCompileCFileCmd*(cfilename: string, isExternal = false): string = 
+proc getCompileCFileCmd*(cfilename: string, isExternal = false): string =
   var c = cCompiler
   var options = cFileSpecificOptions(cfilename)
   var exe = getConfigVar(c, ".exe")
   if exe.len == 0: exe = c.getCompilerExe
-  
+
   if needsExeExt(): exe = addFileExt(exe, "exe")
   if optGenDynLib in gGlobalOptions and
       ospNeedsPIC in platform.OS[targetOS].props:
     add(options, ' ' & CC[c].pic)
-  
+
   var includeCmd, compilePattern: string
   if not noAbsolutePaths():
     # compute include paths:
@@ -539,7 +551,7 @@ proc getCompileCFileCmd*(cfilename: string, isExternal = false): string =
   else:
     includeCmd = ""
     compilePattern = c.getCompilerExe
-  
+
   var cfile = if noAbsolutePaths(): extractFilename(cfilename)
               else: cfilename
   var objfile = if not isExternal or noAbsolutePaths():
@@ -547,15 +559,16 @@ proc getCompileCFileCmd*(cfilename: string, isExternal = false): string =
                 else:
                   completeCFilePath(toObjFile(cfile))
   objfile = quoteShell(objfile)
+  cfile = quoteShell(cfile)
   result = quoteShell(compilePattern % [
     "file", cfile, "objfile", objfile, "options", options,
-    "include", includeCmd, "nimrod", getPrefixDir(),
+    "include", includeCmd, "nim", getPrefixDir(),
     "nim", getPrefixDir(), "lib", libpath])
   add(result, ' ')
   addf(result, CC[c].compileTmpl, [
     "file", cfile, "objfile", objfile,
     "options", options, "include", includeCmd,
-    "nimrod", quoteShell(getPrefixDir()),
+    "nim", quoteShell(getPrefixDir()),
     "nim", quoteShell(getPrefixDir()),
     "lib", quoteShell(libpath)])
 
@@ -567,11 +580,14 @@ proc footprint(filename: string): TCrc32 =
       extccomp.CC[extccomp.cCompiler].name ><
       getCompileCFileCmd(filename, true)
 
-proc externalFileChanged(filename: string): bool = 
+proc externalFileChanged(filename: string): bool =
+  if gCmd notin {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToLLVM}:
+    return false
+
   var crcFile = toGeneratedFile(filename.withPackageName, "crc")
   var currentCrc = int(footprint(filename))
   var f: File
-  if open(f, crcFile, fmRead): 
+  if open(f, crcFile, fmRead):
     var line = newStringOfCap(40)
     if not f.readLine(line): line = "0"
     close(f)
@@ -579,7 +595,7 @@ proc externalFileChanged(filename: string): bool =
     result = oldCrc != currentCrc
   else:
     result = true
-  if result: 
+  if result:
     if open(f, crcFile, fmWrite):
       f.writeln($currentCrc)
       close(f)
@@ -588,49 +604,51 @@ proc addExternalFileToCompile*(filename: string) =
   if optForceFullMake in gGlobalOptions or externalFileChanged(filename):
     appendStr(externalToCompile, filename)
 
-proc compileCFile(list: TLinkedList, script: var PRope, cmds: var TStringSeq,
+proc compileCFile(list: TLinkedList, script: var Rope, cmds: var TStringSeq,
                   prettyCmds: var TStringSeq, isExternal: bool) =
   var it = PStrEntry(list.head)
-  while it != nil: 
+  while it != nil:
     inc(fileCounter)          # call the C compiler for the .c file:
     var compileCmd = getCompileCFileCmd(it.data, isExternal)
-    if optCompileOnly notin gGlobalOptions: 
+    if optCompileOnly notin gGlobalOptions:
       add(cmds, compileCmd)
       let (dir, name, ext) = splitFile(it.data)
       add(prettyCmds, "CC: " & name)
-    if optGenScript in gGlobalOptions: 
-      app(script, compileCmd)
-      app(script, tnl)
+    if optGenScript in gGlobalOptions:
+      add(script, compileCmd)
+      add(script, tnl)
     it = PStrEntry(it.next)
 
 proc callCCompiler*(projectfile: string) =
-  var 
+  var
     linkCmd, buildgui, builddll: string
-  if gGlobalOptions * {optCompileOnly, optGenScript} == {optCompileOnly}: 
+  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 script: PRope = nil
+  var script: Rope = nil
   var cmds: TStringSeq = @[]
   var prettyCmds: TStringSeq = @[]
   let prettyCb = proc (idx: int) =
     echo prettyCmds[idx]
   compileCFile(toCompile, script, cmds, prettyCmds, false)
   compileCFile(externalToCompile, script, cmds, prettyCmds, true)
-  if optCompileOnly notin gGlobalOptions: 
+  if optCompileOnly notin gGlobalOptions:
     if gNumberOfProcessors == 0: gNumberOfProcessors = countProcessors()
     var res = 0
-    if gNumberOfProcessors <= 1: 
-      for i in countup(0, high(cmds)): res = max(execCmd(cmds[i]), res)
+    if gNumberOfProcessors <= 1:
+      for i in countup(0, high(cmds)):
+        res = execWithEcho(cmds[i])
+        if res != 0: rawMessage(errExecutionOfProgramFailed, [])
     elif optListCmd in gGlobalOptions or gVerbosity > 1:
-      res = execProcesses(cmds, {poEchoCmd, poUseShell, poParentStreams},
+      res = execProcesses(cmds, {poEchoCmd, poUsePath, poParentStreams},
                           gNumberOfProcessors)
     elif gVerbosity == 1:
-      res = execProcesses(cmds, {poUseShell, poParentStreams},
+      res = execProcesses(cmds, {poUsePath, poParentStreams},
                           gNumberOfProcessors, prettyCb)
     else:
-      res = execProcesses(cmds, {poUseShell, poParentStreams},
+      res = execProcesses(cmds, {poUsePath, poParentStreams},
                           gNumberOfProcessors)
     if res != 0:
       if gNumberOfProcessors <= 1:
@@ -667,21 +685,22 @@ proc callCCompiler*(projectfile: string) =
       else:
         exefile = splitFile(projectfile).name & platform.OS[targetOS].exeExt
         builddll = ""
-      if options.outFile.len > 0: 
+      if options.outFile.len > 0:
         exefile = options.outFile.expandTilde
       if not noAbsolutePaths():
         if not exefile.isAbsolute():
           exefile = joinPath(splitFile(projectfile).dir, exefile)
       exefile = quoteShell(exefile)
-      let linkOptions = getLinkOptions()
+      let linkOptions = getLinkOptions() & " " &
+                        getConfigVar(cCompiler, ".options.linker")
       linkCmd = quoteShell(linkCmd % ["builddll", builddll,
           "buildgui", buildgui, "options", linkOptions, "objfiles", objfiles,
-          "exefile", exefile, "nimrod", getPrefixDir(), "lib", libpath])
+          "exefile", exefile, "nim", getPrefixDir(), "lib", libpath])
       linkCmd.add ' '
       addf(linkCmd, CC[c].linkTmpl, ["builddll", builddll,
           "buildgui", buildgui, "options", linkOptions,
           "objfiles", objfiles, "exefile", exefile,
-          "nimrod", quoteShell(getPrefixDir()),
+          "nim", quoteShell(getPrefixDir()),
           "lib", quoteShell(libpath)])
     if optCompileOnly notin gGlobalOptions:
       if gVerbosity == 1:
@@ -691,30 +710,30 @@ proc callCCompiler*(projectfile: string) =
   else:
     linkCmd = ""
   if optGenScript in gGlobalOptions:
-    app(script, linkCmd)
-    app(script, tnl)
+    add(script, linkCmd)
+    add(script, tnl)
     generateScript(projectfile, script)
 
-proc genMappingFiles(list: TLinkedList): PRope = 
+proc genMappingFiles(list: TLinkedList): Rope =
   var it = PStrEntry(list.head)
-  while it != nil: 
-    appf(result, "--file:r\"$1\"$N", [toRope(it.data)])
+  while it != nil:
+    addf(result, "--file:r\"$1\"$N", [rope(it.data)])
     it = PStrEntry(it.next)
 
-proc writeMapping*(gSymbolMapping: PRope) = 
-  if optGenMapping notin gGlobalOptions: return 
-  var code = toRope("[C_Files]\n")
-  app(code, genMappingFiles(toCompile))
-  app(code, genMappingFiles(externalToCompile))
-  app(code, "\n[C_Compiler]\nFlags=")
-  app(code, strutils.escape(getCompileOptions()))
-  
-  app(code, "\n[Linker]\nFlags=")
-  app(code, strutils.escape(getLinkOptions()))
-
-  app(code, "\n[Environment]\nlibpath=")
-  app(code, strutils.escape(libpath))
-  
-  appf(code, "\n[Symbols]$n$1", [gSymbolMapping])
+proc writeMapping*(gSymbolMapping: Rope) =
+  if optGenMapping notin gGlobalOptions: return
+  var code = rope("[C_Files]\n")
+  add(code, genMappingFiles(toCompile))
+  add(code, genMappingFiles(externalToCompile))
+  add(code, "\n[C_Compiler]\nFlags=")
+  add(code, strutils.escape(getCompileOptions()))
+
+  add(code, "\n[Linker]\nFlags=")
+  add(code, strutils.escape(getLinkOptions() & " " &
+                            getConfigVar(cCompiler, ".options.linker")))
+
+  add(code, "\n[Environment]\nlibpath=")
+  add(code, strutils.escape(libpath))
+
+  addf(code, "\n[Symbols]$n$1", [gSymbolMapping])
   writeRope(code, joinPath(gProjectPath, "mapping.txt"))
-