summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md3
-rw-r--r--compiler/extccomp.nim19
-rw-r--r--compiler/options.nim3
-rw-r--r--compiler/pragmas.nim7
-rw-r--r--compiler/rodimpl.nim2
-rw-r--r--compiler/wordrecg.nim5
-rw-r--r--doc/manual.rst21
7 files changed, 48 insertions, 12 deletions
diff --git a/changelog.md b/changelog.md
index 5b2509663..6320ec158 100644
--- a/changelog.md
+++ b/changelog.md
@@ -79,6 +79,9 @@
   generated JavaScript.
 - The Nim compiler now supports the ``--asm`` command option for easier
   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
diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim
index 5c63f246b..42020822c 100644
--- a/compiler/extccomp.nim
+++ b/compiler/extccomp.nim
@@ -14,7 +14,7 @@
 
 import
   ropes, os, strutils, osproc, platform, condsyms, options, msgs,
-  lineinfos, std / sha1, streams, pathutils, sequtils, times
+  lineinfos, std / sha1, streams, pathutils, sequtils, times, strtabs
 
 type
   TInfoCCProp* = enum         # properties of the C compiler:
@@ -471,6 +471,13 @@ proc toObjFile*(conf: ConfigRef; filename: AbsoluteFile): AbsoluteFile =
 proc addFileToCompile*(conf: ConfigRef; cf: Cfile) =
   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) =
   conf.toCompile.setLen 0
   ## 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.
   result = conf.globalOptions * {optGenScript, optGenMapping} != {}
 
-proc cFileSpecificOptions(conf: ConfigRef; nimname: string): string =
+proc cFileSpecificOptions(conf: ConfigRef; nimname, fullNimFile: string): string =
   result = conf.compileOptions
+  addOpt(result, conf.cfileSpecificOptions.getOrDefault(fullNimFile))
+
   for option in conf.compileOptionsCmd:
     if strutils.find(result, option, 0) < 0:
       addOpt(result, option)
@@ -545,7 +554,7 @@ proc cFileSpecificOptions(conf: ConfigRef; nimname: string): string =
   if existsConfigVar(conf, key): addOpt(result, getConfigVar(conf, key))
 
 proc getCompileOptions(conf: ConfigRef): string =
-  result = cFileSpecificOptions(conf, "__dummy__")
+  result = cFileSpecificOptions(conf, "__dummy__", "__dummy__")
 
 proc vccplatform(conf: ConfigRef): string =
   # 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,
                          isMainFile = false; produceOutput = false): string =
   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")
   if exe.len == 0: exe = getCompilerExe(conf, c, cfile.cname)
 
diff --git a/compiler/options.nim b/compiler/options.nim
index 2da73ec85..8cfd2f2fb 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -239,7 +239,7 @@ type
     outFile*: RelativeFile
     outDir*: AbsoluteDir
     prefixDir*, libpath*, nimcacheDir*: AbsoluteDir
-    dllOverrides, moduleOverrides*: StringTableRef
+    dllOverrides, moduleOverrides*, cfileSpecificOptions*: StringTableRef
     projectName*: string # holds a name like 'nim'
     projectPath*: AbsoluteDir # holds a path like /home/alice/projects/nim/compiler/
     projectFull*: AbsoluteFile # projectPath/projectName
@@ -347,6 +347,7 @@ proc newConfigRef*(): ConfigRef =
     libpath: AbsoluteDir"", nimcacheDir: AbsoluteDir"",
     dllOverrides: newStringTable(modeCaseInsensitive),
     moduleOverrides: newStringTable(modeStyleInsensitive),
+    cfileSpecificOptions: newStringTable(modeCaseSensitive),
     projectName: "", # holds a name like 'nim'
     projectPath: AbsoluteDir"", # holds a path like /home/alice/projects/nim/compiler/
     projectFull: AbsoluteFile"", # projectPath/projectName
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index e43004bf8..ad58c0bd8 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -46,7 +46,7 @@ const
     wWarnings, wHints,
     wLineDir, wStackTrace, wLineTrace, wOptimization, wHint, wWarning, wError,
     wFatal, wDefine, wUndef, wCompile, wLink, wLinksys, wPure, wPush, wPop,
-    wPassl, wPassc,
+    wPassl, wPassc, wLocalPassc,
     wDeadCodeElimUnused,  # deprecated, always on
     wDeprecated,
     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)
         extccomp.addCompileOption(c.config, 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:
         processPush(c, n, i + 1)
         result = true
diff --git a/compiler/rodimpl.nim b/compiler/rodimpl.nim
index 94fd792bf..188a32dc4 100644
--- a/compiler/rodimpl.nim
+++ b/compiler/rodimpl.nim
@@ -851,6 +851,8 @@ proc replay(g: ModuleGraph; module: PSym; n: PNode) =
         extccomp.addLinkOption(g.config, n[1].strVal)
       of "passc":
         extccomp.addCompileOption(g.config, n[1].strVal)
+      of "localpassc":
+        extccomp.addLocalCompileOption(g.config, n[1].strVal, toFullPathConsiderDirty(g.config, module.info.fileIndex))
       of "cppdefine":
         options.cppDefine(g.config, n[1].strVal)
       of "inc":
diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim
index fa18d4f7f..f2946ffa2 100644
--- a/compiler/wordrecg.nim
+++ b/compiler/wordrecg.nim
@@ -58,7 +58,7 @@ type
     wSafecode, wPackage, wNoForward, wReorder, wNoRewrite, wNoDestroy,
     wPragma,
     wCompileTime, wNoInit,
-    wPassc, wPassl, wBorrow, wDiscardable,
+    wPassc, wPassl, wLocalPassc, wBorrow, wDiscardable,
     wFieldChecks,
     wSubsChar, wAcyclic, wShallow, wUnroll, wLinearScanEnd, wComputedGoto,
     wInjectStmt, wExperimental,
@@ -146,7 +146,7 @@ const
     "safecode", "package", "noforward", "reorder", "norewrite", "nodestroy",
     "pragma",
     "compiletime", "noinit",
-    "passc", "passl", "borrow", "discardable", "fieldchecks",
+    "passc", "passl", "localpassc", "borrow", "discardable", "fieldchecks",
     "subschar", "acyclic", "shallow", "unroll", "linearscanend",
     "computedgoto", "injectstmt", "experimental",
     "write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit",
@@ -209,4 +209,5 @@ proc canonPragmaSpelling*(w: TSpecialWord): string =
   of wImplicitStatic: "implicitStatic"
   of wCodegenDecl: "codegenDecl"
   of wLiftLocals: "liftLocals"
+  of wLocalPassc: "localPassc"
   else: specialWords[w]
diff --git a/doc/manual.rst b/doc/manual.rst
index 82487a385..50d3a9baa 100644
--- a/doc/manual.rst
+++ b/doc/manual.rst
@@ -6560,18 +6560,31 @@ The ``link`` pragma can be used to link an additional file with the project:
 
 PassC pragma
 ------------
-The ``passC`` pragma can be used to pass additional parameters to the C
-compiler like you would using the commandline switch ``--passC``:
+The ``passc`` pragma can be used to pass additional parameters to the C
+compiler like you would using the commandline switch ``--passc``:
 
 .. code-block:: Nim
-  {.passC: "-Wall -Werror".}
+  {.passc: "-Wall -Werror".}
 
 Note that you can use ``gorge`` from the `system module <system.html>`_ to
 embed parameters from an external command that will be executed
 during semantic analysis:
 
 .. 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
 ------------