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;
 | |
|    }
 | |
| }
 |