bmk_make.bmx 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915
  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." + processor.CPU() + ".sysroot", path)
  180. globals.SetVar("ios." + processor.CPU() + ".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." + processor.CPU() + ".sysroot", path)
  184. globals.SetVar("ios." + processor.CPU() + ".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 And Not opt_gdbdebug 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. If opt_coverage Then
  297. cc_opts :+ " -DBMX_COVERAGE"
  298. End If
  299. End If
  300. Local sb:TStringBuffer = New TStringBuffer
  301. sb.Append(" -g ").Append(processor.CPU())
  302. If opt_quiet sb.Append(" -q")
  303. If opt_verbose sb.Append(" -v")
  304. If opt_release sb.Append(" -r")
  305. If opt_threaded sb.Append(" -h")
  306. If opt_framework sb.Append(" -f ").Append(opt_framework)
  307. If processor.BCCVersion() <> "BlitzMax" Then
  308. If opt_gdbdebug Then
  309. sb.Append(" -d")
  310. End If
  311. If Not opt_nostrictupgrade Then
  312. sb.Append(" -s")
  313. End If
  314. If opt_warnover Then
  315. sb.Append(" -w")
  316. End If
  317. If opt_musl Then
  318. sb.Append(" -musl")
  319. End If
  320. If makelib Then
  321. sb.Append(" -makelib")
  322. If opt_nodef Then
  323. sb.append(" -nodef")
  324. End If
  325. If opt_nohead Then
  326. sb.append(" -nohead")
  327. End If
  328. End If
  329. If opt_require_override Then
  330. sb.Append(" -override")
  331. If opt_override_error Then
  332. sb.Append(" -overerr")
  333. End If
  334. End If
  335. Local defs:String = opt_userdefs
  336. If globals.Get("user_defs") Then
  337. If defs Then
  338. defs :+ ","
  339. End If
  340. defs :+ globals.Get("user_defs")
  341. End If
  342. If defs Then
  343. sb.Append(" -ud ").Append(defs)
  344. End If
  345. If opt_standalone Then
  346. sb.Append(" -ib")
  347. End If
  348. If opt_coverage Then
  349. sb.Append(" -cov")
  350. End If
  351. End If
  352. source.cc_opts :+ cc_opts
  353. source.cpp_opts :+ cpp_opts
  354. source.c_opts :+ c_opts
  355. source.modimports.AddLast("brl.blitz")
  356. source.modimports.AddLast(opt_appstub)
  357. If source.framewk
  358. If opt_framework Then
  359. Throw "Framework already specified on commandline"
  360. End If
  361. opt_framework = source.framewk
  362. sb.Append(" -f ").Append(opt_framework)
  363. source.modimports.AddLast(opt_framework)
  364. Else
  365. framework_mods = New TList
  366. For Local t:String = EachIn EnumModules()
  367. If t.Find("brl.") = 0 Or t.Find("pub.") = 0 Then
  368. If t <> "brl.blitz" And t <> opt_appstub Then
  369. source.modimports.AddLast(t)
  370. framework_mods.AddLast(t)
  371. End If
  372. End If
  373. Next
  374. End If
  375. source.bcc_opts = sb.ToString()
  376. source.SetRequiresBuild(opt_all)
  377. CalculateDependencies(source, False, opt_all)
  378. source.bcc_opts :+ " -t " + opt_apptype
  379. ' create bmx stages :
  380. Local gen:TSourceFile
  381. ' for osx x86 on legacy, we need to convert asm
  382. If processor.BCCVersion() = "BlitzMax" And processor.CPU() = "x86" And processor.Platform() = "macos" Then
  383. Local fasm2as:TSourceFile = CreateFasm2AsStage(source)
  384. gen = CreateGenStage(fasm2as)
  385. Else
  386. gen = CreateGenStage(source)
  387. End If
  388. If Not compileOnly Then
  389. Local link:TSourceFile = CreateLinkStage(gen, STAGE_APP_LINK)
  390. End If
  391. End Method
  392. Method DoBuild(makelib:Int, app_build:Int = False)
  393. Local arc_order:TList = New TList
  394. Local files:TList = New TList
  395. For Local file:TSourceFile = EachIn sources.Values()
  396. files.AddLast(file)
  397. Next
  398. ' get the list of parallelizable batches
  399. ' each list of batches has no outstanding dependencies, and therefore
  400. ' can be compiled in parallel.
  401. ' the last list of batches requires all previous lists to have
  402. ' been compiled.
  403. Local batches:TList = CalculateBatches(files)
  404. For Local batch:TList = EachIn batches
  405. Local s:String
  406. For Local m:TSourceFile = EachIn batch
  407. ' sort archives for app linkage
  408. If m.modid Then
  409. Local path:String = m.arc_path
  410. If IOS_HAS_MERGE And processor.Platform() = "ios" Then
  411. path = m.merge_path
  412. End If
  413. If Not arc_order.Contains(path) Then
  414. arc_order.AddFirst(path)
  415. End If
  416. End If
  417. Local build_path:String
  418. If m.obj_path Then
  419. build_path = ExtractDir(m.obj_path)
  420. Else
  421. build_path = ExtractDir(m.path) + "/.bmx"
  422. End If
  423. If Not FileType(build_path) Then
  424. CreateDir build_path
  425. End If
  426. If FileType(build_path) <> FILETYPE_DIR Then
  427. Throw "Unable to create temporary directory : " + build_path
  428. End If
  429. ' change dir, so relative commands work as expected
  430. ' (eg. file processing in BMK-scripts called via pragma)
  431. ChangeDir ExtractDir( m.path )
  432. ' bmx file
  433. If Match(m.ext, "bmx") Then
  434. Select m.stage
  435. Case STAGE_GENERATE
  436. If m.requiresBuild Or (m.time > m.gen_time Or m.iface_time < m.MaxIfaceTime() Or Not m.MaxIfaceTime()) Then
  437. If Not opt_quiet Then
  438. Print ShowPct(m.pct) + "Processing:" + StripDir(m.path)
  439. End If
  440. ' process pragmas
  441. Local pragma_inDefine:Int, pragma_text:String, pragma_name:String
  442. For Local pragma:String = EachIn m.pragmas
  443. processor.ProcessPragma(pragma, pragma_inDefine, pragma_text, pragma_name)
  444. Next
  445. CompileBMX m.path, m.obj_path, m.bcc_opts
  446. End If
  447. Case STAGE_FASM2AS
  448. For Local s:TSourceFile = EachIn m.depsList
  449. If s.requiresBuild Then
  450. m.SetRequiresBuild(True)
  451. Exit
  452. End If
  453. Next
  454. If m.requiresBuild Or (m.time > m.obj_time Or m.iface_time < m.MaxIfaceTime()) Then
  455. m.SetRequiresBuild(True)
  456. If Not opt_quiet Then
  457. Print ShowPct(m.pct) + "Converting:" + StripDir(StripExt(m.obj_path) + ".s")
  458. End If
  459. Fasm2As m.path, m.obj_path
  460. m.asm_time = time_(Null)
  461. End If
  462. Case STAGE_OBJECT
  463. If m.requiresBuild Or (m.time > m.obj_time Or m.iface_time < m.MaxIfaceTime()) Then
  464. m.SetRequiresBuild(True)
  465. If processor.BCCVersion() <> "BlitzMax" Then
  466. Local csrc_path:String = StripExt(m.obj_path) + ".c"
  467. Local cobj_path:String = StripExt(m.obj_path) + ".o"
  468. If Not opt_quiet Then
  469. Local s:String = ShowPct(m.pct) + "Compiling:" + StripDir(csrc_path)
  470. If opt_standalone And Not opt_nolog processor.PushEcho(FixPct(s))
  471. Print s
  472. End If
  473. If opt_standalone And opt_boot Then
  474. processor.PushSource(csrc_path)
  475. processor.PushSource(StripExt(m.obj_path) + ".h")
  476. End If
  477. CompileC csrc_path,cobj_path, m.GetIncludePaths() + " " + m.cc_opts + " " + m.c_opts
  478. Else
  479. ' asm compilation
  480. Local src_path:String = StripExt(m.obj_path) + ".s"
  481. Local obj_path:String = StripExt(m.obj_path) + ".o"
  482. If Not opt_quiet Then
  483. Print ShowPct(m.pct) + "Compiling:" + StripDir(src_path)
  484. End If
  485. Assemble src_path, obj_path
  486. End If
  487. m.obj_time = time_(Null)
  488. End If
  489. Case STAGE_LINK
  490. Local max_obj_time:Int = m.MaxObjTime()
  491. If max_obj_time > m.arc_time And Not m.dontbuild Then
  492. Local objs:TList = New TList
  493. m.GetObjs(objs)
  494. If Not opt_quiet Then
  495. Local s:String = ShowPct(m.pct) + "Archiving:" + StripDir(m.arc_path)
  496. If opt_standalone And Not opt_nolog processor.PushEcho(FixPct(s))
  497. Print s
  498. End If
  499. Local at:TArcTask = New TArcTask.Create(m, m.arc_path, objs)
  500. ?threaded
  501. If opt_single Then
  502. at.CreateArc()
  503. Else
  504. processManager.AddTask(TArcTask._CreateArc, at)
  505. End If
  506. ?Not threaded
  507. at.CreateArc()
  508. ?
  509. End If
  510. Case STAGE_APP_LINK
  511. ' this probably should never happen.
  512. ' may be a bad module?
  513. If Not opt_outfile Then
  514. Throw "Build Error: Did not expect to link against " + m.path
  515. End If
  516. ' an app!
  517. Local max_lnk_time:Int = m.MaxLinkTime()
  518. ' include settings and icon times in calculation
  519. If opt_manifest And processor.Platform() = "win32" And opt_apptype="gui" Then
  520. Local settings:String = ExtractDir(opt_infile) + "/" + StripDir(StripExt(opt_outfile)) + ".settings"
  521. If Not FileType(settings) Then
  522. settings = ExtractDir(opt_infile) + "/" + StripDir(StripExt(opt_infile)) + ".settings"
  523. End If
  524. max_lnk_time = Max(FileTime(settings), max_lnk_time)
  525. Local icon:String = ExtractDir(opt_infile) + "/" + StripDir(StripExt(opt_outfile)) + ".ico"
  526. If Not FileType(icon) Then
  527. icon = ExtractDir(opt_infile) + "/" + StripDir(StripExt(opt_infile)) + ".ico"
  528. End If
  529. max_lnk_time = Max(FileTime(icon), max_lnk_time)
  530. End If
  531. If max_lnk_time > FileTime(opt_outfile) Or opt_all Then
  532. ' generate manifest for app
  533. If opt_manifest And processor.Platform() = "win32" And opt_apptype="gui" Then
  534. processor.RunCommand("make_win32_resource", Null)
  535. Local res:String = ExtractDir(opt_infile) + "/.bmx/" + StripDir(StripExt(opt_outfile)) + "." + processor.CPU() + ".res.o"
  536. If Not FileType(res) Then
  537. res = ExtractDir(opt_infile) + "/.bmx/" + StripDir(StripExt(opt_infile)) + "." + processor.CPU() + ".res.o"
  538. End If
  539. If FileType(res) = FILETYPE_FILE Then
  540. Local s:TSourceFile = New TSourceFile
  541. s.obj_path = res
  542. s.stage = STAGE_LINK
  543. s.exti = SOURCE_RES
  544. m.depslist.AddLast(s)
  545. End If
  546. End If
  547. If Not opt_quiet Then
  548. Local s:String = ShowPct(m.pct) + "Linking:" + StripDir(opt_outfile)
  549. If opt_standalone And Not opt_nolog processor.PushEcho(FixPct(s))
  550. Print s
  551. End If
  552. Local links:TList = New TList
  553. Local opts:TList = New TList
  554. m.GetLinks(links, opts)
  555. For Local arc:String = EachIn arc_order
  556. links.AddLast(arc)
  557. Next
  558. For Local o:String = EachIn opts
  559. links.AddLast(o)
  560. Next
  561. LinkApp opt_outfile, links, makelib, globals.Get("ld_opts")
  562. m.obj_time = time_(Null)
  563. End If
  564. Case STAGE_MERGE
  565. If IOS_HAS_MERGE Then
  566. ' a module?
  567. If m.modid Then
  568. Local max_obj_time:Int = m.MaxObjTime()
  569. If max_obj_time > m.merge_time And Not m.dontbuild Then
  570. If Not opt_quiet Then
  571. Print ShowPct(m.pct) + "Merging:" + StripDir(m.merge_path)
  572. End If
  573. CreateMergeArc m.merge_path, m.arc_path
  574. m.merge_time = time_(Null)
  575. End If
  576. End If
  577. End If
  578. End Select
  579. Else If Match(m.ext, "s") Then
  580. If m.time > m.obj_time Then ' object is older or doesn't exist
  581. m.SetRequiresBuild(True)
  582. End If
  583. If m.requiresBuild Then
  584. If Not opt_quiet Then
  585. Local s:String = ShowPct(m.pct) + "Compiling:" + StripDir(m.path)
  586. If opt_standalone And Not opt_nolog processor.PushEcho(FixPct(s))
  587. Print s
  588. End If
  589. If processor.BCCVersion() = "BlitzMax" Then
  590. Assemble m.path, m.obj_path
  591. Else
  592. CompileC m.path, m.obj_path, m.GetIncludePaths() + " " + m.cc_opts + " " + m.c_opts
  593. End If
  594. End If
  595. Else
  596. If Not m.dontbuild Then
  597. ' c/c++ source
  598. If m.time > m.obj_time Then ' object is older or doesn't exist
  599. m.SetRequiresBuild(True)
  600. End If
  601. If m.requiresBuild Then
  602. If Not opt_quiet Then
  603. Local s:String = ShowPct(m.pct) + "Compiling:" + StripDir(m.path)
  604. If opt_standalone And Not opt_nolog processor.PushEcho(FixPct(s))
  605. Print s
  606. End If
  607. If m.path.EndsWith(".cpp") Or m.path.EndsWith(".cc") Or m.path.EndsWith(".mm") Or m.path.EndsWith(".cxx") Then
  608. CompileC m.path, m.obj_path, m.GetIncludePaths() + " " + m.cc_opts + " " + m.cpp_opts
  609. ElseIf m.path.EndsWith(".S") Or m.path.EndsWith("asm") Then
  610. AssembleNative m.path, m.obj_path
  611. Else
  612. CompileC m.path, m.obj_path, m.GetIncludePaths() + " " + m.cc_opts + " " + m.c_opts
  613. End If
  614. m.obj_time = time_(Null)
  615. End If
  616. End If
  617. End If
  618. Next
  619. ?threaded
  620. If Not opt_single Then
  621. processManager.WaitForTasks()
  622. End If
  623. ?
  624. Next
  625. If app_build Then
  626. ' global post process
  627. LoadBMK("post.bmk")
  628. ' generic post process
  629. LoadBMK(ExtractDir(app_main) + "/post.bmk")
  630. ' project-specific post process
  631. LoadBMK(ExtractDir(app_main) + "/" + StripDir( opt_outfile ) + ".post.bmk")
  632. Select processor.Platform()
  633. Case "android"
  634. ' create the apk
  635. ' copy shared object
  636. Local androidABI:String = processor.Option("android.abi", "")
  637. Local appId:String = StripDir(StripExt(opt_outfile))
  638. If opt_debug And opt_outfile.EndsWith(".debug") Then
  639. appId :+ ".debug"
  640. End If
  641. Local buildDir:String = ExtractDir(opt_outfile)
  642. Local projectDir:String = buildDir + "/android-project-" + appId
  643. Local abiPath:String = projectDir + "/libs/" + androidABI
  644. Local sharedObject:String = "lib" + appId
  645. sharedObject :+ ".so"
  646. CopyFile(buildDir + "/" + sharedObject, abiPath + "/" + sharedObject)
  647. ' build the apk :
  648. Local antHome:String = processor.Option("ant.home", "").Trim()
  649. Local cmd:String = "~q" + antHome + "/bin/ant"
  650. ?win32
  651. cmd :+ ".bat"
  652. ?
  653. cmd :+ "~q debug"
  654. Local dir:String = CurrentDir()
  655. ChangeDir(projectDir)
  656. If opt_dumpbuild Then
  657. Print cmd
  658. End If
  659. If Sys( cmd ) Then
  660. Throw "Error creating apk"
  661. End If
  662. ChangeDir(dir)
  663. 'End If
  664. Case "ios"
  665. Local iosSimulator:Int = (processor.CPU() = "x86")
  666. ' TODO - other stuff ?
  667. Case "nx"
  668. ' TODO - build nro, nso, psf0 and nacp
  669. End Select
  670. End If
  671. End Method
  672. Method CalculateDependencies(source:TSourceFile, isMod:Int = False, rebuildImports:Int = False, isInclude:Int = False)
  673. If source And Not source.processed Then
  674. source.processed = True
  675. For Local m:String = EachIn source.modimports
  676. Local s:TSourceFile = GetMod(m)
  677. If s Then
  678. If Not source.moddeps Then
  679. source.moddeps = New TMap
  680. End If
  681. If Not source.moddeps.ValueForKey(m) Then
  682. source.moddeps.Insert(m, s)
  683. source.deps.Insert(s.GetSourcePath(), s)
  684. source.AddIncludePath(" -I" + CQuote(ExtractDir(s.path)))
  685. End If
  686. End If
  687. Next
  688. Local ib:TSourceFile
  689. If processor.BCCVersion() <> "BlitzMax" And Not source.incbins.IsEmpty() Then
  690. If source.owner_path Then
  691. ib = CreateIncBin(source, source.owner_path)
  692. Else
  693. ib = CreateIncBin(source, source.path)
  694. End If
  695. End If
  696. For Local f:String = EachIn source.imports
  697. If f[0] <> Asc("-") Then
  698. Local path:String = CheckPath(ExtractDir(source.path), f)
  699. Local s:TSourceFile = GetSourceFile(path, isMod)
  700. ' imported sourcefile not there? Maybe it's relative to the owner path instead?
  701. ' For example, an incbin as part of an included source file.
  702. If Not s Then
  703. Local p:String = CheckPath(ExtractDir(source.owner_path), f)
  704. s = GetSourceFile(p, isMod)
  705. If s Then
  706. path = p
  707. End If
  708. End If
  709. If s Then
  710. If rebuildImports Then
  711. s.SetRequiresBuild(rebuildImports)
  712. End If
  713. If Match(s.ext, "bmx") Then
  714. s.modimports.AddLast("brl.blitz")
  715. ' app source files need framework/mod dependencies applied
  716. If Not isMod Then
  717. If opt_framework Then
  718. ' add framework as dependency
  719. s.modimports.AddLast(opt_framework)
  720. Else
  721. ' add all pub/brl mods as dependency
  722. If framework_mods Then
  723. For Local m:String = EachIn framework_mods
  724. s.modimports.AddLast(m)
  725. Next
  726. End If
  727. End If
  728. End If
  729. s.bcc_opts = source.bcc_opts
  730. s.cc_opts :+ source.cc_opts
  731. s.cpp_opts :+ source.cpp_opts
  732. s.c_opts :+ source.c_opts
  733. s.CopyIncludePaths(source.includePaths)
  734. CalculateDependencies(s, isMod, rebuildImports)
  735. ' if file that we generate is missing, we need to rebuild
  736. If processor.BCCVersion() = "BlitzMax" Then
  737. If Not FileType(StripExt(s.obj_path) + ".s") Then
  738. s.SetRequiresBuild(True)
  739. End If
  740. Else
  741. If Not FileType(StripExt(s.obj_path) + ".c") Then
  742. s.SetRequiresBuild(True)
  743. End If
  744. End If
  745. Local gen:TSourceFile
  746. ' for osx x86 on legacy, we need to convert asm
  747. If processor.BCCVersion() = "BlitzMax" And processor.CPU() = "x86" And processor.Platform() = "macos" Then
  748. Local fasm2as:TSourceFile = CreateFasm2AsStage(s)
  749. gen = CreateGenStage(fasm2as)
  750. Else
  751. gen = CreateGenStage(s)
  752. End If
  753. source.deps.Insert(gen.GetSourcePath(), gen)
  754. If Not source.depsList Then
  755. source.depsList = New TList
  756. End If
  757. source.depsList.AddLast(gen)
  758. Else
  759. s.cc_opts = source.cc_opts
  760. s.cpp_opts = source.cpp_opts
  761. s.c_opts = source.c_opts
  762. s.CopyIncludePaths(source.includePaths)
  763. source.deps.Insert(s.GetSourcePath(), s)
  764. If Not source.depsList Then
  765. source.depsList = New TList
  766. End If
  767. source.depsList.AddLast(s)
  768. End If
  769. Else
  770. Local ext:String = ExtractExt(path)
  771. If Match(ext, "h;hpp;hxx") Then ' header?
  772. source.AddIncludePath(" -I" + CQuote(ExtractDir(path)))
  773. Else If Match(ext, "o;a;lib") Then ' object or archive?
  774. Local s:TSourceFile = New TSourceFile
  775. s.time = FileTime(path)
  776. s.obj_time = s.time
  777. s.path = path
  778. s.obj_path = path
  779. s.modid = source.modid
  780. If s.time > source.time Then
  781. source.time = s.time
  782. End If
  783. If Not source.depsList Then
  784. source.depsList = New TList
  785. End If
  786. source.depsList.AddLast(s)
  787. End If
  788. End If
  789. Else
  790. If Not source.ext_files Then
  791. source.ext_files = New TList
  792. End If
  793. source.ext_files.AddLast(f)
  794. End If
  795. Next
  796. For Local f:String = EachIn source.includes
  797. Local path:String = CheckPath(ExtractDir(source.path), f)
  798. Local s:TSourceFile = GetSourceFile(path, isMod, rebuildImports, True)
  799. If s Then
  800. s.owner_path = source.path
  801. If s.includePaths.IsEmpty() Then
  802. s.CopyIncludePaths(source.includePaths)
  803. End If
  804. ' calculate included file dependencies
  805. CalculateDependencies(s, isMod, rebuildImports)
  806. ' update our time to latest included time
  807. If s.time > source.time Then
  808. source.time = s.time
  809. End If
  810. If Not source.depsList Then
  811. source.depsList = New TList
  812. End If
  813. source.depsList.AddLast(s)
  814. End If
  815. Next
  816. For Local f:String = EachIn source.incbins
  817. Local path:String = CheckPath(ExtractDir(source.path), f)
  818. If FileType(path) = FILETYPE_FILE Then
  819. source.hashes.Insert(f, CalculateFileHash(path))
  820. End If
  821. Local time:Int = FileTime(path)
  822. ' update our time to the latest incbin time
  823. If time > source.time Then
  824. source.time = time
  825. End If
  826. ' update ib time to the latest incbin time
  827. If ib And ib.time And ib.time < time Then
  828. ib.time = time
  829. End If
  830. Next
  831. ' incbin file
  832. If ib Then
  833. Local requiresBuild:Int = False
  834. ' missing source.. generate and compile
  835. If Not ib.time Then
  836. requiresBuild = True
  837. Else If IncbinsDifference(source.incbins, ib.incbins) Then
  838. requiresBuild = True
  839. Else If IncbinsHashDifference(source, ib) Then
  840. requiresBuild = True
  841. End If
  842. If requiresBuild Then
  843. ib.SetRequiresBuild(True)
  844. source.SetRequiresBuild(True)
  845. End If
  846. ' sync timestamps
  847. If ib.time > source.time Then
  848. source.time = ib.time
  849. End If
  850. End If
  851. If source.depsList Then
  852. For Local s:TSourceFile = EachIn source.depsList
  853. If Not Match(s.ext, "bmx") Then
  854. s.cc_opts = source.cc_opts
  855. s.cpp_opts = source.cpp_opts
  856. s.c_opts = source.c_opts
  857. s.CopyIncludePaths(source.includePaths)
  858. End If
  859. Next
  860. End If
  861. End If
  862. End Method
  863. Method GetSourceFile:TSourceFile(source_path:String, isMod:Int = False, rebuild:Int = False, isInclude:Int = False, doCreate:Int = True)
  864. Local source:TSourceFile = TSourceFile(sources.ValueForKey(source_path))
  865. If Not source And doCreate Then
  866. source = ParseSourceFile(source_path)
  867. If source Then
  868. Local ext:String = ExtractExt(source_path)
  869. If Match(ext, ALL_SRC_EXTS) Then
  870. If Not isInclude Then
  871. sources.Insert(source_path, source)
  872. Local sp:String
  873. If app_main = source_path Then
  874. sp = ConcatString(ExtractDir(source_path), "/.bmx/", StripDir(source_path), "." + opt_apptype, opt_configmung, processor.CPU())
  875. Else
  876. sp = ConcatString(ExtractDir(source_path), "/.bmx/", StripDir(source_path), opt_configmung, processor.CPU())
  877. End If
  878. If Match(ext, "bmx") Then
  879. source.obj_path = sp + ".o"
  880. source.obj_time = FileTime(source.obj_path)
  881. source.iface_path = sp + ".i"
  882. source.iface_path2 = source.iface_path + "2"
  883. source.iface_time = FileTime(source.iface_path2)
  884. ' gen file times
  885. If processor.BCCVersion() <> "BlitzMax" Then
  886. Local p:String = sp + ".c"
  887. source.gen_time = FileTime(p)
  888. If source.gen_time Then
  889. p = sp + ".h"
  890. source.gen_time = Min(source.gen_time, FileTime(p))
  891. End If
  892. Else
  893. Local p:String = sp + ".s"
  894. source.gen_time = FileTime(p)
  895. End If
  896. Else
  897. source.obj_path = PPFix(sp) + ".o"
  898. source.obj_time = FileTime(source.obj_path)
  899. End If
  900. Else
  901. source.isInclude = True
  902. End If
  903. End If
  904. End If
  905. End If
  906. Return source
  907. End Method
  908. Method PPFix:String(path:String)
  909. Local dir:String = ExtractDir(ExtractDir(path))
  910. Local s:String
  911. For Local i:Int = 0 Until 3
  912. Local t:String = StripDir(dir)
  913. If Not t Then
  914. t = "x"
  915. End If
  916. s = t[..1] + s
  917. dir = ExtractDir(dir)
  918. Next
  919. Return ExtractDir(path) + "/" + s + "_" + StripDir(path)
  920. End Method
  921. Method GetISourceFile:TSourceFile(arc_path:String, arc_time:Int, iface_path:String, iface_time:Int, merge_path:String, merge_time:Int)
  922. Local source:TSourceFile
  923. If IOS_HAS_MERGE And processor.Platform() = "ios" Then
  924. source = TSourceFile(sources.ValueForKey(merge_path))
  925. Else
  926. source = TSourceFile(sources.ValueForKey(arc_path))
  927. End If
  928. If Not source Then
  929. Local iface_path2:String = iface_path + 2
  930. source = ParseISourceFile(iface_path2)
  931. If source Then
  932. source.arc_path = arc_path
  933. source.arc_time = arc_time
  934. source.iface_path = iface_path
  935. source.iface_path2 = iface_path2
  936. source.iface_time = iface_time
  937. source.merge_time = merge_time
  938. If IOS_HAS_MERGE And processor.Platform() = "ios" Then
  939. sources.Insert(merge_path, source)
  940. Else
  941. sources.Insert(arc_path, source)
  942. End If
  943. End If
  944. End If
  945. Return source
  946. End Method
  947. Method GetMod:TSourceFile(m:String, rebuild:Int = False)
  948. 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
  949. rebuild = True
  950. End If
  951. Local path:String = ModulePath(m)
  952. Local id:String = ModuleIdent(m)
  953. Local mp:String = ConcatString(path, "/", id, opt_configmung, processor.CPU())
  954. ' get the module interface and lib details
  955. Local arc_path:String = mp + ".a"
  956. Local arc_time:Int = FileTime(arc_path)
  957. Local iface_path:String = mp + ".i"
  958. Local iface_path2:String = iface_path + "2"
  959. Local iface_time:Int = FileTime(iface_path2)
  960. Local merge_path:String
  961. Local merge_time:Int
  962. If IOS_HAS_MERGE And processor.Platform() = "ios" Then
  963. If processor.CPU() = "x86" Or processor.CPU() = "x64" Then
  964. merge_path = ConcatString(path, "/", id, opt_configmung, "sim.a")
  965. Else
  966. merge_path = ConcatString(path, "/", id, opt_configmung, "dev.a")
  967. End If
  968. merge_time = FileTime(merge_path)
  969. End If
  970. Local source:TSourceFile
  971. Local link:TSourceFile
  972. ' do a quick scan only when building apps. For module builds we want to check required modules.
  973. If arc_time And iface_time And opt_quickscan And app_main Then
  974. source = GetISourceFile(arc_path, arc_time, iface_path, iface_time, merge_path, merge_time)
  975. If Not source Then
  976. Return Null
  977. End If
  978. If Not source.processed Then
  979. source.modid = m
  980. source.arc_path = arc_path
  981. source.arc_time = arc_time
  982. source.iface_path = iface_path
  983. source.iface_path2 = iface_path2
  984. source.iface_time = iface_time
  985. source.obj_path = arc_path
  986. source.merge_path = merge_path
  987. source.merge_time = merge_time
  988. CalculateDependencies(source, True, rebuild)
  989. source.dontbuild = True
  990. If IOS_HAS_MERGE And processor.Platform() = "ios" Then
  991. source.stage = STAGE_MERGE
  992. sources.Insert(source.merge_path, source)
  993. Else
  994. source.stage = STAGE_LINK
  995. sources.Insert(source.arc_path, source)
  996. End If
  997. End If
  998. link = source
  999. Else
  1000. Local src_path:String = ConcatString(path, "/", id, ".bmx")
  1001. source = GetSourceFile(src_path, True, rebuild)
  1002. If Not source Then
  1003. Return Null
  1004. End If
  1005. ' main module file without "Module" line?
  1006. If Not source.modid Then
  1007. Return Null
  1008. End If
  1009. End If
  1010. If Not source.processed Then
  1011. source.arc_path = arc_path
  1012. source.arc_time = arc_time
  1013. source.iface_path = iface_path
  1014. source.iface_path2 = iface_path2
  1015. source.iface_time = iface_time
  1016. source.merge_path = merge_path
  1017. source.merge_time = merge_time
  1018. Local cc_opts:String
  1019. source.AddIncludePath(" -I" + CQuote(path))
  1020. source.AddIncludePath(" -I" + CQuote(ModulePath("")))
  1021. If opt_release And Not opt_gdbdebug Then
  1022. cc_opts :+ " -DNDEBUG"
  1023. End If
  1024. If opt_threaded Then
  1025. cc_opts :+ " -DTHREADED"
  1026. End If
  1027. If processor.BCCVersion() <> "BlitzMax" Then
  1028. If opt_gdbdebug Then
  1029. cc_opts :+ " -g"
  1030. End If
  1031. If opt_gprof Then
  1032. cc_opts :+ " -pg"
  1033. End If
  1034. If opt_coverage Then
  1035. cc_opts :+ " -DBMX_COVERAGE"
  1036. End If
  1037. End If
  1038. source.cc_opts = ""
  1039. If source.mod_opts Then
  1040. source.cc_opts :+ source.mod_opts.cc_opts
  1041. source.cpp_opts :+ source.mod_opts.cpp_opts
  1042. source.c_opts :+ source.mod_opts.c_opts
  1043. End If
  1044. source.cc_opts :+ cc_opts
  1045. source.cpp_opts :+ cpp_opts
  1046. source.c_opts :+ c_opts
  1047. ' Module BCC opts
  1048. Local sb:TStringBuffer = New TStringBuffer
  1049. sb.Append(" -g ").Append(processor.CPU())
  1050. sb.Append(" -m ").Append(m)
  1051. If opt_quiet sb.Append(" -q")
  1052. If opt_verbose sb.Append(" -v")
  1053. If opt_release sb.Append(" -r")
  1054. If opt_threaded sb.Append(" -h")
  1055. If processor.BCCVersion() <> "BlitzMax" Then
  1056. If opt_gdbdebug Then
  1057. sb.Append(" -d")
  1058. End If
  1059. If Not opt_nostrictupgrade Then
  1060. sb.Append(" -s")
  1061. End If
  1062. If opt_warnover Then
  1063. sb.Append(" -w")
  1064. End If
  1065. If opt_musl Then
  1066. sb.Append(" -musl")
  1067. End If
  1068. If opt_require_override Then
  1069. sb.Append(" -override")
  1070. If opt_override_error Then
  1071. sb.Append(" -overerr")
  1072. End If
  1073. End If
  1074. Local defs:String = opt_userdefs
  1075. If globals.Get("user_defs") Then
  1076. If defs Then
  1077. defs :+ ","
  1078. End If
  1079. defs :+ globals.Get("user_defs")
  1080. End If
  1081. If defs Then
  1082. sb.Append(" -ud ").Append(defs)
  1083. End If
  1084. If opt_standalone Then
  1085. sb.Append(" -ib")
  1086. End If
  1087. If opt_coverage Then
  1088. sb.Append(" -cov")
  1089. End If
  1090. End If
  1091. source.bcc_opts = sb.ToString()
  1092. source.SetRequiresBuild(rebuild)
  1093. ' interface is REQUIRED for compilation
  1094. If Not iface_time Then
  1095. source.SetRequiresBuild(True)
  1096. End If
  1097. If m <> "brl.blitz" Then
  1098. source.modimports.AddLast("brl.blitz")
  1099. End If
  1100. CalculateDependencies(source, True, rebuild)
  1101. ' create bmx stages :
  1102. Local gen:TSourceFile
  1103. ' for osx x86 on legacy, we need to convert asm
  1104. If processor.BCCVersion() = "BlitzMax" And processor.CPU() = "x86" And processor.Platform() = "macos" Then
  1105. Local fasm2as:TSourceFile = CreateFasm2AsStage(source)
  1106. gen = CreateGenStage(fasm2as)
  1107. Else
  1108. gen = CreateGenStage(source)
  1109. End If
  1110. If processor.Platform() <> "ios" Then
  1111. link = CreateLinkStage(gen)
  1112. Else
  1113. If IOS_HAS_MERGE Then
  1114. Local realLink:TSourceFile = CreateLinkStage(gen)
  1115. ' create a fat archive
  1116. link = CreateMergeStage(realLink)
  1117. Else
  1118. link = CreateLinkStage(gen)
  1119. End If
  1120. End If
  1121. Else
  1122. If IOS_HAS_MERGE And processor.Platform() = "ios" Then
  1123. link = TSourceFile(sources.ValueForKey(source.merge_path))
  1124. Else
  1125. link = TSourceFile(sources.ValueForKey(source.arc_path))
  1126. End If
  1127. If Not link Then
  1128. Throw "Can't find link for : " + source.path
  1129. End If
  1130. End If
  1131. Return link
  1132. End Method
  1133. Method CreateFasm2AsStage:TSourceFile(source:TSourceFile)
  1134. Local fasm:TSourceFile = New TSourceFile
  1135. source.CopyInfo(fasm)
  1136. fasm.deps.Insert(source.path, source)
  1137. fasm.stage = STAGE_FASM2AS
  1138. fasm.processed = True
  1139. fasm.depsList = New TList
  1140. fasm.depsList.AddLast(source)
  1141. sources.Insert(StripExt(fasm.obj_path) + ".s", fasm)
  1142. Return fasm
  1143. End Method
  1144. Method CreateGenStage:TSourceFile(source:TSourceFile)
  1145. Local gen:TSourceFile = New TSourceFile
  1146. source.CopyInfo(gen)
  1147. If processor.BCCVersion() = "BlitzMax" And processor.CPU() = "x86" And processor.Platform() = "macos" Then
  1148. gen.deps.Insert(StripExt(source.obj_path) + ".s", source)
  1149. Else
  1150. gen.deps.Insert(source.path, source)
  1151. End If
  1152. gen.stage = STAGE_OBJECT
  1153. gen.processed = True
  1154. gen.depsList = New TList
  1155. gen.depsList.AddLast(source)
  1156. sources.Insert(StripExt(gen.obj_path) + ".c", gen)
  1157. Return gen
  1158. End Method
  1159. Method CreateIncBin:TSourceFile(source:TSourceFile, sourcePath:String)
  1160. Local path:String = StripDir(sourcePath) + opt_configmung + processor.CPU()
  1161. If opt_standalone Or (processor.CPU() = "x86" And processor.Platform() = "win32") Then
  1162. path :+ ".incbin.c"
  1163. Else
  1164. path :+ ".incbin2.c"
  1165. End If
  1166. Local ibPath:String = ExtractDir(sourcePath) + "/.bmx/" + path
  1167. Local ib:TSourceFile = GetSourceFile(ibPath,,,,False)
  1168. If Not ib Then
  1169. ib = New TSourceFile
  1170. ib.path = ibPath
  1171. ib.obj_path = StripExt(ib.path) + ".o"
  1172. ib.ext = "c"
  1173. ib.exti = String(processor.RunCommand("source_type", [ib.ext])).ToInt()
  1174. source.imports.AddLast(".bmx/" + StripDir(path) )
  1175. End If
  1176. If ib.includePaths.IsEmpty() Then
  1177. ib.CopyIncludePaths(source.includePaths)
  1178. End If
  1179. GetIncBinFileList(ib)
  1180. ib.time = FileTime(ib.path)
  1181. ib.obj_time = FileTime(ib.obj_path)
  1182. sources.Insert(ib.path, ib)
  1183. If opt_standalone And opt_boot Then
  1184. processor.PushSource(ib.path)
  1185. End If
  1186. Return ib
  1187. End Method
  1188. Method GetIncBinFileList(source:TSourceFile)
  1189. Local stream:TStream = ReadStream(source.path)
  1190. If stream Then
  1191. While Not stream.Eof()
  1192. Local line:String = stream.ReadLine()
  1193. If line.StartsWith("// FILE : ") Then
  1194. Local parts:String[] = line[10..].Split("~t")
  1195. Local ib:String = parts[0].Replace("~q", "")
  1196. If ib Then
  1197. source.incbins.AddLast(ib)
  1198. If parts.length = 2 Then
  1199. source.hashes.Insert(ib, parts[1])
  1200. End If
  1201. End If
  1202. Else If line.StartsWith("// ----") Then
  1203. Exit
  1204. EndIf
  1205. Wend
  1206. stream.Close()
  1207. End If
  1208. End Method
  1209. Method IncbinsDifference:Int(ib1:TList, ib2:TList)
  1210. If ib1.Count() <> ib2.Count() Then
  1211. Return True
  1212. End If
  1213. For Local ib:String = EachIn ib1
  1214. If Not ib2.Contains(ib) Then
  1215. Return True
  1216. End If
  1217. Next
  1218. For Local ib:String = EachIn ib2
  1219. If Not ib1.Contains(ib) Then
  1220. Return True
  1221. End If
  1222. Next
  1223. Return False
  1224. End Method
  1225. Method IncbinsHashDifference:Int(source:TSourceFile, ib:TSourceFile)
  1226. If source.hashes.IsEmpty() Then
  1227. Return True
  1228. End If
  1229. For Local file:String = EachIn source.hashes.Keys()
  1230. Local sourceHash:String = String(source.hashes.ValueForKey(file))
  1231. If sourceHash <> String(ib.hashes.ValueForKey(file)) Then
  1232. Return True
  1233. End If
  1234. Next
  1235. For Local file:String = EachIn ib.hashes.Keys()
  1236. Local ibHash:String = String(ib.hashes.ValueForKey(file))
  1237. If ibHash <> String(source.hashes.ValueForKey(file)) Then
  1238. Return True
  1239. End If
  1240. Next
  1241. End Method
  1242. Method CreateLinkStage:TSourceFile(source:TSourceFile, stage:Int = STAGE_LINK)
  1243. Local link:TSourceFile = New TSourceFile
  1244. source.CopyInfo(link)
  1245. link.deps.Insert(StripExt(link.obj_path) + ".c", source)
  1246. link.stage = stage
  1247. link.processed = True
  1248. link.depsList = New TList
  1249. link.depsList.AddLast(source)
  1250. If IOS_HAS_MERGE And processor.Platform() = "ios" Then
  1251. sources.Insert(link.obj_path, link)
  1252. Else
  1253. sources.Insert(link.arc_path, link)
  1254. End If
  1255. Return link
  1256. End Method
  1257. Method CreateMergeStage:TSourceFile(source:TSourceFile)
  1258. Local merge:TSourceFile = New TSourceFile
  1259. source.CopyInfo(merge)
  1260. merge.deps.Insert(merge.obj_path, source)
  1261. merge.stage = STAGE_MERGE
  1262. merge.processed = True
  1263. merge.depsList = New TList
  1264. merge.depsList.AddLast(source)
  1265. sources.Insert(merge.merge_path, merge)
  1266. Return merge
  1267. End Method
  1268. Method CalculateBatches:TList(files:TList)
  1269. Local batches:TList = New TList
  1270. Local count:Int
  1271. Local instances:TMap = New TMap
  1272. For Local m:TSourceFile = EachIn files
  1273. instances.Insert(m.GetSourcePath(), m)
  1274. count :+ 1
  1275. Next
  1276. Local dependencies:TMap = New TMap
  1277. For Local m:TSourceFile = EachIn files
  1278. dependencies.Insert(m.GetSourcePath(), m.deps)
  1279. Next
  1280. Local pct:Float = 100.0 / count
  1281. Local total:Float
  1282. Local num:Int
  1283. While Not dependencies.IsEmpty()
  1284. Local noDeps:TList = New TList
  1285. For Local depName:String = EachIn dependencies.Keys()
  1286. Local dep:TMap = TMap(dependencies.ValueForKey(depName))
  1287. If dep.IsEmpty() Then
  1288. noDeps.AddLast(depName)
  1289. End If
  1290. Next
  1291. If noDeps.IsEmpty() Then
  1292. ' circular dependency!
  1293. ' TODO : dump current list for user to work out?
  1294. Print "REMAINING :"
  1295. For Local depName:String = EachIn dependencies.Keys()
  1296. Print " " + depName
  1297. Next
  1298. Throw "circular dependency!"
  1299. End If
  1300. ' remove from dependencies
  1301. For Local name:String = EachIn noDeps
  1302. dependencies.Remove(name)
  1303. Next
  1304. For Local dep:TMap = EachIn dependencies.Values()
  1305. For Local name:String = EachIn noDeps
  1306. dep.Remove(name)
  1307. Next
  1308. Next
  1309. Local list:TList = New TList
  1310. For Local name:String = EachIn noDeps
  1311. Local m:TSourceFile = TSourceFile(instances.ValueForKey(name))
  1312. list.AddLast(m)
  1313. Next
  1314. batches.AddLast(list)
  1315. Wend
  1316. ' post process batches
  1317. Local suffix:String[]
  1318. Local stage:Int
  1319. For Local i:Int = 0 Until 3
  1320. Select i
  1321. Case 0
  1322. suffix = ["c", "cpp", "cc", "cxx", "m", "mm"]
  1323. Case 1
  1324. suffix = ["o"]
  1325. stage = STAGE_LINK
  1326. Case 2
  1327. suffix = ["o"]
  1328. stage = STAGE_APP_LINK
  1329. End Select
  1330. Local newList:TList = New TList
  1331. For Local list:TList = EachIn batches
  1332. For Local f:TSourceFile = EachIn list
  1333. Local p:String = f.GetSourcePath()
  1334. If Not p.EndsWith("bmx") Then
  1335. For Local s:String = EachIn suffix
  1336. If p.EndsWith(s) Then
  1337. If app_iface And stage Then
  1338. If (stage = STAGE_LINK And app_iface = f.iface_path) Or (stage = STAGE_APP_LINK And app_iface <> f.iface_path) Then
  1339. Continue
  1340. End If
  1341. End If
  1342. newList.AddLast(f)
  1343. list.Remove(f)
  1344. If list.IsEmpty() Then
  1345. batches.Remove(list)
  1346. End If
  1347. ' found, no need to loop further
  1348. Exit
  1349. End If
  1350. Next
  1351. End If
  1352. Next
  1353. Next
  1354. If Not newList.IsEmpty() Then
  1355. batches.AddLast(newList)
  1356. End If
  1357. Next
  1358. For Local list:TList = EachIn batches
  1359. For Local m:TSourceFile = EachIn list
  1360. total :+ pct
  1361. num :+ 1
  1362. If num = count Then
  1363. m.pct = 100
  1364. Else
  1365. m.pct = total
  1366. End If
  1367. Next
  1368. Next
  1369. Return batches
  1370. End Method
  1371. Method ShowPct:String(pct:Int)
  1372. Local s:String = "["
  1373. Local p:String = String.FromInt(pct)
  1374. Select p.length
  1375. Case 1
  1376. s :+ " "
  1377. Case 2
  1378. s :+ " "
  1379. End Select
  1380. Return s + p + "%] "
  1381. End Method
  1382. Method FixPct:String(pct:String)
  1383. If processor.Platform() = "win32" Then
  1384. Return pct.Replace("%", "%%")
  1385. Else
  1386. Return pct
  1387. End If
  1388. End Method
  1389. Method CheckPath:String(basePath:String, path:String)
  1390. Local p:String = RealPath(basePath + "/" + path)
  1391. If Not FileType(p) Then
  1392. ' maybe path is a full path already?
  1393. p = RealPath(path)
  1394. If Not FileType(p) Then
  1395. ' meh... fallback to original
  1396. p = RealPath(basePath + "/" + path)
  1397. End If
  1398. End If
  1399. Return p
  1400. End Method
  1401. Method DoCallback(src:String)
  1402. Local update:Int = True
  1403. Local m:TSourceFile = TSourceFile(sources.ValueForKey(src))
  1404. If m Then
  1405. If FileType(m.iface_path) = FILETYPE_FILE Then
  1406. ' has the interface/api changed since the last build?
  1407. If FileType(m.iface_path2) = FILETYPE_FILE And m.time = FileTime( m.path ) Then
  1408. If FileSize(m.iface_path) = FileSize(m.iface_path2) Then
  1409. Local i_bytes:Byte[] = LoadByteArray(m.iface_path)
  1410. Local i_bytes2:Byte[] = LoadByteArray(m.iface_path2)
  1411. ?bmxng
  1412. If i_bytes.length = i_bytes2.length And memcmp_( i_bytes, i_bytes2, Size_T(i_bytes.length) )=0 Then
  1413. ?Not bmxng
  1414. If i_bytes.length = i_bytes2.length And memcmp_( i_bytes, i_bytes2, i_bytes.length )=0 Then
  1415. ?
  1416. update = False
  1417. End If
  1418. End If
  1419. End If
  1420. If update Then
  1421. CopyFile m.iface_path, m.iface_path2
  1422. Else If m.iface_time < m.MaxIfaceTime() Then
  1423. SetFileTimeNow(m.iface_path2)
  1424. m.iface_time = time_(Null)
  1425. m.maxIfaceTimeCache = -1
  1426. End If
  1427. End If
  1428. If update Then
  1429. m.SetRequiresBuild(True)
  1430. m.iface_time = time_(Null)
  1431. m.maxIfaceTimeCache = -1
  1432. m.gen_time = time_(Null)
  1433. End If
  1434. End If
  1435. End Method
  1436. End Type
  1437. Type TArcTask
  1438. Field m:TSourceFile
  1439. Field path:String
  1440. Field oobjs:TList
  1441. Method Create:TArcTask(m:TSourceFile, path$ , oobjs:TList )
  1442. Self.m = m
  1443. Self.path = path
  1444. Self.oobjs = oobjs
  1445. Return Self
  1446. End Method
  1447. Function _CreateArc:Object(data:Object)
  1448. Return TArcTask(data).CreateArc()
  1449. End Function
  1450. Method CreateArc:Object()
  1451. DeleteFile path
  1452. Local cmd$,t$
  1453. If processor.Platform() = "win32"
  1454. For t$=EachIn oobjs
  1455. If Len(cmd)+Len(t)>1000
  1456. If opt_standalone And Not opt_nolog processor.PushLog(cmd)
  1457. If processor.Sys( cmd )
  1458. DeleteFile path
  1459. Throw "Build Error: Failed to create archive "+path
  1460. EndIf
  1461. cmd=""
  1462. EndIf
  1463. If Not cmd Then
  1464. Local prefix:String = processor.MinGWExePrefix()
  1465. Local ext:String = ""
  1466. If processor.OSPlatform() = "win32" Then
  1467. ext = ".exe"
  1468. End If
  1469. cmd= processor.Option("path_to_ar", processor.MinGWBinPath() + "/" + prefix + "ar" + ext) + " -rc "+CQuote(path)
  1470. End If
  1471. cmd:+" "+CQuote(t)
  1472. Next
  1473. End If
  1474. If processor.Platform() = "macos" Or processor.Platform() = "osx" Then
  1475. cmd=processor.Option(processor.BuildName("libtool"), "libtool") + " -o "+CQuote(path)
  1476. For Local t$=EachIn oobjs
  1477. cmd:+" "+CQuote(t)
  1478. Next
  1479. End If
  1480. If processor.Platform() = "ios" Then
  1481. Local proc:String = processor.CPU()
  1482. Select proc
  1483. Case "x86"
  1484. proc = "i386"
  1485. Case "x64"
  1486. proc = "x86_64"
  1487. End Select
  1488. cmd= processor.Option(processor.BuildName("libtool"), "libtool") + " -static -arch_only " + proc + " -o "+CQuote(path)
  1489. For Local t$=EachIn oobjs
  1490. cmd:+" "+CQuote(t)
  1491. Next
  1492. End If
  1493. If processor.Platform() = "linux" Or processor.Platform() = "raspberrypi" Or processor.Platform() = "android" Or processor.Platform() = "emscripten" Or processor.Platform() = "nx" Or processor.Platform() = "haiku"
  1494. For Local t$=EachIn oobjs
  1495. If Len(cmd)+Len(t)>1000
  1496. If opt_standalone And Not opt_nolog processor.PushLog(cmd)
  1497. If processor.Sys( cmd )
  1498. DeleteFile path
  1499. Throw "Build Error: Failed to create archive "+path
  1500. EndIf
  1501. cmd=""
  1502. EndIf
  1503. If processor.Platform() = "emscripten" Then
  1504. If Not cmd cmd=processor.Option(processor.BuildName("ar"), "emar") + " r "+CQuote(path)
  1505. Else
  1506. If Not cmd cmd=processor.Option(processor.BuildName("ar"), "ar") + " -r "+CQuote(path)
  1507. End If
  1508. cmd:+" "+CQuote(t)
  1509. Next
  1510. End If
  1511. If cmd
  1512. If opt_standalone And Not opt_nolog processor.PushLog(cmd)
  1513. If processor.Sys( cmd )
  1514. DeleteFile path
  1515. Throw "Build Error: Failed to create archive "+path
  1516. End If
  1517. EndIf
  1518. m.arc_time = time_(Null)
  1519. m.obj_time = time_(Null)
  1520. End Method
  1521. End Type