diff options
-rw-r--r-- | compiler/extccomp.nim | 4 | ||||
-rw-r--r-- | compiler/options.nim | 1 | ||||
-rw-r--r-- | compiler/pragmas.nim | 30 | ||||
-rw-r--r-- | compiler/rodimpl.nim | 5 | ||||
-rw-r--r-- | doc/manual.rst | 8 | ||||
-rw-r--r-- | tests/pragmas/cfunction.c | 4 | ||||
-rw-r--r-- | tests/pragmas/tcompile_pragma.nim | 9 |
7 files changed, 49 insertions, 12 deletions
diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index 79b4ba637..11b001f9d 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -554,6 +554,10 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile, ospNeedsPIC in platform.OS[conf.target.targetOS].props: options.add(' ' & CC[c].pic) + if cfile.customArgs != "": + options.add ' ' + options.add cfile.customArgs + var compilePattern: string # compute include paths: var includeCmd = CC[c].includeCmd & quoteShell(conf.libpath) diff --git a/compiler/options.nim b/compiler/options.nim index 40d86a01d..6054eb3a5 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -198,6 +198,7 @@ type nimname*: string cname*, obj*: AbsoluteFile flags*: set[CfileFlag] + customArgs*: string CfileList* = seq[Cfile] Suggest* = ref object diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index fe8cd3cfe..4d5240e3c 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -93,11 +93,10 @@ proc getPragmaVal*(procAst: PNode; name: TSpecialWord): PNode = proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords; isStatement: bool = false) -proc recordPragma(c: PContext; n: PNode; key, val: string; val2 = "") = +proc recordPragma(c: PContext; n: PNode; args: varargs[string]) = var recorded = newNodeI(nkCommentStmt, n.info) - recorded.add newStrNode(key, n.info) - recorded.add newStrNode(val, n.info) - if val2.len > 0: recorded.add newStrNode(val2, n.info) + for i in 0..args.high: + recorded.add newStrNode(args[i], n.info) c.graph.recordStmt(c.graph, c.module, recorded) const @@ -491,11 +490,12 @@ proc relativeFile(c: PContext; n: PNode; ext=""): AbsoluteFile = if result.isEmpty: result = AbsoluteFile s proc processCompile(c: PContext, n: PNode) = - proc docompile(c: PContext; it: PNode; src, dest: AbsoluteFile) = + proc docompile(c: PContext; it: PNode; src, dest: AbsoluteFile; customArgs: string) = var cf = Cfile(nimname: splitFile(src).name, - cname: src, obj: dest, flags: {CfileFlag.External}) + cname: src, obj: dest, flags: {CfileFlag.External}, + customArgs: customArgs) extccomp.addExternalFileToCompile(c.config, cf) - recordPragma(c, it, "compile", src.string, dest.string) + recordPragma(c, it, "compile", src.string, dest.string, customArgs) proc getStrLit(c: PContext, n: PNode; i: int): string = n[i] = c.semConstExpr(c, n[i]) @@ -513,9 +513,19 @@ proc processCompile(c: PContext, n: PNode) = var found = parentDir(toFullPath(c.config, n.info)) / s for f in os.walkFiles(found): let obj = completeCfilePath(c.config, AbsoluteFile(dest % extractFilename(f))) - docompile(c, it, AbsoluteFile f, obj) + docompile(c, it, AbsoluteFile f, obj, "") else: - let s = expectStrLit(c, n) + var s = "" + var customArgs = "" + if n.kind in nkCallKinds: + s = getStrLit(c, n, 1) + if n.len <= 3: + customArgs = getStrLit(c, n, 2) + else: + localError(c.config, n.info, "'.compile' pragma takes up 2 arguments") + else: + s = expectStrLit(c, n) + var found = AbsoluteFile(parentDir(toFullPath(c.config, n.info)) / s) if not fileExists(found): if isAbsolute(s): found = AbsoluteFile s @@ -523,7 +533,7 @@ proc processCompile(c: PContext, n: PNode) = found = findFile(c.config, s) if found.isEmpty: found = AbsoluteFile s let obj = toObjFile(c.config, completeCfilePath(c.config, found, false)) - docompile(c, it, found, obj) + docompile(c, it, found, obj, customArgs) proc processLink(c: PContext, n: PNode) = let found = relativeFile(c, n, CC[c.config.cCompiler].objExt) diff --git a/compiler/rodimpl.nim b/compiler/rodimpl.nim index 52b4d1f85..e50ab66de 100644 --- a/compiler/rodimpl.nim +++ b/compiler/rodimpl.nim @@ -838,11 +838,12 @@ proc replay(g: ModuleGraph; module: PSym; n: PNode) = of "warning": message(g.config, n.info, warnUser, n[1].strVal) of "error": localError(g.config, n.info, errUser, n[1].strVal) of "compile": - internalAssert g.config, n.len == 3 and n[2].kind == nkStrLit + internalAssert g.config, n.len == 4 and n[2].kind == nkStrLit let cname = AbsoluteFile n[1].strVal var cf = Cfile(nimname: splitFile(cname).name, cname: cname, obj: AbsoluteFile n[2].strVal, - flags: {CfileFlag.External}) + flags: {CfileFlag.External}, + customArgs: n[3].strVal) extccomp.addExternalFileToCompile(g.config, cf) of "link": extccomp.addExternalFileToLink(g.config, AbsoluteFile n[1].strVal) diff --git a/doc/manual.rst b/doc/manual.rst index 494a009cb..7258e7775 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -6622,6 +6622,14 @@ with the project: has changed. One can use the ``-f`` command line option to force recompilation of the file. +Since 1.4 the `compile` pragma is also available with this syntax: + +.. code-block:: Nim + {.compile("myfile.cpp", "--custom flags here").} + +As can be seen in the example, this new variant allows for custom flags +that are passed to the C compiler when the file is recompiled. + Link pragma ----------- diff --git a/tests/pragmas/cfunction.c b/tests/pragmas/cfunction.c new file mode 100644 index 000000000..bf49d6a29 --- /dev/null +++ b/tests/pragmas/cfunction.c @@ -0,0 +1,4 @@ + +int cfunction(void) { + return NUMBER_HERE; +} diff --git a/tests/pragmas/tcompile_pragma.nim b/tests/pragmas/tcompile_pragma.nim new file mode 100644 index 000000000..4e09a7501 --- /dev/null +++ b/tests/pragmas/tcompile_pragma.nim @@ -0,0 +1,9 @@ +discard """ + output: '''34''' +""" + +{.compile("cfunction.c", "-DNUMBER_HERE=34").} + +proc cfunction(): cint {.importc.} + +echo cfunction() |