bmk.bmx 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677
  1. Strict
  2. Framework brl.filesystem
  3. Import "bmk_make.bmx"
  4. Import "bmk_zap.bmx"
  5. ?MacOS
  6. Import BRL.RamStream
  7. Incbin "macos.icns"
  8. ?
  9. If AppArgs.length<2 CmdError "Not enough parameters", True
  10. Local cmd$=AppArgs[1],args$[]
  11. args=ParseConfigArgs( AppArgs[2..], processor.BCCVersion() = "BlitzMax" )
  12. ' validate the platform configuration
  13. ValidatePlatformArchitecture()
  14. ' preload the default options
  15. processor.RunCommand("default_cc_opts", Null)
  16. ' load any global custom options (in BlitzMax/bin)
  17. LoadOptions
  18. ' pre-init gcc version cache
  19. processor.GCCVersion()
  20. CreateDir BlitzMaxPath()+"/tmp"
  21. Select cmd.ToLower()
  22. Case "makeapp"
  23. If opt_universal And processor.Platform() = "macos" And Float(processor.XCodeVersion()) < 12 Then
  24. Throw "XCode 12+ required for universal macOS build"
  25. End If
  26. SetConfigMung
  27. MakeApplication args,False
  28. Case "makelib"
  29. SetConfigMung
  30. MakeApplication args,True
  31. Case "makemods"
  32. If opt_universal And processor.Platform() = "macos" And Float(processor.XCodeVersion()) < 12 Then
  33. Throw "XCode 12+ required for universal macOS build"
  34. End If
  35. opt_quickscan = False
  36. If opt_debug Or opt_release
  37. SetConfigMung
  38. MakeModules args
  39. If opt_universal
  40. SetConfigMung
  41. processor.ToggleCPU()
  42. LoadOptions(True) ' reload options for PPC
  43. MakeModules args
  44. processor.ToggleCPU()
  45. LoadOptions(True)
  46. End If
  47. Else
  48. opt_debug=True
  49. opt_release=False
  50. SetConfigMung
  51. MakeModules args
  52. If opt_universal
  53. SetConfigMung
  54. processor.ToggleCPU()
  55. LoadOptions(True) ' reload options for PPC
  56. MakeModules args
  57. processor.ToggleCPU()
  58. LoadOptions(True)
  59. End If
  60. opt_debug=False
  61. opt_release=True
  62. SetConfigMung
  63. MakeModules args
  64. If opt_universal
  65. SetConfigMung
  66. processor.ToggleCPU()
  67. LoadOptions(True) ' reload options for PPC
  68. MakeModules args
  69. processor.ToggleCPU()
  70. LoadOptions(True)
  71. End If
  72. EndIf
  73. Case "makebootstrap"
  74. ' copy sources
  75. ' pub ->
  76. ' stdc, lua, win32, zlib, freeprocess
  77. '
  78. ' brl ->
  79. ' blitz, appstub, stream, filesystem, bank, ramstream, map, linkedlist, system, systemdefault, threads, stringbuilder, standardio
  80. '
  81. ' bah ->
  82. ' libcurl, mbedtls, libarchive, libxml, xz, libiconv
  83. '
  84. '
  85. ' create folder in src -> bootstrap
  86. ' create sub folders as per blitzmax layout
  87. ' copy required mod sources
  88. ' copy bmk/bcc/etc sources
  89. ' make standalone's for each app, for all required target platforms.
  90. opt_boot = True
  91. MakeBootstrap
  92. Case "compile"
  93. SetConfigMung
  94. MakeApplication args,False,True
  95. Case "cleanmods"
  96. CleanModules args
  97. Case "zapmod"
  98. ZapModule args
  99. Case "unzapmod"
  100. UnzapModule args
  101. Case "ranlibdir"
  102. RanlibDir args
  103. Case "-v"
  104. VersionInfo(processor.GCCVersion(), GetCoreCount(), processor.XCodeVersion())
  105. Default
  106. CmdError "Unknown operation '" + cmd.ToLower() + "'"
  107. End Select
  108. Function SetConfigMung()
  109. If opt_release
  110. opt_debug=False
  111. opt_configmung="release"
  112. If processor.BCCVersion() = "BlitzMax" Then
  113. If opt_threaded opt_configmung:+".mt"
  114. End If
  115. If opt_coverage Then
  116. opt_configmung :+ ".cov"
  117. End If
  118. opt_configmung="."+opt_configmung+"."+processor.Platform()+"."'+opt_arch
  119. Else
  120. opt_debug=True
  121. opt_release=False
  122. opt_configmung="debug"
  123. If processor.BCCVersion() = "BlitzMax" Then
  124. If opt_threaded opt_configmung:+".mt"
  125. End If
  126. opt_configmung="."+opt_configmung+"."+processor.Platform()+"."'+opt_arch
  127. EndIf
  128. End Function
  129. Function SetModfilter( t$ )
  130. opt_modfilter=t.ToLower()
  131. If opt_modfilter="*"
  132. opt_modfilter=""
  133. Else If opt_modfilter[opt_modfilter.length-1]<>"." And opt_modfilter.Find(".") < 0 Then
  134. opt_modfilter:+"."
  135. EndIf
  136. End Function
  137. Function MakeModules( args$[] )
  138. If opt_standalone CmdError "Standalone build not available for makemods"
  139. If args.length>1 CmdError "Expecting only 1 argument for makemods"
  140. Local mods:TList
  141. If args.length Then
  142. Local m:String = args[0]
  143. If m.find(".") > 0 And m[m.length-1]<>"." Then
  144. ' full module name?
  145. mods = New TList
  146. mods.AddLast(m)
  147. SetModfilter m
  148. Else
  149. SetModfilter m
  150. mods = EnumModules()
  151. End If
  152. Else
  153. opt_modfilter=""
  154. mods = EnumModules()
  155. End If
  156. BeginMake
  157. Local buildManager:TBuildManager = New TBuildManager
  158. buildManager.MakeMods(mods, opt_all)
  159. buildManager.DoBuild(False)
  160. End Function
  161. Function CleanModules( args$[] )
  162. If args.length>1 CmdError "Expecting only 1 argument for cleanmods"
  163. If args.length SetModfilter args[0] Else opt_modfilter=""
  164. Local mods:TList=EnumModules()
  165. Local name$
  166. For name=EachIn mods
  167. If (name+".").Find(opt_modfilter)<>0 Continue
  168. Print "Cleaning:"+name
  169. Local path$=ModulePath(name)
  170. CleanBmxDirs(path)
  171. Rem
  172. If Not opt_kill Continue
  173. For Local f$=EachIn LoadDir( path )
  174. Local p$=path+"/"+f
  175. Select FileType(p)
  176. Case FILETYPE_DIR
  177. If f<>"doc"
  178. DeleteDir p,True
  179. EndIf
  180. Case FILETYPE_FILE
  181. Select ExtractExt(f).tolower()
  182. Case "i","a","txt","htm","html"
  183. 'nop
  184. Default
  185. DeleteFile p
  186. End Select
  187. End Select
  188. Next
  189. End Rem
  190. Next
  191. End Function
  192. Function CleanBmxDirs(path:String)
  193. Local bmx:String = path + "/.bmx"
  194. If FileType(bmx) = FILETYPE_DIR Then
  195. If opt_verbose Then
  196. Print " Deleting " + bmx
  197. End If
  198. DeleteDir bmx,True
  199. End If
  200. For Local f:String = EachIn LoadDir( path )
  201. Local p:String = path + "/" + f
  202. Select FileType(p)
  203. Case FILETYPE_DIR
  204. CleanBmxDirs(p)
  205. End Select
  206. Next
  207. End Function
  208. Function MakeApplication( args$[],makelib:Int,compileOnly:Int = False )
  209. If opt_execute And Not compileOnly
  210. If Len(args)=0 CmdError "Execute requires at least 1 argument"
  211. Else
  212. If Len(args)<>1 Then
  213. If compileOnly Then
  214. CmdError "Expecting only 1 argument for compile"
  215. Else
  216. CmdError "Expecting only 1 argument for makeapp"
  217. End If
  218. End If
  219. EndIf
  220. Local Main$=RealPath( args[0] )
  221. Select ExtractExt(Main).ToLower()
  222. Case ""
  223. Main:+".bmx"
  224. Case "c","cpp","cxx","mm","bmx"
  225. Default
  226. Throw "Unrecognized app source file type:"+ExtractExt(Main)
  227. End Select
  228. If FileType(Main)<>FILETYPE_FILE Throw "Unable to open source file '"+Main+"'"
  229. opt_infile = Main
  230. If Not opt_outfile Then
  231. opt_outfile = StripExt( Main )
  232. Else
  233. opt_outfile = RealPath(opt_outfile)
  234. End If
  235. If opt_universal And processor.Platform() = "macos" Then
  236. opt_outfile :+ "." + processor.CPU()
  237. End If
  238. ' set some useful global variables
  239. globals.SetVar("BUILDPATH", ExtractDir(opt_infile))
  240. globals.SetVar("EXEPATH", ExtractDir(opt_outfile))
  241. globals.SetVar("OUTFILE", StripDir(StripExt(opt_outfile)))
  242. globals.SetVar("INFILE", StripDir(StripExt(opt_infile)))
  243. ' some more useful globals
  244. If processor.Platform() = "macos" And opt_apptype="gui" And Not compileOnly Then
  245. Local appId$=StripDir( opt_outfile )
  246. If opt_universal Then
  247. appId = StripExt(appId)
  248. End If
  249. globals.SetVar("APPID", appId)
  250. ' modify for bundle
  251. globals.SetVar("EXEPATH", ExtractDir(opt_outfile+".app/Contents/MacOS/"+appId))
  252. Local baseDir:String = opt_outfile
  253. If opt_universal Then
  254. baseDir = StripExt(baseDir)
  255. End If
  256. ' make bundle dirs
  257. Local exeDir:String = baseDir + ".app"
  258. Local d:String
  259. d=exeDir+"/Contents/MacOS"
  260. Select FileType( d )
  261. Case FILETYPE_NONE
  262. CreateDir d,True
  263. If FileType( d )<>FILETYPE_DIR
  264. Throw "Unable to create application directory"
  265. EndIf
  266. Case FILETYPE_FILE
  267. Throw "Unable to create application directory"
  268. Case FILETYPE_DIR
  269. End Select
  270. d=exeDir+"/Contents/Resources"
  271. Select FileType( d )
  272. Case FILETYPE_NONE
  273. CreateDir d
  274. If FileType( d )<>FILETYPE_DIR
  275. Throw "Unable to create resources directory"
  276. EndIf
  277. Case FILETYPE_FILE
  278. Throw "Unable to create resources directory"
  279. Case FILETYPE_DIR
  280. End Select
  281. Else
  282. Local d:String = ExtractDir(opt_outfile)
  283. Select FileType(d)
  284. Case FILETYPE_NONE
  285. CreateDir d, True
  286. If FileType(d) <> FILETYPE_DIR Then
  287. Throw "Unable to create output directory : " + d
  288. End If
  289. Case FILETYPE_FILE
  290. Throw "Invalid output directory : " + d
  291. End Select
  292. End If
  293. ' generic pre process
  294. LoadBMK(ExtractDir(Main) + "/pre.bmk")
  295. ' project-specific pre process
  296. LoadBMK(ExtractDir(Main) + "/" + StripDir( opt_outfile ) + ".pre.bmk")
  297. If processor.Platform() = "win32" Then
  298. If makelib
  299. If ExtractExt(opt_outfile).ToLower()<>"dll" opt_outfile:+".dll"
  300. Else
  301. If ExtractExt(opt_outfile).ToLower()<>"exe" opt_outfile:+".exe"
  302. EndIf
  303. EndIf
  304. If processor.Platform() = "macos" Or processor.Platform() = "osx" Then
  305. If opt_apptype="gui" And Not compileOnly
  306. 'Local appId$=StripDir( opt_outfile )
  307. Local appId$ = globals.Get("APPID")
  308. Local baseDir:String = opt_outfile
  309. If opt_universal Then
  310. baseDir = StripExt(baseDir)
  311. End If
  312. Local exeDir:String = baseDir+".app"
  313. Local t:TStream
  314. t=WriteStream( exeDir+"/Contents/Info.plist" )
  315. If Not t Throw "Unable to create Info.plist"
  316. t.WriteLine "<?xml version=~q1.0~q encoding=~qUTF-8~q?>"
  317. t.WriteLine "<!DOCTYPE plist PUBLIC ~q-//Apple Computer//DTD PLIST 1.0//EN~q ~qhttp://www.apple.com/DTDs/PropertyList-1.0.dtd~q>"
  318. t.WriteLine "<plist version=~q1.0~q>"
  319. t.WriteLine "<dict>"
  320. t.WriteLine "~t<key>CFBundleExecutable</key>"
  321. t.WriteLine "~t<string>"+appId+"</string>"
  322. t.WriteLine "~t<key>CFBundleIconFile</key>"
  323. t.WriteLine "~t<string>"+appId+"</string>"
  324. t.WriteLine "~t<key>CFBundlePackageType</key>"
  325. t.WriteLine "~t<string>APPL</string>"
  326. If opt_hi Then
  327. t.WriteLine "~t<key>NSHighResolutionCapable</key>"
  328. t.WriteLine "~t<true/>"
  329. End If
  330. If globals.Get("custom_plist") Then
  331. t.WriteLine "~t" + globals.Get("custom_plist")
  332. End If
  333. t.WriteLine "</dict>"
  334. t.WriteLine "</plist>"
  335. t.Close
  336. t=WriteStream( exeDir+"/Contents/Resources/"+appId+".icns" )
  337. If Not t Throw "Unable to create icons"
  338. Local in:TStream=ReadStream( "incbin::macos.icns" )
  339. CopyStream in,t
  340. in.Close
  341. t.Close
  342. opt_outfile=exeDir+"/Contents/MacOS/"+appId
  343. If opt_universal Then
  344. opt_outfile :+ "." + processor.CPU()
  345. End If
  346. EndIf
  347. End If
  348. If processor.Platform() = "emscripten" Then
  349. If ExtractExt(opt_outfile).ToLower()<>"html" opt_outfile:+".html"
  350. End If
  351. If processor.Platform() = "nx" Then
  352. If ExtractExt(opt_outfile).ToLower()<>"elf" opt_outfile:+".elf"
  353. End If
  354. BeginMake
  355. 'MakeApp Main,makelib
  356. Local buildManager:TBuildManager = New TBuildManager
  357. ' "android-project" check and copy
  358. If processor.Platform() = "android" And Not compileOnly Then
  359. DeployAndroidProject()
  360. End If
  361. buildManager.MakeApp(Main, makelib, compileOnly)
  362. buildManager.DoBuild(makelib, Not compileOnly)
  363. If opt_universal And processor.Platform() = "macos" Then
  364. Local original:String = opt_outfile
  365. processor.ToggleCPU()
  366. LoadOptions(True) ' reload options for other arch
  367. opt_outfile = StripExt(opt_outfile) + "." + processor.CPU()
  368. BeginMake
  369. Local buildManager:TBuildManager = New TBuildManager
  370. buildManager.MakeApp(Main, makelib, compileOnly)
  371. buildManager.DoBuild(False, True)
  372. processor.ToggleCPU()
  373. LoadOptions(True)
  374. MergeApp original, opt_outfile, StripExt(opt_outfile)
  375. End If
  376. If processor.Platform() = "nx" And Not compileOnly Then
  377. BuildNxDependencies()
  378. End If
  379. If opt_standalone And Not compileOnly
  380. Local suffix:String = ".build"
  381. If processor.Platform() = "win32" Then
  382. suffix :+ ".bat"
  383. End If
  384. Local buildScript:String = String(globals.GetRawVar("EXEPATH")) + "/" + StripExt(StripDir( app_main )) + "." + opt_apptype + opt_configmung + processor.CPU() + suffix
  385. Local stream:TStream = WriteStream(buildScript)
  386. If processor.Platform() <> "win32" Then
  387. Local ldScript:String = "$APP_ROOT/ld." + processor.AppDet() + ".txt"
  388. stream.WriteString("echo ~qBuilding " + String(globals.GetRawVar("OUTFILE")) + "...~q~n~n")
  389. stream.WriteString("if [ -z ~q${APP_ROOT}~q ]; then~n")
  390. If opt_boot Then
  391. stream.WriteString("~tAPP_ROOT=`pwd`~n")
  392. Else
  393. stream.WriteString("~tAPP_ROOT=" + String(globals.GetRawVar("EXEPATH")) + "~n")
  394. End If
  395. stream.WriteString("fi~n~n")
  396. stream.WriteString("if [ -z ~q${BMX_ROOT}~q ]; then~n")
  397. If opt_boot Then
  398. stream.WriteString("~tBMX_ROOT=$(dirname $(dirname `pwd`))~n")
  399. Else
  400. stream.WriteString("~tBMX_ROOT=" + BlitzMaxPath() + "~n")
  401. End If
  402. stream.WriteString("fi~n")
  403. stream.WriteString("~n~n")
  404. stream.WriteString("cp " + ldScript + " " + ldScript + ".tmp~n")
  405. stream.WriteString("sed -i -- 's=\$BMX_ROOT='$BMX_ROOT'=g' " + ldScript + ".tmp~n")
  406. stream.WriteString("sed -i -- 's=\$APP_ROOT='$APP_ROOT'=g' " + ldScript + ".tmp~n")
  407. stream.WriteString("~n~n")
  408. Else
  409. Local ldScript:String = "%APP_ROOT%/ld." + processor.AppDet() + ".txt"
  410. stream.WriteString("@ECHO OFF~n")
  411. stream.WriteString("SETLOCAL ENABLEEXTENSIONS~n")
  412. stream.WriteString("SET PARENT=%~~dp0~n~n")
  413. stream.WriteString("echo Building " + String(globals.GetRawVar("OUTFILE")) + "...~n")
  414. stream.WriteString("If Not DEFINED APP_ROOT (~n")
  415. If opt_boot Then
  416. stream.WriteString("~tSET APP_ROOT=%PARENT%~n")
  417. Else
  418. stream.WriteString("~tSET APP_ROOT=" + String(globals.GetRawVar("EXEPATH")) + "~n")
  419. End If
  420. stream.WriteString(")~n~n")
  421. stream.WriteString("If Not DEFINED BMX_ROOT (~n")
  422. If opt_boot Then
  423. stream.WriteString("~tSET BMX_ROOT=%PARENT%..\..~n")
  424. Else
  425. stream.WriteString("~tSET BMX_ROOT=" + BlitzMaxPath() + "~n")
  426. End If
  427. stream.WriteString(")~n~n")
  428. stream.WriteString("set PATH=%PATH%;" + processor.FixPaths(processor.MinGWBinPath()) + "~n~n");
  429. stream.WriteString("%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe -Command ~q((get-content \~q" + ldScript + "\~q) -replace '%%BMX_ROOT%%','%BMX_ROOT%') | set-content \~q" + ldScript + ".tmp\~q~q~n~n")
  430. End If
  431. If processor.buildLog Then
  432. For Local s:String = EachIn processor.buildLog
  433. stream.WriteString(s + "~n")
  434. Next
  435. End If
  436. If processor.Platform() <> "win32" Then
  437. stream.WriteString("unset APP_ROOT~n")
  438. stream.WriteString("~necho ~qFinished.~q~n")
  439. Else
  440. stream.WriteString("echo Finished.~n")
  441. stream.WriteString("ENDLOCAL~n")
  442. stream.WriteString("Goto :Eof~n")
  443. End If
  444. stream.Close()
  445. End If
  446. If opt_upx And Not compileOnly Then
  447. MakeUpx()
  448. End If
  449. If opt_execute And Not compileOnly
  450. ?Not android
  451. Print "Executing:"+StripDir( opt_outfile )
  452. Local cmd$=CQuote( opt_outfile )
  453. For Local i=1 Until args.length
  454. cmd:+" "+CQuote( args[i] )
  455. Next
  456. Sys cmd
  457. ?android
  458. ' on android we'll deploy the apk
  459. ?
  460. EndIf
  461. End Function
  462. Function ZapModule( args$[] )
  463. If Len(args)<>2 CmdError "Both module name and outfile required"
  464. Local modname$=args[0].ToLower()
  465. Local outfile$=RealPath( args[1] )
  466. Local stream:TStream=WriteStream( outfile )
  467. If Not stream Throw "Unable to open output file"
  468. ZapMod modname,stream
  469. stream.Close
  470. End Function
  471. Function UnzapModule( args$[] )
  472. If Len(args)<>1 CmdError "Expecting 1 argument for unzapmod"
  473. Local infile$=args[0]
  474. Local stream:TStream=ReadStream( infile )
  475. If Not stream Throw "Unable to open input file"
  476. UnzapMod stream
  477. stream.Close
  478. End Function
  479. Function RanlibDir( args$[] )
  480. If args.length<>1 CmdError "Expecting 1 argument for ranlibdir"
  481. Ranlib args[0]
  482. End Function
  483. Function LoadOptions(reload:Int = False)
  484. If reload Then
  485. ' reset the options to default
  486. processor.RunCommand("default_cc_opts", Null)
  487. End If
  488. LoadBMK(AppDir + "/custom.bmk")
  489. End Function
  490. Function MakeBootstrap()
  491. Local config:TBootstrapConfig = LoadBootstrapConfig()
  492. Local bootstrapPath:String = BlitzMaxPath() + "/dist/bootstrap"
  493. If Not CreateDir(bootstrapPath, True) Throw "Error creating bootstrap folder"
  494. If Not CreateDir(bootstrapPath + "/bin") Throw "Error creating boostrap/bin folder"
  495. If Not CreateDir(bootstrapPath + "/mod") Throw "Error creating boostrap/mod folder"
  496. If Not CreateDir(bootstrapPath + "/src") Throw "Error creating boostrap/src folder"
  497. config.CopyAssets(bootstrapPath)
  498. opt_release = True
  499. opt_all = True
  500. For Local target:TBootstrapTarget = EachIn config.targets
  501. For Local app:TBootstrapAsset = EachIn config.assets
  502. If app.assetType <> "a" Then
  503. Continue
  504. End If
  505. Local appPath:String = BlitzMaxPath() + "/src/" + app.name + "/" + app.name + ".bmx"
  506. If Not FileType(appPath) Throw "App not found : " + app.name
  507. opt_outfile = Null
  508. opt_standalone = True
  509. opt_warnover = True
  510. opt_target_platform = target.platform
  511. opt_arch = target.arch
  512. Print "Generating " + app.name + " : " + target.platform + "/" + target.arch
  513. Local args:String[] = [appPath]
  514. processor.Reset()
  515. SetConfigMung
  516. LoadOptions(True)
  517. MakeApplication args,False
  518. config.CopySources(bootstrapPath, processor.sourceList)
  519. config.CopyScripts(bootstrapPath, app)
  520. Next
  521. Next
  522. End Function