diff options
Diffstat (limited to 'compiler/extccomp.nim')
-rw-r--r-- | compiler/extccomp.nim | 190 |
1 files changed, 109 insertions, 81 deletions
diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index bbbbbfb8e..f0e5dad11 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -16,7 +16,7 @@ import type TSystemCC* = enum ccNone, ccGcc, ccLLVM_Gcc, ccCLang, ccLcc, ccBcc, ccDmc, ccWcc, ccVcc, - ccTcc, ccPcc, ccUcc, ccIcl, ccGpp + ccTcc, ccPcc, ccUcc, ccIcl TInfoCCProp* = enum # properties of the C compiler: hasSwitchRange, # CC allows ranges in switch statements (GNU C) hasComputedGoto, # CC has computed goto (GNU C extension) @@ -33,11 +33,12 @@ type optSpeed: string, # the options for optimization for speed optSize: string, # the options for optimization for size compilerExe: string, # the compiler's executable + cppCompiler: string, # name of the C++ compiler's executable (if supported) 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 + linkerExe: string, # the linker's executable (if not matching compiler's) 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 @@ -46,6 +47,8 @@ type pic: string, # command for position independent code # used on some platforms asmStmtFrmt: string, # format of ASM statement + structStmtFmt: string, # Format for struct statement + packedPragma: string, # Attribute/pragma to make struct packed (1-byte aligned) props: TInfoCCProps] # properties of the C compiler @@ -63,11 +66,12 @@ compiler gcc: optSpeed: " -O3 -ffast-math ", optSize: " -Os -ffast-math ", compilerExe: "gcc", + cppCompiler: "g++", compileTmpl: "-c $options $include -o $objfile $file", buildGui: " -mwindows", buildDll: " -shared", buildLib: "ar rcs $libfile $objfiles", - linkerExe: "gcc", + linkerExe: "", linkTmpl: "$buildgui $builddll -o $exefile $objfiles $options", includeCmd: " -I", linkDirCmd: " -L", @@ -75,34 +79,25 @@ compiler gcc: debug: "", pic: "-fPIC", asmStmtFrmt: "asm($1);$n", + structStmtFmt: "$1 $3 $2 ", # struct|union [packed] $name + packedPragma: "__attribute__((__packed__))", props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard, hasGnuAsm, hasNakedAttribute}) - -compiler gpp: - result = gcc() - - result.name = "gpp" - result.compilerExe = "g++" - result.linkerExe = "g++" - - 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.cppCompiler = "llvm-g++" result.buildLib = "llvm-ar rcs $libfile $objfiles" - result.linkerExe = "llvm-gcc" compiler clang: result = llvmGcc() result.name = "clang" result.compilerExe = "clang" - result.linkerExe = "clang" + result.cppCompiler = "clang++" compiler vcc: result = ( @@ -111,6 +106,7 @@ compiler vcc: optSpeed: " /Ogityb2 /G7 /arch:SSE2 ", optSize: " /O1 /G7 ", compilerExe: "cl", + cppCompiler: "cl", compileTmpl: "/c $options $include /Fo$objfile $file", buildGui: " /link /SUBSYSTEM:WINDOWS ", buildDll: " /LD", @@ -123,6 +119,8 @@ compiler vcc: debug: " /GZ /Zi ", pic: "", asmStmtFrmt: "__asm{$n$1$n}$n", + structStmtFmt: "$3$n$1 $2", + packedPragma: "#pragma pack(1)", props: {hasCpp, hasAssume, hasNakedDeclspec}) compiler icl: @@ -131,7 +129,7 @@ compiler icl: result = vcc() else: result = gcc() - + result.name = "icl" result.compilerExe = "icl" result.linkerExe = "icl" @@ -143,6 +141,7 @@ compiler lcc: optSpeed: " -O -p6 ", optSize: " -O -p6 ", compilerExe: "lcc", + cppCompiler: "", compileTmpl: "$options $include -Fo$objfile $file", buildGui: " -subsystem windows", buildDll: " -dll", @@ -155,6 +154,8 @@ compiler lcc: debug: " -g5 ", pic: "", asmStmtFrmt: "_asm{$n$1$n}$n", + structStmtFmt: "$1 $2", + packedPragma: "", # XXX: not supported yet props: {}) compiler bcc: @@ -164,6 +165,7 @@ compiler bcc: optSpeed: " -O2 -6 ", optSize: " -O1 -6 ", compilerExe: "bcc32", + cppCompiler: "", compileTmpl: "-c $options $include -o$objfile $file", buildGui: " -tW", buildDll: " -tWD", @@ -176,6 +178,8 @@ compiler bcc: debug: "", pic: "", asmStmtFrmt: "__asm{$n$1$n}$n", + structStmtFmt: "$1 $2", + packedPragma: "", # XXX: not supported yet props: {hasCpp}) compiler dmc: @@ -185,6 +189,7 @@ compiler dmc: optSpeed: " -ff -o -6 ", optSize: " -ff -o -6 ", compilerExe: "dmc", + cppCompiler: "", compileTmpl: "-c $options $include -o$objfile $file", buildGui: " -L/exet:nt/su:windows", buildDll: " -WD", @@ -197,6 +202,8 @@ compiler dmc: debug: " -g ", pic: "", asmStmtFrmt: "__asm{$n$1$n}$n", + structStmtFmt: "$3$n$1 $2", + packedPragma: "#pragma pack(1)", props: {hasCpp}) compiler wcc: @@ -206,6 +213,7 @@ compiler wcc: optSpeed: " -ox -on -6 -d0 -fp6 -zW ", optSize: "", compilerExe: "wcl386", + cppCompiler: "", compileTmpl: "-c $options $include -fo=$objfile $file", buildGui: " -bw", buildDll: " -bd", @@ -218,6 +226,8 @@ compiler wcc: debug: " -d2 ", pic: "", asmStmtFrmt: "__asm{$n$1$n}$n", + structStmtFmt: "$1 $2", + packedPragma: "", # XXX: not supported yet props: {hasCpp}) compiler tcc: @@ -227,6 +237,7 @@ compiler tcc: optSpeed: "", optSize: "", compilerExe: "tcc", + cppCompiler: "", compileTmpl: "-c $options $include -o $objfile $file", buildGui: "UNAVAILABLE!", buildDll: " -shared", @@ -239,6 +250,8 @@ compiler tcc: debug: " -g ", pic: "", asmStmtFrmt: "__asm{$n$1$n}$n", + structStmtFmt: "$1 $2", + packedPragma: "", # XXX: not supported yet props: {hasSwitchRange, hasComputedGoto}) compiler pcc: @@ -249,6 +262,7 @@ compiler pcc: optSpeed: " -Ox ", optSize: " -Os ", compilerExe: "cc", + cppCompiler: "", compileTmpl: "-c $options $include -Fo$objfile $file", buildGui: " -SUBSYSTEM:WINDOWS", buildDll: " -DLL", @@ -261,6 +275,8 @@ compiler pcc: debug: " -Zi ", pic: "", asmStmtFrmt: "__asm{$n$1$n}$n", + structStmtFmt: "$1 $2", + packedPragma: "", # XXX: not supported yet props: {}) compiler ucc: @@ -270,6 +286,7 @@ compiler ucc: optSpeed: " -O3 ", optSize: " -O1 ", compilerExe: "cc", + cppCompiler: "", compileTmpl: "-c $options $include -o $objfile $file", buildGui: "", buildDll: " -shared ", @@ -282,6 +299,8 @@ compiler ucc: debug: "", pic: "", asmStmtFrmt: "__asm{$n$1$n}$n", + structStmtFmt: "$1 $2", + packedPragma: "", # XXX: not supported yet props: {}) const @@ -297,8 +316,7 @@ const tcc(), pcc(), ucc(), - icl(), - gpp()] + icl()] const hExt* = ".h" @@ -324,7 +342,7 @@ var compileOptions: string = "" ccompilerpath: string = "" -proc NameToCC*(name: string): TSystemCC = +proc nameToCC*(name: string): TSystemCC = for i in countup(succ(ccNone), high(TSystemCC)): if cmpIgnoreStyle(name, CC[i].name) == 0: return i @@ -335,8 +353,8 @@ proc getConfigVar(c: TSystemCC, suffix: string): string = # for niminst support 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 & suffix result = getConfigVar(fullCCname) if result.len == 0: @@ -346,13 +364,13 @@ proc getConfigVar(c: TSystemCC, suffix: string): string = result = getConfigVar(CC[c].name & suffix) proc setCC*(ccname: string) = - ccompiler = nameToCC(ccname) - if ccompiler == ccNone: rawMessage(errUnknownCcompiler, ccname) - compileOptions = getConfigVar(ccompiler, ".options.always") - linkOptions = getConfigVar(ccompiler, ".options.linker") - ccompilerpath = getConfigVar(ccompiler, ".path") + cCompiler = nameToCC(ccname) + if cCompiler == ccNone: rawMessage(errUnknownCcompiler, ccname) + compileOptions = getConfigVar(cCompiler, ".options.always") + linkOptions = getConfigVar(cCompiler, ".options.linker") + ccompilerpath = getConfigVar(cCompiler, ".path") for i in countup(low(CC), high(CC)): undefSymbol(CC[i].name) - defineSymbol(CC[ccompiler].name) + defineSymbol(CC[cCompiler].name) proc addOpt(dest: var string, src: string) = if len(dest) == 0 or dest[len(dest)-1] != ' ': add(dest, " ") @@ -368,20 +386,20 @@ proc addCompileOption*(option: string) = 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) + defineSymbol(CC[cCompiler].name) if gCmd == cmdCompileToCpp: cExt = ".cpp" elif gCmd == cmdCompileToOC: cExt = ".m" - addCompileOption(getConfigVar(ccompiler, ".options.always")) - addLinkOption(getConfigVar(ccompiler, ".options.linker")) - if len(ccompilerPath) == 0: - ccompilerpath = getConfigVar(ccompiler, ".path") + addCompileOption(getConfigVar(cCompiler, ".options.always")) + addLinkOption(getConfigVar(cCompiler, ".options.linker")) + if len(ccompilerpath) == 0: + ccompilerpath = getConfigVar(cCompiler, ".path") proc completeCFilePath*(cfile: string, createSubDir: bool = true): string = result = completeGeneratedFilePath(cfile, createSubDir) proc toObjFile*(filenameWithoutExt: string): string = # Object file for compilation - result = changeFileExt(filenameWithoutExt, cc[ccompiler].objExt) + result = changeFileExt(filenameWithoutExt, CC[cCompiler].objExt) proc addFileToCompile*(filename: string) = appendStr(toCompile, filename) @@ -400,28 +418,28 @@ proc addFileToLink*(filename: string) = # BUGFIX: was ``appendStr`` proc execExternalProgram*(cmd: string) = - if optListCmd in gGlobalOptions or gVerbosity > 0: MsgWriteln(cmd) + if optListCmd in gGlobalOptions or gVerbosity > 0: msgWriteln(cmd) if execCmd(cmd) != 0: rawMessage(errExecutionOfProgramFailed, "") proc generateScript(projectFile: string, script: PRope) = let (dir, name, ext) = splitFile(projectFile) - WriteRope(script, dir / addFileExt("compile_" & name, - platform.os[targetOS].scriptExt)) + writeRope(script, dir / addFileExt("compile_" & name, + platform.OS[targetOS].scriptExt)) proc getOptSpeed(c: TSystemCC): string = result = getConfigVar(c, ".options.speed") if result == "": - result = cc[c].optSpeed # use default settings from this file + result = CC[c].optSpeed # use default settings from this file proc getDebug(c: TSystemCC): string = result = getConfigVar(c, ".options.debug") if result == "": - result = cc[c].debug # use default settings from this file + result = CC[c].debug # use default settings from this file proc getOptSize(c: TSystemCC): string = result = getConfigVar(c, ".options.size") if result == "": - result = cc[c].optSize # use default settings from this file + result = CC[c].optSize # use default settings from this file proc noAbsolutePaths: bool {.inline.} = # We used to check current OS != specified OS, but this makes no sense @@ -436,78 +454,88 @@ const var fileCounter: int -proc add(s: var string, many: openarray[string]) = +proc add(s: var string, many: openArray[string]) = s.add many.join -proc CFileSpecificOptions(cfilename: string): string = +proc cFileSpecificOptions(cfilename: string): string = result = compileOptions var trunk = splitFile(cfilename).name if optCDebug in gGlobalOptions: var key = trunk & ".debug" if existsConfigVar(key): addOpt(result, getConfigVar(key)) - else: addOpt(result, getDebug(ccompiler)) + else: addOpt(result, getDebug(cCompiler)) if optOptimizeSpeed in gOptions: var key = trunk & ".speed" if existsConfigVar(key): addOpt(result, getConfigVar(key)) - else: addOpt(result, getOptSpeed(ccompiler)) + else: addOpt(result, getOptSpeed(cCompiler)) elif optOptimizeSize in gOptions: var key = trunk & ".size" if existsConfigVar(key): addOpt(result, getConfigVar(key)) - else: addOpt(result, getOptSize(ccompiler)) + else: addOpt(result, getOptSize(cCompiler)) var key = trunk & ".always" if existsConfigVar(key): addOpt(result, getConfigVar(key)) proc getCompileOptions: string = - result = CFileSpecificOptions("__dummy__") + result = cFileSpecificOptions("__dummy__") proc getLinkOptions: string = result = linkOptions for linkedLib in items(cLinkedLibs): - result.add(cc[ccompiler].linkLibCmd % linkedLib.quoteShell) + result.add(CC[cCompiler].linkLibCmd % linkedLib.quoteShell) for libDir in items(cLibs): - result.add([cc[ccompiler].linkDirCmd, libDir.quoteShell]) + result.add([CC[cCompiler].linkDirCmd, libDir.quoteShell]) proc needsExeExt(): bool {.inline.} = result = (optGenScript in gGlobalOptions and targetOS == osWindows) or (platform.hostOS == osWindows) +proc getCompilerExe(compiler: TSystemCC): string = + result = if gCmd == cmdCompileToCpp: CC[compiler].cppCompiler + else: CC[compiler].compilerExe + if result.len == 0: + rawMessage(errCompilerDoesntSupportTarget, CC[compiler].name) + +proc getLinkerExe(compiler: TSystemCC): string = + result = if CC[compiler].linkerExe.len > 0: CC[compiler].linkerExe + else: compiler.getCompilerExe + proc getCompileCFileCmd*(cfilename: string, isExternal = false): string = - var c = ccompiler - var options = CFileSpecificOptions(cfilename) + var c = cCompiler + var options = cFileSpecificOptions(cfilename) var exe = getConfigVar(c, ".exe") - if exe.len == 0: exe = cc[c].compilerExe + 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) + add(options, ' ' & CC[c].pic) var includeCmd, compilePattern: string if not noAbsolutePaths(): # compute include paths: - includeCmd = cc[c].includeCmd & quoteShell(libpath) + includeCmd = CC[c].includeCmd & quoteShell(libpath) for includeDir in items(cIncludes): - includeCmd.add([cc[c].includeCmd, includeDir.quoteShell]) + includeCmd.add([CC[c].includeCmd, includeDir.quoteShell]) - compilePattern = JoinPath(ccompilerpath, exe) + compilePattern = joinPath(ccompilerpath, exe) else: includeCmd = "" - compilePattern = cc[c].compilerExe + compilePattern = c.getCompilerExe - var cfile = if noAbsolutePaths(): extractFileName(cfilename) + var cfile = if noAbsolutePaths(): extractFilename(cfilename) else: cfilename var objfile = if not isExternal or noAbsolutePaths(): toObjFile(cfile) else: completeCFilePath(toObjFile(cfile)) - cfile = quoteShell(AddFileExt(cfile, cExt)) + cfile = quoteShell(addFileExt(cfile, cExt)) objfile = quoteShell(objfile) result = quoteShell(compilePattern % [ "file", cfile, "objfile", objfile, "options", options, "include", includeCmd, "nimrod", getPrefixDir(), "lib", libpath]) add(result, ' ') - addf(result, cc[c].compileTmpl, [ + addf(result, CC[c].compileTmpl, [ "file", cfile, "objfile", objfile, "options", options, "include", includeCmd, "nimrod", quoteShell(getPrefixDir()), @@ -517,7 +545,7 @@ proc footprint(filename: string): TCrc32 = result = crcFromFile(filename) >< platform.OS[targetOS].name >< platform.CPU[targetCPU].name >< - extccomp.CC[extccomp.ccompiler].name >< + extccomp.CC[extccomp.cCompiler].name >< getCompileCFileCmd(filename, true) proc externalFileChanged(filename: string): bool = @@ -541,7 +569,7 @@ 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 PRope, cmds: var TStringSeq, isExternal: bool) = var it = PStrEntry(list.head) while it != nil: @@ -554,18 +582,18 @@ proc CompileCFile(list: TLinkedList, script: var PRope, cmds: var TStringSeq, app(script, tnl) it = PStrEntry(it.next) -proc CallCCompiler*(projectfile: string) = +proc callCCompiler*(projectfile: string) = var linkCmd, buildgui, builddll: 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: PRope = nil var cmds: TStringSeq = @[] - CompileCFile(toCompile, script, cmds, false) - CompileCFile(externalToCompile, script, cmds, true) + compileCFile(toCompile, script, cmds, false) + compileCFile(externalToCompile, script, cmds, true) if optCompileOnly notin gGlobalOptions: if gNumberOfProcessors == 0: gNumberOfProcessors = countProcessors() var res = 0 @@ -591,40 +619,40 @@ proc CallCCompiler*(projectfile: string) = let objFile = if noAbsolutePaths(): it.data.extractFilename else: it.data add(objfiles, ' ') add(objfiles, quoteShell( - addFileExt(objFile, cc[ccompiler].objExt))) + addFileExt(objFile, CC[cCompiler].objExt))) it = PStrEntry(it.next) if optGenStaticLib in gGlobalOptions: - linkcmd = cc[c].buildLib % ["libfile", (libNameTmpl() % gProjectName), + linkCmd = CC[c].buildLib % ["libfile", (libNameTmpl() % gProjectName), "objfiles", objfiles] if optCompileOnly notin gGlobalOptions: execExternalProgram(linkCmd) else: var linkerExe = getConfigVar(c, ".linkerexe") - if len(linkerExe) == 0: linkerExe = cc[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 = "" + 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 + exefile = platform.OS[targetOS].dllFrmt % splitFile(projectfile).name + builddll = CC[c].buildDll else: - exefile = splitFile(projectFile).name & platform.os[targetOS].exeExt - buildDll = "" + exefile = splitFile(projectfile).name & platform.OS[targetOS].exeExt + builddll = "" if options.outFile.len > 0: exefile = options.outFile.expandTilde if not noAbsolutePaths(): - if not exeFile.isAbsolute(): - exefile = joinPath(splitFile(projectFile).dir, exefile) + if not exefile.isAbsolute(): + exefile = joinPath(splitFile(projectfile).dir, exefile) exefile = quoteShell(exefile) let linkOptions = getLinkOptions() linkCmd = quoteShell(linkCmd % ["builddll", builddll, "buildgui", buildgui, "options", linkOptions, "objfiles", objfiles, "exefile", exefile, "nimrod", getPrefixDir(), "lib", libpath]) linkCmd.add ' ' - addf(linkCmd, cc[c].linkTmpl, ["builddll", builddll, + addf(linkCmd, CC[c].linkTmpl, ["builddll", builddll, "buildgui", buildgui, "options", linkOptions, "objfiles", objfiles, "exefile", exefile, "nimrod", quoteShell(getPrefixDir()), @@ -635,12 +663,12 @@ proc CallCCompiler*(projectfile: string) = if optGenScript in gGlobalOptions: app(script, linkCmd) app(script, tnl) - generateScript(projectFile, script) + generateScript(projectfile, script) proc genMappingFiles(list: TLinkedList): PRope = var it = PStrEntry(list.head) while it != nil: - appf(result, "--file:r\"$1\"$N", [toRope(AddFileExt(it.data, cExt))]) + appf(result, "--file:r\"$1\"$N", [toRope(addFileExt(it.data, cExt))]) it = PStrEntry(it.next) proc writeMapping*(gSymbolMapping: PRope) = @@ -658,5 +686,5 @@ proc writeMapping*(gSymbolMapping: PRope) = app(code, strutils.escape(libpath)) appf(code, "\n[Symbols]$n$1", [gSymbolMapping]) - WriteRope(code, joinPath(gProjectPath, "mapping.txt")) + writeRope(code, joinPath(gProjectPath, "mapping.txt")) |