options.nim 41 KB

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