options.nim 41 KB

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