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