build_settings.cpp 69 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470
  1. #if defined(GB_SYSTEM_FREEBSD) || defined(GB_SYSTEM_OPENBSD)
  2. #include <sys/types.h>
  3. #include <sys/sysctl.h>
  4. #endif
  5. #include "build_cpuid.cpp"
  6. // #if defined(GB_SYSTEM_WINDOWS)
  7. // #define DEFAULT_TO_THREADED_CHECKER
  8. // #endif
  9. #define DEFAULT_MAX_ERROR_COLLECTOR_COUNT (36)
  10. enum TargetOsKind : u16 {
  11. TargetOs_Invalid,
  12. TargetOs_windows,
  13. TargetOs_darwin,
  14. TargetOs_linux,
  15. TargetOs_essence,
  16. TargetOs_freebsd,
  17. TargetOs_openbsd,
  18. TargetOs_netbsd,
  19. TargetOs_haiku,
  20. TargetOs_wasi,
  21. TargetOs_js,
  22. TargetOs_orca,
  23. TargetOs_freestanding,
  24. TargetOs_COUNT,
  25. };
  26. gb_global String target_os_names[TargetOs_COUNT] = {
  27. str_lit(""),
  28. str_lit("windows"),
  29. str_lit("darwin"),
  30. str_lit("linux"),
  31. str_lit("essence"),
  32. str_lit("freebsd"),
  33. str_lit("openbsd"),
  34. str_lit("netbsd"),
  35. str_lit("haiku"),
  36. str_lit("wasi"),
  37. str_lit("js"),
  38. str_lit("orca"),
  39. str_lit("freestanding"),
  40. };
  41. enum TargetArchKind : u16 {
  42. TargetArch_Invalid,
  43. TargetArch_amd64,
  44. TargetArch_i386,
  45. TargetArch_arm32,
  46. TargetArch_arm64,
  47. TargetArch_wasm32,
  48. TargetArch_wasm64p32,
  49. TargetArch_riscv64,
  50. TargetArch_COUNT,
  51. };
  52. gb_global String target_arch_names[TargetArch_COUNT] = {
  53. str_lit(""),
  54. str_lit("amd64"),
  55. str_lit("i386"),
  56. str_lit("arm32"),
  57. str_lit("arm64"),
  58. str_lit("wasm32"),
  59. str_lit("wasm64p32"),
  60. str_lit("riscv64"),
  61. };
  62. enum TargetEndianKind : u8 {
  63. TargetEndian_Little,
  64. TargetEndian_Big,
  65. TargetEndian_COUNT,
  66. };
  67. gb_global String target_endian_names[TargetEndian_COUNT] = {
  68. str_lit("little"),
  69. str_lit("big"),
  70. };
  71. enum TargetABIKind : u16 {
  72. TargetABI_Default,
  73. TargetABI_Win64,
  74. TargetABI_SysV,
  75. TargetABI_COUNT,
  76. };
  77. gb_global String target_abi_names[TargetABI_COUNT] = {
  78. str_lit(""),
  79. str_lit("win64"),
  80. str_lit("sysv"),
  81. };
  82. enum Windows_Subsystem : u8 {
  83. Windows_Subsystem_UNKNOWN,
  84. Windows_Subsystem_BOOT_APPLICATION,
  85. Windows_Subsystem_CONSOLE, // Default,
  86. Windows_Subsystem_EFI_APPLICATION,
  87. Windows_Subsystem_EFI_BOOT_SERVICE_DRIVER,
  88. Windows_Subsystem_EFI_ROM,
  89. Windows_Subsystem_EFI_RUNTIME_DRIVER,
  90. Windows_Subsystem_NATIVE,
  91. Windows_Subsystem_POSIX,
  92. Windows_Subsystem_WINDOWS,
  93. Windows_Subsystem_WINDOWSCE,
  94. Windows_Subsystem_COUNT,
  95. };
  96. gb_global String windows_subsystem_names[Windows_Subsystem_COUNT] = {
  97. str_lit(""),
  98. str_lit("BOOT_APPLICATION"),
  99. str_lit("CONSOLE"), // Default
  100. str_lit("EFI_APPLICATION"),
  101. str_lit("EFI_BOOT_SERVICE_DRIVER"),
  102. str_lit("EFI_ROM"),
  103. str_lit("EFI_RUNTIME_DRIVER"),
  104. str_lit("NATIVE"),
  105. str_lit("POSIX"),
  106. str_lit("WINDOWS"),
  107. str_lit("WINDOWSCE"),
  108. };
  109. struct MicroarchFeatureList {
  110. String microarch;
  111. String features;
  112. };
  113. #if defined(GB_SYSTEM_WINDOWS)
  114. #include <llvm-c/Config/llvm-config.h>
  115. #else
  116. #include <llvm/Config/llvm-config.h>
  117. #endif
  118. #include "build_settings_microarch.cpp"
  119. gb_global TargetEndianKind target_endians[TargetArch_COUNT] = {
  120. TargetEndian_Little,
  121. TargetEndian_Little,
  122. TargetEndian_Little,
  123. TargetEndian_Little,
  124. TargetEndian_Little,
  125. TargetEndian_Little,
  126. TargetEndian_Little,
  127. };
  128. #ifndef ODIN_VERSION_RAW
  129. #define ODIN_VERSION_RAW "dev-unknown-unknown"
  130. #endif
  131. gb_global String const ODIN_VERSION = str_lit(ODIN_VERSION_RAW);
  132. struct TargetMetrics {
  133. TargetOsKind os;
  134. TargetArchKind arch;
  135. isize ptr_size;
  136. isize int_size;
  137. isize max_align;
  138. isize max_simd_align;
  139. String target_triplet;
  140. TargetABIKind abi;
  141. };
  142. enum Subtarget : u32 {
  143. Subtarget_Default,
  144. Subtarget_iPhone,
  145. Subtarget_iPhoneSimulator,
  146. Subtarget_Android,
  147. Subtarget_COUNT,
  148. Subtarget_Invalid, // NOTE(harold): Must appear after _COUNT as this is not a real subtarget
  149. };
  150. gb_global String subtarget_strings[Subtarget_COUNT] = {
  151. str_lit(""),
  152. str_lit("iphone"),
  153. str_lit("iphonesimulator"),
  154. str_lit("android"),
  155. };
  156. enum QueryDataSetKind {
  157. QueryDataSet_Invalid,
  158. QueryDataSet_GlobalDefinitions,
  159. QueryDataSet_GoToDefinitions,
  160. };
  161. struct QueryDataSetSettings {
  162. QueryDataSetKind kind;
  163. bool ok;
  164. bool compact;
  165. };
  166. enum BuildModeKind {
  167. BuildMode_Executable,
  168. BuildMode_DynamicLibrary,
  169. BuildMode_StaticLibrary,
  170. BuildMode_Object,
  171. BuildMode_Assembly,
  172. BuildMode_LLVM_IR,
  173. BuildMode_COUNT,
  174. };
  175. enum CommandKind : u64 {
  176. Command_run = 1<<0,
  177. Command_build = 1<<1,
  178. Command_check = 1<<2,
  179. Command_doc = 1<<3,
  180. Command_version = 1<<4,
  181. Command_test = 1<<5,
  182. Command_strip_semicolon = 1<<6,
  183. Command_bug_report = 1<<7,
  184. Command_bundle_android = 1<<8,
  185. Command_bundle_macos = 1<<9,
  186. Command_bundle_ios = 1<<10,
  187. Command_bundle_orca = 1<<11,
  188. Command__does_check = Command_run|Command_build|Command_check|Command_doc|Command_test|Command_strip_semicolon,
  189. Command__does_build = Command_run|Command_build|Command_test,
  190. Command_all = ~(CommandKind)0,
  191. };
  192. gb_global char const *odin_command_strings[32] = {
  193. "run",
  194. "build",
  195. "check",
  196. "doc",
  197. "version",
  198. "test",
  199. "strip-semicolon",
  200. "",
  201. "bundle android",
  202. "bundle macos",
  203. "bundle ios",
  204. "bundle orca",
  205. };
  206. enum CmdDocFlag : u32 {
  207. CmdDocFlag_Short = 1<<0,
  208. CmdDocFlag_AllPackages = 1<<1,
  209. CmdDocFlag_DocFormat = 1<<2,
  210. };
  211. enum TimingsExportFormat : i32 {
  212. TimingsExportUnspecified = 0,
  213. TimingsExportJson = 1,
  214. TimingsExportCSV = 2,
  215. };
  216. enum DependenciesExportFormat : i32 {
  217. DependenciesExportUnspecified = 0,
  218. DependenciesExportMake = 1,
  219. DependenciesExportJson = 2,
  220. };
  221. enum ErrorPosStyle {
  222. ErrorPosStyle_Default, // path(line:column) msg
  223. ErrorPosStyle_Unix, // path:line:column: msg
  224. ErrorPosStyle_COUNT
  225. };
  226. enum RelocMode : u8 {
  227. RelocMode_Default,
  228. RelocMode_Static,
  229. RelocMode_PIC,
  230. RelocMode_DynamicNoPIC,
  231. };
  232. enum BuildPath : u8 {
  233. BuildPath_Main_Package, // Input Path to the package directory (or file) we're building.
  234. BuildPath_RC, // Input Path for .rc file, can be set with `-resource:`.
  235. BuildPath_RES, // Output Path for .res file, generated from previous.
  236. BuildPath_Win_SDK_Bin_Path, // windows_sdk_bin_path
  237. BuildPath_Win_SDK_UM_Lib, // windows_sdk_um_library_path
  238. BuildPath_Win_SDK_UCRT_Lib, // windows_sdk_ucrt_library_path
  239. BuildPath_VS_EXE, // vs_exe_path
  240. BuildPath_VS_LIB, // vs_library_path
  241. BuildPath_Output, // Output Path for .exe, .dll, .so, etc. Can be overridden with `-out:`.
  242. BuildPath_Symbols, // Output Path for .pdb or .dSym file, can be overridden with `-pdb-name:`.
  243. BuildPathCOUNT,
  244. };
  245. enum VetFlags : u64 {
  246. VetFlag_NONE = 0,
  247. VetFlag_Shadowing = 1u<<0,
  248. VetFlag_UsingStmt = 1u<<1,
  249. VetFlag_UsingParam = 1u<<2,
  250. VetFlag_Style = 1u<<3,
  251. VetFlag_Semicolon = 1u<<4,
  252. VetFlag_UnusedVariables = 1u<<5,
  253. VetFlag_UnusedImports = 1u<<6,
  254. VetFlag_Deprecated = 1u<<7,
  255. VetFlag_Cast = 1u<<8,
  256. VetFlag_Tabs = 1u<<9,
  257. VetFlag_UnusedProcedures = 1u<<10,
  258. VetFlag_ExplicitAllocators = 1u<<11,
  259. VetFlag_Unused = VetFlag_UnusedVariables|VetFlag_UnusedImports,
  260. VetFlag_All = VetFlag_Unused|VetFlag_Shadowing|VetFlag_UsingStmt|VetFlag_Deprecated|VetFlag_Cast,
  261. VetFlag_Using = VetFlag_UsingStmt|VetFlag_UsingParam,
  262. };
  263. u64 get_vet_flag_from_name(String const &name) {
  264. if (name == "unused") {
  265. return VetFlag_Unused;
  266. } else if (name == "unused-variables") {
  267. return VetFlag_UnusedVariables;
  268. } else if (name == "unused-imports") {
  269. return VetFlag_UnusedImports;
  270. } else if (name == "shadowing") {
  271. return VetFlag_Shadowing;
  272. } else if (name == "using-stmt") {
  273. return VetFlag_UsingStmt;
  274. } else if (name == "using-param") {
  275. return VetFlag_UsingParam;
  276. } else if (name == "style") {
  277. return VetFlag_Style;
  278. } else if (name == "semicolon") {
  279. return VetFlag_Semicolon;
  280. } else if (name == "deprecated") {
  281. return VetFlag_Deprecated;
  282. } else if (name == "cast") {
  283. return VetFlag_Cast;
  284. } else if (name == "tabs") {
  285. return VetFlag_Tabs;
  286. } else if (name == "unused-procedures") {
  287. return VetFlag_UnusedProcedures;
  288. } else if (name == "explicit-allocators") {
  289. return VetFlag_ExplicitAllocators;
  290. }
  291. return VetFlag_NONE;
  292. }
  293. enum OptInFeatureFlags : u64 {
  294. OptInFeatureFlag_NONE = 0,
  295. OptInFeatureFlag_DynamicLiterals = 1u<<0,
  296. };
  297. u64 get_feature_flag_from_name(String const &name) {
  298. if (name == "dynamic-literals") {
  299. return OptInFeatureFlag_DynamicLiterals;
  300. }
  301. return OptInFeatureFlag_NONE;
  302. }
  303. enum SanitizerFlags : u32 {
  304. SanitizerFlag_NONE = 0,
  305. SanitizerFlag_Address = 1u<<0,
  306. SanitizerFlag_Memory = 1u<<1,
  307. SanitizerFlag_Thread = 1u<<2,
  308. };
  309. struct BuildCacheData {
  310. u64 crc;
  311. String cache_dir;
  312. // manifests
  313. String files_path;
  314. String args_path;
  315. String env_path;
  316. bool copy_already_done;
  317. };
  318. enum LinkerChoice : i32 {
  319. Linker_Invalid = -1,
  320. Linker_Default = 0,
  321. Linker_lld,
  322. Linker_radlink,
  323. Linker_COUNT,
  324. };
  325. enum SourceCodeLocationInfo : u8 {
  326. SourceCodeLocationInfo_Normal = 0,
  327. SourceCodeLocationInfo_Obfuscated = 1,
  328. SourceCodeLocationInfo_Filename = 2,
  329. SourceCodeLocationInfo_None = 3,
  330. };
  331. String linker_choices[Linker_COUNT] = {
  332. str_lit("default"),
  333. str_lit("lld"),
  334. str_lit("radlink"),
  335. };
  336. // This stores the information for the specify architecture of this build
  337. struct BuildContext {
  338. // Constants
  339. String ODIN_OS; // Target operating system
  340. String ODIN_ARCH; // Target architecture
  341. String ODIN_VENDOR; // Compiler vendor
  342. String ODIN_VERSION; // Compiler version
  343. String ODIN_ROOT; // Odin ROOT
  344. String ODIN_BUILD_PROJECT_NAME; // Odin main/initial package's directory name
  345. Windows_Subsystem ODIN_WINDOWS_SUBSYSTEM; // .Console, .Windows
  346. bool ODIN_DEBUG; // Odin in debug mode
  347. bool ODIN_DISABLE_ASSERT; // Whether the default 'assert' et al is disabled in code or not
  348. bool ODIN_DEFAULT_TO_NIL_ALLOCATOR; // Whether the default allocator is a "nil" allocator or not (i.e. it does nothing)
  349. bool ODIN_DEFAULT_TO_PANIC_ALLOCATOR; // Whether the default allocator is a "panic" allocator or not (i.e. panics on any call to it)
  350. bool ODIN_FOREIGN_ERROR_PROCEDURES;
  351. bool ODIN_VALGRIND_SUPPORT;
  352. ErrorPosStyle ODIN_ERROR_POS_STYLE;
  353. TargetEndianKind endian_kind;
  354. // In bytes
  355. i64 ptr_size; // Size of a pointer, must be >= 4
  356. i64 int_size; // Size of a int/uint, must be >= 4
  357. i64 max_align; // max alignment, must be >= 1 (and typically >= ptr_size)
  358. i64 max_simd_align; // max alignment, must be >= 1 (and typically >= ptr_size)
  359. CommandKind command_kind;
  360. String command;
  361. TargetMetrics metrics;
  362. bool show_help;
  363. Array<Path> build_paths; // Contains `Path` objects to output filename, pdb, resource and intermediate files.
  364. // BuildPath enum contains the indices of paths we know *before* the work starts.
  365. String out_filepath;
  366. String resource_filepath;
  367. String pdb_filepath;
  368. u64 vet_flags;
  369. u32 sanitizer_flags;
  370. StringSet vet_packages;
  371. bool has_resource;
  372. String link_flags;
  373. String extra_linker_flags;
  374. String extra_assembler_flags;
  375. String microarch;
  376. BuildModeKind build_mode;
  377. bool keep_executable;
  378. bool generate_docs;
  379. bool custom_optimization_level;
  380. i32 optimization_level;
  381. bool show_timings;
  382. TimingsExportFormat export_timings_format;
  383. String export_timings_file;
  384. DependenciesExportFormat export_dependencies_format;
  385. String export_dependencies_file;
  386. bool show_unused;
  387. bool show_unused_with_location;
  388. bool show_more_timings;
  389. bool show_defineables;
  390. String export_defineables_file;
  391. bool show_system_calls;
  392. bool keep_temp_files;
  393. bool ignore_unknown_attributes;
  394. bool no_bounds_check;
  395. bool no_type_assert;
  396. bool dynamic_literals; // Opt-in to `#+feature dynamic-literals` project-wide.
  397. bool no_output_files;
  398. bool no_crt;
  399. bool no_rpath;
  400. bool no_entry_point;
  401. bool no_thread_local;
  402. bool cross_compiling;
  403. bool different_os;
  404. bool keep_object_files;
  405. bool disallow_do;
  406. LinkerChoice linker_choice;
  407. StringSet custom_attributes;
  408. bool strict_style;
  409. bool ignore_warnings;
  410. bool warnings_as_errors;
  411. bool hide_error_line;
  412. bool terse_errors;
  413. bool json_errors;
  414. bool has_ansi_terminal_colours;
  415. bool fast_isel;
  416. bool ignore_lazy;
  417. bool ignore_llvm_build;
  418. bool ignore_panic;
  419. bool ignore_microsoft_magic;
  420. bool linker_map_file;
  421. bool use_single_module;
  422. bool use_separate_modules;
  423. bool module_per_file;
  424. bool cached;
  425. BuildCacheData build_cache_data;
  426. bool internal_no_inline;
  427. bool internal_by_value;
  428. bool no_threaded_checker;
  429. bool show_debug_messages;
  430. bool copy_file_contents;
  431. bool no_rtti;
  432. bool dynamic_map_calls;
  433. SourceCodeLocationInfo source_code_location_info;
  434. bool min_link_libs;
  435. bool print_linker_flags;
  436. RelocMode reloc_mode;
  437. bool disable_red_zone;
  438. isize max_error_count;
  439. bool tilde_backend;
  440. u32 cmd_doc_flags;
  441. Array<String> extra_packages;
  442. bool test_all_packages;
  443. gbAffinity affinity;
  444. isize thread_count;
  445. PtrMap<char const *, ExactValue> defined_values;
  446. StringSet target_features_set;
  447. String target_features_string;
  448. bool strict_target_features;
  449. String minimum_os_version_string;
  450. bool minimum_os_version_string_given;
  451. int ODIN_ANDROID_API_LEVEL;
  452. String ODIN_ANDROID_SDK;
  453. String ODIN_ANDROID_NDK;
  454. String ODIN_ANDROID_NDK_TOOLCHAIN;
  455. String ODIN_ANDROID_NDK_TOOLCHAIN_LIB;
  456. String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL;
  457. String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT;
  458. String android_keystore;
  459. String android_keystore_alias;
  460. String android_keystore_password;
  461. };
  462. gb_global BuildContext build_context = {0};
  463. gb_internal bool IS_ODIN_DEBUG(void) {
  464. return build_context.ODIN_DEBUG;
  465. }
  466. gb_internal bool global_warnings_as_errors(void) {
  467. return build_context.warnings_as_errors;
  468. }
  469. gb_internal bool global_ignore_warnings(void) {
  470. return build_context.ignore_warnings;
  471. }
  472. gb_internal isize MAX_ERROR_COLLECTOR_COUNT(void) {
  473. if (build_context.max_error_count <= 0) {
  474. return DEFAULT_MAX_ERROR_COLLECTOR_COUNT;
  475. }
  476. return build_context.max_error_count;
  477. }
  478. // NOTE: AMD64 targets had their alignment on 128 bit ints bumped from 8 to 16 (undocumented of course).
  479. #if LLVM_VERSION_MAJOR >= 18
  480. #define AMD64_MAX_ALIGNMENT 16
  481. #else
  482. #define AMD64_MAX_ALIGNMENT 8
  483. #endif
  484. #if LLVM_VERSION_MAJOR >= 18
  485. #define I386_MAX_ALIGNMENT 16
  486. #else
  487. #define I386_MAX_ALIGNMENT 4
  488. #endif
  489. gb_global TargetMetrics target_windows_i386 = {
  490. TargetOs_windows,
  491. TargetArch_i386,
  492. 4, 4, I386_MAX_ALIGNMENT, 16,
  493. str_lit("i386-pc-windows-msvc"),
  494. };
  495. gb_global TargetMetrics target_windows_amd64 = {
  496. TargetOs_windows,
  497. TargetArch_amd64,
  498. 8, 8, AMD64_MAX_ALIGNMENT, 32,
  499. str_lit("x86_64-pc-windows-msvc"),
  500. };
  501. gb_global TargetMetrics target_linux_i386 = {
  502. TargetOs_linux,
  503. TargetArch_i386,
  504. 4, 4, I386_MAX_ALIGNMENT, 16,
  505. str_lit("i386-pc-linux-gnu"),
  506. };
  507. gb_global TargetMetrics target_linux_amd64 = {
  508. TargetOs_linux,
  509. TargetArch_amd64,
  510. 8, 8, AMD64_MAX_ALIGNMENT, 32,
  511. str_lit("x86_64-pc-linux-gnu"),
  512. };
  513. gb_global TargetMetrics target_linux_arm64 = {
  514. TargetOs_linux,
  515. TargetArch_arm64,
  516. 8, 8, 16, 32,
  517. str_lit("aarch64-linux-elf"),
  518. };
  519. gb_global TargetMetrics target_linux_arm32 = {
  520. TargetOs_linux,
  521. TargetArch_arm32,
  522. 4, 4, 8, 16,
  523. str_lit("arm-unknown-linux-gnueabihf"),
  524. };
  525. gb_global TargetMetrics target_linux_riscv64 = {
  526. TargetOs_linux,
  527. TargetArch_riscv64,
  528. 8, 8, 16, 32,
  529. str_lit("riscv64-linux-gnu"),
  530. };
  531. gb_global TargetMetrics target_darwin_amd64 = {
  532. TargetOs_darwin,
  533. TargetArch_amd64,
  534. 8, 8, AMD64_MAX_ALIGNMENT, 32,
  535. str_lit("x86_64-apple-macosx"), // NOTE: Changes during initialization based on build flags.
  536. };
  537. gb_global TargetMetrics target_darwin_arm64 = {
  538. TargetOs_darwin,
  539. TargetArch_arm64,
  540. 8, 8, 16, 32,
  541. str_lit("arm64-apple-macosx"), // NOTE: Changes during initialization based on build flags.
  542. };
  543. gb_global TargetMetrics target_freebsd_i386 = {
  544. TargetOs_freebsd,
  545. TargetArch_i386,
  546. 4, 4, I386_MAX_ALIGNMENT, 16,
  547. str_lit("i386-unknown-freebsd-elf"),
  548. };
  549. gb_global TargetMetrics target_freebsd_amd64 = {
  550. TargetOs_freebsd,
  551. TargetArch_amd64,
  552. 8, 8, AMD64_MAX_ALIGNMENT, 32,
  553. str_lit("x86_64-unknown-freebsd-elf"),
  554. };
  555. gb_global TargetMetrics target_freebsd_arm64 = {
  556. TargetOs_freebsd,
  557. TargetArch_arm64,
  558. 8, 8, 16, 32,
  559. str_lit("aarch64-unknown-freebsd-elf"),
  560. };
  561. gb_global TargetMetrics target_openbsd_amd64 = {
  562. TargetOs_openbsd,
  563. TargetArch_amd64,
  564. 8, 8, AMD64_MAX_ALIGNMENT, 32,
  565. str_lit("x86_64-unknown-openbsd-elf"),
  566. };
  567. gb_global TargetMetrics target_netbsd_amd64 = {
  568. TargetOs_netbsd,
  569. TargetArch_amd64,
  570. 8, 8, AMD64_MAX_ALIGNMENT, 32,
  571. str_lit("x86_64-unknown-netbsd-elf"),
  572. };
  573. gb_global TargetMetrics target_netbsd_arm64 = {
  574. TargetOs_netbsd,
  575. TargetArch_arm64,
  576. 8, 8, 16, 32,
  577. str_lit("aarch64-unknown-netbsd-elf"),
  578. };
  579. gb_global TargetMetrics target_haiku_amd64 = {
  580. TargetOs_haiku,
  581. TargetArch_amd64,
  582. 8, 8, AMD64_MAX_ALIGNMENT, 32,
  583. str_lit("x86_64-unknown-haiku"),
  584. };
  585. gb_global TargetMetrics target_essence_amd64 = {
  586. TargetOs_essence,
  587. TargetArch_amd64,
  588. 8, 8, AMD64_MAX_ALIGNMENT, 32,
  589. str_lit("x86_64-pc-none-elf"),
  590. };
  591. gb_global TargetMetrics target_freestanding_wasm32 = {
  592. TargetOs_freestanding,
  593. TargetArch_wasm32,
  594. 4, 4, 8, 16,
  595. str_lit("wasm32-freestanding-js"),
  596. };
  597. gb_global TargetMetrics target_js_wasm32 = {
  598. TargetOs_js,
  599. TargetArch_wasm32,
  600. 4, 4, 8, 16,
  601. str_lit("wasm32-js-js"),
  602. };
  603. gb_global TargetMetrics target_wasi_wasm32 = {
  604. TargetOs_wasi,
  605. TargetArch_wasm32,
  606. 4, 4, 8, 16,
  607. str_lit("wasm32-wasi-js"),
  608. };
  609. gb_global TargetMetrics target_orca_wasm32 = {
  610. TargetOs_orca,
  611. TargetArch_wasm32,
  612. 4, 4, 8, 16,
  613. str_lit("wasm32-wasi-js"),
  614. };
  615. gb_global TargetMetrics target_freestanding_wasm64p32 = {
  616. TargetOs_freestanding,
  617. TargetArch_wasm64p32,
  618. 4, 8, 8, 16,
  619. str_lit("wasm32-freestanding-js"),
  620. };
  621. gb_global TargetMetrics target_js_wasm64p32 = {
  622. TargetOs_js,
  623. TargetArch_wasm64p32,
  624. 4, 8, 8, 16,
  625. str_lit("wasm32-js-js"),
  626. };
  627. gb_global TargetMetrics target_wasi_wasm64p32 = {
  628. TargetOs_wasi,
  629. TargetArch_wasm32,
  630. 4, 8, 8, 16,
  631. str_lit("wasm32-wasi-js"),
  632. };
  633. gb_global TargetMetrics target_freestanding_amd64_sysv = {
  634. TargetOs_freestanding,
  635. TargetArch_amd64,
  636. 8, 8, AMD64_MAX_ALIGNMENT, 32,
  637. str_lit("x86_64-pc-none-gnu"),
  638. TargetABI_SysV,
  639. };
  640. gb_global TargetMetrics target_freestanding_amd64_win64 = {
  641. TargetOs_freestanding,
  642. TargetArch_amd64,
  643. 8, 8, AMD64_MAX_ALIGNMENT, 32,
  644. str_lit("x86_64-pc-none-msvc"),
  645. TargetABI_Win64,
  646. };
  647. gb_global TargetMetrics target_freestanding_arm64 = {
  648. TargetOs_freestanding,
  649. TargetArch_arm64,
  650. 8, 8, 16, 32,
  651. str_lit("aarch64-none-elf"),
  652. };
  653. gb_global TargetMetrics target_freestanding_arm32 = {
  654. TargetOs_freestanding,
  655. TargetArch_arm32,
  656. 4, 4, 8, 16,
  657. str_lit("arm-unknown-unknown-gnueabihf"),
  658. };
  659. gb_global TargetMetrics target_freestanding_riscv64 = {
  660. TargetOs_freestanding,
  661. TargetArch_riscv64,
  662. 8, 8, 16, 32,
  663. str_lit("riscv64-unknown-gnu"),
  664. };
  665. struct NamedTargetMetrics {
  666. String name;
  667. TargetMetrics *metrics;
  668. };
  669. gb_global NamedTargetMetrics named_targets[] = {
  670. { str_lit("darwin_amd64"), &target_darwin_amd64 },
  671. { str_lit("darwin_arm64"), &target_darwin_arm64 },
  672. { str_lit("essence_amd64"), &target_essence_amd64 },
  673. { str_lit("linux_i386"), &target_linux_i386 },
  674. { str_lit("linux_amd64"), &target_linux_amd64 },
  675. { str_lit("linux_arm64"), &target_linux_arm64 },
  676. { str_lit("linux_arm32"), &target_linux_arm32 },
  677. { str_lit("linux_riscv64"), &target_linux_riscv64 },
  678. { str_lit("windows_i386"), &target_windows_i386 },
  679. { str_lit("windows_amd64"), &target_windows_amd64 },
  680. { str_lit("freebsd_i386"), &target_freebsd_i386 },
  681. { str_lit("freebsd_amd64"), &target_freebsd_amd64 },
  682. { str_lit("freebsd_arm64"), &target_freebsd_arm64 },
  683. { str_lit("netbsd_amd64"), &target_netbsd_amd64 },
  684. { str_lit("netbsd_arm64"), &target_netbsd_arm64 },
  685. { str_lit("openbsd_amd64"), &target_openbsd_amd64 },
  686. { str_lit("haiku_amd64"), &target_haiku_amd64 },
  687. { str_lit("freestanding_wasm32"), &target_freestanding_wasm32 },
  688. { str_lit("wasi_wasm32"), &target_wasi_wasm32 },
  689. { str_lit("js_wasm32"), &target_js_wasm32 },
  690. { str_lit("orca_wasm32"), &target_orca_wasm32 },
  691. { str_lit("freestanding_wasm64p32"), &target_freestanding_wasm64p32 },
  692. { str_lit("js_wasm64p32"), &target_js_wasm64p32 },
  693. { str_lit("wasi_wasm64p32"), &target_wasi_wasm64p32 },
  694. { str_lit("freestanding_amd64_sysv"), &target_freestanding_amd64_sysv },
  695. { str_lit("freestanding_amd64_win64"), &target_freestanding_amd64_win64 },
  696. { str_lit("freestanding_arm64"), &target_freestanding_arm64 },
  697. { str_lit("freestanding_arm32"), &target_freestanding_arm32 },
  698. { str_lit("freestanding_riscv64"), &target_freestanding_riscv64 },
  699. };
  700. gb_global NamedTargetMetrics *selected_target_metrics;
  701. gb_global Subtarget selected_subtarget;
  702. gb_internal TargetOsKind get_target_os_from_string(String str, Subtarget *subtarget_ = nullptr, String *subtarget_str = nullptr) {
  703. String os_name = str;
  704. String subtarget = {};
  705. auto part = string_partition(str, str_lit(":"));
  706. if (part.match.len == 1) {
  707. os_name = part.head;
  708. subtarget = part.tail;
  709. }
  710. TargetOsKind kind = TargetOs_Invalid;
  711. for (isize i = 0; i < TargetOs_COUNT; i++) {
  712. if (str_eq_ignore_case(target_os_names[i], os_name)) {
  713. kind = cast(TargetOsKind)i;
  714. break;
  715. }
  716. }
  717. if (subtarget_str) *subtarget_str = subtarget;
  718. if (subtarget_) {
  719. if (subtarget.len != 0) {
  720. *subtarget_ = Subtarget_Invalid;
  721. if (str_eq_ignore_case(subtarget, "generic") || str_eq_ignore_case(subtarget, "default")) {
  722. *subtarget_ = Subtarget_Default;
  723. } else {
  724. for (isize i = 1; i < Subtarget_COUNT; i++) {
  725. if (str_eq_ignore_case(subtarget_strings[i], subtarget)) {
  726. *subtarget_ = cast(Subtarget)i;
  727. break;
  728. }
  729. }
  730. }
  731. } else {
  732. *subtarget_ = Subtarget_Default;
  733. }
  734. }
  735. return kind;
  736. }
  737. gb_internal TargetArchKind get_target_arch_from_string(String str) {
  738. for (isize i = 0; i < TargetArch_COUNT; i++) {
  739. if (str_eq_ignore_case(target_arch_names[i], str)) {
  740. return cast(TargetArchKind)i;
  741. }
  742. }
  743. return TargetArch_Invalid;
  744. }
  745. gb_internal bool is_excluded_target_filename(String name) {
  746. String original_name = name;
  747. name = remove_extension_from_path(name);
  748. if (string_starts_with(name, str_lit("."))) {
  749. // Ignore .*.odin files
  750. return true;
  751. }
  752. if (build_context.command_kind != Command_test) {
  753. String test_suffix = str_lit("_test");
  754. if (string_ends_with(name, test_suffix) && name != test_suffix) {
  755. // Ignore *_test.odin files
  756. return true;
  757. }
  758. }
  759. String str1 = {};
  760. String str2 = {};
  761. isize n = 0;
  762. str1 = name;
  763. n = str1.len;
  764. for (isize i = str1.len-1; i >= 0 && str1[i] != '_'; i--) {
  765. n -= 1;
  766. }
  767. str1 = substring(str1, n, str1.len);
  768. str2 = substring(name, 0, gb_max(n-1, 0));
  769. n = str2.len;
  770. for (isize i = str2.len-1; i >= 0 && str2[i] != '_'; i--) {
  771. n -= 1;
  772. }
  773. str2 = substring(str2, n, str2.len);
  774. if (str1 == name) {
  775. return false;
  776. }
  777. TargetOsKind os1 = get_target_os_from_string(str1);
  778. TargetArchKind arch1 = get_target_arch_from_string(str1);
  779. TargetOsKind os2 = get_target_os_from_string(str2);
  780. TargetArchKind arch2 = get_target_arch_from_string(str2);
  781. if (os1 != TargetOs_Invalid && arch2 != TargetArch_Invalid) {
  782. return os1 != build_context.metrics.os || arch2 != build_context.metrics.arch;
  783. } else if (arch1 != TargetArch_Invalid && os2 != TargetOs_Invalid) {
  784. return arch1 != build_context.metrics.arch || os2 != build_context.metrics.os;
  785. } else if (os1 != TargetOs_Invalid) {
  786. return os1 != build_context.metrics.os;
  787. } else if (arch1 != TargetArch_Invalid) {
  788. return arch1 != build_context.metrics.arch;
  789. }
  790. return false;
  791. }
  792. struct LibraryCollections {
  793. String name;
  794. String path;
  795. };
  796. gb_global Array<LibraryCollections> library_collections = {0};
  797. gb_internal void add_library_collection(String name, String path) {
  798. LibraryCollections lc = {name, string_trim_whitespace(path)};
  799. array_add(&library_collections, lc);
  800. }
  801. gb_internal bool find_library_collection_path(String name, String *path) {
  802. for (auto const &lc : library_collections) {
  803. if (lc.name == name) {
  804. if (path) *path = lc.path;
  805. return true;
  806. }
  807. }
  808. return false;
  809. }
  810. gb_internal bool is_arch_wasm(void) {
  811. switch (build_context.metrics.arch) {
  812. case TargetArch_wasm32:
  813. case TargetArch_wasm64p32:
  814. return true;
  815. }
  816. return false;
  817. }
  818. gb_internal bool is_arch_x86(void) {
  819. switch (build_context.metrics.arch) {
  820. case TargetArch_i386:
  821. case TargetArch_amd64:
  822. return true;
  823. }
  824. return false;
  825. }
  826. // TODO(bill): OS dependent versions for the BuildContext
  827. // join_path
  828. // is_dir
  829. // is_file
  830. // is_abs_path
  831. // has_subdir
  832. gb_global String const WIN32_SEPARATOR_STRING = {cast(u8 *)"\\", 1};
  833. gb_global String const NIX_SEPARATOR_STRING = {cast(u8 *)"/", 1};
  834. gb_global String const SEPARATOR_STRING =
  835. #if defined(GB_SYSTEM_WINDOWS)
  836. WIN32_SEPARATOR_STRING;
  837. #else
  838. NIX_SEPARATOR_STRING;
  839. #endif
  840. gb_global String const WASM_MODULE_NAME_SEPARATOR = str_lit("..");
  841. gb_internal String internal_odin_root_dir(void);
  842. gb_internal String odin_root_dir(void) {
  843. if (global_module_path_set) {
  844. return global_module_path;
  845. }
  846. gbAllocator a = permanent_allocator();
  847. char const *found = gb_get_env("ODIN_ROOT", a);
  848. if (found) {
  849. String path = path_to_full_path(a, make_string_c(found));
  850. #if defined(GB_SYSTEM_WINDOWS)
  851. path = normalize_path(a, path, WIN32_SEPARATOR_STRING);
  852. #else
  853. path = normalize_path(a, path, NIX_SEPARATOR_STRING);
  854. #endif
  855. global_module_path = path;
  856. global_module_path_set = true;
  857. return global_module_path;
  858. }
  859. return internal_odin_root_dir();
  860. }
  861. #if defined(GB_SYSTEM_WINDOWS)
  862. gb_internal String internal_odin_root_dir(void) {
  863. String path = global_module_path;
  864. isize len, i;
  865. wchar_t *text;
  866. if (global_module_path_set) {
  867. return global_module_path;
  868. }
  869. auto path_buf = array_make<wchar_t>(heap_allocator(), 300);
  870. len = 0;
  871. for (;;) {
  872. len = GetModuleFileNameW(nullptr, &path_buf[0], cast(int)path_buf.count);
  873. if (len == 0) {
  874. return make_string(nullptr, 0);
  875. }
  876. if (len < path_buf.count) {
  877. break;
  878. }
  879. array_resize(&path_buf, 2*path_buf.count + 300);
  880. }
  881. len += 1; // NOTE(bill): It needs an extra 1 for some reason
  882. mutex_lock(&string_buffer_mutex);
  883. defer (mutex_unlock(&string_buffer_mutex));
  884. text = gb_alloc_array(permanent_allocator(), wchar_t, len+1);
  885. GetModuleFileNameW(nullptr, text, cast(int)len);
  886. path = string16_to_string(heap_allocator(), make_string16(text, len));
  887. for (i = path.len-1; i >= 0; i--) {
  888. u8 c = path[i];
  889. if (c == '/' || c == '\\') {
  890. break;
  891. }
  892. path.len--;
  893. }
  894. global_module_path = path;
  895. global_module_path_set = true;
  896. array_free(&path_buf);
  897. return path;
  898. }
  899. #elif defined(GB_SYSTEM_HAIKU)
  900. #include <FindDirectory.h>
  901. gb_internal String path_to_fullpath(gbAllocator a, String s, bool *ok_);
  902. gb_internal String internal_odin_root_dir(void) {
  903. String path = global_module_path;
  904. isize len, i;
  905. u8 *text;
  906. if (global_module_path_set) {
  907. return global_module_path;
  908. }
  909. auto path_buf = array_make<char>(heap_allocator(), 300);
  910. defer (array_free(&path_buf));
  911. len = 0;
  912. for (;;) {
  913. u32 sz = path_buf.count;
  914. int res = find_path(B_APP_IMAGE_SYMBOL, B_FIND_PATH_IMAGE_PATH, nullptr, &path_buf[0], sz);
  915. if(res == B_OK) {
  916. len = sz;
  917. break;
  918. } else {
  919. array_resize(&path_buf, sz + 1);
  920. }
  921. }
  922. mutex_lock(&string_buffer_mutex);
  923. defer (mutex_unlock(&string_buffer_mutex));
  924. text = gb_alloc_array(permanent_allocator(), u8, len + 1);
  925. gb_memmove(text, &path_buf[0], len);
  926. path = path_to_fullpath(heap_allocator(), make_string(text, len), nullptr);
  927. for (i = path.len-1; i >= 0; i--) {
  928. u8 c = path[i];
  929. if (c == '/' || c == '\\') {
  930. break;
  931. }
  932. path.len--;
  933. }
  934. global_module_path = path;
  935. global_module_path_set = true;
  936. return path;
  937. }
  938. #elif defined(GB_SYSTEM_OSX)
  939. #include <mach-o/dyld.h>
  940. gb_internal String path_to_fullpath(gbAllocator a, String s, bool *ok_);
  941. gb_internal String internal_odin_root_dir(void) {
  942. String path = global_module_path;
  943. isize len, i;
  944. u8 *text;
  945. if (global_module_path_set) {
  946. return global_module_path;
  947. }
  948. auto path_buf = array_make<char>(heap_allocator(), 300);
  949. defer (array_free(&path_buf));
  950. len = 0;
  951. for (;;) {
  952. u32 sz = path_buf.count;
  953. int res = _NSGetExecutablePath(&path_buf[0], &sz);
  954. if(res == 0) {
  955. len = sz;
  956. break;
  957. } else {
  958. array_resize(&path_buf, sz + 1);
  959. }
  960. }
  961. mutex_lock(&string_buffer_mutex);
  962. defer (mutex_unlock(&string_buffer_mutex));
  963. text = gb_alloc_array(permanent_allocator(), u8, len + 1);
  964. gb_memmove(text, &path_buf[0], len);
  965. path = path_to_fullpath(heap_allocator(), make_string(text, len), nullptr);
  966. for (i = path.len-1; i >= 0; i--) {
  967. u8 c = path[i];
  968. if (c == '/' || c == '\\') {
  969. break;
  970. }
  971. path.len--;
  972. }
  973. global_module_path = path;
  974. global_module_path_set = true;
  975. return path;
  976. }
  977. #else
  978. // NOTE: Linux / Unix is unfinished and not tested very well.
  979. #include <sys/stat.h>
  980. gb_internal String path_to_fullpath(gbAllocator a, String s, bool *ok_);
  981. gb_internal String internal_odin_root_dir(void) {
  982. String path = global_module_path;
  983. isize len, i;
  984. u8 *text;
  985. if (global_module_path_set) {
  986. return global_module_path;
  987. }
  988. auto path_buf = array_make<char>(heap_allocator(), 300);
  989. defer (array_free(&path_buf));
  990. len = 0;
  991. for (;;) {
  992. // This is not a 100% reliable system, but for the purposes
  993. // of this compiler, it should be _good enough_.
  994. // That said, there's no solid 100% method on Linux to get the program's
  995. // path without checking this link. Sorry.
  996. #if defined(GB_SYSTEM_FREEBSD)
  997. int mib[4];
  998. mib[0] = CTL_KERN;
  999. mib[1] = KERN_PROC;
  1000. mib[2] = KERN_PROC_PATHNAME;
  1001. mib[3] = -1;
  1002. len = path_buf.count;
  1003. sysctl(mib, 4, &path_buf[0], (size_t *) &len, NULL, 0);
  1004. #elif defined(GB_SYSTEM_NETBSD)
  1005. len = readlink("/proc/curproc/exe", &path_buf[0], path_buf.count);
  1006. #elif defined(GB_SYSTEM_DRAGONFLYBSD)
  1007. len = readlink("/proc/curproc/file", &path_buf[0], path_buf.count);
  1008. #elif defined(GB_SYSTEM_LINUX)
  1009. len = readlink("/proc/self/exe", &path_buf[0], path_buf.count);
  1010. #elif defined(GB_SYSTEM_OPENBSD)
  1011. int error;
  1012. int mib[] = {
  1013. CTL_KERN,
  1014. KERN_PROC_ARGS,
  1015. getpid(),
  1016. KERN_PROC_ARGV,
  1017. };
  1018. // get argv size
  1019. error = sysctl(mib, 4, NULL, (size_t *) &len, NULL, 0);
  1020. if (error == -1) {
  1021. // sysctl error
  1022. return make_string(nullptr, 0);
  1023. }
  1024. // get argv
  1025. char **argv = (char **)gb_malloc(len);
  1026. error = sysctl(mib, 4, argv, (size_t *) &len, NULL, 0);
  1027. if (error == -1) {
  1028. // sysctl error
  1029. gb_mfree(argv);
  1030. return make_string(nullptr, 0);
  1031. }
  1032. // NOTE(Jeroen):
  1033. // On OpenBSD, if `odin` is on the path, `argv[0]` will contain just `odin`,
  1034. // even though that isn't then the relative path.
  1035. // When run from Odin's directory, it returns `./odin`.
  1036. // Check argv[0] for lack of / to see if it's a reference to PATH.
  1037. // If so, walk PATH to find the executable.
  1038. len = gb_strlen(argv[0]);
  1039. bool slash_found = false;
  1040. bool odin_found = false;
  1041. for (int i = 0; i < len; i += 1) {
  1042. if (argv[0][i] == '/') {
  1043. slash_found = true;
  1044. break;
  1045. }
  1046. }
  1047. if (slash_found) {
  1048. // copy argv[0] to path_buf
  1049. if(len < path_buf.count) {
  1050. gb_memmove(&path_buf[0], argv[0], len);
  1051. odin_found = true;
  1052. }
  1053. } else {
  1054. gbAllocator a = heap_allocator();
  1055. char const *path_env = gb_get_env("PATH", a);
  1056. defer (gb_free(a, cast(void *)path_env));
  1057. if (path_env) {
  1058. int path_len = gb_strlen(path_env);
  1059. int path_start = 0;
  1060. int path_end = 0;
  1061. for (; path_start < path_len; ) {
  1062. for (; path_end <= path_len; path_end++) {
  1063. if (path_env[path_end] == ':' || path_end == path_len) {
  1064. break;
  1065. }
  1066. }
  1067. String path_needle = (const String)make_string((const u8 *)(path_env + path_start), path_end - path_start);
  1068. String argv0 = (const String)make_string((const u8 *)argv[0], len);
  1069. String odin_candidate = concatenate3_strings(a, path_needle, STR_LIT("/"), argv0);
  1070. defer (gb_free(a, odin_candidate.text));
  1071. if (gb_file_exists((const char *)odin_candidate.text)) {
  1072. len = odin_candidate.len;
  1073. if(len < path_buf.count) {
  1074. gb_memmove(&path_buf[0], odin_candidate.text, len);
  1075. }
  1076. odin_found = true;
  1077. break;
  1078. }
  1079. path_start = path_end + 1;
  1080. path_end = path_start;
  1081. if (path_start > path_len) {
  1082. break;
  1083. }
  1084. }
  1085. }
  1086. if (!odin_found) {
  1087. gb_printf_err("Odin could not locate itself in PATH, and ODIN_ROOT wasn't set either.\n");
  1088. }
  1089. }
  1090. gb_mfree(argv);
  1091. #endif
  1092. if(len == 0 || len == -1) {
  1093. return make_string(nullptr, 0);
  1094. }
  1095. if (len < path_buf.count) {
  1096. break;
  1097. }
  1098. array_resize(&path_buf, 2*path_buf.count + 300);
  1099. }
  1100. mutex_lock(&string_buffer_mutex);
  1101. defer (mutex_unlock(&string_buffer_mutex));
  1102. text = gb_alloc_array(permanent_allocator(), u8, len + 1);
  1103. gb_memmove(text, &path_buf[0], len);
  1104. path = path_to_fullpath(heap_allocator(), make_string(text, len), nullptr);
  1105. for (i = path.len-1; i >= 0; i--) {
  1106. u8 c = path[i];
  1107. if (c == '/' || c == '\\') {
  1108. break;
  1109. }
  1110. path.len--;
  1111. }
  1112. global_module_path = path;
  1113. global_module_path_set = true;
  1114. return path;
  1115. }
  1116. #endif
  1117. gb_global BlockingMutex fullpath_mutex;
  1118. #if defined(GB_SYSTEM_WINDOWS)
  1119. gb_internal String path_to_fullpath(gbAllocator a, String s, bool *ok_) {
  1120. String result = {};
  1121. String16 string16 = string_to_string16(heap_allocator(), s);
  1122. defer (gb_free(heap_allocator(), string16.text));
  1123. DWORD len;
  1124. mutex_lock(&fullpath_mutex);
  1125. len = GetFullPathNameW(&string16[0], 0, nullptr, nullptr);
  1126. if (len != 0) {
  1127. wchar_t *text = gb_alloc_array(permanent_allocator(), wchar_t, len+1);
  1128. GetFullPathNameW(&string16[0], len, text, nullptr);
  1129. mutex_unlock(&fullpath_mutex);
  1130. text[len] = 0;
  1131. result = string16_to_string(a, make_string16(text, len));
  1132. result = string_trim_whitespace(result);
  1133. // Replace Windows style separators
  1134. for (isize i = 0; i < result.len; i++) {
  1135. if (result.text[i] == '\\') {
  1136. result.text[i] = '/';
  1137. }
  1138. }
  1139. if (ok_) *ok_ = true;
  1140. } else {
  1141. if (ok_) *ok_ = false;
  1142. mutex_unlock(&fullpath_mutex);
  1143. }
  1144. return result;
  1145. }
  1146. #elif defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_UNIX)
  1147. struct PathToFullpathResult {
  1148. String result;
  1149. bool ok;
  1150. };
  1151. gb_internal String path_to_fullpath(gbAllocator a, String s, bool *ok_) {
  1152. static gb_thread_local StringMap<PathToFullpathResult> cache;
  1153. PathToFullpathResult *cached = string_map_get(&cache, s);
  1154. if (cached != nullptr) {
  1155. if (ok_) *ok_ = cached->ok;
  1156. return copy_string(a, cached->result);
  1157. }
  1158. char *p;
  1159. p = realpath(cast(char *)s.text, 0);
  1160. defer (free(p));
  1161. if(p == nullptr) {
  1162. if (ok_) *ok_ = false;
  1163. // Path doesn't exist or is malformed, Windows's `GetFullPathNameW` does not check for
  1164. // existence of the file where `realpath` does, which causes different behaviour between platforms.
  1165. // Two things could be done here:
  1166. // 1. clean the path and resolve it manually, just like the Windows function does,
  1167. // probably requires porting `filepath.clean` from Odin and doing some more processing.
  1168. // 2. just return a copy of the original path.
  1169. //
  1170. // I have opted for 2 because it is much simpler + we already return `ok = false` + further
  1171. // checks and processes will use the path and cause errors (which we want).
  1172. String result = copy_string(a, s);
  1173. PathToFullpathResult cached_result = {};
  1174. cached_result.result = copy_string(permanent_allocator(), result);
  1175. cached_result.ok = false;
  1176. string_map_set(&cache, copy_string(permanent_allocator(), s), cached_result);
  1177. return result;
  1178. }
  1179. if (ok_) *ok_ = true;
  1180. String result = copy_string(a, make_string_c(p));
  1181. PathToFullpathResult cached_result = {};
  1182. cached_result.result = copy_string(permanent_allocator(), result);
  1183. cached_result.ok = true;
  1184. string_map_set(&cache, copy_string(permanent_allocator(), s), cached_result);
  1185. return result;
  1186. }
  1187. #else
  1188. #error Implement system
  1189. #endif
  1190. gb_internal String get_fullpath_relative(gbAllocator a, String base_dir, String path, bool *ok_) {
  1191. u8 *str = gb_alloc_array(heap_allocator(), u8, base_dir.len+1+path.len+1);
  1192. defer (gb_free(heap_allocator(), str));
  1193. isize i = 0;
  1194. gb_memmove(str+i, base_dir.text, base_dir.len); i += base_dir.len;
  1195. gb_memmove(str+i, "/", 1); i += 1;
  1196. gb_memmove(str+i, path.text, path.len); i += path.len;
  1197. str[i] = 0;
  1198. // IMPORTANT NOTE(bill): Remove trailing path separators
  1199. // this is required to make sure there is a conventional
  1200. // notation for the path
  1201. for (/**/; i > 0; i--) {
  1202. u8 c = str[i-1];
  1203. if (c != '/' && c != '\\') {
  1204. break;
  1205. }
  1206. }
  1207. String res = make_string(str, i);
  1208. res = string_trim_whitespace(res);
  1209. return path_to_fullpath(a, res, ok_);
  1210. }
  1211. gb_internal String get_fullpath_base_collection(gbAllocator a, String path, bool *ok_) {
  1212. String module_dir = odin_root_dir();
  1213. String base = str_lit("base/");
  1214. isize str_len = module_dir.len + base.len + path.len;
  1215. u8 *str = gb_alloc_array(heap_allocator(), u8, str_len+1);
  1216. defer (gb_free(heap_allocator(), str));
  1217. isize i = 0;
  1218. gb_memmove(str+i, module_dir.text, module_dir.len); i += module_dir.len;
  1219. gb_memmove(str+i, base.text, base.len); i += base.len;
  1220. gb_memmove(str+i, path.text, path.len); i += path.len;
  1221. str[i] = 0;
  1222. String res = make_string(str, i);
  1223. res = string_trim_whitespace(res);
  1224. return path_to_fullpath(a, res, ok_);
  1225. }
  1226. gb_internal String get_fullpath_core_collection(gbAllocator a, String path, bool *ok_) {
  1227. String module_dir = odin_root_dir();
  1228. String core = str_lit("core/");
  1229. isize str_len = module_dir.len + core.len + path.len;
  1230. u8 *str = gb_alloc_array(heap_allocator(), u8, str_len+1);
  1231. defer (gb_free(heap_allocator(), str));
  1232. isize i = 0;
  1233. gb_memmove(str+i, module_dir.text, module_dir.len); i += module_dir.len;
  1234. gb_memmove(str+i, core.text, core.len); i += core.len;
  1235. gb_memmove(str+i, path.text, path.len); i += path.len;
  1236. str[i] = 0;
  1237. String res = make_string(str, i);
  1238. res = string_trim_whitespace(res);
  1239. return path_to_fullpath(a, res, ok_);
  1240. }
  1241. gb_internal bool show_error_line(void) {
  1242. return !build_context.hide_error_line && !build_context.json_errors;
  1243. }
  1244. gb_internal bool terse_errors(void) {
  1245. return build_context.terse_errors;
  1246. }
  1247. gb_internal bool json_errors(void) {
  1248. return build_context.json_errors;
  1249. }
  1250. gb_internal bool has_ansi_terminal_colours(void) {
  1251. return build_context.has_ansi_terminal_colours && !json_errors();
  1252. }
  1253. gb_internal void init_android_values(bool with_sdk) {
  1254. auto *bc = &build_context;
  1255. { // Android SDK/API Level
  1256. String default_level = str_lit("34");
  1257. if (!bc->minimum_os_version_string_given) {
  1258. bc->minimum_os_version_string = default_level;
  1259. }
  1260. BigInt level = {};
  1261. bool success = false;
  1262. big_int_from_string(&level, bc->minimum_os_version_string, &success);
  1263. if (!success) {
  1264. gb_printf_err("Warning: Invalid -minimum-os-version:%.*s for -subtarget:Android, defaulting to %.*s\n", LIT(bc->minimum_os_version_string), LIT(default_level));
  1265. bc->minimum_os_version_string = default_level;
  1266. big_int_from_string(&level, bc->minimum_os_version_string, &success);
  1267. GB_ASSERT(success);
  1268. }
  1269. i64 new_level = big_int_to_i64(&level);
  1270. if (new_level >= 21) {
  1271. bc->ODIN_ANDROID_API_LEVEL = cast(int)new_level;
  1272. } else {
  1273. gb_printf_err("Warning: Invalid -minimum-os-version:%.*s for -subtarget:Android, defaulting to %.*s\n", LIT(bc->minimum_os_version_string), LIT(default_level));
  1274. bc->ODIN_ANDROID_API_LEVEL = atoi(cast(char const *)default_level.text);
  1275. }
  1276. }
  1277. bc->ODIN_ANDROID_NDK = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK", permanent_allocator())), NIX_SEPARATOR_STRING);
  1278. bc->ODIN_ANDROID_NDK_TOOLCHAIN = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK_TOOLCHAIN", permanent_allocator())), NIX_SEPARATOR_STRING);
  1279. bc->ODIN_ANDROID_SDK = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_SDK", permanent_allocator())), NIX_SEPARATOR_STRING);
  1280. #if defined(GB_SYSTEM_WINDOWS)
  1281. if (bc->ODIN_ANDROID_SDK.len == 0) {
  1282. bc->ODIN_ANDROID_SDK = normalize_path(permanent_allocator(),
  1283. path_to_fullpath(permanent_allocator(), str_lit("%LocalAppData%/Android/Sdk"), nullptr),
  1284. NIX_SEPARATOR_STRING);
  1285. }
  1286. #endif
  1287. if (bc->ODIN_ANDROID_NDK.len != 0 && bc->ODIN_ANDROID_NDK_TOOLCHAIN.len == 0) {
  1288. String arch = str_lit("x86_64");
  1289. #if defined (GB_CPU_ARM)
  1290. // TODO(bill): this is a complete guess
  1291. arch = str_lit("aarch64");
  1292. #endif
  1293. #if defined(GB_SYSTEM_WINDOWS)
  1294. bc->ODIN_ANDROID_NDK_TOOLCHAIN = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK, str_lit("toolchains/llvm/prebuilt/"), str_lit("windows-"), arch);
  1295. #elif defined(GB_SYSTEM_OSX)
  1296. // TODO(bill): is this name even correct?
  1297. bc->ODIN_ANDROID_NDK_TOOLCHAIN = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK, str_lit("toolchains/llvm/prebuilt/"), str_lit("darwin-"), arch);
  1298. #elif defined(GB_SYSTEM_LINUX)
  1299. bc->ODIN_ANDROID_NDK_TOOLCHAIN = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK, str_lit("toolchains/llvm/prebuilt/"), str_lit("linux-"), arch);
  1300. #endif
  1301. bc->ODIN_ANDROID_NDK_TOOLCHAIN = normalize_path(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN, NIX_SEPARATOR_STRING);
  1302. }
  1303. if (bc->ODIN_ANDROID_NDK.len == 0 && !with_sdk) {
  1304. gb_printf_err("Error: ODIN_ANDROID_NDK not set");
  1305. gb_exit(1);
  1306. }
  1307. if (bc->ODIN_ANDROID_NDK_TOOLCHAIN.len == 0 && !with_sdk) {
  1308. gb_printf_err("Error: ODIN_ANDROID_NDK not set");
  1309. gb_exit(1);
  1310. }
  1311. bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN, str_lit("sysroot/usr/lib/aarch64-linux-android/"));
  1312. char buf[32] = {};
  1313. gb_snprintf(buf, gb_size_of(buf), "%d/", bc->ODIN_ANDROID_API_LEVEL);
  1314. bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB, make_string_c(buf));
  1315. bc->ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN, str_lit("sysroot/"));
  1316. if (with_sdk) {
  1317. if (bc->ODIN_ANDROID_SDK.len == 0) {
  1318. gb_printf_err("Error: ODIN_ANDROID_SDK not set, which is required for -build-mode:executable for -subtarget:android");
  1319. gb_exit(1);
  1320. }
  1321. if (bc->android_keystore.len == 0) {
  1322. gb_printf_err("Error: -android-keystore:<string> has not been set\n");
  1323. gb_exit(1);
  1324. }
  1325. }
  1326. }
  1327. gb_internal bool has_asm_extension(String const &path) {
  1328. String ext = path_extension(path);
  1329. if (ext == ".asm") {
  1330. return true;
  1331. } else if (ext == ".s") {
  1332. return true;
  1333. } else if (ext == ".S") {
  1334. return true;
  1335. }
  1336. return false;
  1337. }
  1338. // temporary
  1339. gb_internal char *token_pos_to_string(TokenPos const &pos) {
  1340. gbString s = gb_string_make_reserve(temporary_allocator(), 128);
  1341. String file = get_file_path_string(pos.file_id);
  1342. switch (build_context.ODIN_ERROR_POS_STYLE) {
  1343. default: /*fallthrough*/
  1344. case ErrorPosStyle_Default:
  1345. s = gb_string_append_fmt(s, "%.*s(%d:%d)", LIT(file), pos.line, pos.column);
  1346. break;
  1347. case ErrorPosStyle_Unix:
  1348. s = gb_string_append_fmt(s, "%.*s:%d:%d:", LIT(file), pos.line, pos.column);
  1349. break;
  1350. }
  1351. return s;
  1352. }
  1353. gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subtarget) {
  1354. BuildContext *bc = &build_context;
  1355. gb_affinity_init(&bc->affinity);
  1356. if (bc->thread_count == 0) {
  1357. bc->thread_count = gb_max(bc->affinity.thread_count, 1);
  1358. }
  1359. bc->ODIN_VENDOR = str_lit("odin");
  1360. bc->ODIN_VERSION = ODIN_VERSION;
  1361. bc->ODIN_ROOT = odin_root_dir();
  1362. if (bc->max_error_count <= 0) {
  1363. bc->max_error_count = DEFAULT_MAX_ERROR_COLLECTOR_COUNT;
  1364. }
  1365. {
  1366. char const *found = gb_get_env("ODIN_ERROR_POS_STYLE", permanent_allocator());
  1367. if (found) {
  1368. ErrorPosStyle kind = ErrorPosStyle_Default;
  1369. String style = make_string_c(found);
  1370. style = string_trim_whitespace(style);
  1371. if (style == "" || style == "default" || style == "odin") {
  1372. kind = ErrorPosStyle_Default;
  1373. } else if (style == "unix" || style == "gcc" || style == "clang" || style == "llvm") {
  1374. kind = ErrorPosStyle_Unix;
  1375. } else {
  1376. gb_printf_err("Invalid ODIN_ERROR_POS_STYLE: got %.*s\n", LIT(style));
  1377. gb_printf_err("Valid formats:\n");
  1378. gb_printf_err("\t\"default\" or \"odin\"\n");
  1379. gb_printf_err("\t\tpath(line:column) message\n");
  1380. gb_printf_err("\t\"unix\"\n");
  1381. gb_printf_err("\t\tpath:line:column: message\n");
  1382. gb_exit(1);
  1383. }
  1384. build_context.ODIN_ERROR_POS_STYLE = kind;
  1385. }
  1386. }
  1387. bc->copy_file_contents = true;
  1388. TargetMetrics *metrics = nullptr;
  1389. #if defined(GB_ARCH_64_BIT)
  1390. #if defined(GB_SYSTEM_WINDOWS)
  1391. metrics = &target_windows_amd64;
  1392. #elif defined(GB_SYSTEM_OSX)
  1393. #if defined(GB_CPU_ARM)
  1394. metrics = &target_darwin_arm64;
  1395. #else
  1396. metrics = &target_darwin_amd64;
  1397. #endif
  1398. #elif defined(GB_SYSTEM_FREEBSD)
  1399. #if defined(GB_CPU_ARM)
  1400. metrics = &target_freebsd_arm64;
  1401. #else
  1402. metrics = &target_freebsd_amd64;
  1403. #endif
  1404. #elif defined(GB_SYSTEM_OPENBSD)
  1405. metrics = &target_openbsd_amd64;
  1406. #elif defined(GB_SYSTEM_NETBSD)
  1407. #if defined(GB_CPU_ARM)
  1408. metrics = &target_netbsd_arm64;
  1409. #else
  1410. metrics = &target_netbsd_amd64;
  1411. #endif
  1412. #elif defined(GB_SYSTEM_HAIKU)
  1413. metrics = &target_haiku_amd64;
  1414. #elif defined(GB_CPU_ARM)
  1415. metrics = &target_linux_arm64;
  1416. #elif defined(GB_CPU_RISCV)
  1417. metrics = &target_linux_riscv64;
  1418. #else
  1419. metrics = &target_linux_amd64;
  1420. #endif
  1421. #elif defined(GB_CPU_ARM)
  1422. #if defined(GB_SYSTEM_WINDOWS)
  1423. #error "Build Error: Unsupported architecture"
  1424. #elif defined(GB_SYSTEM_OSX)
  1425. #error "Build Error: Unsupported architecture"
  1426. #elif defined(GB_SYSTEM_FREEBSD)
  1427. #error "Build Error: Unsupported architecture"
  1428. #else
  1429. metrics = &target_linux_arm32;
  1430. #endif
  1431. #else
  1432. #if defined(GB_SYSTEM_WINDOWS)
  1433. metrics = &target_windows_i386;
  1434. #elif defined(GB_SYSTEM_OSX)
  1435. #error "Build Error: Unsupported architecture"
  1436. #elif defined(GB_SYSTEM_FREEBSD)
  1437. metrics = &target_freebsd_i386;
  1438. #else
  1439. metrics = &target_linux_i386;
  1440. #endif
  1441. #endif
  1442. if (cross_target != nullptr && metrics != cross_target) {
  1443. bc->different_os = cross_target->os != metrics->os;
  1444. bc->cross_compiling = true;
  1445. metrics = cross_target;
  1446. }
  1447. GB_ASSERT(metrics->os != TargetOs_Invalid);
  1448. GB_ASSERT(metrics->arch != TargetArch_Invalid);
  1449. GB_ASSERT(metrics->ptr_size > 1);
  1450. GB_ASSERT(metrics->int_size > 1);
  1451. GB_ASSERT(metrics->max_align > 1);
  1452. GB_ASSERT(metrics->max_simd_align > 1);
  1453. GB_ASSERT(metrics->int_size >= metrics->ptr_size);
  1454. if (metrics->int_size > metrics->ptr_size) {
  1455. GB_ASSERT(metrics->int_size == 2*metrics->ptr_size);
  1456. }
  1457. bc->metrics = *metrics;
  1458. bc->ODIN_OS = target_os_names[metrics->os];
  1459. bc->ODIN_ARCH = target_arch_names[metrics->arch];
  1460. bc->endian_kind = target_endians[metrics->arch];
  1461. bc->ptr_size = metrics->ptr_size;
  1462. bc->int_size = metrics->int_size;
  1463. bc->max_align = metrics->max_align;
  1464. bc->max_simd_align = metrics->max_simd_align;
  1465. bc->link_flags = str_lit(" ");
  1466. #if defined(DEFAULT_TO_THREADED_CHECKER)
  1467. bc->threaded_checker = true;
  1468. #endif
  1469. if (bc->disable_red_zone) {
  1470. if (is_arch_wasm() && bc->metrics.os == TargetOs_freestanding) {
  1471. gb_printf_err("-disable-red-zone is not support for this target");
  1472. gb_exit(1);
  1473. }
  1474. }
  1475. if (bc->metrics.os == TargetOs_freestanding) {
  1476. bc->no_entry_point = true;
  1477. } else {
  1478. if (bc->no_rtti) {
  1479. gb_printf_err("-no-rtti is only allowed on freestanding targets\n");
  1480. gb_exit(1);
  1481. }
  1482. }
  1483. // Default to subsystem:CONSOLE on Windows targets
  1484. if (bc->ODIN_WINDOWS_SUBSYSTEM == Windows_Subsystem_UNKNOWN && bc->metrics.os == TargetOs_windows) {
  1485. bc->ODIN_WINDOWS_SUBSYSTEM = Windows_Subsystem_CONSOLE;
  1486. }
  1487. if (subtarget == Subtarget_Android) {
  1488. switch (build_context.build_mode) {
  1489. case BuildMode_DynamicLibrary:
  1490. case BuildMode_Object:
  1491. case BuildMode_Assembly:
  1492. case BuildMode_LLVM_IR:
  1493. break;
  1494. default:
  1495. case BuildMode_Executable:
  1496. case BuildMode_StaticLibrary:
  1497. if ((build_context.command_kind & Command__does_build) != 0) {
  1498. gb_printf_err("Unsupported -build-mode for -subtarget:android\n");
  1499. gb_printf_err("\tCurrently only supporting: \n");
  1500. // gb_printf_err("\t\texe\n");
  1501. gb_printf_err("\t\tshared\n");
  1502. gb_printf_err("\t\tobject\n");
  1503. gb_printf_err("\t\tassembly\n");
  1504. gb_printf_err("\t\tllvm-ir\n");
  1505. gb_exit(1);
  1506. }
  1507. break;
  1508. }
  1509. }
  1510. if (metrics->os == TargetOs_darwin) {
  1511. switch (subtarget) {
  1512. case Subtarget_iPhone:
  1513. switch (metrics->arch) {
  1514. case TargetArch_arm64:
  1515. bc->metrics.target_triplet = str_lit("arm64-apple-ios");
  1516. break;
  1517. default:
  1518. GB_PANIC("Unknown architecture for -subtarget:iphone");
  1519. }
  1520. break;
  1521. case Subtarget_iPhoneSimulator:
  1522. switch (metrics->arch) {
  1523. case TargetArch_arm64:
  1524. bc->metrics.target_triplet = str_lit("arm64-apple-ios-simulator");
  1525. break;
  1526. case TargetArch_amd64:
  1527. bc->metrics.target_triplet = str_lit("x86_64-apple-ios-simulator");
  1528. break;
  1529. default:
  1530. GB_PANIC("Unknown architecture for -subtarget:iphonesimulator");
  1531. }
  1532. break;
  1533. }
  1534. } else if (metrics->os == TargetOs_linux && subtarget == Subtarget_Android) {
  1535. switch (metrics->arch) {
  1536. case TargetArch_arm64:
  1537. bc->metrics.target_triplet = str_lit("aarch64-none-linux-android");
  1538. bc->reloc_mode = RelocMode_PIC;
  1539. break;
  1540. default:
  1541. GB_PANIC("Unknown architecture for -subtarget:android");
  1542. }
  1543. }
  1544. if (bc->metrics.os == TargetOs_windows) {
  1545. switch (bc->metrics.arch) {
  1546. case TargetArch_amd64:
  1547. bc->link_flags = str_lit("/machine:x64 ");
  1548. break;
  1549. case TargetArch_i386:
  1550. bc->link_flags = str_lit("/machine:x86 ");
  1551. break;
  1552. }
  1553. } else if (bc->metrics.os == TargetOs_darwin) {
  1554. bc->link_flags = concatenate3_strings(permanent_allocator(),
  1555. str_lit("-target "), bc->metrics.target_triplet, str_lit(" "));
  1556. } else if (is_arch_wasm()) {
  1557. gbString link_flags = gb_string_make(heap_allocator(), " ");
  1558. // NOTE(laytan): Put the stack first in the memory,
  1559. // causing a stack overflow to error immediately instead of corrupting globals.
  1560. link_flags = gb_string_appendc(link_flags, "--stack-first ");
  1561. // NOTE(laytan): default stack size is 64KiB, up to a more reasonable 1MiB.
  1562. link_flags = gb_string_appendc(link_flags, "-z stack-size=1048576 ");
  1563. // link_flags = gb_string_appendc(link_flags, "--export-all ");
  1564. // link_flags = gb_string_appendc(link_flags, "--export-table ");
  1565. // if (bc->metrics.arch == TargetArch_wasm64) {
  1566. // link_flags = gb_string_appendc(link_flags, "-mwasm64 ");
  1567. // }
  1568. if (bc->metrics.os != TargetOs_orca) {
  1569. link_flags = gb_string_appendc(link_flags, "--allow-undefined ");
  1570. }
  1571. if (bc->no_entry_point || bc->metrics.os == TargetOs_orca) {
  1572. link_flags = gb_string_appendc(link_flags, "--no-entry ");
  1573. }
  1574. bc->link_flags = make_string_c(link_flags);
  1575. // Disallow on wasm
  1576. bc->use_separate_modules = false;
  1577. } if(bc->metrics.arch == TargetArch_riscv64 && bc->cross_compiling) {
  1578. bc->link_flags = str_lit("-target riscv64 ");
  1579. } else {
  1580. // NOTE: for targets other than darwin, we don't specify a `-target` link flag.
  1581. // This is because we don't support cross-linking and clang is better at figuring
  1582. // out what the actual target for linking is,
  1583. // for example, on x86/alpine/musl it HAS to be `x86_64-alpine-linux-musl` to link correctly.
  1584. //
  1585. // Note that codegen will still target the triplet we specify, but the intricate details of
  1586. // a target shouldn't matter as much to codegen (if it does at all) as it does to linking.
  1587. }
  1588. // NOTE: needs to be done after adding the -target flag to the linker flags so the linker
  1589. // does not annoy the user with version warnings.
  1590. if (metrics->os == TargetOs_darwin) {
  1591. if (!bc->minimum_os_version_string_given) {
  1592. if (subtarget == Subtarget_Default) {
  1593. bc->minimum_os_version_string = str_lit("11.0.0");
  1594. } else if (subtarget == Subtarget_iPhone || subtarget == Subtarget_iPhoneSimulator) {
  1595. // NOTE(harold): We default to 17.4 on iOS because that's when os_sync_wait_on_address was added and
  1596. // we'd like to avoid any potential App Store issues by using the private ulock_* there.
  1597. bc->minimum_os_version_string = str_lit("17.4");
  1598. }
  1599. }
  1600. if (subtarget == Subtarget_iPhoneSimulator) {
  1601. // For the iPhoneSimulator subtarget, the version must be between 'ios' and '-simulator'.
  1602. String suffix = str_lit("-simulator");
  1603. GB_ASSERT(string_ends_with(bc->metrics.target_triplet, suffix));
  1604. String prefix = substring(bc->metrics.target_triplet, 0, bc->metrics.target_triplet.len - suffix.len);
  1605. bc->metrics.target_triplet = concatenate3_strings(permanent_allocator(), prefix, bc->minimum_os_version_string, suffix);
  1606. } else {
  1607. bc->metrics.target_triplet = concatenate_strings(permanent_allocator(), bc->metrics.target_triplet, bc->minimum_os_version_string);
  1608. }
  1609. } else if (selected_subtarget == Subtarget_Android) {
  1610. init_android_values(bc->build_mode == BuildMode_Executable && (bc->command_kind & Command__does_build) != 0);
  1611. }
  1612. if (!bc->custom_optimization_level) {
  1613. // NOTE(bill): when building with `-debug` but not specifying an optimization level
  1614. // default to `-o:none` to improve the debug symbol generation by default
  1615. if (bc->ODIN_DEBUG) {
  1616. bc->optimization_level = -1; // -o:none
  1617. } else {
  1618. bc->optimization_level = 0; // -o:minimal
  1619. }
  1620. }
  1621. bc->optimization_level = gb_clamp(bc->optimization_level, -1, 3);
  1622. if (bc->optimization_level <= 0) {
  1623. if (!is_arch_wasm()) {
  1624. bc->use_separate_modules = true;
  1625. }
  1626. }
  1627. if (build_context.use_single_module) {
  1628. bc->use_separate_modules = false;
  1629. }
  1630. bc->ODIN_VALGRIND_SUPPORT = false;
  1631. if (build_context.metrics.os != TargetOs_windows) {
  1632. switch (bc->metrics.arch) {
  1633. case TargetArch_amd64:
  1634. bc->ODIN_VALGRIND_SUPPORT = true;
  1635. break;
  1636. }
  1637. }
  1638. if (bc->metrics.os == TargetOs_freestanding) {
  1639. bc->ODIN_DEFAULT_TO_NIL_ALLOCATOR = !bc->ODIN_DEFAULT_TO_PANIC_ALLOCATOR;
  1640. }
  1641. }
  1642. #if defined(GB_SYSTEM_WINDOWS)
  1643. // NOTE(IC): In order to find Visual C++ paths without relying on environment variables.
  1644. // NOTE(Jeroen): No longer needed in `main.cpp -> linker_stage`. We now resolve those paths in `init_build_paths`.
  1645. #include "microsoft_craziness.h"
  1646. #endif
  1647. // NOTE: the target feature and microarch lists are all sorted, so if it turns out to be slow (I don't think it will)
  1648. // a binary search is possible.
  1649. gb_internal bool check_single_target_feature_is_valid(String const &feature_list, String const &feature) {
  1650. String_Iterator it = {feature_list, 0};
  1651. for (;;) {
  1652. String str = string_split_iterator(&it, ',');
  1653. if (str == "") break;
  1654. if (str == feature) {
  1655. return true;
  1656. }
  1657. }
  1658. return false;
  1659. }
  1660. gb_internal bool check_target_feature_is_valid(String const &feature, TargetArchKind arch, String *invalid) {
  1661. String feature_list = target_features_list[arch];
  1662. String_Iterator it = {feature, 0};
  1663. for (;;) {
  1664. String str = string_split_iterator(&it, ',');
  1665. if (str == "") break;
  1666. if (!check_single_target_feature_is_valid(feature_list, str)) {
  1667. if (invalid) *invalid = str;
  1668. return false;
  1669. }
  1670. }
  1671. return true;
  1672. }
  1673. gb_internal bool check_target_feature_is_valid_globally(String const &feature, String *invalid) {
  1674. String_Iterator it = {feature, 0};
  1675. for (;;) {
  1676. String str = string_split_iterator(&it, ',');
  1677. if (str == "") break;
  1678. bool valid = false;
  1679. for (int arch = TargetArch_Invalid; arch < TargetArch_COUNT; arch += 1) {
  1680. if (check_target_feature_is_valid(str, cast(TargetArchKind)arch, invalid)) {
  1681. valid = true;
  1682. break;
  1683. }
  1684. }
  1685. if (!valid) {
  1686. if (invalid) *invalid = str;
  1687. return false;
  1688. }
  1689. }
  1690. return true;
  1691. }
  1692. gb_internal bool check_target_feature_is_valid_for_target_arch(String const &feature, String *invalid) {
  1693. return check_target_feature_is_valid(feature, build_context.metrics.arch, invalid);
  1694. }
  1695. gb_internal bool check_target_feature_is_enabled(String const &feature, String *not_enabled) {
  1696. String_Iterator it = {feature, 0};
  1697. for (;;) {
  1698. String str = string_split_iterator(&it, ',');
  1699. if (str == "") break;
  1700. if (!string_set_exists(&build_context.target_features_set, str)) {
  1701. if (not_enabled) *not_enabled = str;
  1702. return false;
  1703. }
  1704. }
  1705. return true;
  1706. }
  1707. gb_internal bool check_target_feature_is_superset_of(String const &superset, String const &of, String *missing) {
  1708. String_Iterator it = {of, 0};
  1709. for (;;) {
  1710. String str = string_split_iterator(&it, ',');
  1711. if (str == "") break;
  1712. if (!check_single_target_feature_is_valid(superset, str)) {
  1713. if (missing) *missing = str;
  1714. return false;
  1715. }
  1716. }
  1717. return true;
  1718. }
  1719. gb_internal String infer_object_extension_from_build_context() {
  1720. String output_extension = {};
  1721. if (is_arch_wasm()) {
  1722. output_extension = STR_LIT("wasm.o");
  1723. } else {
  1724. switch (build_context.metrics.os) {
  1725. case TargetOs_windows:
  1726. output_extension = STR_LIT("obj");
  1727. break;
  1728. default:
  1729. case TargetOs_darwin:
  1730. case TargetOs_linux:
  1731. case TargetOs_essence:
  1732. output_extension = STR_LIT("o");
  1733. break;
  1734. case TargetOs_freestanding:
  1735. switch (build_context.metrics.abi) {
  1736. default:
  1737. case TargetABI_Default:
  1738. case TargetABI_SysV:
  1739. output_extension = STR_LIT("o");
  1740. break;
  1741. case TargetABI_Win64:
  1742. output_extension = STR_LIT("obj");
  1743. break;
  1744. }
  1745. break;
  1746. }
  1747. }
  1748. return output_extension;
  1749. }
  1750. // NOTE(Jeroen): Set/create the output and other paths and report an error as appropriate.
  1751. // We've previously called `parse_build_flags`, so `out_filepath` should be set.
  1752. gb_internal bool init_build_paths(String init_filename) {
  1753. gbAllocator ha = heap_allocator();
  1754. BuildContext *bc = &build_context;
  1755. // NOTE(Jeroen): We're pre-allocating BuildPathCOUNT slots so that certain paths are always at the same enumerated index.
  1756. array_init(&bc->build_paths, permanent_allocator(), BuildPathCOUNT);
  1757. string_set_init(&bc->target_features_set, 1024);
  1758. // [BuildPathMainPackage] Turn given init path into a `Path`, which includes normalizing it into a full path.
  1759. bc->build_paths[BuildPath_Main_Package] = path_from_string(ha, init_filename);
  1760. {
  1761. String build_project_name = last_path_element(bc->build_paths[BuildPath_Main_Package].basename);
  1762. GB_ASSERT(build_project_name.len > 0);
  1763. bc->ODIN_BUILD_PROJECT_NAME = build_project_name;
  1764. }
  1765. bool produces_output_file = false;
  1766. if (bc->command_kind == Command_doc && bc->cmd_doc_flags & CmdDocFlag_DocFormat) {
  1767. produces_output_file = true;
  1768. } else if (bc->command_kind & Command__does_build) {
  1769. produces_output_file = true;
  1770. }
  1771. if (!produces_output_file) {
  1772. // Command doesn't produce output files. We're done.
  1773. return true;
  1774. }
  1775. #if defined(GB_SYSTEM_WINDOWS)
  1776. if (bc->metrics.os == TargetOs_windows) {
  1777. if (bc->resource_filepath.len > 0) {
  1778. bc->build_paths[BuildPath_RES] = path_from_string(ha, bc->resource_filepath);
  1779. if (!string_ends_with(bc->resource_filepath, str_lit(".res"))) {
  1780. bc->build_paths[BuildPath_RES].ext = copy_string(ha, STR_LIT("res"));
  1781. bc->build_paths[BuildPath_RC] = path_from_string(ha, bc->resource_filepath);
  1782. bc->build_paths[BuildPath_RC].ext = copy_string(ha, STR_LIT("rc"));
  1783. }
  1784. }
  1785. if ((bc->command_kind & Command__does_build) && (!bc->ignore_microsoft_magic)) {
  1786. // NOTE(ic): It would be nice to extend this so that we could specify the Visual Studio version that we want instead of defaulting to the latest.
  1787. Find_Result find_result = find_visual_studio_and_windows_sdk();
  1788. if (find_result.windows_sdk_version == 0) {
  1789. gb_printf_err("Windows SDK not found.\n");
  1790. return false;
  1791. }
  1792. if (build_context.linker_choice == Linker_Default && find_result.vs_exe_path.len == 0) {
  1793. gb_printf_err("link.exe not found.\n");
  1794. return false;
  1795. }
  1796. if (find_result.vs_library_path.len == 0) {
  1797. gb_printf_err("VS library path not found.\n");
  1798. return false;
  1799. }
  1800. if (find_result.windows_sdk_um_library_path.len > 0) {
  1801. GB_ASSERT(find_result.windows_sdk_ucrt_library_path.len > 0);
  1802. if (find_result.windows_sdk_bin_path.len > 0) {
  1803. bc->build_paths[BuildPath_Win_SDK_Bin_Path] = path_from_string(ha, find_result.windows_sdk_bin_path);
  1804. }
  1805. if (find_result.windows_sdk_um_library_path.len > 0) {
  1806. bc->build_paths[BuildPath_Win_SDK_UM_Lib] = path_from_string(ha, find_result.windows_sdk_um_library_path);
  1807. }
  1808. if (find_result.windows_sdk_ucrt_library_path.len > 0) {
  1809. bc->build_paths[BuildPath_Win_SDK_UCRT_Lib] = path_from_string(ha, find_result.windows_sdk_ucrt_library_path);
  1810. }
  1811. if (find_result.vs_exe_path.len > 0) {
  1812. bc->build_paths[BuildPath_VS_EXE] = path_from_string(ha, find_result.vs_exe_path);
  1813. }
  1814. if (find_result.vs_library_path.len > 0) {
  1815. bc->build_paths[BuildPath_VS_LIB] = path_from_string(ha, find_result.vs_library_path);
  1816. }
  1817. }
  1818. }
  1819. }
  1820. #endif
  1821. // All the build targets and OSes.
  1822. String output_extension;
  1823. if (bc->command_kind == Command_doc && bc->cmd_doc_flags & CmdDocFlag_DocFormat) {
  1824. output_extension = STR_LIT("odin-doc");
  1825. } else if (is_arch_wasm()) {
  1826. output_extension = STR_LIT("wasm");
  1827. } else if (build_context.build_mode == BuildMode_Executable) {
  1828. // By default use no executable extension.
  1829. output_extension = make_string(nullptr, 0);
  1830. String const single_file_extension = str_lit(".odin");
  1831. if (selected_subtarget == Subtarget_Android) {
  1832. // NOTE(bill): It's always shared!
  1833. output_extension = STR_LIT("so");
  1834. } else if (build_context.metrics.os == TargetOs_windows) {
  1835. output_extension = STR_LIT("exe");
  1836. } else if (build_context.cross_compiling && selected_target_metrics->metrics == &target_essence_amd64) {
  1837. // Do nothing: we don't want the .bin extension
  1838. // when cross compiling
  1839. } else if (path_is_directory(last_path_element(bc->build_paths[BuildPath_Main_Package].basename))) {
  1840. // Add .bin extension to avoid collision
  1841. // with package directory name
  1842. output_extension = STR_LIT("bin");
  1843. } else if (string_ends_with(init_filename, single_file_extension) && path_is_directory(remove_extension_from_path(init_filename))) {
  1844. // Add bin extension if compiling single-file package
  1845. // with same output name as a directory
  1846. output_extension = STR_LIT("bin");
  1847. }
  1848. } else if (build_context.build_mode == BuildMode_DynamicLibrary) {
  1849. // By default use a .so shared library extension.
  1850. output_extension = STR_LIT("so");
  1851. if (build_context.metrics.os == TargetOs_windows) {
  1852. output_extension = STR_LIT("dll");
  1853. } else if (build_context.metrics.os == TargetOs_darwin) {
  1854. output_extension = STR_LIT("dylib");
  1855. }
  1856. } else if (build_context.build_mode == BuildMode_StaticLibrary) {
  1857. output_extension = STR_LIT("a");
  1858. if (build_context.metrics.os == TargetOs_windows) {
  1859. output_extension = STR_LIT("lib");
  1860. }
  1861. } else if (build_context.build_mode == BuildMode_Object) {
  1862. output_extension = infer_object_extension_from_build_context();
  1863. } else if (build_context.build_mode == BuildMode_Assembly) {
  1864. // By default use a .S asm extension.
  1865. output_extension = STR_LIT("S");
  1866. } else if (build_context.build_mode == BuildMode_LLVM_IR) {
  1867. output_extension = STR_LIT("ll");
  1868. } else {
  1869. GB_PANIC("Unhandled build mode/target combination.\n");
  1870. }
  1871. if (bc->out_filepath.len > 0) {
  1872. bc->build_paths[BuildPath_Output] = path_from_string(ha, bc->out_filepath);
  1873. if (build_context.metrics.os == TargetOs_windows) {
  1874. String output_file = path_to_string(ha, bc->build_paths[BuildPath_Output]);
  1875. defer (gb_free(ha, output_file.text));
  1876. if (path_is_directory(bc->build_paths[BuildPath_Output])) {
  1877. gb_printf_err("Output path %.*s is a directory.\n", LIT(output_file));
  1878. return false;
  1879. } else if (bc->build_paths[BuildPath_Output].ext.len == 0) {
  1880. gb_printf_err("Output path %.*s must have an appropriate extension.\n", LIT(output_file));
  1881. return false;
  1882. }
  1883. }
  1884. } else {
  1885. Path output_path;
  1886. if (str_eq(init_filename, str_lit("."))) {
  1887. // We must name the output file after the current directory.
  1888. debugf("Output name will be created from current base name %.*s.\n", LIT(bc->build_paths[BuildPath_Main_Package].basename));
  1889. String last_element = last_path_element(bc->build_paths[BuildPath_Main_Package].basename);
  1890. if (last_element.len == 0) {
  1891. gb_printf_err("The output name is created from the last path element. `%.*s` has none. Use `-out:output_name.ext` to set it.\n", LIT(bc->build_paths[BuildPath_Main_Package].basename));
  1892. return false;
  1893. }
  1894. output_path.basename = copy_string(ha, bc->build_paths[BuildPath_Main_Package].basename);
  1895. output_path.name = copy_string(ha, last_element);
  1896. } else {
  1897. // Init filename was not 'current path'.
  1898. // Contruct the output name from the path elements as usual.
  1899. String output_name = init_filename;
  1900. // If it ends with a trailing (back)slash, strip it before continuing.
  1901. while (output_name.len > 0 && (output_name[output_name.len-1] == '/' || output_name[output_name.len-1] == '\\')) {
  1902. output_name.len -= 1;
  1903. }
  1904. // Only trim the extension if it's an Odin source file.
  1905. // This lets people build folders with extensions or files beginning with dots.
  1906. if (path_extension(output_name) == ".odin" && !path_is_directory(output_name)) {
  1907. output_name = remove_extension_from_path(output_name);
  1908. }
  1909. output_name = remove_directory_from_path(output_name);
  1910. output_name = copy_string(ha, string_trim_whitespace(output_name));
  1911. // This is `path_from_string` without the extension trimming.
  1912. Path res = {};
  1913. if (output_name.len > 0) {
  1914. String fullpath = path_to_full_path(ha, output_name);
  1915. defer (gb_free(ha, fullpath.text));
  1916. res.basename = directory_from_path(fullpath);
  1917. res.basename = copy_string(ha, res.basename);
  1918. if (path_is_directory(fullpath)) {
  1919. if (res.basename.len > 0 && res.basename.text[res.basename.len - 1] == '/') {
  1920. res.basename.len--;
  1921. }
  1922. } else {
  1923. isize name_start = (res.basename.len > 0) ? res.basename.len + 1 : res.basename.len;
  1924. res.name = substring(fullpath, name_start, fullpath.len);
  1925. res.name = copy_string(ha, res.name);
  1926. }
  1927. }
  1928. output_path = res;
  1929. // Note(Dragos): This is a fix for empty filenames
  1930. // Turn the trailing folder into the file name
  1931. if (output_path.name.len == 0) {
  1932. isize len = output_path.basename.len;
  1933. while (len > 1 && output_path.basename[len - 1] != '/') {
  1934. len -= 1;
  1935. }
  1936. // We reached the slash
  1937. String old_basename = output_path.basename;
  1938. output_path.basename.len = len - 1; // Remove the slash
  1939. output_path.name = substring(old_basename, len, old_basename.len);
  1940. output_path.basename = copy_string(ha, output_path.basename);
  1941. output_path.name = copy_string(ha, output_path.name);
  1942. // The old basename is wrong. Delete it
  1943. gb_free(ha, old_basename.text);
  1944. }
  1945. // Replace extension.
  1946. if (output_path.ext.len > 0) {
  1947. gb_free(ha, output_path.ext.text);
  1948. }
  1949. }
  1950. output_path.ext = copy_string(ha, output_extension);
  1951. bc->build_paths[BuildPath_Output] = output_path;
  1952. }
  1953. if (build_context.ODIN_DEBUG) {
  1954. if (build_context.metrics.os == TargetOs_windows) {
  1955. if (bc->pdb_filepath.len > 0) {
  1956. bc->build_paths[BuildPath_Symbols] = path_from_string(ha, bc->pdb_filepath);
  1957. } else {
  1958. Path symbol_path;
  1959. symbol_path.basename = copy_string(ha, bc->build_paths[BuildPath_Output].basename);
  1960. symbol_path.name = copy_string(ha, bc->build_paths[BuildPath_Output].name);
  1961. symbol_path.ext = copy_string(ha, STR_LIT("pdb"));
  1962. bc->build_paths[BuildPath_Symbols] = symbol_path;
  1963. }
  1964. } else if (build_context.metrics.os == TargetOs_darwin) {
  1965. Path symbol_path;
  1966. symbol_path.basename = copy_string(ha, bc->build_paths[BuildPath_Output].basename);
  1967. symbol_path.name = copy_string(ha, bc->build_paths[BuildPath_Output].name);
  1968. symbol_path.ext = copy_string(ha, STR_LIT("dSYM"));
  1969. bc->build_paths[BuildPath_Symbols] = symbol_path;
  1970. }
  1971. }
  1972. // Do we have an extension? We might not if the output filename was supplied.
  1973. if (bc->build_paths[BuildPath_Output].ext.len == 0) {
  1974. if (build_context.metrics.os == TargetOs_windows || is_arch_wasm() || build_context.build_mode != BuildMode_Executable) {
  1975. bc->build_paths[BuildPath_Output].ext = copy_string(ha, output_extension);
  1976. }
  1977. }
  1978. String output_file = path_to_string(ha, bc->build_paths[BuildPath_Output]);
  1979. defer (gb_free(ha, output_file.text));
  1980. // Check if output path is a directory.
  1981. if (path_is_directory(bc->build_paths[BuildPath_Output])) {
  1982. gb_printf_err("Output path %.*s is a directory.\n", LIT(output_file));
  1983. return false;
  1984. }
  1985. // gbFile output_file_test;
  1986. // const char* output_file_name = (const char*)output_file.text;
  1987. // gbFileError output_test_err = gb_file_open_mode(&output_file_test, gbFileMode_Append | gbFileMode_Rw, output_file_name);
  1988. // if (output_test_err == 0) {
  1989. // gb_file_close(&output_file_test);
  1990. // gb_file_remove(output_file_name);
  1991. // } else {
  1992. // String output_file = path_to_string(ha, bc->build_paths[BuildPath_Output]);
  1993. // defer (gb_free(ha, output_file.text));
  1994. // gb_printf_err("No write permissions for output path: %.*s\n", LIT(output_file));
  1995. // return false;
  1996. // }
  1997. if (build_context.sanitizer_flags & SanitizerFlag_Address) {
  1998. switch (build_context.metrics.os) {
  1999. case TargetOs_windows:
  2000. case TargetOs_linux:
  2001. case TargetOs_darwin:
  2002. case TargetOs_freebsd:
  2003. break;
  2004. default:
  2005. gb_printf_err("-sanitize:address is only supported on Windows, Linux, Darwin, and FreeBSD\n");
  2006. return false;
  2007. }
  2008. }
  2009. if (build_context.sanitizer_flags & SanitizerFlag_Memory) {
  2010. switch (build_context.metrics.os) {
  2011. case TargetOs_linux:
  2012. case TargetOs_freebsd:
  2013. break;
  2014. default:
  2015. gb_printf_err("-sanitize:memory is only supported on Linux and FreeBSD\n");
  2016. return false;
  2017. }
  2018. }
  2019. if (build_context.sanitizer_flags & SanitizerFlag_Thread) {
  2020. switch (build_context.metrics.os) {
  2021. case TargetOs_linux:
  2022. case TargetOs_darwin:
  2023. case TargetOs_freebsd:
  2024. break;
  2025. default:
  2026. gb_printf_err("-sanitize:thread is only supported on Linux, Darwin, and FreeBSD\n");
  2027. return false;
  2028. }
  2029. }
  2030. bool no_crt_checks_failed = false;
  2031. if (build_context.no_crt && !build_context.ODIN_DEFAULT_TO_NIL_ALLOCATOR && !build_context.ODIN_DEFAULT_TO_PANIC_ALLOCATOR) {
  2032. switch (build_context.metrics.os) {
  2033. case TargetOs_linux:
  2034. case TargetOs_darwin:
  2035. case TargetOs_essence:
  2036. case TargetOs_freebsd:
  2037. case TargetOs_openbsd:
  2038. case TargetOs_netbsd:
  2039. case TargetOs_haiku:
  2040. gb_printf_err("-no-crt on Unix systems requires either -default-to-nil-allocator or -default-to-panic-allocator to also be present, because the default allocator requires CRT\n");
  2041. no_crt_checks_failed = true;
  2042. }
  2043. }
  2044. if (build_context.no_crt && !build_context.no_thread_local) {
  2045. switch (build_context.metrics.os) {
  2046. case TargetOs_linux:
  2047. case TargetOs_darwin:
  2048. case TargetOs_essence:
  2049. case TargetOs_freebsd:
  2050. case TargetOs_openbsd:
  2051. case TargetOs_netbsd:
  2052. case TargetOs_haiku:
  2053. gb_printf_err("-no-crt on Unix systems requires the -no-thread-local flag to also be present, because the TLS is inaccessible without CRT\n");
  2054. no_crt_checks_failed = true;
  2055. }
  2056. }
  2057. if (no_crt_checks_failed) {
  2058. return false;
  2059. }
  2060. return true;
  2061. }