12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664 |
- SuperStrict
- Import BRL.Reflection
- Import BRL.Map
- Import BRL.LinkedList
- '?win32
- Import Pub.FreeProcess
- '?
- ?threaded
- Import BRL.Threads
- Import "bmk_proc_man.bmx"
- ?
- ?Not win32
- Import "waitpid.c"
- ?
- Import "bmk_config.bmx"
- Import "bmk_ng_utils.bmx"
- Global processor:TBMK = New TBMK
- Global globals:TBMKGlobals = New TBMKGlobals
- ' load in the base stuff
- LoadBMK(AppDir + "/core.bmk", True)
- LoadBMK(AppDir + "/make.bmk", True)
- ' optional
- LoadBMK(AppDir + "/config.bmk")
- ' add some defaults
- globals.SetVar("macos_version", String(macos_version))
- globals.SetVar("cc_opts", New TOptionVariable)
- globals.SetVar("ld_opts", New TOptionVariable)
- globals.SetVar("c_opts", New TOptionVariable)
- globals.SetVar("cpp_opts", New TOptionVariable)
- 'globals.SetVar("gcc_version", String(processor.GCCVersion()))
- Function LoadBMK(path:String, required:Int = False)
- processor.LoadBMK(path, required)
- End Function
- ' this is the core bmk processor.
- Type TBMK
- Field commands:TMap = New TMap
- Field buildLog:TList
- Field sourceList:TList
- Field _minGWBinPath:String
- Field _minGWPath:String
- Field _minGWLinkPaths:String
- Field _minGWDLLCrtPath:String
- Field _minGWCrtPath:String
- Field _minGWExePrefix:String
-
- Field callback:TCallback
- Field _appSettings:TMap
- Method New()
- LuaRegisterObject Self,"bmk"
- End Method
-
- Method Reset()
- buildLog = Null
- sourceList = Null
- _minGWBinPath = Null
- _minGWPath = Null
- _minGWLinkPaths = Null
- _minGWDLLCrtPath = Null
- _minGWCrtPath = Null
- _minGWExePrefix = Null
- End Method
- ' loads a .bmk, stores any functions, and runs any commands.
- Method LoadBMK(path:String, required:Int = False)
- Local str:String
- Try
- If FileType(path) = 1 Then
- str = LoadText( path )
- If Int(globals.Get("verbose")) Or opt_verbose
- Print "Loading " + path
- End If
- Else
- If FileType(AppDir + "/" + path) = 1 Then
- str = LoadText( AppDir + "/" + path )
- If Int(globals.Get("verbose")) Or opt_verbose
- Print "Loading " + AppDir + "/" + path
- End If
- Else
- If FileType(globals.Get("BUILDPATH") + "/" + path) = 1 Then
- str = LoadText(globals.Get("BUILDPATH") + "/" + path )
- If Int(globals.Get("verbose")) Or opt_verbose
- Print "Loading " + globals.Get("BUILDPATH") + "/" + path
- End If
- Else
- If required Then
- Throw "Could not load required config '" + path + "'"
- End If
- Return
- End If
- End If
- End If
- Catch e:Object
- Try
- If FileType(AppDir + "/" + path) = 1 Then
- str = LoadText( AppDir + "/" + path )
- If Int(globals.Get("verbose")) Or opt_verbose
- Print "Loading " + AppDir + "/" + path
- End If
- Else
- If FileType(globals.Get("BUILDPATH") + "/" + path) = 1 Then
- str = LoadText(globals.Get("BUILDPATH") + "/" + path )
- If Int(globals.Get("verbose")) Or opt_verbose
- Print "Loading " + globals.Get("BUILDPATH") + "/" + path
- End If
- Else
- If required Then
- Throw "Could not load required config '" + path + "'"
- End If
- Return
- End If
- End If
- Catch e:Object
- ' we tried... twice
- ' fail silently...
- ' unless the file was required!
- If required Then
- Throw "Could not load required config '" + path + "'"
- End If
- Return
- End Try
- End Try
- Local pos:Int, inDefine:Int, Text:String, name:String
-
- While pos < str.length
-
- Local eol:Int = str.Find( "~n",pos )
- If eol = -1 Then
- eol = str.length
- End If
-
- Local line:String = str[pos..eol].Trim()
- pos = eol+1
-
- ProcessLine(line, inDefine, Text, name)
- ' anything else?
- Wend
- End Method
-
- ' processes a pragma
- Method ProcessPragma(line:String, inDefine:Int Var, Text:String Var, name:String Var)
- ProcessLine(line, inDefine, Text, name)
- End Method
-
- Method ProcessLine(line:String, inDefine:Int Var, Text:String Var, name:String Var)
-
- If line.StartsWith("#") Then
- Return
- End If
-
- Local lline:String = line.ToLower()
-
- If line.StartsWith("@") Then
-
- If lline[1..].StartsWith("define") Then
-
- inDefine = True
- name = line[8..].Trim()
-
- Local cmd:TBMKCommand = New TBMKCommand
- cmd.name = name
- commands.Insert(name.ToLower(), cmd)
-
- Return
- End If
-
- If lline[1..].StartsWith("end") Then
-
- If inDefine Then
- Local cmd:TBMKCommand = TBMKCommand(commands.ValueForKey(name.ToLower()))
- cmd.LoadCommand(Text)
-
- Text = ""
- inDefine = False
- End If
-
- Return
- End If
-
- End If
-
- If inDefine Then
- Text:+ line + "~n"
- Return
- End If
-
- If line.length = 0 Then
- Return
- End If
-
- ' find command, and run
- Local i:Int=1
- While i < lline.length And (CharIsAlpha(lline[i]) Or CharIsDigit(lline[i]))
- i:+1
- Wend
- 'If i = lline.length Then
- ' Continue
- 'End If
-
- Local command:String = lline[..i]
- Local cmd:TBMKCommand = TBMKCommand(commands.ValueForKey(command))
-
- ' this is a command!
- If cmd Then
- cmd.RunCommand(line[i+1..])
- Return
- End If
-
- ' what's left?
- ' setting a variable?
- i = line.Find("=")
- If i <> -1 Then
- ' hmm. maybe a variable...
- Local variable:String = line[..i].Trim()
- Local value:String = Parse(line[i+1..].Trim())
- globals.SetVar(variable, value)
- End If
-
- End Method
-
- Method Parse:String(str:String)
- Local done:Int
-
- While Not done
-
- Local pos:Int, restart:Int, changed:Int
- While pos < str.length And Not restart
-
- Local eol:Int = str.Find( "~n",pos )
- If eol = -1 Then
- eol = str.length
- End If
-
- Local line:String = str[pos..eol].Trim()
- pos = eol+1
-
- Local i:Int
- While i < line.length
- i = line.find("%", i)
- If i = -1 Then
- i = line.length
- Continue
- End If
- Local start:Int = i
- i:+ 1
-
- While i < line.length And (CharIsAlpha(line[i]) Or CharIsDigit(line[i]))
- i:+1
- Wend
-
- If i > start Then
- If line[i..i+1] = "%" Then
- i:+ 1
- Local toReplace:String = line[start..i]
- ' we want to replace this with something, so we
- ' will look in the globals list and env for a match.
- ' Otherwise, it will swap % with $, and leave it as is.
- Local with:String = FindValue(toReplace)
- If with Then
- str = str.Replace(toReplace, with)
- restart = True
- End If
- End If
- End If
-
-
- Wend
-
-
- Wend
-
-
- If Not restart Then
- done = True
- End If
-
- Wend
- Return str
- End Method
-
- Method FindValue:String(variable:String)
- Local plainVar:String = variable.Replace("%", "")
- Local value:String = globals.Get(plainVar)
-
- If value Then
- Return value
- End If
-
- ' look for environment variable ?
- Local env:String = getenv_(plainVar)
- If env Then
- Return env
- End If
-
- ' return the original
- Return variable.Replace("%", "$")
- End Method
-
- ' quotes a string, if required (does it have spaces in it?)
- Method Quote:String(t:String)
- Return CQuote(t)
- End Method
-
- ' returns the platform as a string
- Method Platform:String()
- If Not opt_target_platform Then
- ' the native target platform
- ?raspberrypi
- Return "raspberrypi"
- ?android
- Return "android"
- ?macos
- Return "macos"
- ?linux
- Return "linux"
- ?win32
- Return "win32"
- ?emscripten
- Return "emscripten"
- ?haiku
- Return "haiku"
- ?
- Else
- ' the custom target platform
- Return opt_target_platform
- End If
- End Method
- Method OSPlatform:String()
- ?raspberrypi
- Return "raspberrypi"
- ?android
- Return "android"
- ?macos
- Return "macos"
- ?linux
- Return "linux"
- ?win32
- Return "win32"
- ?emscripten
- Return "emscripten"
- ?haiku
- Return "haiku"
- ?
- End Method
- 'returns the app type as a string ("gui", "console" ...)
- Method AppType:String()
- Return opt_apptype
- End Method
-
- ' returns the cpu type, as a string
- Method CPU:String()
- Return opt_arch
- ' Return cputypes[cputype]
- End Method
-
- Method ToggleCPU()
- If opt_universal Then
- Select Platform()
- Case "macos"
- Select CPU()
- Case "ppc"
- opt_arch = "x86"
- Case "x86"
- opt_arch = "ppc"
- Case "x64"
- opt_arch = "arm64"
- Case "arm64"
- opt_arch = "x64"
- End Select
- Case "ios"
- Select CPU()
- Case "x86"
- opt_arch = "x64"
- Case "x64"
- opt_arch = "x86"
- Case "armv7"
- opt_arch = "arm64"
- Case "arm64"
- opt_arch = "armv7"
- End Select
- End Select
- End If
- End Method
-
- Method BuildName:String(v:String)
- Local s:String = Platform() + "." + CPU() + "." + v
- Return s.ToLower()
- End Method
-
- Method Sys:Int(cmd:String)
- If Int(globals.Get("verbose")) Or opt_verbose
- Print cmd
- Else If Int(globals.Get("dumpbuild"))
- Local p$=cmd
- p = p.Replace( BlitzMaxPath()+"/","./" )
- WriteStdout p+"~n"
- Local t$="mkdir "
- If cmd.StartsWith( t ) And FileType( cmd[t.length..] ) Return False
- EndIf
- If opt_standalone And Not opt_nolog PushLog(cmd)
- If Not opt_standalone Or (opt_standalone And opt_nolog) Then
- ?win32
- Return system_( cmd )
- ?Not win32
- Local s:Byte Ptr = cmd.ToUtf8String()
- Local res:Int = bmx_system(s)
- MemFree(s)
- Return res
- ?
- End If
- End Method
- Method MultiSys:Int(cmd:String, src:String, obj:String, supp:String)
- If Int(globals.Get("verbose")) Or opt_verbose
- Print cmd
- Else If Int(globals.Get("dumpbuild"))
- Local p$=cmd
- p = p.Replace( BlitzMaxPath()+"/","./" )
- WriteStdout p+"~n"
- Local t$="mkdir "
- If cmd.StartsWith( t ) And FileType( cmd[t.length..] ) Return False
- EndIf
- If opt_standalone And Not opt_nolog PushLog(cmd)
-
- If Not opt_standalone Or (opt_standalone And opt_nolog) Then
- Local threaded:Int
- ?threaded
- threaded = True
- If threaded And Not opt_single Then
- processManager.DoSystem(cmd, src, obj, supp)
- Else
- ?
- If obj Then
- DeleteFile obj
- End If
-
- If supp Then
- DeleteFile supp
- End If
-
- Local res:Int = system_( cmd )
- If Not res Then
- If src.EndsWith(".bmx") Then
- processor.DoCallback(src)
- End If
- End If
-
- Return res
- ?threaded
- End If
- ?
- End If
- End Method
- Method ThrowNew(e:String)
- Throw e
- End Method
-
- Method Call(name:String, args:String[])
- RunCommand(name, args)
- End Method
- Method AddArg(option:String, extra:String)
- Local args:String[] = [option]
- If extra Then
- args:+ [extra]
- End If
-
- ParseConfigArgs args
- End Method
- Method Option:String(key:String, defaultValue:String)
- Local value:String = globals.Get(key)
-
- If Not value Then
- Return defaultValue
- Else
- Return value
- End If
- End Method
-
- Method GCCVersion:String(getVersionNum:Int = False, getRawVersion:Int = False)
- '?win32
- Global compiler:String
- Global version:String
- Global rawVersion:String
-
- If compiler Then
- If getVersionNum Then
- If getRawVersion Then
- Return rawVersion
- Else
- Return version
- End If
- Else
- Return compiler + " " + version
- End If
- End If
- Local process:TProcess
- If Platform() = "win32" Then
- process = CreateProcess(Option("path_to_gcc", MinGWBinPath() + "/gcc.exe") + " --version", HIDECONSOLE)
- Else
- process = CreateProcess(Option(BuildName("gcc"), "gcc") + " --version")
- End If
-
- If Not process Then
- Throw "Cannot find a valid GCC compiler. Please check your paths and environment."
- End If
-
- While True
- Delay 10
-
- Local line:String = process.pipe.ReadLine()
- If Not process.Status() And Not line Then
- Exit
- End If
- Local parts:String[] = line.Split(" ")
-
- If line.startswith("gcc") or parts[0].EndsWith("gcc") Then
- compiler = "gcc"
- Else If line.startswith("Target:") Then
- _target = line[7..].Trim()
- Else
- Local pos:Int = line.Find("clang")
- If pos >= 0 Then
- compiler = "clang"
- _clang = True
- End If
- End If
-
- Wend
- If process Then
- process.Close()
- End If
- If Int(globals.Get("verbose")) Or opt_verbose
- Print "Compiler : " + compiler
- Print "Is clang : " + _clang
- End If
- ' get version
- If Platform() = "win32" Then
- process = CreateProcess(Option("path_to_gcc", MinGWBinPath() + "/gcc.exe") + " -dumpversion -dumpfullversion", HIDECONSOLE)
- Else
- process = CreateProcess(Option(BuildName("gcc"), "gcc") + " -dumpversion -dumpfullversion")
- End If
- Local s:String
-
- While True
- Delay 10
-
- Local line:String = process.pipe.ReadLine()
- If Not process.Status() And Not line Then
- Exit
- End If
-
- If Not rawVersion and line Then
- rawVersion = line.Trim()
- Local count:Int = 0
- Local parts:String[] = rawVersion.split("-") ' First split by "-"
- For Local part:String = EachIn parts
- Local values:String[] = part.split(".") ' Then split by "."
- For Local v:String = EachIn values
- If IsNumeric(v)
- Local n:String = "0" + v
- s :+ n[n.length - 2..]
- count :+ 1
- EndIf
- Next
- Next
- ' Append "00" for each missing segment
- For Local i:Int = count To 2
- s:+ "00"
- Next
- End If
-
- Wend
-
- If process Then
- process.Close()
- End If
- version = s
-
- If getVersionNum Then
- If getRawVersion Then
- Return rawVersion
- Else
- Return version
- End If
- End If
- If Int(globals.Get("verbose")) Or opt_verbose
- Print "Version : " + version
- Print "Raw version : " + rawVersion
- End If
- Return compiler + " " + version
- '?
- End Method
- Function IsNumeric:Int(value:String)
- For Local i:Int = 0 Until value.length
- If Not CharIsDigit(value[i]) Then
- Return False
- End If
- Next
- Return True
- End Function
- Method XCodeVersion:String()
- ?macos
- Global xcode:String
- Global version:String
-
- If xcode Then
- Return version
- End If
- Local process:TProcess
- process = CreateProcess(Option(BuildName("xcodebuild"), "xcodebuild") + " -version")
- Local s:String
-
- If Not process Then
- Throw "Cannot find xcodebuild. Please check your paths and environment."
- End If
-
- While True
- Delay 10
-
- Local line:String = process.pipe.ReadLine()
- If Not process.Status() And Not line Then
- Exit
- End If
-
- If line.startswith("Xcode") Then
- xcode = line
- Local parts:String[] = line.split(" ")
-
- version =parts[1].Trim()
- End If
-
- Wend
- If process Then
- process.Close()
- End If
-
- Return version
- ?Not macos
- Return Null
- ?
- End Method
- Global _target:String
- Global _clang:Int
-
- Method HasTarget:Int(find:String)
-
- If Not _target Then
- GCCVersion()
- End If
-
- If _target Then
- If _target.Find(find) >= 0 Then
- Return True
- End If
- End If
-
- Return False
-
- End Method
-
- Method GCCVersionInt:Int()
- End Method
- Method HasClang:Int()
- Return _clang
- End Method
- Method BCCVersion:String()
- Global bcc:String
-
- If bcc Then
- Return bcc
- End If
- Local exe:String = "bcc"
- If OSPlatform() = "win32" Then
- exe :+ ".exe"
- End If
- Local process:TProcess = CreateProcess(CQuote(BlitzMaxPath() + "/bin/" + exe), HIDECONSOLE)
- Local s:String
-
- If Not process Then
- Throw "Cannot find a valid bcc. I am looking for it here : " + BlitzMaxPath() + "/bin/" + exe
- End If
-
- While True
- Delay 10
-
- Local line:String = process.pipe.ReadLine()
-
- If Not process.Status() And Not line Then
- Exit
- End If
-
- If line.startswith("BlitzMax") Then
- bcc = "BlitzMax"
- Else
- bcc = line[..line.Find(" ")]
- End If
-
- Wend
- If process Then
- process.Close()
- End If
- Return bcc
- End Method
- Method MinGWBinPath:String()
- If Not _minGWBinPath Then
- _minGWBinPath = MinGWPath() + "/bin"
- ?win32
- Local PATH:String = _wgetenv("PATH")
- PATH = _minGWBinPath + ";" + PATH
- _wputenv("PATH=" + PATH)
- ?
- End If
-
- Return _minGWBinPath
- End Method
-
- Method MinGWPath:String()
- If Not _minGWPath Then
- Local path:String
- ' look for local MinGW32 dir
- ' some distros (eg. MinGW-w64) only support a single target architecture - x86 or x64
- ' to compile for both, requires two separate MinGW installations. Check against
- ' CPU target based dir first, before working through the fallbacks.
- Local cpuMinGW:String = "/MinGW32x86"
- If processor.CPU()="x64" Then
- cpuMinGW = "/MinGW32x64"
- EndIf
- path = BlitzMaxPath() + cpuMinGW + "/bin"
- If FileType(path) = FILETYPE_DIR Then
- ' bin dir exists, go with that
- _minGWPath = BlitzMaxPath() + cpuMinGW
- Return _minGWPath
- End If
- path = BlitzMaxPath() + "/MinGW32/bin"
- If FileType(path) = FILETYPE_DIR Then
- ' bin dir exists, go with that
- _minGWPath = BlitzMaxPath() + "/MinGW32"
- Return _minGWPath
- End If
- path = BlitzMaxPath() + "/MinGW32x86/bin"
- If FileType(path) = FILETYPE_DIR Then
- ' bin dir exists, go with that
- _minGWPath = BlitzMaxPath() + "/MinGW32x86"
- Return _minGWPath
- End If
- path = BlitzMaxPath() + "/MinGW32x64/bin"
- If FileType(path) = FILETYPE_DIR Then
- ' bin dir exists, go with that
- _minGWPath = BlitzMaxPath() + "/MinGW32x64"
- Return _minGWPath
- End If
- path = BlitzMaxPath() + "/llvm-mingw/bin"
- If FileType(path) = FILETYPE_DIR Then
- ' bin dir exists, go with that
- _minGWPath = BlitzMaxPath() + "/llvm-mingw"
- Return _minGWPath
- End If
- ' try MINGW environment variable
- path = getenv_("MINGW")
- If path And FileType(path) = FILETYPE_DIR Then
- ' check for bin dir
- If FileType(path + "/bin") = FILETYPE_DIR Then
- ' go with that
- _minGWPath = path
- Return _minGWPath
- End If
- End If
- ' none of the above? fallback to BlitzMax dir (for bin and lib)
- _minGWPath = BlitzMaxPath()
- End If
-
- Return _minGWPath
- End Method
-
- Method MinGWLinkPaths:String()
- If Not _minGWLinkPaths Then
- Local links:String
-
- If HasClang() Then
- Select processor.CPU()
- Case "x86"
- links :+ " -L" + CQuote(RealPath(MinGWPath() + "/i686-w64-mingw32/lib"))
- Case "x64"
- links :+ " -L" + CQuote(RealPath(MinGWPath() + "/x86_64-w64-mingw32/lib"))
- Case "armv7"
- links :+ " -L" + CQuote(RealPath(MinGWPath() + "/armv7-w64-mingw32/lib"))
- Case "arm64"
- links :+ " -L" + CQuote(RealPath(MinGWPath() + "/aarch64-w64-mingw32/lib"))
- End Select
- Else If processor.HasTarget("x86_64") Then
- If processor.CPU()="x86" Then
- links :+ " -L" + CQuote(RealPath(MinGWPath() + "/lib/gcc/x86_64-w64-mingw32/" + GCCVersion(True, True) + "/32"))
- links :+ " -L" + CQuote(RealPath(MinGWPath() + "/x86_64-w64-mingw32/lib32"))
- Else
- links :+ " -L" + CQuote(RealPath(MinGWPath() + "/lib/gcc/x86_64-w64-mingw32/" + GCCVersion(True, True)))
- links :+ " -L" + CQuote(RealPath(MinGWPath() + "/x86_64-w64-mingw32/lib"))
- End If
- Else
- links :+ " -L" + CQuote(RealPath(MinGWPath() + "/lib"))
- links :+ " -L" + CQuote(RealPath(MinGWPath() +"/lib/gcc/mingw32/" + GCCVersion(True, True)))
- End If
-
- _minGWLinkPaths = links
- End If
-
- Return _minGWLinkPaths
- End Method
-
- ' the path where dllcrt2.o resides
- Method MinGWDLLCrtPath:String()
- If Not _minGWDLLCrtPath Then
- ' mingw64 ?
- Local path:String = MinGWPath() + "/"
- If processor.HasTarget("x86_64") Then
-
- path :+ "x86_64-w64-mingw32/"
-
- If processor.CPU()="x86" Then
- path :+ "lib32"
- Else
- path :+ "lib"
- End If
-
- If FileType(path) = 0 Then
- Throw "Could not determine MinGWDLLCrtPath : Expecting '" + path + "'"
- End If
-
- _minGWDLLCrtPath = path
- Else
- path :+ "lib"
- If FileType(path) = 0 Then
- Throw "Could not determine MinGWDLLCrtPath : Expecting '" + path + "'"
- End If
-
- _minGWDLLCrtPath = path
- End If
- End If
-
- Return RealPath(_minGWDLLCrtPath)
- End Method
-
- ' the path where crtbegin.o resides
- Method MinGWCrtPath:String()
- If Not _minGWCrtPath Then
- ' mingw64 ?
- Local path:String = MinGWPath() + "/"
- If processor.HasTarget("x86_64") Then
-
- path :+ "x86_64-w64-mingw32/"
-
- If processor.CPU()="x86" Then
- path :+ "lib32"
- Else
- path :+ "lib"
- End If
-
- If FileType(path) = 0 Then
- Throw "Could not determine MinGWCrtPath: Expecting '" + path + "'"
- End If
-
- _minGWCrtPath = path
- Else
-
- Local p:String = path + "lib/gcc/mingw32/" + GCCVersion(True, True)
- If FileType(p) = 0 Then
- path :+ "lib/gcc/i686-w64-mingw32/" + GCCVersion(True, True)
- Else
- path = p
- End If
- If FileType(path) = 0 Then
- Throw "Could not determine MinGWCrtPath: Expecting '" + p + "' or '" + path + "'"
- End If
-
- _minGWCrtPath = path
- End If
- End If
-
- Return RealPath(_minGWCrtPath)
- End Method
- Method MinGWExePrefix:String()
- If Not _minGWExePrefix Then
- GCCVersion()
- If processor.HasClang() Then
- Select processor.CPU()
- Case "x86"
- _minGWExePrefix = "i686-w64-mingw32uwp-"
- Case "x64"
- _minGWExePrefix = "x86_64-w64-mingw32uwp-"
- Case "armv7"
- _minGWExePrefix = "armv7-w64-mingw32-"
- Case "arm64"
- _minGWExePrefix = "aarch64-w64-mingw32-"
- End Select
- End If
- End If
- Return _minGWExePrefix
- End Method
-
- Method IsDebugBuild:Int()
- Return opt_debug
- End Method
- Method IsGdbDebugBuild:Int()
- Return opt_gdbdebug
- End Method
- Method IsReleaseBuild:Int()
- Return opt_release
- End Method
- Method IsThreadedBuild:Int()
- Return opt_threaded
- End Method
- Method IsQuickscanBuild:Int()
- Return opt_quickscan
- End Method
- Method IsUniversalBuild:Int()
- Return opt_universal
- End Method
- Method GetModFilter:String()
- Return opt_modfilter
- End Method
- Method GetConfigMung:String()
- Return opt_configmung
- End Method
-
- Method SupportsHiRes:Int()
- Return opt_hi
- End Method
- Method RunCommand:Object(command:String, args:String[])
- Local cmd:TBMKCommand = TBMKCommand(commands.ValueForKey(command.ToLower()))
- If cmd Then
- ' we need to add the "arg0" string to the front of the array
- Local all:String
- For Local i:Int = 0 Until args.length
- Local arg:String = args[i]
- all:+ CQuote$(arg) + " "
- Next
- args = [ all.Trim() ] + args
- ' now we can run the command
- Return cmd.RunCommandArgs(args)
- End If
- End Method
- Method PushLog(cmd:String)
- If Not buildLog Then
- buildLog = New TList
- End If
- Local p:String = FixPaths(cmd)
- buildLog.AddLast(p)
- End Method
- Method PushSource(src:String)
- If Not sourceList Then
- sourceList = New TList
- End If
- Local p:String = FixPaths(src)
- sourceList.AddLast(p)
- End Method
- Method PushEcho(cmd:String)
- PushLog("echo ~q" + cmd + "~q")
- End Method
-
- Method FixPaths:String(Text:String)
- Local p:String = Text
- Local bmxRoot:String = "$BMX_ROOT"
- If Platform() = "win32" Then
- bmxRoot = "%BMX_ROOT%"
- End If
- Local appRoot:String = "$APP_ROOT"
- If Platform() = "win32" Then
- appRoot = "%APP_ROOT%"
- End If
- p = p.Replace(BlitzMaxPath()+"/", bmxRoot + "/")
- p = p.Replace(String(globals.GetRawVar("EXEPATH")), appRoot)
- Return p
- End Method
-
- Method AppDet:String()
- Return StripExt(StripDir(app_main)) + "." + opt_apptype + opt_configmung + processor.CPU()
- End Method
-
- Method DoCallback(src:String)
- If callback Then
- callback.DoCallback(src)
- End If
- End Method
-
- Method VerboseBuild:Int()
- Return opt_verbose
- End Method
-
- Method AppSetting:String(key:String)
- If Not _appSettings Then
- _appSettings = ParseApplicationIniFile()
- End If
-
- Return String(_appSettings.ValueForKey(key))
- End Method
-
- End Type
- ?win32
- Extern
- Function _wgetenv$w(varname$w)
- Function _wputenv:Int(varname$w)
- End Extern
- ?
- ' stores variables, as well as a variable stack which can be pushed and popped.
- Type TBMKGlobals
- ' current value of variables
- Field vars:TMap = New TMap
- ' variable stack
- Field stack:TMap = New TMap
-
- Method New()
- LuaRegisterObject Self,"globals"
- End Method
- ' sets the variable with value
- Method SetVar(variable:String, value:Object)
- 'Print "SetVar : " + variable + " : " + String(value)
- vars.Insert(variable.ToUpper(), value)
- End Method
-
- ' returns the current value for variable
- Method Get:String(variable:String)
- Local obj:Object = vars.ValueForKey(variable.ToUpper())
- If obj Then
- If String(obj) Then
- Return String(obj)
- End If
- Return obj.ToString()
- End If
- End Method
-
- Method GetRawVar:Object(variable:String)
- Local obj:Object = vars.ValueForKey(variable.ToUpper())
- If TOptionVariable(obj) Then
- ' return a copy of the object - any changes to this won't affect the current value.
- Return TOptionVariable(obj).Clone()
- End If
- Return obj
- End Method
- Method GetOptionVar:String(variable:String, name:String)
- Local obj:TOptionVariable = TOptionVariable(vars.ValueForKey(variable.ToUpper()))
- If obj Then
- Return obj.GetVar(name)
- End If
- End Method
- ' push the variable onto the stack (save the value)
- Method Push(variable:String)
- variable = variable.ToUpper()
-
- Local list:TList = TList(stack.ValueForKey(variable))
- If Not list Then
- list = New TList
- stack.Insert(variable, list)
- End If
-
- list.AddLast(GetRawVar(variable))
- End Method
-
- ' pop the variable from the stack (load the value)
- Method Pop(variable:String)
- variable = variable.ToUpper()
-
- Local list:TList = TList(stack.ValueForKey(variable))
- If list And Not list.IsEmpty() Then
- SetVar(variable, list.RemoveLast())
- End If
- End Method
-
- ' push all the variables
- Method PushAll(exclude:String[] = Null)
- For Local v:String = EachIn vars.Keys()
- If Not exclude
- Push(v)
- Else
- For Local s:String = EachIn exclude
- If s <> v Then
- Push(v)
- Exit
- End If
- Next
- End If
- Next
- End Method
-
- ' pop all the variables
- Method PopAll()
- For Local v:String = EachIn vars.Keys()
- Pop(v)
- Next
- End Method
-
- ' adds value to the end of variable
- Method Add(variable:String, value:String, once:Int = False)
- If Not AsConfigurable(variable.ToLower(), value) Then
- variable = variable.ToUpper()
-
- Local v:Object = vars.ValueForKey(variable)
- If Not TOptionVariable(v) Then
- If v And Not once Then
- SetVar(variable, String(v) + " " + value)
- Else
- SetVar(variable, value)
- End If
- End If
- End If
- End Method
- ' adds comma separated value to the end of variable
- Method AddC(variable:String, value:String)
- If Not AsConfigurable(variable.ToLower(), value) Then
- variable = variable.ToUpper()
-
- Local v:Object = vars.ValueForKey(variable)
- If Not TOptionVariable(v) Then
- If v Then
- SetVar(variable, String(v) + "," + value)
- Else
- SetVar(variable, value)
- End If
- End If
- End If
- End Method
- Method AddOption(variable:String, key:String, value:String)
- variable = variable.ToUpper()
- Local v:Object = vars.ValueForKey(variable)
- If TOptionVariable(v) Then
- TOptionVariable(v).AddVar(key, value)
- Else
- Local opt:TOptionVariable = New TOptionVariable
- opt.addVar(key, value)
- setVar(variable, opt)
- End If
- End Method
- Method SetOption(variable:String, key:String, value:String)
- variable = variable.ToUpper()
- Local v:Object = vars.ValueForKey(variable)
- If TOptionVariable(v) Then
- TOptionVariable(v).SetVar(key, value)
- Else
- Local opt:TOptionVariable = New TOptionVariable
- opt.SetVar(key, value)
- setVar(variable, opt)
- End If
- End Method
- ' only appropriate for TOptionVariables
- Method RemoveVar(variable:String, name:String)
- variable = variable.ToUpper()
- Local v:Object = vars.ValueForKey(variable)
- If TOptionVariable(v) Then
- TOptionVariable(v).RemoveVar(name)
- End If
- End Method
-
- Method Clear(variable:String)
- variable = variable.ToUpper()
- Local v:Object = vars.ValueForKey(variable)
- If TOptionVariable(v) Then
- vars.remove(variable)
- End If
- End Method
-
- Method Reset()
- stack.Clear()
- End Method
-
- Method Dump()
- For Local k:String = EachIn vars.Keys()
- Print k + " : " + Get(k)
- Next
- End Method
-
- End Type
- Type TOpt
- Field name:String
- Field value:String
- End Type
- ' holds a list of options.
- ' useful for storing a list of cc_opts, for example.
- ' the list can be modified as required, and cloned during push/pop calls.
- Type TOptionVariable
- Field options:TMap = New TMap
- Field orderedOptions:TList = New TList
-
- Method AddVar(name:String, value:String)', insertBefore:Int = False)
- Local opt:TOpt = New TOpt
-
- If Not name Then
- Global count:Int
- count:+1
- name = "VAR" + count
- opt.name = name
- Else
- opt.name = name
- End If
- opt.value = value
-
- options.Insert(name, opt)
- orderedOptions.AddLast(opt)
-
- End Method
- Method SetVar(name:String, value:String)', insertBefore:Int = False)
- Local opt:TOpt = New TOpt
-
- If Not name Then
- Global count:Int
- count:+1
- name = "VAR" + count
- opt.name = name
- Else
- opt.name = name
- End If
- opt.value = value
- ' option already exists?
- Local o:TOpt = TOpt(options.ValueForKey(name))
- If o Then
- orderedOptions.Remove(o)
- End If
-
- options.Insert(name, opt)
- orderedOptions.AddLast(opt)
-
- End Method
-
- Method GetVar:String(name:String)
- Return String(options.ValueForKey(name))
- End Method
-
- ' finds and removes a matching value
- Method RemoveVar(name:String)
- Local opt:TOpt = TOpt(options.ValueForKey(name))
- options.Remove(opt)
- orderedOptions.Remove(opt)
- End Method
-
- Method ToString:String()
- Local s:String = " "
-
- For Local opt:TOpt = EachIn orderedOptions
- s:+ opt.value + " "
- Next
- Return s
- End Method
-
- ' create an exact copy of me
- Method Clone:TOptionVariable()
- Local me:TOptionVariable = New TOptionVariable
- For Local name:String = EachIn options.Keys()
- me.options.insert(name, options.ValueForKey(name))
- Next
- For Local opt:TOpt = EachIn orderedOptions
- me.orderedOptions.AddLast(opt)
- Next
- Return me
- End Method
- End Type
- ' a bmk function/command
- Type TBMKCommand
- Field name:String
- Field command:String
- Field argCount:Int = 0
- Field class:TLuaClass
- Field instance:TLuaObject
-
- Method LoadCommand(cmd:String)
-
- cmd = WrapVariables(ParseArgs(cmd))
-
-
- Local code:String = "function bmk_" + name + "(...)~n" + ..
- GetArgs() + ..
- "nvl = function(a1,a2) if a1 == nil then return a2 else return a1 end end~n" + ..
- cmd + ..
- "end"
- class = New TLuaClass.SetSourceCode( code )
- instance = New TLuaObject.Init( class, Null )
- End Method
-
- Method RunCommand:Object(args:String)
- Return RunCommandArgs([args] + ExtractArgs(args))
- End Method
-
- ' This assumes we have arg0 + other args
- Method RunCommandArgs:Object(args:Object[])
- Return instance.invoke("bmk_" + name, args)
- End Method
- ' handles quotes and arrays [].
- ' [] inside quotes are ignored.
- Method ExtractArgs:Object[](args:String)
- Local argArray:Object[]
- Local arg:String, arr:String[]
- Local i:Int, inString:Int, inArray:Int
- While i < args.length
- Local c:String = args[i..i+1]
- i:+ 1
-
- If c = "~q" Then
- If inString Then
- If arg Then
- If Not inArray Then
- argArray:+ [ arg ]
- Else
- arr:+ [ arg ]
- End If
- End If
- arg = ""
- inString = False
- Continue
- Else
- arg = ""
- inString = True
- Continue
- End If
- End If
-
- If c = " " And Not inString Then
- If arg Then
- If Not inArray Then
- argArray:+ [ arg ]
- Else
- arr:+ [ arg ]
- End If
- arg = ""
- End If
- Continue
- End If
-
- If c = "[" And Not inString Then
- If Not inArray Then
- inArray = True
- arr = Null
- arg = ""
- Continue
- End If
- End If
-
- If c = "]" And Not inString Then
- If inArray Then
- If arg Then
- arr:+ [ arg ]
- End If
- inArray = False
- argArray:+ [ arr ]
- arr = Null
- arg = ""
- Continue
- End If
- End If
-
-
- arg:+ c
-
- Wend
-
- If arg Then
- If arr Then
- arr:+ [arg]
- argArray:+ [arr]
- Else
- argArray:+ [arg]
- End If
- Else
- If arr Then
- argArray:+ [arr]
- End If
- End If
-
- Return argArray
- End Method
-
- Method ParseArgs:String(cmd:String)
- ' This needs to process the command text to work out what args are used.
- ' so, for example, arg0, arg1 and arg2.
- ' That way, we generate the correct functionality when we build the function code.
- Local pos:Int
- While pos < cmd.length
-
- Local eol:Int = cmd.Find( "~n",pos )
- If eol = -1 Then
- eol = cmd.length
- End If
-
- Local line:String = cmd[pos..eol].Trim()
- pos = eol+1
- Local i:Int
- While i < line.length
- i = line.find("arg", i)
- If i = -1 Then
- i = line.length
- Continue
- End If
-
- i:+ 3
- Local start:Int = i
-
- While i < line.length And CharIsDigit(line[i])
- i:+1
- Wend
- Local num:Int = line[start..i].ToInt()
- If num Then
- argCount = Max(argCount, num)
- End If
-
- Wend
- Wend
-
- Return cmd
-
- End Method
-
- Method GetArgs:String()
- Local args:String = "local arg0"
- Local rep:String = "arg0 = bmk.Parse(arg0)~n"
-
- If argCount > 0 Then
- For Local i:Int = 1 To argCount
- args:+ ",arg" + i
- rep :+ "arg" + i + " = bmk.Parse(arg" + i + ")~n"
- Next
- End If
-
- args :+ " = unpack({...})~n"
- args :+ rep
- Return args
- End Method
-
- Method WrapVariables:String(str:String)
- Local done:Int
-
- While Not done
-
- Local pos:Int, restart:Int, changed:Int
- While pos < str.length And Not restart
-
- Local eol:Int = str.Find( "~n",pos )
- If eol = -1 Then
- eol = str.length
- End If
-
- Local line:String = str[pos..eol].Trim()
- pos = eol+1
-
- Local i:Int
- While i < line.length
- i = line.find("%", i)
- If i = -1 Then
- i = line.length
- Continue
- End If
- Local start:Int = i
- i:+ 1
-
- While i < line.length And (CharIsAlpha(line[i]) Or CharIsDigit(line[i]))
- i:+1
- Wend
-
- If i > start Then
- If line[i..i+1] = "%" Then
- i:+ 1
- Local toReplace:String = line[start..i]
- Local with:String = "globals.Get(~q" + toReplace.Replace("%", "") + "~q)"
- str = str.Replace(toReplace, with)
- restart = True
- End If
- End If
-
- Wend
-
- Wend
-
- If Not restart Then
- done = True
- End If
-
- Wend
- Return str
- End Method
- End Type
- ?Not win32
- Extern
- Function bmx_system:Int(cmd:Byte Ptr)
- End Extern
- ?
- Type TProcessTaskFactoryImpl Extends TProcessTaskFactory
- Method Create:TProcessTask( cmd:String, src:String, obj:String, supp:String )
- Return new TProcessTaskImpl.Create(cmd, src, obj, supp)
- End Method
- End Type
- new TProcessTaskFactoryImpl
- Type TProcessTaskImpl Extends TProcessTask
- Field command:String
- Field source:String
-
- Field obj:String
- Field supp:String
-
- Method Create:TProcessTask(cmd:String, src:String, obj:String, supp:String)
- command = cmd
- source = src
- Self.obj = obj
- Self.supp = supp
- Return Self
- End Method
-
- Method DoTasks:Object()
- Local res:Int
-
- If obj Then
- DeleteFile(obj)
- End If
-
- If supp Then
- DeleteFile(supp)
- End If
-
- ?Not win32
- Local s:Byte Ptr = command.ToUtf8String()
- res = bmx_system(s)
- MemFree(s)
- ?win32
- res = system_(command)
- ?
- If res Then
- Local s:String = "Build Error: failed to compile (" + res + ") " + source
- Throw s
- End If
-
- If source.EndsWith(".bmx") Then
- processor.DoCallback(source)
- End If
- End Method
- End Type
- Type TCallback
- Method DoCallback(src:String) Abstract
-
- End Type
- ?threaded
- Global processManager:TProcessManager = New TProcessManager
- ?
|