Compare commits
3 commits
devel
...
fix_static
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2482eeeed4 | ||
|
|
13c6491b10 | ||
|
|
2c904039fa |
6 changed files with 65 additions and 9 deletions
|
|
@ -185,4 +185,7 @@
|
||||||
- Nintendo Switch was added as a new platform target. See [the compiler user guide](https://nim-lang.org/docs/nimc.html)
|
- Nintendo Switch was added as a new platform target. See [the compiler user guide](https://nim-lang.org/docs/nimc.html)
|
||||||
for more info.
|
for more info.
|
||||||
|
|
||||||
|
- Compiler switch ``--uniqueMain`` was added. See [the compiler user guide](https://nim-lang.org/docs/nimc.html#linking-a-nim-generated-static-library-in-nim) for more info.
|
||||||
|
|
||||||
|
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
|
||||||
|
|
@ -947,19 +947,27 @@ proc genFilenames(m: BModule): Rope =
|
||||||
for i in 0..<m.config.m.fileInfos.len:
|
for i in 0..<m.config.m.fileInfos.len:
|
||||||
result.addf("dbgRegisterFilename($1);$N", [m.config.m.fileInfos[i].projPath.makeCString])
|
result.addf("dbgRegisterFilename($1);$N", [m.config.m.fileInfos[i].projPath.makeCString])
|
||||||
|
|
||||||
|
proc genHashName(m: PSym, name: string): string =
|
||||||
|
name & $hashProc(m)
|
||||||
|
|
||||||
|
proc maybeHashMain(m: BModule, name: string): string =
|
||||||
|
result = name
|
||||||
|
if optUniqueMain in m.config.globalOptions:
|
||||||
|
result = m.module.genHashName(name)
|
||||||
|
|
||||||
proc genMainProc(m: BModule) =
|
proc genMainProc(m: BModule) =
|
||||||
const
|
let
|
||||||
# The use of a volatile function pointer to call Pre/NimMainInner
|
# The use of a volatile function pointer to call Pre/NimMainInner
|
||||||
# prevents inlining of the NimMainInner function and dependent
|
# prevents inlining of the NimMainInner function and dependent
|
||||||
# functions, which might otherwise merge their stack frames.
|
# functions, which might otherwise merge their stack frames.
|
||||||
PreMainBody =
|
PreMainBody =
|
||||||
"void PreMainInner(void) {$N" &
|
"static void PreMainInner(void) {$N" &
|
||||||
"\tsystemInit000();$N" &
|
"\tsystemInit000();$N" &
|
||||||
"$1" &
|
"$1" &
|
||||||
"$2" &
|
"$2" &
|
||||||
"$3" &
|
"$3" &
|
||||||
"}$N$N" &
|
"}$N$N" &
|
||||||
"void PreMain(void) {$N" &
|
"static void PreMain(void) {$N" &
|
||||||
"\tvoid (*volatile inner)(void);$N" &
|
"\tvoid (*volatile inner)(void);$N" &
|
||||||
"\tsystemDatInit000();$N" &
|
"\tsystemDatInit000();$N" &
|
||||||
"\tinner = PreMainInner;$N" &
|
"\tinner = PreMainInner;$N" &
|
||||||
|
|
@ -968,17 +976,17 @@ proc genMainProc(m: BModule) =
|
||||||
"}$N$N"
|
"}$N$N"
|
||||||
|
|
||||||
MainProcs =
|
MainProcs =
|
||||||
"\tNimMain();$N"
|
"\t" & m.maybeHashMain("NimMain") & "();$N"
|
||||||
|
|
||||||
MainProcsWithResult =
|
MainProcsWithResult =
|
||||||
MainProcs & "\treturn nim_program_result;$N"
|
MainProcs & "\treturn nim_program_result;$N"
|
||||||
|
|
||||||
NimMainInner = "N_CDECL(void, NimMainInner)(void) {$N" &
|
NimMainInner = "N_CDECL(static void, NimMainInner)(void) {$N" &
|
||||||
"$1" &
|
"$1" &
|
||||||
"}$N$N"
|
"}$N$N"
|
||||||
|
|
||||||
NimMainProc =
|
NimMainProc =
|
||||||
"N_CDECL(void, NimMain)(void) {$N" &
|
"N_CDECL(void, " & m.maybeHashMain("NimMain") & ")(void) {$N" &
|
||||||
"\tvoid (*volatile inner)(void);$N" &
|
"\tvoid (*volatile inner)(void);$N" &
|
||||||
"\tPreMain();$N" &
|
"\tPreMain();$N" &
|
||||||
"\tinner = NimMainInner;$N" &
|
"\tinner = NimMainInner;$N" &
|
||||||
|
|
@ -1026,7 +1034,7 @@ proc genMainProc(m: BModule) =
|
||||||
PosixNimDllMain = WinNimDllMain
|
PosixNimDllMain = WinNimDllMain
|
||||||
|
|
||||||
PosixCDllMain =
|
PosixCDllMain =
|
||||||
"void NIM_POSIX_INIT NimMainInit(void) {$N" &
|
"static void NIM_POSIX_INIT NimMainInit(void) {$N" &
|
||||||
MainProcs &
|
MainProcs &
|
||||||
"}$N$N"
|
"}$N$N"
|
||||||
|
|
||||||
|
|
@ -1117,6 +1125,9 @@ proc registerModuleToMain(g: BModuleList; m: PSym) =
|
||||||
var
|
var
|
||||||
init = m.getInitName
|
init = m.getInitName
|
||||||
datInit = m.getDatInitName
|
datInit = m.getDatInitName
|
||||||
|
if sfMainModule in m.flags:
|
||||||
|
addf(g.mainModProcs, "N_LIB_PRIVATE N_NIMCALL(static void, $1)(void);$N", [init])
|
||||||
|
else:
|
||||||
addf(g.mainModProcs, "N_LIB_PRIVATE N_NIMCALL(void, $1)(void);$N", [init])
|
addf(g.mainModProcs, "N_LIB_PRIVATE N_NIMCALL(void, $1)(void);$N", [init])
|
||||||
addf(g.mainModProcs, "N_LIB_PRIVATE N_NIMCALL(void, $1)(void);$N", [datInit])
|
addf(g.mainModProcs, "N_LIB_PRIVATE N_NIMCALL(void, $1)(void);$N", [datInit])
|
||||||
if sfSystemModule notin m.flags:
|
if sfSystemModule notin m.flags:
|
||||||
|
|
@ -1129,7 +1140,11 @@ proc registerModuleToMain(g: BModuleList; m: PSym) =
|
||||||
|
|
||||||
proc genInitCode(m: BModule) =
|
proc genInitCode(m: BModule) =
|
||||||
var initname = getInitName(m.module)
|
var initname = getInitName(m.module)
|
||||||
var prc = "N_LIB_PRIVATE N_NIMCALL(void, $1)(void) {$N" % [initname]
|
var prc: Rope
|
||||||
|
if sfMainModule in m.module.flags:
|
||||||
|
prc = "N_LIB_PRIVATE N_NIMCALL(static void, $1)(void) {$N" % [initname]
|
||||||
|
else:
|
||||||
|
prc = "N_LIB_PRIVATE N_NIMCALL(void, $1)(void) {$N" % [initname]
|
||||||
if m.typeNodes > 0:
|
if m.typeNodes > 0:
|
||||||
appcg(m, m.s[cfsTypeInit1], "static #TNimNode $1[$2];$n",
|
appcg(m, m.s[cfsTypeInit1], "static #TNimNode $1[$2];$n",
|
||||||
[m.typeNodesName, rope(m.typeNodes)])
|
[m.typeNodesName, rope(m.typeNodes)])
|
||||||
|
|
|
||||||
|
|
@ -246,6 +246,7 @@ proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool
|
||||||
of "compileonly", "c": result = contains(conf.globalOptions, optCompileOnly)
|
of "compileonly", "c": result = contains(conf.globalOptions, optCompileOnly)
|
||||||
of "nolinking": result = contains(conf.globalOptions, optNoLinking)
|
of "nolinking": result = contains(conf.globalOptions, optNoLinking)
|
||||||
of "nomain": result = contains(conf.globalOptions, optNoMain)
|
of "nomain": result = contains(conf.globalOptions, optNoMain)
|
||||||
|
of "uniquemain": result = contains(conf.globalOptions, optUniqueMain)
|
||||||
of "forcebuild", "f": result = contains(conf.globalOptions, optForceFullMake)
|
of "forcebuild", "f": result = contains(conf.globalOptions, optForceFullMake)
|
||||||
of "warnings", "w": result = contains(conf.options, optWarns)
|
of "warnings", "w": result = contains(conf.options, optWarns)
|
||||||
of "hints": result = contains(conf.options, optHints)
|
of "hints": result = contains(conf.options, optHints)
|
||||||
|
|
@ -416,6 +417,9 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||||
of "nomain":
|
of "nomain":
|
||||||
expectNoArg(conf, switch, arg, pass, info)
|
expectNoArg(conf, switch, arg, pass, info)
|
||||||
incl(conf.globalOptions, optNoMain)
|
incl(conf.globalOptions, optNoMain)
|
||||||
|
of "uniquemain":
|
||||||
|
expectNoArg(conf, switch, arg, pass, info)
|
||||||
|
incl(conf.globalOptions, optUniqueMain)
|
||||||
of "forcebuild", "f":
|
of "forcebuild", "f":
|
||||||
expectNoArg(conf, switch, arg, pass, info)
|
expectNoArg(conf, switch, arg, pass, info)
|
||||||
incl(conf.globalOptions, optForceFullMake)
|
incl(conf.globalOptions, optForceFullMake)
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ type # please make sure we have under 32 options
|
||||||
optSkipUserConfigFile, # skip the users's config file
|
optSkipUserConfigFile, # skip the users's config file
|
||||||
optSkipParentConfigFiles, # skip parent dir's config files
|
optSkipParentConfigFiles, # skip parent dir's config files
|
||||||
optNoMain, # do not generate a "main" proc
|
optNoMain, # do not generate a "main" proc
|
||||||
|
optUniqueMain, # generate a unique name for the NimMain function
|
||||||
optUseColors, # use colors for hints, warnings, and errors
|
optUseColors, # use colors for hints, warnings, and errors
|
||||||
optThreads, # support for multi-threading
|
optThreads, # support for multi-threading
|
||||||
optStdout, # output to stdout
|
optStdout, # output to stdout
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,8 @@ Advanced options:
|
||||||
-c, --compileOnly compile Nim files only; do not assemble or link
|
-c, --compileOnly compile Nim files only; do not assemble or link
|
||||||
--noLinking compile Nim and generated files but do not link
|
--noLinking compile Nim and generated files but do not link
|
||||||
--noMain do not generate a main procedure
|
--noMain do not generate a main procedure
|
||||||
|
--uniqueMain generate a unique main function call which is usefull
|
||||||
|
for linking to static libaries written in Nim
|
||||||
--genScript generate a compile script (in the 'nimcache'
|
--genScript generate a compile script (in the 'nimcache'
|
||||||
subdirectory named 'compile_$$project$$scriptext'),
|
subdirectory named 'compile_$$project$$scriptext'),
|
||||||
implies --compileOnly
|
implies --compileOnly
|
||||||
|
|
|
||||||
31
doc/nimc.rst
31
doc/nimc.rst
|
|
@ -430,6 +430,37 @@ on Linux::
|
||||||
|
|
||||||
nim c --dynlibOverride:lua --passL:liblua.lib program.nim
|
nim c --dynlibOverride:lua --passL:liblua.lib program.nim
|
||||||
|
|
||||||
|
Linking a Nim generated static library in Nim
|
||||||
|
=============================================
|
||||||
|
|
||||||
|
By default, Nim generates a publicly visible main function in C that is always
|
||||||
|
named the same thing (NimMain) in order to make it easy for clients written in
|
||||||
|
other languages to link to Nim generated code. However, this causes issues
|
||||||
|
when Nim clients want to link to Nim static libraries because of multiple
|
||||||
|
definitions of the same function, which C doesn't allow.
|
||||||
|
|
||||||
|
In order to work around this issue, a compiler flag exists that generates a
|
||||||
|
unique name for ``NimMain`` by hashing the name of the module it's in and
|
||||||
|
appending it to the end of the ``NimMain``, separated by an underscore.
|
||||||
|
|
||||||
|
An example to compile a static library on Linux and then link it is as follows::
|
||||||
|
|
||||||
|
nim --noMain --uniqueMain --app:staticLib c static.nim
|
||||||
|
nim --passL:libstatic.a c main.nim
|
||||||
|
|
||||||
|
Where an example of ``static.nim`` could be:
|
||||||
|
|
||||||
|
.. code-block:: Nim
|
||||||
|
proc testing*(testInt: int): int {.cdecl, exportc.} =
|
||||||
|
return testInt + 100
|
||||||
|
|
||||||
|
and an example of ``main.nim`` could be:
|
||||||
|
|
||||||
|
.. code-block:: Nim
|
||||||
|
proc testing*(testInt: int): int {.importc, cdecl.}
|
||||||
|
|
||||||
|
echo testing(50) # Should output "150"
|
||||||
|
|
||||||
|
|
||||||
Backend language options
|
Backend language options
|
||||||
========================
|
========================
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue