options.nim 39 KB

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