commands.nim 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2015 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. # This module handles the parsing of command line arguments.
  10. # We do this here before the 'import' statement so 'defined' does not get
  11. # confused with 'TGCMode.gcGenerational' etc.
  12. template bootSwitch(name, expr, userString) =
  13. # Helper to build boot constants, for debugging you can 'echo' the else part.
  14. const name = if expr: " " & userString else: ""
  15. bootSwitch(usedRelease, defined(release), "-d:release")
  16. bootSwitch(usedDanger, defined(danger), "-d:danger")
  17. # `useLinenoise` deprecated in favor of `nimUseLinenoise`, kept for backward compatibility
  18. bootSwitch(useLinenoise, defined(nimUseLinenoise) or defined(useLinenoise), "-d:nimUseLinenoise")
  19. bootSwitch(usedBoehm, defined(boehmgc), "--gc:boehm")
  20. bootSwitch(usedMarkAndSweep, defined(gcmarkandsweep), "--gc:markAndSweep")
  21. bootSwitch(usedGenerational, defined(gcgenerational), "--gc:generational")
  22. bootSwitch(usedGoGC, defined(gogc), "--gc:go")
  23. bootSwitch(usedNoGC, defined(nogc), "--gc:none")
  24. import
  25. os, msgs, options, nversion, condsyms, strutils, extccomp, platform,
  26. wordrecg, parseutils, nimblecmd, parseopt, sequtils, lineinfos,
  27. pathutils, strtabs
  28. from incremental import nimIncremental
  29. from ast import eqTypeFlags, tfGcSafe, tfNoSideEffect
  30. # but some have deps to imported modules. Yay.
  31. bootSwitch(usedTinyC, hasTinyCBackend, "-d:tinyc")
  32. bootSwitch(usedNativeStacktrace,
  33. defined(nativeStackTrace) and nativeStackTraceSupported,
  34. "-d:nativeStackTrace")
  35. bootSwitch(usedFFI, hasFFI, "-d:nimHasLibFFI")
  36. type
  37. TCmdLinePass* = enum
  38. passCmd1, # first pass over the command line
  39. passCmd2, # second pass over the command line
  40. passPP # preprocessor called processCommand()
  41. const
  42. HelpMessage = "Nim Compiler Version $1 [$2: $3]\n" &
  43. "Compiled at $4\n" &
  44. "Copyright (c) 2006-" & copyrightYear & " by Andreas Rumpf\n"
  45. proc genFeatureDesc[T: enum](t: typedesc[T]): string {.compileTime.} =
  46. result = ""
  47. for f in T:
  48. if result.len > 0: result.add "|"
  49. result.add $f
  50. const
  51. Usage = slurp"../doc/basicopt.txt".replace(" //", " ")
  52. AdvancedUsage = slurp"../doc/advopt.txt".replace(" //", " ") % [genFeatureDesc(Feature), genFeatureDesc(LegacyFeature)]
  53. proc getCommandLineDesc(conf: ConfigRef): string =
  54. result = (HelpMessage % [VersionAsString, platform.OS[conf.target.hostOS].name,
  55. CPU[conf.target.hostCPU].name, CompileDate]) &
  56. Usage
  57. proc helpOnError(conf: ConfigRef; pass: TCmdLinePass) =
  58. if pass == passCmd1:
  59. msgWriteln(conf, getCommandLineDesc(conf), {msgStdout})
  60. msgQuit(0)
  61. proc writeAdvancedUsage(conf: ConfigRef; pass: TCmdLinePass) =
  62. if pass == passCmd1:
  63. msgWriteln(conf, (HelpMessage % [VersionAsString,
  64. platform.OS[conf.target.hostOS].name,
  65. CPU[conf.target.hostCPU].name, CompileDate]) &
  66. AdvancedUsage,
  67. {msgStdout})
  68. msgQuit(0)
  69. proc writeFullhelp(conf: ConfigRef; pass: TCmdLinePass) =
  70. if pass == passCmd1:
  71. msgWriteln(conf, `%`(HelpMessage, [VersionAsString,
  72. platform.OS[conf.target.hostOS].name,
  73. CPU[conf.target.hostCPU].name, CompileDate]) &
  74. Usage & AdvancedUsage,
  75. {msgStdout})
  76. msgQuit(0)
  77. proc writeVersionInfo(conf: ConfigRef; pass: TCmdLinePass) =
  78. if pass == passCmd1:
  79. msgWriteln(conf, `%`(HelpMessage, [VersionAsString,
  80. platform.OS[conf.target.hostOS].name,
  81. CPU[conf.target.hostCPU].name, CompileDate]),
  82. {msgStdout})
  83. const gitHash {.strdefine.} = gorge("git log -n 1 --format=%H").strip
  84. when gitHash.len == 40:
  85. msgWriteln(conf, "git hash: " & gitHash, {msgStdout})
  86. msgWriteln(conf, "active boot switches:" & usedRelease & usedDanger &
  87. usedTinyC & useLinenoise & usedNativeStacktrace &
  88. usedFFI & usedBoehm & usedMarkAndSweep & usedGenerational & usedGoGC & usedNoGC,
  89. {msgStdout})
  90. msgQuit(0)
  91. proc writeCommandLineUsage*(conf: ConfigRef) =
  92. msgWriteln(conf, getCommandLineDesc(conf), {msgStdout})
  93. proc addPrefix(switch: string): string =
  94. if switch.len <= 1: result = "-" & switch
  95. else: result = "--" & switch
  96. const
  97. errInvalidCmdLineOption = "invalid command line option: '$1'"
  98. errOnOrOffExpectedButXFound = "'on' or 'off' expected, but '$1' found"
  99. errOnOffOrListExpectedButXFound = "'on', 'off' or 'list' expected, but '$1' found"
  100. errOffHintsError = "'off', 'hint' or 'error' expected, but '$1' found"
  101. proc invalidCmdLineOption(conf: ConfigRef; pass: TCmdLinePass, switch: string, info: TLineInfo) =
  102. if switch == " ": localError(conf, info, errInvalidCmdLineOption % "-")
  103. else: localError(conf, info, errInvalidCmdLineOption % addPrefix(switch))
  104. proc splitSwitch(conf: ConfigRef; switch: string, cmd, arg: var string, pass: TCmdLinePass,
  105. info: TLineInfo) =
  106. cmd = ""
  107. var i = 0
  108. if i < switch.len and switch[i] == '-': inc(i)
  109. if i < switch.len and switch[i] == '-': inc(i)
  110. while i < switch.len:
  111. case switch[i]
  112. of 'a'..'z', 'A'..'Z', '0'..'9', '_', '.': cmd.add(switch[i])
  113. else: break
  114. inc(i)
  115. if i >= switch.len: arg = ""
  116. # cmd:arg => (cmd,arg)
  117. elif switch[i] in {':', '='}: arg = substr(switch, i + 1)
  118. # cmd[sub]:rest => (cmd,[sub]:rest)
  119. elif switch[i] == '[': arg = substr(switch, i)
  120. else: invalidCmdLineOption(conf, pass, switch, info)
  121. proc processOnOffSwitch(conf: ConfigRef; op: TOptions, arg: string, pass: TCmdLinePass,
  122. info: TLineInfo) =
  123. case arg.normalize
  124. of "","on": conf.options.incl op
  125. of "off": conf.options.excl op
  126. else: localError(conf, info, errOnOrOffExpectedButXFound % arg)
  127. proc processOnOffSwitchOrList(conf: ConfigRef; op: TOptions, arg: string, pass: TCmdLinePass,
  128. info: TLineInfo): bool =
  129. result = false
  130. case arg.normalize
  131. of "on": conf.options.incl op
  132. of "off": conf.options.excl op
  133. of "list": result = true
  134. else: localError(conf, info, errOnOffOrListExpectedButXFound % arg)
  135. proc processOnOffSwitchG(conf: ConfigRef; op: TGlobalOptions, arg: string, pass: TCmdLinePass,
  136. info: TLineInfo) =
  137. case arg.normalize
  138. of "", "on": conf.globalOptions.incl op
  139. of "off": conf.globalOptions.excl op
  140. else: localError(conf, info, errOnOrOffExpectedButXFound % arg)
  141. proc expectArg(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
  142. if arg == "":
  143. localError(conf, info, "argument for command line option expected: '$1'" % addPrefix(switch))
  144. proc expectNoArg(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
  145. if arg != "":
  146. localError(conf, info, "invalid argument for command line option: '$1'" % addPrefix(switch))
  147. proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass,
  148. info: TLineInfo; orig: string; conf: ConfigRef) =
  149. var id = "" # arg = key or [key] or key:val or [key]:val; with val=on|off
  150. var i = 0
  151. var n = hintMin
  152. var isBracket = false
  153. if i < arg.len and arg[i] == '[':
  154. isBracket = true
  155. inc(i)
  156. while i < arg.len and (arg[i] notin {':', '=', ']'}):
  157. id.add(arg[i])
  158. inc(i)
  159. if isBracket:
  160. if i < arg.len and arg[i] == ']': inc(i)
  161. else: invalidCmdLineOption(conf, pass, orig, info)
  162. if i == arg.len: discard
  163. elif i < arg.len and (arg[i] in {':', '='}): inc(i)
  164. else: invalidCmdLineOption(conf, pass, orig, info)
  165. if state == wHint:
  166. let x = findStr(lineinfos.HintsToStr, id)
  167. if x >= 0: n = TNoteKind(x + ord(hintMin))
  168. else: localError(conf, info, "unknown hint: " & id)
  169. else:
  170. let x = findStr(lineinfos.WarningsToStr, id)
  171. if x >= 0: n = TNoteKind(x + ord(warnMin))
  172. else: localError(conf, info, "unknown warning: " & id)
  173. var val = substr(arg, i).normalize
  174. if val == "": val = "on"
  175. if val notin ["on", "off"]:
  176. localError(conf, info, errOnOrOffExpectedButXFound % arg)
  177. elif n notin conf.cmdlineNotes or pass == passCmd1:
  178. if pass == passCmd1: incl(conf.cmdlineNotes, n)
  179. incl(conf.modifiedyNotes, n)
  180. case val
  181. of "on":
  182. if state == wWarningAsError:
  183. incl(conf.warningAsErrors, n)
  184. else:
  185. incl(conf.notes, n)
  186. incl(conf.mainPackageNotes, n)
  187. of "off":
  188. if state == wWarningAsError:
  189. excl(conf.warningAsErrors, n)
  190. else:
  191. excl(conf.notes, n)
  192. excl(conf.mainPackageNotes, n)
  193. excl(conf.foreignPackageNotes, n)
  194. proc processCompile(conf: ConfigRef; filename: string) =
  195. var found = findFile(conf, filename)
  196. if found.isEmpty: found = AbsoluteFile filename
  197. extccomp.addExternalFileToCompile(conf, found)
  198. const
  199. errNoneBoehmRefcExpectedButXFound = "'arc', 'orc', 'markAndSweep', 'boehm', 'go', 'none', 'regions', or 'refc' expected, but '$1' found"
  200. errNoneSpeedOrSizeExpectedButXFound = "'none', 'speed' or 'size' expected, but '$1' found"
  201. errGuiConsoleOrLibExpectedButXFound = "'gui', 'console' or 'lib' expected, but '$1' found"
  202. errInvalidExceptionSystem = "'goto', 'setjump', 'cpp' or 'quirky' expected, but '$1' found"
  203. proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo): bool =
  204. case switch.normalize
  205. of "gc":
  206. case arg.normalize
  207. of "boehm": result = conf.selectedGC == gcBoehm
  208. of "refc": result = conf.selectedGC == gcRefc
  209. of "v2": result = false
  210. of "markandsweep": result = conf.selectedGC == gcMarkAndSweep
  211. of "generational": result = false
  212. of "destructors", "arc": result = conf.selectedGC == gcArc
  213. of "orc": result = conf.selectedGC == gcOrc
  214. of "hooks": result = conf.selectedGC == gcHooks
  215. of "go": result = conf.selectedGC == gcGo
  216. of "none": result = conf.selectedGC == gcNone
  217. of "stack", "regions": result = conf.selectedGC == gcRegions
  218. else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
  219. of "opt":
  220. case arg.normalize
  221. of "speed": result = contains(conf.options, optOptimizeSpeed)
  222. of "size": result = contains(conf.options, optOptimizeSize)
  223. of "none": result = conf.options * {optOptimizeSpeed, optOptimizeSize} == {}
  224. else: localError(conf, info, errNoneSpeedOrSizeExpectedButXFound % arg)
  225. of "verbosity": result = $conf.verbosity == arg
  226. of "app":
  227. case arg.normalize
  228. of "gui": result = contains(conf.globalOptions, optGenGuiApp)
  229. of "console": result = not contains(conf.globalOptions, optGenGuiApp)
  230. of "lib": result = contains(conf.globalOptions, optGenDynLib) and
  231. not contains(conf.globalOptions, optGenGuiApp)
  232. of "staticlib": result = contains(conf.globalOptions, optGenStaticLib) and
  233. not contains(conf.globalOptions, optGenGuiApp)
  234. else: localError(conf, info, errGuiConsoleOrLibExpectedButXFound % arg)
  235. of "dynliboverride":
  236. result = isDynlibOverride(conf, arg)
  237. of "exceptions":
  238. case arg.normalize
  239. of "cpp": result = conf.exc == excCpp
  240. of "setjmp": result = conf.exc == excSetjmp
  241. of "quirky": result = conf.exc == excQuirky
  242. of "goto": result = conf.exc == excGoto
  243. else: localError(conf, info, errInvalidExceptionSystem % arg)
  244. else: invalidCmdLineOption(conf, passCmd1, switch, info)
  245. proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool =
  246. case switch.normalize
  247. of "debuginfo": result = contains(conf.globalOptions, optCDebug)
  248. of "compileonly", "c": result = contains(conf.globalOptions, optCompileOnly)
  249. of "nolinking": result = contains(conf.globalOptions, optNoLinking)
  250. of "nomain": result = contains(conf.globalOptions, optNoMain)
  251. of "forcebuild", "f": result = contains(conf.globalOptions, optForceFullMake)
  252. of "warnings", "w": result = contains(conf.options, optWarns)
  253. of "hints": result = contains(conf.options, optHints)
  254. of "threadanalysis": result = contains(conf.globalOptions, optThreadAnalysis)
  255. of "stacktrace": result = contains(conf.options, optStackTrace)
  256. of "stacktracemsgs": result = contains(conf.options, optStackTraceMsgs)
  257. of "linetrace": result = contains(conf.options, optLineTrace)
  258. of "debugger": result = contains(conf.globalOptions, optCDebug)
  259. of "profiler": result = contains(conf.options, optProfiler)
  260. of "memtracker": result = contains(conf.options, optMemTracker)
  261. of "checks", "x": result = conf.options * ChecksOptions == ChecksOptions
  262. of "floatchecks":
  263. result = conf.options * {optNaNCheck, optInfCheck} == {optNaNCheck, optInfCheck}
  264. of "infchecks": result = contains(conf.options, optInfCheck)
  265. of "nanchecks": result = contains(conf.options, optNaNCheck)
  266. of "nilchecks": result = false # not a thing
  267. of "objchecks": result = contains(conf.options, optObjCheck)
  268. of "fieldchecks": result = contains(conf.options, optFieldCheck)
  269. of "rangechecks": result = contains(conf.options, optRangeCheck)
  270. of "boundchecks": result = contains(conf.options, optBoundsCheck)
  271. of "refchecks": result = contains(conf.options, optRefCheck)
  272. of "overflowchecks": result = contains(conf.options, optOverflowCheck)
  273. of "staticboundchecks": result = contains(conf.options, optStaticBoundsCheck)
  274. of "stylechecks": result = contains(conf.options, optStyleCheck)
  275. of "linedir": result = contains(conf.options, optLineDir)
  276. of "assertions", "a": result = contains(conf.options, optAssert)
  277. of "run", "r": result = contains(conf.globalOptions, optRun)
  278. of "symbolfiles": result = conf.symbolFiles != disabledSf
  279. of "genscript": result = contains(conf.globalOptions, optGenScript)
  280. of "threads": result = contains(conf.globalOptions, optThreads)
  281. of "taintmode": result = contains(conf.globalOptions, optTaintMode)
  282. of "tlsemulation": result = contains(conf.globalOptions, optTlsEmulation)
  283. of "implicitstatic": result = contains(conf.options, optImplicitStatic)
  284. of "patterns", "trmacros": result = contains(conf.options, optTrMacros)
  285. of "excessivestacktrace": result = contains(conf.globalOptions, optExcessiveStackTrace)
  286. of "nilseqs": result = contains(conf.options, optNilSeqs)
  287. else: invalidCmdLineOption(conf, passCmd1, switch, info)
  288. proc processPath(conf: ConfigRef; path: string, info: TLineInfo,
  289. notRelativeToProj = false): AbsoluteDir =
  290. let p = if os.isAbsolute(path) or '$' in path:
  291. path
  292. elif notRelativeToProj:
  293. getCurrentDir() / path
  294. else:
  295. conf.projectPath.string / path
  296. try:
  297. result = AbsoluteDir pathSubs(conf, p, toFullPath(conf, info).splitFile().dir)
  298. except ValueError:
  299. localError(conf, info, "invalid path: " & p)
  300. result = AbsoluteDir p
  301. proc processCfgPath(conf: ConfigRef; path: string, info: TLineInfo): AbsoluteDir =
  302. let path = if path.len > 0 and path[0] == '"': strutils.unescape(path)
  303. else: path
  304. let basedir = toFullPath(conf, info).splitFile().dir
  305. let p = if os.isAbsolute(path) or '$' in path:
  306. path
  307. else:
  308. basedir / path
  309. try:
  310. result = AbsoluteDir pathSubs(conf, p, basedir)
  311. except ValueError:
  312. localError(conf, info, "invalid path: " & p)
  313. result = AbsoluteDir p
  314. const
  315. errInvalidNumber = "$1 is not a valid number"
  316. proc trackDirty(conf: ConfigRef; arg: string, info: TLineInfo) =
  317. var a = arg.split(',')
  318. if a.len != 4: localError(conf, info,
  319. "DIRTY_BUFFER,ORIGINAL_FILE,LINE,COLUMN expected")
  320. var line, column: int
  321. if parseUtils.parseInt(a[2], line) <= 0:
  322. localError(conf, info, errInvalidNumber % a[1])
  323. if parseUtils.parseInt(a[3], column) <= 0:
  324. localError(conf, info, errInvalidNumber % a[2])
  325. let dirtyOriginalIdx = fileInfoIdx(conf, AbsoluteFile a[1])
  326. if dirtyOriginalIdx.int32 >= 0:
  327. msgs.setDirtyFile(conf, dirtyOriginalIdx, AbsoluteFile a[0])
  328. conf.m.trackPos = newLineInfo(dirtyOriginalIdx, line, column)
  329. proc track(conf: ConfigRef; arg: string, info: TLineInfo) =
  330. var a = arg.split(',')
  331. if a.len != 3: localError(conf, info, "FILE,LINE,COLUMN expected")
  332. var line, column: int
  333. if parseUtils.parseInt(a[1], line) <= 0:
  334. localError(conf, info, errInvalidNumber % a[1])
  335. if parseUtils.parseInt(a[2], column) <= 0:
  336. localError(conf, info, errInvalidNumber % a[2])
  337. conf.m.trackPos = newLineInfo(conf, AbsoluteFile a[0], line, column)
  338. proc dynlibOverride(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
  339. if pass in {passCmd2, passPP}:
  340. expectArg(conf, switch, arg, pass, info)
  341. options.inclDynlibOverride(conf, arg)
  342. proc handleStdinInput*(conf: ConfigRef) =
  343. conf.projectName = "stdinfile"
  344. conf.projectFull = conf.projectName.AbsoluteFile
  345. conf.projectPath = AbsoluteDir getCurrentDir()
  346. conf.projectIsStdin = true
  347. if conf.outDir.isEmpty:
  348. conf.outDir = getNimcacheDir(conf)
  349. proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
  350. conf: ConfigRef) =
  351. var
  352. key, val: string
  353. case switch.normalize
  354. of "path", "p":
  355. expectArg(conf, switch, arg, pass, info)
  356. for path in nimbleSubs(conf, arg):
  357. addPath(conf, if pass == passPP: processCfgPath(conf, path, info)
  358. else: processPath(conf, path, info), info)
  359. of "nimblepath", "babelpath":
  360. # keep the old name for compat
  361. if pass in {passCmd2, passPP} and optNoNimblePath notin conf.globalOptions:
  362. expectArg(conf, switch, arg, pass, info)
  363. var path = processPath(conf, arg, info, notRelativeToProj=true)
  364. let nimbleDir = AbsoluteDir getEnv("NIMBLE_DIR")
  365. if not nimbleDir.isEmpty and pass == passPP:
  366. path = nimbleDir / RelativeDir"pkgs"
  367. nimblePath(conf, path, info)
  368. of "nonimblepath", "nobabelpath":
  369. expectNoArg(conf, switch, arg, pass, info)
  370. disableNimblePath(conf)
  371. of "clearnimblepath":
  372. expectNoArg(conf, switch, arg, pass, info)
  373. clearNimblePath(conf)
  374. of "excludepath":
  375. expectArg(conf, switch, arg, pass, info)
  376. let path = processPath(conf, arg, info)
  377. conf.searchPaths.keepItIf(it != path)
  378. conf.lazyPaths.keepItIf(it != path)
  379. of "nimcache":
  380. expectArg(conf, switch, arg, pass, info)
  381. conf.nimcacheDir = processPath(conf, arg, info, notRelativeToProj=true)
  382. of "out", "o":
  383. expectArg(conf, switch, arg, pass, info)
  384. let f = splitFile(processPath(conf, arg, info, notRelativeToProj=true).string)
  385. conf.outFile = RelativeFile f.name & f.ext
  386. conf.outDir = toAbsoluteDir f.dir
  387. of "outdir":
  388. expectArg(conf, switch, arg, pass, info)
  389. conf.outDir = processPath(conf, arg, info, notRelativeToProj=true)
  390. of "usenimcache":
  391. processOnOffSwitchG(conf, {optUseNimcache}, arg, pass, info)
  392. of "docseesrcurl":
  393. expectArg(conf, switch, arg, pass, info)
  394. conf.docSeeSrcUrl = arg
  395. of "docroot":
  396. conf.docRoot = if arg.len == 0: docRootDefault else: arg
  397. of "backend", "b":
  398. let backend = parseEnum(arg.normalize, TBackend.default)
  399. if backend == TBackend.default: localError(conf, info, "invalid backend: '$1'" % arg)
  400. conf.backend = backend
  401. of "doccmd": conf.docCmd = arg
  402. of "mainmodule", "m":
  403. discard "allow for backwards compatibility, but don't do anything"
  404. of "define", "d":
  405. expectArg(conf, switch, arg, pass, info)
  406. if {':', '='} in arg:
  407. splitSwitch(conf, arg, key, val, pass, info)
  408. if cmpIgnoreStyle(key, "nimQuirky") == 0:
  409. conf.exc = excQuirky
  410. defineSymbol(conf.symbols, key, val)
  411. else:
  412. if cmpIgnoreStyle(arg, "nimQuirky") == 0:
  413. conf.exc = excQuirky
  414. defineSymbol(conf.symbols, arg)
  415. of "undef", "u":
  416. expectArg(conf, switch, arg, pass, info)
  417. undefSymbol(conf.symbols, arg)
  418. of "symbol":
  419. expectArg(conf, switch, arg, pass, info)
  420. # deprecated, do nothing
  421. of "compile":
  422. expectArg(conf, switch, arg, pass, info)
  423. if pass in {passCmd2, passPP}: processCompile(conf, arg)
  424. of "link":
  425. expectArg(conf, switch, arg, pass, info)
  426. if pass in {passCmd2, passPP}:
  427. addExternalFileToLink(conf, AbsoluteFile arg)
  428. of "debuginfo":
  429. processOnOffSwitchG(conf, {optCDebug}, arg, pass, info)
  430. of "embedsrc":
  431. processOnOffSwitchG(conf, {optEmbedOrigSrc}, arg, pass, info)
  432. of "compileonly", "c":
  433. processOnOffSwitchG(conf, {optCompileOnly}, arg, pass, info)
  434. of "nolinking":
  435. processOnOffSwitchG(conf, {optNoLinking}, arg, pass, info)
  436. of "nomain":
  437. processOnOffSwitchG(conf, {optNoMain}, arg, pass, info)
  438. of "forcebuild", "f":
  439. processOnOffSwitchG(conf, {optForceFullMake}, arg, pass, info)
  440. of "project":
  441. processOnOffSwitchG(conf, {optWholeProject, optGenIndex}, arg, pass, info)
  442. of "gc":
  443. if conf.backend == backendJs:
  444. return
  445. expectArg(conf, switch, arg, pass, info)
  446. if pass in {passCmd2, passPP}:
  447. case arg.normalize
  448. of "boehm":
  449. conf.selectedGC = gcBoehm
  450. defineSymbol(conf.symbols, "boehmgc")
  451. incl conf.globalOptions, optTlsEmulation # Boehm GC doesn't scan the real TLS
  452. of "refc":
  453. conf.selectedGC = gcRefc
  454. of "v2":
  455. message(conf, info, warnDeprecated, "--gc:v2 is deprecated; using default gc")
  456. of "markandsweep":
  457. conf.selectedGC = gcMarkAndSweep
  458. defineSymbol(conf.symbols, "gcmarkandsweep")
  459. of "destructors", "arc":
  460. conf.selectedGC = gcArc
  461. defineSymbol(conf.symbols, "gcdestructors")
  462. defineSymbol(conf.symbols, "gcarc")
  463. incl conf.globalOptions, optSeqDestructors
  464. incl conf.globalOptions, optTinyRtti
  465. if pass in {passCmd2, passPP}:
  466. defineSymbol(conf.symbols, "nimSeqsV2")
  467. defineSymbol(conf.symbols, "nimV2")
  468. of "orc":
  469. conf.selectedGC = gcOrc
  470. defineSymbol(conf.symbols, "gcdestructors")
  471. defineSymbol(conf.symbols, "gcorc")
  472. incl conf.globalOptions, optSeqDestructors
  473. incl conf.globalOptions, optTinyRtti
  474. if pass in {passCmd2, passPP}:
  475. defineSymbol(conf.symbols, "nimSeqsV2")
  476. defineSymbol(conf.symbols, "nimV2")
  477. of "hooks":
  478. conf.selectedGC = gcHooks
  479. defineSymbol(conf.symbols, "gchooks")
  480. incl conf.globalOptions, optSeqDestructors
  481. processOnOffSwitchG(conf, {optSeqDestructors}, arg, pass, info)
  482. if pass in {passCmd2, passPP}:
  483. defineSymbol(conf.symbols, "nimSeqsV2")
  484. of "go":
  485. conf.selectedGC = gcGo
  486. defineSymbol(conf.symbols, "gogc")
  487. of "none":
  488. conf.selectedGC = gcNone
  489. defineSymbol(conf.symbols, "nogc")
  490. of "stack", "regions":
  491. conf.selectedGC = gcRegions
  492. defineSymbol(conf.symbols, "gcregions")
  493. else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
  494. of "warnings", "w":
  495. if processOnOffSwitchOrList(conf, {optWarns}, arg, pass, info): listWarnings(conf)
  496. of "warning": processSpecificNote(arg, wWarning, pass, info, switch, conf)
  497. of "hint": processSpecificNote(arg, wHint, pass, info, switch, conf)
  498. of "warningaserror": processSpecificNote(arg, wWarningAsError, pass, info, switch, conf)
  499. of "hints":
  500. if processOnOffSwitchOrList(conf, {optHints}, arg, pass, info): listHints(conf)
  501. of "threadanalysis": processOnOffSwitchG(conf, {optThreadAnalysis}, arg, pass, info)
  502. of "stacktrace": processOnOffSwitch(conf, {optStackTrace}, arg, pass, info)
  503. of "stacktracemsgs": processOnOffSwitch(conf, {optStackTraceMsgs}, arg, pass, info)
  504. of "excessivestacktrace": processOnOffSwitchG(conf, {optExcessiveStackTrace}, arg, pass, info)
  505. of "linetrace": processOnOffSwitch(conf, {optLineTrace}, arg, pass, info)
  506. of "debugger":
  507. case arg.normalize
  508. of "on", "native", "gdb":
  509. conf.globalOptions.incl optCDebug
  510. conf.options.incl optLineDir
  511. #defineSymbol(conf.symbols, "nimTypeNames") # type names are used in gdb pretty printing
  512. of "off":
  513. conf.globalOptions.excl optCDebug
  514. else:
  515. localError(conf, info, "expected native|gdb|on|off but found " & arg)
  516. of "g": # alias for --debugger:native
  517. conf.globalOptions.incl optCDebug
  518. conf.options.incl optLineDir
  519. #defineSymbol(conf.symbols, "nimTypeNames") # type names are used in gdb pretty printing
  520. of "profiler":
  521. processOnOffSwitch(conf, {optProfiler}, arg, pass, info)
  522. if optProfiler in conf.options: defineSymbol(conf.symbols, "profiler")
  523. else: undefSymbol(conf.symbols, "profiler")
  524. of "memtracker":
  525. processOnOffSwitch(conf, {optMemTracker}, arg, pass, info)
  526. if optMemTracker in conf.options: defineSymbol(conf.symbols, "memtracker")
  527. else: undefSymbol(conf.symbols, "memtracker")
  528. of "hotcodereloading":
  529. processOnOffSwitchG(conf, {optHotCodeReloading}, arg, pass, info)
  530. if conf.hcrOn:
  531. defineSymbol(conf.symbols, "hotcodereloading")
  532. defineSymbol(conf.symbols, "useNimRtl")
  533. # hardcoded linking with dynamic runtime for MSVC for smaller binaries
  534. # should do the same for all compilers (wherever applicable)
  535. if isVSCompatible(conf):
  536. extccomp.addCompileOptionCmd(conf, "/MD")
  537. else:
  538. undefSymbol(conf.symbols, "hotcodereloading")
  539. undefSymbol(conf.symbols, "useNimRtl")
  540. of "nilseqs": processOnOffSwitch(conf, {optNilSeqs}, arg, pass, info)
  541. of "checks", "x": processOnOffSwitch(conf, ChecksOptions, arg, pass, info)
  542. of "floatchecks":
  543. processOnOffSwitch(conf, {optNaNCheck, optInfCheck}, arg, pass, info)
  544. of "infchecks": processOnOffSwitch(conf, {optInfCheck}, arg, pass, info)
  545. of "nanchecks": processOnOffSwitch(conf, {optNaNCheck}, arg, pass, info)
  546. of "nilchecks": discard "no such thing anymore"
  547. of "objchecks": processOnOffSwitch(conf, {optObjCheck}, arg, pass, info)
  548. of "fieldchecks": processOnOffSwitch(conf, {optFieldCheck}, arg, pass, info)
  549. of "rangechecks": processOnOffSwitch(conf, {optRangeCheck}, arg, pass, info)
  550. of "boundchecks": processOnOffSwitch(conf, {optBoundsCheck}, arg, pass, info)
  551. of "refchecks": processOnOffSwitch(conf, {optRefCheck}, arg, pass, info)
  552. of "overflowchecks": processOnOffSwitch(conf, {optOverflowCheck}, arg, pass, info)
  553. of "staticboundchecks": processOnOffSwitch(conf, {optStaticBoundsCheck}, arg, pass, info)
  554. of "stylechecks": processOnOffSwitch(conf, {optStyleCheck}, arg, pass, info)
  555. of "linedir": processOnOffSwitch(conf, {optLineDir}, arg, pass, info)
  556. of "assertions", "a": processOnOffSwitch(conf, {optAssert}, arg, pass, info)
  557. of "deadcodeelim": discard # deprecated, dead code elim always on
  558. of "threads":
  559. processOnOffSwitchG(conf, {optThreads}, arg, pass, info)
  560. #if optThreads in conf.globalOptions: conf.setNote(warnGcUnsafe)
  561. of "tlsemulation": processOnOffSwitchG(conf, {optTlsEmulation}, arg, pass, info)
  562. of "taintmode": processOnOffSwitchG(conf, {optTaintMode}, arg, pass, info)
  563. of "implicitstatic":
  564. processOnOffSwitch(conf, {optImplicitStatic}, arg, pass, info)
  565. of "patterns", "trmacros":
  566. processOnOffSwitch(conf, {optTrMacros}, arg, pass, info)
  567. of "opt":
  568. expectArg(conf, switch, arg, pass, info)
  569. case arg.normalize
  570. of "speed":
  571. incl(conf.options, optOptimizeSpeed)
  572. excl(conf.options, optOptimizeSize)
  573. of "size":
  574. excl(conf.options, optOptimizeSpeed)
  575. incl(conf.options, optOptimizeSize)
  576. of "none":
  577. excl(conf.options, optOptimizeSpeed)
  578. excl(conf.options, optOptimizeSize)
  579. else: localError(conf, info, errNoneSpeedOrSizeExpectedButXFound % arg)
  580. of "app":
  581. expectArg(conf, switch, arg, pass, info)
  582. case arg.normalize
  583. of "gui":
  584. incl(conf.globalOptions, optGenGuiApp)
  585. defineSymbol(conf.symbols, "executable")
  586. defineSymbol(conf.symbols, "guiapp")
  587. of "console":
  588. excl(conf.globalOptions, optGenGuiApp)
  589. defineSymbol(conf.symbols, "executable")
  590. defineSymbol(conf.symbols, "consoleapp")
  591. of "lib":
  592. incl(conf.globalOptions, optGenDynLib)
  593. excl(conf.globalOptions, optGenGuiApp)
  594. defineSymbol(conf.symbols, "library")
  595. defineSymbol(conf.symbols, "dll")
  596. of "staticlib":
  597. incl(conf.globalOptions, optGenStaticLib)
  598. excl(conf.globalOptions, optGenGuiApp)
  599. defineSymbol(conf.symbols, "library")
  600. defineSymbol(conf.symbols, "staticlib")
  601. else: localError(conf, info, errGuiConsoleOrLibExpectedButXFound % arg)
  602. of "passc", "t":
  603. expectArg(conf, switch, arg, pass, info)
  604. if pass in {passCmd2, passPP}: extccomp.addCompileOptionCmd(conf, arg)
  605. of "passl", "l":
  606. expectArg(conf, switch, arg, pass, info)
  607. if pass in {passCmd2, passPP}: extccomp.addLinkOptionCmd(conf, arg)
  608. of "cincludes":
  609. expectArg(conf, switch, arg, pass, info)
  610. if pass in {passCmd2, passPP}: conf.cIncludes.add processPath(conf, arg, info)
  611. of "clibdir":
  612. expectArg(conf, switch, arg, pass, info)
  613. if pass in {passCmd2, passPP}: conf.cLibs.add processPath(conf, arg, info)
  614. of "clib":
  615. expectArg(conf, switch, arg, pass, info)
  616. if pass in {passCmd2, passPP}:
  617. conf.cLinkedLibs.add processPath(conf, arg, info).string
  618. of "header":
  619. if conf != nil: conf.headerFile = arg
  620. incl(conf.globalOptions, optGenIndex)
  621. of "index":
  622. processOnOffSwitchG(conf, {optGenIndex}, arg, pass, info)
  623. of "import":
  624. expectArg(conf, switch, arg, pass, info)
  625. if pass in {passCmd2, passPP}:
  626. conf.implicitImports.add findModule(conf, arg, toFullPath(conf, info)).string
  627. of "include":
  628. expectArg(conf, switch, arg, pass, info)
  629. if pass in {passCmd2, passPP}:
  630. conf.implicitIncludes.add findModule(conf, arg, toFullPath(conf, info)).string
  631. of "listcmd":
  632. processOnOffSwitchG(conf, {optListCmd}, arg, pass, info)
  633. of "asm":
  634. processOnOffSwitchG(conf, {optProduceAsm}, arg, pass, info)
  635. of "genmapping":
  636. processOnOffSwitchG(conf, {optGenMapping}, arg, pass, info)
  637. of "os":
  638. expectArg(conf, switch, arg, pass, info)
  639. let theOS = platform.nameToOS(arg)
  640. if theOS == osNone:
  641. let osList = platform.listOSnames().join(", ")
  642. localError(conf, info, "unknown OS: '$1'. Available options are: $2" % [arg, $osList])
  643. else:
  644. setTarget(conf.target, theOS, conf.target.targetCPU)
  645. of "cpu":
  646. expectArg(conf, switch, arg, pass, info)
  647. let cpu = platform.nameToCPU(arg)
  648. if cpu == cpuNone:
  649. let cpuList = platform.listCPUnames().join(", ")
  650. localError(conf, info, "unknown CPU: '$1'. Available options are: $2" % [ arg, cpuList])
  651. else:
  652. setTarget(conf.target, conf.target.targetOS, cpu)
  653. of "run", "r":
  654. processOnOffSwitchG(conf, {optRun}, arg, pass, info)
  655. of "maxloopiterationsvm":
  656. expectArg(conf, switch, arg, pass, info)
  657. conf.maxLoopIterationsVM = parseInt(arg)
  658. of "errormax":
  659. expectArg(conf, switch, arg, pass, info)
  660. # Note: `nim check` (etc) can overwrite this.
  661. # `0` is meaningless, give it a useful meaning as in clang's -ferror-limit
  662. # If user doesn't set this flag and the code doesn't either, it'd
  663. # have the same effect as errorMax = 1
  664. let ret = parseInt(arg)
  665. conf.errorMax = if ret == 0: high(int) else: ret
  666. of "verbosity":
  667. expectArg(conf, switch, arg, pass, info)
  668. let verbosity = parseInt(arg)
  669. if verbosity notin {0..3}:
  670. localError(conf, info, "invalid verbosity level: '$1'" % arg)
  671. conf.verbosity = verbosity
  672. var verb = NotesVerbosity[conf.verbosity]
  673. ## We override the default `verb` by explicitly modified (set/unset) notes.
  674. conf.notes = (conf.modifiedyNotes * conf.notes + verb) -
  675. (conf.modifiedyNotes * verb - conf.notes)
  676. conf.mainPackageNotes = conf.notes
  677. of "parallelbuild":
  678. expectArg(conf, switch, arg, pass, info)
  679. conf.numberOfProcessors = parseInt(arg)
  680. of "version", "v":
  681. expectNoArg(conf, switch, arg, pass, info)
  682. writeVersionInfo(conf, pass)
  683. of "advanced":
  684. expectNoArg(conf, switch, arg, pass, info)
  685. writeAdvancedUsage(conf, pass)
  686. of "fullhelp":
  687. expectNoArg(conf, switch, arg, pass, info)
  688. writeFullhelp(conf, pass)
  689. of "help", "h":
  690. expectNoArg(conf, switch, arg, pass, info)
  691. helpOnError(conf, pass)
  692. of "symbolfiles": discard "ignore for backwards compat"
  693. of "incremental":
  694. when not nimIncremental:
  695. localError(conf, info, "the compiler was not built with " &
  696. "incremental compilation features; bootstrap with " &
  697. "-d:nimIncremental to enable")
  698. case arg.normalize
  699. of "on": conf.symbolFiles = v2Sf
  700. of "off": conf.symbolFiles = disabledSf
  701. of "writeonly": conf.symbolFiles = writeOnlySf
  702. of "readonly": conf.symbolFiles = readOnlySf
  703. of "v2": conf.symbolFiles = v2Sf
  704. else: localError(conf, info, "invalid option for --incremental: " & arg)
  705. of "skipcfg":
  706. processOnOffSwitchG(conf, {optSkipSystemConfigFile}, arg, pass, info)
  707. of "skipprojcfg":
  708. processOnOffSwitchG(conf, {optSkipProjConfigFile}, arg, pass, info)
  709. of "skipusercfg":
  710. processOnOffSwitchG(conf, {optSkipUserConfigFile}, arg, pass, info)
  711. of "skipparentcfg":
  712. processOnOffSwitchG(conf, {optSkipParentConfigFiles}, arg, pass, info)
  713. of "genscript", "gendeps":
  714. processOnOffSwitchG(conf, {optGenScript}, arg, pass, info)
  715. processOnOffSwitchG(conf, {optCompileOnly}, arg, pass, info)
  716. of "colors": processOnOffSwitchG(conf, {optUseColors}, arg, pass, info)
  717. of "lib":
  718. expectArg(conf, switch, arg, pass, info)
  719. conf.libpath = processPath(conf, arg, info, notRelativeToProj=true)
  720. of "putenv":
  721. expectArg(conf, switch, arg, pass, info)
  722. splitSwitch(conf, arg, key, val, pass, info)
  723. os.putEnv(key, val)
  724. of "cc":
  725. expectArg(conf, switch, arg, pass, info)
  726. setCC(conf, arg, info)
  727. of "track":
  728. expectArg(conf, switch, arg, pass, info)
  729. track(conf, arg, info)
  730. of "trackdirty":
  731. expectArg(conf, switch, arg, pass, info)
  732. trackDirty(conf, arg, info)
  733. of "suggest":
  734. expectNoArg(conf, switch, arg, pass, info)
  735. conf.ideCmd = ideSug
  736. of "def":
  737. expectNoArg(conf, switch, arg, pass, info)
  738. conf.ideCmd = ideDef
  739. of "eval":
  740. expectArg(conf, switch, arg, pass, info)
  741. conf.evalExpr = arg
  742. of "context":
  743. expectNoArg(conf, switch, arg, pass, info)
  744. conf.ideCmd = ideCon
  745. of "usages":
  746. expectNoArg(conf, switch, arg, pass, info)
  747. conf.ideCmd = ideUse
  748. of "stdout":
  749. processOnOffSwitchG(conf, {optStdout}, arg, pass, info)
  750. of "listfullpaths":
  751. processOnOffSwitchG(conf, {optListFullPaths}, arg, pass, info)
  752. of "dynliboverride":
  753. dynlibOverride(conf, switch, arg, pass, info)
  754. of "dynliboverrideall":
  755. processOnOffSwitchG(conf, {optDynlibOverrideAll}, arg, pass, info)
  756. of "cs":
  757. # only supported for compatibility. Does nothing.
  758. expectArg(conf, switch, arg, pass, info)
  759. of "experimental":
  760. if arg.len == 0:
  761. conf.features.incl oldExperimentalFeatures
  762. else:
  763. try:
  764. conf.features.incl parseEnum[Feature](arg)
  765. except ValueError:
  766. localError(conf, info, "unknown experimental feature")
  767. of "legacy":
  768. try:
  769. conf.legacyFeatures.incl parseEnum[LegacyFeature](arg)
  770. except ValueError:
  771. localError(conf, info, "unknown obsolete feature")
  772. of "nocppexceptions":
  773. expectNoArg(conf, switch, arg, pass, info)
  774. conf.exc = low(ExceptionSystem)
  775. defineSymbol(conf.symbols, "noCppExceptions")
  776. of "exceptions":
  777. case arg.normalize
  778. of "cpp": conf.exc = excCpp
  779. of "setjmp": conf.exc = excSetjmp
  780. of "quirky": conf.exc = excQuirky
  781. of "goto": conf.exc = excGoto
  782. else: localError(conf, info, errInvalidExceptionSystem % arg)
  783. of "cppdefine":
  784. expectArg(conf, switch, arg, pass, info)
  785. if conf != nil:
  786. conf.cppDefine(arg)
  787. of "newruntime":
  788. expectNoArg(conf, switch, arg, pass, info)
  789. if pass in {passCmd2, passPP}:
  790. doAssert(conf != nil)
  791. incl(conf.features, destructor)
  792. incl(conf.globalOptions, optTinyRtti)
  793. incl(conf.globalOptions, optOwnedRefs)
  794. incl(conf.globalOptions, optSeqDestructors)
  795. defineSymbol(conf.symbols, "nimV2")
  796. conf.selectedGC = gcHooks
  797. defineSymbol(conf.symbols, "gchooks")
  798. defineSymbol(conf.symbols, "nimSeqsV2")
  799. defineSymbol(conf.symbols, "nimOwnedEnabled")
  800. of "seqsv2":
  801. processOnOffSwitchG(conf, {optSeqDestructors}, arg, pass, info)
  802. if pass in {passCmd2, passPP}:
  803. defineSymbol(conf.symbols, "nimSeqsV2")
  804. of "stylecheck":
  805. case arg.normalize
  806. of "off": conf.globalOptions = conf.globalOptions - {optStyleHint, optStyleError}
  807. of "hint": conf.globalOptions = conf.globalOptions + {optStyleHint} - {optStyleError}
  808. of "error": conf.globalOptions = conf.globalOptions + {optStyleError}
  809. else: localError(conf, info, errOffHintsError % arg)
  810. of "showallmismatches":
  811. processOnOffSwitchG(conf, {optShowAllMismatches}, arg, pass, info)
  812. of "cppcompiletonamespace":
  813. if arg.len > 0:
  814. conf.cppCustomNamespace = arg
  815. else:
  816. conf.cppCustomNamespace = "Nim"
  817. defineSymbol(conf.symbols, "cppCompileToNamespace", conf.cppCustomNamespace)
  818. of "docinternal":
  819. processOnOffSwitchG(conf, {optDocInternal}, arg, pass, info)
  820. of "multimethods":
  821. processOnOffSwitchG(conf, {optMultiMethods}, arg, pass, info)
  822. of "expandmacro":
  823. expectArg(conf, switch, arg, pass, info)
  824. conf.macrosToExpand[arg] = "T"
  825. of "expandarc":
  826. expectArg(conf, switch, arg, pass, info)
  827. conf.arcToExpand[arg] = "T"
  828. of "useversion":
  829. expectArg(conf, switch, arg, pass, info)
  830. case arg
  831. of "1.0":
  832. defineSymbol(conf.symbols, "NimMajor", "1")
  833. defineSymbol(conf.symbols, "NimMinor", "0")
  834. # always be compatible with 1.0.100:
  835. defineSymbol(conf.symbols, "NimPatch", "100")
  836. # old behaviors go here:
  837. defineSymbol(conf.symbols, "nimOldRelativePathBehavior")
  838. undefSymbol(conf.symbols, "nimDoesntTrackDefects")
  839. ast.eqTypeFlags.excl {tfGcSafe, tfNoSideEffect}
  840. conf.globalOptions.incl optNimV1Emulation
  841. of "1.2":
  842. defineSymbol(conf.symbols, "NimMajor", "1")
  843. defineSymbol(conf.symbols, "NimMinor", "2")
  844. # always be compatible with 1.2.100:
  845. defineSymbol(conf.symbols, "NimPatch", "100")
  846. conf.globalOptions.incl optNimV12Emulation
  847. else:
  848. localError(conf, info, "unknown Nim version; currently supported values are: {1.0}")
  849. of "benchmarkvm":
  850. processOnOffSwitchG(conf, {optBenchmarkVM}, arg, pass, info)
  851. of "profilevm":
  852. processOnOffSwitchG(conf, {optProfileVM}, arg, pass, info)
  853. of "sinkinference":
  854. processOnOffSwitch(conf, {optSinkInference}, arg, pass, info)
  855. of "cursorinference":
  856. # undocumented, for debugging purposes only:
  857. processOnOffSwitch(conf, {optCursorInference}, arg, pass, info)
  858. of "panics":
  859. processOnOffSwitchG(conf, {optPanics}, arg, pass, info)
  860. if optPanics in conf.globalOptions:
  861. defineSymbol(conf.symbols, "nimPanics")
  862. of "sourcemap":
  863. conf.globalOptions.incl optSourcemap
  864. conf.options.incl optLineDir
  865. of "deepcopy":
  866. processOnOffSwitchG(conf, {optEnableDeepCopy}, arg, pass, info)
  867. of "": # comes from "-" in for example: `nim c -r -` (gets stripped from -)
  868. handleStdinInput(conf)
  869. else:
  870. if strutils.find(switch, '.') >= 0: options.setConfigVar(conf, switch, arg)
  871. else: invalidCmdLineOption(conf, pass, switch, info)
  872. proc processCommand*(switch: string, pass: TCmdLinePass; config: ConfigRef) =
  873. var cmd, arg: string
  874. splitSwitch(config, switch, cmd, arg, pass, gCmdLineInfo)
  875. processSwitch(cmd, arg, pass, gCmdLineInfo, config)
  876. proc processSwitch*(pass: TCmdLinePass; p: OptParser; config: ConfigRef) =
  877. # hint[X]:off is parsed as (p.key = "hint[X]", p.val = "off")
  878. # we transform it to (key = hint, val = [X]:off)
  879. var bracketLe = strutils.find(p.key, '[')
  880. if bracketLe >= 0:
  881. var key = substr(p.key, 0, bracketLe - 1)
  882. var val = substr(p.key, bracketLe) & ':' & p.val
  883. processSwitch(key, val, pass, gCmdLineInfo, config)
  884. else:
  885. processSwitch(p.key, p.val, pass, gCmdLineInfo, config)
  886. proc processArgument*(pass: TCmdLinePass; p: OptParser;
  887. argsCount: var int; config: ConfigRef): bool =
  888. if argsCount == 0:
  889. # nim filename.nims is the same as "nim e filename.nims":
  890. if p.key.endsWith(".nims"):
  891. config.command = "e"
  892. incl(config.globalOptions, optWasNimscript)
  893. config.projectName = unixToNativePath(p.key)
  894. config.arguments = cmdLineRest(p)
  895. result = true
  896. elif pass != passCmd2:
  897. config.command = p.key
  898. else:
  899. if pass == passCmd1: config.commandArgs.add p.key
  900. if argsCount == 1:
  901. # support UNIX style filenames everywhere for portable build scripts:
  902. if config.projectName.len == 0:
  903. config.projectName = unixToNativePath(p.key)
  904. config.arguments = cmdLineRest(p)
  905. result = true
  906. inc argsCount