bmk_make.bmx 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873
  1. SuperStrict
  2. Import "bmk_modutil.bmx"
  3. Global cc_opts$
  4. Global bcc_opts$
  5. Global cpp_opts$
  6. Global c_opts$
  7. Function BeginMake()
  8. cc_opts=Null
  9. cpp_opts=Null
  10. c_opts=Null
  11. bcc_opts=Null
  12. app_main=Null
  13. opt_framework=""
  14. End Function
  15. Function ConfigureAndroidPaths()
  16. CheckAndroidPaths()
  17. Local toolchain:String
  18. Local toolchainBin:String
  19. Local arch:String
  20. Local abi:String
  21. Select processor.CPU()
  22. Case "x86"
  23. toolchain = "x86-"
  24. toolchainBin = "i686-linux-android-"
  25. arch = "arch-x86"
  26. abi = "x86"
  27. Case "x64"
  28. toolchain = "x86_64-"
  29. toolchainBin = "x86_64-linux-android-"
  30. arch = "arch-x86_64"
  31. abi = "x86_64"
  32. Case "arm", "armeabi", "armeabiv7a"
  33. toolchain = "arm-linux-androideabi-"
  34. toolchainBin = "arm-linux-androideabi-"
  35. arch = "arch-arm"
  36. If processor.CPU() = "armeabi" Then
  37. abi = "armeabi"
  38. Else
  39. abi = "armeabi-v7a"
  40. End If
  41. Case "arm64v8a"
  42. toolchain = "aarch64-linux-android-"
  43. toolchainBin = "aarch64-linux-android-"
  44. arch = "arch-arm64"
  45. abi = "arm64-v8a"
  46. End Select
  47. Local native:String
  48. ?macos
  49. native = "darwin"
  50. ?linux
  51. native = "linux"
  52. ?win32
  53. native = "windows"
  54. ?
  55. Local toolchainDir:String = processor.Option("android.ndk", "") + "/toolchains/" + ..
  56. toolchain + processor.Option("android.toolchain.version", "") + "/prebuilt/" + native
  57. ' look for 64 bit build first, then x86, then fallback to no architecture (generally on 32-bit dists)
  58. If FileType(toolchainDir + "-x86_64") = FILETYPE_DIR Then
  59. toolchainDir :+ "-x86_64"
  60. Else If FileType(toolchainDir + "-x86") = FILETYPE_DIR Then
  61. toolchainDir :+ "-x86"
  62. Else If FileType(toolchainDir) <> FILETYPE_DIR Then
  63. Throw "Cannot determine toolchain dir for '" + native + "', at '" + toolchainDir + "'"
  64. End If
  65. Local exe:String
  66. ?win32
  67. exe = ".exe"
  68. ?
  69. Local gccPath:String = toolchainDir + "/bin/" + toolchainBin + "gcc" + exe
  70. Local gppPath:String = toolchainDir + "/bin/" + toolchainBin + "g++" + exe
  71. Local arPath:String = toolchainDir + "/bin/" + toolchainBin + "ar" + exe
  72. Local libPath:String = toolchainDir + "/lib"
  73. ' check paths
  74. If Not FileType(RealPath(gccPath)) Then
  75. Throw "gcc not found at '" + gccPath + "'"
  76. End If
  77. If Not FileType(RealPath(gppPath)) Then
  78. Throw "g++ not found at '" + gppPath + "'"
  79. End If
  80. If Not FileType(RealPath(gccPath)) Then
  81. Throw "ar not found at '" + arPath + "'"
  82. End If
  83. globals.SetVar("android." + processor.CPU() + ".gcc", gccPath)
  84. globals.SetVar("android." + processor.CPU() + ".gpp", gppPath)
  85. globals.SetVar("android." + processor.CPU() + ".ar", arPath)
  86. globals.SetVar("android." + processor.CPU() + ".lib", "-L" + libPath)
  87. ' platform
  88. Local platformDir:String = processor.Option("android.ndk", "") + "/platforms/android-" + ..
  89. processor.Option("android.platform", "") + "/" + arch
  90. If Not FileType(platformDir) Then
  91. Throw "Cannot determine platform dir for '" + arch + "' at '" + platformDir + "'"
  92. End If
  93. ' platform sysroot
  94. globals.SetVar("android.platform.sysroot", "--sysroot " + platformDir)
  95. globals.AddOption("cc_opts", "android.platform.sysroot", "--sysroot " + platformDir)
  96. ' abi
  97. globals.SetVar("android.abi", abi)
  98. ' sdk target
  99. Local target:String = GetAndroidSDKTarget()
  100. If Not target Or Not FileType(processor.Option("android.sdk", "") + "/platforms/android-" + target) Then
  101. Local sdkPath:String = processor.Option("android.sdk.target", "")
  102. If sdkPath Then
  103. Throw "Cannot determine SDK target for '" + sdkPath + "'"
  104. Else
  105. Throw "Cannot determine SDK target dir. ANDROID_SDK_TARGET or android.sdk.target option is not set, and auto-lookup failed."
  106. End If
  107. End If
  108. globals.SetVar("android.sdk.target", target)
  109. End Function
  110. Function CheckAndroidPaths()
  111. ' check envs and paths
  112. Local androidHome:String = processor.Option("android.home", getenv_("ANDROID_HOME")).Trim()
  113. If Not androidHome Then
  114. Throw "ANDROID_HOME or 'android.home' config option not set"
  115. End If
  116. putenv_("ANDROID_HOME=" + androidHome)
  117. globals.SetVar("android.home", androidHome)
  118. Local androidSDK:String = processor.Option("android.sdk", getenv_("ANDROID_SDK")).Trim()
  119. If Not androidSDK Then
  120. Throw "ANDROID_SDK or 'android.sdk' config option not set"
  121. End If
  122. putenv_("ANDROID_SDK=" + androidSDK)
  123. globals.SetVar("android.sdk", androidSDK)
  124. Local androidNDK:String = processor.Option("android.ndk", getenv_("ANDROID_NDK")).Trim()
  125. If Not androidNDK Then
  126. Throw "ANDROID_NDK or 'android.ndk' config option not set"
  127. End If
  128. putenv_("ANDROID_NDK=" + androidNDK)
  129. globals.SetVar("android.ndk", androidNDK)
  130. Local androidToolchainVersion:String = processor.Option("android.toolchain.version", getenv_("ANDROID_TOOLCHAIN_VERSION")).Trim()
  131. If Not androidToolchainVersion Then
  132. Throw "ANDROID_TOOLCHAIN_VERSION or 'android.toolchain.version' config option not set"
  133. End If
  134. putenv_("ANDROID_TOOLCHAIN_VERSION=" + androidToolchainVersion)
  135. globals.SetVar("android.toolchain.version", androidToolchainVersion)
  136. Local androidPlatform:String = processor.Option("android.platform", getenv_("ANDROID_PLATFORM")).Trim()
  137. If Not androidPlatform Then
  138. Throw "ANDROID_PLATFORM or 'android.platform' config option not set"
  139. End If
  140. putenv_("ANDROID_PLATFORM=" + androidPlatform.Trim())
  141. globals.SetVar("android.platform", androidPlatform)
  142. Local androidSDKTarget:String = processor.Option("android.sdk.target", getenv_("ANDROID_SDK_TARGET")).Trim()
  143. ' NOTE : if not set, we'll try to determine the actual target later, and fail if required then.
  144. If androidSDKTarget Then
  145. putenv_("ANDROID_SDK_TARGET=" + androidSDKTarget)
  146. globals.SetVar("android.sdk.target", androidSDKTarget)
  147. End If
  148. Local antHome:String = processor.Option("ant.home", getenv_("ANT_HOME")).Trim()
  149. If Not antHome Then
  150. ' as a further fallback, we can use the one from resources folder if it exists.
  151. Local antDir:String = RealPath(BlitzMaxPath() + "/resources/android/apache-ant")
  152. If FileType(antDir) <> FILETYPE_DIR Then
  153. Throw "ANT_HOME or 'ant.home' config option not set, and resources missing apache-ant."
  154. Else
  155. antHome = antDir
  156. globals.SetVar("ant.home", antHome)
  157. End If
  158. End If
  159. putenv_("ANT_HOME=" + antHome)
  160. globals.SetVar("ant.home", antHome)
  161. ?Not win32
  162. Local pathSeparator:String = ":"
  163. Local dirSeparator:String = "/"
  164. ?win32
  165. Local pathSeparator:String = ";"
  166. Local dirSeparator:String = "\"
  167. ?
  168. Local path:String = getenv_("PATH")
  169. path = androidSDK + dirSeparator + "platform-tools" + pathSeparator + path
  170. path = androidSDK + dirSeparator + "tools" + pathSeparator + path
  171. path = androidNDK + pathSeparator + path
  172. path = antHome + dirSeparator + "bin" + pathSeparator + path
  173. putenv_("PATH=" + path)
  174. End Function
  175. Function ConfigureIOSPaths()
  176. Select processor.CPU()
  177. Case "x86", "x64"
  178. Local path:String = "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk"
  179. globals.SetVar("ios.sysroot", path)
  180. globals.SetVar("ios.syslibroot", path)
  181. Case "armv7", "arm64"
  182. Local path:String = "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk"
  183. globals.SetVar("ios.sysroot", path)
  184. globals.SetVar("ios.syslibroot", path)
  185. End Select
  186. End Function
  187. Function ConfigureNXPaths()
  188. CheckNXPaths()
  189. Local toolchainBin:String
  190. Select processor.CPU()
  191. Case "arm64"
  192. toolchainBin = "aarch64-none-elf-"
  193. End Select
  194. Local toolchainDir:String = processor.Option("nx.devkitpro", "") + "/devkitA64/"
  195. If FileType(RealPath(toolchainDir)) <> FILETYPE_DIR Then
  196. Throw "Cannot determine toolchain dir for NX, at '" + toolchainDir + "'"
  197. End If
  198. Local exe:String
  199. ?win32
  200. exe = ".exe"
  201. ?
  202. Local gccPath:String = toolchainDir + "/bin/" + toolchainBin + "gcc" + exe
  203. Local gppPath:String = toolchainDir + "/bin/" + toolchainBin + "g++" + exe
  204. Local arPath:String = toolchainDir + "/bin/" + toolchainBin + "ar" + exe
  205. Local libPath:String = toolchainDir + "/lib"
  206. ' check paths
  207. If Not FileType(RealPath(gccPath)) Then
  208. Throw "gcc not found at '" + gccPath + "'"
  209. End If
  210. If Not FileType(RealPath(gppPath)) Then
  211. Throw "g++ not found at '" + gppPath + "'"
  212. End If
  213. If Not FileType(RealPath(gccPath)) Then
  214. Throw "ar not found at '" + arPath + "'"
  215. End If
  216. globals.SetVar("nx." + processor.CPU() + ".gcc", gccPath)
  217. globals.SetVar("nx." + processor.CPU() + ".gpp", gppPath)
  218. globals.SetVar("nx." + processor.CPU() + ".ar", arPath)
  219. globals.SetVar("nx." + processor.CPU() + ".lib", "-L" + libPath)
  220. ?Not win32
  221. Local pathSeparator:String = ":"
  222. Local dirSeparator:String = "/"
  223. ?win32
  224. Local pathSeparator:String = ";"
  225. Local dirSeparator:String = "\"
  226. ?
  227. Local path:String = getenv_("PATH")
  228. path = toolchainDir + dirSeparator + "bin" + pathSeparator + path
  229. putenv_("PATH=" + path)
  230. End Function
  231. Function CheckNXPaths()
  232. ' check envs and paths
  233. Local devkitpro:String = processor.Option("nx.devkitpro", getenv_("DEVKITPRO")).Trim()
  234. If Not devkitpro Then
  235. Throw "DEVKITPRO or 'nx.devkitpro' config option not set"
  236. End If
  237. putenv_("DEVKITPRO=" + devkitpro)
  238. globals.SetVar("nx.devkitpro", devkitpro)
  239. End Function
  240. Type TBuildManager Extends TCallback
  241. Field sources:TMap = New TMap
  242. Field buildAll:Int
  243. Field framework_mods:TList
  244. Field app_iface:String
  245. Method New()
  246. ' pre build checks
  247. If processor.Platform() = "android" Then
  248. ConfigureAndroidPaths()
  249. Else If processor.Platform() = "ios" Then
  250. ConfigureIOSPaths()
  251. Else If processor.Platform() = "nx" Then
  252. ConfigureNXPaths()
  253. End If
  254. If processor.Platform() = "linux" Or processor.Platform() = "raspberrypi" Then
  255. If opt_nopie Then
  256. globals.SetVar("nopie", "true")
  257. End If
  258. End If
  259. processor.callback = Self
  260. End Method
  261. Method MakeMods(mods:TList, rebuild:Int = False)
  262. For Local m:String = EachIn mods
  263. If (opt_modfilter And ((m).Find(opt_modfilter) = 0)) Or (Not opt_modfilter) Then
  264. GetMod(m, rebuild Or buildAll)
  265. End If
  266. Next
  267. End Method
  268. Method MakeApp(main_path:String, makelib:Int, compileOnly:Int = False)
  269. app_main = main_path
  270. Local source:TSourceFile = GetSourceFile(app_main, False, opt_all)
  271. If Not source Then
  272. Return
  273. End If
  274. Local build_path:String = ExtractDir(main_path) + "/.bmx"
  275. Local appType:String
  276. If Not compileOnly Or source.framewk Then
  277. appType = "." + opt_apptype
  278. End If
  279. source.obj_path = build_path + "/" + StripDir( main_path ) + appType + opt_configmung + processor.CPU() + ".o"
  280. source.obj_time = FileTime(source.obj_path)
  281. source.iface_path = StripExt(source.obj_path) + ".i"
  282. source.iface_time = FileTime(source.iface_path)
  283. app_iface = source.iface_path
  284. Local cc_opts:String
  285. source.AddIncludePath(" -I" + CQuote(ModulePath("")))
  286. If opt_release Then
  287. cc_opts :+ " -DNDEBUG"
  288. End If
  289. If processor.BCCVersion() <> "BlitzMax" Then
  290. If opt_gdbdebug Then
  291. cc_opts :+ " -g"
  292. End If
  293. If opt_gprof Then
  294. cc_opts :+ " -pg"
  295. End If
  296. End If
  297. Local sb:TStringBuffer = New TStringBuffer
  298. sb.Append(" -g ").Append(processor.CPU())
  299. If opt_quiet sb.Append(" -q")
  300. If opt_verbose sb.Append(" -v")
  301. If opt_release sb.Append(" -r")
  302. If opt_threaded sb.Append(" -h")
  303. If opt_framework sb.Append(" -f ").Append(opt_framework)
  304. If processor.BCCVersion() <> "BlitzMax" Then
  305. If opt_gdbdebug Then
  306. sb.Append(" -d")
  307. End If
  308. If Not opt_nostrictupgrade Then
  309. sb.Append(" -s")
  310. End If
  311. If opt_warnover Then
  312. sb.Append(" -w")
  313. End If
  314. If opt_musl Then
  315. sb.Append(" -musl")
  316. End If
  317. If makelib Then
  318. sb.Append(" -makelib")
  319. If opt_nodef Then
  320. sb.append(" -nodef")
  321. End If
  322. If opt_nohead Then
  323. sb.append(" -nohead")
  324. End If
  325. End If
  326. If opt_require_override Then
  327. sb.Append(" -override")
  328. If opt_override_error Then
  329. sb.Append(" -overerr")
  330. End If
  331. End If
  332. Local defs:String = opt_userdefs
  333. If globals.Get("user_defs") Then
  334. If defs Then
  335. defs :+ ","
  336. End If
  337. defs :+ globals.Get("user_defs")
  338. End If
  339. If defs Then
  340. sb.Append(" -ud ").Append(defs)
  341. End If
  342. If opt_standalone Then
  343. sb.Append(" -ib")
  344. End If
  345. End If
  346. source.cc_opts :+ cc_opts
  347. source.cpp_opts :+ cpp_opts
  348. source.c_opts :+ c_opts
  349. source.modimports.AddLast("brl.blitz")
  350. source.modimports.AddLast(opt_appstub)
  351. If source.framewk
  352. If opt_framework Then
  353. Throw "Framework already specified on commandline"
  354. End If
  355. opt_framework = source.framewk
  356. sb.Append(" -f ").Append(opt_framework)
  357. source.modimports.AddLast(opt_framework)
  358. Else
  359. framework_mods = New TList
  360. For Local t:String = EachIn EnumModules()
  361. If t.Find("brl.") = 0 Or t.Find("pub.") = 0 Then
  362. If t <> "brl.blitz" And t <> opt_appstub Then
  363. source.modimports.AddLast(t)
  364. framework_mods.AddLast(t)
  365. End If
  366. End If
  367. Next
  368. End If
  369. source.bcc_opts = sb.ToString()
  370. source.SetRequiresBuild(opt_all)
  371. CalculateDependencies(source, False, opt_all)
  372. source.bcc_opts :+ " -t " + opt_apptype
  373. ' create bmx stages :
  374. Local gen:TSourceFile
  375. ' for osx x86 on legacy, we need to convert asm
  376. If processor.BCCVersion() = "BlitzMax" And processor.CPU() = "x86" And processor.Platform() = "macos" Then
  377. Local fasm2as:TSourceFile = CreateFasm2AsStage(source)
  378. gen = CreateGenStage(fasm2as)
  379. Else
  380. gen = CreateGenStage(source)
  381. End If
  382. If Not compileOnly Then
  383. Local link:TSourceFile = CreateLinkStage(gen, STAGE_APP_LINK)
  384. End If
  385. End Method
  386. Method DoBuild(makelib:Int, app_build:Int = False)
  387. Local arc_order:TList = New TList
  388. Local files:TList = New TList
  389. For Local file:TSourceFile = EachIn sources.Values()
  390. files.AddLast(file)
  391. Next
  392. ' get the list of parallelizable batches
  393. ' each list of batches has no outstanding dependencies, and therefore
  394. ' can be compiled in parallel.
  395. ' the last list of batches requires all previous lists to have
  396. ' been compiled.
  397. Local batches:TList = CalculateBatches(files)
  398. For Local batch:TList = EachIn batches
  399. Local s:String
  400. For Local m:TSourceFile = EachIn batch
  401. ' sort archives for app linkage
  402. If m.modid Then
  403. Local path:String = m.arc_path
  404. If IOS_HAS_MERGE And processor.Platform() = "ios" Then
  405. path = m.merge_path
  406. End If
  407. If Not arc_order.Contains(path) Then
  408. arc_order.AddFirst(path)
  409. End If
  410. End If
  411. Local build_path:String
  412. If m.obj_path Then
  413. build_path = ExtractDir(m.obj_path)
  414. Else
  415. build_path = ExtractDir(m.path) + "/.bmx"
  416. End If
  417. If Not FileType(build_path) Then
  418. CreateDir build_path
  419. End If
  420. If FileType(build_path) <> FILETYPE_DIR Then
  421. Throw "Unable to create temporary directory : " + build_path
  422. End If
  423. ' change dir, so relative commands work as expected
  424. ' (eg. file processing in BMK-scripts called via pragma)
  425. ChangeDir ExtractDir( m.path )
  426. ' bmx file
  427. If Match(m.ext, "bmx") Then
  428. Select m.stage
  429. Case STAGE_GENERATE
  430. If m.requiresBuild Or (m.time > m.gen_time Or m.iface_time < m.MaxIfaceTime() Or Not m.MaxIfaceTime()) Then
  431. If Not opt_quiet Then
  432. Print ShowPct(m.pct) + "Processing:" + StripDir(m.path)
  433. End If
  434. ' process pragmas
  435. Local pragma_inDefine:Int, pragma_text:String, pragma_name:String
  436. For Local pragma:String = EachIn m.pragmas
  437. processor.ProcessPragma(pragma, pragma_inDefine, pragma_text, pragma_name)
  438. Next
  439. CompileBMX m.path, m.obj_path, m.bcc_opts
  440. End If
  441. Case STAGE_FASM2AS
  442. For Local s:TSourceFile = EachIn m.depsList
  443. If s.requiresBuild Then
  444. m.SetRequiresBuild(True)
  445. Exit
  446. End If
  447. Next
  448. If m.requiresBuild Or (m.time > m.obj_time Or m.iface_time < m.MaxIfaceTime()) Then
  449. m.SetRequiresBuild(True)
  450. If Not opt_quiet Then
  451. Print ShowPct(m.pct) + "Converting:" + StripDir(StripExt(m.obj_path) + ".s")
  452. End If
  453. Fasm2As m.path, m.obj_path
  454. m.asm_time = time_(Null)
  455. End If
  456. Case STAGE_OBJECT
  457. If m.requiresBuild Or (m.time > m.obj_time Or m.iface_time < m.MaxIfaceTime()) Then
  458. m.SetRequiresBuild(True)
  459. If processor.BCCVersion() <> "BlitzMax" Then
  460. Local csrc_path:String = StripExt(m.obj_path) + ".c"
  461. Local cobj_path:String = StripExt(m.obj_path) + ".o"
  462. If Not opt_quiet Then
  463. Local s:String = ShowPct(m.pct) + "Compiling:" + StripDir(csrc_path)
  464. If opt_standalone And Not opt_nolog processor.PushEcho(FixPct(s))
  465. Print s
  466. End If
  467. If opt_standalone And opt_boot Then
  468. processor.PushSource(csrc_path)
  469. processor.PushSource(StripExt(m.obj_path) + ".h")
  470. End If
  471. CompileC csrc_path,cobj_path, m.GetIncludePaths() + " " + m.cc_opts + " " + m.c_opts
  472. Else
  473. ' asm compilation
  474. Local src_path:String = StripExt(m.obj_path) + ".s"
  475. Local obj_path:String = StripExt(m.obj_path) + ".o"
  476. If Not opt_quiet Then
  477. Print ShowPct(m.pct) + "Compiling:" + StripDir(src_path)
  478. End If
  479. Assemble src_path, obj_path
  480. End If
  481. m.obj_time = time_(Null)
  482. End If
  483. Case STAGE_LINK
  484. Local max_obj_time:Int = m.MaxObjTime()
  485. If max_obj_time > m.arc_time And Not m.dontbuild Then
  486. Local objs:TList = New TList
  487. m.GetObjs(objs)
  488. If Not opt_quiet Then
  489. Local s:String = ShowPct(m.pct) + "Archiving:" + StripDir(m.arc_path)
  490. If opt_standalone And Not opt_nolog processor.PushEcho(FixPct(s))
  491. Print s
  492. End If
  493. Local at:TArcTask = New TArcTask.Create(m, m.arc_path, objs)
  494. ?threaded
  495. If opt_single Then
  496. at.CreateArc()
  497. Else
  498. processManager.AddTask(TArcTask._CreateArc, at)
  499. End If
  500. ?Not threaded
  501. at.CreateArc()
  502. ?
  503. End If
  504. Case STAGE_APP_LINK
  505. ' this probably should never happen.
  506. ' may be a bad module?
  507. If Not opt_outfile Then
  508. Throw "Build Error: Did not expect to link against " + m.path
  509. End If
  510. ' an app!
  511. Local max_lnk_time:Int = m.MaxLinkTime()
  512. ' include settings and icon times in calculation
  513. If opt_manifest And processor.Platform() = "win32" And opt_apptype="gui" Then
  514. Local settings:String = ExtractDir(opt_infile) + "/" + StripDir(StripExt(opt_outfile)) + ".settings"
  515. If Not FileType(settings) Then
  516. settings = ExtractDir(opt_infile) + "/" + StripDir(StripExt(opt_infile)) + ".settings"
  517. End If
  518. max_lnk_time = Max(FileTime(settings), max_lnk_time)
  519. Local icon:String = ExtractDir(opt_infile) + "/" + StripDir(StripExt(opt_outfile)) + ".ico"
  520. If Not FileType(icon) Then
  521. icon = ExtractDir(opt_infile) + "/" + StripDir(StripExt(opt_infile)) + ".ico"
  522. End If
  523. max_lnk_time = Max(FileTime(icon), max_lnk_time)
  524. End If
  525. If max_lnk_time > FileTime(opt_outfile) Or opt_all Then
  526. ' generate manifest for app
  527. If opt_manifest And processor.Platform() = "win32" And opt_apptype="gui" Then
  528. processor.RunCommand("make_win32_resource", Null)
  529. Local res:String = ExtractDir(opt_infile) + "/.bmx/" + StripDir(StripExt(opt_outfile)) + "." + processor.CPU() + ".res.o"
  530. If Not FileType(res) Then
  531. res = ExtractDir(opt_infile) + "/.bmx/" + StripDir(StripExt(opt_infile)) + "." + processor.CPU() + ".res.o"
  532. End If
  533. If FileType(res) = FILETYPE_FILE Then
  534. Local s:TSourceFile = New TSourceFile
  535. s.obj_path = res
  536. s.stage = STAGE_LINK
  537. s.exti = SOURCE_RES
  538. m.depslist.AddLast(s)
  539. End If
  540. End If
  541. If Not opt_quiet Then
  542. Local s:String = ShowPct(m.pct) + "Linking:" + StripDir(opt_outfile)
  543. If opt_standalone And Not opt_nolog processor.PushEcho(FixPct(s))
  544. Print s
  545. End If
  546. Local links:TList = New TList
  547. Local opts:TList = New TList
  548. m.GetLinks(links, opts)
  549. For Local arc:String = EachIn arc_order
  550. links.AddLast(arc)
  551. Next
  552. For Local o:String = EachIn opts
  553. links.AddLast(o)
  554. Next
  555. LinkApp opt_outfile, links, makelib, globals.Get("ld_opts")
  556. m.obj_time = time_(Null)
  557. End If
  558. Case STAGE_MERGE
  559. If IOS_HAS_MERGE Then
  560. ' a module?
  561. If m.modid Then
  562. Local max_obj_time:Int = m.MaxObjTime()
  563. If max_obj_time > m.merge_time And Not m.dontbuild Then
  564. If Not opt_quiet Then
  565. Print ShowPct(m.pct) + "Merging:" + StripDir(m.merge_path)
  566. End If
  567. CreateMergeArc m.merge_path, m.arc_path
  568. m.merge_time = time_(Null)
  569. End If
  570. End If
  571. End If
  572. End Select
  573. Else If Match(m.ext, "s") Then
  574. If m.time > m.obj_time Then ' object is older or doesn't exist
  575. m.SetRequiresBuild(True)
  576. End If
  577. If m.requiresBuild Then
  578. If Not opt_quiet Then
  579. Local s:String = ShowPct(m.pct) + "Compiling:" + StripDir(m.path)
  580. If opt_standalone And Not opt_nolog processor.PushEcho(FixPct(s))
  581. Print s
  582. End If
  583. If processor.BCCVersion() = "BlitzMax" Then
  584. Assemble m.path, m.obj_path
  585. Else
  586. CompileC m.path, m.obj_path, m.GetIncludePaths() + " " + m.cc_opts + " " + m.c_opts
  587. End If
  588. End If
  589. Else
  590. If Not m.dontbuild Then
  591. ' c/c++ source
  592. If m.time > m.obj_time Then ' object is older or doesn't exist
  593. m.SetRequiresBuild(True)
  594. End If
  595. If m.requiresBuild Then
  596. If Not opt_quiet Then
  597. Local s:String = ShowPct(m.pct) + "Compiling:" + StripDir(m.path)
  598. If opt_standalone And Not opt_nolog processor.PushEcho(FixPct(s))
  599. Print s
  600. End If
  601. If m.path.EndsWith(".cpp") Or m.path.EndsWith("cc") Then
  602. CompileC m.path, m.obj_path, m.GetIncludePaths() + " " + m.cc_opts + " " + m.cpp_opts
  603. ElseIf m.path.EndsWith(".S") Or m.path.EndsWith("asm") Then
  604. AssembleNative m.path, m.obj_path
  605. Else
  606. CompileC m.path, m.obj_path, m.GetIncludePaths() + " " + m.cc_opts + " " + m.c_opts
  607. End If
  608. m.obj_time = time_(Null)
  609. End If
  610. End If
  611. End If
  612. Next
  613. ?threaded
  614. If Not opt_single Then
  615. processManager.WaitForTasks()
  616. End If
  617. ?
  618. Next
  619. If app_build Then
  620. ' global post process
  621. LoadBMK("post.bmk")
  622. ' generic post process
  623. LoadBMK(ExtractDir(app_main) + "/post.bmk")
  624. ' project-specific post process
  625. LoadBMK(ExtractDir(app_main) + "/" + StripDir( opt_outfile ) + ".post.bmk")
  626. Select processor.Platform()
  627. Case "android"
  628. ' create the apk
  629. ' copy shared object
  630. Local androidABI:String = processor.Option("android.abi", "")
  631. Local appId:String = StripDir(StripExt(opt_outfile))
  632. If opt_debug And opt_outfile.EndsWith(".debug") Then
  633. appId :+ ".debug"
  634. End If
  635. Local buildDir:String = ExtractDir(opt_outfile)
  636. Local projectDir:String = buildDir + "/android-project-" + appId
  637. Local abiPath:String = projectDir + "/libs/" + androidABI
  638. Local sharedObject:String = "lib" + appId
  639. sharedObject :+ ".so"
  640. CopyFile(buildDir + "/" + sharedObject, abiPath + "/" + sharedObject)
  641. ' build the apk :
  642. Local antHome:String = processor.Option("ant.home", "").Trim()
  643. Local cmd:String = "~q" + antHome + "/bin/ant"
  644. ?win32
  645. cmd :+ ".bat"
  646. ?
  647. cmd :+ "~q debug"
  648. Local dir:String = CurrentDir()
  649. ChangeDir(projectDir)
  650. If opt_dumpbuild Then
  651. Print cmd
  652. End If
  653. If Sys( cmd ) Then
  654. Throw "Error creating apk"
  655. End If
  656. ChangeDir(dir)
  657. 'End If
  658. Case "ios"
  659. Local iosSimulator:Int = (processor.CPU() = "x86")
  660. ' TODO - other stuff ?
  661. Case "nx"
  662. ' TODO - build nro, nso, psf0 and nacp
  663. End Select
  664. End If
  665. End Method
  666. Method CalculateDependencies(source:TSourceFile, isMod:Int = False, rebuildImports:Int = False, isInclude:Int = False)
  667. If source And Not source.processed Then
  668. source.processed = True
  669. For Local m:String = EachIn source.modimports
  670. Local s:TSourceFile = GetMod(m)
  671. If s Then
  672. If Not source.moddeps Then
  673. source.moddeps = New TMap
  674. End If
  675. If Not source.moddeps.ValueForKey(m) Then
  676. source.moddeps.Insert(m, s)
  677. source.deps.Insert(s.GetSourcePath(), s)
  678. source.AddIncludePath(" -I" + CQuote(ExtractDir(s.path)))
  679. End If
  680. End If
  681. Next
  682. Local ib:TSourceFile
  683. If processor.BCCVersion() <> "BlitzMax" And Not source.incbins.IsEmpty() Then
  684. If source.owner_path Then
  685. ib = CreateIncBin(source, source.owner_path)
  686. Else
  687. ib = CreateIncBin(source, source.path)
  688. End If
  689. End If
  690. For Local f:String = EachIn source.imports
  691. If f[0] <> Asc("-") Then
  692. Local path:String = CheckPath(ExtractDir(source.path), f)
  693. Local s:TSourceFile = GetSourceFile(path, isMod)
  694. If s Then
  695. If rebuildImports Then
  696. s.SetRequiresBuild(rebuildImports)
  697. End If
  698. If Match(s.ext, "bmx") Then
  699. s.modimports.AddLast("brl.blitz")
  700. ' app source files need framework/mod dependencies applied
  701. If Not isMod Then
  702. If opt_framework Then
  703. ' add framework as dependency
  704. s.modimports.AddLast(opt_framework)
  705. Else
  706. ' add all pub/brl mods as dependency
  707. If framework_mods Then
  708. For Local m:String = EachIn framework_mods
  709. s.modimports.AddLast(m)
  710. Next
  711. End If
  712. End If
  713. End If
  714. s.bcc_opts = source.bcc_opts
  715. s.cc_opts :+ source.cc_opts
  716. s.cpp_opts :+ source.cpp_opts
  717. s.c_opts :+ source.c_opts
  718. s.CopyIncludePaths(source.includePaths)
  719. CalculateDependencies(s, isMod, rebuildImports)
  720. ' if file that we generate is missing, we need to rebuild
  721. If processor.BCCVersion() = "BlitzMax" Then
  722. If Not FileType(StripExt(s.obj_path) + ".s") Then
  723. s.SetRequiresBuild(True)
  724. End If
  725. Else
  726. If Not FileType(StripExt(s.obj_path) + ".c") Then
  727. s.SetRequiresBuild(True)
  728. End If
  729. End If
  730. Local gen:TSourceFile
  731. ' for osx x86 on legacy, we need to convert asm
  732. If processor.BCCVersion() = "BlitzMax" And processor.CPU() = "x86" And processor.Platform() = "macos" Then
  733. Local fasm2as:TSourceFile = CreateFasm2AsStage(s)
  734. gen = CreateGenStage(fasm2as)
  735. Else
  736. gen = CreateGenStage(s)
  737. End If
  738. source.deps.Insert(gen.GetSourcePath(), gen)
  739. If Not source.depsList Then
  740. source.depsList = New TList
  741. End If
  742. source.depsList.AddLast(gen)
  743. Else
  744. s.cc_opts = source.cc_opts
  745. s.cpp_opts = source.cpp_opts
  746. s.c_opts = source.c_opts
  747. s.CopyIncludePaths(source.includePaths)
  748. source.deps.Insert(s.GetSourcePath(), s)
  749. If Not source.depsList Then
  750. source.depsList = New TList
  751. End If
  752. source.depsList.AddLast(s)
  753. End If
  754. Else
  755. Local ext:String = ExtractExt(path)
  756. If Match(ext, "h;hpp;hxx") Then ' header?
  757. source.AddIncludePath(" -I" + CQuote(ExtractDir(path)))
  758. Else If Match(ext, "o;a;lib") Then ' object or archive?
  759. Local s:TSourceFile = New TSourceFile
  760. s.time = FileTime(path)
  761. s.obj_time = s.time
  762. s.path = path
  763. s.obj_path = path
  764. s.modid = source.modid
  765. If s.time > source.time Then
  766. source.time = s.time
  767. End If
  768. If Not source.depsList Then
  769. source.depsList = New TList
  770. End If
  771. source.depsList.AddLast(s)
  772. End If
  773. End If
  774. Else
  775. If Not source.ext_files Then
  776. source.ext_files = New TList
  777. End If
  778. source.ext_files.AddLast(f)
  779. End If
  780. Next
  781. For Local f:String = EachIn source.includes
  782. Local path:String = CheckPath(ExtractDir(source.path), f)
  783. Local s:TSourceFile = GetSourceFile(path, isMod, rebuildImports, True)
  784. If s Then
  785. s.owner_path = source.path
  786. ' calculate included file dependencies
  787. CalculateDependencies(s, isMod, rebuildImports)
  788. ' update our time to latest included time
  789. If s.time > source.time Then
  790. source.time = s.time
  791. End If
  792. If Not source.depsList Then
  793. source.depsList = New TList
  794. End If
  795. source.depsList.AddLast(s)
  796. End If
  797. Next
  798. For Local f:String = EachIn source.incbins
  799. Local path:String = CheckPath(ExtractDir(source.path), f)
  800. If FileType(path) = FILETYPE_FILE Then
  801. source.hashes.Insert(f, CalculateFileHash(path))
  802. End If
  803. Local time:Int = FileTime(path)
  804. ' update our time to the latest incbin time
  805. If time > source.time Then
  806. source.time = time
  807. End If
  808. ' update ib time to the latest incbin time
  809. If ib And ib.time And ib.time < time Then
  810. ib.time = time
  811. End If
  812. Next
  813. ' incbin file
  814. If ib Then
  815. Local requiresBuild:Int = False
  816. ' missing source.. generate and compile
  817. If Not ib.time Then
  818. requiresBuild = True
  819. Else If IncbinsDifference(source.incbins, ib.incbins) Then
  820. requiresBuild = True
  821. Else If IncbinsHashDifference(source, ib) Then
  822. requiresBuild = True
  823. End If
  824. If requiresBuild Then
  825. ib.SetRequiresBuild(True)
  826. source.SetRequiresBuild(True)
  827. End If
  828. ' sync timestamps
  829. If ib.time > source.time Then
  830. source.time = ib.time
  831. End If
  832. End If
  833. If source.depsList Then
  834. For Local s:TSourceFile = EachIn source.depsList
  835. If Not Match(s.ext, "bmx") Then
  836. s.cc_opts = source.cc_opts
  837. s.cpp_opts = source.cpp_opts
  838. s.c_opts = source.c_opts
  839. s.CopyIncludePaths(source.includePaths)
  840. End If
  841. Next
  842. End If
  843. End If
  844. End Method
  845. Method GetSourceFile:TSourceFile(source_path:String, isMod:Int = False, rebuild:Int = False, isInclude:Int = False)
  846. Local source:TSourceFile = TSourceFile(sources.ValueForKey(source_path))
  847. If Not source Then
  848. source = ParseSourceFile(source_path)
  849. If source Then
  850. Local ext:String = ExtractExt(source_path)
  851. If Match(ext, ALL_SRC_EXTS) Then
  852. If Not isInclude Then
  853. sources.Insert(source_path, source)
  854. Local sp:String
  855. If app_main = source_path Then
  856. sp = ConcatString(ExtractDir(source_path), "/.bmx/", StripDir(source_path), "." + opt_apptype, opt_configmung, processor.CPU())
  857. Else
  858. sp = ConcatString(ExtractDir(source_path), "/.bmx/", StripDir(source_path), opt_configmung, processor.CPU())
  859. End If
  860. If Match(ext, "bmx") Then
  861. source.obj_path = sp + ".o"
  862. source.obj_time = FileTime(source.obj_path)
  863. source.iface_path = sp + ".i"
  864. source.iface_path2 = source.iface_path + "2"
  865. source.iface_time = FileTime(source.iface_path2)
  866. ' gen file times
  867. If processor.BCCVersion() <> "BlitzMax" Then
  868. Local p:String = sp + ".c"
  869. source.gen_time = FileTime(p)
  870. If source.gen_time Then
  871. p = sp + ".h"
  872. source.gen_time = Min(source.gen_time, FileTime(p))
  873. End If
  874. Else
  875. Local p:String = sp + ".s"
  876. source.gen_time = FileTime(p)
  877. End If
  878. Else
  879. source.obj_path = PPFix(sp) + ".o"
  880. source.obj_time = FileTime(source.obj_path)
  881. End If
  882. Else
  883. source.isInclude = True
  884. End If
  885. End If
  886. End If
  887. End If
  888. Return source
  889. End Method
  890. Method PPFix:String(path:String)
  891. Local dir:String = ExtractDir(ExtractDir(path))
  892. Local s:String
  893. For Local i:Int = 0 Until 3
  894. Local t:String = StripDir(dir)
  895. If Not t Then
  896. t = "x"
  897. End If
  898. s = t[..1] + s
  899. dir = ExtractDir(dir)
  900. Next
  901. Return ExtractDir(path) + "/" + s + "_" + StripDir(path)
  902. End Method
  903. Method GetISourceFile:TSourceFile(arc_path:String, arc_time:Int, iface_path:String, iface_time:Int, merge_path:String, merge_time:Int)
  904. Local source:TSourceFile
  905. If IOS_HAS_MERGE And processor.Platform() = "ios" Then
  906. source = TSourceFile(sources.ValueForKey(merge_path))
  907. Else
  908. source = TSourceFile(sources.ValueForKey(arc_path))
  909. End If
  910. If Not source Then
  911. Local iface_path2:String = iface_path + 2
  912. source = ParseISourceFile(iface_path2)
  913. If source Then
  914. source.arc_path = arc_path
  915. source.arc_time = arc_time
  916. source.iface_path = iface_path
  917. source.iface_path2 = iface_path2
  918. source.iface_time = iface_time
  919. source.merge_time = merge_time
  920. If IOS_HAS_MERGE And processor.Platform() = "ios" Then
  921. sources.Insert(merge_path, source)
  922. Else
  923. sources.Insert(arc_path, source)
  924. End If
  925. End If
  926. End If
  927. Return source
  928. End Method
  929. Method GetMod:TSourceFile(m:String, rebuild:Int = False)
  930. If (opt_all And ((opt_modfilter And ((m).Find(opt_modfilter) = 0)) Or (Not opt_modfilter)) And Not app_main) Or (app_main And opt_standalone) Then
  931. rebuild = True
  932. End If
  933. Local path:String = ModulePath(m)
  934. Local id:String = ModuleIdent(m)
  935. Local mp:String = ConcatString(path, "/", id, opt_configmung, processor.CPU())
  936. ' get the module interface and lib details
  937. Local arc_path:String = mp + ".a"
  938. Local arc_time:Int = FileTime(arc_path)
  939. Local iface_path:String = mp + ".i"
  940. Local iface_path2:String = iface_path + "2"
  941. Local iface_time:Int = FileTime(iface_path2)
  942. Local merge_path:String
  943. Local merge_time:Int
  944. If IOS_HAS_MERGE And processor.Platform() = "ios" Then
  945. If processor.CPU() = "x86" Or processor.CPU() = "x64" Then
  946. merge_path = ConcatString(path, "/", id, opt_configmung, "sim.a")
  947. Else
  948. merge_path = ConcatString(path, "/", id, opt_configmung, "dev.a")
  949. End If
  950. merge_time = FileTime(merge_path)
  951. End If
  952. Local source:TSourceFile
  953. Local link:TSourceFile
  954. ' do a quick scan only when building apps. For module builds we want to check required modules.
  955. If arc_time And iface_time And opt_quickscan And app_main Then
  956. source = GetISourceFile(arc_path, arc_time, iface_path, iface_time, merge_path, merge_time)
  957. If Not source Then
  958. Return Null
  959. End If
  960. If Not source.processed Then
  961. source.modid = m
  962. source.arc_path = arc_path
  963. source.arc_time = arc_time
  964. source.iface_path = iface_path
  965. source.iface_path2 = iface_path2
  966. source.iface_time = iface_time
  967. source.obj_path = arc_path
  968. source.merge_path = merge_path
  969. source.merge_time = merge_time
  970. CalculateDependencies(source, True, rebuild)
  971. source.dontbuild = True
  972. If IOS_HAS_MERGE And processor.Platform() = "ios" Then
  973. source.stage = STAGE_MERGE
  974. sources.Insert(source.merge_path, source)
  975. Else
  976. source.stage = STAGE_LINK
  977. sources.Insert(source.arc_path, source)
  978. End If
  979. End If
  980. link = source
  981. Else
  982. Local src_path:String = ConcatString(path, "/", id, ".bmx")
  983. source = GetSourceFile(src_path, True, rebuild)
  984. If Not source Then
  985. Return Null
  986. End If
  987. ' main module file without "Module" line?
  988. If Not source.modid Then
  989. Return Null
  990. End If
  991. End If
  992. If Not source.processed Then
  993. source.arc_path = arc_path
  994. source.arc_time = arc_time
  995. source.iface_path = iface_path
  996. source.iface_path2 = iface_path2
  997. source.iface_time = iface_time
  998. source.merge_path = merge_path
  999. source.merge_time = merge_time
  1000. Local cc_opts:String
  1001. source.AddIncludePath(" -I" + CQuote(path))
  1002. source.AddIncludePath(" -I" + CQuote(ModulePath("")))
  1003. If opt_release Then
  1004. cc_opts :+ " -DNDEBUG"
  1005. End If
  1006. If opt_threaded Then
  1007. cc_opts :+ " -DTHREADED"
  1008. End If
  1009. If processor.BCCVersion() <> "BlitzMax" Then
  1010. If opt_gdbdebug Then
  1011. cc_opts :+ " -g"
  1012. End If
  1013. If opt_gprof Then
  1014. cc_opts :+ " -pg"
  1015. End If
  1016. End If
  1017. source.cc_opts = ""
  1018. If source.mod_opts Then
  1019. source.cc_opts :+ source.mod_opts.cc_opts
  1020. source.cpp_opts :+ source.mod_opts.cpp_opts
  1021. source.c_opts :+ source.mod_opts.c_opts
  1022. End If
  1023. source.cc_opts :+ cc_opts
  1024. source.cpp_opts :+ cpp_opts
  1025. source.c_opts :+ c_opts
  1026. ' Module BCC opts
  1027. Local sb:TStringBuffer = New TStringBuffer
  1028. sb.Append(" -g ").Append(processor.CPU())
  1029. sb.Append(" -m ").Append(m)
  1030. If opt_quiet sb.Append(" -q")
  1031. If opt_verbose sb.Append(" -v")
  1032. If opt_release sb.Append(" -r")
  1033. If opt_threaded sb.Append(" -h")
  1034. If processor.BCCVersion() <> "BlitzMax" Then
  1035. If opt_gdbdebug Then
  1036. sb.Append(" -d")
  1037. End If
  1038. If Not opt_nostrictupgrade Then
  1039. sb.Append(" -s")
  1040. End If
  1041. If opt_warnover Then
  1042. sb.Append(" -w")
  1043. End If
  1044. If opt_musl Then
  1045. sb.Append(" -musl")
  1046. End If
  1047. If opt_require_override Then
  1048. sb.Append(" -override")
  1049. If opt_override_error Then
  1050. sb.Append(" -overerr")
  1051. End If
  1052. End If
  1053. Local defs:String = opt_userdefs
  1054. If globals.Get("user_defs") Then
  1055. If defs Then
  1056. defs :+ ","
  1057. End If
  1058. defs :+ globals.Get("user_defs")
  1059. End If
  1060. If defs Then
  1061. sb.Append(" -ud ").Append(defs)
  1062. End If
  1063. If opt_standalone Then
  1064. sb.Append(" -ib")
  1065. End If
  1066. End If
  1067. source.bcc_opts = sb.ToString()
  1068. source.SetRequiresBuild(rebuild)
  1069. ' interface is REQUIRED for compilation
  1070. If Not iface_time Then
  1071. source.SetRequiresBuild(True)
  1072. End If
  1073. If m <> "brl.blitz" Then
  1074. source.modimports.AddLast("brl.blitz")
  1075. End If
  1076. CalculateDependencies(source, True, rebuild)
  1077. ' create bmx stages :
  1078. Local gen:TSourceFile
  1079. ' for osx x86 on legacy, we need to convert asm
  1080. If processor.BCCVersion() = "BlitzMax" And processor.CPU() = "x86" And processor.Platform() = "macos" Then
  1081. Local fasm2as:TSourceFile = CreateFasm2AsStage(source)
  1082. gen = CreateGenStage(fasm2as)
  1083. Else
  1084. gen = CreateGenStage(source)
  1085. End If
  1086. If processor.Platform() <> "ios" Then
  1087. link = CreateLinkStage(gen)
  1088. Else
  1089. If IOS_HAS_MERGE Then
  1090. Local realLink:TSourceFile = CreateLinkStage(gen)
  1091. ' create a fat archive
  1092. link = CreateMergeStage(realLink)
  1093. Else
  1094. link = CreateLinkStage(gen)
  1095. End If
  1096. End If
  1097. Else
  1098. If IOS_HAS_MERGE And processor.Platform() = "ios" Then
  1099. link = TSourceFile(sources.ValueForKey(source.merge_path))
  1100. Else
  1101. link = TSourceFile(sources.ValueForKey(source.arc_path))
  1102. End If
  1103. If Not link Then
  1104. Throw "Can't find link for : " + source.path
  1105. End If
  1106. End If
  1107. Return link
  1108. End Method
  1109. Method CreateFasm2AsStage:TSourceFile(source:TSourceFile)
  1110. Local fasm:TSourceFile = New TSourceFile
  1111. source.CopyInfo(fasm)
  1112. fasm.deps.Insert(source.path, source)
  1113. fasm.stage = STAGE_FASM2AS
  1114. fasm.processed = True
  1115. fasm.depsList = New TList
  1116. fasm.depsList.AddLast(source)
  1117. sources.Insert(StripExt(fasm.obj_path) + ".s", fasm)
  1118. Return fasm
  1119. End Method
  1120. Method CreateGenStage:TSourceFile(source:TSourceFile)
  1121. Local gen:TSourceFile = New TSourceFile
  1122. source.CopyInfo(gen)
  1123. If processor.BCCVersion() = "BlitzMax" And processor.CPU() = "x86" And processor.Platform() = "macos" Then
  1124. gen.deps.Insert(StripExt(source.obj_path) + ".s", source)
  1125. Else
  1126. gen.deps.Insert(source.path, source)
  1127. End If
  1128. gen.stage = STAGE_OBJECT
  1129. gen.processed = True
  1130. gen.depsList = New TList
  1131. gen.depsList.AddLast(source)
  1132. sources.Insert(StripExt(gen.obj_path) + ".c", gen)
  1133. Return gen
  1134. End Method
  1135. Method CreateIncBin:TSourceFile(source:TSourceFile, sourcePath:String)
  1136. Local path:String = StripDir(sourcePath) + opt_configmung + processor.CPU()
  1137. If opt_standalone Then
  1138. path :+ ".incbin.c"
  1139. Else
  1140. path :+ ".incbin2.c"
  1141. End If
  1142. Local ib:TSourceFile = GetSourceFile(path)
  1143. If Not ib Then
  1144. ib = New TSourceFile
  1145. ib.path = ExtractDir(sourcePath) + "/.bmx/" + path
  1146. ib.obj_path = StripExt(ib.path) + ".o"
  1147. ib.ext = "c"
  1148. ib.exti = String(processor.RunCommand("source_type", [ib.ext])).ToInt()
  1149. source.imports.AddLast(".bmx/" + StripDir(path) )
  1150. End If
  1151. GetIncBinFileList(ib)
  1152. ib.time = FileTime(ib.path)
  1153. ib.obj_time = FileTime(ib.obj_path)
  1154. sources.Insert(ib.path, ib)
  1155. If opt_standalone And opt_boot Then
  1156. processor.PushSource(ib.path)
  1157. End If
  1158. Return ib
  1159. End Method
  1160. Method GetIncBinFileList(source:TSourceFile)
  1161. Local stream:TStream = ReadStream(source.path)
  1162. If stream Then
  1163. While Not stream.Eof()
  1164. Local line:String = stream.ReadLine()
  1165. If line.StartsWith("// FILE : ") Then
  1166. Local parts:String[] = line[10..].Split("~t")
  1167. Local ib:String = parts[0].Replace("~q", "")
  1168. If ib Then
  1169. source.incbins.AddLast(ib)
  1170. If parts.length = 2 Then
  1171. source.hashes.Insert(ib, parts[1])
  1172. End If
  1173. End If
  1174. Else If line.StartsWith("// ----") Then
  1175. Exit
  1176. EndIf
  1177. Wend
  1178. stream.Close()
  1179. End If
  1180. End Method
  1181. Method IncbinsDifference:Int(ib1:TList, ib2:TList)
  1182. If ib1.Count() <> ib2.Count() Then
  1183. Return True
  1184. End If
  1185. For Local ib:String = EachIn ib1
  1186. If Not ib2.Contains(ib) Then
  1187. Return True
  1188. End If
  1189. Next
  1190. For Local ib:String = EachIn ib2
  1191. If Not ib1.Contains(ib) Then
  1192. Return True
  1193. End If
  1194. Next
  1195. Return False
  1196. End Method
  1197. Method IncbinsHashDifference:Int(source:TSourceFile, ib:TSourceFile)
  1198. If source.hashes.IsEmpty() Then
  1199. Return True
  1200. End If
  1201. For Local file:String = EachIn source.hashes.Keys()
  1202. Local sourceHash:String = String(source.hashes.ValueForKey(file))
  1203. If sourceHash <> String(ib.hashes.ValueForKey(file)) Then
  1204. Return True
  1205. End If
  1206. Next
  1207. For Local file:String = EachIn ib.hashes.Keys()
  1208. Local ibHash:String = String(ib.hashes.ValueForKey(file))
  1209. If ibHash <> String(source.hashes.ValueForKey(file)) Then
  1210. Return True
  1211. End If
  1212. Next
  1213. End Method
  1214. Method CreateLinkStage:TSourceFile(source:TSourceFile, stage:Int = STAGE_LINK)
  1215. Local link:TSourceFile = New TSourceFile
  1216. source.CopyInfo(link)
  1217. link.deps.Insert(StripExt(link.obj_path) + ".c", source)
  1218. link.stage = stage
  1219. link.processed = True
  1220. link.depsList = New TList
  1221. link.depsList.AddLast(source)
  1222. If IOS_HAS_MERGE And processor.Platform() = "ios" Then
  1223. sources.Insert(link.obj_path, link)
  1224. Else
  1225. sources.Insert(link.arc_path, link)
  1226. End If
  1227. Return link
  1228. End Method
  1229. Method CreateMergeStage:TSourceFile(source:TSourceFile)
  1230. Local merge:TSourceFile = New TSourceFile
  1231. source.CopyInfo(merge)
  1232. merge.deps.Insert(merge.obj_path, source)
  1233. merge.stage = STAGE_MERGE
  1234. merge.processed = True
  1235. merge.depsList = New TList
  1236. merge.depsList.AddLast(source)
  1237. sources.Insert(merge.merge_path, merge)
  1238. Return merge
  1239. End Method
  1240. Method CalculateBatches:TList(files:TList)
  1241. Local batches:TList = New TList
  1242. Local count:Int
  1243. Local instances:TMap = New TMap
  1244. For Local m:TSourceFile = EachIn files
  1245. instances.Insert(m.GetSourcePath(), m)
  1246. count :+ 1
  1247. Next
  1248. Local dependencies:TMap = New TMap
  1249. For Local m:TSourceFile = EachIn files
  1250. dependencies.Insert(m.GetSourcePath(), m.deps)
  1251. Next
  1252. Local pct:Float = 100.0 / count
  1253. Local total:Float
  1254. Local num:Int
  1255. While Not dependencies.IsEmpty()
  1256. Local noDeps:TList = New TList
  1257. For Local depName:String = EachIn dependencies.Keys()
  1258. Local dep:TMap = TMap(dependencies.ValueForKey(depName))
  1259. If dep.IsEmpty() Then
  1260. noDeps.AddLast(depName)
  1261. End If
  1262. Next
  1263. If noDeps.IsEmpty() Then
  1264. ' circular dependency!
  1265. ' TODO : dump current list for user to work out?
  1266. Print "REMAINING :"
  1267. For Local depName:String = EachIn dependencies.Keys()
  1268. Print " " + depName
  1269. Next
  1270. Throw "circular dependency!"
  1271. End If
  1272. ' remove from dependencies
  1273. For Local name:String = EachIn noDeps
  1274. dependencies.Remove(name)
  1275. Next
  1276. For Local dep:TMap = EachIn dependencies.Values()
  1277. For Local name:String = EachIn noDeps
  1278. dep.Remove(name)
  1279. Next
  1280. Next
  1281. Local list:TList = New TList
  1282. For Local name:String = EachIn noDeps
  1283. Local m:TSourceFile = TSourceFile(instances.ValueForKey(name))
  1284. list.AddLast(m)
  1285. Next
  1286. batches.AddLast(list)
  1287. Wend
  1288. ' post process batches
  1289. Local suffix:String[]
  1290. Local stage:Int
  1291. For Local i:Int = 0 Until 3
  1292. Select i
  1293. Case 0
  1294. suffix = ["c", "cpp", "cc", "cxx", "m", "mm"]
  1295. Case 1
  1296. suffix = ["o"]
  1297. stage = STAGE_LINK
  1298. Case 2
  1299. suffix = ["o"]
  1300. stage = STAGE_APP_LINK
  1301. End Select
  1302. Local newList:TList = New TList
  1303. For Local list:TList = EachIn batches
  1304. For Local f:TSourceFile = EachIn list
  1305. Local p:String = f.GetSourcePath()
  1306. If Not p.EndsWith("bmx") Then
  1307. For Local s:String = EachIn suffix
  1308. If p.EndsWith(s) Then
  1309. If app_iface And stage Then
  1310. If (stage = STAGE_LINK And app_iface = f.iface_path) Or (stage = STAGE_APP_LINK And app_iface <> f.iface_path) Then
  1311. Continue
  1312. End If
  1313. End If
  1314. newList.AddLast(f)
  1315. list.Remove(f)
  1316. If list.IsEmpty() Then
  1317. batches.Remove(list)
  1318. End If
  1319. ' found, no need to loop further
  1320. Exit
  1321. End If
  1322. Next
  1323. End If
  1324. Next
  1325. Next
  1326. If Not newList.IsEmpty() Then
  1327. batches.AddLast(newList)
  1328. End If
  1329. Next
  1330. For Local list:TList = EachIn batches
  1331. For Local m:TSourceFile = EachIn list
  1332. total :+ pct
  1333. num :+ 1
  1334. If num = count Then
  1335. m.pct = 100
  1336. Else
  1337. m.pct = total
  1338. End If
  1339. Next
  1340. Next
  1341. Return batches
  1342. End Method
  1343. Method ShowPct:String(pct:Int)
  1344. Local s:String = "["
  1345. Local p:String = String.FromInt(pct)
  1346. Select p.length
  1347. Case 1
  1348. s :+ " "
  1349. Case 2
  1350. s :+ " "
  1351. End Select
  1352. Return s + p + "%] "
  1353. End Method
  1354. Method FixPct:String(pct:String)
  1355. If processor.Platform() = "win32" Then
  1356. Return pct.Replace("%", "%%")
  1357. Else
  1358. Return pct
  1359. End If
  1360. End Method
  1361. Method CheckPath:String(basePath:String, path:String)
  1362. Local p:String = RealPath(basePath + "/" + path)
  1363. If Not FileType(p) Then
  1364. ' maybe path is a full path already?
  1365. p = RealPath(path)
  1366. If Not FileType(p) Then
  1367. ' meh... fallback to original
  1368. p = RealPath(basePath + "/" + path)
  1369. End If
  1370. End If
  1371. Return p
  1372. End Method
  1373. Method DoCallback(src:String)
  1374. Local update:Int = True
  1375. Local m:TSourceFile = TSourceFile(sources.ValueForKey(src))
  1376. If m Then
  1377. If FileType(m.iface_path) = FILETYPE_FILE Then
  1378. ' has the interface/api changed since the last build?
  1379. If FileType(m.iface_path2) = FILETYPE_FILE And m.time = FileTime( m.path ) Then
  1380. If FileSize(m.iface_path) = FileSize(m.iface_path2) Then
  1381. Local i_bytes:Byte[] = LoadByteArray(m.iface_path)
  1382. Local i_bytes2:Byte[] = LoadByteArray(m.iface_path2)
  1383. ?bmxng
  1384. If i_bytes.length = i_bytes2.length And memcmp_( i_bytes, i_bytes2, Size_T(i_bytes.length) )=0 Then
  1385. ?Not bmxng
  1386. If i_bytes.length = i_bytes2.length And memcmp_( i_bytes, i_bytes2, i_bytes.length )=0 Then
  1387. ?
  1388. update = False
  1389. End If
  1390. End If
  1391. End If
  1392. If update Then
  1393. CopyFile m.iface_path, m.iface_path2
  1394. Else If m.iface_time < m.MaxIfaceTime() Then
  1395. SetFileTimeNow(m.iface_path2)
  1396. m.iface_time = time_(Null)
  1397. m.maxIfaceTimeCache = -1
  1398. End If
  1399. End If
  1400. If update Then
  1401. m.SetRequiresBuild(True)
  1402. m.iface_time = time_(Null)
  1403. m.maxIfaceTimeCache = -1
  1404. m.gen_time = time_(Null)
  1405. End If
  1406. End If
  1407. End Method
  1408. End Type
  1409. Type TArcTask
  1410. Field m:TSourceFile
  1411. Field path:String
  1412. Field oobjs:TList
  1413. Method Create:TArcTask(m:TSourceFile, path$ , oobjs:TList )
  1414. Self.m = m
  1415. Self.path = path
  1416. Self.oobjs = oobjs
  1417. Return Self
  1418. End Method
  1419. Function _CreateArc:Object(data:Object)
  1420. Return TArcTask(data).CreateArc()
  1421. End Function
  1422. Method CreateArc:Object()
  1423. DeleteFile path
  1424. Local cmd$,t$
  1425. If processor.Platform() = "win32"
  1426. For t$=EachIn oobjs
  1427. If Len(cmd)+Len(t)>1000
  1428. If opt_standalone And Not opt_nolog processor.PushLog(cmd)
  1429. If processor.Sys( cmd )
  1430. DeleteFile path
  1431. Throw "Build Error: Failed to create archive "+path
  1432. EndIf
  1433. cmd=""
  1434. EndIf
  1435. If Not cmd cmd= processor.Option("path_to_ar", processor.MinGWBinPath() + "/ar.exe") + " -r "+CQuote(path)
  1436. cmd:+" "+CQuote(t)
  1437. Next
  1438. End If
  1439. If processor.Platform() = "macos" Or processor.Platform() = "osx" Then
  1440. cmd=processor.Option(processor.BuildName("libtool"), "libtool") + " -o "+CQuote(path)
  1441. For Local t$=EachIn oobjs
  1442. cmd:+" "+CQuote(t)
  1443. Next
  1444. End If
  1445. If processor.Platform() = "ios" Then
  1446. Local proc:String = processor.CPU()
  1447. Select proc
  1448. Case "x86"
  1449. proc = "i386"
  1450. Case "x64"
  1451. proc = "x86_64"
  1452. End Select
  1453. cmd= processor.Option(processor.BuildName("libtool"), "libtool") + " -static -arch_only " + proc + " -o "+CQuote(path)
  1454. For Local t$=EachIn oobjs
  1455. cmd:+" "+CQuote(t)
  1456. Next
  1457. End If
  1458. If processor.Platform() = "linux" Or processor.Platform() = "raspberrypi" Or processor.Platform() = "android" Or processor.Platform() = "emscripten" Or processor.Platform() = "nx"
  1459. For Local t$=EachIn oobjs
  1460. If Len(cmd)+Len(t)>1000
  1461. If opt_standalone And Not opt_nolog processor.PushLog(cmd)
  1462. If processor.Sys( cmd )
  1463. DeleteFile path
  1464. Throw "Build Error: Failed to create archive "+path
  1465. EndIf
  1466. cmd=""
  1467. EndIf
  1468. If processor.Platform() = "emscripten" Then
  1469. If Not cmd cmd=processor.Option(processor.BuildName("ar"), "emar") + " r "+CQuote(path)
  1470. Else
  1471. If Not cmd cmd=processor.Option(processor.BuildName("ar"), "ar") + " -r "+CQuote(path)
  1472. End If
  1473. cmd:+" "+CQuote(t)
  1474. Next
  1475. End If
  1476. If cmd
  1477. If opt_standalone And Not opt_nolog processor.PushLog(cmd)
  1478. If processor.Sys( cmd )
  1479. DeleteFile path
  1480. Throw "Build Error: Failed to create archive "+path
  1481. End If
  1482. EndIf
  1483. m.arc_time = time_(Null)
  1484. m.obj_time = time_(Null)
  1485. End Method
  1486. End Type