commands.nim 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974
  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(hintMin, hintMax, id, errUnknown)
  167. if x != errUnknown: n = TNoteKind(x)
  168. else: localError(conf, info, "unknown hint: " & id)
  169. else:
  170. let x = findStr(warnMin, warnMax, id, errUnknown)
  171. if x != errUnknown: n = TNoteKind(x)
  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. template handleStdinOrCmdInput =
  343. conf.projectFull = conf.projectName.AbsoluteFile
  344. conf.projectPath = AbsoluteDir getCurrentDir()
  345. if conf.outDir.isEmpty:
  346. conf.outDir = getNimcacheDir(conf)
  347. proc handleStdinInput*(conf: ConfigRef) =
  348. conf.projectName = "stdinfile"
  349. conf.projectIsStdin = true
  350. handleStdinOrCmdInput()
  351. proc handleCmdInput*(conf: ConfigRef) =
  352. conf.projectName = "cmdfile"
  353. handleStdinOrCmdInput()
  354. proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
  355. conf: ConfigRef) =
  356. var
  357. key, val: string
  358. case switch.normalize
  359. of "eval":
  360. expectArg(conf, switch, arg, pass, info)
  361. conf.projectIsCmd = true
  362. conf.cmdInput = arg # can be empty (a nim file with empty content is valid too)
  363. if conf.command == "":
  364. conf.command = "e" # better than "r" as a default
  365. conf.implicitCmd = true
  366. of "path", "p":
  367. expectArg(conf, switch, arg, pass, info)
  368. for path in nimbleSubs(conf, arg):
  369. addPath(conf, if pass == passPP: processCfgPath(conf, path, info)
  370. else: processPath(conf, path, info), info)
  371. of "nimblepath", "babelpath":
  372. # keep the old name for compat
  373. if pass in {passCmd2, passPP} and optNoNimblePath notin conf.globalOptions:
  374. expectArg(conf, switch, arg, pass, info)
  375. var path = processPath(conf, arg, info, notRelativeToProj=true)
  376. let nimbleDir = AbsoluteDir getEnv("NIMBLE_DIR")
  377. if not nimbleDir.isEmpty and pass == passPP:
  378. path = nimbleDir / RelativeDir"pkgs"
  379. nimblePath(conf, path, info)
  380. of "nonimblepath", "nobabelpath":
  381. expectNoArg(conf, switch, arg, pass, info)
  382. disableNimblePath(conf)
  383. of "clearnimblepath":
  384. expectNoArg(conf, switch, arg, pass, info)
  385. clearNimblePath(conf)
  386. of "excludepath":
  387. expectArg(conf, switch, arg, pass, info)
  388. let path = processPath(conf, arg, info)
  389. conf.searchPaths.keepItIf(it != path)
  390. conf.lazyPaths.keepItIf(it != path)
  391. of "nimcache":
  392. expectArg(conf, switch, arg, pass, info)
  393. conf.nimcacheDir = processPath(conf, arg, info, notRelativeToProj=true)
  394. of "out", "o":
  395. expectArg(conf, switch, arg, pass, info)
  396. let f = splitFile(processPath(conf, arg, info, notRelativeToProj=true).string)
  397. conf.outFile = RelativeFile f.name & f.ext
  398. conf.outDir = toAbsoluteDir f.dir
  399. of "outdir":
  400. expectArg(conf, switch, arg, pass, info)
  401. conf.outDir = processPath(conf, arg, info, notRelativeToProj=true)
  402. of "usenimcache":
  403. processOnOffSwitchG(conf, {optUseNimcache}, arg, pass, info)
  404. of "docseesrcurl":
  405. expectArg(conf, switch, arg, pass, info)
  406. conf.docSeeSrcUrl = arg
  407. of "docroot":
  408. conf.docRoot = if arg.len == 0: docRootDefault else: arg
  409. of "backend", "b":
  410. let backend = parseEnum(arg.normalize, TBackend.default)
  411. if backend == TBackend.default: localError(conf, info, "invalid backend: '$1'" % arg)
  412. conf.backend = backend
  413. of "doccmd": conf.docCmd = arg
  414. of "mainmodule", "m":
  415. discard "allow for backwards compatibility, but don't do anything"
  416. of "define", "d":
  417. expectArg(conf, switch, arg, pass, info)
  418. if {':', '='} in arg:
  419. splitSwitch(conf, arg, key, val, pass, info)
  420. if cmpIgnoreStyle(key, "nimQuirky") == 0:
  421. conf.exc = excQuirky
  422. defineSymbol(conf.symbols, key, val)
  423. else:
  424. if cmpIgnoreStyle(arg, "nimQuirky") == 0:
  425. conf.exc = excQuirky
  426. defineSymbol(conf.symbols, arg)
  427. of "undef", "u":
  428. expectArg(conf, switch, arg, pass, info)
  429. undefSymbol(conf.symbols, arg)
  430. of "symbol":
  431. expectArg(conf, switch, arg, pass, info)
  432. # deprecated, do nothing
  433. of "compile":
  434. expectArg(conf, switch, arg, pass, info)
  435. if pass in {passCmd2, passPP}: processCompile(conf, arg)
  436. of "link":
  437. expectArg(conf, switch, arg, pass, info)
  438. if pass in {passCmd2, passPP}:
  439. addExternalFileToLink(conf, AbsoluteFile arg)
  440. of "debuginfo":
  441. processOnOffSwitchG(conf, {optCDebug}, arg, pass, info)
  442. of "embedsrc":
  443. processOnOffSwitchG(conf, {optEmbedOrigSrc}, arg, pass, info)
  444. of "compileonly", "c":
  445. processOnOffSwitchG(conf, {optCompileOnly}, arg, pass, info)
  446. of "nolinking":
  447. processOnOffSwitchG(conf, {optNoLinking}, arg, pass, info)
  448. of "nomain":
  449. processOnOffSwitchG(conf, {optNoMain}, arg, pass, info)
  450. of "forcebuild", "f":
  451. processOnOffSwitchG(conf, {optForceFullMake}, arg, pass, info)
  452. of "project":
  453. processOnOffSwitchG(conf, {optWholeProject, optGenIndex}, arg, pass, info)
  454. of "gc":
  455. if conf.backend == backendJs or conf.command == "js":
  456. # for: bug #16033
  457. # This might still be imperfect, in rarse corner cases
  458. # (where command is reset in nimscript, maybe).
  459. return
  460. expectArg(conf, switch, arg, pass, info)
  461. if pass in {passCmd2, passPP}:
  462. case arg.normalize
  463. of "boehm":
  464. conf.selectedGC = gcBoehm
  465. defineSymbol(conf.symbols, "boehmgc")
  466. incl conf.globalOptions, optTlsEmulation # Boehm GC doesn't scan the real TLS
  467. of "refc":
  468. conf.selectedGC = gcRefc
  469. of "v2":
  470. message(conf, info, warnDeprecated, "--gc:v2 is deprecated; using default gc")
  471. of "markandsweep":
  472. conf.selectedGC = gcMarkAndSweep
  473. defineSymbol(conf.symbols, "gcmarkandsweep")
  474. of "destructors", "arc":
  475. conf.selectedGC = gcArc
  476. defineSymbol(conf.symbols, "gcdestructors")
  477. defineSymbol(conf.symbols, "gcarc")
  478. incl conf.globalOptions, optSeqDestructors
  479. incl conf.globalOptions, optTinyRtti
  480. if pass in {passCmd2, passPP}:
  481. defineSymbol(conf.symbols, "nimSeqsV2")
  482. defineSymbol(conf.symbols, "nimV2")
  483. of "orc":
  484. conf.selectedGC = gcOrc
  485. defineSymbol(conf.symbols, "gcdestructors")
  486. defineSymbol(conf.symbols, "gcorc")
  487. incl conf.globalOptions, optSeqDestructors
  488. incl conf.globalOptions, optTinyRtti
  489. if pass in {passCmd2, passPP}:
  490. defineSymbol(conf.symbols, "nimSeqsV2")
  491. defineSymbol(conf.symbols, "nimV2")
  492. of "hooks":
  493. conf.selectedGC = gcHooks
  494. defineSymbol(conf.symbols, "gchooks")
  495. incl conf.globalOptions, optSeqDestructors
  496. processOnOffSwitchG(conf, {optSeqDestructors}, arg, pass, info)
  497. if pass in {passCmd2, passPP}:
  498. defineSymbol(conf.symbols, "nimSeqsV2")
  499. of "go":
  500. conf.selectedGC = gcGo
  501. defineSymbol(conf.symbols, "gogc")
  502. of "none":
  503. conf.selectedGC = gcNone
  504. defineSymbol(conf.symbols, "nogc")
  505. of "stack", "regions":
  506. conf.selectedGC = gcRegions
  507. defineSymbol(conf.symbols, "gcregions")
  508. else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
  509. of "warnings", "w":
  510. if processOnOffSwitchOrList(conf, {optWarns}, arg, pass, info): listWarnings(conf)
  511. of "warning": processSpecificNote(arg, wWarning, pass, info, switch, conf)
  512. of "hint": processSpecificNote(arg, wHint, pass, info, switch, conf)
  513. of "warningaserror": processSpecificNote(arg, wWarningAsError, pass, info, switch, conf)
  514. of "hints":
  515. if processOnOffSwitchOrList(conf, {optHints}, arg, pass, info): listHints(conf)
  516. of "threadanalysis": processOnOffSwitchG(conf, {optThreadAnalysis}, arg, pass, info)
  517. of "stacktrace": processOnOffSwitch(conf, {optStackTrace}, arg, pass, info)
  518. of "stacktracemsgs": processOnOffSwitch(conf, {optStackTraceMsgs}, arg, pass, info)
  519. of "excessivestacktrace": processOnOffSwitchG(conf, {optExcessiveStackTrace}, arg, pass, info)
  520. of "linetrace": processOnOffSwitch(conf, {optLineTrace}, arg, pass, info)
  521. of "debugger":
  522. case arg.normalize
  523. of "on", "native", "gdb":
  524. conf.globalOptions.incl optCDebug
  525. conf.options.incl optLineDir
  526. #defineSymbol(conf.symbols, "nimTypeNames") # type names are used in gdb pretty printing
  527. of "off":
  528. conf.globalOptions.excl optCDebug
  529. else:
  530. localError(conf, info, "expected native|gdb|on|off but found " & arg)
  531. of "g": # alias for --debugger:native
  532. conf.globalOptions.incl optCDebug
  533. conf.options.incl optLineDir
  534. #defineSymbol(conf.symbols, "nimTypeNames") # type names are used in gdb pretty printing
  535. of "profiler":
  536. processOnOffSwitch(conf, {optProfiler}, arg, pass, info)
  537. if optProfiler in conf.options: defineSymbol(conf.symbols, "profiler")
  538. else: undefSymbol(conf.symbols, "profiler")
  539. of "memtracker":
  540. processOnOffSwitch(conf, {optMemTracker}, arg, pass, info)
  541. if optMemTracker in conf.options: defineSymbol(conf.symbols, "memtracker")
  542. else: undefSymbol(conf.symbols, "memtracker")
  543. of "hotcodereloading":
  544. processOnOffSwitchG(conf, {optHotCodeReloading}, arg, pass, info)
  545. if conf.hcrOn:
  546. defineSymbol(conf.symbols, "hotcodereloading")
  547. defineSymbol(conf.symbols, "useNimRtl")
  548. # hardcoded linking with dynamic runtime for MSVC for smaller binaries
  549. # should do the same for all compilers (wherever applicable)
  550. if isVSCompatible(conf):
  551. extccomp.addCompileOptionCmd(conf, "/MD")
  552. else:
  553. undefSymbol(conf.symbols, "hotcodereloading")
  554. undefSymbol(conf.symbols, "useNimRtl")
  555. of "nilseqs": processOnOffSwitch(conf, {optNilSeqs}, arg, pass, info)
  556. of "checks", "x": processOnOffSwitch(conf, ChecksOptions, arg, pass, info)
  557. of "floatchecks":
  558. processOnOffSwitch(conf, {optNaNCheck, optInfCheck}, arg, pass, info)
  559. of "infchecks": processOnOffSwitch(conf, {optInfCheck}, arg, pass, info)
  560. of "nanchecks": processOnOffSwitch(conf, {optNaNCheck}, arg, pass, info)
  561. of "nilchecks": discard "no such thing anymore"
  562. of "objchecks": processOnOffSwitch(conf, {optObjCheck}, arg, pass, info)
  563. of "fieldchecks": processOnOffSwitch(conf, {optFieldCheck}, arg, pass, info)
  564. of "rangechecks": processOnOffSwitch(conf, {optRangeCheck}, arg, pass, info)
  565. of "boundchecks": processOnOffSwitch(conf, {optBoundsCheck}, arg, pass, info)
  566. of "refchecks": processOnOffSwitch(conf, {optRefCheck}, arg, pass, info)
  567. of "overflowchecks": processOnOffSwitch(conf, {optOverflowCheck}, arg, pass, info)
  568. of "staticboundchecks": processOnOffSwitch(conf, {optStaticBoundsCheck}, arg, pass, info)
  569. of "stylechecks": processOnOffSwitch(conf, {optStyleCheck}, arg, pass, info)
  570. of "linedir": processOnOffSwitch(conf, {optLineDir}, arg, pass, info)
  571. of "assertions", "a": processOnOffSwitch(conf, {optAssert}, arg, pass, info)
  572. of "deadcodeelim": discard # deprecated, dead code elim always on
  573. of "threads":
  574. processOnOffSwitchG(conf, {optThreads}, arg, pass, info)
  575. #if optThreads in conf.globalOptions: conf.setNote(warnGcUnsafe)
  576. of "tlsemulation": processOnOffSwitchG(conf, {optTlsEmulation}, arg, pass, info)
  577. of "taintmode": processOnOffSwitchG(conf, {optTaintMode}, arg, pass, info)
  578. of "implicitstatic":
  579. processOnOffSwitch(conf, {optImplicitStatic}, arg, pass, info)
  580. of "patterns", "trmacros":
  581. processOnOffSwitch(conf, {optTrMacros}, arg, pass, info)
  582. of "opt":
  583. expectArg(conf, switch, arg, pass, info)
  584. case arg.normalize
  585. of "speed":
  586. incl(conf.options, optOptimizeSpeed)
  587. excl(conf.options, optOptimizeSize)
  588. of "size":
  589. excl(conf.options, optOptimizeSpeed)
  590. incl(conf.options, optOptimizeSize)
  591. of "none":
  592. excl(conf.options, optOptimizeSpeed)
  593. excl(conf.options, optOptimizeSize)
  594. else: localError(conf, info, errNoneSpeedOrSizeExpectedButXFound % arg)
  595. of "app":
  596. expectArg(conf, switch, arg, pass, info)
  597. case arg.normalize
  598. of "gui":
  599. incl(conf.globalOptions, optGenGuiApp)
  600. defineSymbol(conf.symbols, "executable")
  601. defineSymbol(conf.symbols, "guiapp")
  602. of "console":
  603. excl(conf.globalOptions, optGenGuiApp)
  604. defineSymbol(conf.symbols, "executable")
  605. defineSymbol(conf.symbols, "consoleapp")
  606. of "lib":
  607. incl(conf.globalOptions, optGenDynLib)
  608. excl(conf.globalOptions, optGenGuiApp)
  609. defineSymbol(conf.symbols, "library")
  610. defineSymbol(conf.symbols, "dll")
  611. of "staticlib":
  612. incl(conf.globalOptions, optGenStaticLib)
  613. excl(conf.globalOptions, optGenGuiApp)
  614. defineSymbol(conf.symbols, "library")
  615. defineSymbol(conf.symbols, "staticlib")
  616. else: localError(conf, info, errGuiConsoleOrLibExpectedButXFound % arg)
  617. of "passc", "t":
  618. expectArg(conf, switch, arg, pass, info)
  619. if pass in {passCmd2, passPP}: extccomp.addCompileOptionCmd(conf, arg)
  620. of "passl", "l":
  621. expectArg(conf, switch, arg, pass, info)
  622. if pass in {passCmd2, passPP}: extccomp.addLinkOptionCmd(conf, arg)
  623. of "cincludes":
  624. expectArg(conf, switch, arg, pass, info)
  625. if pass in {passCmd2, passPP}: conf.cIncludes.add processPath(conf, arg, info)
  626. of "clibdir":
  627. expectArg(conf, switch, arg, pass, info)
  628. if pass in {passCmd2, passPP}: conf.cLibs.add processPath(conf, arg, info)
  629. of "clib":
  630. expectArg(conf, switch, arg, pass, info)
  631. if pass in {passCmd2, passPP}:
  632. conf.cLinkedLibs.add processPath(conf, arg, info).string
  633. of "header":
  634. if conf != nil: conf.headerFile = arg
  635. incl(conf.globalOptions, optGenIndex)
  636. of "index":
  637. processOnOffSwitchG(conf, {optGenIndex}, arg, pass, info)
  638. of "import":
  639. expectArg(conf, switch, arg, pass, info)
  640. if pass in {passCmd2, passPP}:
  641. conf.implicitImports.add findModule(conf, arg, toFullPath(conf, info)).string
  642. of "include":
  643. expectArg(conf, switch, arg, pass, info)
  644. if pass in {passCmd2, passPP}:
  645. conf.implicitIncludes.add findModule(conf, arg, toFullPath(conf, info)).string
  646. of "listcmd":
  647. processOnOffSwitchG(conf, {optListCmd}, arg, pass, info)
  648. of "asm":
  649. processOnOffSwitchG(conf, {optProduceAsm}, arg, pass, info)
  650. of "genmapping":
  651. processOnOffSwitchG(conf, {optGenMapping}, arg, pass, info)
  652. of "os":
  653. expectArg(conf, switch, arg, pass, info)
  654. let theOS = platform.nameToOS(arg)
  655. if theOS == osNone:
  656. let osList = platform.listOSnames().join(", ")
  657. localError(conf, info, "unknown OS: '$1'. Available options are: $2" % [arg, $osList])
  658. else:
  659. setTarget(conf.target, theOS, conf.target.targetCPU)
  660. of "cpu":
  661. expectArg(conf, switch, arg, pass, info)
  662. let cpu = platform.nameToCPU(arg)
  663. if cpu == cpuNone:
  664. let cpuList = platform.listCPUnames().join(", ")
  665. localError(conf, info, "unknown CPU: '$1'. Available options are: $2" % [ arg, cpuList])
  666. else:
  667. setTarget(conf.target, conf.target.targetOS, cpu)
  668. of "run", "r":
  669. processOnOffSwitchG(conf, {optRun}, arg, pass, info)
  670. of "maxloopiterationsvm":
  671. expectArg(conf, switch, arg, pass, info)
  672. conf.maxLoopIterationsVM = parseInt(arg)
  673. of "errormax":
  674. expectArg(conf, switch, arg, pass, info)
  675. # Note: `nim check` (etc) can overwrite this.
  676. # `0` is meaningless, give it a useful meaning as in clang's -ferror-limit
  677. # If user doesn't set this flag and the code doesn't either, it'd
  678. # have the same effect as errorMax = 1
  679. let ret = parseInt(arg)
  680. conf.errorMax = if ret == 0: high(int) else: ret
  681. of "verbosity":
  682. expectArg(conf, switch, arg, pass, info)
  683. let verbosity = parseInt(arg)
  684. if verbosity notin {0..3}:
  685. localError(conf, info, "invalid verbosity level: '$1'" % arg)
  686. conf.verbosity = verbosity
  687. var verb = NotesVerbosity[conf.verbosity]
  688. ## We override the default `verb` by explicitly modified (set/unset) notes.
  689. conf.notes = (conf.modifiedyNotes * conf.notes + verb) -
  690. (conf.modifiedyNotes * verb - conf.notes)
  691. conf.mainPackageNotes = conf.notes
  692. of "parallelbuild":
  693. expectArg(conf, switch, arg, pass, info)
  694. conf.numberOfProcessors = parseInt(arg)
  695. of "version", "v":
  696. expectNoArg(conf, switch, arg, pass, info)
  697. writeVersionInfo(conf, pass)
  698. of "advanced":
  699. expectNoArg(conf, switch, arg, pass, info)
  700. writeAdvancedUsage(conf, pass)
  701. of "fullhelp":
  702. expectNoArg(conf, switch, arg, pass, info)
  703. writeFullhelp(conf, pass)
  704. of "help", "h":
  705. expectNoArg(conf, switch, arg, pass, info)
  706. helpOnError(conf, pass)
  707. of "symbolfiles": discard "ignore for backwards compat"
  708. of "incremental":
  709. when not nimIncremental:
  710. localError(conf, info, "the compiler was not built with " &
  711. "incremental compilation features; bootstrap with " &
  712. "-d:nimIncremental to enable")
  713. case arg.normalize
  714. of "on": conf.symbolFiles = v2Sf
  715. of "off": conf.symbolFiles = disabledSf
  716. of "writeonly": conf.symbolFiles = writeOnlySf
  717. of "readonly": conf.symbolFiles = readOnlySf
  718. of "v2": conf.symbolFiles = v2Sf
  719. else: localError(conf, info, "invalid option for --incremental: " & arg)
  720. of "skipcfg":
  721. processOnOffSwitchG(conf, {optSkipSystemConfigFile}, arg, pass, info)
  722. of "skipprojcfg":
  723. processOnOffSwitchG(conf, {optSkipProjConfigFile}, arg, pass, info)
  724. of "skipusercfg":
  725. processOnOffSwitchG(conf, {optSkipUserConfigFile}, arg, pass, info)
  726. of "skipparentcfg":
  727. processOnOffSwitchG(conf, {optSkipParentConfigFiles}, arg, pass, info)
  728. of "genscript", "gendeps":
  729. processOnOffSwitchG(conf, {optGenScript}, arg, pass, info)
  730. processOnOffSwitchG(conf, {optCompileOnly}, arg, pass, info)
  731. of "colors": processOnOffSwitchG(conf, {optUseColors}, arg, pass, info)
  732. of "lib":
  733. expectArg(conf, switch, arg, pass, info)
  734. conf.libpath = processPath(conf, arg, info, notRelativeToProj=true)
  735. of "putenv":
  736. expectArg(conf, switch, arg, pass, info)
  737. splitSwitch(conf, arg, key, val, pass, info)
  738. os.putEnv(key, val)
  739. of "cc":
  740. expectArg(conf, switch, arg, pass, info)
  741. setCC(conf, arg, info)
  742. of "track":
  743. expectArg(conf, switch, arg, pass, info)
  744. track(conf, arg, info)
  745. of "trackdirty":
  746. expectArg(conf, switch, arg, pass, info)
  747. trackDirty(conf, arg, info)
  748. of "suggest":
  749. expectNoArg(conf, switch, arg, pass, info)
  750. conf.ideCmd = ideSug
  751. of "def":
  752. expectNoArg(conf, switch, arg, pass, info)
  753. conf.ideCmd = ideDef
  754. of "context":
  755. expectNoArg(conf, switch, arg, pass, info)
  756. conf.ideCmd = ideCon
  757. of "usages":
  758. expectNoArg(conf, switch, arg, pass, info)
  759. conf.ideCmd = ideUse
  760. of "stdout":
  761. processOnOffSwitchG(conf, {optStdout}, arg, pass, info)
  762. of "listfullpaths":
  763. processOnOffSwitchG(conf, {optListFullPaths}, arg, pass, info)
  764. of "declaredlocs":
  765. processOnOffSwitchG(conf, {optDeclaredLocs}, arg, pass, info)
  766. of "dynliboverride":
  767. dynlibOverride(conf, switch, arg, pass, info)
  768. of "dynliboverrideall":
  769. processOnOffSwitchG(conf, {optDynlibOverrideAll}, arg, pass, info)
  770. of "cs":
  771. # only supported for compatibility. Does nothing.
  772. expectArg(conf, switch, arg, pass, info)
  773. of "experimental":
  774. if arg.len == 0:
  775. conf.features.incl oldExperimentalFeatures
  776. else:
  777. try:
  778. conf.features.incl parseEnum[Feature](arg)
  779. except ValueError:
  780. localError(conf, info, "unknown experimental feature")
  781. of "legacy":
  782. try:
  783. conf.legacyFeatures.incl parseEnum[LegacyFeature](arg)
  784. except ValueError:
  785. localError(conf, info, "unknown obsolete feature")
  786. of "nocppexceptions":
  787. expectNoArg(conf, switch, arg, pass, info)
  788. conf.exc = low(ExceptionSystem)
  789. defineSymbol(conf.symbols, "noCppExceptions")
  790. of "exceptions":
  791. case arg.normalize
  792. of "cpp": conf.exc = excCpp
  793. of "setjmp": conf.exc = excSetjmp
  794. of "quirky": conf.exc = excQuirky
  795. of "goto": conf.exc = excGoto
  796. else: localError(conf, info, errInvalidExceptionSystem % arg)
  797. of "cppdefine":
  798. expectArg(conf, switch, arg, pass, info)
  799. if conf != nil:
  800. conf.cppDefine(arg)
  801. of "newruntime":
  802. expectNoArg(conf, switch, arg, pass, info)
  803. if pass in {passCmd2, passPP}:
  804. doAssert(conf != nil)
  805. incl(conf.features, destructor)
  806. incl(conf.globalOptions, optTinyRtti)
  807. incl(conf.globalOptions, optOwnedRefs)
  808. incl(conf.globalOptions, optSeqDestructors)
  809. defineSymbol(conf.symbols, "nimV2")
  810. conf.selectedGC = gcHooks
  811. defineSymbol(conf.symbols, "gchooks")
  812. defineSymbol(conf.symbols, "nimSeqsV2")
  813. defineSymbol(conf.symbols, "nimOwnedEnabled")
  814. of "seqsv2":
  815. processOnOffSwitchG(conf, {optSeqDestructors}, arg, pass, info)
  816. if pass in {passCmd2, passPP}:
  817. defineSymbol(conf.symbols, "nimSeqsV2")
  818. of "stylecheck":
  819. case arg.normalize
  820. of "off": conf.globalOptions = conf.globalOptions - {optStyleHint, optStyleError}
  821. of "hint": conf.globalOptions = conf.globalOptions + {optStyleHint} - {optStyleError}
  822. of "error": conf.globalOptions = conf.globalOptions + {optStyleError}
  823. else: localError(conf, info, errOffHintsError % arg)
  824. of "showallmismatches":
  825. processOnOffSwitchG(conf, {optShowAllMismatches}, arg, pass, info)
  826. of "cppcompiletonamespace":
  827. if arg.len > 0:
  828. conf.cppCustomNamespace = arg
  829. else:
  830. conf.cppCustomNamespace = "Nim"
  831. defineSymbol(conf.symbols, "cppCompileToNamespace", conf.cppCustomNamespace)
  832. of "docinternal":
  833. processOnOffSwitchG(conf, {optDocInternal}, arg, pass, info)
  834. of "multimethods":
  835. processOnOffSwitchG(conf, {optMultiMethods}, arg, pass, info)
  836. of "expandmacro":
  837. expectArg(conf, switch, arg, pass, info)
  838. conf.macrosToExpand[arg] = "T"
  839. of "expandarc":
  840. expectArg(conf, switch, arg, pass, info)
  841. conf.arcToExpand[arg] = "T"
  842. of "useversion":
  843. expectArg(conf, switch, arg, pass, info)
  844. case arg
  845. of "1.0":
  846. defineSymbol(conf.symbols, "NimMajor", "1")
  847. defineSymbol(conf.symbols, "NimMinor", "0")
  848. # always be compatible with 1.0.100:
  849. defineSymbol(conf.symbols, "NimPatch", "100")
  850. # old behaviors go here:
  851. defineSymbol(conf.symbols, "nimOldRelativePathBehavior")
  852. undefSymbol(conf.symbols, "nimDoesntTrackDefects")
  853. ast.eqTypeFlags.excl {tfGcSafe, tfNoSideEffect}
  854. conf.globalOptions.incl optNimV1Emulation
  855. of "1.2":
  856. defineSymbol(conf.symbols, "NimMajor", "1")
  857. defineSymbol(conf.symbols, "NimMinor", "2")
  858. # always be compatible with 1.2.100:
  859. defineSymbol(conf.symbols, "NimPatch", "100")
  860. conf.globalOptions.incl optNimV12Emulation
  861. else:
  862. localError(conf, info, "unknown Nim version; currently supported values are: {1.0}")
  863. of "benchmarkvm":
  864. processOnOffSwitchG(conf, {optBenchmarkVM}, arg, pass, info)
  865. of "profilevm":
  866. processOnOffSwitchG(conf, {optProfileVM}, arg, pass, info)
  867. of "sinkinference":
  868. processOnOffSwitch(conf, {optSinkInference}, arg, pass, info)
  869. of "cursorinference":
  870. # undocumented, for debugging purposes only:
  871. processOnOffSwitch(conf, {optCursorInference}, arg, pass, info)
  872. of "panics":
  873. processOnOffSwitchG(conf, {optPanics}, arg, pass, info)
  874. if optPanics in conf.globalOptions:
  875. defineSymbol(conf.symbols, "nimPanics")
  876. of "sourcemap":
  877. conf.globalOptions.incl optSourcemap
  878. conf.options.incl optLineDir
  879. of "deepcopy":
  880. processOnOffSwitchG(conf, {optEnableDeepCopy}, arg, pass, info)
  881. of "": # comes from "-" in for example: `nim c -r -` (gets stripped from -)
  882. handleStdinInput(conf)
  883. else:
  884. if strutils.find(switch, '.') >= 0: options.setConfigVar(conf, switch, arg)
  885. else: invalidCmdLineOption(conf, pass, switch, info)
  886. proc processCommand*(switch: string, pass: TCmdLinePass; config: ConfigRef) =
  887. var cmd, arg: string
  888. splitSwitch(config, switch, cmd, arg, pass, gCmdLineInfo)
  889. processSwitch(cmd, arg, pass, gCmdLineInfo, config)
  890. proc processSwitch*(pass: TCmdLinePass; p: OptParser; config: ConfigRef) =
  891. # hint[X]:off is parsed as (p.key = "hint[X]", p.val = "off")
  892. # we transform it to (key = hint, val = [X]:off)
  893. var bracketLe = strutils.find(p.key, '[')
  894. if bracketLe >= 0:
  895. var key = substr(p.key, 0, bracketLe - 1)
  896. var val = substr(p.key, bracketLe) & ':' & p.val
  897. processSwitch(key, val, pass, gCmdLineInfo, config)
  898. else:
  899. processSwitch(p.key, p.val, pass, gCmdLineInfo, config)
  900. proc processArgument*(pass: TCmdLinePass; p: OptParser;
  901. argsCount: var int; config: ConfigRef): bool =
  902. if argsCount == 0 and config.implicitCmd:
  903. argsCount.inc
  904. if argsCount == 0:
  905. # nim filename.nims is the same as "nim e filename.nims":
  906. if p.key.endsWith(".nims"):
  907. config.command = "e"
  908. incl(config.globalOptions, optWasNimscript)
  909. config.projectName = unixToNativePath(p.key)
  910. config.arguments = cmdLineRest(p)
  911. result = true
  912. elif pass != passCmd2:
  913. config.command = p.key
  914. else:
  915. if pass == passCmd1: config.commandArgs.add p.key
  916. if argsCount == 1:
  917. # support UNIX style filenames everywhere for portable build scripts:
  918. if config.projectName.len == 0:
  919. config.projectName = unixToNativePath(p.key)
  920. config.arguments = cmdLineRest(p)
  921. result = true
  922. inc argsCount