|
1 | | -import std/[macros, atomics, sysatomics], strformat, chronicles, chronos |
| 1 | +import |
| 2 | + std/[macros, atomics, sysatomics, compilesettings], strformat, chronicles, chronos |
| 3 | +import strutils |
2 | 4 | import ../codegen/meta |
3 | 5 |
|
| 6 | +func nimMainPrefixOnCmdLine(cmdLine: string): tuple[found: bool, value: string] = |
| 7 | + ## Scan the compiler command line for `--nimMainPrefix:X` (last one wins) and |
| 8 | + ## return its value. Switch names in Nim are style-insensitive, so the name |
| 9 | + ## is matched lowercased and with underscores stripped; the separator may be |
| 10 | + ## `:` or `=`. Returns `(false, "")` when the flag is absent — note config.nims |
| 11 | + ## switches may not surface here, so absence is not proof it was never set. |
| 12 | + var found = false |
| 13 | + var value = "" |
| 14 | + for tok in cmdLine.splitWhitespace(): |
| 15 | + let body = tok.strip(trailing = false, chars = {'-'}) |
| 16 | + let sep = body.find({':', '='}) |
| 17 | + if sep < 0: |
| 18 | + continue |
| 19 | + if body[0 ..< sep].toLowerAscii().replace("_", "") == "nimmainprefix": |
| 20 | + found = true |
| 21 | + value = body[sep + 1 .. ^1] |
| 22 | + (found, value) |
| 23 | + |
| 24 | +proc validateNimMainPrefix(libraryName: string) {.compileTime.} = |
| 25 | + ## The Nim runtime init symbol is importc'd as `lib{libraryName}NimMain`, so |
| 26 | + ## the build must pass `--nimMainPrefix:lib{libraryName}`; a mismatch otherwise |
| 27 | + ## surfaces only at link time as an obscure undefined-symbol error. Absence |
| 28 | + ## can't be an error — config.nims may set the prefix without it showing on |
| 29 | + ## `commandLine` — so it only warrants a hint, and only for the `--app:lib` |
| 30 | + ## build where the prefix actually matters. |
| 31 | + let expectedPrefix = "lib" & libraryName |
| 32 | + let (prefixFound, prefixValue) = |
| 33 | + nimMainPrefixOnCmdLine(querySetting(SingleValueSetting.commandLine)) |
| 34 | + if prefixFound and prefixValue != expectedPrefix: |
| 35 | + error( |
| 36 | + "declareLibrary(\"" & libraryName & |
| 37 | + "\"): the Nim runtime init symbol is importc'd as " & expectedPrefix & |
| 38 | + "NimMain, so the build needs --nimMainPrefix:" & expectedPrefix & |
| 39 | + ", but the command line passes --nimMainPrefix:" & prefixValue & |
| 40 | + ". Change the flag to --nimMainPrefix:" & expectedPrefix & |
| 41 | + " (it must be \"lib\" followed by the declareLibrary name)." |
| 42 | + ) |
| 43 | + elif not prefixFound and compileOption("app", "lib"): |
| 44 | + hint( |
| 45 | + "declareLibrary(\"" & libraryName & "\"): pass --nimMainPrefix:" & expectedPrefix & |
| 46 | + " so the Nim runtime init symbol " & expectedPrefix & |
| 47 | + "NimMain resolves; without it the build may fail with an undefined-symbol" & |
| 48 | + " link error (ignore this hint if the prefix is set in config.nims)." |
| 49 | + ) |
| 50 | + |
4 | 51 | macro declareLibraryBase*(libraryName: static[string]): untyped = |
5 | 52 | # Record the library name for binding generation |
6 | 53 | currentLibName = libraryName |
7 | 54 |
|
| 55 | + validateNimMainPrefix(libraryName) |
| 56 | + |
8 | 57 | var res = newStmtList() |
9 | 58 |
|
10 | 59 | ## Generate {.pragma: exported, exportc, cdecl, raises: [].} |
|
0 commit comments