2553 lines
		
	
	
		
			85 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
			
		
		
	
	
			2553 lines
		
	
	
		
			85 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
import CopyFile.Overwrite;
 | 
						|
import haxe.io.Path;
 | 
						|
import haxe.Json;
 | 
						|
import sys.io.Process;
 | 
						|
import sys.FileSystem;
 | 
						|
 | 
						|
#if haxe4
 | 
						|
import sys.thread.Thread;
 | 
						|
import sys.thread.Mutex;
 | 
						|
import sys.thread.Tls;
 | 
						|
#elseif neko
 | 
						|
import neko.vm.Thread;
 | 
						|
import neko.vm.Mutex;
 | 
						|
import neko.vm.Tls;
 | 
						|
#else
 | 
						|
import cpp.vm.Thread;
 | 
						|
import cpp.vm.Mutex;
 | 
						|
import cpp.vm.Tls;
 | 
						|
#end
 | 
						|
 | 
						|
import haxe.crypto.Md5;
 | 
						|
 | 
						|
import Log.NORMAL;
 | 
						|
import Log.BOLD;
 | 
						|
import Log.ITALIC;
 | 
						|
import Log.YELLOW;
 | 
						|
import Log.WHITE;
 | 
						|
 | 
						|
using StringTools;
 | 
						|
 | 
						|
#if (haxe_ver>=4)
 | 
						|
typedef XmlAccess = haxe.xml.Access;
 | 
						|
#else
 | 
						|
typedef XmlAccess = haxe.xml.Fast;
 | 
						|
#end
 | 
						|
 | 
						|
#if haxe3
 | 
						|
typedef Hash<T> = haxe.ds.StringMap<T>;
 | 
						|
#end
 | 
						|
typedef FileGroups = Hash<FileGroup>;
 | 
						|
typedef Targets = Hash<Target>;
 | 
						|
typedef Prelinkers = Hash<Prelinker>;
 | 
						|
typedef Linkers = Hash<Linker>;
 | 
						|
 | 
						|
 | 
						|
class BuildTool
 | 
						|
{
 | 
						|
   public inline static var SupportedVersion = 430;
 | 
						|
 | 
						|
   var mDefines:Hash<String>;
 | 
						|
   var mCurrentIncludeFile:String;
 | 
						|
   var mIncludePath:Array<String>;
 | 
						|
   var mCompiler:Compiler;
 | 
						|
   var mStripper:Stripper;
 | 
						|
   var mManifester:Manifester;
 | 
						|
   var mPrelinkers:Prelinkers;
 | 
						|
   var mLinkers:Linkers;
 | 
						|
   var mCopyFiles:Array<CopyFile>;
 | 
						|
   var mFileGroups:FileGroups;
 | 
						|
   var mTargets:Targets;
 | 
						|
   var mFileStack:Array<String>;
 | 
						|
   var mMakefile:String;
 | 
						|
   var mMagicLibs:Array<{name:String, replace:String}>;
 | 
						|
   var mPragmaOnce:Map<String,Bool>;
 | 
						|
   var mNvccFlags:Array<String>;
 | 
						|
   var mNvccLinkFlags:Array<String>;
 | 
						|
   var mDirtyList:Array<String>;
 | 
						|
   var arm64:Bool;
 | 
						|
   var m64:Bool;
 | 
						|
   var m32:Bool;
 | 
						|
 | 
						|
   public static var os="";
 | 
						|
   public static var sAllowNumProcs = true;
 | 
						|
   public static var sCompileThreadCount = 1;
 | 
						|
   public static var sThreadPool:ThreadPool;
 | 
						|
   public static var sReportedThreads = -1;
 | 
						|
   public static var HXCPP = "";
 | 
						|
   public static var is64 = false;
 | 
						|
   public static var isWindows = false;
 | 
						|
   public static var isWindowsArm = false;
 | 
						|
   public static var isLinux = false;
 | 
						|
   public static var isRPi = false;
 | 
						|
   public static var isMac = false;
 | 
						|
   public static var targetKey:String;
 | 
						|
   public static var instance:BuildTool;
 | 
						|
   public static var helperThread = new Tls<Thread>();
 | 
						|
   public static var destination:String;
 | 
						|
   public static var outputs = new Array<String>();
 | 
						|
   public static var groupMutex = new Mutex();
 | 
						|
   static var mVarMatch = new EReg("\\${(.*?)}","");
 | 
						|
   static var mNoDollarMatch = new EReg("{(.*?)}","");
 | 
						|
 | 
						|
   public static var exitOnThreadError = false;
 | 
						|
   public static var threadExitCode = 0;
 | 
						|
   public static var startDir:String;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
   public function new(inJob:String,inDefines:Hash<String>,inTargets:Array<String>,
 | 
						|
        inIncludePath:Array<String>, inDirtyList:Array<String> )
 | 
						|
   {
 | 
						|
      mDefines = inDefines;
 | 
						|
      mFileGroups = new FileGroups();
 | 
						|
      mCompiler = null;
 | 
						|
      mStripper = null;
 | 
						|
      mTargets = new Targets();
 | 
						|
      mPrelinkers = new Prelinkers();
 | 
						|
      mLinkers = new Linkers();
 | 
						|
      mCurrentIncludeFile = "";
 | 
						|
      mFileStack = [];
 | 
						|
      mCopyFiles = [];
 | 
						|
      mIncludePath = inIncludePath;
 | 
						|
      mPragmaOnce = new Map<String,Bool>();
 | 
						|
      mMagicLibs = [];
 | 
						|
      mNvccFlags = [];
 | 
						|
      mNvccLinkFlags = [];
 | 
						|
      mMakefile = "";
 | 
						|
      mDirtyList = inDirtyList;
 | 
						|
 | 
						|
      if (inJob=="cache")
 | 
						|
      {
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
         mMakefile = inJob;
 | 
						|
         if (!PathManager.isAbsolute(mMakefile) && sys.FileSystem.exists(mMakefile))
 | 
						|
            mMakefile = sys.FileSystem.fullPath(mMakefile);
 | 
						|
         mDefines.set("HXCPP_BUILD_DIR", Path.addTrailingSlash(Path.directory(mMakefile)) );
 | 
						|
      }
 | 
						|
 | 
						|
 | 
						|
      instance = this;
 | 
						|
 | 
						|
      m64 = mDefines.exists("HXCPP_M64");
 | 
						|
      m32 = mDefines.exists("HXCPP_M32");
 | 
						|
      arm64 = mDefines.exists("HXCPP_ARM64");
 | 
						|
      if (m64==m32 && !arm64)
 | 
						|
      {
 | 
						|
         var arch = getArch();
 | 
						|
 | 
						|
         // Default to the current OS version.  windowsArm runs m32 code too
 | 
						|
         m64 = arch=="m64";
 | 
						|
         m32 = arch=="m32";
 | 
						|
         arm64 = arch=="arm64";
 | 
						|
         mDefines.remove(m32 ? "HXCPP_M64" : "HXCPP_M32");
 | 
						|
         set64(mDefines,m64,arm64);
 | 
						|
      }
 | 
						|
 | 
						|
      Profile.setEntry("parse xml");
 | 
						|
 | 
						|
      include("toolchain/setup.xml");
 | 
						|
 | 
						|
 | 
						|
 | 
						|
      if (mDefines.exists("toolchain"))
 | 
						|
      {
 | 
						|
         if (!mDefines.exists("BINDIR"))
 | 
						|
         {
 | 
						|
            mDefines.set("BINDIR", Path.withoutDirectory(Path.withoutExtension(mDefines.get("toolchain"))));
 | 
						|
         }
 | 
						|
         if ( (new EReg("window","i")).match(os) )
 | 
						|
            mDefines.set("windows_host","1");
 | 
						|
      }
 | 
						|
      else
 | 
						|
         setDefaultToolchain(mDefines);
 | 
						|
 | 
						|
 | 
						|
      if (mDefines.exists("dll_import"))
 | 
						|
      {
 | 
						|
         var path = new Path(mDefines.get("dll_import"));
 | 
						|
         if (!mDefines.exists("dll_import_include"))
 | 
						|
            mDefines.set("dll_import_include", path.dir + "/include" );
 | 
						|
         if (!mDefines.exists("dll_import_link"))
 | 
						|
            mDefines.set("dll_import_link", mDefines.get("dll_import") );
 | 
						|
      }
 | 
						|
 | 
						|
      setupAppleDirectories(mDefines);
 | 
						|
 | 
						|
      if (isMsvc())
 | 
						|
      {
 | 
						|
         mDefines.set("isMsvc","1");
 | 
						|
         if (Std.parseInt(mDefines.get("MSVC_VER"))>=18)
 | 
						|
            mDefines.set("MSVC18+","1");
 | 
						|
      }
 | 
						|
 | 
						|
      include("toolchain/finish-setup.xml", false);
 | 
						|
 | 
						|
 | 
						|
      if (mMakefile!="")
 | 
						|
      {
 | 
						|
         pushFile(mMakefile,"makefile");
 | 
						|
         var make_contents = "";
 | 
						|
         try {
 | 
						|
            make_contents = sys.io.File.getContent(mMakefile);
 | 
						|
         } catch (e:Dynamic) {
 | 
						|
            Log.error("Could not open build file \"" + mMakefile + "\"");
 | 
						|
            //println("Could not open build file '" + mMakefile + "'");
 | 
						|
            //Sys.exit(1);
 | 
						|
         }
 | 
						|
 | 
						|
 | 
						|
         var xml_slow = Xml.parse(make_contents);
 | 
						|
         var xml = new XmlAccess(xml_slow.firstElement());
 | 
						|
 | 
						|
         parseXML(xml,"",false);
 | 
						|
         popFile();
 | 
						|
 | 
						|
         include("toolchain/" + mDefines.get("toolchain") + "-toolchain.xml", false);
 | 
						|
 | 
						|
 | 
						|
         if (mDefines.exists("HXCPP_CONFIG"))
 | 
						|
            include(mDefines.get("HXCPP_CONFIG"),"exes",true);
 | 
						|
      }
 | 
						|
 | 
						|
      for(group in mFileGroups)
 | 
						|
         group.filter(mDefines);
 | 
						|
 | 
						|
      if (Log.verbose) Log.println ("");
 | 
						|
 | 
						|
      // MSVC needs this before the toolchain file, Emscripten wants to set HXCPP_COMPILE_THREADS
 | 
						|
      // If not already calculated in "setup"
 | 
						|
      getThreadCount();
 | 
						|
 | 
						|
      var cached = CompileCache.init(mDefines);
 | 
						|
 | 
						|
      Profile.setEntry("setup cache");
 | 
						|
 | 
						|
      if (inJob=="cache")
 | 
						|
      {
 | 
						|
         if (!cached)
 | 
						|
         {
 | 
						|
            Log.error("HXCPP_COMPILE_CACHE is not set");
 | 
						|
         }
 | 
						|
         switch(inTargets[0])
 | 
						|
         {
 | 
						|
            case "days" :
 | 
						|
               var days = inTargets[1]==null ? null : Std.parseInt(inTargets[1]);
 | 
						|
               if (days==null)
 | 
						|
               {
 | 
						|
                  Log.error("cache days - expected day count");
 | 
						|
                  Tools.exit(1);
 | 
						|
               }
 | 
						|
               CompileCache.clear(days,0,true,null);
 | 
						|
            case "resize" :
 | 
						|
               var mb = inTargets[1]==null ? null : Std.parseInt(inTargets[1]);
 | 
						|
               if (mb==null)
 | 
						|
               {
 | 
						|
                  Log.error("cache resize - expected megabyte count");
 | 
						|
                  Tools.exit(1);
 | 
						|
               }
 | 
						|
               CompileCache.clear(0,mb,true,inTargets[2]);
 | 
						|
 | 
						|
            case "clear" : CompileCache.clear(0,0,true,inTargets[1]);
 | 
						|
            case "list" : CompileCache.list(false,inTargets[1]);
 | 
						|
            case "details" : CompileCache.list(true,inTargets[1]);
 | 
						|
            default:
 | 
						|
              printUsage();
 | 
						|
              Tools.exit(1);
 | 
						|
         }
 | 
						|
         return;
 | 
						|
      }
 | 
						|
 | 
						|
      if (cached)
 | 
						|
      {
 | 
						|
         var cacheSize = mDefines.exists("HXCPP_CACHE_MB") ? Std.parseInt( mDefines.get("HXCPP_CACHE_MB") ) : 1000;
 | 
						|
         if (cacheSize!=null && cacheSize>0)
 | 
						|
            CompileCache.clear(0,cacheSize,false,null);
 | 
						|
      }
 | 
						|
 | 
						|
      if (Log.verbose) Log.println ("");
 | 
						|
 | 
						|
      if (inTargets.remove("clear"))
 | 
						|
      {
 | 
						|
         Profile.setEntry("clear");
 | 
						|
         for(target in mTargets.keys())
 | 
						|
            cleanTarget(target,false);
 | 
						|
       }
 | 
						|
 | 
						|
      if (inTargets.remove("clean"))
 | 
						|
      {
 | 
						|
         Profile.setEntry("clean");
 | 
						|
         for(target in mTargets.keys())
 | 
						|
            cleanTarget(target,true);
 | 
						|
      }
 | 
						|
 | 
						|
      if (destination!=null && inTargets.length!=1)
 | 
						|
      {
 | 
						|
         Log.warn("Exactly one target must be specified with 'destination'.  Specified:" + inTargets );
 | 
						|
         destination = null;
 | 
						|
      }
 | 
						|
 | 
						|
      Profile.setEntry("build");
 | 
						|
      for(target in inTargets)
 | 
						|
         buildTarget(target,destination);
 | 
						|
 | 
						|
      var linkOutputs = mDefines.get("HXCPP_LINK_OUTPUTS");
 | 
						|
      if (linkOutputs!=null)
 | 
						|
         sys.io.File.saveContent(linkOutputs,outputs.join("\n")+"\n");
 | 
						|
      if (Log.verbose)
 | 
						|
      {
 | 
						|
         for(out in outputs)
 | 
						|
            Log.v(" generated " + out);
 | 
						|
      }
 | 
						|
 | 
						|
      if (threadExitCode != 0)
 | 
						|
         Tools.exit(threadExitCode);
 | 
						|
   }
 | 
						|
 | 
						|
   public static function isDefault64()
 | 
						|
   {
 | 
						|
   }
 | 
						|
 | 
						|
   public function pushFile(inFilename:String, inWhy:String, inSection:String="")
 | 
						|
   {
 | 
						|
      Log.info("", " - \x1b[1mParsing " + inWhy + ":\x1b[0m " + inFilename + (inSection == "" ? "" : " \x1b[3m(section \"" + inSection + "\")\x1b[0m"));
 | 
						|
      mFileStack.push(inFilename);
 | 
						|
   }
 | 
						|
 | 
						|
   public function popFile()
 | 
						|
   {
 | 
						|
      mFileStack.pop();
 | 
						|
   }
 | 
						|
 | 
						|
   public static function addOutput(inWhat:String, inWhere:String)
 | 
						|
   {
 | 
						|
      outputs.push(inWhat + "=" + inWhere);
 | 
						|
   }
 | 
						|
 | 
						|
   public static function getThreadCount() : Int
 | 
						|
   {
 | 
						|
      if (instance==null)
 | 
						|
         return sCompileThreadCount;
 | 
						|
      var defs = instance.mDefines;
 | 
						|
      if (sAllowNumProcs)
 | 
						|
      {
 | 
						|
         var thread_var = defs.exists("HXCPP_COMPILE_THREADS") ?
 | 
						|
            defs.get("HXCPP_COMPILE_THREADS") : Sys.getEnv("HXCPP_COMPILE_THREADS");
 | 
						|
 | 
						|
         if (thread_var == null)
 | 
						|
         {
 | 
						|
            sCompileThreadCount = getNumberOfProcesses();
 | 
						|
         }
 | 
						|
         else
 | 
						|
         {
 | 
						|
            sCompileThreadCount = (Std.parseInt(thread_var)<2) ? 1 : Std.parseInt(thread_var);
 | 
						|
         }
 | 
						|
         if (sCompileThreadCount!=sReportedThreads)
 | 
						|
         {
 | 
						|
            sReportedThreads = sCompileThreadCount;
 | 
						|
            Log.v("\x1b[33;1mUsing compile threads: " + sCompileThreadCount + "\x1b[0m");
 | 
						|
         }
 | 
						|
      }
 | 
						|
      if (sCompileThreadCount>1 && sThreadPool==null)
 | 
						|
         sThreadPool = new ThreadPool(sCompileThreadCount);
 | 
						|
 | 
						|
      return sCompileThreadCount;
 | 
						|
   }
 | 
						|
 | 
						|
   public static function setThreadError(inCode:Int)
 | 
						|
   {
 | 
						|
      threadExitCode = inCode;
 | 
						|
      if (exitOnThreadError)
 | 
						|
         Tools.exit(inCode);
 | 
						|
   }
 | 
						|
 | 
						|
   public function buildTarget(inTarget:String, inDestination:String)
 | 
						|
   {
 | 
						|
      //var dependDebug = function(s:String) Log.error(s);
 | 
						|
      var dependDebug = null;
 | 
						|
 | 
						|
      // Sys.println("Build : " + inTarget );
 | 
						|
      if (!mTargets.exists(inTarget))
 | 
						|
      {
 | 
						|
         Log.error ("Could not find build target \"" + inTarget + "\"");
 | 
						|
         //throw "Could not find target '" + inTarget + "' to build.";
 | 
						|
      }
 | 
						|
      if (mCompiler==null)
 | 
						|
      {
 | 
						|
         Log.error("No compiler defined for the current build target");
 | 
						|
         //throw "No compiler defined";
 | 
						|
      }
 | 
						|
 | 
						|
      var target:Target = mTargets.get(inTarget);
 | 
						|
      target.checkError();
 | 
						|
 | 
						|
      for(sub in target.mSubTargets)
 | 
						|
         buildTarget(sub,null);
 | 
						|
 | 
						|
      var threadPool = BuildTool.sThreadPool;
 | 
						|
 | 
						|
 | 
						|
      PathManager.resetDirectoryCache();
 | 
						|
      var restoreDir = "";
 | 
						|
      if (target.mBuildDir!="")
 | 
						|
      {
 | 
						|
         restoreDir = Sys.getCwd();
 | 
						|
         Log.info("", " - \x1b[1mChanging directory:\x1b[0m " + target.mBuildDir);
 | 
						|
         Sys.setCwd(target.mBuildDir);
 | 
						|
      }
 | 
						|
 | 
						|
      targetKey = inTarget + target.getKey();
 | 
						|
 | 
						|
      var objs = new Array<String>();
 | 
						|
 | 
						|
      mCompiler.objToAbsolute();
 | 
						|
 | 
						|
      if (target.mFileGroups.length > 0)
 | 
						|
         PathManager.mkdir(mCompiler.mObjDir);
 | 
						|
 | 
						|
      var baseDir = Sys.getCwd();
 | 
						|
      for(group in target.mFileGroups)
 | 
						|
      {
 | 
						|
         var useCache = CompileCache.hasCache && group.mUseCache;
 | 
						|
         if (!useCache && group.mUseCache)
 | 
						|
            Log.v("Ignoring compiler cache because HXCPP_COMPILE_CACHE is not valid.");
 | 
						|
 | 
						|
         var groupObjs = new Array<String>();
 | 
						|
 | 
						|
         if (group.mDir!="." && group.mSetImportDir)
 | 
						|
            Sys.setCwd( PathManager.combine(baseDir, group.mDir ) );
 | 
						|
         group.checkOptions(mCompiler.mObjDir);
 | 
						|
 | 
						|
         group.checkDependsExist();
 | 
						|
 | 
						|
         if (!mCompiler.initPrecompile(mDefines.get("USE_PRECOMPILED_HEADERS") ))
 | 
						|
            group.dontPrecompile();
 | 
						|
 | 
						|
         group.preBuild();
 | 
						|
 | 
						|
         var to_be_compiled = new Array<File>();
 | 
						|
 | 
						|
         var cached = useCache && mCompiler.createCompilerVersion(group);
 | 
						|
 | 
						|
         var inList = new Array<Bool>();
 | 
						|
         var groupIsOutOfDate = mDirtyList.indexOf(group.mId)>=0 || mDirtyList.indexOf("all")>=0;
 | 
						|
 | 
						|
         if (useCache)
 | 
						|
         {
 | 
						|
            Profile.push("compute hash");
 | 
						|
            if (useCache && group.hasFiles() && threadPool!=null)
 | 
						|
            {
 | 
						|
               Log.initMultiThreaded();
 | 
						|
               var names:Array<String> = Lambda.array(Lambda.map(group.mFiles, function(file:File) {return file.mName; }));
 | 
						|
               threadPool.setArrayCount( names.length );
 | 
						|
               threadPool.runJob( function(tid) {
 | 
						|
                  var localCache = new Map<String,String>();
 | 
						|
 | 
						|
                  while(threadExitCode==0)
 | 
						|
                  {
 | 
						|
                     var id = sThreadPool.getNextIndex();
 | 
						|
                     if (id<0)
 | 
						|
                        break;
 | 
						|
 | 
						|
                     group.mFiles.get(names[id]).computeDependHash(localCache);
 | 
						|
                  }
 | 
						|
               } );
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
               for(file in group.mFiles)
 | 
						|
                  file.computeDependHash(null);
 | 
						|
            }
 | 
						|
            Profile.pop();
 | 
						|
         }
 | 
						|
 | 
						|
 | 
						|
         for(file in group.mFiles)
 | 
						|
         {
 | 
						|
            var obj_name = mCompiler.getCachedObjName(file);
 | 
						|
            groupObjs.push(obj_name);
 | 
						|
            var outOfDate = groupIsOutOfDate || file.isOutOfDate(obj_name, dependDebug);
 | 
						|
            if (outOfDate)
 | 
						|
            {
 | 
						|
               if (dependDebug!=null)
 | 
						|
                  dependDebug(mCompiler.getCacheString(file));
 | 
						|
               to_be_compiled.push(file);
 | 
						|
            }
 | 
						|
            inList.push(outOfDate);
 | 
						|
         }
 | 
						|
         var someCompiled = to_be_compiled.length > 0;
 | 
						|
 | 
						|
         var pchStamp:Null<Float> = null;
 | 
						|
         if (group.mPrecompiledHeader!="")
 | 
						|
         {
 | 
						|
            Profile.push("pch");
 | 
						|
 | 
						|
            var obj = mCompiler.precompile(group,cached || to_be_compiled.length==0);
 | 
						|
            if (obj!=null)
 | 
						|
            {
 | 
						|
               pchStamp = FileSystem.stat(obj).mtime.getTime();
 | 
						|
               groupObjs.push(obj);
 | 
						|
 | 
						|
               /*
 | 
						|
               for(i in 0...group.mFiles.length)
 | 
						|
               {
 | 
						|
                  var obj_name = groupObjs[i];
 | 
						|
                  if (!inList[i])
 | 
						|
                  {
 | 
						|
                     if (FileSystem.stat(obj_name).mtime.getTime() < pchStamp)
 | 
						|
                     {
 | 
						|
                        groupObjs.push(obj_name);
 | 
						|
                        trace(' Add $obj_name');
 | 
						|
                     }
 | 
						|
                     else
 | 
						|
                        trace(' Ok $obj_name');
 | 
						|
                  }
 | 
						|
                  else
 | 
						|
                  {
 | 
						|
                        trace(' Listed $obj_name  ' + group.mFiles[i].mName);
 | 
						|
                  }
 | 
						|
               }
 | 
						|
               */
 | 
						|
            }
 | 
						|
            Profile.pop();
 | 
						|
         }
 | 
						|
 | 
						|
         if (group.mConfig!="")
 | 
						|
         {
 | 
						|
            var lines = ["#ifndef HXCPP_CONFIG_INCLUDED","#define HXCPP_CONFIG_INCLUDED"];
 | 
						|
 | 
						|
            var flags = group.mCompilerFlags.concat(mCompiler.getCompilerDefines("haxe"));
 | 
						|
            var define = ~/^-D([^=]*)=?(.*)/;
 | 
						|
            for(flag in flags)
 | 
						|
            {
 | 
						|
                if (define.match(flag))
 | 
						|
                {
 | 
						|
                   var name = define.matched(1);
 | 
						|
                   var val = define.matched(2);
 | 
						|
                   lines.push("");
 | 
						|
                   lines.push( '#if !defined($name) && !defined(NO_$name)' );
 | 
						|
                   lines.push( '#define $name $val' );
 | 
						|
                   lines.push( '#endif' );
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            lines.push("");
 | 
						|
            lines.push("#include <hxcpp.h>");
 | 
						|
            lines.push("");
 | 
						|
            lines.push("#endif");
 | 
						|
            lines.push("");
 | 
						|
 | 
						|
            var filename = mDefines.exists("HXCPP_OUTPUT_CONFIG_NAME") ?
 | 
						|
                           mDefines.get("HXCPP_OUTPUT_CONFIG_NAME") :
 | 
						|
                           PathManager.combine( target.mOutputDir, group.mConfig );
 | 
						|
            if (!PathManager.isAbsolute(filename))
 | 
						|
               filename = PathManager.combine( Sys.getCwd(), filename);
 | 
						|
 | 
						|
            var content = lines.join("\n");
 | 
						|
            if (!FileSystem.exists(filename) || sys.io.File.getContent(filename)!=content)
 | 
						|
               sys.io.File.saveContent(filename, content);
 | 
						|
            addOutput("config",filename);
 | 
						|
         }
 | 
						|
 | 
						|
 | 
						|
         var nvcc = group.mNvcc;
 | 
						|
         var first = true;
 | 
						|
         var groupHeader = (!Log.quiet && !Log.verbose) ? function()
 | 
						|
         {
 | 
						|
            if (first)
 | 
						|
            {
 | 
						|
               groupMutex.acquire();
 | 
						|
               if (first)
 | 
						|
               {
 | 
						|
                  first = false;
 | 
						|
                  Log.lock();
 | 
						|
                  Log.println("");
 | 
						|
                  Log.info("\x1b[33;1mCompiling group: " + group.mId + "\x1b[0m");
 | 
						|
                  var message = "\x1b[1m" + (nvcc ? getNvcc() : mCompiler.mExe) + "\x1b[0m";
 | 
						|
                  var flags = group.mCompilerFlags;
 | 
						|
                  if (!nvcc)
 | 
						|
                     flags = flags.concat(mCompiler.getFlagStrings());
 | 
						|
                  else
 | 
						|
                     flags = flags.concat( BuildTool.getNvccFlags() );
 | 
						|
 | 
						|
                  for (compilerFlag in flags)
 | 
						|
                  {
 | 
						|
                     if (StringTools.startsWith(compilerFlag, "-D"))
 | 
						|
                     {
 | 
						|
                        var index = compilerFlag.indexOf("(");
 | 
						|
                        if (index > -1)
 | 
						|
                        {
 | 
						|
                           message += " \x1b[1m" + compilerFlag.substr(0, index) + "\x1b[0m\x1b[2m" + compilerFlag.substr(index) + "\x1b[0m";
 | 
						|
                        }
 | 
						|
                        else
 | 
						|
                        {
 | 
						|
                           message += " \x1b[1m" + compilerFlag + "\x1b[0m";
 | 
						|
                        }
 | 
						|
                     }
 | 
						|
                     else
 | 
						|
                     {
 | 
						|
                        message += " \x1b[0m" + compilerFlag + "\x1b[0m";
 | 
						|
                     }
 | 
						|
                  }
 | 
						|
                  message += " \x1b[2m...\x1b[0m \x1b[2mtags=" + group.mTags.split(",") + "\x1b[0m";
 | 
						|
                  Log.info(message);
 | 
						|
                  Log.unlock();
 | 
						|
               }
 | 
						|
               groupMutex.release();
 | 
						|
            }
 | 
						|
         } : null;
 | 
						|
 | 
						|
         Profile.push("compile");
 | 
						|
         if (threadPool==null)
 | 
						|
         {
 | 
						|
            for(file in to_be_compiled)
 | 
						|
               mCompiler.compile(file,-1,groupHeader,pchStamp);
 | 
						|
         }
 | 
						|
         else
 | 
						|
         {
 | 
						|
            Log.initMultiThreaded();
 | 
						|
            var mutex = threadPool.mutex;
 | 
						|
            var compiler = mCompiler;
 | 
						|
            threadPool.setArrayCount(to_be_compiled.length);
 | 
						|
            threadPool.runJob( function(threadId:Int) {
 | 
						|
                  while(threadExitCode==0)
 | 
						|
                  {
 | 
						|
                     var index = threadPool.getNextIndex();
 | 
						|
                     if (index<0)
 | 
						|
                        break;
 | 
						|
                     var file = to_be_compiled[index];
 | 
						|
 | 
						|
                     compiler.compile(file,threadId,groupHeader,pchStamp);
 | 
						|
                  }
 | 
						|
            });
 | 
						|
         }
 | 
						|
         Profile.pop();
 | 
						|
 | 
						|
         if (CompileCache.hasCache && group.mAsLibrary && mLinkers.exists("static_link"))
 | 
						|
         {
 | 
						|
            Profile.push("link libs");
 | 
						|
            var linker = mLinkers.get("static_link");
 | 
						|
            var targetDir = mCompiler.mObjDir;
 | 
						|
            if (useCache)
 | 
						|
            {
 | 
						|
               targetDir = CompileCache.compileCache + "/" + group.getCacheProject() + "/lib";
 | 
						|
               PathManager.mkdir(targetDir);
 | 
						|
            }
 | 
						|
            var libName = targetDir + "/" + mCompiler.getTargetPrefix() + "_" + group.getCacheProject();
 | 
						|
 | 
						|
            var libTarget = new Target(libName, "linker", "static_link" );
 | 
						|
            linker.link(libTarget,groupObjs, mCompiler, [] );
 | 
						|
            target.mAutoLibs.push(linker.mLastOutName);
 | 
						|
            // Linux the libraries must be added again if the references were not resolved the firs time
 | 
						|
            if (group.mAddTwice)
 | 
						|
               target.mLibs.push(linker.mLastOutName);
 | 
						|
            Profile.pop();
 | 
						|
         }
 | 
						|
         else if (nvcc)
 | 
						|
         {
 | 
						|
            var objDir = mCompiler.mObjDir;
 | 
						|
            if (group.isCached())
 | 
						|
               objDir = CompileCache.compileCache;
 | 
						|
            var extraObj = linkNvccFiles(objDir, someCompiled, groupObjs, group.mId, mCompiler.mExt);
 | 
						|
            groupObjs.push(extraObj);
 | 
						|
            objs = objs.concat(groupObjs);
 | 
						|
         }
 | 
						|
         else
 | 
						|
         {
 | 
						|
            objs = objs.concat(groupObjs);
 | 
						|
         }
 | 
						|
 | 
						|
         if (group.mDir!="." && group.mSetImportDir)
 | 
						|
            Sys.setCwd( baseDir );
 | 
						|
      }
 | 
						|
 | 
						|
      switch(target.mTool)
 | 
						|
      {
 | 
						|
         case "linker":
 | 
						|
            Profile.push("linker");
 | 
						|
            if (mPrelinkers.exists(target.mToolID))
 | 
						|
            {
 | 
						|
               var result = mPrelinkers.get(target.mToolID).prelink(target,objs, mCompiler);
 | 
						|
               if (result != "")
 | 
						|
                  objs.push(result);
 | 
						|
               //throw "Missing linker :\"" + target.mToolID + "\"";
 | 
						|
            }
 | 
						|
 | 
						|
            if (!mLinkers.exists(target.mToolID))
 | 
						|
            {
 | 
						|
               Log.error ("Could not find linker for \"" + target.mToolID + "\"");
 | 
						|
               //throw "Missing linker :\"" + target.mToolID + "\"";
 | 
						|
            }
 | 
						|
            var extraDeps = [];
 | 
						|
            var manifest = mDefines.get("manifestFile");
 | 
						|
            if (manifest!=null)
 | 
						|
               extraDeps.push(manifest);
 | 
						|
 | 
						|
            var linker = mLinkers.get(target.mToolID);
 | 
						|
            var output = linker.link(target,objs, mCompiler, extraDeps);
 | 
						|
 | 
						|
            if (output!="")
 | 
						|
            {
 | 
						|
               if (mStripper!=null)
 | 
						|
               {
 | 
						|
                  if (target.mToolID=="exe" || target.mToolID=="dll")
 | 
						|
                  {
 | 
						|
                     if ( mDefines.exists("HXCPP_DEBUG_LINK_AND_STRIP") )
 | 
						|
                     {
 | 
						|
                        var unstripped = linker.getUnstrippedFilename(mCompiler.mObjDir,target);
 | 
						|
                        //var unstripped = mCompiler.mObjDir + "/" + linker.getSimpleFilename(target);
 | 
						|
                        Log.v("Save unstripped to " + unstripped);
 | 
						|
 | 
						|
                        var chmod = isWindows ? false : target.mToolID=="exe";
 | 
						|
                        CopyFile.copyFile(output, unstripped, false, Overwrite.ALWAYS, chmod);
 | 
						|
                     }
 | 
						|
 | 
						|
                     mStripper.strip(output);
 | 
						|
                  }
 | 
						|
               }
 | 
						|
 | 
						|
               if (manifest!=null && (target.mToolID=="exe" || target.mToolID=="dll") )
 | 
						|
               {
 | 
						|
                  if (mManifester==null)
 | 
						|
                  {
 | 
						|
                     Log.v('Could not find manifest tool for "$manifest" - ignoring');
 | 
						|
                  }
 | 
						|
                  else
 | 
						|
                  {
 | 
						|
                     //if (!PathManager.isAbsolute(manifest))
 | 
						|
                        //manifest = PathManager.combine(startDir,manifest);
 | 
						|
                     Log.v('Adding manifest "$manifest"');
 | 
						|
                     mManifester.add(output, manifest,target.mToolID=="exe");
 | 
						|
                  }
 | 
						|
               }
 | 
						|
            }
 | 
						|
 | 
						|
 | 
						|
            var outFile = linker.mLastOutName;
 | 
						|
            if (outFile!="" && !PathManager.isAbsolute(outFile) && sys.FileSystem.exists(mMakefile))
 | 
						|
            {
 | 
						|
               var baseFile = PathManager.standardize(mMakefile);
 | 
						|
               var parts = baseFile.split("/");
 | 
						|
               parts[ parts.length-1 ] = outFile;
 | 
						|
               outFile = parts.join("/");
 | 
						|
            }
 | 
						|
            if (outFile!="")
 | 
						|
               addOutput(target.mToolID, outFile);
 | 
						|
 | 
						|
            if (output!="" && inDestination!=null)
 | 
						|
            {
 | 
						|
               inDestination = substitute(inDestination,false);
 | 
						|
               if (inDestination!="")
 | 
						|
               {
 | 
						|
                  if (!PathManager.isAbsolute(inDestination) && sys.FileSystem.exists(mMakefile))
 | 
						|
                  {
 | 
						|
                     var baseFile = PathManager.standardize(mMakefile);
 | 
						|
                     var parts = baseFile.split("/");
 | 
						|
                     parts[ parts.length-1 ] = inDestination;
 | 
						|
                     inDestination = parts.join("/");
 | 
						|
                  }
 | 
						|
 | 
						|
                  inDestination = PathManager.clean(inDestination);
 | 
						|
                  var fileParts = inDestination.split("/");
 | 
						|
                  fileParts.pop();
 | 
						|
                  PathManager.mkdir(fileParts.join("/"));
 | 
						|
 | 
						|
                  var chmod = isWindows ? false : target.mToolID=="exe";
 | 
						|
                  CopyFile.copyFile(output, inDestination, false, Overwrite.ALWAYS, chmod);
 | 
						|
               }
 | 
						|
            }
 | 
						|
            Profile.pop();
 | 
						|
      }
 | 
						|
 | 
						|
      if (mCopyFiles.length>0)
 | 
						|
      {
 | 
						|
         Profile.push("copy files");
 | 
						|
         for(copyFile in mCopyFiles)
 | 
						|
            if (copyFile.toolId==null || copyFile.toolId==target.mToolID)
 | 
						|
               copyFile.copy(target.mOutputDir);
 | 
						|
         Profile.pop();
 | 
						|
      }
 | 
						|
 | 
						|
      if (restoreDir!="")
 | 
						|
         Sys.setCwd(restoreDir);
 | 
						|
   }
 | 
						|
 | 
						|
   function linkNvccFiles(objDir:String, hasChanged:Bool, nvObjs:Array<String>, inGroupName:String, objExt:String)
 | 
						|
   {
 | 
						|
      // nvcc -arch=sm_30 -dlink test1.o test2.o -o link.o
 | 
						|
      // Sadly, nvcc has no 'fromFile' options, so we must do it from objDir
 | 
						|
      var objDirLen = objDir.length;
 | 
						|
      var last = objDir.substr(objDirLen-1);
 | 
						|
      if (last!="/" && last!="\\")
 | 
						|
         objDirLen++;
 | 
						|
      var outFile = "nvcc_" + inGroupName + mCompiler.mExt;
 | 
						|
      var fullFile = objDir + "/" + outFile;
 | 
						|
 | 
						|
      if (hasChanged || !sys.FileSystem.exists(fullFile) )
 | 
						|
      {
 | 
						|
         var maxObjs = 25;
 | 
						|
         var shortObjs = nvObjs.map( function(f) return f.substr(objDirLen) );
 | 
						|
         if (shortObjs.length>maxObjs)
 | 
						|
         {
 | 
						|
            var partObjs = new Array<String>();
 | 
						|
            var p0 = 0;
 | 
						|
            var n =shortObjs.length;
 | 
						|
            var groupIdx = 0;
 | 
						|
            while(p0<n)
 | 
						|
            {
 | 
						|
               var subName = "nvcc_" + inGroupName + "_" + (groupIdx++) + mCompiler.mExt;
 | 
						|
               var remain = n-p0;
 | 
						|
               var use = remain<maxObjs ? remain : remain<maxObjs*2 ? (remain>>1) : maxObjs;
 | 
						|
               var files = shortObjs.slice(p0,p0+use);
 | 
						|
 | 
						|
               var flags = getNvccLinkFlags().concat(files).concat(["-o",subName]);
 | 
						|
               var dbgFlags = getNvccLinkFlags().concat(["[.", "x"+subName.length,".]"]).concat(["-o",subName]);
 | 
						|
               Log.v("Linking nvcc in " + objDir + ":" + getNvcc() + dbgFlags.join(" ") );
 | 
						|
               ProcessManager.runCommand(objDir ,getNvcc(),  flags );
 | 
						|
               partObjs.push(subName);
 | 
						|
               p0 += use;
 | 
						|
            }
 | 
						|
            shortObjs = partObjs;
 | 
						|
         }
 | 
						|
 | 
						|
         var flags = getNvccLinkFlags().concat(shortObjs).concat(["-o",outFile]);
 | 
						|
         var dbgFlags = getNvccLinkFlags().concat(["[.", "x"+shortObjs.length,".]"]).concat(["-o",outFile]);
 | 
						|
         Log.v("Linking nvcc in " + objDir + ":" + getNvcc() + dbgFlags.join(" ") );
 | 
						|
         ProcessManager.runCommand(objDir ,getNvcc(),  flags );
 | 
						|
      }
 | 
						|
      return fullFile;
 | 
						|
   }
 | 
						|
 | 
						|
 | 
						|
   public function cleanTarget(inTarget:String,allObj:Bool)
 | 
						|
   {
 | 
						|
      // Sys.println("Build : " + inTarget );
 | 
						|
      if (!mTargets.exists(inTarget))
 | 
						|
      {
 | 
						|
         Log.error("Could not find build target \"" + inTarget + "\"");
 | 
						|
         //throw "Could not find target '" + inTarget + "' to build.";
 | 
						|
      }
 | 
						|
      if (mCompiler==null)
 | 
						|
      {
 | 
						|
         Log.error("No compiler defined");
 | 
						|
         //throw "No compiler defined";
 | 
						|
      }
 | 
						|
 | 
						|
      var target = mTargets.get(inTarget);
 | 
						|
      target.checkError();
 | 
						|
 | 
						|
      for(sub in target.mSubTargets)
 | 
						|
         cleanTarget(sub,allObj);
 | 
						|
 | 
						|
      var restoreDir = "";
 | 
						|
      if (target.mBuildDir!="")
 | 
						|
      {
 | 
						|
         restoreDir = Sys.getCwd();
 | 
						|
         Log.info("", " - \x1b[1mChanging directory:\x1b[0m " + target.mBuildDir);
 | 
						|
         Sys.setCwd(target.mBuildDir);
 | 
						|
      }
 | 
						|
 | 
						|
      PathManager.removeDirectory(mCompiler.mObjDir);
 | 
						|
      PathManager.removeFile("all_objs");
 | 
						|
      PathManager.removeFilesWithExtension(".pdb");
 | 
						|
      if (allObj)
 | 
						|
         PathManager.removeDirectory("obj");
 | 
						|
 | 
						|
      if (restoreDir!="")
 | 
						|
         Sys.setCwd(restoreDir);
 | 
						|
   }
 | 
						|
 | 
						|
   public function createCompiler(inXML:XmlAccess,inBase:Compiler) : Compiler
 | 
						|
   {
 | 
						|
      var c = inBase;
 | 
						|
      var id = inXML.has.id ? substitute(inXML.att.id) : null;
 | 
						|
      var exe = inXML.has.exe ? substitute(inXML.att.exe) : null;
 | 
						|
      if (inBase==null || inXML.has.replace)
 | 
						|
      {
 | 
						|
         c = new Compiler(id,exe);
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
         if (id!=null)
 | 
						|
            c.mID = id;
 | 
						|
         if (exe!=null)
 | 
						|
            c.mExe = exe;
 | 
						|
      }
 | 
						|
      c.mAddGCCIdentity = mDefines.exists("USE_GCC_FILETYPES");
 | 
						|
 | 
						|
      for(el in inXML.elements)
 | 
						|
      {
 | 
						|
         if (valid(el,""))
 | 
						|
            switch(el.name)
 | 
						|
            {
 | 
						|
               case "flag" : c.addFlag(substitute(el.att.value), el.has.tag?substitute(el.att.tag):"");
 | 
						|
               case "cflag" : c.mCFlags.push(substitute(el.att.value));
 | 
						|
               case "cppflag" : c.mCPPFlags.push(substitute(el.att.value));
 | 
						|
               case "objcflag" : c.mOBJCFlags.push(substitute(el.att.value));
 | 
						|
               case "rcflag" : c.mRcFlags.push( substitute((el.att.value)) );
 | 
						|
               case "mmflag" : c.mMMFlags.push(substitute(el.att.value));
 | 
						|
               case "pchflag" : c.mPCHFlags.push(substitute(el.att.value));
 | 
						|
               case "objdir" : c.mObjDir = substitute((el.att.value));
 | 
						|
               case "outflag" : c.mOutFlag = substitute((el.att.value));
 | 
						|
               case "exe" : c.mExe = substitute((el.att.name));
 | 
						|
               case "rcexe" : c.mRcExe = substitute((el.att.name));
 | 
						|
               case "rcext" : c.mRcExt = substitute((el.att.value));
 | 
						|
               case "ext" : c.mExt = substitute((el.att.value));
 | 
						|
               case "pch" : c.setPCH( substitute((el.att.value)) );
 | 
						|
               case "getversion" : c.mGetCompilerVersion = substitute((el.att.value));
 | 
						|
               case "section" : createCompiler(el,c);
 | 
						|
               case "include" :
 | 
						|
                  var name = substitute(el.att.name);
 | 
						|
                  var full_name = findIncludeFile(name);
 | 
						|
                  if (full_name!="")
 | 
						|
                  {
 | 
						|
                     pushFile(full_name,"compiler");
 | 
						|
                     var make_contents = sys.io.File.getContent(full_name);
 | 
						|
                     var xml_slow = Xml.parse(make_contents);
 | 
						|
                     createCompiler(new XmlAccess(xml_slow.firstElement()),c);
 | 
						|
                     popFile();
 | 
						|
                  }
 | 
						|
                  else if (!el.has.noerror)
 | 
						|
                  {
 | 
						|
                     Log.error("Could not find include file \"" + name + "\"");
 | 
						|
                     //throw "Could not find include file " + name;
 | 
						|
                  }
 | 
						|
               default:
 | 
						|
                  Log.error("Unknown compiler option \"" + el.name + "\"");
 | 
						|
                  //throw "Unknown compiler option: '" + el.name + "'";
 | 
						|
            }
 | 
						|
      }
 | 
						|
 | 
						|
      return c;
 | 
						|
   }
 | 
						|
 | 
						|
   public function loadNvccXml()
 | 
						|
   {
 | 
						|
      var incName = findIncludeFile("nvcc-setup.xml");
 | 
						|
      if (incName=="")
 | 
						|
         incName = findIncludeFile('$HXCPP/toolchain/nvcc-setup.xml');
 | 
						|
      if (incName=="")
 | 
						|
        Log.error("Could not setup nvcc - missing nvcc-setup.xml");
 | 
						|
      else if (!mPragmaOnce.get(incName))
 | 
						|
      {
 | 
						|
         pushFile(incName, "Nvcc");
 | 
						|
         var make_contents = sys.io.File.getContent(incName);
 | 
						|
         mPragmaOnce.set(incName,true);
 | 
						|
         var xml = Xml.parse(make_contents);
 | 
						|
         parseXML(new XmlAccess(xml.firstElement()),"", false);
 | 
						|
         popFile();
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   public static function setupNvcc()
 | 
						|
   {
 | 
						|
      instance.loadNvccXml();
 | 
						|
   }
 | 
						|
 | 
						|
 | 
						|
   public function createFileGroup(inXML:XmlAccess,inFiles:FileGroup,inName:String, inForceRelative:Bool, inTags:String):FileGroup
 | 
						|
   {
 | 
						|
      var dir = inXML.has.dir ? substitute(inXML.att.dir) : ".";
 | 
						|
      if (inForceRelative)
 | 
						|
         dir = PathManager.combine( Path.directory(mCurrentIncludeFile), dir );
 | 
						|
 | 
						|
      var group:FileGroup = inFiles==null ? new FileGroup(dir,inName, inForceRelative) :
 | 
						|
                                  inXML.has.replace ? inFiles.replace(dir, inForceRelative) :
 | 
						|
                                  inFiles;
 | 
						|
 | 
						|
      if (inTags!=null)
 | 
						|
         group.mTags = inTags;
 | 
						|
 | 
						|
      for(el in inXML.elements)
 | 
						|
      {
 | 
						|
         if (valid(el,""))
 | 
						|
            switch(el.name)
 | 
						|
            {
 | 
						|
               case "file" :
 | 
						|
                  var name = substitute(el.att.name);
 | 
						|
                  var file:File = group.find(name);
 | 
						|
                  if (file==null)
 | 
						|
                  {
 | 
						|
                     file = new File(name,group);
 | 
						|
                     group.addFile( file );
 | 
						|
                  }
 | 
						|
 | 
						|
                  if (el.has.tag)
 | 
						|
                  {
 | 
						|
                     var extra = substitute(el.att.tag);
 | 
						|
                     file.setTags(group.mTags==null || group.mTags=="" ? extra : group.mTags+","+extra);
 | 
						|
                  }
 | 
						|
                  if (el.has.tags)
 | 
						|
                     file.setTags( substitute(el.att.tags) );
 | 
						|
                  if (el.has.filterout)
 | 
						|
                     file.mFilterOut = substitute(el.att.filterout);
 | 
						|
                  if (el.has.embedName)
 | 
						|
                     file.mEmbedName = substitute(el.att.embedName);
 | 
						|
                  if (el.has.scramble)
 | 
						|
                     file.mScramble = substitute(el.att.scramble);
 | 
						|
                  for(f in el.elements)
 | 
						|
                     if (valid(f,"") && f.name=="depend")
 | 
						|
                        file.mDepends.push( substitute(f.att.name) );
 | 
						|
               case "section" : createFileGroup(el,group,inName,inForceRelative,null);
 | 
						|
               case "cache" :
 | 
						|
                  group.mUseCache = parseBool( substitute(el.att.value) );
 | 
						|
                  if (el.has.project)
 | 
						|
                     group.mCacheProject = substitute(el.att.project);
 | 
						|
                  if (el.has.asLibrary)
 | 
						|
                     group.mAsLibrary = true;
 | 
						|
                  if (el.has.respectTimestamp)
 | 
						|
                     group.mRespectTimestamp = true;
 | 
						|
               case "tag" :
 | 
						|
                   group.addTag( substitute(el.att.value) );
 | 
						|
               case "addTwice" :
 | 
						|
                  group.mAddTwice = true;
 | 
						|
               case "depend" :
 | 
						|
                  if (el.has.name)
 | 
						|
                  {
 | 
						|
                     var dateOnly = el.has.dateOnly && parseBool( substitute(el.att.dateOnly) );
 | 
						|
                     group.addDepend( substitute(el.att.name), dateOnly );
 | 
						|
                  }
 | 
						|
                  else if (el.has.files)
 | 
						|
                  {
 | 
						|
                     var name = substitute(el.att.files);
 | 
						|
                     if (!mFileGroups.exists(name))
 | 
						|
                         Log.error( "Could not find filegroup for depend node:" + name );
 | 
						|
                     group.addDependFiles(mFileGroups.get(name));
 | 
						|
                  }
 | 
						|
                  else
 | 
						|
                     Log.error("depend node must have 'name' or 'files' attribute");
 | 
						|
               case "hlsl" :
 | 
						|
                  group.addHLSL( substitute(el.att.name), substitute(el.att.profile),
 | 
						|
                  substitute(el.att.variable), substitute(el.att.target)  );
 | 
						|
               case "options" : group.addOptions( substitute(el.att.name) );
 | 
						|
               case "config" : group.mConfig = substitute(el.att.name);
 | 
						|
               case "compilerflag" :
 | 
						|
                  if (el.has.name)
 | 
						|
                     group.addCompilerFlag( substitute(el.att.name) );
 | 
						|
                  group.addCompilerFlag( substitute(el.att.value) );
 | 
						|
               case "nvcc" :
 | 
						|
                  setupNvcc();
 | 
						|
                  group.mNvcc = true;
 | 
						|
                  if (group.mTags=="haxe,static")
 | 
						|
                     group.mTags=="nvcc";
 | 
						|
               case "objprefix" :
 | 
						|
                  group.mObjPrefix = substitute(el.att.value);
 | 
						|
               case "compilervalue" :
 | 
						|
                  group.addCompilerFlag( substitute(el.att.name) );
 | 
						|
                  group.addCompilerFlag( substitute(el.att.value) );
 | 
						|
               case "precompiledheader" :
 | 
						|
                  group.setPrecompiled( substitute(el.att.name), substitute(el.att.dir) );
 | 
						|
               case "include" :
 | 
						|
                  var subbed_name = substitute(el.att.name);
 | 
						|
                  var full_name = findIncludeFile(subbed_name);
 | 
						|
                  if (full_name!="")
 | 
						|
                  {
 | 
						|
                     if (!mPragmaOnce.get(full_name))
 | 
						|
                     {
 | 
						|
                        pushFile(full_name, "FileGroup");
 | 
						|
                        var make_contents = sys.io.File.getContent(full_name);
 | 
						|
                        var xml_slow = Xml.parse(make_contents);
 | 
						|
                        createFileGroup(new XmlAccess(xml_slow.firstElement()), group, inName, false,null);
 | 
						|
                        popFile();
 | 
						|
                     }
 | 
						|
                  }
 | 
						|
                  else
 | 
						|
                  {
 | 
						|
                     Log.error("Could not find include file \"" + subbed_name + "\"");
 | 
						|
 | 
						|
                  }
 | 
						|
            }
 | 
						|
      }
 | 
						|
 | 
						|
      return group;
 | 
						|
   }
 | 
						|
 | 
						|
   public function createLinker(inXML:XmlAccess,inBase:Linker):Linker
 | 
						|
   {
 | 
						|
      var exe:String = inXML.has.exe ? substitute(inXML.att.exe) : null;
 | 
						|
      if (inBase!=null && !inXML.has.replace && inBase.mExe==null)
 | 
						|
         inBase.mExe = exe;
 | 
						|
      var l = (inBase!=null && !inXML.has.replace) ? inBase : new Linker(exe);
 | 
						|
      for(el in inXML.elements)
 | 
						|
      {
 | 
						|
         if (valid(el,""))
 | 
						|
            switch(el.name)
 | 
						|
            {
 | 
						|
               case "flag" : l.mFlags.push(substitute(el.att.value));
 | 
						|
               case "ext" : l.mExt = (substitute(el.att.value));
 | 
						|
               case "outflag" : l.mOutFlag = (substitute(el.att.value));
 | 
						|
               case "libdir" : l.mLibDir = (substitute(el.att.name));
 | 
						|
               case "lib" :
 | 
						|
                  if (el.has.hxbase)
 | 
						|
                     l.mLibs.push( substitute(el.att.hxbase) + mDefines.get("LIBEXTRA") + mDefines.get("LIBEXT") );
 | 
						|
                  else if (el.has.base)
 | 
						|
                     l.mLibs.push( substitute(el.att.base) + mDefines.get("LIBEXT") );
 | 
						|
                  else
 | 
						|
                     l.mLibs.push( substitute(el.att.name) );
 | 
						|
 | 
						|
               case "prefix" : l.mNamePrefix = substitute(el.att.value);
 | 
						|
               case "ranlib" : l.mRanLib = (substitute(el.att.name));
 | 
						|
               case "libpathflag" : l.mAddLibPath = (substitute(el.att.value));
 | 
						|
               case "recreate" : l.mRecreate = (substitute(el.att.value)) != "";
 | 
						|
               case "expandAr" : l.mExpandArchives = substitute(el.att.value) != "";
 | 
						|
               case "fromfile" :
 | 
						|
                  if (el.has.value)
 | 
						|
                     l.mFromFile = substitute(el.att.value);
 | 
						|
                  if (el.has.needsQuotes)
 | 
						|
                     l.mFromFileNeedsQuotes = parseBool(substitute(el.att.needsQuotes));
 | 
						|
               case "exe" : l.mExe = (substitute(el.att.name));
 | 
						|
               case "section" : createLinker(el,l);
 | 
						|
            }
 | 
						|
      }
 | 
						|
 | 
						|
      return l;
 | 
						|
   }
 | 
						|
 | 
						|
   public function createPrelinker(inXML:XmlAccess,inBase:Prelinker):Prelinker
 | 
						|
   {
 | 
						|
      var l = (inBase!=null && !inXML.has.replace) ? inBase : new Prelinker(substitute(inXML.att.exe));
 | 
						|
      for(el in inXML.elements)
 | 
						|
      {
 | 
						|
         if (valid(el,""))
 | 
						|
            switch(el.name)
 | 
						|
            {
 | 
						|
               case "flag" : l.mFlags.push(substitute(el.att.value));
 | 
						|
               //case "ext" : l.mExt = (substitute(el.att.value));
 | 
						|
               case "outflag" : l.mOutFlag = (substitute(el.att.value));
 | 
						|
               case "expandAr" : l.mExpandArchives = substitute(el.att.value) != "";
 | 
						|
               case "fromfile" : l.mFromFile = (substitute(el.att.value));
 | 
						|
               case "exe" : l.mExe = (substitute(el.att.name));
 | 
						|
               case "section" : createPrelinker(el,l);
 | 
						|
            }
 | 
						|
      }
 | 
						|
 | 
						|
      return l;
 | 
						|
   }
 | 
						|
 | 
						|
   public function createManifester(inXML:XmlAccess,inBase:Manifester):Manifester
 | 
						|
   {
 | 
						|
      var s = (inBase!=null && !inXML.has.replace) ? inBase :
 | 
						|
                 new Manifester(substitute(inXML.att.exe));
 | 
						|
      for(el in inXML.elements)
 | 
						|
      {
 | 
						|
         if (valid(el,""))
 | 
						|
            switch(el.name)
 | 
						|
            {
 | 
						|
                case "flag" : s.mFlags.push(substitute(el.att.value));
 | 
						|
                case "outPre" : s.mOutPre = substitute(el.att.value);
 | 
						|
                case "outPost" : s.mOutPost = substitute(el.att.value);
 | 
						|
                case "exe" : s.mExe = substitute((el.att.name));
 | 
						|
            }
 | 
						|
      }
 | 
						|
 | 
						|
      return s;
 | 
						|
   }
 | 
						|
 | 
						|
 | 
						|
   public function createStripper(inXML:XmlAccess,inBase:Stripper):Stripper
 | 
						|
   {
 | 
						|
      var s = (inBase!=null && !inXML.has.replace) ? inBase :
 | 
						|
                 new Stripper(substitute(inXML.att.exe));
 | 
						|
      for(el in inXML.elements)
 | 
						|
      {
 | 
						|
         if (valid(el,""))
 | 
						|
            switch(el.name)
 | 
						|
            {
 | 
						|
                case "flag" : s.mFlags.push(substitute(el.att.value));
 | 
						|
                case "exe" : s.mExe = substitute((el.att.name));
 | 
						|
            }
 | 
						|
      }
 | 
						|
 | 
						|
      return s;
 | 
						|
   }
 | 
						|
 | 
						|
   public function createTarget(inXML:XmlAccess,?inTarget:Target, inForceRelative) : Target
 | 
						|
   {
 | 
						|
      var target:Target = inTarget;
 | 
						|
      var output = inXML.has.output ? substitute(inXML.att.output) : "";
 | 
						|
      var tool = inXML.has.tool ? substitute(inXML.att.tool) : "";
 | 
						|
      var toolid = inXML.has.toolid ? substitute(inXML.att.toolid) : "";
 | 
						|
 | 
						|
      if (target==null)
 | 
						|
      {
 | 
						|
         target = new Target(output,tool,toolid);
 | 
						|
         if (inForceRelative)
 | 
						|
            target.mBuildDir = Path.directory(mCurrentIncludeFile);
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
         if (output!="")
 | 
						|
            target.mOutput = output;
 | 
						|
         if (tool!="")
 | 
						|
            target.mTool = tool;
 | 
						|
         if (toolid!="")
 | 
						|
            target.mToolID = toolid;
 | 
						|
      }
 | 
						|
 | 
						|
      for(el in inXML.elements)
 | 
						|
      {
 | 
						|
         if (valid(el,""))
 | 
						|
            switch(el.name)
 | 
						|
            {
 | 
						|
               case "target" : target.mSubTargets.push( substitute(el.att.id) );
 | 
						|
               case "merge" :
 | 
						|
                  var name = substitute(el.att.id);
 | 
						|
                  if (!mTargets.exists(name))
 | 
						|
                     Log.error("Could not find target " + name + " to merge.");
 | 
						|
                  target.merge( mTargets.get(name) );
 | 
						|
 | 
						|
               case "lib" :
 | 
						|
                  if (el.has.hxbase)
 | 
						|
                     target.mLibs.push( substitute(el.att.hxbase) + mDefines.get("LIBEXTRA") + mDefines.get("LIBEXT") );
 | 
						|
                  else if (el.has.base)
 | 
						|
                     target.mLibs.push( substitute(el.att.base) + mDefines.get("LIBEXT") );
 | 
						|
                  else
 | 
						|
                  {
 | 
						|
                      var lib = substitute(el.att.name);
 | 
						|
                      var found = false;
 | 
						|
                      for(magicLib in mMagicLibs)
 | 
						|
                      {
 | 
						|
                         if (lib.endsWith(magicLib.name))
 | 
						|
                         {
 | 
						|
                            var replace = lib.substr(0, lib.length-magicLib.name.length) +
 | 
						|
                                              magicLib.replace;
 | 
						|
                            Log.v('Using $replace instead of $lib');
 | 
						|
                            found = true;
 | 
						|
                            include(replace, "", false, true );
 | 
						|
                            break;
 | 
						|
                         }
 | 
						|
                      }
 | 
						|
                      if (!found)
 | 
						|
                         target.mLibs.push(lib);
 | 
						|
                  }
 | 
						|
 | 
						|
               case "flag" : target.mFlags.push( substitute(el.att.value) );
 | 
						|
               case "depend" : target.mDepends.push( substitute(el.att.name) );
 | 
						|
               case "vflag" :
 | 
						|
                  target.mFlags.push( substitute(el.att.name) );
 | 
						|
                  target.mFlags.push( substitute(el.att.value) );
 | 
						|
               case "dir" : target.mDirs.push( substitute(el.att.name) );
 | 
						|
               case "outdir" : target.mOutputDir = substitute(el.att.name)+"/";
 | 
						|
               case "ext" : target.setExt( (substitute(el.att.value)) );
 | 
						|
               case "builddir" : target.mBuildDir = substitute(el.att.name);
 | 
						|
               case "libpath" : target.mLibPaths.push( substitute(el.att.name) );
 | 
						|
               case "fullouput" : target.mFullOutputName = substitute(el.att.name);
 | 
						|
               case "fullunstripped" : target.mFullUnstrippedName = substitute(el.att.name);
 | 
						|
               case "files" :
 | 
						|
                  var id = el.att.id;
 | 
						|
                  if (!mFileGroups.exists(id))
 | 
						|
                     target.addError( "Could not find filegroup " + id );
 | 
						|
                  else
 | 
						|
                     target.addFiles( mFileGroups.get(id), el.has.asLibrary );
 | 
						|
               case "section" : createTarget(el,target,false);
 | 
						|
            }
 | 
						|
      }
 | 
						|
 | 
						|
      return target;
 | 
						|
   }
 | 
						|
 | 
						|
   public function defined(inString:String):Bool
 | 
						|
   {
 | 
						|
      if (inString=="this_dir")
 | 
						|
         return true;
 | 
						|
      return mDefines.exists(inString);
 | 
						|
   }
 | 
						|
 | 
						|
   public function parseBool(inValue:String):Bool
 | 
						|
   {
 | 
						|
      return inValue=="1" || inValue=="t" || inValue=="true";
 | 
						|
   }
 | 
						|
 | 
						|
   function findLocalIncludeFile(inBase:String):String
 | 
						|
   {
 | 
						|
      if (inBase == null || inBase=="") return "";
 | 
						|
      var c0 = inBase.substr(0,1);
 | 
						|
      if (c0!="/" && c0!="\\")
 | 
						|
      {
 | 
						|
         var c1 = inBase.substr(1,1);
 | 
						|
         if (c1!=":")
 | 
						|
         {
 | 
						|
            if (mCurrentIncludeFile!="")
 | 
						|
            {
 | 
						|
               var relative = Path.directory(mCurrentIncludeFile);
 | 
						|
               var name = PathManager.combine(relative, inBase);
 | 
						|
               if (FileSystem.exists(name))
 | 
						|
                  return name;
 | 
						|
            }
 | 
						|
 | 
						|
            for(p in mIncludePath)
 | 
						|
            {
 | 
						|
               var name = PathManager.combine(p, inBase);
 | 
						|
               if (FileSystem.exists(name))
 | 
						|
               {
 | 
						|
                  return name;
 | 
						|
               }
 | 
						|
            }
 | 
						|
            return "";
 | 
						|
         }
 | 
						|
      }
 | 
						|
      if (FileSystem.exists(inBase))
 | 
						|
         return inBase;
 | 
						|
      return "";
 | 
						|
   }
 | 
						|
 | 
						|
   function findIncludeFile(inBase:String):String
 | 
						|
   {
 | 
						|
      var result = findLocalIncludeFile(inBase);
 | 
						|
      if (result!="" && !Path.isAbsolute(result))
 | 
						|
         result =  Path.normalize( PathManager.combine( mCurrentIncludeFile=="" ? Sys.getCwd() : Path.directory(mCurrentIncludeFile), result ) );
 | 
						|
      return result;
 | 
						|
   }
 | 
						|
 | 
						|
   private static function getArch():String
 | 
						|
   {
 | 
						|
      if (isWindows)
 | 
						|
      {
 | 
						|
         if (isWindowsArm)
 | 
						|
            return "arm64";
 | 
						|
         var architecture = Sys.getEnv("PROCESSOR_ARCHITECTURE");
 | 
						|
         var wow64Architecture = Sys.getEnv("PROCESSOR_ARCHITEW6432");
 | 
						|
         if (architecture.indexOf("64") > -1 || wow64Architecture != null && wow64Architecture.indexOf("64") > -1)
 | 
						|
         {
 | 
						|
            return "m64";
 | 
						|
         }
 | 
						|
         else
 | 
						|
         {
 | 
						|
            return "m32";
 | 
						|
         }
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
         var process = new Process("uname", [ "-m" ]);
 | 
						|
         var output = process.stdout.readAll().toString();
 | 
						|
         var error = process.stderr.readAll().toString();
 | 
						|
         process.exitCode();
 | 
						|
         process.close();
 | 
						|
 | 
						|
         if ( (output.indexOf("aarch64") > -1) ||  (output.indexOf("arm64") > -1) )
 | 
						|
         {
 | 
						|
            return "arm64";
 | 
						|
         }
 | 
						|
         else if (output.indexOf("64") > -1)
 | 
						|
         {
 | 
						|
            return "m64";
 | 
						|
         }
 | 
						|
         else
 | 
						|
         {
 | 
						|
            return "m32";
 | 
						|
         }
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   static public function getMsvcVer()
 | 
						|
   {
 | 
						|
      return instance.mDefines.get("MSVC_VER");
 | 
						|
   }
 | 
						|
 | 
						|
   static public function keepTemp()
 | 
						|
   {
 | 
						|
      return instance.mDefines.exists("HXCPP_KEEP_TEMP");
 | 
						|
   }
 | 
						|
 | 
						|
 | 
						|
   // Setting HXCPP_COMPILE_THREADS to 2x number or cores can help with hyperthreading
 | 
						|
   public static function getNumberOfProcesses():Int
 | 
						|
   {
 | 
						|
      var cache = Log.verbose;
 | 
						|
      Log.verbose = false;
 | 
						|
 | 
						|
      var result = null;
 | 
						|
      if (isWindows)
 | 
						|
      {
 | 
						|
         var env = Sys.getEnv("NUMBER_OF_PROCESSORS");
 | 
						|
         if (env != null)
 | 
						|
         {
 | 
						|
            result = env;
 | 
						|
         }
 | 
						|
      }
 | 
						|
      else if (isLinux)
 | 
						|
      {
 | 
						|
         result = ProcessManager.runProcessLine("", "nproc", [], true, false, true, true);
 | 
						|
         if (result == null)
 | 
						|
         {
 | 
						|
            var cpuinfo = ProcessManager.runProcess("", "cat", [ "/proc/cpuinfo" ], true, false, true, true);
 | 
						|
            if (cpuinfo != null)
 | 
						|
            {
 | 
						|
               var split = cpuinfo.split("processor");
 | 
						|
               result = Std.string(split.length - 1);
 | 
						|
            }
 | 
						|
         }
 | 
						|
      }
 | 
						|
      else if (isMac)
 | 
						|
      {
 | 
						|
         var cores = ~/Total Number of Cores: (\d+)/;
 | 
						|
         var output = ProcessManager.runProcess("", "/usr/sbin/system_profiler", [ "-detailLevel", "full", "SPHardwareDataType" ], true, false, true, true);
 | 
						|
         if (output != null && cores.match(output))
 | 
						|
         {
 | 
						|
            result = cores.matched(1);
 | 
						|
         }
 | 
						|
      }
 | 
						|
 | 
						|
      Log.verbose = cache;
 | 
						|
 | 
						|
      if (result == null || Std.parseInt(result) < 1)
 | 
						|
      {
 | 
						|
         return 1;
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
         return Std.parseInt(result);
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   private static function getVersion():String
 | 
						|
   {
 | 
						|
      try
 | 
						|
      {
 | 
						|
         var json = Json.parse (sys.io.File.getContent (PathManager.getHaxelib ("hxcpp") + "/haxelib.json"));
 | 
						|
         return json.version;
 | 
						|
      }
 | 
						|
      catch (e:Dynamic)
 | 
						|
      {
 | 
						|
         return "0.0.0";
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   public static function isMsvc()
 | 
						|
   {
 | 
						|
      return instance.mDefines.get("toolchain")=="msvc";
 | 
						|
   }
 | 
						|
 | 
						|
   public static function isMingw()
 | 
						|
   {
 | 
						|
      return instance.mDefines.get("toolchain")=="mingw";
 | 
						|
   }
 | 
						|
 | 
						|
   public static function getNvcc()
 | 
						|
   {
 | 
						|
      return instance.mDefines.get("NVCC");
 | 
						|
   }
 | 
						|
 | 
						|
   public static function getNvccLinkFlags() : Array<String>
 | 
						|
   {
 | 
						|
      return instance.mNvccLinkFlags;
 | 
						|
   }
 | 
						|
 | 
						|
   public static function getNvccFlags() : Array<String>
 | 
						|
   {
 | 
						|
      return instance.mNvccFlags;
 | 
						|
   }
 | 
						|
 | 
						|
   public static function copy(from:String, to:String)
 | 
						|
   {
 | 
						|
      Log.v('copy $from $to');
 | 
						|
 | 
						|
      try {
 | 
						|
         if (FileSystem.isDirectory(to))
 | 
						|
            to += "/" + Path.withoutDirectory(from);
 | 
						|
         var bytes = sys.io.File.getBytes(from);
 | 
						|
         sys.io.File.saveBytes(to,bytes);
 | 
						|
      } catch(e:Dynamic)
 | 
						|
      {
 | 
						|
         Log.error('Could not copy file $from $to');
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
 | 
						|
   static public function main()
 | 
						|
   {
 | 
						|
     try {
 | 
						|
       runMain();
 | 
						|
     }
 | 
						|
     catch(e:Dynamic) {
 | 
						|
       Log.error('Uncaught exception on main thread: $e\n${haxe.CallStack.toString(haxe.CallStack.exceptionStack())}');
 | 
						|
       Tools.exit(1);
 | 
						|
     }
 | 
						|
     Tools.exit(0);
 | 
						|
   }
 | 
						|
 | 
						|
   // Process args and environment.
 | 
						|
   static function runMain()
 | 
						|
   {
 | 
						|
      var targets = new Array<String>();
 | 
						|
      var defines = new Hash<String>();
 | 
						|
      var include_path = new Array<String>();
 | 
						|
      var makefile:String="";
 | 
						|
      var optionsTxt = "Options.txt";
 | 
						|
 | 
						|
      Profile.start();
 | 
						|
 | 
						|
      include_path.push(".");
 | 
						|
 | 
						|
      var args = Sys.args();
 | 
						|
      var env = Sys.environment();
 | 
						|
 | 
						|
      for(e in env.keys())
 | 
						|
         defines.set(e, Sys.getEnv(e) );
 | 
						|
 | 
						|
 | 
						|
      // Check for calling from haxelib ...
 | 
						|
      if (args.length>0)
 | 
						|
      {
 | 
						|
         var last:String = (new Path(args[args.length-1])).toString();
 | 
						|
         var isRootDir = last=="/";
 | 
						|
         if (!isRootDir)
 | 
						|
         {
 | 
						|
            var slash = last.substr(-1);
 | 
						|
            if (slash=="/"|| slash=="\\")
 | 
						|
               last = last.substr(0,last.length-1);
 | 
						|
         }
 | 
						|
         if (isRootDir || (FileSystem.exists(last) && FileSystem.isDirectory(last)))
 | 
						|
         {
 | 
						|
            // When called from haxelib, the last arg is the original directory, and
 | 
						|
            //  the current direcory is the library directory.
 | 
						|
            HXCPP = PathManager.standardize(Sys.getCwd());
 | 
						|
            defines.set("HXCPP",HXCPP);
 | 
						|
            args.pop();
 | 
						|
            Sys.setCwd(last);
 | 
						|
         }
 | 
						|
      }
 | 
						|
 | 
						|
 | 
						|
      if (defines.exists("HXCPP_NO_COLOUR") || defines.exists("HXCPP_NO_COLOR"))
 | 
						|
         Log.colorSupported = false;
 | 
						|
      Log.verbose = defines.exists("HXCPP_VERBOSE");
 | 
						|
      exitOnThreadError = defines.exists("HXCPP_EXIT_ON_ERROR");
 | 
						|
 | 
						|
 | 
						|
      os = Sys.systemName();
 | 
						|
 | 
						|
      startDir = Sys.getCwd();
 | 
						|
 | 
						|
      isWindows = (new EReg("window","i")).match(os);
 | 
						|
      if (isWindows)
 | 
						|
      {
 | 
						|
         var proc = Sys.getEnv("PROCESSOR_IDENTIFIER");
 | 
						|
         isWindowsArm = proc!=null && (new EReg("\\barm","i")).match(proc);
 | 
						|
         if (isWindowsArm)
 | 
						|
            defines.set("windows_arm_host", "1");
 | 
						|
      }
 | 
						|
      isMac = (new EReg("mac","i")).match(os);
 | 
						|
      if (isMac)
 | 
						|
         defines.set("mac_host", "1");
 | 
						|
      isLinux = (new EReg("linux","i")).match(os);
 | 
						|
      if (isLinux)
 | 
						|
         defines.set("linux_host", "1");
 | 
						|
 | 
						|
 | 
						|
      if (args.length>0 && args[0].endsWith(".cppia"))
 | 
						|
      {
 | 
						|
         var binDir = isWindows ? "Windows" : isMac ? "Mac64" : isLinux ? "Linux64" : null;
 | 
						|
         if (binDir==null)
 | 
						|
            Log.error("Cppia is not supported on this host.");
 | 
						|
         var arch = getArch();
 | 
						|
         var binDir = isWindows ? (isWindowsArm ? "WindowsArm64" : "Windows64" ) :
 | 
						|
                       isMac ? "Mac64" :
 | 
						|
                       isLinux ? ("Linux64") :
 | 
						|
                       null;
 | 
						|
         var exe = '$HXCPP/bin/$binDir/Cppia' + (isWindows ? ".exe" : "");
 | 
						|
         if (!isWindows)
 | 
						|
         {
 | 
						|
            var phase = "find";
 | 
						|
            try
 | 
						|
            {
 | 
						|
               var stat = FileSystem.stat(exe);
 | 
						|
               if (stat==null)
 | 
						|
                  throw "Could not find exe:" + exe;
 | 
						|
               var mode = stat.mode;
 | 
						|
               var exeFlags = (1<<0) | (1<<3) | (1<<6);
 | 
						|
               if ( (mode&exeFlags) != exeFlags )
 | 
						|
               {
 | 
						|
                  var phase = "add exe permissions to";
 | 
						|
                  if (Sys.command( "chmod", ["755", exe])!=0)
 | 
						|
                     Log.error('Please use root access to add execute permissions to $exe');
 | 
						|
               }
 | 
						|
            }
 | 
						|
            catch(e:Dynamic)
 | 
						|
            {
 | 
						|
               Log.error('Could not $phase Cppia host $exe ($e)');
 | 
						|
            }
 | 
						|
         }
 | 
						|
 | 
						|
         #if (haxe_ver < 3.3)
 | 
						|
         // avoid issue of path with spaces
 | 
						|
         // https://github.com/HaxeFoundation/haxe/issues/3603
 | 
						|
         if (isWindows)
 | 
						|
            exe = '"$exe"';
 | 
						|
         #end
 | 
						|
 | 
						|
         Tools.exit( Sys.command( exe, args ) );
 | 
						|
      }
 | 
						|
      else if (args.length>0 && args[0].endsWith(".js"))
 | 
						|
      {
 | 
						|
         Setup.initHXCPPConfig(defines);
 | 
						|
         Setup.setupEmscripten(defines);
 | 
						|
         var node = defines.get("EMSCRIPTEN_NODE_JS");
 | 
						|
         Log.v( node==null ? "EMSCRIPTEN_NODE_JS undefined, using 'node'" : 'Using $node from EMSCRIPTEN_NODE_JS');
 | 
						|
         if (node=="" || node==null)
 | 
						|
            node = "node";
 | 
						|
 | 
						|
         Log.v(  node + " " + args.join(" ") );
 | 
						|
         Tools.exit( Sys.command( node, args ) );
 | 
						|
      }
 | 
						|
      else if (args.length==1 && args[0]=="defines")
 | 
						|
      {
 | 
						|
         var dir = '$HXCPP/tools/hxcpp';
 | 
						|
         try
 | 
						|
         {
 | 
						|
            var defineMatch = ~/m*defines\.\w+\("(\w+)"/i;
 | 
						|
            var allDefines = new Map<String,Bool>();
 | 
						|
            for(file in FileSystem.readDirectory(dir))
 | 
						|
               if (file.endsWith(".hx"))
 | 
						|
                  for(line in sys.io.File.getContent(file).split("\n"))
 | 
						|
                     if (defineMatch.match(line))
 | 
						|
                        allDefines.set(defineMatch.matched(1),true);
 | 
						|
            for(key in allDefines.keys())
 | 
						|
               Sys.println(key);
 | 
						|
         }
 | 
						|
         catch(e:Dynamic)
 | 
						|
         {
 | 
						|
            Log.error('Could not read $dir : $e');
 | 
						|
         }
 | 
						|
         return;
 | 
						|
      }
 | 
						|
 | 
						|
 | 
						|
      isRPi = isLinux && Setup.isRaspberryPi();
 | 
						|
 | 
						|
      is64 = getArch()!="m32";
 | 
						|
      var dirtyList = new Array<String>();
 | 
						|
 | 
						|
      var a = 0;
 | 
						|
      while(a < args.length)
 | 
						|
      {
 | 
						|
         var arg = args[a];
 | 
						|
         if (arg.substr(0,2)=="-D" || (~/^[a-zA-Z0-9_][a-zA-Z0-9_-]*=/).match(arg) )
 | 
						|
         {
 | 
						|
            var define = arg.substr(0,2)=="-D" ? arg.substr(2) : arg;
 | 
						|
            var equals = define.indexOf("=");
 | 
						|
            if (equals>0)
 | 
						|
            {
 | 
						|
               var value = define.substr(equals+1);
 | 
						|
               define = define.substr(0,equals);
 | 
						|
               if (define=="destination")
 | 
						|
               {
 | 
						|
                  destination = value;
 | 
						|
               }
 | 
						|
               else
 | 
						|
                  defines.set(define,value);
 | 
						|
            }
 | 
						|
            else
 | 
						|
               defines.set(define,"");
 | 
						|
            if (define=="verbose")
 | 
						|
               Log.verbose = true;
 | 
						|
         }
 | 
						|
         else if (arg=="-debug")
 | 
						|
               defines.set("debug","1");
 | 
						|
         else if (arg=="-no-options")
 | 
						|
            optionsTxt = "";
 | 
						|
         else if (arg=="-options")
 | 
						|
         {
 | 
						|
            a++;
 | 
						|
            optionsTxt = args[a];
 | 
						|
            if (optionsTxt==null)
 | 
						|
               optionsTxt = "";
 | 
						|
         }
 | 
						|
         else if (arg=="-dirty")
 | 
						|
         {
 | 
						|
            a++;
 | 
						|
            dirtyList.push(args[a]);
 | 
						|
         }
 | 
						|
         else if (arg=="-v" || arg=="-verbose")
 | 
						|
            Log.verbose = true;
 | 
						|
         else if (arg=="-nocolor")
 | 
						|
            Log.colorSupported = false;
 | 
						|
         else if (arg.substr(0,2)=="-I")
 | 
						|
            include_path.push(PathManager.standardize(arg.substr(2)));
 | 
						|
         else if (makefile.length==0)
 | 
						|
            makefile = arg;
 | 
						|
         else
 | 
						|
            targets.push(arg);
 | 
						|
 | 
						|
         a++;
 | 
						|
      }
 | 
						|
 | 
						|
      if (defines.exists("HXCPP_TIMES"))
 | 
						|
         Profile.enable();
 | 
						|
 | 
						|
      if (defines.exists("HXCPP_NO_COLOUR") || defines.exists("HXCPP_NO_COLOR"))
 | 
						|
         Log.colorSupported = false;
 | 
						|
      Log.verbose = Log.verbose || defines.exists("HXCPP_VERBOSE");
 | 
						|
      Log.quiet = defines.exists("HXCPP_QUIET") && !Log.verbose;
 | 
						|
      Log.mute = defines.exists("HXCPP_SILENT") && !Log.quiet && !Log.verbose;
 | 
						|
 | 
						|
      if ( optionsTxt!="" && makefile!="")
 | 
						|
      {
 | 
						|
         var path = PathManager.combine(haxe.io.Path.directory(makefile), optionsTxt);
 | 
						|
         if (FileSystem.exists(path))
 | 
						|
            try
 | 
						|
            {
 | 
						|
               var contents = sys.io.File.getContent(path);
 | 
						|
               if (contents.substr(0,1)!=" ") // Is it New-style?
 | 
						|
                  for(def in contents.split("\r").join("").split("\n"))
 | 
						|
                  {
 | 
						|
                     var equals = def.indexOf("=");
 | 
						|
                     if (equals>0)
 | 
						|
                     {
 | 
						|
                        var name = def.substr(0,equals);
 | 
						|
                        var value = def.substr(equals+1);
 | 
						|
                        if (name=="hxcpp")
 | 
						|
                        {
 | 
						|
                           // Ignore
 | 
						|
                        }
 | 
						|
                        else if (name=="destination")
 | 
						|
                            destination = value;
 | 
						|
                        else
 | 
						|
                           defines.set(name,value);
 | 
						|
                     }
 | 
						|
                  }
 | 
						|
           }
 | 
						|
           catch(e:Dynamic)
 | 
						|
           {
 | 
						|
              Log.error('Could not parse options file $path ($e)');
 | 
						|
           }
 | 
						|
      }
 | 
						|
 | 
						|
      Profile.setEntry("setup");
 | 
						|
      Setup.initHXCPPConfig(defines);
 | 
						|
 | 
						|
      if (HXCPP=="" && env.exists("HXCPP"))
 | 
						|
      {
 | 
						|
         HXCPP = PathManager.standardize(env.get("HXCPP"));
 | 
						|
         defines.set("HXCPP",HXCPP);
 | 
						|
      }
 | 
						|
 | 
						|
      if (HXCPP=="")
 | 
						|
      {
 | 
						|
         if (!defines.exists("HXCPP"))
 | 
						|
         {
 | 
						|
            Log.error("Please run hxcpp using haxelib");
 | 
						|
            //throw "HXCPP not set, and not run from haxelib";
 | 
						|
         }
 | 
						|
         HXCPP = PathManager.standardize(defines.get("HXCPP"));
 | 
						|
         defines.set("HXCPP",HXCPP);
 | 
						|
      }
 | 
						|
 | 
						|
      //Log.info("", "HXCPP : " + HXCPP);
 | 
						|
 | 
						|
      include_path.push(".");
 | 
						|
      if (env.exists("HOME"))
 | 
						|
        include_path.push(env.get("HOME"));
 | 
						|
      if (env.exists("USERPROFILE"))
 | 
						|
        include_path.push(env.get("USERPROFILE"));
 | 
						|
      include_path.push(HXCPP);
 | 
						|
 | 
						|
 | 
						|
 | 
						|
      //trace(include_path);
 | 
						|
 | 
						|
      //var msvc = false;
 | 
						|
 | 
						|
      // Create alias...
 | 
						|
      if (defines.exists("ios"))
 | 
						|
      {
 | 
						|
         if (defines.exists("simulator"))
 | 
						|
            defines.set("iphonesim", "iphonesim");
 | 
						|
         else if (!defines.exists ("iphonesim"))
 | 
						|
            defines.set("iphoneos", "iphoneos");
 | 
						|
         defines.set("iphone", "iphone");
 | 
						|
      }
 | 
						|
 | 
						|
      if (defines.exists("tvos"))
 | 
						|
      {
 | 
						|
         if (defines.exists("simulator"))
 | 
						|
            defines.set("appletvsim", "appletvsim");
 | 
						|
         else if (!defines.exists ("appletvsim"))
 | 
						|
            defines.set("appletvos", "appletvos");
 | 
						|
         defines.set("appletv", "appletv");
 | 
						|
      }
 | 
						|
 | 
						|
 | 
						|
 | 
						|
      if (makefile=="" || Log.verbose)
 | 
						|
      {
 | 
						|
         printBanner();
 | 
						|
      }
 | 
						|
 | 
						|
      if (makefile=="")
 | 
						|
      {
 | 
						|
         printUsage();
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
         Log.v('${BOLD}${YELLOW}Using makefile: $makefile${NORMAL}');
 | 
						|
         Log.v('${BOLD}${YELLOW}Reading HXCPP config: ' + defines.get("HXCPP_CONFIG") + NORMAL);
 | 
						|
         if (defines.exists("toolchain"))
 | 
						|
            Log.v('${BOLD}{$YELLOW}Using target toolchain: ' + defines.get("toolchain") + NORMAL);
 | 
						|
         else
 | 
						|
            Log.v('${BOLD}${YELLOW}No specified toolchain${NORMAL}');
 | 
						|
         if (Log.verbose) Log.println("");
 | 
						|
 | 
						|
 | 
						|
         if (targets.length==0)
 | 
						|
            targets.push("default");
 | 
						|
 | 
						|
 | 
						|
         new BuildTool(makefile,defines,targets,include_path,dirtyList);
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
 | 
						|
   static function printUsage()
 | 
						|
   {
 | 
						|
      Log.println('${YELLOW}Usage:${NORMAL}');
 | 
						|
      Log.println(' ${BOLD}haxelib run hxcpp${NORMAL} file.xml ${ITALIC}${WHITE}[options]${NORMAL}');
 | 
						|
      Log.println('   Build project from "file.xml".  options:');
 | 
						|
      Log.println('    ${BOLD}-D${NORMAL}${ITALIC}value${NORMAL} -- Specify a define to use when processing other commands');
 | 
						|
      Log.println('    ${BOLD}-verbose${NORMAL} -- Print additional information (when available)');
 | 
						|
      Log.println('    ${BOLD}-dirty [groudId|all]${NORMAL} -- always rebuild files in given group');
 | 
						|
      Log.println(' ${BOLD}haxelib run hxcpp${NORMAL} ${ITALIC}${WHITE}file.cppia${NORMAL}');
 | 
						|
      Log.println('   Run cppia script using default Cppia host');
 | 
						|
      Log.println(' ${BOLD}haxelib run hxcpp${NORMAL} ${ITALIC}${WHITE}file.js${NORMAL}');
 | 
						|
      Log.println('    Run emscripten compiled scipt "file.js"');
 | 
						|
      Log.println(' ${BOLD}haxelib run hxcpp${NORMAL} ${ITALIC}${WHITE}cache [command] [project]${NORMAL}');
 | 
						|
      Log.println('   Perform command on cache, either on specific project or all. commands:');
 | 
						|
      Log.println('    ${BOLD}clear${NORMAL} -- remove all files from cache');
 | 
						|
      Log.println('    ${BOLD}days${NORMAL} #days -- remove files older than "days"');
 | 
						|
      Log.println('    ${BOLD}resize${NORMAL} #megabytes -- Only keep #megabytes MB');
 | 
						|
      Log.println('    ${BOLD}list${NORMAL} -- list cache usage');
 | 
						|
      Log.println('    ${BOLD}details${NORMAL} -- list cache usage, per file');
 | 
						|
      Log.println('');
 | 
						|
   }
 | 
						|
 | 
						|
 | 
						|
   static function printBanner()
 | 
						|
   {
 | 
						|
      Log.println("\x1b[33;1m __                          ");
 | 
						|
      Log.println("/\\ \\                                      ");
 | 
						|
      Log.println("\\ \\ \\___    __  _   ___   _____   _____   ");
 | 
						|
      Log.println(" \\ \\  _ `\\ /\\ \\/'\\ /'___\\/\\ '__`\\/\\ '__`\\ ");
 | 
						|
      Log.println("  \\ \\ \\ \\ \\\\/>  <//\\ \\__/\\ \\ \\L\\ \\ \\ \\L\\ \\");
 | 
						|
      Log.println("   \\ \\_\\ \\_\\/\\_/\\_\\ \\____\\\\ \\ ,__/\\ \\ ,__/");
 | 
						|
      Log.println("    \\/_/\\/_/\\//\\/_/\\/____/ \\ \\ \\/  \\ \\ \\/ ");
 | 
						|
      Log.println("                            \\ \\_\\   \\ \\_\\ ");
 | 
						|
      Log.println("                             \\/_/    \\/_/ \x1b[0m");
 | 
						|
      Log.println("");
 | 
						|
      Log.println("\x1b[1mhxcpp \x1b[0m\x1b[3;37m(Haxe C++ Runtime Support)\x1b[0m \x1b[1m(" + getVersion() + ")\x1b[0m");
 | 
						|
      Log.println("");
 | 
						|
   }
 | 
						|
 | 
						|
   function setDefaultToolchain(defines:Hash<String>)
 | 
						|
   {
 | 
						|
      if ( (new EReg("window","i")).match(os) )
 | 
						|
         defines.set("windows_host","1");
 | 
						|
 | 
						|
      if (defines.exists("iphoneos"))
 | 
						|
      {
 | 
						|
         defines.set("toolchain","iphoneos");
 | 
						|
         defines.set("iphone","iphone");
 | 
						|
         defines.set("apple","apple");
 | 
						|
         defines.set("BINDIR","iPhone");
 | 
						|
      }
 | 
						|
      else if (defines.exists("iphonesim"))
 | 
						|
      {
 | 
						|
         defines.set("toolchain","iphonesim");
 | 
						|
         defines.set("iphone","iphone");
 | 
						|
         defines.set("apple","apple");
 | 
						|
         defines.set("BINDIR","iPhone");
 | 
						|
      }
 | 
						|
      else if (defines.exists("appletvos"))
 | 
						|
      {
 | 
						|
         defines.set("toolchain","appletvos");
 | 
						|
         defines.set("appletv","appletv");
 | 
						|
         defines.set("apple","apple");
 | 
						|
         defines.set("BINDIR","AppleTV");
 | 
						|
      }
 | 
						|
      else if (defines.exists("appletvsim"))
 | 
						|
      {
 | 
						|
         defines.set("toolchain","appletvsim");
 | 
						|
         defines.set("appletv","appletv");
 | 
						|
         defines.set("apple","apple");
 | 
						|
         defines.set("BINDIR","AppleTV");
 | 
						|
      }
 | 
						|
      else if (defines.exists("watchos"))
 | 
						|
      {
 | 
						|
         defines.set("toolchain","watchos");
 | 
						|
         defines.set("apple","apple");
 | 
						|
         defines.set("applewatch","applewatch");
 | 
						|
         defines.set("BINDIR","watchos");
 | 
						|
      }
 | 
						|
      else if (defines.exists("watchsimulator"))
 | 
						|
      {
 | 
						|
         defines.set("toolchain","watchsimulator");
 | 
						|
         defines.set("applewatch","applewatch");
 | 
						|
         defines.set("apple","apple");
 | 
						|
         defines.set("BINDIR","watchsimulator");
 | 
						|
      }
 | 
						|
 | 
						|
      else if (defines.exists("android"))
 | 
						|
      {
 | 
						|
         defines.set("toolchain","android");
 | 
						|
         defines.set("android","android");
 | 
						|
         defines.set("BINDIR","Android");
 | 
						|
 | 
						|
         if (!defines.exists("ANDROID_HOST"))
 | 
						|
         {
 | 
						|
            if ( (new EReg("mac","i")).match(os) )
 | 
						|
               defines.set("ANDROID_HOST","darwin-x86_64");
 | 
						|
            else if ( (new EReg("window","i")).match(os) )
 | 
						|
            {
 | 
						|
               defines.set("windows_host","1");
 | 
						|
               defines.set("ANDROID_HOST","windows");
 | 
						|
            }
 | 
						|
            else if ( (new EReg("linux","i")).match(os) )
 | 
						|
               defines.set("ANDROID_HOST","linux-x86_64");
 | 
						|
            else
 | 
						|
            {
 | 
						|
               Log.error ("Unknown android host \"" + os + "\"");
 | 
						|
               //throw "Unknown android host:" + os;
 | 
						|
            }
 | 
						|
         }
 | 
						|
      }
 | 
						|
      else if (defines.exists("webos"))
 | 
						|
      {
 | 
						|
         defines.set("toolchain","webos");
 | 
						|
         defines.set("webos","webos");
 | 
						|
         defines.set("BINDIR","webOS");
 | 
						|
      }
 | 
						|
      else if (defines.exists("tizen"))
 | 
						|
      {
 | 
						|
         defines.set("toolchain","tizen");
 | 
						|
         defines.set("tizen","tizen");
 | 
						|
         defines.set("BINDIR","Tizen");
 | 
						|
      }
 | 
						|
      else if (defines.exists("blackberry"))
 | 
						|
      {
 | 
						|
         defines.set("toolchain", "blackberry");
 | 
						|
         defines.set("blackberry","blackberry");
 | 
						|
         defines.set("BINDIR","BlackBerry");
 | 
						|
      }
 | 
						|
      else if (defines.exists("emcc") || defines.exists("emscripten"))
 | 
						|
      {
 | 
						|
         defines.set("toolchain","emscripten");
 | 
						|
         defines.set("emcc","emcc");
 | 
						|
         defines.set("emscripten","emscripten");
 | 
						|
         defines.set("BINDIR","Emscripten");
 | 
						|
      }
 | 
						|
      else if (defines.exists("gph"))
 | 
						|
      {
 | 
						|
         defines.set("toolchain","gph");
 | 
						|
         defines.set("gph","gph");
 | 
						|
         defines.set("BINDIR","GPH");
 | 
						|
      }
 | 
						|
      else if (defines.exists ("gcw0"))
 | 
						|
      {
 | 
						|
         defines.set ("toolchain", "gcw0");
 | 
						|
         defines.set ("gcw0", "gcw0");
 | 
						|
         defines.set ("BINDIR", "GCW0");
 | 
						|
      }
 | 
						|
      else if (defines.exists("cygwin") || defines.exists("HXCPP_CYGWIN"))
 | 
						|
      {
 | 
						|
         set64(defines,m64);
 | 
						|
         defines.set("toolchain","cygwin");
 | 
						|
         defines.set("cygwin","cygwin");
 | 
						|
         defines.set("linux","linux");
 | 
						|
         defines.set("BINDIR",m64 ? "Cygwin64":"Cygwin");
 | 
						|
      }
 | 
						|
      else if ( (new EReg("window","i")).match(os) )
 | 
						|
      {
 | 
						|
         defines.set("windows_host","1");
 | 
						|
         // Cross-compile?
 | 
						|
         if (defines.exists("rpi"))
 | 
						|
         {
 | 
						|
            defines.set("toolchain","linux");
 | 
						|
            defines.set("xcompile","1");
 | 
						|
            defines.set("linux","linux");
 | 
						|
            defines.set("rpi","1");
 | 
						|
            defines.set("hardfp","1");
 | 
						|
            defines.set("BINDIR", "RPi");
 | 
						|
         }
 | 
						|
         else
 | 
						|
         {
 | 
						|
            set64(defines,m64,arm64);
 | 
						|
            defines.set("windows","windows");
 | 
						|
            defines.set("BINDIR",arm64 ? "WindowsArm64" : m64 ? "Windows64":"Windows");
 | 
						|
 | 
						|
            // Choose between MSVC and MINGW
 | 
						|
            var useMsvc = true;
 | 
						|
 | 
						|
            if (defines.exists("mingw") || defines.exists("HXCPP_MINGW") || defines.exists("minimingw"))
 | 
						|
               useMsvc = false;
 | 
						|
            else if ( defines.exists("winrt") || defines.exists("HXCPP_MSVC_VER"))
 | 
						|
               useMsvc = true;
 | 
						|
            else
 | 
						|
            {
 | 
						|
                for(i in 8...24)
 | 
						|
                {
 | 
						|
                   if (Sys.getEnv("VS" + i + "0COMNTOOLS")!=null)
 | 
						|
                   {
 | 
						|
                      useMsvc = true;
 | 
						|
                      break;
 | 
						|
                   }
 | 
						|
                }
 | 
						|
 | 
						|
                Log.v("Using Windows compiler: " + (useMsvc ? "MSVC" : "MinGW") );
 | 
						|
            }
 | 
						|
 | 
						|
            if (useMsvc)
 | 
						|
            {
 | 
						|
               defines.set("toolchain","msvc");
 | 
						|
               if ( defines.exists("winrt") )
 | 
						|
                  defines.set("BINDIR",m64 ? "WinRT64":"WinRT");
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
               defines.set("toolchain","mingw");
 | 
						|
               defines.set("mingw","mingw");
 | 
						|
            }
 | 
						|
         }
 | 
						|
      }
 | 
						|
      else if ( isRPi )
 | 
						|
      {
 | 
						|
         defines.set("toolchain","linux");
 | 
						|
         defines.set("linux","linux");
 | 
						|
         defines.set("rpi","1");
 | 
						|
         defines.set("hardfp","1");
 | 
						|
         defines.set("BINDIR", "RPi");
 | 
						|
      }
 | 
						|
      else if ( (new EReg("linux","i")).match(os) )
 | 
						|
      {
 | 
						|
         set64(defines,m64,arm64);
 | 
						|
         // Cross-compile?
 | 
						|
         if(defines.exists("windows"))
 | 
						|
         {
 | 
						|
            defines.set("toolchain","mingw");
 | 
						|
            defines.set("xcompile","1");
 | 
						|
            defines.set("BINDIR", arm64 ? "WindowsArm64" : m64 ? "Windows64":"Windows");
 | 
						|
         }
 | 
						|
         else
 | 
						|
         {
 | 
						|
            defines.set("toolchain","linux");
 | 
						|
            defines.set("linux","linux");
 | 
						|
 | 
						|
            if (defines.exists("HXCPP_LINUX_ARMV7"))
 | 
						|
            {
 | 
						|
               defines.set("noM32","1");
 | 
						|
               defines.set("noM64","1");
 | 
						|
               defines.set("HXCPP_ARMV7","1");
 | 
						|
               m64 = false;
 | 
						|
            }
 | 
						|
            else if (arm64 || defines.exists("HXCPP_LINUX_ARM64"))
 | 
						|
            {
 | 
						|
               defines.set("noM32","1");
 | 
						|
               defines.set("noM64","1");
 | 
						|
               defines.set("HXCPP_ARM64","1");
 | 
						|
               m64 = true;
 | 
						|
            }
 | 
						|
            defines.set("BINDIR", m64 ? "Linux64":"Linux");
 | 
						|
         }
 | 
						|
      }
 | 
						|
      else if ( (new EReg("mac","i")).match(os) )
 | 
						|
      {
 | 
						|
         set64(defines,m64, arm64);
 | 
						|
         // Cross-compile?
 | 
						|
         if (defines.exists("linux"))
 | 
						|
         {
 | 
						|
            defines.set("mac_host","1");
 | 
						|
            defines.set("linux","linux");
 | 
						|
            defines.set("toolchain","linux");
 | 
						|
            defines.set("xcompile","1");
 | 
						|
            defines.set("BINDIR", m64 ? "Linux64":"Linux");
 | 
						|
         }
 | 
						|
         else
 | 
						|
         {
 | 
						|
            defines.set("toolchain","mac");
 | 
						|
            defines.set("macos","macos");
 | 
						|
            defines.set("apple","apple");
 | 
						|
            defines.set("BINDIR", arm64 ? "MacArm64" : m64 ? "Mac64":"Mac");
 | 
						|
         }
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
 | 
						|
 | 
						|
   function setupAppleDirectories(defines:Hash<String>)
 | 
						|
   {
 | 
						|
      if (defines.exists("HXCPP_CLEAN_ONLY"))
 | 
						|
         return;
 | 
						|
 | 
						|
      if (defines.exists("apple") && !defines.exists("DEVELOPER_DIR"))
 | 
						|
      {
 | 
						|
         var developer_dir = ProcessManager.runProcessLine("", "xcode-select", ["--print-path"], true, false);
 | 
						|
         if (developer_dir == null || developer_dir == "" || developer_dir.indexOf ("Run xcode-select") > -1)
 | 
						|
            developer_dir = "/Applications/Xcode.app/Contents/Developer";
 | 
						|
         if (developer_dir == "/Developer")
 | 
						|
            defines.set("LEGACY_XCODE_LOCATION","1");
 | 
						|
         defines.set("DEVELOPER_DIR",developer_dir);
 | 
						|
      }
 | 
						|
 | 
						|
      if (defines.exists("iphone") && !defines.exists("IPHONE_VER"))
 | 
						|
      {
 | 
						|
         var dev_path = defines.get("DEVELOPER_DIR") + "/Platforms/iPhoneOS.platform/Developer/SDKs/";
 | 
						|
         if (FileSystem.exists(dev_path))
 | 
						|
         {
 | 
						|
            var best="0.0";
 | 
						|
            var files = FileSystem.readDirectory(dev_path);
 | 
						|
            var extract_version = ~/^iPhoneOS(.*).sdk$/;
 | 
						|
            for(file in files)
 | 
						|
            {
 | 
						|
               if (extract_version.match(file))
 | 
						|
               {
 | 
						|
                  var ver = extract_version.matched(1);
 | 
						|
                  if (Std.parseFloat (ver)>Std.parseFloat (best))
 | 
						|
                     best = ver;
 | 
						|
               }
 | 
						|
            }
 | 
						|
            if (best!="0.0")
 | 
						|
               defines.set("IPHONE_VER",best);
 | 
						|
         }
 | 
						|
      }
 | 
						|
 | 
						|
      if (defines.exists("appletv") && !defines.exists("TVOS_VER"))
 | 
						|
      {
 | 
						|
         var dev_path = defines.get("DEVELOPER_DIR") + "/Platforms/AppleTVOS.platform/Developer/SDKs/";
 | 
						|
         if (FileSystem.exists(dev_path))
 | 
						|
         {
 | 
						|
            var best="0.0";
 | 
						|
            var files = FileSystem.readDirectory(dev_path);
 | 
						|
            var extract_version = ~/^AppleTVOS(.*).sdk$/;
 | 
						|
            for(file in files)
 | 
						|
            {
 | 
						|
               if (extract_version.match(file))
 | 
						|
               {
 | 
						|
                  var ver = extract_version.matched(1);
 | 
						|
                  if (Std.parseFloat (ver)>Std.parseFloat (best))
 | 
						|
                     best = ver;
 | 
						|
               }
 | 
						|
            }
 | 
						|
            if (best!="0.0")
 | 
						|
               defines.set("TVOS_VER",best);
 | 
						|
         }
 | 
						|
      }
 | 
						|
 | 
						|
 | 
						|
      if (defines.exists("applewatch") && !defines.exists("WATCHOS_VER"))
 | 
						|
      {
 | 
						|
         var dev_path = defines.get("DEVELOPER_DIR") + "/Platforms/WatchOS.platform/Developer/SDKs/";
 | 
						|
         if (FileSystem.exists(dev_path))
 | 
						|
         {
 | 
						|
            var best="0.0";
 | 
						|
            var files = FileSystem.readDirectory(dev_path);
 | 
						|
            var extract_version = ~/^WatchOS(.*).sdk$/;
 | 
						|
            for(file in files)
 | 
						|
            {
 | 
						|
               if (extract_version.match(file))
 | 
						|
               {
 | 
						|
                  var ver = extract_version.matched(1);
 | 
						|
                  if (Std.parseFloat (ver)>Std.parseFloat (best))
 | 
						|
                     best = ver;
 | 
						|
               }
 | 
						|
            }
 | 
						|
            if (best!="0.0")
 | 
						|
               defines.set("WATCHOS_VER",best);
 | 
						|
         }
 | 
						|
      }
 | 
						|
 | 
						|
 | 
						|
      if (defines.exists("macos") && !defines.exists("MACOSX_VER"))
 | 
						|
      {
 | 
						|
         var dev_path = defines.get("DEVELOPER_DIR") + "/Platforms/MacOSX.platform/Developer/SDKs/";
 | 
						|
         if (FileSystem.exists(dev_path))
 | 
						|
         {
 | 
						|
            var best="0.0";
 | 
						|
            var files = FileSystem.readDirectory(dev_path);
 | 
						|
            var extract_version = ~/^MacOSX(.*).sdk$/;
 | 
						|
            for(file in files)
 | 
						|
            {
 | 
						|
               if (extract_version.match(file))
 | 
						|
               {
 | 
						|
                  var ver = extract_version.matched(1);
 | 
						|
                  var split_best = best.split(".");
 | 
						|
                  var split_ver = ver.split(".");
 | 
						|
                  if (Std.parseFloat(split_ver[0]) > Std.parseFloat(split_best[0]) || Std.parseFloat(split_ver[1]) > Std.parseFloat(split_best[1]))
 | 
						|
                     best = ver;
 | 
						|
               }
 | 
						|
            }
 | 
						|
            if (best!="0.0")
 | 
						|
               defines.set("MACOSX_VER",best);
 | 
						|
            else
 | 
						|
               Log.v("Could not find MACOSX_VER!");
 | 
						|
         }
 | 
						|
      }
 | 
						|
 | 
						|
      if (!FileSystem.exists(defines.get("DEVELOPER_DIR") + "/Platforms/MacOSX.platform/Developer/SDKs/"))
 | 
						|
      {
 | 
						|
         defines.set("LEGACY_MACOSX_SDK","1");
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   function parseXML(inXML:XmlAccess,inSection:String, forceRelative:Bool)
 | 
						|
   {
 | 
						|
      for(el in inXML.elements)
 | 
						|
      {
 | 
						|
         if (valid(el,inSection))
 | 
						|
         {
 | 
						|
            switch(el.name)
 | 
						|
            {
 | 
						|
               case "set" :
 | 
						|
                  var name = substitute(el.att.name);
 | 
						|
                  var value = substitute(el.att.value);
 | 
						|
                  mDefines.set(name,value);
 | 
						|
               case "unset" :
 | 
						|
                  var name = substitute(el.att.name);
 | 
						|
                  mDefines.remove(name);
 | 
						|
               case "setup" :
 | 
						|
                  var name = substitute(el.att.name);
 | 
						|
                  Setup.setup(name,mDefines);
 | 
						|
               case "echo" :
 | 
						|
                  Log.info(substitute(el.att.value));
 | 
						|
               case "setenv" :
 | 
						|
                  var name = substitute(el.att.name);
 | 
						|
                  var value = substitute(el.att.value);
 | 
						|
                  mDefines.set(name,value);
 | 
						|
                  Sys.putEnv(name,value);
 | 
						|
               case "error" :
 | 
						|
                  var error = substitute(el.att.value);
 | 
						|
                  Log.error(error);
 | 
						|
               case "path" :
 | 
						|
                  var path = substitute(el.att.name);
 | 
						|
                  Log.info("", " - \x1b[1mAdding path:\x1b[0m " + path);
 | 
						|
                  var sep = mDefines.exists("windows_host") ? ";" : ":";
 | 
						|
                  var add = path + sep + Sys.getEnv("PATH");
 | 
						|
                  Sys.putEnv("PATH", add);
 | 
						|
                  //trace(Sys.getEnv("PATH"));
 | 
						|
               case "compiler" :
 | 
						|
                  mCompiler = createCompiler(el,mCompiler);
 | 
						|
 | 
						|
               case "stripper" :
 | 
						|
                  mStripper = createStripper(el,mStripper);
 | 
						|
               case "manifest" :
 | 
						|
                  mManifester = createManifester(el,mManifester);
 | 
						|
               case "prelinker" :
 | 
						|
                  var name = substitute(el.att.id);
 | 
						|
                  if (mPrelinkers.exists(name))
 | 
						|
                     createPrelinker(el,mPrelinkers.get(name));
 | 
						|
                  else
 | 
						|
                     mPrelinkers.set(name, createPrelinker(el,null) );
 | 
						|
               case "linker" :
 | 
						|
                  var name = substitute(el.att.id);
 | 
						|
                  if (mLinkers.exists(name))
 | 
						|
                     createLinker(el,mLinkers.get(name));
 | 
						|
                  else
 | 
						|
                     mLinkers.set(name, createLinker(el,null) );
 | 
						|
               case "files" :
 | 
						|
                  var name = substitute(el.att.id);
 | 
						|
                  var tags = el.has.tags ? substitute(el.att.tags) : null;
 | 
						|
                  if (mFileGroups.exists(name) )
 | 
						|
                     createFileGroup(el, mFileGroups.get(name), name, false, tags);
 | 
						|
                  else
 | 
						|
                     mFileGroups.set(name,createFileGroup(el,null,name, forceRelative,tags));
 | 
						|
               case "include", "import" :
 | 
						|
                  var name = substitute(el.att.name);
 | 
						|
                  var section = el.has.section ? substitute(el.att.section) : "";
 | 
						|
                  include(name, section, el.has.noerror, el.name=="import" );
 | 
						|
               case "target" :
 | 
						|
                  var name = substitute(el.att.id);
 | 
						|
                  var overwrite = name=="default";
 | 
						|
                  if (el.has.overwrite)
 | 
						|
                     overwrite = true;
 | 
						|
                  if (el.has.append)
 | 
						|
                     overwrite = false;
 | 
						|
                  if (mTargets.exists(name) && !overwrite)
 | 
						|
                     createTarget(el,mTargets.get(name), forceRelative);
 | 
						|
                  else
 | 
						|
                     mTargets.set( name, createTarget(el,null, forceRelative) );
 | 
						|
 | 
						|
               case "mkdir" :
 | 
						|
                  var name = substitute(el.att.name);
 | 
						|
                  try {
 | 
						|
                     PathManager.mkdir(name);
 | 
						|
                  } catch(e:Dynamic)
 | 
						|
                  {
 | 
						|
                     Log.error("Could not create directory " + name );
 | 
						|
                  }
 | 
						|
 | 
						|
 | 
						|
               case "copy" :
 | 
						|
                   var from = substitute(el.att.from);
 | 
						|
                   from = PathManager.combine( Path.directory(mCurrentIncludeFile), from );
 | 
						|
                   var to = substitute(el.att.to);
 | 
						|
                   to = PathManager.combine( Path.directory(mCurrentIncludeFile), to );
 | 
						|
                   copy(from,to);
 | 
						|
 | 
						|
               case "copyFile" :
 | 
						|
                  mCopyFiles.push(
 | 
						|
                      new CopyFile(substitute(el.att.name),
 | 
						|
                                   substitute(el.att.from),
 | 
						|
                                   el.has.allowMissing ?  subBool(el.att.allowMissing) : false,
 | 
						|
                                   el.has.overwrite ? substitute(el.att.overwrite) : Overwrite.ALWAYS,
 | 
						|
                                   el.has.toolId ?  substitute(el.att.toolId) : null ) );
 | 
						|
               case "section" :
 | 
						|
                  parseXML(el,"",forceRelative);
 | 
						|
 | 
						|
               case "pleaseUpdateHxcppTool" :
 | 
						|
                  checkToolVersion( substitute(el.att.version) );
 | 
						|
 | 
						|
               case "magiclib" :
 | 
						|
                  mMagicLibs.push( {name: substitute(el.att.name),
 | 
						|
                                    replace:substitute(el.att.replace) } );
 | 
						|
               case "nvccflag" :
 | 
						|
                  if (el.has.name)
 | 
						|
                     mNvccFlags.push( substitute(el.att.name) );
 | 
						|
                  mNvccFlags.push( substitute(el.att.value) );
 | 
						|
 | 
						|
               case "nvcclinkflag" :
 | 
						|
                  if (el.has.name)
 | 
						|
                     mNvccLinkFlags.push( substitute(el.att.name) );
 | 
						|
                  mNvccLinkFlags.push( substitute(el.att.value) );
 | 
						|
 | 
						|
               case "pragma" :
 | 
						|
                  if (el.has.once)
 | 
						|
                     mPragmaOnce.set(mCurrentIncludeFile, parseBool(substitute(el.att.once)));
 | 
						|
            }
 | 
						|
         }
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   public function checkToolVersion(inVersion:String)
 | 
						|
   {
 | 
						|
      var ver = Std.parseInt(inVersion);
 | 
						|
      if (ver>3)
 | 
						|
         Log.error("Your version of hxcpp.n is out-of-date.  Please update.");
 | 
						|
   }
 | 
						|
 | 
						|
   public function resolvePath(inPath:String)
 | 
						|
   {
 | 
						|
      return PathManager.combine( mCurrentIncludeFile=="" ? Sys.getCwd() : Path.directory(mCurrentIncludeFile),
 | 
						|
           inPath);
 | 
						|
   }
 | 
						|
 | 
						|
   public function include(inName:String, inSection:String="", inAllowMissing:Bool = false, forceRelative=false)
 | 
						|
   {
 | 
						|
      var full_name = findIncludeFile(inName);
 | 
						|
      if (full_name!="")
 | 
						|
      {
 | 
						|
         if (mPragmaOnce.get(full_name))
 | 
						|
            return;
 | 
						|
 | 
						|
         pushFile(full_name, "include", inSection);
 | 
						|
         // TODO - use mFileStack?
 | 
						|
         var oldInclude = mCurrentIncludeFile;
 | 
						|
         mCurrentIncludeFile = full_name;
 | 
						|
 | 
						|
         var make_contents = sys.io.File.getContent(full_name);
 | 
						|
         var xml_slow = Xml.parse(make_contents);
 | 
						|
 | 
						|
         Profile.push( haxe.io.Path.withoutDirectory(inName) );
 | 
						|
         parseXML(new XmlAccess(xml_slow.firstElement()),inSection, forceRelative);
 | 
						|
         Profile.pop();
 | 
						|
 | 
						|
         mCurrentIncludeFile = oldInclude;
 | 
						|
         popFile();
 | 
						|
      }
 | 
						|
      else if (!inAllowMissing)
 | 
						|
      {
 | 
						|
         Log.error("Could not find include file \"" + inName + "\"");
 | 
						|
         //throw "Could not find include file " + name;
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
 | 
						|
 | 
						|
   static function set64(outDefines:Hash<String>, in64:Bool,isArm64=false)
 | 
						|
   {
 | 
						|
      if (isArm64)
 | 
						|
      {
 | 
						|
         outDefines.set("HXCPP_ARM64","1");
 | 
						|
         outDefines.set("HXCPP_M64","1");
 | 
						|
         outDefines.remove("HXCPP_32");
 | 
						|
      }
 | 
						|
      else if (in64)
 | 
						|
      {
 | 
						|
         outDefines.set("HXCPP_M64","1");
 | 
						|
         outDefines.remove("HXCPP_32");
 | 
						|
         outDefines.remove("HXCPP_ARM64");
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
         outDefines.set("HXCPP_M32","1");
 | 
						|
         outDefines.remove("HXCPP_M64");
 | 
						|
         outDefines.remove("HXCPP_ARM64");
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   public function dospath(path:String) : String
 | 
						|
   {
 | 
						|
      if (mDefines.exists("windows_host"))
 | 
						|
      {
 | 
						|
         path = path.split("\\").join("/");
 | 
						|
         var filename = "";
 | 
						|
         var parts = path.split("/");
 | 
						|
         if (!FileSystem.isDirectory(path))
 | 
						|
            filename = parts.pop();
 | 
						|
 | 
						|
         var oldDir = Sys.getCwd();
 | 
						|
         var output = "";
 | 
						|
         var err = "";
 | 
						|
         Sys.setCwd(parts.join("\\"));
 | 
						|
         try {
 | 
						|
            var bat = '$HXCPP/toolchain/dospath.bat'.split("/").join("\\");
 | 
						|
            var process = new Process("cmd",["/c",bat]);
 | 
						|
            output = process.stdout.readAll().toString();
 | 
						|
            output = output.split("\r")[0].split("\n")[0];
 | 
						|
            err  = process.stderr.readAll().toString();
 | 
						|
            process.close();
 | 
						|
         } catch (e:Dynamic) { Log.error(e); }
 | 
						|
         Sys.setCwd(oldDir);
 | 
						|
 | 
						|
         if (output=="")
 | 
						|
            Log.error("Could not find dos path for " + path + " " + err);
 | 
						|
         return output + "\\" + filename;
 | 
						|
      }
 | 
						|
 | 
						|
      return path;
 | 
						|
   }
 | 
						|
 | 
						|
   public function substitute(str:String,needDollar=true):String
 | 
						|
   {
 | 
						|
      var match = needDollar ? mVarMatch : mNoDollarMatch;
 | 
						|
      while( match.match(str) )
 | 
						|
      {
 | 
						|
         var sub = match.matched(1);
 | 
						|
         if (sub.startsWith("haxelib:"))
 | 
						|
         {
 | 
						|
            sub = PathManager.getHaxelib(sub.substr(8));
 | 
						|
            sub = PathManager.standardize(sub);
 | 
						|
         }
 | 
						|
         else if (sub.startsWith("removeQuotes:"))
 | 
						|
         {
 | 
						|
            sub = mDefines.get(sub.substr(13));
 | 
						|
            var len = sub.length;
 | 
						|
            if (len>1 && sub.substr(0,1)=="\"" && sub.substr(len-1)=="\"")
 | 
						|
               sub = sub.substr(1,len-2);
 | 
						|
         }
 | 
						|
         else if (sub.startsWith("dospath:") )
 | 
						|
         {
 | 
						|
            sub = dospath( mDefines.get(sub.substr(8)) );
 | 
						|
         }
 | 
						|
         else if (sub.startsWith("dir:") )
 | 
						|
         {
 | 
						|
            sub = dospath( mDefines.get(sub.substr(4)) );
 | 
						|
            if (!FileSystem.isDirectory(sub))
 | 
						|
            {
 | 
						|
               sub = haxe.io.Path.directory(sub);
 | 
						|
            }
 | 
						|
         }
 | 
						|
         else if (sub=="this_dir")
 | 
						|
         {
 | 
						|
            sub = Path.normalize(mCurrentIncludeFile=="" ? Sys.getCwd() :  Path.directory(mCurrentIncludeFile));
 | 
						|
         }
 | 
						|
         else
 | 
						|
            sub = mDefines.get(sub);
 | 
						|
 | 
						|
         if (sub==null) sub="";
 | 
						|
         str = match.matchedLeft() + sub + match.matchedRight();
 | 
						|
      }
 | 
						|
 | 
						|
      return str;
 | 
						|
   }
 | 
						|
 | 
						|
   public function subBool(str:String):Bool
 | 
						|
   {
 | 
						|
      var result = substitute(str);
 | 
						|
      return result=="t" || result=="true" || result=="1";
 | 
						|
   }
 | 
						|
 | 
						|
   public function valid(inEl:XmlAccess,inSection:String):Bool
 | 
						|
   {
 | 
						|
      if (inEl.x.get("if") != null)
 | 
						|
      {
 | 
						|
         var value = inEl.x.get("if");
 | 
						|
         var optionalDefines = value.split("||");
 | 
						|
         var matchOptional = false;
 | 
						|
         for (optional in optionalDefines)
 | 
						|
         {
 | 
						|
            var requiredDefines = optional.split(" ");
 | 
						|
            var matchRequired = true;
 | 
						|
            for (required in requiredDefines)
 | 
						|
            {
 | 
						|
               var check = StringTools.trim(required);
 | 
						|
               if (check != "" && !defined(check))
 | 
						|
               {
 | 
						|
                  matchRequired = false;
 | 
						|
               }
 | 
						|
            }
 | 
						|
            if (matchRequired)
 | 
						|
            {
 | 
						|
               matchOptional = true;
 | 
						|
            }
 | 
						|
         }
 | 
						|
         if (optionalDefines.length > 0 && !matchOptional)
 | 
						|
         {
 | 
						|
            return false;
 | 
						|
         }
 | 
						|
      }
 | 
						|
 | 
						|
      if (inEl.has.unless)
 | 
						|
      {
 | 
						|
         var value = substitute(inEl.att.unless);
 | 
						|
         var optionalDefines = value.split("||");
 | 
						|
         var matchOptional = false;
 | 
						|
         for (optional in optionalDefines)
 | 
						|
         {
 | 
						|
            var requiredDefines = optional.split(" ");
 | 
						|
            var matchRequired = true;
 | 
						|
            for (required in requiredDefines)
 | 
						|
            {
 | 
						|
               var check = StringTools.trim(required);
 | 
						|
               if (check != "" && !defined(check))
 | 
						|
               {
 | 
						|
                  matchRequired = false;
 | 
						|
               }
 | 
						|
            }
 | 
						|
            if (matchRequired)
 | 
						|
            {
 | 
						|
               matchOptional = true;
 | 
						|
            }
 | 
						|
         }
 | 
						|
         if (optionalDefines.length > 0 && matchOptional)
 | 
						|
         {
 | 
						|
            return false;
 | 
						|
         }
 | 
						|
      }
 | 
						|
 | 
						|
      if (inEl.has.unlessApi)
 | 
						|
      {
 | 
						|
         var value = substitute(inEl.att.unlessApi);
 | 
						|
         try {
 | 
						|
            var val = Std.parseInt(value);
 | 
						|
            if (val<=SupportedVersion)
 | 
						|
               return false;
 | 
						|
         } catch(e:Dynamic) { }
 | 
						|
      }
 | 
						|
 | 
						|
 | 
						|
      if (inEl.has.ifExists)
 | 
						|
         if (!FileSystem.exists( substitute(inEl.att.ifExists) )) return false;
 | 
						|
 | 
						|
      if (inSection!="")
 | 
						|
      {
 | 
						|
         if (inEl.name!="section")
 | 
						|
            return false;
 | 
						|
         if (!inEl.has.id)
 | 
						|
            return false;
 | 
						|
         if (inEl.att.id!=inSection)
 | 
						|
            return false;
 | 
						|
      }
 | 
						|
 | 
						|
      return true;
 | 
						|
   }
 | 
						|
}
 |