commands.nim 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945
  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. var x = ""
  47. for f in low(T)..high(T):
  48. if x.len > 0: x.add "|"
  49. x.add $f
  50. x
  51. const
  52. Usage = slurp"../doc/basicopt.txt".replace(" //", " ")
  53. AdvancedUsage = slurp"../doc/advopt.txt".replace(" //", " ") % [genFeatureDesc(Feature), genFeatureDesc(LegacyFeature)]
  54. proc getCommandLineDesc(conf: ConfigRef): string =
  55. result = (HelpMessage % [VersionAsString, platform.OS[conf.target.hostOS].name,
  56. CPU[conf.target.hostCPU].name, CompileDate]) &
  57. Usage
  58. proc helpOnError(conf: ConfigRef; pass: TCmdLinePass) =
  59. if pass == passCmd1:
  60. msgWriteln(conf, getCommandLineDesc(conf), {msgStdout})
  61. msgQuit(0)
  62. proc writeAdvancedUsage(conf: ConfigRef; pass: TCmdLinePass) =
  63. if pass == passCmd1:
  64. msgWriteln(conf, (HelpMessage % [VersionAsString,
  65. platform.OS[conf.target.hostOS].name,
  66. CPU[conf.target.hostCPU].name, CompileDate]) &
  67. AdvancedUsage,
  68. {msgStdout})
  69. msgQuit(0)
  70. proc writeFullhelp(conf: ConfigRef; pass: TCmdLinePass) =
  71. if pass == passCmd1:
  72. msgWriteln(conf, `%`(HelpMessage, [VersionAsString,
  73. platform.OS[conf.target.hostOS].name,
  74. CPU[conf.target.hostCPU].name, CompileDate]) &
  75. Usage & AdvancedUsage,
  76. {msgStdout})
  77. msgQuit(0)
  78. proc writeVersionInfo(conf: ConfigRef; pass: TCmdLinePass) =
  79. if pass == passCmd1:
  80. msgWriteln(conf, `%`(HelpMessage, [VersionAsString,
  81. platform.OS[conf.target.hostOS].name,
  82. CPU[conf.target.hostCPU].name, CompileDate]),
  83. {msgStdout})
  84. const gitHash = gorge("git log -n 1 --format=%H").strip
  85. when gitHash.len == 40:
  86. msgWriteln(conf, "git hash: " & gitHash, {msgStdout})
  87. msgWriteln(conf, "active boot switches:" & usedRelease & usedDanger &
  88. usedTinyC & useLinenoise & usedNativeStacktrace &
  89. usedFFI & usedBoehm & usedMarkAndSweep & usedGenerational & usedGoGC & usedNoGC,
  90. {msgStdout})
  91. msgQuit(0)
  92. proc writeCommandLineUsage*(conf: ConfigRef) =
  93. msgWriteln(conf, getCommandLineDesc(conf), {msgStdout})
  94. proc addPrefix(switch: string): string =
  95. if switch.len <= 1: result = "-" & switch
  96. else: result = "--" & switch
  97. const
  98. errInvalidCmdLineOption = "invalid command line option: '$1'"
  99. errOnOrOffExpectedButXFound = "'on' or 'off' expected, but '$1' found"
  100. errOnOffOrListExpectedButXFound = "'on', 'off' or 'list' expected, but '$1' found"
  101. errOffHintsError = "'off', 'hint' or 'error' expected, but '$1' found"
  102. proc invalidCmdLineOption(conf: ConfigRef; pass: TCmdLinePass, switch: string, info: TLineInfo) =
  103. if switch == " ": localError(conf, info, errInvalidCmdLineOption % "-")
  104. else: localError(conf, info, errInvalidCmdLineOption % addPrefix(switch))
  105. proc splitSwitch(conf: ConfigRef; switch: string, cmd, arg: var string, pass: TCmdLinePass,
  106. info: TLineInfo) =
  107. cmd = ""
  108. var i = 0
  109. if i < switch.len and switch[i] == '-': inc(i)
  110. if i < switch.len and switch[i] == '-': inc(i)
  111. while i < switch.len:
  112. case switch[i]
  113. of 'a'..'z', 'A'..'Z', '0'..'9', '_', '.': cmd.add(switch[i])
  114. else: break
  115. inc(i)
  116. if i >= switch.len: arg = ""
  117. # cmd:arg => (cmd,arg)
  118. elif switch[i] in {':', '='}: arg = substr(switch, i + 1)
  119. # cmd[sub]:rest => (cmd,[sub]:rest)
  120. elif switch[i] == '[': arg = substr(switch, i)
  121. else: invalidCmdLineOption(conf, pass, switch, info)
  122. proc processOnOffSwitch(conf: ConfigRef; op: TOptions, arg: string, pass: TCmdLinePass,
  123. info: TLineInfo) =
  124. case arg.normalize
  125. of "","on": conf.options = conf.options + op
  126. of "off": conf.options = conf.options - op
  127. else: localError(conf, info, errOnOrOffExpectedButXFound % arg)
  128. proc processOnOffSwitchOrList(conf: ConfigRef; op: TOptions, arg: string, pass: TCmdLinePass,
  129. info: TLineInfo): bool =
  130. result = false
  131. case arg.normalize
  132. of "on": conf.options = conf.options + op
  133. of "off": conf.options = conf.options - op
  134. of "list": result = true
  135. else: localError(conf, info, errOnOffOrListExpectedButXFound % arg)
  136. proc processOnOffSwitchG(conf: ConfigRef; op: TGlobalOptions, arg: string, pass: TCmdLinePass,
  137. info: TLineInfo) =
  138. case arg.normalize
  139. of "", "on": conf.globalOptions = conf.globalOptions + op
  140. of "off": conf.globalOptions = conf.globalOptions - op
  141. else: localError(conf, info, errOnOrOffExpectedButXFound % arg)
  142. proc expectArg(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
  143. if arg == "":
  144. localError(conf, info, "argument for command line option expected: '$1'" % addPrefix(switch))
  145. proc expectNoArg(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
  146. if arg != "":
  147. localError(conf, info, "invalid argument for command line option: '$1'" % addPrefix(switch))
  148. proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass,
  149. info: TLineInfo; orig: string; conf: ConfigRef) =
  150. var id = "" # arg = key:val or [key]:val; with val=on|off
  151. var i = 0
  152. var n = hintMin
  153. var isBracket = false
  154. if i < arg.len and arg[i] == '[':
  155. isBracket = true
  156. inc(i)
  157. while i < arg.len and (arg[i] notin {':', '=', ']'}):
  158. id.add(arg[i])
  159. inc(i)
  160. if isBracket:
  161. if i < arg.len and arg[i] == ']': inc(i)
  162. else: invalidCmdLineOption(conf, pass, orig, info)
  163. if 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. let val = substr(arg, i).normalize
  174. if val notin ["on", "off"]:
  175. localError(conf, info, errOnOrOffExpectedButXFound % arg)
  176. elif n notin conf.cmdlineNotes or pass == passCmd1:
  177. if pass == passCmd1: incl(conf.cmdlineNotes, n)
  178. incl(conf.modifiedyNotes, n)
  179. case val
  180. of "on":
  181. incl(conf.notes, n)
  182. incl(conf.mainPackageNotes, n)
  183. of "off":
  184. excl(conf.notes, n)
  185. excl(conf.mainPackageNotes, n)
  186. excl(conf.foreignPackageNotes, n)
  187. proc processCompile(conf: ConfigRef; filename: string) =
  188. var found = findFile(conf, filename)
  189. if found.isEmpty: found = AbsoluteFile filename
  190. extccomp.addExternalFileToCompile(conf, found)
  191. const
  192. errNoneBoehmRefcExpectedButXFound = "'none', 'boehm' or 'refc' expected, but '$1' found"
  193. errNoneSpeedOrSizeExpectedButXFound = "'none', 'speed' or 'size' expected, but '$1' found"
  194. errGuiConsoleOrLibExpectedButXFound = "'gui', 'console' or 'lib' expected, but '$1' found"
  195. errInvalidExceptionSystem = "'goto', 'setjmp', 'cpp' or 'quirky' expected, but '$1' found"
  196. proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo): bool =
  197. case switch.normalize
  198. of "gc":
  199. case arg.normalize
  200. of "boehm": result = conf.selectedGC == gcBoehm
  201. of "refc": result = conf.selectedGC == gcRefc
  202. of "v2": result = false
  203. of "markandsweep": result = conf.selectedGC == gcMarkAndSweep
  204. of "generational": result = false
  205. of "destructors", "arc": result = conf.selectedGC == gcArc
  206. of "orc": result = conf.selectedGC == gcOrc
  207. of "hooks": result = conf.selectedGC == gcHooks
  208. of "go": result = conf.selectedGC == gcGo
  209. of "none": result = conf.selectedGC == gcNone
  210. of "stack", "regions": result = conf.selectedGC == gcRegions
  211. else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
  212. of "opt":
  213. case arg.normalize
  214. of "speed": result = contains(conf.options, optOptimizeSpeed)
  215. of "size": result = contains(conf.options, optOptimizeSize)
  216. of "none": result = conf.options * {optOptimizeSpeed, optOptimizeSize} == {}
  217. else: localError(conf, info, errNoneSpeedOrSizeExpectedButXFound % arg)
  218. of "verbosity": result = $conf.verbosity == arg
  219. of "app":
  220. case arg.normalize
  221. of "gui": result = contains(conf.globalOptions, optGenGuiApp)
  222. of "console": result = not contains(conf.globalOptions, optGenGuiApp)
  223. of "lib": result = contains(conf.globalOptions, optGenDynLib) and
  224. not contains(conf.globalOptions, optGenGuiApp)
  225. of "staticlib": result = contains(conf.globalOptions, optGenStaticLib) and
  226. not contains(conf.globalOptions, optGenGuiApp)
  227. else: localError(conf, info, errGuiConsoleOrLibExpectedButXFound % arg)
  228. of "dynliboverride":
  229. result = isDynlibOverride(conf, arg)
  230. of "exceptions":
  231. case arg.normalize
  232. of "cpp": result = conf.exc == excCpp
  233. of "setjmp": result = conf.exc == excSetjmp
  234. of "quirky": result = conf.exc == excQuirky
  235. of "goto": result = conf.exc == excGoto
  236. else: localError(conf, info, errInvalidExceptionSystem % arg)
  237. else: invalidCmdLineOption(conf, passCmd1, switch, info)
  238. proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool =
  239. case switch.normalize
  240. of "debuginfo": result = contains(conf.globalOptions, optCDebug)
  241. of "compileonly", "c": result = contains(conf.globalOptions, optCompileOnly)
  242. of "nolinking": result = contains(conf.globalOptions, optNoLinking)
  243. of "nomain": result = contains(conf.globalOptions, optNoMain)
  244. of "forcebuild", "f": result = contains(conf.globalOptions, optForceFullMake)
  245. of "warnings", "w": result = contains(conf.options, optWarns)
  246. of "hints": result = contains(conf.options, optHints)
  247. of "threadanalysis": result = contains(conf.globalOptions, optThreadAnalysis)
  248. of "stacktrace": result = contains(conf.options, optStackTrace)
  249. of "stacktracemsgs": result = contains(conf.options, optStackTraceMsgs)
  250. of "linetrace": result = contains(conf.options, optLineTrace)
  251. of "debugger": result = contains(conf.globalOptions, optCDebug)
  252. of "profiler": result = contains(conf.options, optProfiler)
  253. of "memtracker": result = contains(conf.options, optMemTracker)
  254. of "checks", "x": result = conf.options * ChecksOptions == ChecksOptions
  255. of "floatchecks":
  256. result = conf.options * {optNaNCheck, optInfCheck} == {optNaNCheck, optInfCheck}
  257. of "infchecks": result = contains(conf.options, optInfCheck)
  258. of "nanchecks": result = contains(conf.options, optNaNCheck)
  259. of "nilchecks": result = contains(conf.options, optNilCheck)
  260. of "objchecks": result = contains(conf.options, optObjCheck)
  261. of "fieldchecks": result = contains(conf.options, optFieldCheck)
  262. of "rangechecks": result = contains(conf.options, optRangeCheck)
  263. of "boundchecks": result = contains(conf.options, optBoundsCheck)
  264. of "refchecks": result = contains(conf.options, optRefCheck)
  265. of "overflowchecks": result = contains(conf.options, optOverflowCheck)
  266. of "staticboundchecks": result = contains(conf.options, optStaticBoundsCheck)
  267. of "stylechecks": result = contains(conf.options, optStyleCheck)
  268. of "linedir": result = contains(conf.options, optLineDir)
  269. of "assertions", "a": result = contains(conf.options, optAssert)
  270. of "run", "r": result = contains(conf.globalOptions, optRun)
  271. of "symbolfiles": result = conf.symbolFiles != disabledSf
  272. of "genscript": result = contains(conf.globalOptions, optGenScript)
  273. of "threads": result = contains(conf.globalOptions, optThreads)
  274. of "taintmode": result = contains(conf.globalOptions, optTaintMode)
  275. of "tlsemulation": result = contains(conf.globalOptions, optTlsEmulation)
  276. of "implicitstatic": result = contains(conf.options, optImplicitStatic)
  277. of "patterns", "trmacros": result = contains(conf.options, optTrMacros)
  278. of "excessivestacktrace": result = contains(conf.globalOptions, optExcessiveStackTrace)
  279. of "nilseqs": result = contains(conf.options, optNilSeqs)
  280. of "oldast": result = contains(conf.options, optOldAst)
  281. else: invalidCmdLineOption(conf, passCmd1, switch, info)
  282. proc processPath(conf: ConfigRef; path: string, info: TLineInfo,
  283. notRelativeToProj = false): AbsoluteDir =
  284. let p = if os.isAbsolute(path) or '$' in path:
  285. path
  286. elif notRelativeToProj:
  287. getCurrentDir() / path
  288. else:
  289. conf.projectPath.string / path
  290. try:
  291. result = AbsoluteDir pathSubs(conf, p, toFullPath(conf, info).splitFile().dir)
  292. except ValueError:
  293. localError(conf, info, "invalid path: " & p)
  294. result = AbsoluteDir p
  295. proc processCfgPath(conf: ConfigRef; path: string, info: TLineInfo): AbsoluteDir =
  296. let path = if path.len > 0 and path[0] == '"': strutils.unescape(path)
  297. else: path
  298. let basedir = toFullPath(conf, info).splitFile().dir
  299. let p = if os.isAbsolute(path) or '$' in path:
  300. path
  301. else:
  302. basedir / path
  303. try:
  304. result = AbsoluteDir pathSubs(conf, p, basedir)
  305. except ValueError:
  306. localError(conf, info, "invalid path: " & p)
  307. result = AbsoluteDir p
  308. const
  309. errInvalidNumber = "$1 is not a valid number"
  310. proc trackDirty(conf: ConfigRef; arg: string, info: TLineInfo) =
  311. var a = arg.split(',')
  312. if a.len != 4: localError(conf, info,
  313. "DIRTY_BUFFER,ORIGINAL_FILE,LINE,COLUMN expected")
  314. var line, column: int
  315. if parseUtils.parseInt(a[2], line) <= 0:
  316. localError(conf, info, errInvalidNumber % a[1])
  317. if parseUtils.parseInt(a[3], column) <= 0:
  318. localError(conf, info, errInvalidNumber % a[2])
  319. let dirtyOriginalIdx = fileInfoIdx(conf, AbsoluteFile a[1])
  320. if dirtyOriginalIdx.int32 >= 0:
  321. msgs.setDirtyFile(conf, dirtyOriginalIdx, AbsoluteFile a[0])
  322. conf.m.trackPos = newLineInfo(dirtyOriginalIdx, line, column)
  323. proc track(conf: ConfigRef; arg: string, info: TLineInfo) =
  324. var a = arg.split(',')
  325. if a.len != 3: localError(conf, info, "FILE,LINE,COLUMN expected")
  326. var line, column: int
  327. if parseUtils.parseInt(a[1], line) <= 0:
  328. localError(conf, info, errInvalidNumber % a[1])
  329. if parseUtils.parseInt(a[2], column) <= 0:
  330. localError(conf, info, errInvalidNumber % a[2])
  331. conf.m.trackPos = newLineInfo(conf, AbsoluteFile a[0], line, column)
  332. proc dynlibOverride(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
  333. if pass in {passCmd2, passPP}:
  334. expectArg(conf, switch, arg, pass, info)
  335. options.inclDynlibOverride(conf, arg)
  336. proc handleStdinInput*(conf: ConfigRef) =
  337. conf.projectName = "stdinfile"
  338. conf.projectFull = conf.projectName.AbsoluteFile
  339. conf.projectPath = AbsoluteDir getCurrentDir()
  340. conf.projectIsStdin = true
  341. if conf.outDir.isEmpty:
  342. conf.outDir = getNimcacheDir(conf)
  343. proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
  344. conf: ConfigRef) =
  345. var
  346. key, val: string
  347. case switch.normalize
  348. of "path", "p":
  349. expectArg(conf, switch, arg, pass, info)
  350. for path in nimbleSubs(conf, arg):
  351. addPath(conf, if pass == passPP: processCfgPath(conf, path, info)
  352. else: processPath(conf, path, info), info)
  353. of "nimblepath", "babelpath":
  354. # keep the old name for compat
  355. if pass in {passCmd2, passPP} and optNoNimblePath notin conf.globalOptions:
  356. expectArg(conf, switch, arg, pass, info)
  357. var path = processPath(conf, arg, info, notRelativeToProj=true)
  358. let nimbleDir = AbsoluteDir getEnv("NIMBLE_DIR")
  359. if not nimbleDir.isEmpty and pass == passPP:
  360. path = nimbleDir / RelativeDir"pkgs"
  361. nimblePath(conf, path, info)
  362. of "nonimblepath", "nobabelpath":
  363. expectNoArg(conf, switch, arg, pass, info)
  364. disableNimblePath(conf)
  365. of "clearnimblepath":
  366. expectNoArg(conf, switch, arg, pass, info)
  367. clearNimblePath(conf)
  368. of "excludepath":
  369. expectArg(conf, switch, arg, pass, info)
  370. let path = processPath(conf, arg, info)
  371. conf.searchPaths.keepItIf(it != path)
  372. conf.lazyPaths.keepItIf(it != path)
  373. of "nimcache":
  374. expectArg(conf, switch, arg, pass, info)
  375. conf.nimcacheDir = processPath(conf, arg, info, notRelativeToProj=true)
  376. of "out", "o":
  377. expectArg(conf, switch, arg, pass, info)
  378. let f = splitFile(processPath(conf, arg, info, notRelativeToProj=true).string)
  379. conf.outFile = RelativeFile f.name & f.ext
  380. conf.outDir = toAbsoluteDir f.dir
  381. of "outdir":
  382. expectArg(conf, switch, arg, pass, info)
  383. conf.outDir = processPath(conf, arg, info, notRelativeToProj=true)
  384. of "docseesrcurl":
  385. expectArg(conf, switch, arg, pass, info)
  386. conf.docSeeSrcUrl = arg
  387. of "docroot":
  388. conf.docRoot = if arg.len == 0: "@default" else: arg
  389. of "mainmodule", "m":
  390. discard "allow for backwards compatibility, but don't do anything"
  391. of "define", "d":
  392. expectArg(conf, switch, arg, pass, info)
  393. if {':', '='} in arg:
  394. splitSwitch(conf, arg, key, val, pass, info)
  395. if cmpIgnoreStyle(key, "nimQuirky") == 0:
  396. conf.exc = excQuirky
  397. defineSymbol(conf.symbols, key, val)
  398. else:
  399. if cmpIgnoreStyle(arg, "nimQuirky") == 0:
  400. conf.exc = excQuirky
  401. defineSymbol(conf.symbols, arg)
  402. of "undef", "u":
  403. expectArg(conf, switch, arg, pass, info)
  404. undefSymbol(conf.symbols, arg)
  405. of "symbol":
  406. expectArg(conf, switch, arg, pass, info)
  407. # deprecated, do nothing
  408. of "compile":
  409. expectArg(conf, switch, arg, pass, info)
  410. if pass in {passCmd2, passPP}: processCompile(conf, arg)
  411. of "link":
  412. expectArg(conf, switch, arg, pass, info)
  413. if pass in {passCmd2, passPP}:
  414. addExternalFileToLink(conf, AbsoluteFile arg)
  415. of "debuginfo":
  416. processOnOffSwitchG(conf, {optCDebug}, arg, pass, info)
  417. of "embedsrc":
  418. processOnOffSwitchG(conf, {optEmbedOrigSrc}, arg, pass, info)
  419. of "compileonly", "c":
  420. processOnOffSwitchG(conf, {optCompileOnly}, arg, pass, info)
  421. of "nolinking":
  422. processOnOffSwitchG(conf, {optNoLinking}, arg, pass, info)
  423. of "nomain":
  424. processOnOffSwitchG(conf, {optNoMain}, arg, pass, info)
  425. of "forcebuild", "f":
  426. processOnOffSwitchG(conf, {optForceFullMake}, arg, pass, info)
  427. of "project":
  428. processOnOffSwitchG(conf, {optWholeProject}, arg, pass, info)
  429. of "gc":
  430. expectArg(conf, switch, arg, pass, info)
  431. if pass in {passCmd2, passPP}:
  432. case arg.normalize
  433. of "boehm":
  434. conf.selectedGC = gcBoehm
  435. defineSymbol(conf.symbols, "boehmgc")
  436. incl conf.globalOptions, optTlsEmulation # Boehm GC doesn't scan the real TLS
  437. of "refc":
  438. conf.selectedGC = gcRefc
  439. of "v2":
  440. message(conf, info, warnDeprecated, "--gc:v2 is deprecated; using default gc")
  441. of "markandsweep":
  442. conf.selectedGC = gcMarkAndSweep
  443. defineSymbol(conf.symbols, "gcmarkandsweep")
  444. of "destructors", "arc":
  445. conf.selectedGC = gcArc
  446. if conf.cmd != cmdCompileToCpp:
  447. conf.exc = excGoto
  448. defineSymbol(conf.symbols, "gcdestructors")
  449. defineSymbol(conf.symbols, "gcarc")
  450. incl conf.globalOptions, optSeqDestructors
  451. incl conf.globalOptions, optTinyRtti
  452. if pass in {passCmd2, passPP}:
  453. defineSymbol(conf.symbols, "nimSeqsV2")
  454. defineSymbol(conf.symbols, "nimV2")
  455. of "orc":
  456. conf.selectedGC = gcOrc
  457. if conf.cmd != cmdCompileToCpp:
  458. conf.exc = excGoto
  459. defineSymbol(conf.symbols, "gcdestructors")
  460. defineSymbol(conf.symbols, "gcorc")
  461. incl conf.globalOptions, optSeqDestructors
  462. incl conf.globalOptions, optTinyRtti
  463. if pass in {passCmd2, passPP}:
  464. defineSymbol(conf.symbols, "nimSeqsV2")
  465. defineSymbol(conf.symbols, "nimV2")
  466. of "hooks":
  467. conf.selectedGC = gcHooks
  468. defineSymbol(conf.symbols, "gchooks")
  469. incl conf.globalOptions, optSeqDestructors
  470. processOnOffSwitchG(conf, {optSeqDestructors}, arg, pass, info)
  471. if pass in {passCmd2, passPP}:
  472. defineSymbol(conf.symbols, "nimSeqsV2")
  473. of "go":
  474. conf.selectedGC = gcGo
  475. defineSymbol(conf.symbols, "gogc")
  476. of "none":
  477. conf.selectedGC = gcNone
  478. defineSymbol(conf.symbols, "nogc")
  479. of "stack", "regions":
  480. conf.selectedGC = gcRegions
  481. defineSymbol(conf.symbols, "gcregions")
  482. else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
  483. of "warnings", "w":
  484. if processOnOffSwitchOrList(conf, {optWarns}, arg, pass, info): listWarnings(conf)
  485. of "warning": processSpecificNote(arg, wWarning, pass, info, switch, conf)
  486. of "hint": processSpecificNote(arg, wHint, pass, info, switch, conf)
  487. of "hints":
  488. if processOnOffSwitchOrList(conf, {optHints}, arg, pass, info): listHints(conf)
  489. of "threadanalysis": processOnOffSwitchG(conf, {optThreadAnalysis}, arg, pass, info)
  490. of "stacktrace": processOnOffSwitch(conf, {optStackTrace}, arg, pass, info)
  491. of "stacktracemsgs": processOnOffSwitch(conf, {optStackTraceMsgs}, arg, pass, info)
  492. of "excessivestacktrace": processOnOffSwitchG(conf, {optExcessiveStackTrace}, arg, pass, info)
  493. of "linetrace": processOnOffSwitch(conf, {optLineTrace}, arg, pass, info)
  494. of "debugger":
  495. case arg.normalize
  496. of "on", "native", "gdb":
  497. conf.globalOptions.incl optCDebug
  498. conf.options.incl optLineDir
  499. #defineSymbol(conf.symbols, "nimTypeNames") # type names are used in gdb pretty printing
  500. of "off":
  501. conf.globalOptions.excl optCDebug
  502. else:
  503. localError(conf, info, "expected native|gdb|on|off but found " & arg)
  504. of "g": # alias for --debugger:native
  505. conf.globalOptions.incl optCDebug
  506. conf.options.incl optLineDir
  507. #defineSymbol(conf.symbols, "nimTypeNames") # type names are used in gdb pretty printing
  508. of "profiler":
  509. processOnOffSwitch(conf, {optProfiler}, arg, pass, info)
  510. if optProfiler in conf.options: defineSymbol(conf.symbols, "profiler")
  511. else: undefSymbol(conf.symbols, "profiler")
  512. of "memtracker":
  513. processOnOffSwitch(conf, {optMemTracker}, arg, pass, info)
  514. if optMemTracker in conf.options: defineSymbol(conf.symbols, "memtracker")
  515. else: undefSymbol(conf.symbols, "memtracker")
  516. of "hotcodereloading":
  517. processOnOffSwitchG(conf, {optHotCodeReloading}, arg, pass, info)
  518. if conf.hcrOn:
  519. defineSymbol(conf.symbols, "hotcodereloading")
  520. defineSymbol(conf.symbols, "useNimRtl")
  521. # hardcoded linking with dynamic runtime for MSVC for smaller binaries
  522. # should do the same for all compilers (wherever applicable)
  523. if isVSCompatible(conf):
  524. extccomp.addCompileOptionCmd(conf, "/MD")
  525. else:
  526. undefSymbol(conf.symbols, "hotcodereloading")
  527. undefSymbol(conf.symbols, "useNimRtl")
  528. of "oldnewlines":
  529. case arg.normalize
  530. of "", "on":
  531. conf.oldNewlines = true
  532. defineSymbol(conf.symbols, "nimOldNewlines")
  533. of "off":
  534. conf.oldNewlines = false
  535. undefSymbol(conf.symbols, "nimOldNewlines")
  536. else:
  537. localError(conf, info, errOnOrOffExpectedButXFound % arg)
  538. of "laxstrings": processOnOffSwitch(conf, {optLaxStrings}, arg, pass, info)
  539. of "nilseqs": processOnOffSwitch(conf, {optNilSeqs}, arg, pass, info)
  540. of "oldast": processOnOffSwitch(conf, {optOldAst}, 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": processOnOffSwitch(conf, {optNilCheck}, arg, pass, info)
  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. of "usages": conf.globalOptions.incl optStyleUsages
  810. else: localError(conf, info, errOffHintsError % arg)
  811. of "showallmismatches":
  812. processOnOffSwitchG(conf, {optShowAllMismatches}, arg, pass, info)
  813. of "cppcompiletonamespace":
  814. if arg.len > 0:
  815. conf.cppCustomNamespace = arg
  816. else:
  817. conf.cppCustomNamespace = "Nim"
  818. defineSymbol(conf.symbols, "cppCompileToNamespace", conf.cppCustomNamespace)
  819. of "docinternal":
  820. processOnOffSwitchG(conf, {optDocInternal}, arg, pass, info)
  821. of "multimethods":
  822. processOnOffSwitchG(conf, {optMultiMethods}, arg, pass, info)
  823. of "expandmacro":
  824. expectArg(conf, switch, arg, pass, info)
  825. conf.macrosToExpand[arg] = "T"
  826. of "oldgensym":
  827. processOnOffSwitchG(conf, {optNimV019}, arg, pass, info)
  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. ast.eqTypeFlags.excl {tfGcSafe, tfNoSideEffect}
  839. conf.globalOptions.incl optNimV1Emulation
  840. else:
  841. localError(conf, info, "unknown Nim version; currently supported values are: {1.0}")
  842. of "benchmarkvm":
  843. processOnOffSwitchG(conf, {optBenchmarkVM}, arg, pass, info)
  844. of "sinkinference":
  845. processOnOffSwitch(conf, {optSinkInference}, arg, pass, info)
  846. of "panics":
  847. processOnOffSwitchG(conf, {optPanics}, arg, pass, info)
  848. if optPanics in conf.globalOptions:
  849. defineSymbol(conf.symbols, "nimPanics")
  850. of "sourcemap":
  851. conf.globalOptions.incl optSourcemap
  852. conf.options.incl optLineDir
  853. # processOnOffSwitchG(conf, {optSourcemap, opt}, arg, pass, info)
  854. of "": # comes from "-" in for example: `nim c -r -` (gets stripped from -)
  855. handleStdinInput(conf)
  856. else:
  857. if strutils.find(switch, '.') >= 0: options.setConfigVar(conf, switch, arg)
  858. else: invalidCmdLineOption(conf, pass, switch, info)
  859. template gCmdLineInfo*(): untyped = newLineInfo(commandLineIdx, 1, 1)
  860. proc processCommand*(switch: string, pass: TCmdLinePass; config: ConfigRef) =
  861. var cmd, arg: string
  862. splitSwitch(config, switch, cmd, arg, pass, gCmdLineInfo)
  863. processSwitch(cmd, arg, pass, gCmdLineInfo, config)
  864. proc processSwitch*(pass: TCmdLinePass; p: OptParser; config: ConfigRef) =
  865. # hint[X]:off is parsed as (p.key = "hint[X]", p.val = "off")
  866. # we transform it to (key = hint, val = [X]:off)
  867. var bracketLe = strutils.find(p.key, '[')
  868. if bracketLe >= 0:
  869. var key = substr(p.key, 0, bracketLe - 1)
  870. var val = substr(p.key, bracketLe) & ':' & p.val
  871. processSwitch(key, val, pass, gCmdLineInfo, config)
  872. else:
  873. processSwitch(p.key, p.val, pass, gCmdLineInfo, config)
  874. proc processArgument*(pass: TCmdLinePass; p: OptParser;
  875. argsCount: var int; config: ConfigRef): bool =
  876. if argsCount == 0:
  877. # nim filename.nims is the same as "nim e filename.nims":
  878. if p.key.endsWith(".nims"):
  879. config.command = "e"
  880. incl(config.globalOptions, optWasNimscript)
  881. config.projectName = unixToNativePath(p.key)
  882. config.arguments = cmdLineRest(p)
  883. result = true
  884. elif pass != passCmd2:
  885. config.command = p.key
  886. else:
  887. if pass == passCmd1: config.commandArgs.add p.key
  888. if argsCount == 1:
  889. # support UNIX style filenames everywhere for portable build scripts:
  890. if config.projectName.len == 0:
  891. config.projectName = unixToNativePath(p.key)
  892. config.arguments = cmdLineRest(p)
  893. result = true
  894. inc argsCount