implemented a new localPassc pragma (#12706)

This commit is contained in:
Andreas Rumpf 2019-11-22 14:20:15 +01:00 • committed by GitHub
commit 64e8f050e1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 48 additions and 12 deletions

View file

@ -79,6 +79,9 @@
generated JavaScript. generated JavaScript.
- The Nim compiler now supports the ``--asm`` command option for easier - The Nim compiler now supports the ``--asm`` command option for easier
inspection of the produced assembler code. inspection of the produced assembler code.
- The Nim compiler now supports a new pragma called ``.localPassc`` to
pass specific compiler options to the C(++) backend for the C(++) file
that was produced from the current Nim module.
## Bugfixes ## Bugfixes

View file

@ -14,7 +14,7 @@
import import
ropes, os, strutils, osproc, platform, condsyms, options, msgs, ropes, os, strutils, osproc, platform, condsyms, options, msgs,
lineinfos, std / sha1, streams, pathutils, sequtils, times lineinfos, std / sha1, streams, pathutils, sequtils, times, strtabs
type type
TInfoCCProp* = enum # properties of the C compiler: TInfoCCProp* = enum # properties of the C compiler:
@ -471,6 +471,13 @@ proc toObjFile*(conf: ConfigRef; filename: AbsoluteFile): AbsoluteFile =
proc addFileToCompile*(conf: ConfigRef; cf: Cfile) = proc addFileToCompile*(conf: ConfigRef; cf: Cfile) =
conf.toCompile.add(cf) conf.toCompile.add(cf)
proc addLocalCompileOption*(conf: ConfigRef; option: string; nimfile: AbsoluteFile) =
let key = completeCfilePath(conf, withPackageName(conf, nimfile)).string
var value = conf.cfileSpecificOptions.getOrDefault(key)
if strutils.find(value, option, 0) < 0:
addOpt(value, option)
conf.cfileSpecificOptions[key] = value
proc resetCompilationLists*(conf: ConfigRef) = proc resetCompilationLists*(conf: ConfigRef) =
conf.toCompile.setLen 0 conf.toCompile.setLen 0
## XXX: we must associate these with their originating module ## XXX: we must associate these with their originating module
@ -523,8 +530,10 @@ proc noAbsolutePaths(conf: ConfigRef): bool {.inline.} =
# `optGenMapping` is included here for niminst. # `optGenMapping` is included here for niminst.
result = conf.globalOptions * {optGenScript, optGenMapping} != {} result = conf.globalOptions * {optGenScript, optGenMapping} != {}
proc cFileSpecificOptions(conf: ConfigRef; nimname: string): string = proc cFileSpecificOptions(conf: ConfigRef; nimname, fullNimFile: string): string =
result = conf.compileOptions result = conf.compileOptions
addOpt(result, conf.cfileSpecificOptions.getOrDefault(fullNimFile))
for option in conf.compileOptionsCmd: for option in conf.compileOptionsCmd:
if strutils.find(result, option, 0) < 0: if strutils.find(result, option, 0) < 0:
addOpt(result, option) addOpt(result, option)
@ -545,7 +554,7 @@ proc cFileSpecificOptions(conf: ConfigRef; nimname: string): string =
if existsConfigVar(conf, key): addOpt(result, getConfigVar(conf, key)) if existsConfigVar(conf, key): addOpt(result, getConfigVar(conf, key))
proc getCompileOptions(conf: ConfigRef): string = proc getCompileOptions(conf: ConfigRef): string =
result = cFileSpecificOptions(conf, "__dummy__") result = cFileSpecificOptions(conf, "__dummy__", "__dummy__")
proc vccplatform(conf: ConfigRef): string = proc vccplatform(conf: ConfigRef): string =
# VCC specific but preferable over the config hacks people # VCC specific but preferable over the config hacks people
@ -589,7 +598,9 @@ proc getLinkerExe(conf: ConfigRef; compiler: TSystemCC): string =
proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile, proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile,
isMainFile = false; produceOutput = false): string = isMainFile = false; produceOutput = false): string =
var c = conf.cCompiler var c = conf.cCompiler
var options = cFileSpecificOptions(conf, cfile.nimname) # We produce files like module.nim.cpp, so the absolute Nim filename is not
# cfile.name but `cfile.cname.changeFileExt("")`:
var options = cFileSpecificOptions(conf, cfile.nimname, cfile.cname.changeFileExt("").string)
var exe = getConfigVar(conf, c, ".exe") var exe = getConfigVar(conf, c, ".exe")
if exe.len == 0: exe = getCompilerExe(conf, c, cfile.cname) if exe.len == 0: exe = getCompilerExe(conf, c, cfile.cname)

View file

@ -239,7 +239,7 @@ type
outFile*: RelativeFile outFile*: RelativeFile
outDir*: AbsoluteDir outDir*: AbsoluteDir
prefixDir*, libpath*, nimcacheDir*: AbsoluteDir prefixDir*, libpath*, nimcacheDir*: AbsoluteDir
dllOverrides, moduleOverrides*: StringTableRef dllOverrides, moduleOverrides*, cfileSpecificOptions*: StringTableRef
projectName*: string # holds a name like 'nim' projectName*: string # holds a name like 'nim'
projectPath*: AbsoluteDir # holds a path like /home/alice/projects/nim/compiler/ projectPath*: AbsoluteDir # holds a path like /home/alice/projects/nim/compiler/
projectFull*: AbsoluteFile # projectPath/projectName projectFull*: AbsoluteFile # projectPath/projectName
@ -347,6 +347,7 @@ proc newConfigRef*(): ConfigRef =
libpath: AbsoluteDir"", nimcacheDir: AbsoluteDir"", libpath: AbsoluteDir"", nimcacheDir: AbsoluteDir"",
dllOverrides: newStringTable(modeCaseInsensitive), dllOverrides: newStringTable(modeCaseInsensitive),
moduleOverrides: newStringTable(modeStyleInsensitive), moduleOverrides: newStringTable(modeStyleInsensitive),
cfileSpecificOptions: newStringTable(modeCaseSensitive),
projectName: "", # holds a name like 'nim' projectName: "", # holds a name like 'nim'
projectPath: AbsoluteDir"", # holds a path like /home/alice/projects/nim/compiler/ projectPath: AbsoluteDir"", # holds a path like /home/alice/projects/nim/compiler/
projectFull: AbsoluteFile"", # projectPath/projectName projectFull: AbsoluteFile"", # projectPath/projectName

View file

@ -46,7 +46,7 @@ const
wWarnings, wHints, wWarnings, wHints,
wLineDir, wStackTrace, wLineTrace, wOptimization, wHint, wWarning, wError, wLineDir, wStackTrace, wLineTrace, wOptimization, wHint, wWarning, wError,
wFatal, wDefine, wUndef, wCompile, wLink, wLinksys, wPure, wPush, wPop, wFatal, wDefine, wUndef, wCompile, wLink, wLinksys, wPure, wPush, wPop,
wPassl, wPassc, wPassl, wPassc, wLocalPassc,
wDeadCodeElimUnused, # deprecated, always on wDeadCodeElimUnused, # deprecated, always on
wDeprecated, wDeprecated,
wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll, wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
@ -998,6 +998,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
let s = expectStrLit(c, it) let s = expectStrLit(c, it)
extccomp.addCompileOption(c.config, s) extccomp.addCompileOption(c.config, s)
recordPragma(c, it, "passc", s) recordPragma(c, it, "passc", s)
of wLocalPassc:
assert sym != nil and sym.kind == skModule
let s = expectStrLit(c, it)
extccomp.addLocalCompileOption(c.config, s, toFullPathConsiderDirty(c.config, sym.info.fileIndex))
recordPragma(c, it, "localpassl", s)
of wPush: of wPush:
processPush(c, n, i + 1) processPush(c, n, i + 1)
result = true result = true

View file

@ -851,6 +851,8 @@ proc replay(g: ModuleGraph; module: PSym; n: PNode) =
extccomp.addLinkOption(g.config, n[1].strVal) extccomp.addLinkOption(g.config, n[1].strVal)
of "passc": of "passc":
extccomp.addCompileOption(g.config, n[1].strVal) extccomp.addCompileOption(g.config, n[1].strVal)
of "localpassc":
extccomp.addLocalCompileOption(g.config, n[1].strVal, toFullPathConsiderDirty(g.config, module.info.fileIndex))
of "cppdefine": of "cppdefine":
options.cppDefine(g.config, n[1].strVal) options.cppDefine(g.config, n[1].strVal)
of "inc": of "inc":

View file

@ -58,7 +58,7 @@ type
wSafecode, wPackage, wNoForward, wReorder, wNoRewrite, wNoDestroy, wSafecode, wPackage, wNoForward, wReorder, wNoRewrite, wNoDestroy,
wPragma, wPragma,
wCompileTime, wNoInit, wCompileTime, wNoInit,
wPassc, wPassl, wBorrow, wDiscardable, wPassc, wPassl, wLocalPassc, wBorrow, wDiscardable,
wFieldChecks, wFieldChecks,
wSubsChar, wAcyclic, wShallow, wUnroll, wLinearScanEnd, wComputedGoto, wSubsChar, wAcyclic, wShallow, wUnroll, wLinearScanEnd, wComputedGoto,
wInjectStmt, wExperimental, wInjectStmt, wExperimental,
@ -146,7 +146,7 @@ const
"safecode", "package", "noforward", "reorder", "norewrite", "nodestroy", "safecode", "package", "noforward", "reorder", "norewrite", "nodestroy",
"pragma", "pragma",
"compiletime", "noinit", "compiletime", "noinit",
"passc", "passl", "borrow", "discardable", "fieldchecks", "passc", "passl", "localpassc", "borrow", "discardable", "fieldchecks",
"subschar", "acyclic", "shallow", "unroll", "linearscanend", "subschar", "acyclic", "shallow", "unroll", "linearscanend",
"computedgoto", "injectstmt", "experimental", "computedgoto", "injectstmt", "experimental",
"write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit", "write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit",
@ -209,4 +209,5 @@ proc canonPragmaSpelling*(w: TSpecialWord): string =
of wImplicitStatic: "implicitStatic" of wImplicitStatic: "implicitStatic"
of wCodegenDecl: "codegenDecl" of wCodegenDecl: "codegenDecl"
of wLiftLocals: "liftLocals" of wLiftLocals: "liftLocals"
of wLocalPassc: "localPassc"
else: specialWords[w] else: specialWords[w]

View file

@ -6560,18 +6560,31 @@ The ``link`` pragma can be used to link an additional file with the project:
PassC pragma PassC pragma
------------ ------------
The ``passC`` pragma can be used to pass additional parameters to the C The ``passc`` pragma can be used to pass additional parameters to the C
compiler like you would using the commandline switch ``--passC``: compiler like you would using the commandline switch ``--passc``:
.. code-block:: Nim .. code-block:: Nim
{.passC: "-Wall -Werror".} {.passc: "-Wall -Werror".}
Note that you can use ``gorge`` from the `system module <system.html>`_ to Note that you can use ``gorge`` from the `system module <system.html>`_ to
embed parameters from an external command that will be executed embed parameters from an external command that will be executed
during semantic analysis: during semantic analysis:
.. code-block:: Nim .. code-block:: Nim
{.passC: gorge("pkg-config --cflags sdl").} {.passc: gorge("pkg-config --cflags sdl").}
LocalPassc pragma
-----------------
The ``localPassc`` pragma can be used to pass additional parameters to the C
compiler, but only for the C/C++ file that is produced from the Nim module
the pragma resides in:
.. code-block:: Nim
# Module A.nim
# Produces: A.nim.cpp
{.localPassc: "-Wall -Werror".} # Passed when compiling A.nim.cpp
PassL pragma PassL pragma
------------ ------------