forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			749 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
		
		
			
		
	
	
			749 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
|  | import haxe.io.Eof; | ||
|  | import sys.io.Process; | ||
|  | import sys.FileSystem; | ||
|  | import BuildTool; | ||
|  | 
 | ||
|  | class Setup | ||
|  | { | ||
|  |    static function findAndroidNdkRoot(defines: Map<String,String>, inBaseVersion:Int):String | ||
|  |    { | ||
|  |       var bestVersion = 0.0; | ||
|  |       var result:String = null; | ||
|  | 
 | ||
|  |       var ndkDir = defines.get("ANDROID_NDK_DIR"); | ||
|  |       if (ndkDir!=null) | ||
|  |       { | ||
|  |          Log.v("Looking in ANDROID_NDK_DIR " + ndkDir); | ||
|  |       } | ||
|  |       else | ||
|  |       { | ||
|  |          Log.v("ANDROID_NDK_DIR not set"); | ||
|  |          if (BuildTool.isMac) | ||
|  |          { | ||
|  |             var lib = defines.get("HOME") + "/Library/Android/sdk/ndk"; | ||
|  |             if (FileSystem.exists(lib)) | ||
|  |             { | ||
|  |                Log.v("trying default " + lib); | ||
|  |                ndkDir = lib; | ||
|  |             } | ||
|  |          } | ||
|  |       } | ||
|  | 
 | ||
|  |       if (ndkDir!=null) | ||
|  |       { | ||
|  |         ndkDir = ndkDir.split("\\").join("/"); | ||
|  |         var files:Array<String> = null; | ||
|  |         var checkFiles:Bool = true; | ||
|  |         try | ||
|  |         { | ||
|  |              files = FileSystem.readDirectory(ndkDir); | ||
|  |         } | ||
|  |         catch (e:Dynamic) | ||
|  |         { | ||
|  |              Log.warn('ANDROID_NDK_DIR "$ndkDir" does not point to a valid directory'); | ||
|  |              checkFiles=false; | ||
|  |         } | ||
|  |         if (checkFiles) | ||
|  |           for (file in files) | ||
|  |           { | ||
|  |              file = file.split("\\").join("/"); | ||
|  |              var version = getNdkVersion(ndkDir + "/" + file); | ||
|  |              if (inBaseVersion==0 || Std.int(version)==inBaseVersion) | ||
|  |              { | ||
|  |                 if (version>bestVersion) | ||
|  |                 { | ||
|  |                    bestVersion = version; | ||
|  |                    result = ndkDir + "/" + file; | ||
|  |                 } | ||
|  |              } | ||
|  |           } | ||
|  |       } | ||
|  | 
 | ||
|  |       Log.v("Looking in ANDROID_SDK/ndk-bundle"); | ||
|  |       if (defines.exists("ANDROID_SDK")) | ||
|  |       { | ||
|  |         Log.v("checks default ndk-bundle in android sdk"); | ||
|  |         var ndkBundle = defines.get("ANDROID_SDK")+"/ndk-bundle"; | ||
|  |         ndkBundle = ndkBundle.split("\\").join("/"); | ||
|  |         var version = getNdkVersion(ndkBundle); | ||
|  |         if (version>bestVersion && (inBaseVersion==0 || inBaseVersion==Std.int(version)) ) | ||
|  |         { | ||
|  |            Log.v("Using default ndk-bundle in android sdk"); | ||
|  |            result = ndkBundle; | ||
|  |         } | ||
|  |       } | ||
|  | 
 | ||
|  |       return result; | ||
|  |    } | ||
|  | 
 | ||
|  |    static public function getNdkVersion(inDirName:String):Float | ||
|  |    { | ||
|  |       Log.v("Try to get version from source.properties"); | ||
|  |       var src = toPath(inDirName+"/source.properties"); | ||
|  |       if (sys.FileSystem.exists(src)) | ||
|  |       { | ||
|  |          var fin = sys.io.File.read(src, false); | ||
|  |          try | ||
|  |          { | ||
|  |             while (true) | ||
|  |             { | ||
|  |                var str = fin.readLine(); | ||
|  |                var split = str.split ("="); | ||
|  |                var name = StringTools.trim(split[0]); | ||
|  |                if (name == "Pkg.Revision") | ||
|  |                { | ||
|  |                   var revision = StringTools.trim(split[1]); | ||
|  |                   var split2 = revision.split( "." ); | ||
|  |                   var result:Float = 1.0 * Std.parseInt(split2[0]) + 0.001 * Std.parseInt(split2[1]); | ||
|  |                   if (result>=8) | ||
|  |                   { | ||
|  |                      Log.v('Deduced NDK version '+result+' from "$inDirName"/source.properties'); | ||
|  |                      fin.close(); | ||
|  |                      return result; | ||
|  |                   } | ||
|  |                } | ||
|  |             } | ||
|  |          } | ||
|  |          catch (e:haxe.io.Eof) | ||
|  |          { | ||
|  |             Log.v('Could not deduce NDK version from "$inDirName"/source.properties'); | ||
|  |          } | ||
|  |          fin.close(); | ||
|  |       } | ||
|  | 
 | ||
|  |       var dir = inDirName.split("\\").join("/"); | ||
|  |       Log.v('Try to get version from directory name "$dir"'); | ||
|  |       var extract_version = ~/\/?(android-ndk-)?r(\d+)([a-z]?)$/; | ||
|  |       if (extract_version.match(dir)) | ||
|  |       { | ||
|  |          var major:Int = Std.parseInt( extract_version.matched(2) ); | ||
|  |          var result:Float = 1.0 * major; | ||
|  |          var minor = extract_version.matched(3); | ||
|  |          if (minor!=null && minor.length>0) | ||
|  |             result += 0.001 * (minor.toLowerCase().charCodeAt(0)-'a'.code); | ||
|  |          return result; | ||
|  |       } | ||
|  | 
 | ||
|  |       Log.v('Could not deduce NDK version from "$inDirName" - assuming 8'); | ||
|  |       return 8; | ||
|  |    } | ||
|  | 
 | ||
|  |    public static function initHXCPPConfig(ioDefines:Hash<String>) | ||
|  |    { | ||
|  |       var env = Sys.environment(); | ||
|  |       // If the user has set it themselves, they mush know what they are doing... | ||
|  |       if (env.exists("HXCPP_CONFIG")) | ||
|  |          return; | ||
|  | 
 | ||
|  |       var home = ""; | ||
|  |       if (env.exists("HOME")) | ||
|  |          home = env.get("HOME"); | ||
|  |       else if (env.exists("USERPROFILE")) | ||
|  |          home = env.get("USERPROFILE"); | ||
|  |       else | ||
|  |       { | ||
|  |          Log.warn("No $HOME variable set, \".hxcpp_config.xml\" might be missing"); | ||
|  |          //Sys.println("Warning: No 'HOME' variable set - .hxcpp_config.xml might be missing."); | ||
|  |          return; | ||
|  |       } | ||
|  | 
 | ||
|  |       ioDefines.set("HXCPP_HOME", home); | ||
|  | 
 | ||
|  |       var  config = toPath(home+"/.hxcpp_config.xml"); | ||
|  |       ioDefines.set("HXCPP_CONFIG",config); | ||
|  | 
 | ||
|  |       if (BuildTool.HXCPP!="") | ||
|  |       { | ||
|  |          var src = toPath(BuildTool.HXCPP + "/toolchain/example.hxcpp_config.xml"); | ||
|  |          if (!sys.FileSystem.exists(config)) | ||
|  |          { | ||
|  |             try | ||
|  |             { | ||
|  |                Log.info("", "Copying HXCPP config \"" + src + "\" to \"" + config + "\""); | ||
|  |                sys.io.File.copy(src,config); | ||
|  |             } | ||
|  |             catch(e:Dynamic) | ||
|  |             { | ||
|  |                Log.warn("Could not create HXCPP config \"" + config + "\""); | ||
|  |                //Sys.println("Warning : could not create config: " + config ); | ||
|  |             } | ||
|  |          } | ||
|  |       } | ||
|  |    } | ||
|  | 
 | ||
|  |    public static function setupMingw(ioDefines:Hash<String>) | ||
|  |    { | ||
|  |       // Setup MINGW_ROOT or fail | ||
|  |       if (!ioDefines.exists("MINGW_ROOT")) | ||
|  |       { | ||
|  | 
 | ||
|  |          var haxelib = PathManager.getHaxelib("minimingw","",false); | ||
|  |          if (haxelib!=null && haxelib!="") | ||
|  |          { | ||
|  |             ioDefines.set("MINGW_ROOT", haxelib); | ||
|  |             Log.v('Using haxelib version of MinGW, $haxelib'); | ||
|  |             return; | ||
|  |          } | ||
|  | 
 | ||
|  |          var guesses = ["c:/MinGW"]; | ||
|  |          for (guess in guesses) | ||
|  |          { | ||
|  |             if (FileSystem.exists(guess)) | ||
|  |             { | ||
|  |                ioDefines.set("MINGW_ROOT", guess); | ||
|  |                Log.v('Using default version of MinGW, $guess'); | ||
|  |                return; | ||
|  |             } | ||
|  |          } | ||
|  | 
 | ||
|  |          if (ioDefines.exists("mingw")) | ||
|  |          { | ||
|  |             //when mingw is explicitly indicated but not properly configured, this log will be shown | ||
|  |             Log.error('Could not guess MINGW_ROOT (tried $guesses) - please set explicitly'); | ||
|  |          } | ||
|  |          else | ||
|  |          { | ||
|  |             //when both mingw and MSVC is not properly configured, this log will be shown | ||
|  |             Log.error('Could not setup any C++ compiler, please install or reinstall a valid C++ compiler'); | ||
|  |          } | ||
|  |       } | ||
|  |    } | ||
|  | 
 | ||
|  | 
 | ||
|  |    public static function setupEmscripten(ioDefines:Hash<String>) | ||
|  |    { | ||
|  |       // Setup EMSCRIPTEN_SDK if possible - else assume developer has it in path | ||
|  |       if (!ioDefines.exists("EMSCRIPTEN_SDK")) | ||
|  |       { | ||
|  |          var home = ioDefines.get("HXCPP_HOME"); | ||
|  |          var file = home + "/.emscripten"; | ||
|  |          if (FileSystem.exists(file)) | ||
|  |          { | ||
|  |             var content = sys.io.File.getContent(file); | ||
|  |             content = content.split("\r").join(""); | ||
|  |             var value = ~/^(\w*)\s*=\s*'(.*)'/; | ||
|  |             for (line in content.split("\n")) | ||
|  |             { | ||
|  |                if (value.match(line)) | ||
|  |                { | ||
|  |                   var name = value.matched(1); | ||
|  |                   var val= value.matched(2); | ||
|  |                   if (name=="EMSCRIPTEN_ROOT") | ||
|  |                   { | ||
|  |                      ioDefines.set("EMSCRIPTEN_SDK", val); | ||
|  |                   } | ||
|  |                   if (name=="PYTHON") | ||
|  |                      ioDefines.set("EMSCRIPTEN_PYTHON", val); | ||
|  |                   if (name=="NODE_JS") | ||
|  |                      ioDefines.set("EMSCRIPTEN_NODE_JS", val); | ||
|  |                } | ||
|  |             } | ||
|  |          } | ||
|  |       } | ||
|  |    } | ||
|  | 
 | ||
|  | 
 | ||
|  |    public static function isRaspberryPi() | ||
|  |    { | ||
|  |        var modelFile = '/sys/firmware/devicetree/base/model'; | ||
|  |        if( !FileSystem.exists( modelFile ) ) | ||
|  |            return false; | ||
|  |        try { | ||
|  |            var model = sys.io.File.getContent( modelFile ); | ||
|  |            return ~/Raspberry/.match( model ); | ||
|  |        } catch(e:Dynamic) { | ||
|  |            trace( e ); | ||
|  |        } | ||
|  |        return false; | ||
|  |    } | ||
|  | 
 | ||
|  |    static public function startPdbServer() | ||
|  |    { | ||
|  |       var oldPath = Sys.getCwd(); | ||
|  |       try | ||
|  |       { | ||
|  |          // Run it in hxcpp directory so it does not lock the build directory after build finishes | ||
|  |          Sys.setCwd(BuildTool.HXCPP); | ||
|  |          var proc = new Process("mspdbsrv.exe",["-start"]); | ||
|  |          Tools.addOnExitHook(function(_) { | ||
|  |            proc.kill(); | ||
|  |          }); | ||
|  |       } | ||
|  |       catch(e:Dynamic) | ||
|  |       { | ||
|  |          Log.v("Could not start mspdbsrv:" + e); | ||
|  |       } | ||
|  |       Sys.setCwd(oldPath); | ||
|  |    } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  |    public static function setup(inWhat:String,ioDefines:Map<String,String>) | ||
|  |    { | ||
|  |       if (ioDefines.exists("HXCPP_CLEAN_ONLY")) | ||
|  |          return; | ||
|  | 
 | ||
|  |       Profile.push("setup " + inWhat); | ||
|  |       if (inWhat=="androidNdk") | ||
|  |       { | ||
|  |          setupAndroidNdk(ioDefines); | ||
|  |       } | ||
|  |       else if (inWhat=="blackberry") | ||
|  |       { | ||
|  |          setupBlackBerryNativeSDK(ioDefines); | ||
|  |       } | ||
|  |       else if (inWhat=="msvc") | ||
|  |       { | ||
|  |          setupMSVC(ioDefines, ioDefines.exists("HXCPP_M64"), ioDefines.exists("HXCPP_ARM64"), ioDefines.exists("winrt")); | ||
|  |       } | ||
|  |       else if (inWhat=="pdbserver") | ||
|  |       { | ||
|  |          startPdbServer(); | ||
|  |       } | ||
|  |       else if (inWhat=="mingw") | ||
|  |       { | ||
|  |          setupMingw(ioDefines); | ||
|  |       } | ||
|  |       else if (inWhat=="emscripten") | ||
|  |       { | ||
|  |          setupEmscripten(ioDefines); | ||
|  |       } | ||
|  |       else if (inWhat=="nvcc") | ||
|  |       { | ||
|  |          BuildTool.setupNvcc(); | ||
|  |       } | ||
|  |       else | ||
|  |       { | ||
|  |          Log.error('Unknown setup feature "$inWhat"'); | ||
|  |          //throw 'Unknown setup feature $inWhat'; | ||
|  |       } | ||
|  |       Profile.pop(); | ||
|  |    } | ||
|  | 
 | ||
|  |    static public function setupAndroidNdk(defines:Map<String,String>) | ||
|  |    { | ||
|  |       var root:String = null; | ||
|  | 
 | ||
|  |       if (Log.verbose) Log.println(""); | ||
|  | 
 | ||
|  |       var ndkVersion = 0; | ||
|  |       for (i in 6...20) | ||
|  |       { | ||
|  |          if (defines.exists("NDKV" + i)) | ||
|  |          { | ||
|  |             ndkVersion = i; | ||
|  |             Log.info("", "\x1b[33;1mRequested Android NDK r" + i + "\x1b[0m"); | ||
|  |             break; | ||
|  |          } | ||
|  |       } | ||
|  | 
 | ||
|  |       if (!defines.exists("ANDROID_NDK_ROOT") || ndkVersion!=0) | ||
|  |       { | ||
|  |          root = Setup.findAndroidNdkRoot( defines, ndkVersion ); | ||
|  |          if (root==null) | ||
|  |          { | ||
|  |             var ndkDir = defines.exists("ANDROID_NDK_DIR") ? defines.get("ANDROID_NDK_DIR") : "not set"; | ||
|  |             if (ndkVersion!=0) | ||
|  |                Log.error('ANDROID_NDK_DIR ["$ndkDir"] or ndk-bundle does not contain requested NDK $ndkVersion'); | ||
|  |             else | ||
|  |                Log.error('ANDROID_NDK_DIR ["$ndkDir"] or ndk-bundle does not contain a matching NDK'); | ||
|  |          } | ||
|  |          else | ||
|  |          { | ||
|  |             Sys.putEnv("ANDROID_NDK_ROOT", root); | ||
|  |             defines.set("ANDROID_NDK_ROOT", root); | ||
|  |          } | ||
|  |       } | ||
|  |       else | ||
|  |       { | ||
|  |          root = defines.get("ANDROID_NDK_ROOT"); | ||
|  |          Log.info("", "\x1b[33;1mUsing Android NDK root: " + root + "\x1b[0m"); | ||
|  |       } | ||
|  | 
 | ||
|  |       if (ndkVersion==0) | ||
|  |       { | ||
|  |          var version = Setup.getNdkVersion( root ); | ||
|  |          if (version > 0) | ||
|  |          { | ||
|  |             Log.info("", "\x1b[33;1mDetected Android NDK " + version + "\x1b[0m"); | ||
|  |             defines.set("NDKV" + Std.int(version), "1" ); | ||
|  |             ndkVersion = Std.int(version); | ||
|  |          } | ||
|  |          else | ||
|  |             Log.error("Invalid ndk version"); | ||
|  |       } | ||
|  |       for (i in 5...ndkVersion+1) | ||
|  |          defines.set("NDKV" + i + "+", "1"); | ||
|  | 
 | ||
|  |       var arm_type = 'arm-linux-androideabi'; | ||
|  |       var arm_64 = defines.exists('HXCPP_ARM64'); | ||
|  |       if(arm_64) arm_type = 'aarch64-linux-android'; | ||
|  | 
 | ||
|  |       // Find toolchain | ||
|  |       if (!defines.exists("TOOLCHAIN_VERSION")) | ||
|  |       { | ||
|  |          try | ||
|  |          { | ||
|  |             var files = FileSystem.readDirectory(root+"/toolchains"); | ||
|  | 
 | ||
|  |             // Prefer clang? | ||
|  |             var extract_version = ~/^arm-linux-androideabi-(\d.*)/; | ||
|  |             if(arm_64) extract_version = ~/^aarch64-linux-android-(\d.*)/; | ||
|  | 
 | ||
|  |             var bestVer=""; | ||
|  |             for (file in files) | ||
|  |             { | ||
|  |                if (extract_version.match(file)) | ||
|  |                { | ||
|  |                   var ver = extract_version.matched(1); | ||
|  |                   if (ver<bestVer || bestVer=="") | ||
|  |                   { | ||
|  |                      bestVer = ver; | ||
|  |                   } | ||
|  |                } | ||
|  |             } | ||
|  |             if (bestVer!="") | ||
|  |             { | ||
|  |                defines.set("TOOLCHAIN_VERSION",bestVer); | ||
|  |                Log.info("", "\x1b[33;1mDetected Android toolchain: "+arm_type+"-" + bestVer + "\x1b[0m"); | ||
|  |             } | ||
|  |          } | ||
|  |          catch(e:Dynamic) { } | ||
|  |       } | ||
|  | 
 | ||
|  |       // See what ANDROID_HOST to use ... | ||
|  |       try | ||
|  |       { | ||
|  |          var prebuilt = root+"/toolchains/"; | ||
|  |          if (defines.exists("TOOLCHAIN_VERSION")) | ||
|  |             prebuilt += arm_type + "-" + defines.get("TOOLCHAIN_VERSION") + "/prebuilt"; | ||
|  |          else | ||
|  |             prebuilt += "llvm/prebuilt"; | ||
|  |          var files = FileSystem.readDirectory(prebuilt); | ||
|  |          for (file in files) | ||
|  |          { | ||
|  |             if (!FileSystem.isDirectory (prebuilt + "/" + file)) | ||
|  |             { | ||
|  |                files.remove (file); | ||
|  |             } | ||
|  |          } | ||
|  |          if (files.length==1) | ||
|  |          { | ||
|  |             defines.set("ANDROID_HOST", files[0]); | ||
|  |             Log.info("", "\x1b[33;1mDetected Android host: " + files[0] + "\x1b[0m"); | ||
|  |          } | ||
|  |          else | ||
|  |          { | ||
|  |             Log.info("", "\x1b[33;1mCould not detect ANDROID_HOST (" + files + ") - using default\x1b[0m"); | ||
|  |          } | ||
|  |       } | ||
|  |       catch(e:Dynamic) { } | ||
|  | 
 | ||
|  |       if(defines.exists('NDKV20+')) { | ||
|  |          Log.v([ | ||
|  |             "x86 Platform: 16", | ||
|  |             "arm Platform: 16", | ||
|  |             "x86_64 Platform: 21", | ||
|  |             "arm_64 Platform: 21", | ||
|  |             "Frameworks should set the minSdkVersion for each APK to these values." | ||
|  |          ].join('\n')); | ||
|  |       } | ||
|  |       else { | ||
|  |          globallySetThePlatform(root, defines); | ||
|  |       } | ||
|  |    } | ||
|  | 
 | ||
|  |    private static function globallySetThePlatform(root:String, defines:Map<String,String>) { | ||
|  |       var androidPlatform = 5; | ||
|  |       if (!defines.exists("PLATFORM")) | ||
|  |       { | ||
|  |          for (i in 5...100) | ||
|  |          { | ||
|  |             var test = "android-" + i; | ||
|  |             if (defines.exists(test)) | ||
|  |             { | ||
|  |                defines.set("PLATFORM",test); | ||
|  |                break; | ||
|  |             } | ||
|  |          } | ||
|  |       } | ||
|  | 
 | ||
|  |       if (defines.exists("PLATFORM")) | ||
|  |       { | ||
|  |          var platform = defines.get("PLATFORM"); | ||
|  |          var id = Std.parseInt( platform.substr("android-".length) ); | ||
|  |          if (id==0 || id==null) | ||
|  |             Log.error('Badly formed android PLATFORM "$platform" - should be like android-123'); | ||
|  |          androidPlatform = id; | ||
|  |          Log.info("", "\x1b[33;1mUsing Android NDK platform: " + defines.get("PLATFORM") + "\x1b[0m"); | ||
|  |       } | ||
|  |       else | ||
|  |       { | ||
|  |          var base = root + "/platforms"; | ||
|  |          var best = 0; | ||
|  |          try | ||
|  |          { | ||
|  |             for (file in FileSystem.readDirectory(base)) | ||
|  |             { | ||
|  |                if (file.substr(0,8)=="android-") | ||
|  |                { | ||
|  |                   var platform = Std.parseInt(file.substr(8)); | ||
|  |                   if (platform>best) | ||
|  |                      best = platform; | ||
|  |                } | ||
|  |             } | ||
|  |          } catch(e:Dynamic) {} | ||
|  | 
 | ||
|  |          if (best==0) | ||
|  |          { | ||
|  |             Log.error("Could not detect Android API platforms in \"" + base + "\""); | ||
|  |             //throw "Could not find platform in " + base; | ||
|  |          } | ||
|  | 
 | ||
|  |          Log.info("", "\x1b[33;1mUsing newest Android NDK platform: " + best + "\x1b[0m"); | ||
|  |          defines.set("PLATFORM", "android-" + best); | ||
|  |          androidPlatform = best; | ||
|  |       } | ||
|  |       defines.set("ANDROID_PLATFORM_DEFINE", "HXCPP_ANDROID_PLATFORM=" + androidPlatform); | ||
|  |       if (Log.verbose) Log.println(""); | ||
|  |    } | ||
|  | 
 | ||
|  |    public static function setupBlackBerryNativeSDK(ioDefines:Hash<String>) | ||
|  |    { | ||
|  |       if (!ioDefines.exists ("BLACKBERRY_NDK_ROOT")) | ||
|  |       { | ||
|  |           Log.error("Could not find BLACKBERRY_NDK_ROOT variable"); | ||
|  |       } | ||
|  | 
 | ||
|  |       var fileName = ioDefines.get ("BLACKBERRY_NDK_ROOT"); | ||
|  |       if (BuildTool.isWindows) | ||
|  |       { | ||
|  |          fileName += "\\bbndk-env.bat"; | ||
|  |       } | ||
|  |       else | ||
|  |       { | ||
|  |          fileName += "/bbndk-env.sh"; | ||
|  |       } | ||
|  | 
 | ||
|  |       if (FileSystem.exists (fileName)) | ||
|  |       { | ||
|  |          var fin = sys.io.File.read(fileName, false); | ||
|  |          try | ||
|  |          { | ||
|  |             while(true) | ||
|  |             { | ||
|  |                var str = fin.readLine(); | ||
|  |                var split = str.split ("="); | ||
|  |                var name = StringTools.trim (split[0].substr (split[0].lastIndexOf (" ") + 1)); | ||
|  |                switch (name) | ||
|  |                { | ||
|  |                   case "QNX_HOST", "QNX_TARGET", "QNX_HOST_VERSION", "QNX_TARGET_VERSION": | ||
|  |                      var value = split[1]; | ||
|  |                      if (StringTools.startsWith (value, "${") && split.length > 2) | ||
|  |                      { | ||
|  |                         value = split[2].substr (0, split[2].length - 1); | ||
|  |                      } | ||
|  |                      if (StringTools.startsWith(value, "\"")) | ||
|  |                      { | ||
|  |                         value = value.substr (1); | ||
|  |                      } | ||
|  |                      if (StringTools.endsWith(value, "\"")) | ||
|  |                      { | ||
|  |                         value = value.substr (0, value.length - 1); | ||
|  |                      } | ||
|  |                      if (name == "QNX_HOST_VERSION" || name == "QNX_TARGET_VERSION") | ||
|  |                      { | ||
|  |                         if (Sys.getEnv (name) != null) | ||
|  |                         { | ||
|  |                            continue; | ||
|  |                         } | ||
|  |                      } | ||
|  |                      else | ||
|  |                      { | ||
|  |                         value = StringTools.replace (value, "$BASE_DIR", ioDefines.get ("BLACKBERRY_NDK_ROOT")); | ||
|  |                         value = StringTools.replace (value, "%BASE_DIR%", ioDefines.get ("BLACKBERRY_NDK_ROOT")); | ||
|  |                         value = StringTools.replace (value, "$TARGET", "qnx6"); | ||
|  |                         value = StringTools.replace (value, "%TARGET%", "qnx6"); | ||
|  |                         value = StringTools.replace (value, "$QNX_HOST_VERSION", Sys.getEnv("QNX_HOST_VERSION")); | ||
|  |                         value = StringTools.replace (value, "$QNX_TARGET_VERSION", Sys.getEnv("QNX_TARGET_VERSION")); | ||
|  |                         value = StringTools.replace (value, "%QNX_HOST_VERSION%", Sys.getEnv("QNX_HOST_VERSION")); | ||
|  |                         value = StringTools.replace (value, "%QNX_TARGET_VERSION%", Sys.getEnv("QNX_TARGET_VERSION")); | ||
|  |                      } | ||
|  |                      ioDefines.set(name,value); | ||
|  |                      Sys.putEnv(name,value); | ||
|  |                } | ||
|  |             } | ||
|  |          } | ||
|  |          catch( ex:Eof ) | ||
|  |          {} | ||
|  |          fin.close(); | ||
|  |       } | ||
|  |       else | ||
|  |       { | ||
|  |          Log.error("Could not find \"" + fileName + "\""); | ||
|  |       } | ||
|  |    } | ||
|  | 
 | ||
|  |    public static function setupMSVC(ioDefines:Hash<String>, in64:Bool, inArm64, isWinRT:Bool) | ||
|  |    { | ||
|  |       var detectMsvc = !ioDefines.exists("NO_AUTO_MSVC") && | ||
|  |                        !ioDefines.exists("HXCPP_MSVC_CUSTOM"); | ||
|  | 
 | ||
|  |       if (ioDefines.exists("HXCPP_MSVC_VER")) | ||
|  |       { | ||
|  |          var val = ioDefines.get("HXCPP_MSVC_VER"); | ||
|  |          if (val=="") | ||
|  |             detectMsvc = false; | ||
|  |          else | ||
|  |          { | ||
|  |             var ival = Std.parseInt(ioDefines.get("HXCPP_MSVC_VER")); | ||
|  |             if (ival>0) | ||
|  |             { | ||
|  |                var varName = "VS" + ival+ "COMNTOOLS"; | ||
|  |                var where = Sys.getEnv(varName); | ||
|  |                if (where==null) | ||
|  |                { | ||
|  |                   for (env in Sys.environment().keys()) | ||
|  |                   { | ||
|  |                      if (env.substr(0,2)=="VS") | ||
|  |                      { | ||
|  |                         Log.info("Found VS variable: " + env); | ||
|  |                         //Sys.println("Found VS variable " + env); | ||
|  |                      } | ||
|  |                   } | ||
|  |                   Log.error("Could not find specified MSVC version: " + ival); | ||
|  |                   //throw "Could not find specified MSVC version " + ival; | ||
|  |                } | ||
|  |                ioDefines.set("HXCPP_MSVC", where ); | ||
|  |                Sys.putEnv("HXCPP_MSVC", where); | ||
|  |                Log.info("", 'Using MSVC Ver $ival in $where ($varName)'); | ||
|  |             } | ||
|  |             else | ||
|  |             { | ||
|  |                Log.info("", 'Using specified MSVC Ver $val'); | ||
|  |                ioDefines.set("HXCPP_MSVC", val ); | ||
|  |                Sys.putEnv("HXCPP_MSVC", val); | ||
|  |             } | ||
|  |         } | ||
|  |       } | ||
|  | 
 | ||
|  |       if (detectMsvc) | ||
|  |       { | ||
|  |         var extra:String = ""; | ||
|  |         if (isWinRT) | ||
|  |             extra += "-winrt"; | ||
|  |         if (inArm64) | ||
|  |             extra += "-arm64"; | ||
|  |         else if (in64) | ||
|  |             extra += "64"; | ||
|  |          var xpCompat = false; | ||
|  |          if (ioDefines.exists("HXCPP_WINXP_COMPAT")) | ||
|  |          { | ||
|  |             Sys.putEnv("HXCPP_WINXP_COMPAT","1"); | ||
|  |             xpCompat = true; | ||
|  |          } | ||
|  |          Sys.putEnv("msvc_host_arch", ioDefines.exists("windows_arm_host") ? "x86" : "x64" ); | ||
|  | 
 | ||
|  |          var vc_setup_proc = new Process("cmd.exe", ["/C", BuildTool.HXCPP + "\\toolchain\\msvc" + extra + "-setup.bat" ]); | ||
|  |          var vars_found = false; | ||
|  |          var error_string = ""; | ||
|  |          var output = new Array<String>(); | ||
|  |          try{ | ||
|  |             while(true) | ||
|  |             { | ||
|  |                var str = vc_setup_proc.stdout.readLine(); | ||
|  |                if (str=="HXCPP_VARS") | ||
|  |                   vars_found = true; | ||
|  |                else if (!vars_found) | ||
|  |                { | ||
|  |                   if (str.substr(0,5)=="Error" || ~/missing/.match(str) ) | ||
|  |                      error_string = str; | ||
|  | 
 | ||
|  |                   output.push(str); | ||
|  |                } | ||
|  |                else | ||
|  |                { | ||
|  |                   var pos = str.indexOf("="); | ||
|  |                   var name = str.substr(0,pos); | ||
|  |                   switch(name.toLowerCase()) | ||
|  |                   { | ||
|  |                      case "path", "vcinstalldir", "windowssdkdir","framework35version", | ||
|  |                         "frameworkdir", "frameworkdir32", "frameworkversion", | ||
|  |                         "frameworkversion32", "devenvdir", "include", "lib", "libpath", "hxcpp_xp_define", | ||
|  |                         "hxcpp_hack_pdbsrv" | ||
|  |                       : | ||
|  |                         var value = str.substr(pos+1); | ||
|  |                         ioDefines.set(name,value); | ||
|  |                         Log.v('  msvs $name=$value'); | ||
|  |                         Sys.putEnv(name,value); | ||
|  |                   } | ||
|  |                } | ||
|  |             } | ||
|  |          } catch (e:Dynamic) { | ||
|  |          }; | ||
|  | 
 | ||
|  |          vc_setup_proc.exitCode(); | ||
|  |          vc_setup_proc.close(); | ||
|  |          if (!vars_found || error_string!="") | ||
|  |          { | ||
|  |             for (o in output) | ||
|  |             { | ||
|  |                Log.info(o); | ||
|  |                //BuildTool.println(o); | ||
|  |             } | ||
|  |             if (error_string!="") | ||
|  |             { | ||
|  |                Log.error (error_string); | ||
|  |                //throw(error_string); | ||
|  |             } | ||
|  |             else | ||
|  |             { | ||
|  |                Log.info("Missing HXCPP_VARS"); | ||
|  |                //BuildTool.println("Missing HXCPP_VARS"); | ||
|  |             } | ||
|  | 
 | ||
|  |             Log.error("Could not automatically setup MSVC"); | ||
|  |             //throw("Could not automatically setup MSVC"); | ||
|  |          } | ||
|  |       } | ||
|  | 
 | ||
|  |       try | ||
|  |       { | ||
|  |          var proc = new Process("cl.exe",[]); | ||
|  |          var str = proc.stderr.readLine(); | ||
|  |          proc.close(); | ||
|  |          if (str>"") | ||
|  |          { | ||
|  |             Log.v("MSVC output:" + str); | ||
|  |             var reg = ~/(\d{2})\.\d+/i; | ||
|  |             if (reg.match(str)) | ||
|  |             { | ||
|  |                var cl_version = Std.parseInt(reg.matched(1)); | ||
|  |                Log.info("", "Using MSVC version: " + cl_version); | ||
|  |                ioDefines.set("MSVC_VER", cl_version+""); | ||
|  |                if (cl_version>=17) | ||
|  |                   ioDefines.set("MSVC17+","1"); | ||
|  |                if (cl_version>=18) | ||
|  |                   ioDefines.set("MSVC18+","1"); | ||
|  |                if (cl_version==19) | ||
|  |                   ioDefines.set("MSVC19","1"); | ||
|  |                BuildTool.sAllowNumProcs = cl_version >= 14; | ||
|  |                var threads = BuildTool.getThreadCount(); | ||
|  |                if (threads>1 && cl_version>=18) | ||
|  |                   ioDefines.set("HXCPP_FORCE_PDB_SERVER","1"); | ||
|  |             } | ||
|  |          } | ||
|  |       } catch(e:Dynamic){} | ||
|  |       //if (cl_version!="") BuildTool.println("Using cl version: " + cl_version); | ||
|  |    } | ||
|  | 
 | ||
|  |    static function toPath(inPath:String) | ||
|  |    { | ||
|  |       if (!BuildTool.isWindows) | ||
|  |          return inPath; | ||
|  |       var bits = inPath.split("/"); | ||
|  |       return bits.join("\\"); | ||
|  |    } | ||
|  | } |