options.nim 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098
  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. import
  10. lineinfos, platform,
  11. prefixmatches, pathutils, nimpaths
  12. import std/[tables, os, strutils, strtabs, sets]
  13. from std/terminal import isatty
  14. from std/times import utc, fromUnix, local, getTime, format, DateTime
  15. from std/private/globs import nativeToUnixPath
  16. when defined(nimPreviewSlimSystem):
  17. import std/[syncio, assertions]
  18. const
  19. hasTinyCBackend* = defined(tinyc)
  20. useEffectSystem* = true
  21. useWriteTracking* = false
  22. hasFFI* = defined(nimHasLibFFI)
  23. copyrightYear* = "2025"
  24. nimEnableCovariance* = defined(nimEnableCovariance)
  25. type # please make sure we have under 32 options
  26. # (improves code efficiency a lot!)
  27. TOption* = enum # **keep binary compatible**
  28. optNone, optObjCheck, optFieldCheck, optRangeCheck, optBoundsCheck,
  29. optOverflowCheck, optRefCheck,
  30. optNaNCheck, optInfCheck, optStaticBoundsCheck, optStyleCheck,
  31. optAssert, optLineDir, optWarns, optHints,
  32. optOptimizeSpeed, optOptimizeSize,
  33. optStackTrace, # stack tracing support
  34. optStackTraceMsgs, # enable custom runtime msgs via `setFrameMsg`
  35. optLineTrace, # line tracing support (includes stack tracing)
  36. optByRef, # use pass by ref for objects
  37. # (for interfacing with C)
  38. optProfiler, # profiler turned on
  39. optImplicitStatic, # optimization: implicit at compile time
  40. # evaluation
  41. optTrMacros, # en/disable pattern matching
  42. optMemTracker,
  43. optSinkInference # 'sink T' inference
  44. optCursorInference
  45. optImportHidden
  46. optQuirky
  47. TOptions* = set[TOption]
  48. TGlobalOption* = enum
  49. gloptNone, optForceFullMake,
  50. optWasNimscript, # redundant with `cmdNimscript`, could be removed
  51. optListCmd, optCompileOnly, optNoLinking,
  52. optCDebug, # turn on debugging information
  53. optGenDynLib, # generate a dynamic library
  54. optGenStaticLib, # generate a static library
  55. optGenGuiApp, # generate a GUI application
  56. optGenScript, # generate a script file to compile the *.c files
  57. optGenCDeps, # generate a list of *.c files to be read by CMake
  58. optGenMapping, # generate a mapping file
  59. optRun, # run the compiled project
  60. optUseNimcache, # save artifacts (including binary) in $nimcache
  61. optStyleHint, # check that the names adhere to NEP-1
  62. optStyleError, # enforce that the names adhere to NEP-1
  63. optStyleUsages, # only enforce consistent **usages** of the symbol
  64. optSkipSystemConfigFile, # skip the system's cfg/nims config file
  65. optSkipProjConfigFile, # skip the project's cfg/nims config file
  66. optSkipUserConfigFile, # skip the users's cfg/nims config file
  67. optSkipParentConfigFiles, # skip parent dir's cfg/nims config files
  68. optNoMain, # do not generate a "main" proc
  69. optUseColors, # use colors for hints, warnings, and errors
  70. optThreads, # support for multi-threading
  71. optStdout, # output to stdout
  72. optThreadAnalysis, # thread analysis pass
  73. optTlsEmulation, # thread var emulation turned on
  74. optGenIndex # generate index file for documentation;
  75. optGenIndexOnly # generate only index file for documentation
  76. optNoImportdoc # disable loading external documentation files
  77. optEmbedOrigSrc # embed the original source in the generated code
  78. # also: generate header file
  79. optIdeDebug # idetools: debug mode
  80. optIdeTerse # idetools: use terse descriptions
  81. optIdeExceptionInlayHints
  82. optExcessiveStackTrace # fully qualified module filenames
  83. optShowAllMismatches # show all overloading resolution candidates
  84. optWholeProject # for 'doc': output any dependency
  85. optDocInternal # generate documentation for non-exported symbols
  86. optMixedMode # true if some module triggered C++ codegen
  87. optDeclaredLocs # show declaration locations in messages
  88. optNoNimblePath
  89. optHotCodeReloading
  90. optDynlibOverrideAll
  91. optSeqDestructors # active if the implementation uses the new
  92. # string/seq implementation based on destructors
  93. optTinyRtti # active if we use the new "tiny RTTI"
  94. # implementation
  95. optOwnedRefs # active if the Nim compiler knows about 'owned'.
  96. optMultiMethods
  97. optBenchmarkVM # Enables cpuTime() in the VM
  98. optProduceAsm # produce assembler code
  99. optPanics # turn panics (sysFatal) into a process termination
  100. optSourcemap
  101. optProfileVM # enable VM profiler
  102. optEnableDeepCopy # ORC specific: enable 'deepcopy' for all types.
  103. optShowNonExportedFields # for documentation: show fields that are not exported
  104. optJsBigInt64 # use bigints for 64-bit integers in JS
  105. TGlobalOptions* = set[TGlobalOption]
  106. const
  107. harmlessOptions* = {optForceFullMake, optNoLinking, optRun, optUseColors, optStdout}
  108. genSubDir* = RelativeDir"nimcache"
  109. NimExt* = "nim"
  110. RodExt* = "rod"
  111. HtmlExt* = "html"
  112. JsonExt* = "json"
  113. TagsExt* = "tags"
  114. TexExt* = "tex"
  115. IniExt* = "ini"
  116. DefaultConfig* = RelativeFile"nim.cfg"
  117. DefaultConfigNims* = RelativeFile"config.nims"
  118. DocConfig* = RelativeFile"nimdoc.cfg"
  119. DocTexConfig* = RelativeFile"nimdoc.tex.cfg"
  120. htmldocsDir* = htmldocsDirname.RelativeDir
  121. docRootDefault* = "@default" # using `@` instead of `$` to avoid shell quoting complications
  122. oKeepVariableNames* = true
  123. spellSuggestSecretSauce* = -1
  124. type
  125. TBackend* = enum
  126. backendInvalid = "" # for parseEnum
  127. backendC = "c"
  128. backendCpp = "cpp"
  129. backendJs = "js"
  130. backendObjc = "objc"
  131. # backendNimscript = "nimscript" # this could actually work
  132. # backendLlvm = "llvm" # probably not well supported; was cmdCompileToLLVM
  133. Command* = enum ## Nim's commands
  134. cmdNone # not yet processed command
  135. cmdUnknown # command unmapped
  136. cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToJS,
  137. cmdCrun # compile and run in nimache
  138. cmdTcc # run the project via TCC backend
  139. cmdCheck # semantic checking for whole project
  140. cmdM # only compile a single
  141. cmdParse # parse a single file (for debugging)
  142. cmdRod # .rod to some text representation (for debugging)
  143. cmdIdeTools # ide tools (e.g. nimsuggest)
  144. cmdNimscript # evaluate nimscript
  145. cmdDoc0
  146. cmdDoc # convert .nim doc comments to HTML
  147. cmdDoc2tex # convert .nim doc comments to LaTeX
  148. cmdRst2html # convert a reStructuredText file to HTML
  149. cmdRst2tex # convert a reStructuredText file to TeX
  150. cmdMd2html # convert a Markdown file to HTML
  151. cmdMd2tex # convert a Markdown file to TeX
  152. cmdJsondoc0
  153. cmdJsondoc
  154. cmdCtags
  155. cmdBuildindex
  156. cmdGendepend
  157. cmdDump
  158. cmdInteractive # start interactive session
  159. cmdNop
  160. cmdJsonscript # compile a .json build file
  161. # old unused: cmdInterpret, cmdDef: def feature (find definition for IDEs)
  162. const
  163. cmdBackends* = {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC,
  164. cmdCompileToJS, cmdCrun}
  165. cmdDocLike* = {cmdDoc0, cmdDoc, cmdDoc2tex, cmdJsondoc0, cmdJsondoc,
  166. cmdCtags, cmdBuildindex}
  167. type
  168. TStringSeq* = seq[string]
  169. TGCMode* = enum # the selected GC
  170. gcUnselected = "unselected"
  171. gcNone = "none"
  172. gcBoehm = "boehm"
  173. gcRegions = "regions"
  174. gcArc = "arc"
  175. gcOrc = "orc"
  176. gcAtomicArc = "atomicArc"
  177. gcMarkAndSweep = "markAndSweep"
  178. gcHooks = "hooks"
  179. gcRefc = "refc"
  180. gcGo = "go"
  181. # gcRefc and the GCs that follow it use a write barrier,
  182. # as far as usesWriteBarrier() is concerned
  183. IdeCmd* = enum
  184. ideNone, ideSug, ideCon, ideDef, ideUse, ideDus, ideChk, ideChkFile, ideMod,
  185. ideHighlight, ideOutline, ideKnown, ideMsg, ideProject, ideGlobalSymbols,
  186. ideRecompile, ideChanged, ideType, ideDeclaration, ideExpand, ideInlayHints
  187. Feature* = enum ## experimental features; DO NOT RENAME THESE!
  188. dotOperators,
  189. callOperator,
  190. parallel,
  191. destructor,
  192. notnil,
  193. dynamicBindSym,
  194. forLoopMacros, # not experimental anymore; remains here for backwards compatibility
  195. caseStmtMacros, # ditto
  196. codeReordering,
  197. compiletimeFFI,
  198. ## This requires building nim with `-d:nimHasLibFFI`
  199. ## which itself requires `koch installdeps libffi`, see #10150
  200. ## Note: this feature can't be localized with {.push.}
  201. vmopsDanger,
  202. strictFuncs,
  203. views,
  204. strictNotNil,
  205. overloadableEnums, # deadcode
  206. strictEffects,
  207. unicodeOperators, # deadcode
  208. flexibleOptionalParams,
  209. strictDefs,
  210. strictCaseObjects,
  211. inferGenericTypes,
  212. openSym, # remove nfDisabledOpenSym when this is default
  213. # alternative to above:
  214. genericsOpenSym
  215. vtables
  216. typeBoundOps
  217. LegacyFeature* = enum
  218. allowSemcheckedAstModification,
  219. ## Allows to modify a NimNode where the type has already been
  220. ## flagged with nfSem. If you actually do this, it will cause
  221. ## bugs.
  222. checkUnsignedConversions
  223. ## Historically and especially in version 1.0.0 of the language
  224. ## conversions to unsigned numbers were checked. In 1.0.4 they
  225. ## are not anymore.
  226. laxEffects
  227. ## Lax effects system prior to Nim 2.0.
  228. verboseTypeMismatch
  229. emitGenerics
  230. ## generics are emitted in the module that contains them.
  231. ## Useful for libraries that rely on local passC
  232. jsNoLambdaLifting
  233. ## Old transformation for closures in JS backend
  234. noPanicOnExcept
  235. ## don't panic on bare except
  236. SymbolFilesOption* = enum
  237. disabledSf, writeOnlySf, readOnlySf, v2Sf, stressTest
  238. TSystemCC* = enum
  239. ccNone, ccGcc, ccNintendoSwitch, ccLLVM_Gcc, ccCLang, ccBcc, ccVcc,
  240. ccTcc, ccEnv, ccIcl, ccIcc, ccClangCl, ccHipcc, ccNvcc
  241. ExceptionSystem* = enum
  242. excNone, # no exception system selected yet
  243. excSetjmp, # setjmp based exception handling
  244. excCpp, # use C++'s native exception handling
  245. excGoto, # exception handling based on goto (should become the new default for C)
  246. excQuirky # quirky exception handling
  247. CfileFlag* {.pure.} = enum
  248. Cached, ## no need to recompile this time
  249. External ## file was introduced via .compile pragma
  250. Cfile* = object
  251. nimname*: string
  252. cname*, obj*: AbsoluteFile
  253. flags*: set[CfileFlag]
  254. customArgs*: string
  255. CfileList* = seq[Cfile]
  256. Suggest* = ref object
  257. section*: IdeCmd
  258. qualifiedPath*: seq[string]
  259. name*: ptr string # not used beyond sorting purposes; name is also
  260. # part of 'qualifiedPath'
  261. filePath*: string
  262. line*: int # Starts at 1
  263. column*: int # Starts at 0
  264. doc*: string # Not escaped (yet)
  265. forth*: string # type
  266. quality*: range[0..100] # matching quality
  267. isGlobal*: bool # is a global variable
  268. contextFits*: bool # type/non-type context matches
  269. prefix*: PrefixMatch
  270. symkind*: byte
  271. scope*, localUsages*, globalUsages*: int # more usages is better
  272. tokenLen*: int
  273. version*: int
  274. endLine*: uint16
  275. endCol*: int
  276. inlayHintInfo*: SuggestInlayHint
  277. Suggestions* = seq[Suggest]
  278. SuggestInlayHintKind* = enum
  279. sihkType = "Type",
  280. sihkParameter = "Parameter"
  281. sihkException = "Exception"
  282. SuggestInlayHint* = ref object
  283. kind*: SuggestInlayHintKind
  284. line*: int # Starts at 1
  285. column*: int # Starts at 0
  286. label*: string
  287. paddingLeft*: bool
  288. paddingRight*: bool
  289. allowInsert*: bool
  290. tooltip*: string
  291. ProfileInfo* = object
  292. time*: float
  293. count*: int
  294. ProfileData* = ref object
  295. data*: TableRef[TLineInfo, ProfileInfo]
  296. StdOrrKind* = enum
  297. stdOrrStdout
  298. stdOrrStderr
  299. FilenameOption* = enum
  300. foAbs # absolute path, e.g.: /pathto/bar/foo.nim
  301. foRelProject # relative to project path, e.g.: ../foo.nim
  302. foCanonical # canonical module name
  303. foLegacyRelProj # legacy, shortest of (foAbs, foRelProject)
  304. foName # lastPathPart, e.g.: foo.nim
  305. foStacktrace # if optExcessiveStackTrace: foAbs else: foName
  306. ConfigRef* {.acyclic.} = ref object ## every global configuration
  307. ## fields marked with '*' are subject to
  308. ## the incremental compilation mechanisms
  309. ## (+) means "part of the dependency"
  310. backend*: TBackend # set via `nim x` or `nim --backend:x`
  311. target*: Target # (+)
  312. linesCompiled*: int # all lines that have been compiled
  313. options*: TOptions # (+)
  314. globalOptions*: TGlobalOptions # (+)
  315. macrosToExpand*: StringTableRef
  316. arcToExpand*: StringTableRef
  317. m*: MsgConfig
  318. filenameOption*: FilenameOption # how to render paths in compiler messages
  319. unitSep*: string
  320. evalTemplateCounter*: int
  321. evalMacroCounter*: int
  322. exitcode*: int8
  323. cmd*: Command # raw command parsed as enum
  324. cmdInput*: string # input command
  325. projectIsCmd*: bool # whether we're compiling from a command input
  326. implicitCmd*: bool # whether some flag triggered an implicit `command`
  327. selectedGC*: TGCMode # the selected GC (+)
  328. exc*: ExceptionSystem
  329. hintProcessingDots*: bool # true for dots, false for filenames
  330. verbosity*: int # how verbose the compiler is
  331. numberOfProcessors*: int # number of processors
  332. lastCmdTime*: float # when caas is enabled, we measure each command
  333. symbolFiles*: SymbolFilesOption
  334. spellSuggestMax*: int # max number of spelling suggestions for typos
  335. cppDefines*: HashSet[string] # (*)
  336. headerFile*: string
  337. nimbasePattern*: string # pattern to find nimbase.h
  338. features*: set[Feature]
  339. legacyFeatures*: set[LegacyFeature]
  340. arguments*: string ## the arguments to be passed to the program that
  341. ## should be run
  342. ideCmd*: IdeCmd
  343. cCompiler*: TSystemCC # the used compiler
  344. modifiedyNotes*: TNoteKinds # notes that have been set/unset from either cmdline/configs
  345. cmdlineNotes*: TNoteKinds # notes that have been set/unset from cmdline
  346. foreignPackageNotes*: TNoteKinds
  347. notes*: TNoteKinds # notes after resolving all logic(defaults, verbosity)/cmdline/configs
  348. warningAsErrors*: TNoteKinds
  349. mainPackageNotes*: TNoteKinds
  350. mainPackageId*: int
  351. errorCounter*: int
  352. hintCounter*: int
  353. warnCounter*: int
  354. errorMax*: int
  355. maxLoopIterationsVM*: int ## VM: max iterations of all loops
  356. maxCallDepthVM*: int ## VM: max call depth
  357. isVmTrace*: bool
  358. configVars*: StringTableRef
  359. symbols*: StringTableRef ## We need to use a StringTableRef here as defined
  360. ## symbols are always guaranteed to be style
  361. ## insensitive. Otherwise hell would break lose.
  362. packageCache*: StringTableRef
  363. nimblePaths*: seq[AbsoluteDir]
  364. searchPaths*: seq[AbsoluteDir]
  365. lazyPaths*: seq[AbsoluteDir]
  366. outFile*: RelativeFile
  367. outDir*: AbsoluteDir
  368. jsonBuildFile*: AbsoluteFile
  369. prefixDir*, libpath*, nimcacheDir*: AbsoluteDir
  370. dllOverrides*, moduleOverrides*, cfileSpecificOptions*: StringTableRef
  371. projectName*: string # holds a name like 'nim'
  372. projectPath*: AbsoluteDir # holds a path like /home/alice/projects/nim/compiler/
  373. projectFull*: AbsoluteFile # projectPath/projectName
  374. projectIsStdin*: bool # whether we're compiling from stdin
  375. stdinFile*: AbsoluteFile # Filename to use in messages for stdin
  376. lastMsgWasDot*: set[StdOrrKind] # the last compiler message was a single '.'
  377. projectMainIdx*: FileIndex # the canonical path id of the main module
  378. projectMainIdx2*: FileIndex # consider merging with projectMainIdx
  379. command*: string # the main command (e.g. cc, check, scan, etc)
  380. commandArgs*: seq[string] # any arguments after the main command
  381. commandLine*: string
  382. extraCmds*: seq[string] # for writeJsonBuildInstructions
  383. implicitImports*: seq[string] # modules that are to be implicitly imported
  384. implicitIncludes*: seq[string] # modules that are to be implicitly included
  385. docSeeSrcUrl*: string # if empty, no seeSrc will be generated. \
  386. # The string uses the formatting variables `path` and `line`.
  387. docRoot*: string ## see nim --fullhelp for --docRoot
  388. docCmd*: string ## see nim --fullhelp for --docCmd
  389. configFiles*: seq[AbsoluteFile] # config files (cfg,nims)
  390. cIncludes*: seq[AbsoluteDir] # directories to search for included files
  391. cLibs*: seq[AbsoluteDir] # directories to search for lib files
  392. cLinkedLibs*: seq[string] # libraries to link
  393. externalToLink*: seq[string] # files to link in addition to the file
  394. # we compiled (*)
  395. linkOptionsCmd*: string
  396. compileOptionsCmd*: seq[string]
  397. linkOptions*: string # (*)
  398. compileOptions*: string # (*)
  399. cCompilerPath*: string
  400. toCompile*: CfileList # (*)
  401. suggestionResultHook*: proc (result: Suggest) {.closure.}
  402. suggestVersion*: int
  403. suggestMaxResults*: int
  404. lastLineInfo*: TLineInfo
  405. writelnHook*: proc (output: string) {.closure, gcsafe.}
  406. structuredErrorHook*: proc (config: ConfigRef; info: TLineInfo; msg: string;
  407. severity: Severity) {.closure, gcsafe.}
  408. cppCustomNamespace*: string
  409. nimMainPrefix*: string
  410. vmProfileData*: ProfileData
  411. expandProgress*: bool
  412. expandLevels*: int
  413. expandNodeResult*: string
  414. expandPosition*: TLineInfo
  415. currentConfigDir*: string # used for passPP only; absolute dir
  416. clientProcessId*: int
  417. proc assignIfDefault*[T](result: var T, val: T, def = default(T)) =
  418. ## if `result` was already assigned to a value (that wasn't `def`), this is a noop.
  419. if result == def: result = val
  420. template setErrorMaxHighMaybe*(conf: ConfigRef) =
  421. ## do not stop after first error (but honor --errorMax if provided)
  422. assignIfDefault(conf.errorMax, high(int))
  423. proc setNoteDefaults*(conf: ConfigRef, note: TNoteKind, enabled = true) =
  424. template fun(op) =
  425. conf.notes.op note
  426. conf.mainPackageNotes.op note
  427. conf.foreignPackageNotes.op note
  428. if enabled: fun(incl) else: fun(excl)
  429. proc setNote*(conf: ConfigRef, note: TNoteKind, enabled = true) =
  430. # see also `prepareConfigNotes` which sets notes
  431. if note notin conf.cmdlineNotes:
  432. if enabled: incl(conf.notes, note) else: excl(conf.notes, note)
  433. proc hasHint*(conf: ConfigRef, note: TNoteKind): bool =
  434. # ternary states instead of binary states would simplify logic
  435. if optHints notin conf.options: false
  436. elif note in {hintConf, hintProcessing}:
  437. # could add here other special notes like hintSource
  438. # these notes apply globally.
  439. note in conf.mainPackageNotes
  440. else: note in conf.notes
  441. proc hasWarn*(conf: ConfigRef, note: TNoteKind): bool {.inline.} =
  442. optWarns in conf.options and note in conf.notes
  443. proc hcrOn*(conf: ConfigRef): bool = return optHotCodeReloading in conf.globalOptions
  444. when false:
  445. template depConfigFields*(fn) {.dirty.} = # deadcode
  446. fn(target)
  447. fn(options)
  448. fn(globalOptions)
  449. fn(selectedGC)
  450. const oldExperimentalFeatures* = {dotOperators, callOperator, parallel}
  451. const
  452. ChecksOptions* = {optObjCheck, optFieldCheck, optRangeCheck,
  453. optOverflowCheck, optBoundsCheck, optAssert, optNaNCheck, optInfCheck,
  454. optStyleCheck}
  455. DefaultOptions* = {optObjCheck, optFieldCheck, optRangeCheck,
  456. optBoundsCheck, optOverflowCheck, optAssert, optWarns, optRefCheck,
  457. optHints, optStackTrace, optLineTrace, # consider adding `optStackTraceMsgs`
  458. optTrMacros, optStyleCheck, optCursorInference}
  459. DefaultGlobalOptions* = {optThreadAnalysis, optExcessiveStackTrace,
  460. optJsBigInt64}
  461. proc getSrcTimestamp(): DateTime =
  462. try:
  463. result = utc(fromUnix(parseInt(getEnv("SOURCE_DATE_EPOCH",
  464. "not a number"))))
  465. except ValueError:
  466. # Environment variable malformed.
  467. # https://reproducible-builds.org/specs/source-date-epoch/: "If the
  468. # value is malformed, the build process SHOULD exit with a non-zero
  469. # error code", which this doesn't do. This uses local time, because
  470. # that maintains compatibility with existing usage.
  471. result = utc getTime()
  472. proc getDateStr*(): string =
  473. result = format(getSrcTimestamp(), "yyyy-MM-dd")
  474. proc getClockStr*(): string =
  475. result = format(getSrcTimestamp(), "HH:mm:ss")
  476. template newPackageCache*(): untyped =
  477. newStringTable(when FileSystemCaseSensitive:
  478. modeCaseInsensitive
  479. else:
  480. modeCaseSensitive)
  481. proc newProfileData(): ProfileData =
  482. ProfileData(data: newTable[TLineInfo, ProfileInfo]())
  483. const foreignPackageNotesDefault* = {
  484. hintProcessing, warnUnknownMagic, hintQuitCalled, hintExecuting, hintUser, warnUser}
  485. proc isDefined*(conf: ConfigRef; symbol: string): bool
  486. when defined(nimDebugUtils):
  487. # this allows inserting debugging utilties in all modules that import `options`
  488. # with a single switch, which is useful when debugging compiler.
  489. import debugutils
  490. export debugutils
  491. proc initConfigRefCommon(conf: ConfigRef) =
  492. conf.selectedGC = gcUnselected
  493. conf.verbosity = 1
  494. conf.hintProcessingDots = true
  495. conf.options = DefaultOptions
  496. conf.globalOptions = DefaultGlobalOptions
  497. conf.filenameOption = foAbs
  498. conf.foreignPackageNotes = foreignPackageNotesDefault
  499. conf.notes = NotesVerbosity[1]
  500. conf.mainPackageNotes = NotesVerbosity[1]
  501. proc newConfigRef*(): ConfigRef =
  502. result = ConfigRef(
  503. cCompiler: ccGcc,
  504. macrosToExpand: newStringTable(modeStyleInsensitive),
  505. arcToExpand: newStringTable(modeStyleInsensitive),
  506. m: initMsgConfig(),
  507. cppDefines: initHashSet[string](),
  508. headerFile: "", features: {}, legacyFeatures: {},
  509. configVars: newStringTable(modeStyleInsensitive),
  510. symbols: newStringTable(modeStyleInsensitive),
  511. packageCache: newPackageCache(),
  512. searchPaths: @[],
  513. lazyPaths: @[],
  514. outFile: RelativeFile"",
  515. outDir: AbsoluteDir"",
  516. prefixDir: AbsoluteDir"",
  517. libpath: AbsoluteDir"", nimcacheDir: AbsoluteDir"",
  518. dllOverrides: newStringTable(modeCaseInsensitive),
  519. moduleOverrides: newStringTable(modeStyleInsensitive),
  520. cfileSpecificOptions: newStringTable(modeCaseSensitive),
  521. projectName: "", # holds a name like 'nim'
  522. projectPath: AbsoluteDir"", # holds a path like /home/alice/projects/nim/compiler/
  523. projectFull: AbsoluteFile"", # projectPath/projectName
  524. projectIsStdin: false, # whether we're compiling from stdin
  525. stdinFile: AbsoluteFile"stdinfile",
  526. projectMainIdx: FileIndex(0'i32), # the canonical path id of the main module
  527. command: "", # the main command (e.g. cc, check, scan, etc)
  528. commandArgs: @[], # any arguments after the main command
  529. commandLine: "",
  530. implicitImports: @[], # modules that are to be implicitly imported
  531. implicitIncludes: @[], # modules that are to be implicitly included
  532. docSeeSrcUrl: "",
  533. cIncludes: @[], # directories to search for included files
  534. cLibs: @[], # directories to search for lib files
  535. cLinkedLibs: @[], # libraries to link
  536. backend: backendInvalid,
  537. externalToLink: @[],
  538. linkOptionsCmd: "",
  539. compileOptionsCmd: @[],
  540. linkOptions: "",
  541. compileOptions: "",
  542. ccompilerpath: "",
  543. toCompile: @[],
  544. arguments: "",
  545. suggestMaxResults: 10_000,
  546. maxLoopIterationsVM: 10_000_000,
  547. maxCallDepthVM: 2_000,
  548. vmProfileData: newProfileData(),
  549. spellSuggestMax: spellSuggestSecretSauce,
  550. currentConfigDir: ""
  551. )
  552. initConfigRefCommon(result)
  553. setTargetFromSystem(result.target)
  554. # enable colors by default on terminals
  555. if terminal.isatty(stderr):
  556. incl(result.globalOptions, optUseColors)
  557. when defined(nimDebugUtils):
  558. onNewConfigRef(result)
  559. proc newPartialConfigRef*(): ConfigRef =
  560. ## create a new ConfigRef that is only good enough for error reporting.
  561. when defined(nimDebugUtils):
  562. result = getConfigRef()
  563. else:
  564. result = ConfigRef()
  565. initConfigRefCommon(result)
  566. proc cppDefine*(c: ConfigRef; define: string) =
  567. c.cppDefines.incl define
  568. proc isDefined*(conf: ConfigRef; symbol: string): bool =
  569. if conf.symbols.hasKey(symbol):
  570. result = true
  571. elif cmpIgnoreStyle(symbol, CPU[conf.target.targetCPU].name) == 0:
  572. result = true
  573. elif cmpIgnoreStyle(symbol, platform.OS[conf.target.targetOS].name) == 0:
  574. result = true
  575. else:
  576. case symbol.normalize
  577. of "x86": result = conf.target.targetCPU == cpuI386
  578. of "itanium": result = conf.target.targetCPU == cpuIa64
  579. of "x8664": result = conf.target.targetCPU == cpuAmd64
  580. of "posix", "unix":
  581. result = conf.target.targetOS in {osLinux, osMorphos, osSkyos, osIrix, osPalmos,
  582. osQnx, osAtari, osAix,
  583. osHaiku, osVxWorks, osSolaris, osNetbsd,
  584. osFreebsd, osOpenbsd, osDragonfly, osMacosx, osIos,
  585. osAndroid, osNintendoSwitch, osFreeRTOS, osCrossos, osZephyr, osNuttX}
  586. of "linux":
  587. result = conf.target.targetOS in {osLinux, osAndroid}
  588. of "bsd":
  589. result = conf.target.targetOS in {osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osCrossos}
  590. of "freebsd":
  591. result = conf.target.targetOS in {osFreebsd, osCrossos}
  592. of "emulatedthreadvars":
  593. result = platform.OS[conf.target.targetOS].props.contains(ospLacksThreadVars)
  594. of "msdos": result = conf.target.targetOS == osDos
  595. of "mswindows", "win32": result = conf.target.targetOS == osWindows
  596. of "macintosh":
  597. result = conf.target.targetOS in {osMacos, osMacosx, osIos}
  598. of "osx", "macosx":
  599. result = conf.target.targetOS in {osMacosx, osIos}
  600. of "sunos": result = conf.target.targetOS == osSolaris
  601. of "nintendoswitch":
  602. result = conf.target.targetOS == osNintendoSwitch
  603. of "freertos", "lwip":
  604. result = conf.target.targetOS == osFreeRTOS
  605. of "zephyr":
  606. result = conf.target.targetOS == osZephyr
  607. of "nuttx":
  608. result = conf.target.targetOS == osNuttX
  609. of "littleendian": result = CPU[conf.target.targetCPU].endian == littleEndian
  610. of "bigendian": result = CPU[conf.target.targetCPU].endian == bigEndian
  611. of "cpu8": result = CPU[conf.target.targetCPU].bit == 8
  612. of "cpu16": result = CPU[conf.target.targetCPU].bit == 16
  613. of "cpu32": result = CPU[conf.target.targetCPU].bit == 32
  614. of "cpu64": result = CPU[conf.target.targetCPU].bit == 64
  615. of "nimrawsetjmp":
  616. result = conf.target.targetOS in {osSolaris, osNetbsd, osFreebsd, osOpenbsd,
  617. osDragonfly, osMacosx}
  618. else: result = false
  619. template quitOrRaise*(conf: ConfigRef, msg = "") =
  620. # xxx in future work, consider whether to also intercept `msgQuit` calls
  621. if conf.isDefined("nimDebug"):
  622. raiseAssert msg
  623. else:
  624. quit(msg) # quits with QuitFailure
  625. proc importantComments*(conf: ConfigRef): bool {.inline.} = conf.cmd in cmdDocLike + {cmdIdeTools}
  626. proc usesWriteBarrier*(conf: ConfigRef): bool {.inline.} = conf.selectedGC >= gcRefc
  627. template compilationCachePresent*(conf: ConfigRef): untyped =
  628. false
  629. # conf.symbolFiles in {v2Sf, writeOnlySf}
  630. template optPreserveOrigSource*(conf: ConfigRef): untyped =
  631. optEmbedOrigSrc in conf.globalOptions
  632. proc mainCommandArg*(conf: ConfigRef): string =
  633. ## This is intended for commands like check or parse
  634. ## which will work on the main project file unless
  635. ## explicitly given a specific file argument
  636. if conf.commandArgs.len > 0:
  637. result = conf.commandArgs[0]
  638. else:
  639. result = conf.projectName
  640. proc existsConfigVar*(conf: ConfigRef; key: string): bool =
  641. result = hasKey(conf.configVars, key)
  642. proc getConfigVar*(conf: ConfigRef; key: string, default = ""): string =
  643. result = conf.configVars.getOrDefault(key, default)
  644. proc setConfigVar*(conf: ConfigRef; key, val: string) =
  645. conf.configVars[key] = val
  646. proc getOutFile*(conf: ConfigRef; filename: RelativeFile, ext: string): AbsoluteFile =
  647. # explains regression https://github.com/nim-lang/Nim/issues/6583#issuecomment-625711125
  648. # Yet another reason why "" should not mean "."; `""/something` should raise
  649. # instead of implying "" == "." as it's bug prone.
  650. doAssert conf.outDir.string.len > 0
  651. result = conf.outDir / changeFileExt(filename, ext)
  652. proc absOutFile*(conf: ConfigRef): AbsoluteFile =
  653. doAssert not conf.outDir.isEmpty
  654. doAssert not conf.outFile.isEmpty
  655. result = conf.outDir / conf.outFile
  656. when defined(posix):
  657. if dirExists(result.string): result.string.add ".out"
  658. proc prepareToWriteOutput*(conf: ConfigRef): AbsoluteFile =
  659. ## Create the output directory and returns a full path to the output file
  660. result = conf.absOutFile
  661. createDir result.string.parentDir
  662. proc getPrefixDir*(conf: ConfigRef): AbsoluteDir =
  663. ## Gets the prefix dir, usually the parent directory where the binary resides.
  664. ##
  665. ## This is overridden by some tools (namely nimsuggest) via the ``conf.prefixDir``
  666. ## field.
  667. ## This should resolve to root of nim sources, whether running nim from a local
  668. ## clone or using installed nim, so that these exist: `result/doc/advopt.txt`
  669. ## and `result/lib/system.nim`
  670. if not conf.prefixDir.isEmpty: result = conf.prefixDir
  671. else:
  672. let binParent = AbsoluteDir splitPath(getAppDir()).head
  673. when defined(posix):
  674. if binParent == AbsoluteDir"/usr":
  675. result = AbsoluteDir"/usr/lib/nim"
  676. elif binParent == AbsoluteDir"/usr/local":
  677. result = AbsoluteDir"/usr/local/lib/nim"
  678. else:
  679. result = binParent
  680. else:
  681. result = binParent
  682. proc setDefaultLibpath*(conf: ConfigRef) =
  683. # set default value (can be overwritten):
  684. if conf.libpath.isEmpty:
  685. # choose default libpath:
  686. var prefix = getPrefixDir(conf)
  687. conf.libpath = prefix / RelativeDir"lib"
  688. # Special rule to support other tools (nimble) which import the compiler
  689. # modules and make use of them.
  690. let realNimPath = findExe("nim")
  691. # Find out if $nim/../../lib/system.nim exists.
  692. let parentNimLibPath = realNimPath.parentDir.parentDir / "lib"
  693. if not fileExists(conf.libpath.string / "system.nim") and
  694. fileExists(parentNimLibPath / "system.nim"):
  695. conf.libpath = AbsoluteDir parentNimLibPath
  696. proc canonicalizePath*(conf: ConfigRef; path: AbsoluteFile): AbsoluteFile =
  697. result = AbsoluteFile path.string.expandFilename
  698. proc setFromProjectName*(conf: ConfigRef; projectName: string) =
  699. try:
  700. conf.projectFull = canonicalizePath(conf, AbsoluteFile projectName)
  701. except OSError:
  702. conf.projectFull = AbsoluteFile projectName
  703. let p = splitFile(conf.projectFull)
  704. let dir = if p.dir.isEmpty: AbsoluteDir getCurrentDir() else: p.dir
  705. try:
  706. conf.projectPath = AbsoluteDir canonicalizePath(conf, AbsoluteFile dir)
  707. except OSError:
  708. conf.projectPath = dir
  709. conf.projectName = p.name
  710. proc removeTrailingDirSep*(path: string): string =
  711. if (path.len > 0) and (path[^1] == DirSep):
  712. result = substr(path, 0, path.len - 2)
  713. else:
  714. result = path
  715. proc disableNimblePath*(conf: ConfigRef) =
  716. incl conf.globalOptions, optNoNimblePath
  717. conf.lazyPaths.setLen(0)
  718. conf.nimblePaths.setLen(0)
  719. proc clearNimblePath*(conf: ConfigRef) =
  720. conf.lazyPaths.setLen(0)
  721. conf.nimblePaths.setLen(0)
  722. include packagehandling
  723. proc getOsCacheDir(): string =
  724. when defined(posix):
  725. result = getEnv("XDG_CACHE_HOME", getHomeDir() / ".cache") / "nim"
  726. else:
  727. result = getHomeDir() / genSubDir.string
  728. proc getNimcacheDir*(conf: ConfigRef): AbsoluteDir =
  729. proc nimcacheSuffix(conf: ConfigRef): string =
  730. if conf.cmd == cmdCheck: "_check"
  731. elif isDefined(conf, "release") or isDefined(conf, "danger"): "_r"
  732. else: "_d"
  733. # XXX projectName should always be without a file extension!
  734. result =
  735. if not conf.nimcacheDir.isEmpty:
  736. conf.nimcacheDir
  737. elif conf.backend == backendJs:
  738. if conf.outDir.isEmpty:
  739. conf.projectPath / genSubDir
  740. else:
  741. conf.outDir / genSubDir
  742. else:
  743. AbsoluteDir(getOsCacheDir() / splitFile(conf.projectName).name &
  744. nimcacheSuffix(conf))
  745. proc pathSubs*(conf: ConfigRef; p, config: string): string =
  746. let home = removeTrailingDirSep(os.getHomeDir())
  747. result = unixToNativePath(p % [
  748. "nim", getPrefixDir(conf).string,
  749. "lib", conf.libpath.string,
  750. "home", home,
  751. "config", config,
  752. "projectname", conf.projectName,
  753. "projectpath", conf.projectPath.string,
  754. "projectdir", conf.projectPath.string,
  755. "nimcache", getNimcacheDir(conf).string]).expandTilde
  756. iterator nimbleSubs*(conf: ConfigRef; p: string): string =
  757. let pl = p.toLowerAscii
  758. if "$nimblepath" in pl or "$nimbledir" in pl:
  759. for i in countdown(conf.nimblePaths.len-1, 0):
  760. let nimblePath = removeTrailingDirSep(conf.nimblePaths[i].string)
  761. yield p % ["nimblepath", nimblePath, "nimbledir", nimblePath]
  762. else:
  763. yield p
  764. proc toGeneratedFile*(conf: ConfigRef; path: AbsoluteFile,
  765. ext: string): AbsoluteFile =
  766. ## converts "/home/a/mymodule.nim", "rod" to "/home/a/nimcache/mymodule.rod"
  767. result = getNimcacheDir(conf) / RelativeFile path.string.splitPath.tail.changeFileExt(ext)
  768. proc completeGeneratedFilePath*(conf: ConfigRef; f: AbsoluteFile,
  769. createSubDir: bool = true): AbsoluteFile =
  770. ## Return an absolute path of a generated intermediary file.
  771. ## Optionally creates the cache directory if `createSubDir` is `true`.
  772. let subdir = getNimcacheDir(conf)
  773. if createSubDir:
  774. try:
  775. createDir(subdir.string)
  776. except OSError:
  777. conf.quitOrRaise "cannot create directory: " & subdir.string
  778. result = subdir / RelativeFile f.string.splitPath.tail
  779. proc rawFindFile(conf: ConfigRef; f: RelativeFile; suppressStdlib: bool): AbsoluteFile =
  780. for it in conf.searchPaths:
  781. if suppressStdlib and it.string.startsWith(conf.libpath.string):
  782. continue
  783. result = it / f
  784. if fileExists(result):
  785. return canonicalizePath(conf, result)
  786. result = AbsoluteFile""
  787. proc rawFindFile2(conf: ConfigRef; f: RelativeFile): AbsoluteFile =
  788. for i, it in conf.lazyPaths:
  789. result = it / f
  790. if fileExists(result):
  791. # bring to front
  792. for j in countdown(i, 1):
  793. swap(conf.lazyPaths[j], conf.lazyPaths[j-1])
  794. return canonicalizePath(conf, result)
  795. result = AbsoluteFile""
  796. template patchModule(conf: ConfigRef) {.dirty.} =
  797. if not result.isEmpty and conf.moduleOverrides.len > 0:
  798. let key = getPackageName(conf, result.string) & "_" & splitFile(result).name
  799. if conf.moduleOverrides.hasKey(key):
  800. let ov = conf.moduleOverrides[key]
  801. if ov.len > 0: result = AbsoluteFile(ov)
  802. const stdlibDirs* = [
  803. "pure", "core", "arch",
  804. "pure/collections",
  805. "pure/concurrency",
  806. "pure/unidecode", "impure",
  807. "wrappers", "wrappers/linenoise",
  808. "windows", "posix", "js",
  809. "deprecated/pure"]
  810. const
  811. pkgPrefix = "pkg/"
  812. stdPrefix* = "std/"
  813. proc getRelativePathFromConfigPath*(conf: ConfigRef; f: AbsoluteFile, isTitle = false): RelativeFile =
  814. result = RelativeFile("")
  815. let f = $f
  816. if isTitle:
  817. for dir in stdlibDirs:
  818. let path = conf.libpath.string / dir / f.lastPathPart
  819. if path.cmpPaths(f) == 0:
  820. return RelativeFile(stdPrefix & f.splitFile.name)
  821. template search(paths) =
  822. for it in paths:
  823. let it = $it
  824. if f.isRelativeTo(it):
  825. return relativePath(f, it).RelativeFile
  826. search(conf.searchPaths)
  827. search(conf.lazyPaths)
  828. proc findFile*(conf: ConfigRef; f: string; suppressStdlib = false): AbsoluteFile =
  829. if f.isAbsolute:
  830. result = if f.fileExists: AbsoluteFile(f) else: AbsoluteFile""
  831. else:
  832. result = rawFindFile(conf, RelativeFile f, suppressStdlib)
  833. if result.isEmpty:
  834. result = rawFindFile(conf, RelativeFile f.toLowerAscii, suppressStdlib)
  835. if result.isEmpty:
  836. result = rawFindFile2(conf, RelativeFile f)
  837. if result.isEmpty:
  838. result = rawFindFile2(conf, RelativeFile f.toLowerAscii)
  839. patchModule(conf)
  840. proc findModule*(conf: ConfigRef; modulename, currentModule: string): AbsoluteFile =
  841. # returns path to module
  842. var m = addFileExt(modulename, NimExt)
  843. var hasRelativeDot = false
  844. if m.startsWith(pkgPrefix):
  845. result = findFile(conf, m.substr(pkgPrefix.len), suppressStdlib = true)
  846. else:
  847. if m.startsWith(stdPrefix):
  848. result = AbsoluteFile("")
  849. let stripped = m.substr(stdPrefix.len)
  850. for candidate in stdlibDirs:
  851. let path = (conf.libpath.string / candidate / stripped)
  852. if fileExists(path):
  853. result = AbsoluteFile path
  854. break
  855. else: # If prefixed with std/ why would we add the current module path!
  856. let currentPath = currentModule.splitFile.dir
  857. result = AbsoluteFile currentPath / m
  858. if m.startsWith('.') and not fileExists(result):
  859. result = AbsoluteFile ""
  860. hasRelativeDot = true
  861. if not fileExists(result) and not hasRelativeDot:
  862. result = findFile(conf, m)
  863. patchModule(conf)
  864. proc findProjectNimFile*(conf: ConfigRef; pkg: string): string =
  865. const extensions = [".nims", ".cfg", ".nimcfg", ".nimble"]
  866. var
  867. candidates: seq[string] = @[]
  868. dir = pkg
  869. prev = dir
  870. nimblepkg = ""
  871. let pkgname = pkg.lastPathPart()
  872. while true:
  873. for k, f in os.walkDir(dir, relative = true):
  874. if k == pcFile and f != "config.nims":
  875. let (_, name, ext) = splitFile(f)
  876. if ext in extensions:
  877. let x = changeFileExt(dir / name, ".nim")
  878. if fileExists(x):
  879. candidates.add x
  880. if ext == ".nimble":
  881. if nimblepkg.len == 0:
  882. nimblepkg = name
  883. # Since nimble packages can have their source in a subfolder,
  884. # check the last folder we were in for a possible match.
  885. if dir != prev:
  886. let x = prev / x.extractFilename()
  887. if fileExists(x):
  888. candidates.add x
  889. else:
  890. # If we found more than one nimble file, chances are that we
  891. # missed the real project file, or this is an invalid nimble
  892. # package. Either way, bailing is the better choice.
  893. return ""
  894. let pkgname = if nimblepkg.len > 0: nimblepkg else: pkgname
  895. for c in candidates:
  896. if pkgname in c.extractFilename(): return c
  897. if candidates.len > 0:
  898. return candidates[0]
  899. prev = dir
  900. dir = parentDir(dir)
  901. if dir == "": break
  902. return ""
  903. proc canonicalImportAux*(conf: ConfigRef, file: AbsoluteFile): string =
  904. ##[
  905. Shows the canonical module import, e.g.:
  906. system, std/tables, fusion/pointers, system/assertions, std/private/asciitables
  907. ]##
  908. var ret = getRelativePathFromConfigPath(conf, file, isTitle = true)
  909. let dir = getNimbleFile(conf, $file).parentDir.AbsoluteDir
  910. if not dir.isEmpty:
  911. let relPath = relativeTo(file, dir)
  912. if not relPath.isEmpty and (ret.isEmpty or relPath.string.len < ret.string.len):
  913. ret = relPath
  914. if ret.isEmpty:
  915. ret = relativeTo(file, conf.projectPath)
  916. result = ret.string
  917. proc canonicalImport*(conf: ConfigRef, file: AbsoluteFile): string =
  918. let ret = canonicalImportAux(conf, file)
  919. result = ret.nativeToUnixPath.changeFileExt("")
  920. proc canonDynlibName(s: string): string =
  921. let start = if s.startsWith("lib"): 3 else: 0
  922. let ende = strutils.find(s, {'(', ')', '.'})
  923. if ende >= 0:
  924. result = s.substr(start, ende-1)
  925. else:
  926. result = s.substr(start)
  927. proc inclDynlibOverride*(conf: ConfigRef; lib: string) =
  928. conf.dllOverrides[lib.canonDynlibName] = "true"
  929. proc isDynlibOverride*(conf: ConfigRef; lib: string): bool =
  930. result = optDynlibOverrideAll in conf.globalOptions or
  931. conf.dllOverrides.hasKey(lib.canonDynlibName)
  932. proc showNonExportedFields*(conf: ConfigRef) =
  933. incl(conf.globalOptions, optShowNonExportedFields)
  934. proc expandDone*(conf: ConfigRef): bool =
  935. result = conf.ideCmd == ideExpand and conf.expandLevels == 0 and conf.expandProgress
  936. proc parseIdeCmd*(s: string): IdeCmd =
  937. case s:
  938. of "sug": ideSug
  939. of "con": ideCon
  940. of "def": ideDef
  941. of "use": ideUse
  942. of "dus": ideDus
  943. of "chk": ideChk
  944. of "chkFile": ideChkFile
  945. of "mod": ideMod
  946. of "highlight": ideHighlight
  947. of "outline": ideOutline
  948. of "known": ideKnown
  949. of "msg": ideMsg
  950. of "project": ideProject
  951. of "globalSymbols": ideGlobalSymbols
  952. of "recompile": ideRecompile
  953. of "changed": ideChanged
  954. of "type": ideType
  955. else: ideNone
  956. proc `$`*(c: IdeCmd): string =
  957. case c:
  958. of ideSug: "sug"
  959. of ideCon: "con"
  960. of ideDef: "def"
  961. of ideUse: "use"
  962. of ideDus: "dus"
  963. of ideChk: "chk"
  964. of ideChkFile: "chkFile"
  965. of ideMod: "mod"
  966. of ideNone: "none"
  967. of ideHighlight: "highlight"
  968. of ideOutline: "outline"
  969. of ideKnown: "known"
  970. of ideMsg: "msg"
  971. of ideProject: "project"
  972. of ideGlobalSymbols: "globalSymbols"
  973. of ideDeclaration: "declaration"
  974. of ideExpand: "expand"
  975. of ideRecompile: "recompile"
  976. of ideChanged: "changed"
  977. of ideType: "type"
  978. of ideInlayHints: "inlayHints"
  979. proc floatInt64Align*(conf: ConfigRef): int16 =
  980. ## Returns either 4 or 8 depending on reasons.
  981. if conf != nil and conf.target.targetCPU == cpuI386:
  982. #on Linux/BSD i386, double are aligned to 4bytes (except with -malign-double)
  983. if conf.target.targetOS != osWindows:
  984. # on i386 for all known POSIX systems, 64bits ints are aligned
  985. # to 4bytes (except with -malign-double)
  986. return 4
  987. return 8