diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..c6e49efc9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +obj/ +bin/ diff --git a/run.n b/run.n index 2c8f8e084..3ca75bf9b 100644 Binary files a/run.n and b/run.n differ diff --git a/tools/run/BuildTool.hx b/tools/run/BuildTool.hx index af5d950c4..a369f8fb6 100644 --- a/tools/run/BuildTool.hx +++ b/tools/run/BuildTool.hx @@ -1,940 +1,46 @@ import haxe.io.Path; +import haxe.xml.Fast; +import sys.io.Process; import sys.FileSystem; #if neko import neko.vm.Thread; import neko.vm.Mutex; import neko.vm.Tls; -import neko.vm.Tls; #else import cpp.vm.Thread; import cpp.vm.Mutex; import cpp.vm.Tls; #end -class DirManager -{ - static var mMade = new Hash(); - - static public function make(inDir:String) - { - var parts = inDir.split("/"); - var total = ""; - for(part in parts) - { - if (part!="." && part!="") - { - if (total!="") total+="/"; - total += part; - if (!mMade.exists(total)) - { - mMade.set(total,true); - if (!FileSystem.exists(total)) - { - try - { - #if haxe3 - FileSystem.createDirectory(total + "/"); - #else - FileSystem.createDirectory(total ); - #end - } catch (e:Dynamic) - { - return false; - } - } - } - } - } - return true; - } - public static function reset() - { - mMade = new Hash(); - } - static public function makeFileDir(inFile:String) - { - var parts = StringTools.replace (inFile, "\\", "/").split("/"); - if (parts.length<2) - return; - parts.pop(); - make(parts.join("/")); - } - - static public function deleteFile(inName:String) - { - if (FileSystem.exists(inName)) - { - BuildTool.log("rm " + inName); - FileSystem.deleteFile(inName); - } - } - - static public function deleteExtension(inExt:String) - { - var contents = FileSystem.readDirectory("."); - for(item in contents) - { - if (item.length > inExt.length && item.substr(item.length-inExt.length)==inExt) - deleteFile(item); - } - } - - static public function deleteRecurse(inDir:String) - { - if (FileSystem.exists(inDir)) - { - var contents = FileSystem.readDirectory(inDir); - for(item in contents) - { - if (item!="." && item!="..") - { - var name = inDir + "/" + item; - if (FileSystem.isDirectory(name)) - deleteRecurse(name); - else - { - BuildTool.log("rm " + name); - FileSystem.deleteFile(name); - } - } - } - BuildTool.log("rmdir " + inDir); - FileSystem.deleteDirectory(inDir); - } - } - -} - -class Compiler -{ - public var mFlags : Array; - public var mCFlags : Array; - public var mMMFlags : Array; - public var mCPPFlags : Array; - public var mOBJCFlags : Array; - public var mPCHFlags : Array; - public var mAddGCCIdentity: Bool; - public var mExe:String; - public var mOutFlag:String; - public var mObjDir:String; - public var mExt:String; - - public var mPCHExt:String; - public var mPCHCreate:String; - public var mPCHUse:String; - public var mPCHFilename:String; - public var mPCH:String; - - public var mGetCompilerVersion:String; - public var mCompilerVersion:String; - public var mCached:Bool; - - public var mID:String; - - public function new(inID,inExe:String,inGCCFileTypes:Bool) - { - mFlags = []; - mCFlags = []; - mCPPFlags = []; - mOBJCFlags = []; - mMMFlags = []; - mPCHFlags = []; - mAddGCCIdentity = inGCCFileTypes; - mCompilerVersion = null; - mObjDir = "obj"; - mOutFlag = "-o"; - mExe = inExe; - mID = inID; - mExt = ".o"; - mPCHExt = ".pch"; - mPCHCreate = "-Yc"; - mPCHUse = "-Yu"; - mPCHFilename = "/Fp"; - mCached = false; - } - - function addIdentity(ext:String,ioArgs:Array) - { - if (mAddGCCIdentity) - { - var identity = switch(ext) - { - case "c" : "c"; - case "m" : "objective-c"; - case "mm" : "objective-c++"; - case "cpp" : "c++"; - case "c++" : "c++"; - default:""; - } - if (identity!="") - { - ioArgs.push("-x"); - ioArgs.push(identity); - } - } - } - - public function setPCH(inPCH:String) - { - mPCH = inPCH; - if (mPCH=="gcc") - { - mPCHExt = ".h.gch"; - mPCHUse = ""; - mPCHFilename = ""; - } - } - - public function needsPchObj() - { - return !mCached && mPCH!="gcc"; - } - - public function createCompilerVersion(inGroup:FileGroup) - { - if (mGetCompilerVersion!=null && mCompilerVersion==null) - { - var exe = mGetCompilerVersion; - var args = new Array(); - if (exe.indexOf (" ") > -1) - { - var splitExe = exe.split(" "); - exe = splitExe.shift(); - args = splitExe.concat(args); - } - - var versionString = Setup.readStderr(exe,args).join(" "); - if (BuildTool.verbose) - { - BuildTool.println("--- Compiler verison ---" ); - BuildTool.println( versionString ); - BuildTool.println("------------------"); - } - - mCompilerVersion = haxe.crypto.Md5.encode(versionString); - mCached = true; - } - - return mCached; - } - - public function precompile(inObjDir:String,inGroup:FileGroup) - { - var header = inGroup.mPrecompiledHeader; - var file = inGroup.getPchName(); - - var args = inGroup.mCompilerFlags.concat(mFlags).concat( mCPPFlags ).concat( mPCHFlags ); - - var dir = inObjDir + "/" + inGroup.getPchDir() + "/"; - var pch_name = dir + file + mPCHExt; - - BuildTool.log("Make pch dir " + dir ); - DirManager.make(dir); - - if (mPCH!="gcc") - { - args.push( mPCHCreate + header + ".h" ); - - // Create a temp file for including ... - var tmp_cpp = dir + file + ".cpp"; - var outFile = sys.io.File.write(tmp_cpp,false); - outFile.writeString("#include <" + header + ".h>\n"); - outFile.close(); - - args.push( tmp_cpp ); - args.push(mPCHFilename + pch_name); - args.push(mOutFlag + dir + file + mExt); - } - else - { - BuildTool.log("Make pch dir " + dir + header ); - DirManager.make(dir + header); - args.push( "-o" ); - args.push(pch_name); - args.push( inGroup.mPrecompiledHeaderDir + "/" + inGroup.mPrecompiledHeader + ".h" ); - } - - - BuildTool.println("Creating " + pch_name + "..."); - var result = BuildTool.runCommand( mExe, args, true, false ); - if (result!=0) - { - if (FileSystem.exists(pch_name)) - FileSystem.deleteFile(pch_name); - throw "Error creating pch: " + result + " - build cancelled"; - } - } - - public function getObjName(inFile:File) - { - var path = new haxe.io.Path(inFile.mName); - var dirId = - haxe.crypto.Md5.encode(BuildTool.targetKey + path.dir).substr(0,8) + "_"; - - return mObjDir + "/" + dirId + path.file + mExt; - } - - public function compile(inFile:File,inTid:Int) - { - var path = new haxe.io.Path(mObjDir + "/" + inFile.mName); - var obj_name = getObjName(inFile); - - var args = new Array(); - - args = args.concat(inFile.mCompilerFlags).concat(inFile.mGroup.mCompilerFlags).concat(mFlags); - - var ext = path.ext.toLowerCase(); - addIdentity(ext,args); - - var allowPch = false; - if (ext=="c") - args = args.concat(mCFlags); - else if (ext=="m") - args = args.concat(mOBJCFlags); - else if (ext=="mm") - args = args.concat(mMMFlags); - else if (ext=="cpp" || ext=="c++") - { - allowPch = true; - args = args.concat(mCPPFlags); - } - - - if (!mCached && inFile.mGroup.mPrecompiledHeader!="" && allowPch) - { - var pchDir = inFile.mGroup.getPchDir(); - if (mPCHUse!="") - { - args.push(mPCHUse + inFile.mGroup.mPrecompiledHeader + ".h"); - args.push(mPCHFilename + mObjDir + "/" + pchDir + "/" + inFile.mGroup.getPchName() + mPCHExt); - } - else - args.unshift("-I"+mObjDir + "/" + pchDir); - } - - - var found = false; - var cacheName:String = null; - if (mCompilerVersion!=null) - { - var sourceName = inFile.mDir + inFile.mName; - var contents = sys.io.File.getContent(sourceName); - if (contents!="") - { - var md5 = haxe.crypto.Md5.encode(contents + args.join(" ") + - inFile.mGroup.mDependHash + mCompilerVersion + inFile.mDependHash ); - cacheName = BuildTool.compileCache + "/" + md5; - if (FileSystem.exists(cacheName)) - { - sys.io.File.copy(cacheName, obj_name); - BuildTool.println("use cache for " + obj_name + "(" + md5 + ")" ); - found = true; - } - else - { - BuildTool.log(" not in cache " + cacheName); - } - } - else - throw "Unkown source contents " + sourceName; - } - - if (!found) - { - args.push( (new haxe.io.Path( inFile.mDir + inFile.mName)).toString() ); - - var out = mOutFlag; - if (out.substr(-1)==" ") - { - args.push(out.substr(0,out.length-1)); - out = ""; - } - - args.push(out + obj_name); - var result = BuildTool.runCommand( mExe, args, true, inTid>=0 ); - if (result!=0) - { - if (FileSystem.exists(obj_name)) - FileSystem.deleteFile(obj_name); - throw "Error : " + result + " - build cancelled"; - } - if (cacheName!=null) - { - sys.io.File.copy(obj_name, cacheName ); - BuildTool.log(" caching " + cacheName); - } - } - - return obj_name; - } -} - - -class Linker -{ - public var mExe:String; - public var mFlags : Array; - public var mOutFlag:String; - public var mExt:String; - public var mNamePrefix:String; - public var mLibDir:String; - public var mRanLib:String; - public var mFromFile:String; - public var mLibs:Array; - public var mExpandArchives : Bool; - public var mRecreate:Bool; - - public function new(inExe:String) - { - mFlags = []; - mOutFlag = "-o"; - mExe = inExe; - mNamePrefix = ""; - mLibDir = ""; - mRanLib = ""; - mExpandArchives = false; - // Default to on... - mFromFile = "@"; - mLibs = []; - mRecreate = false; - } - public function link(inTarget:Target,inObjs:Array,inCompiler:Compiler) - { - var ext = inTarget.mExt=="" ? mExt : inTarget.mExt; - var file_name = mNamePrefix + inTarget.mOutput + ext; - if(!DirManager.make(inTarget.mOutputDir)) - { - throw "Unable to create output directory " + inTarget.mOutputDir; - } - var out_name = inTarget.mOutputDir + file_name; - - var libs = inTarget.mLibs.concat(mLibs); - var v18Added = false; - var isOutOfDateLibs = false; - - for(i in 0...libs.length) - { - var lib = libs[i]; - var parts = lib.split("{MSVC_VER}"); - if (parts.length==2) - { - var ver = ""; - if (BuildTool.isMsvc()) - { - var current = parts[0] + "-" + BuildTool.getMsvcVer() + parts[1]; - if (FileSystem.exists(current)) - { - BuildTool.log("Using current compiler library " + current); - libs[i]=current; - } - else - { - var v18 = parts[0] + "-18" + parts[1]; - if (FileSystem.exists(v18)) - { - BuildTool.log("Using msvc18 compatible library " + v18); - libs[i]=v18; - if (!v18Added) - { - v18Added=true; - libs.push( BuildTool.HXCPP + "/lib/Windows/libmsvccompat-18.lib"); - } - } - else - { - throw "Could not find compatible library for " + lib + ", " + v18 + " does not exist"; - } - } - } - else - libs[i] = parts[0] + parts[1]; - } - if (!isOutOfDateLibs) - { - var lib = libs[i]; - if (FileSystem.exists(lib)) - isOutOfDateLibs = isOutOfDate(out_name,[lib]); - } - } - - - if (isOutOfDateLibs || isOutOfDate(out_name,inObjs) || isOutOfDate(out_name,inTarget.mDepends)) - { - var args = new Array(); - var out = mOutFlag; - if (out.substr(-1)==" ") - { - args.push(out.substr(0,out.length-1)); - out = ""; - } - // Build in temp dir, and then move out so all the crap windows - // creates stays out of the way - if (mLibDir!="") - { - DirManager.make(mLibDir); - args.push(out + mLibDir + "/" + file_name); - } - else - { - if (mRecreate && FileSystem.exists(out_name)) - { - BuildTool.println(" clean " + out_name ); - FileSystem.deleteFile(out_name); - } - args.push(out + out_name); - } - - args = args.concat(mFlags).concat(inTarget.mFlags); - - - var objs = inObjs.copy(); - - if (mExpandArchives) - { - var isArchive = ~/\.a$/; - var libArgs = new Array(); - for(lib in libs) - { - if (isArchive.match(lib)) - { - var libName = Path.withoutDirectory(lib); - var libObjs = Setup.readStdout( mExe , ["t", lib] ); - var objDir = inCompiler.mObjDir + "/" + libName; - DirManager.make(objDir); - var here = Sys.getCwd(); - Sys.setCwd(objDir); - BuildTool.runCommand( mExe , ["x", lib], true, false ); - Sys.setCwd(here); - for(obj in libObjs) - objs.push( objDir+"/"+obj ); - } - else - libArgs.push(lib); - } - libs = libArgs; - } - - - // Place list of obj files in a file called "all_objs" - if (mFromFile=="@") - { - var fname = inCompiler.mObjDir + "/all_objs"; - var fout = sys.io.File.write(fname,false); - for(obj in objs) - fout.writeString(obj + "\n"); - fout.close(); - args.push("@" + fname ); - } - else - args = args.concat(objs); - - args = args.concat(libs); - - var result = BuildTool.runCommand( mExe, args, true, false ); - if (result!=0) - throw "Error : " + result + " - build cancelled"; - - if (mRanLib!="") - { - args = [out_name]; - var result = BuildTool.runCommand( mRanLib, args, true, false ); - if (result!=0) - throw "Error : " + result + " - build cancelled"; - } - - if (mLibDir!="") - { - sys.io.File.copy( mLibDir+"/"+file_name, out_name ); - FileSystem.deleteFile( mLibDir+"/"+file_name ); - } - return out_name; - } - - return ""; - } - function isOutOfDate(inName:String, inObjs:Array) - { - if (!FileSystem.exists(inName)) - return true; - var stamp = FileSystem.stat(inName).mtime.getTime(); - for(obj in inObjs) - { - if (!FileSystem.exists(obj)) - throw "Could not find " + obj + " required by " + inName; - var obj_stamp = FileSystem.stat(obj).mtime.getTime(); - if (obj_stamp > stamp) - return true; - } - return false; - } -} - - - -class Stripper -{ - public var mExe:String; - public var mFlags : Array; - - public function new(inExe:String) - { - mFlags = []; - mExe = inExe; - } - public function strip(inTarget:String) - { - var args = new Array(); - - args = args.concat(mFlags); - - args.push(inTarget); - - var result = BuildTool.runCommand( mExe, args, true,false ); - if (result!=0) - throw "Error : " + result + " - build cancelled"; - } -} - -class File -{ - public function new(inName:String, inGroup:FileGroup) - { - mName = inName; - mDir = inGroup.mDir; - if (mDir!="") mDir += "/"; - // Do not take copy - use reference so it can be updated - mGroup = inGroup; - mDepends = []; - mCompilerFlags = []; - } - public function computeDependHash() - { - mDependHash = ""; - for(depend in mDepends) - mDependHash += getFileHash(depend); - mDependHash = haxe.crypto.Md5.encode(mDependHash); - } - - public static function getFileHash(inName:String) - { - if (mFileHashes.exists(inName)) - return mFileHashes.get(inName); - - var content = sys.io.File.getContent(inName); - var md5 = haxe.crypto.Md5.encode(content); - mFileHashes.set(inName,md5); - return md5; - } - - public function isOutOfDate(inObj:String) - { - if (!FileSystem.exists(inObj)) - return true; - var obj_stamp = FileSystem.stat(inObj).mtime.getTime(); - if (mGroup.isOutOfDate(obj_stamp)) - return true; - - var source_name = mDir+mName; - if (!FileSystem.exists(source_name)) - throw "Could not find source '" + source_name + "'"; - var source_stamp = FileSystem.stat(source_name).mtime.getTime(); - if (obj_stamp < source_stamp) - return true; - for(depend in mDepends) - { - if (!FileSystem.exists(depend)) - throw "Could not find dependency '" + depend + "' for '" + mName + "'"; - if (FileSystem.stat(depend).mtime.getTime() > obj_stamp ) - return true; - } - return false; - } - static var mFileHashes = new Map(); - public var mName:String; - public var mDir:String; - public var mDependHash:String; - public var mDepends:Array; - public var mCompilerFlags:Array; - public var mGroup:FileGroup; -} - - -class HLSL -{ - var file:String; - var profile:String; - var target:String; - var variable:String; - - public function new(inFile:String, inProfile:String, inVariable:String, inTarget:String) - { - file = inFile; - profile = inProfile; - variable = inVariable; - target = inTarget; - } - - public function build() - { - if (!FileSystem.exists (Path.directory (target))) - { - DirManager.make(Path.directory (target)); - } - - DirManager.makeFileDir(target); - - var srcStamp = FileSystem.stat(file).mtime.getTime(); - if ( !FileSystem.exists(target) || FileSystem.stat(target).mtime.getTime() < srcStamp) - { - var exe = "fxc.exe"; - var args = [ "/nologo", "/T", profile, file, "/Vn", variable, "/Fh", target ]; - var result = BuildTool.runCommand(exe,args,BuildTool.verbose,false); - if (result!=0) - { - throw "Error : Could not compile shader " + file + " - build cancelled"; - } - } - } -} - - - -class FileGroup -{ - public function new(inDir:String,inId:String) - { - mNewest = 0; - mFiles = []; - mCompilerFlags = []; - mPrecompiledHeader = ""; - mDepends = []; - mMissingDepends = []; - mOptions = []; - mHLSLs = []; - mDir = inDir; - mId = inId; - } - - public function preBuild() - { - for(hlsl in mHLSLs) - hlsl.build(); - - if (BuildTool.useCache) - { - mDependHash = ""; - for(depend in mDepends) - mDependHash += File.getFileHash(depend); - mDependHash = haxe.crypto.Md5.encode(mDependHash); - } - } - - public function addHLSL(inFile:String,inProfile:String,inVariable:String,inTarget:String) - { - addDepend(inFile); - - mHLSLs.push( new HLSL(inFile,inProfile,inVariable,inTarget) ); - } - - - public function addDepend(inFile:String) - { - if (!FileSystem.exists(inFile)) - { - mMissingDepends.push(inFile); - return; - } - var stamp = FileSystem.stat(inFile).mtime.getTime(); - if (stamp>mNewest) - mNewest = stamp; - - mDepends.push(inFile); - } - - - public function addOptions(inFile:String) - { - mOptions.push(inFile); - } - - public function getPchDir() - { - return "__pch/" + mId ; - } - - public function checkOptions(inObjDir:String) - { - var changed = false; - for(option in mOptions) - { - if (!FileSystem.exists(option)) - { - mMissingDepends.push(option); - } - else - { - var contents = sys.io.File.getContent(option); - - var dest = inObjDir + "/" + haxe.io.Path.withoutDirectory(option); - var skip = false; - - if (FileSystem.exists(dest)) - { - var dest_content = sys.io.File.getContent(dest); - if (dest_content==contents) - skip = true; - } - if (!skip) - { - DirManager.make(inObjDir); - var stream = sys.io.File.write(dest,true); - stream.writeString(contents); - stream.close(); - changed = true; - } - addDepend(dest); - } - } - return changed; - } - - public function checkDependsExist() - { - if (mMissingDepends.length>0) - throw "Could not find dependencies: " + mMissingDepends.join(","); - } - - public function addCompilerFlag(inFlag:String) - { - mCompilerFlags.push(inFlag); - } - - public function isOutOfDate(inStamp:Float) - { - return inStamp; - public var mMissingDepends:Array; - public var mOptions:Array; - public var mPrecompiledHeader:String; - public var mPrecompiledHeaderDir:String; - public var mFiles: Array; - public var mHLSLs: Array; - public var mDir : String; - public var mId : String; - public var mDepends:Array; - public var mDependHash : String; -} - #if haxe3 typedef Hash = haxe.ds.StringMap; #end - typedef FileGroups = Hash; - -class Target -{ - public function new(inOutput:String, inTool:String,inToolID:String) - { - mOutput = inOutput; - mOutputDir = ""; - mBuildDir = ""; - mToolID = inToolID; - mTool = inTool; - mFiles = []; - mDepends = []; - mLibs = []; - mFlags = []; - mExt = ""; - mSubTargets = []; - mFileGroups = []; - mFlags = []; - mErrors=[]; - mDirs=[]; - } - - public function addFiles(inGroup:FileGroup) - { - mFiles = mFiles.concat(inGroup.mFiles); - mFileGroups.push(inGroup); - } - public function addError(inError:String) - { - mErrors.push(inError); - } - public function checkError() - { - if (mErrors.length>0) - throw mErrors.join("/"); - } - public function clean() - { - for(dir in mDirs) - { - BuildTool.println("Remove " + dir + "..."); - DirManager.deleteRecurse(dir); - } - } - - public function getKey() - { - return mOutput + mExt; - } - - public var mBuildDir:String; - public var mOutput:String; - public var mOutputDir:String; - public var mTool:String; - public var mToolID:String; - public var mFiles:Array; - public var mFileGroups:Array; - public var mDepends:Array; - public var mSubTargets:Array; - public var mLibs:Array; - public var mFlags:Array; - public var mErrors:Array; - public var mDirs:Array; - public var mExt:String; -} - typedef Targets = Hash; typedef Linkers = Hash; class BuildTool { - var mDefines : Hash; + var mDefines:Hash; var mIncludePath:Array; - var mCompiler : Compiler; - var mStripper : Stripper; - var mLinkers : Linkers; - var mFileGroups : FileGroups; - var mTargets : Targets; + var mCompiler:Compiler; + var mStripper:Stripper; + var mLinkers:Linkers; + var mFileGroups:FileGroups; + var mTargets:Targets; public static var sAllowNumProcs = true; public static var HXCPP = ""; - public static var verbose = false; + public static var is64 = false; public static var isWindows = false; public static var isLinux = false; public static var isMac = false; public static var useCache = false; public static var compileCache:String; public static var targetKey:String; - public static var helperThread = new Tls(); public static var instance:BuildTool; - static var printMutex:Mutex; - + public static var helperThread = new Tls(); + public static var printMutex:Mutex; + static var mVarMatch = new EReg("\\${(.*?)}",""); public function new(inMakefile:String,inDefines:Hash,inTargets:Array, inIncludePath:Array ) @@ -949,18 +55,19 @@ class BuildTool mIncludePath = inIncludePath; instance = this; var make_contents = ""; - try { + try { make_contents = sys.io.File.getContent(inMakefile); } catch (e:Dynamic) { - println("Could not open build file '" + inMakefile + "'"); - Sys.exit(1); + LogManager.error("Could not open build file \"" + inMakefile + "\""); + //println("Could not open build file '" + inMakefile + "'"); + //Sys.exit(1); } if (!mDefines.exists("HXCPP_COMPILE_THREADS")) mDefines.set("HXCPP_COMPILE_THREADS", Std.string(getNumberOfProcesses())); var xml_slow = Xml.parse(make_contents); - var xml = new haxe.xml.Fast(xml_slow.firstElement()); + var xml = new Fast(xml_slow.firstElement()); parseXML(xml,""); @@ -980,22 +87,25 @@ class BuildTool if (FileSystem.exists(compileCache) && FileSystem.isDirectory(compileCache)) { - useCache = true; + useCache = true; } else - throw "Could not find compiler cache: " + compileCache; - + { + LogManager.error("Could not find compiler cache \"" + compileCache + "\""); + //throw "Could not find compiler cache: " + compileCache; + } } if (useCache && (!mDefines.exists("haxe_ver") && !mDefines.exists("HXCPP_DEPENDS_OK"))) { - if (verbose) - println("ignoring cache because of possible missing dependencies"); + LogManager.info("", "Ignoring compiler cache because of possible missing dependencies"); useCache = false; } - if (useCache && verbose) - println("Using cache " + compileCache ); + if (useCache) + { + LogManager.info("", "Using compiler cache \"" + compileCache + "\""); + } if (inTargets.remove("clear")) for(target in mTargets.keys()) @@ -1009,275 +119,19 @@ class BuildTool buildTarget(target); } - public static function isMsvc() - { - return instance.mDefines.get("toolchain")=="msvc"; - } - static public function getMsvcVer() - { - return instance.mDefines.get("MSVC_VER"); - } - - inline public static function log(s:String) - { - if (verbose) - Sys.println(s); - } - - - - inline public static function println(s:String) - { - Sys.println(s); - } - - - function findIncludeFile(inBase:String) : String - { - if (inBase=="") return ""; - var c0 = inBase.substr(0,1); - if (c0!="/" && c0!="\\") - { - var c1 = inBase.substr(1,1); - if (c1!=":") - { - for(p in mIncludePath) - { - var name = p + "/" + inBase; - if (FileSystem.exists(name)) - return name; - } - return ""; - } - } - if (FileSystem.exists(inBase)) - return inBase; - return ""; - } - - function parseXML(inXML:haxe.xml.Fast,inSection :String) - { - for(el in inXML.elements) - { - if (valid(el,inSection)) - { - switch(el.name) - { - case "set" : - var name = el.att.name; - var value = substitute(el.att.value); - mDefines.set(name,value); - if (name == "BLACKBERRY_NDK_ROOT") - { - Setup.setupBlackBerryNativeSDK(mDefines); - } - case "unset" : - var name = el.att.name; - mDefines.remove(name); - case "setup" : - var name = substitute(el.att.name); - Setup.setup(name,mDefines); - case "echo" : - Sys.println(substitute(el.att.value)); - case "setenv" : - var name = 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); - throw(error); - case "path" : - var path = substitute(el.att.name); - if (verbose) - println("Adding path " + path ); - var os = Sys.systemName(); - 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 "linker" : - if (mLinkers.exists(el.att.id)) - createLinker(el,mLinkers.get(el.att.id)); - else - mLinkers.set( el.att.id, createLinker(el,null) ); - - case "files" : - var name = el.att.id; - if (mFileGroups.exists(name)) - createFileGroup(el, mFileGroups.get(name), name); - else - mFileGroups.set(name,createFileGroup(el,null,name)); - - case "include" : - var name = substitute(el.att.name); - var full_name = findIncludeFile(name); - if (full_name!="") - { - var make_contents = sys.io.File.getContent(full_name); - var xml_slow = Xml.parse(make_contents); - var section = el.has.section ? el.att.section : ""; - - parseXML(new haxe.xml.Fast(xml_slow.firstElement()),section); - } - else if (!el.has.noerror) - { - throw "Could not find include file " + name; - } - 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)); - else - mTargets.set( name, createTarget(el,null) ); - case "section" : - parseXML(el,""); - } - } - } - } - - - public static function runCommand(exe:String, args:Array,inPrint:Bool, inMultiThread:Bool ):Int - { - if (exe.indexOf (" ") > -1) - { - var splitExe = exe.split (" "); - exe = splitExe.shift (); - args = splitExe.concat (args); - } - - var useSysCommand = !inMultiThread; - - if ( useSysCommand ) - { - if (inPrint) - println(exe + " " + args.join(" ")); - return Sys.command(exe,args); - } - else - { - var output = new Array(); - if (inPrint) - output.push(exe + " " + args.join(" ")); - var proc = new sys.io.Process(exe, args); - var err = proc.stderr; - var out = proc.stdout; - var reader = BuildTool.helperThread.value; - // Read stderr in separate hreead to avoid blocking ... - if (reader==null) - { - var contoller = Thread.current(); - BuildTool.helperThread.value = reader = Thread.create(function() - { - while(true) - { - var stream = Thread.readMessage(true); - var output:Array = null; - try - { - while(true) - { - var line = stream.readLine(); - if (output==null) - output = [ line ]; - else - output.push(line); - } - } - catch(e:Dynamic){ } - contoller.sendMessage(output); - } - }); - } - - // Start up the error reader ... - reader.sendMessage(err); - - try - { - while(true) - { - var line = out.readLine(); - output.push(line); - } - } - catch(e:Dynamic){ } - - var errOut:Array = Thread.readMessage(true); - - if (errOut!=null && errOut.length>0) - output = output.concat(errOut); - - if (output.length>0) - { - if (printMutex!=null) - printMutex.acquire(); - println(output.join("\n")); - if (printMutex!=null) - printMutex.release(); - } - - var code = proc.exitCode(); - proc.close(); - return code; - } - } - - public function cleanTarget(inTarget:String,allObj:Bool) + public function buildTarget(inTarget:String) { // Sys.println("Build : " + inTarget ); if (!mTargets.exists(inTarget)) - throw "Could not find target '" + inTarget + "' to build."; - if (mCompiler==null) - 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(); - if (verbose) - Sys.println("Enter " + target.mBuildDir); - Sys.setCwd(target.mBuildDir); + LogManager.error ("Could not find build target \"" + inTarget + "\""); + //throw "Could not find target '" + inTarget + "' to build."; } - - DirManager.deleteRecurse(mCompiler.mObjDir); - DirManager.deleteFile("all_objs"); - DirManager.deleteExtension(".pdb"); - if (allObj) - DirManager.deleteRecurse("obj"); - - if (restoreDir!="") - Sys.setCwd(restoreDir); - } - - - - - public function buildTarget(inTarget:String) - { - // Sys.println("Build : " + inTarget ); - if (!mTargets.exists(inTarget)) - throw "Could not find target '" + inTarget + "' to build."; if (mCompiler==null) - throw "No compiler defined"; + { + LogManager.error("No compiler defined for the current build target"); + //throw "No compiler defined"; + } var target = mTargets.get(inTarget); target.checkError(); @@ -1292,20 +146,24 @@ class BuildTool { var thread_var = mDefines.exists("HXCPP_COMPILE_THREADS") ? mDefines.get("HXCPP_COMPILE_THREADS") : Sys.getEnv("HXCPP_COMPILE_THREADS"); - - if (thread_var==null) - thread_var = getNumberOfProcesses(); - threads = (thread_var==null || Std.parseInt(thread_var)<2) ? 1 : - Std.parseInt(thread_var); + + if (thread_var == null) + { + threads = getNumberOfProcesses(); + } + else + { + threads = (Std.parseInt(thread_var)<2) ? 1 : Std.parseInt(thread_var); + } } - DirManager.reset(); + PathManager.resetDirectoryCache(); var restoreDir = ""; if (target.mBuildDir!="") { restoreDir = Sys.getCwd(); - if (verbose) - Sys.println("Enter " + target.mBuildDir); + Sys.println(target.mBuildDir); + LogManager.info("", "\x1b[1mChanging directory:\x1b[0m " + target.mBuildDir); Sys.setCwd(target.mBuildDir); } @@ -1314,7 +172,7 @@ class BuildTool var objs = new Array(); if (target.mFileGroups.length > 0) - DirManager.make(mCompiler.mObjDir); + PathManager.mkdir(mCompiler.mObjDir); for(group in target.mFileGroups) { group.checkOptions(mCompiler.mObjDir); @@ -1348,9 +206,9 @@ class BuildTool { var pchDir = group.getPchDir(); if (pchDir != "") - { + { objs.push(mCompiler.mObjDir + "/" + pchDir + "/" + group.getPchName() + mCompiler.mExt); - } + } } } @@ -1396,9 +254,13 @@ class BuildTool // Wait for theads to finish... for(t in 0...threads) { - var result = Thread.readMessage(true); - if (result=="Error") - throw "Error in building thread"; + var result = Thread.readMessage(true); + if (result=="Error") + { + // Already printed the error from the thread, just need to exit + Sys.exit (1); + //throw "Error in building thread"; + } } } } @@ -1407,7 +269,10 @@ class BuildTool { case "linker": if (!mLinkers.exists(target.mToolID)) - throw "Missing linker :\"" + target.mToolID + "\""; + { + LogManager.error ("Could not find linker for \"" + target.mToolID + "\""); + //throw "Missing linker :\"" + target.mToolID + "\""; + } var exe = mLinkers.get(target.mToolID).link(target,objs, mCompiler); if (exe!="" && mStripper!=null) @@ -1419,12 +284,50 @@ class BuildTool Sys.setCwd(restoreDir); } - public function createCompiler(inXML:haxe.xml.Fast,inBase:Compiler) : Compiler + public function cleanTarget(inTarget:String,allObj:Bool) + { + // Sys.println("Build : " + inTarget ); + if (!mTargets.exists(inTarget)) + { + LogManager.error("Could not find build target \"" + inTarget + "\""); + //throw "Could not find target '" + inTarget + "' to build."; + } + if (mCompiler==null) + { + LogManager.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(); + LogManager.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:Fast,inBase:Compiler) : Compiler { var c = inBase; if (inBase==null || inXML.has.replace) { - c = new Compiler(inXML.att.id,inXML.att.exe,mDefines.exists("USE_GCC_FILETYPES")); + c = new Compiler(substitute(inXML.att.id),substitute(inXML.att.exe),mDefines.exists("USE_GCC_FILETYPES")); if (mDefines.exists("USE_PRECOMPILED_HEADERS")) c.setPCH(mDefines.get("USE_PRECOMPILED_HEADERS")); } @@ -1434,63 +337,76 @@ class BuildTool if (valid(el,"")) switch(el.name) { - case "flag" : c.mFlags.push(substitute(el.att.value)); - 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 "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 "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!="") - { - var make_contents = sys.io.File.getContent(full_name); - var xml_slow = Xml.parse(make_contents); - createCompiler(new haxe.xml.Fast(xml_slow.firstElement()),c); - } - else if (!el.has.noerror) - { - throw "Could not find include file " + name; - } + case "flag" : c.mFlags.push(substitute(el.att.value)); + 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 "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 "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!="") + { + var make_contents = sys.io.File.getContent(full_name); + var xml_slow = Xml.parse(make_contents); + createCompiler(new Fast(xml_slow.firstElement()),c); + } + else if (!el.has.noerror) + { + LogManager.error("Could not find include file \"" + name + "\""); + //throw "Could not find include file " + name; + } default: - throw "Unknown compiler option: '" + el.name + "'"; - - + LogManager.error("Unknown compiler option \"" + el.name + "\""); + //throw "Unknown compiler option: '" + el.name + "'"; } } return c; } - public function createStripper(inXML:haxe.xml.Fast,inBase:Stripper) : Stripper + public function createFileGroup(inXML:Fast,inFiles:FileGroup,inName:String):FileGroup { - var s = (inBase!=null && !inXML.has.replace) ? inBase : - new Stripper(inXML.att.exe); + var dir = inXML.has.dir ? substitute(inXML.att.dir) : "."; + var group = inFiles==null ? new FileGroup(dir,inName) : inFiles; 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)); + case "file" : + var file = new File(substitute(el.att.name),group); + for(f in el.elements) + if (valid(f,"") && f.name=="depend") + file.mDepends.push( substitute(f.att.name) ); + group.mFiles.push( file ); + case "section" : createFileGroup(el,group,inName); + case "depend" : group.addDepend( substitute(el.att.name) ); + 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 "compilerflag" : group.addCompilerFlag( 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) ); } } - return s; + return group; } - - - public function createLinker(inXML:haxe.xml.Fast,inBase:Linker) : Linker + public function createLinker(inXML:Fast,inBase:Linker):Linker { var l = (inBase!=null && !inXML.has.replace) ? inBase : new Linker(inXML.att.exe); for(el in inXML.elements) @@ -1498,57 +414,42 @@ class BuildTool 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" : l.mLibs.push( substitute(el.att.name) ); - case "prefix" : l.mNamePrefix = substitute(el.att.value); - case "ranlib" : l.mRanLib = (substitute(el.att.name)); - case "recreate" : l.mRecreate = (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" : createLinker(el,l); + 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" : l.mLibs.push( substitute(el.att.name) ); + case "prefix" : l.mNamePrefix = substitute(el.att.value); + case "ranlib" : l.mRanLib = (substitute(el.att.name)); + case "recreate" : l.mRecreate = (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" : createLinker(el,l); } } return l; } - public function createFileGroup(inXML:haxe.xml.Fast,inFiles:FileGroup,inName:String) : FileGroup + public function createStripper(inXML:Fast,inBase:Stripper):Stripper { - var dir = inXML.has.dir ? substitute(inXML.att.dir) : "."; - var group = inFiles==null ? new FileGroup(dir,inName) : inFiles; + var s = (inBase!=null && !inXML.has.replace) ? inBase : + new Stripper(inXML.att.exe); for(el in inXML.elements) { if (valid(el,"")) switch(el.name) { - case "file" : - var file = new File(substitute(el.att.name),group); - for(f in el.elements) - if (valid(f,"") && f.name=="depend") - file.mDepends.push( substitute(f.att.name) ); - group.mFiles.push( file ); - case "section" : createFileGroup(el,group,inName); - case "depend" : group.addDepend( substitute(el.att.name) ); - 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 "compilerflag" : group.addCompilerFlag( 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 "flag" : s.mFlags.push(substitute(el.att.value)); + case "exe" : s.mExe = substitute((el.att.name)); } } - return group; + return s; } - - public function createTarget(inXML:haxe.xml.Fast,?inTarget:Target) : Target + public function createTarget(inXML:Fast,?inTarget:Target) : Target { var target:Target = inTarget; if (target==null) @@ -1564,159 +465,146 @@ class BuildTool if (valid(el,"")) switch(el.name) { - case "target" : target.mSubTargets.push( substitute(el.att.id) ); - case "lib" : target.mLibs.push( substitute(el.att.name) ); - 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.mExt = (substitute(el.att.value)); - case "builddir" : target.mBuildDir = 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) ); - case "section" : createTarget(el,target); + case "target" : target.mSubTargets.push( substitute(el.att.id) ); + case "lib" : target.mLibs.push( substitute(el.att.name) ); + 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.mExt = (substitute(el.att.value)); + case "builddir" : target.mBuildDir = 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) ); + case "section" : createTarget(el,target); } } return target; } - - public function valid(inEl:haxe.xml.Fast,inSection:String) : Bool - { - if (inEl.x.get("if")!=null) - if (!defined(inEl.x.get("if"))) return false; - - if (inEl.has.unless) - if (defined(inEl.att.unless)) return false; - - 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; - } - - public function defined(inString:String) : Bool + public function defined(inString:String):Bool { return mDefines.exists(inString); } - public static function getHaxelib(library:String):String + function findIncludeFile(inBase:String):String { - var proc = new sys.io.Process("haxelib",["path",library]); - var result = ""; - try + if (inBase == null || inBase=="") return ""; + var c0 = inBase.substr(0,1); + if (c0!="/" && c0!="\\") { - while(true) + var c1 = inBase.substr(1,1); + if (c1!=":") { - var line = proc.stdout.readLine(); - if (line.substr(0,1) != "-") + for(p in mIncludePath) { - result = line; - break; + var name = PathManager.combine(p, inBase); + if (FileSystem.exists(name)) + return name; } + return ""; } - - } catch (e:Dynamic) { }; - - proc.close(); - - if (result == "") - throw ("Could not find haxelib path " + library + " required by a source file."); - - return result; + } + if (FileSystem.exists(inBase)) + return inBase; + return ""; } - // Setting HXCPP_COMPILE_THREADS to 2x number or cores can help with hyperthreading - public static function getNumberOfProcesses():String + private static function getIs64():Bool { - var env = Sys.getEnv("NUMBER_OF_PROCESSORS"); - if (env!=null) - return env; - - var result = null; - if (isLinux) + if (isWindows) { - var proc = null; - proc = new sys.io.Process("nproc",[]); - try + var architecture = Sys.getEnv ("PROCESSOR_ARCHITEW6432"); + if (architecture != null && architecture.indexOf ("64") > -1) { - result = proc.stdout.readLine(); - proc.close (); - } catch (e:Dynamic) {} - } - else if (isMac) - { - var proc = new sys.io.Process("/usr/sbin/system_profiler", ["-detailLevel", "full", "SPHardwareDataType"]); - var cores = ~/Total Number of Cores: (\d+)/; - try + return true; + } + else { - while(true) - { - var line = proc.stdout.readLine(); - if (cores.match(line)) - { - result = cores.matched(1); - break; - } - } - } catch (e:Dynamic) {} - if (proc!=null) - proc.close(); + return false; + } } - return result; - } - - static var mVarMatch = new EReg("\\${(.*?)}",""); - public function substitute(str:String) : String - { - while( mVarMatch.match(str) ) + else { - var sub = mVarMatch.matched(1); - if (sub.substr(0,8)=="haxelib:") + 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("64") > -1) { - sub = getHaxelib(sub.substr(8)); + return true; } else - sub = mDefines.get(sub); - - if (sub==null) sub=""; - str = mVarMatch.matchedLeft() + sub + mVarMatch.matchedRight(); + { + return false; + } } + } - return str; + static public function getMsvcVer() + { + return instance.mDefines.get("MSVC_VER"); } - static function set64(outDefines:Hash, in64:Bool) + // Setting HXCPP_COMPILE_THREADS to 2x number or cores can help with hyperthreading + public static function getNumberOfProcesses():Int { - if (in64) + var result = null; + if (isWindows) { - outDefines.set("HXCPP_M64","1"); - outDefines.remove("HXCPP_32"); + var env = Sys.getEnv("NUMBER_OF_PROCESSORS"); + if (env != null) + { + result = env; + } } - else + else if (isLinux) { - outDefines.set("HXCPP_M32","1"); - outDefines.remove("HXCPP_M64"); + result = ProcessManager.runProcess("", "nproc", []); + if (result == null) + { + var cpuinfo = ProcessManager.runProcess("", "cat", [ "/proc/cpuinfo" ]); + 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); + if (cores.match(output)) + { + result = cores.matched(1); + } + } + + if (result == null || Std.parseInt(result) < 1) + { + return 1; + } + else + { + return Std.parseInt(result); } } - - + + public static function isMsvc() + { + return instance.mDefines.get("toolchain")=="msvc"; + } + // Process args and environment. static public function main() { @@ -1730,12 +618,12 @@ class BuildTool var args = Sys.args(); var env = Sys.environment(); - verbose = env.exists("HXCPP_VERBOSE"); + LogManager.verbose = env.exists("HXCPP_VERBOSE"); // Check for calling from haxelib ... if (args.length>0) { - var last:String = (new haxe.io.Path(args[args.length-1])).toString(); + var last:String = (new Path(args[args.length-1])).toString(); var slash = last.substr(-1); if (slash=="/"|| slash=="\\") last = last.substr(0,last.length-1); @@ -1743,7 +631,7 @@ class BuildTool { // When called from haxelib, the last arg is the original directory, and // the current direcory is the library directory. - HXCPP = Sys.getCwd(); + HXCPP = PathManager.standardize(Sys.getCwd()); defines.set("HXCPP",HXCPP); args.pop(); Sys.setCwd(last); @@ -1751,18 +639,18 @@ class BuildTool } var os = Sys.systemName(); isWindows = (new EReg("window","i")).match(os); - if (isWindows) - defines.set("windows_host", "1"); + if (isWindows) + defines.set("windows_host", "1"); isMac = (new EReg("mac","i")).match(os); - if (isMac) - defines.set("mac_host", "1"); + if (isMac) + defines.set("mac_host", "1"); isLinux = (new EReg("linux","i")).match(os); - if (isLinux) - defines.set("linux_host", "1"); + if (isLinux) + defines.set("linux_host", "1"); var isRPi = isLinux && Setup.isRaspberryPi(); - - + is64 = getIs64(); + for(arg in args) { if (arg.substr(0,2)=="-D") @@ -1774,12 +662,12 @@ class BuildTool else defines.set(val,""); if (val=="verbose") - verbose = true; + LogManager.verbose = true; } else if (arg=="-v" || arg=="-verbose") - verbose = true; + LogManager.verbose = true; else if (arg.substr(0,2)=="-I") - include_path.push(arg.substr(2)); + include_path.push(PathManager.standardize(arg.substr(2))); else if (makefile.length==0) makefile = arg; else @@ -1790,22 +678,23 @@ class BuildTool if (HXCPP=="" && env.exists("HXCPP")) { - HXCPP = env.get("HXCPP") + "/"; + HXCPP = PathManager.standardize(env.get("HXCPP")); defines.set("HXCPP",HXCPP); } if (HXCPP=="") { if (!defines.exists("HXCPP")) - throw "HXCPP not set, and not run from haxelib"; - HXCPP = defines.get("HXCPP") + "/"; + { + LogManager.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); } - - if (verbose) - BuildTool.println("HXCPP : " + HXCPP); - - + + LogManager.info("", "HXCPP : " + HXCPP); + include_path.push("."); if (env.exists("HOME")) include_path.push(env.get("HOME")); @@ -1824,22 +713,31 @@ class BuildTool } var msvc = false; - - if (defines.exists("ios")) - { - if (defines.exists("simulator")) - { - defines.set("iphonesim", "iphonesim"); - } - else if (!defines.exists ("iphonesim")) - { - defines.set("iphoneos", "iphoneos"); - } - } + + if (defines.exists ("toolchain")) + { + if (!defines.exists ("BINDIR")) + { + defines.set ("BINDIR", Path.withoutDirectory(Path.withoutExtension(defines.get ("toolchain")))); + } + } + + 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("iphoneos")) { - defines.set("toolchain","iphoneos"); + defines.set("toolchain","iphoneos"); defines.set("iphone","iphone"); defines.set("apple","apple"); defines.set("BINDIR","iPhone"); @@ -1866,7 +764,10 @@ class BuildTool else if ( (new EReg("linux","i")).match(os) ) defines.set("ANDROID_HOST","linux-x86"); else - throw "Unknown android host:" + os; + { + LogManager.error ("Unknown android host \"" + os + "\""); + //throw "Unknown android host:" + os; + } } } else if (defines.exists("webos")) @@ -1888,26 +789,26 @@ class BuildTool defines.set("tizen","tizen"); defines.set("BINDIR","Tizen"); } - else if (defines.exists("blackberry")) + else if (defines.exists("blackberry")) { - if (defines.exists("simulator")) - { - defines.set("toolchain", "blackberry-x86"); - } - else - { - defines.set("toolchain", "blackberry"); - } + if (defines.exists("simulator")) + { + defines.set("toolchain", "blackberry-x86"); + } + else + { + defines.set("toolchain", "blackberry"); + } defines.set("blackberry","blackberry"); defines.set("BINDIR","BlackBerry"); } - else if (defines.exists("emcc") || defines.exists("emscripten")) - { + else if (defines.exists("emcc") || defines.exists("emscripten")) + { defines.set("toolchain","emscripten"); - defines.set("emcc","emcc"); - defines.set("emscripten","emscripten"); - defines.set("BINDIR","Emscripten"); - } + defines.set("emcc","emcc"); + defines.set("emscripten","emscripten"); + defines.set("BINDIR","Emscripten"); + } else if (defines.exists("gph")) { defines.set("toolchain","gph"); @@ -1956,7 +857,7 @@ class BuildTool { defines.set("BINDIR",m64 ? "Windows64":"Windows"); } - } + } } else if ( isRPi ) { @@ -1996,24 +897,21 @@ class BuildTool if (defines.exists("dll_import")) { - var path = new haxe.io.Path(defines.get("dll_import")); + var path = new Path(defines.get("dll_import")); if (!defines.exists("dll_import_include")) defines.set("dll_import_include", path.dir + "/include" ); if (!defines.exists("dll_import_link")) defines.set("dll_import_link", defines.get("dll_import") ); } - if (defines.exists("apple") && !defines.exists("DEVELOPER_DIR")) { - var proc = new sys.io.Process("xcode-select", ["--print-path"]); - var developer_dir = proc.stdout.readLine(); - proc.close(); - if (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); + var developer_dir = ProcessManager.runProcess("", "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")) @@ -2070,7 +968,7 @@ class BuildTool if (makefile=="") { - Sys.println("Usage : BuildTool makefile.xml [-DFLAG1] ... [-DFLAGN] ... [target1]...[targetN]"); + LogManager.info("Usage : BuildTool makefile.xml [-DFLAG1] ... [-DFLAGN] ... [target1]...[targetN]"); } else { @@ -2080,5 +978,201 @@ class BuildTool new BuildTool(makefile,defines,targets,include_path); } } - -} + + function parseXML(inXML:Fast,inSection:String) + { + for(el in inXML.elements) + { + if (valid(el,inSection)) + { + switch(el.name) + { + case "set" : + var name = el.att.name; + var value = substitute(el.att.value); + mDefines.set(name,value); + if (name == "BLACKBERRY_NDK_ROOT") + { + Setup.setupBlackBerryNativeSDK(mDefines); + } + case "unset" : + var name = el.att.name; + mDefines.remove(name); + case "setup" : + var name = substitute(el.att.name); + Setup.setup(name,mDefines); + case "echo" : + LogManager.info(substitute(el.att.value)); + case "setenv" : + var name = 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); + throw(error); + case "path" : + var path = substitute(el.att.name); + LogManager.info("", "Adding path " + path); + var os = Sys.systemName(); + 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 "linker" : + if (mLinkers.exists(el.att.id)) + createLinker(el,mLinkers.get(el.att.id)); + else + mLinkers.set( el.att.id, createLinker(el,null) ); + case "files" : + var name = el.att.id; + if (mFileGroups.exists(name)) + createFileGroup(el, mFileGroups.get(name), name); + else + mFileGroups.set(name,createFileGroup(el,null,name)); + case "include" : + var name = substitute(el.att.name); + var full_name = findIncludeFile(name); + if (full_name!="") + { + var make_contents = sys.io.File.getContent(full_name); + var xml_slow = Xml.parse(make_contents); + var section = el.has.section ? el.att.section : ""; + + parseXML(new Fast(xml_slow.firstElement()),section); + } + else if (!el.has.noerror) + { + LogManager.error("Could not find include file \"" + name + "\""); + //throw "Could not find include file " + name; + } + 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)); + else + mTargets.set( name, createTarget(el,null) ); + case "section" : + parseXML(el,""); + } + } + } + } + + static function set64(outDefines:Hash, in64:Bool) + { + if (in64) + { + outDefines.set("HXCPP_M64","1"); + outDefines.remove("HXCPP_32"); + } + else + { + outDefines.set("HXCPP_M32","1"); + outDefines.remove("HXCPP_M64"); + } + } + + public function substitute(str:String):String + { + while( mVarMatch.match(str) ) + { + var sub = mVarMatch.matched(1); + if (sub.substr(0,8)=="haxelib:") + { + sub = PathManager.getHaxelib(sub.substr(8)); + sub = PathManager.standardize(sub); + } + else + sub = mDefines.get(sub); + + if (sub==null) sub=""; + str = mVarMatch.matchedLeft() + sub + mVarMatch.matchedRight(); + } + + return str; + } + + public function valid(inEl:Fast,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.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; + } +} \ No newline at end of file diff --git a/tools/run/Compiler.hx b/tools/run/Compiler.hx new file mode 100644 index 000000000..b8bd23a18 --- /dev/null +++ b/tools/run/Compiler.hx @@ -0,0 +1,278 @@ +import haxe.crypto.Md5; +import haxe.io.Path; +import sys.FileSystem; + +class Compiler +{ + public var mFlags:Array; + public var mCFlags:Array; + public var mMMFlags:Array; + public var mCPPFlags:Array; + public var mOBJCFlags:Array; + public var mPCHFlags:Array; + public var mAddGCCIdentity:Bool; + public var mExe:String; + public var mOutFlag:String; + public var mObjDir:String; + public var mExt:String; + + public var mPCHExt:String; + public var mPCHCreate:String; + public var mPCHUse:String; + public var mPCHFilename:String; + public var mPCH:String; + + public var mGetCompilerVersion:String; + public var mCompilerVersion:String; + public var mCached:Bool; + + public var mID:String; + + public function new(inID,inExe:String,inGCCFileTypes:Bool) + { + mFlags = []; + mCFlags = []; + mCPPFlags = []; + mOBJCFlags = []; + mMMFlags = []; + mPCHFlags = []; + mAddGCCIdentity = inGCCFileTypes; + mCompilerVersion = null; + mObjDir = "obj"; + mOutFlag = "-o"; + mExe = inExe; + mID = inID; + mExt = ".o"; + mPCHExt = ".pch"; + mPCHCreate = "-Yc"; + mPCHUse = "-Yu"; + mPCHFilename = "/Fp"; + mCached = false; + } + + function addIdentity(ext:String,ioArgs:Array) + { + if (mAddGCCIdentity) + { + var identity = switch(ext) + { + case "c" : "c"; + case "m" : "objective-c"; + case "mm" : "objective-c++"; + case "cpp" : "c++"; + case "c++" : "c++"; + default:""; + } + if (identity!="") + { + ioArgs.push("-x"); + ioArgs.push(identity); + } + } + } + + public function compile(inFile:File,inTid:Int) + { + var obj_name = getObjName(inFile); + var args = new Array(); + + args = args.concat(inFile.mCompilerFlags).concat(inFile.mGroup.mCompilerFlags).concat(mFlags); + + var ext = mExt.toLowerCase(); + addIdentity(ext,args); + + var allowPch = false; + if (ext=="c") + args = args.concat(mCFlags); + else if (ext=="m") + args = args.concat(mOBJCFlags); + else if (ext=="mm") + args = args.concat(mMMFlags); + else if (ext=="cpp" || ext=="c++") + { + allowPch = true; + args = args.concat(mCPPFlags); + } + + if (!mCached && inFile.mGroup.mPrecompiledHeader!="" && allowPch) + { + var pchDir = inFile.mGroup.getPchDir(); + if (mPCHUse!="") + { + args.push(mPCHUse + inFile.mGroup.mPrecompiledHeader + ".h"); + args.push(mPCHFilename + mObjDir + "/" + pchDir + "/" + inFile.mGroup.getPchName() + mPCHExt); + } + else + args.unshift("-I"+mObjDir + "/" + pchDir); + } + + var found = false; + var cacheName:String = null; + if (mCompilerVersion!=null) + { + var sourceName = inFile.mDir + inFile.mName; + var contents = sys.io.File.getContent(sourceName); + if (contents!="") + { + var md5 = Md5.encode(contents + args.join(" ") + + inFile.mGroup.mDependHash + mCompilerVersion + inFile.mDependHash ); + cacheName = BuildTool.compileCache + "/" + md5; + if (FileSystem.exists(cacheName)) + { + sys.io.File.copy(cacheName, obj_name); + LogManager.info("use cache for " + obj_name + "(" + md5 + ")" ); + found = true; + } + else + { + LogManager.info("", " not in cache " + cacheName); + } + } + else + throw "Unkown source contents " + sourceName; + } + + if (!found) + { + args.push( (new Path( inFile.mDir + inFile.mName)).toString() ); + + var out = mOutFlag; + if (out.substr(-1)==" ") + { + args.push(out.substr(0,out.length-1)); + out = ""; + } + + args.push(out + obj_name); + + var split = mExe.split (" "); + var exe = split.shift (); + args = split.concat (args); + + if (inTid >= 0) + { + ProcessManager.runProcessThreaded("", exe, args); + } + else + { + var result = ProcessManager.runCommand("", exe, args); + if (result!=0) + { + if (FileSystem.exists(obj_name)) + FileSystem.deleteFile(obj_name); + Sys.exit (result); + //throw "Error : " + result + " - build cancelled"; + } + } + + if (cacheName!=null) + { + sys.io.File.copy(obj_name, cacheName); + LogManager.info("", " caching " + cacheName); + } + } + + return obj_name; + } + + public function createCompilerVersion(inGroup:FileGroup) + { + if (mGetCompilerVersion!=null && mCompilerVersion==null) + { + var exe = mGetCompilerVersion; + var args = new Array(); + if (exe.indexOf (" ") > -1) + { + var splitExe = exe.split(" "); + exe = splitExe.shift(); + args = splitExe.concat(args); + } + + var versionString = Setup.readStderr(exe,args).join(" "); + LogManager.info("", "--- Compiler version ---"); + LogManager.info("", versionString); + LogManager.info("", "------------------------"); + + mCompilerVersion = Md5.encode(versionString); + mCached = true; + } + + return mCached; + } + + public function getObjName(inFile:File) + { + var path = new Path(inFile.mName); + var dirId = Md5.encode(BuildTool.targetKey + path.dir).substr(0,8) + "_"; + + return mObjDir + "/" + dirId + path.file + mExt; + } + + public function needsPchObj() + { + return !mCached && mPCH!="gcc"; + } + + public function precompile(inObjDir:String,inGroup:FileGroup) + { + var header = inGroup.mPrecompiledHeader; + var file = inGroup.getPchName(); + + var args = inGroup.mCompilerFlags.concat(mFlags).concat( mCPPFlags ).concat( mPCHFlags ); + + var dir = inObjDir + "/" + inGroup.getPchDir() + "/"; + var pch_name = dir + file + mPCHExt; + + //LogManager.info("", "Make pch dir " + dir ); + PathManager.mkdir(dir); + + if (mPCH!="gcc") + { + args.push( mPCHCreate + header + ".h" ); + + // Create a temp file for including ... + var tmp_cpp = dir + file + ".cpp"; + var outFile = sys.io.File.write(tmp_cpp,false); + outFile.writeString("#include <" + header + ".h>\n"); + outFile.close(); + + args.push( tmp_cpp ); + args.push(mPCHFilename + pch_name); + args.push(mOutFlag + dir + file + mExt); + } + else + { + //LogManager.info("", "Creating PCH directory \"" + dir + header + "\""); + PathManager.mkdir(dir + header); + args.push( "-o" ); + args.push(pch_name); + args.push( inGroup.mPrecompiledHeaderDir + "/" + inGroup.mPrecompiledHeader + ".h" ); + } + + //LogManager.info("Creating " + pch_name + "..."); + + var split = mExe.split (" "); + var exe = split.shift (); + args = split.concat (args); + + var result = ProcessManager.runCommand("", exe, args); + if (result!=0) + { + if (FileSystem.exists(pch_name)) + FileSystem.deleteFile(pch_name); + LogManager.error("Could not create PCH"); + //throw "Error creating pch: " + result + " - build cancelled"; + } + } + + public function setPCH(inPCH:String) + { + mPCH = inPCH; + if (mPCH=="gcc") + { + mPCHExt = ".h.gch"; + mPCHUse = ""; + mPCHFilename = ""; + } + } +} \ No newline at end of file diff --git a/tools/run/DirManager.hx b/tools/run/DirManager.hx new file mode 100644 index 000000000..ca20a7a34 --- /dev/null +++ b/tools/run/DirManager.hx @@ -0,0 +1,97 @@ +import sys.FileSystem; +import BuildTool; + +class DirManager +{ + static var mMade = new Hash(); + + static public function deleteExtension(inExt:String) + { + var contents = FileSystem.readDirectory("."); + for(item in contents) + { + if (item.length > inExt.length && item.substr(item.length-inExt.length)==inExt) + deleteFile(item); + } + } + + static public function deleteFile(inName:String) + { + if (FileSystem.exists(inName)) + { + BuildTool.log("rm " + inName); + FileSystem.deleteFile(inName); + } + } + + static public function deleteRecurse(inDir:String) + { + if (FileSystem.exists(inDir)) + { + var contents = FileSystem.readDirectory(inDir); + for(item in contents) + { + if (item!="." && item!="..") + { + var name = inDir + "/" + item; + if (FileSystem.isDirectory(name)) + deleteRecurse(name); + else + { + BuildTool.log("rm " + name); + FileSystem.deleteFile(name); + } + } + } + BuildTool.log("rmdir " + inDir); + FileSystem.deleteDirectory(inDir); + } + } + + static public function make(inDir:String) + { + var parts = inDir.split("/"); + var total = ""; + for(part in parts) + { + if (part!="." && part!="") + { + if (total!="") total+="/"; + total += part; + if (!mMade.exists(total)) + { + mMade.set(total,true); + if (!FileSystem.exists(total)) + { + try + { + #if haxe3 + FileSystem.createDirectory(total + "/"); + #else + FileSystem.createDirectory(total ); + #end + } catch (e:Dynamic) + { + return false; + } + } + } + } + } + return true; + } + + static public function makeFileDir(inFile:String) + { + var parts = StringTools.replace (inFile, "\\", "/").split("/"); + if (parts.length<2) + return; + parts.pop(); + make(parts.join("/")); + } + + public static function reset() + { + mMade = new Hash(); + } +} \ No newline at end of file diff --git a/tools/run/File.hx b/tools/run/File.hx new file mode 100644 index 000000000..2a909368c --- /dev/null +++ b/tools/run/File.hx @@ -0,0 +1,72 @@ +import sys.FileSystem; + +class File +{ + static var mFileHashes = new Map(); + public var mName:String; + public var mDir:String; + public var mDependHash:String; + public var mDepends:Array; + public var mCompilerFlags:Array; + public var mGroup:FileGroup; + + public function new(inName:String, inGroup:FileGroup) + { + mName = inName; + mDir = inGroup.mDir; + if (mDir!="") mDir += "/"; + // Do not take copy - use reference so it can be updated + mGroup = inGroup; + mDepends = []; + mCompilerFlags = []; + } + + public function computeDependHash() + { + mDependHash = ""; + for(depend in mDepends) + mDependHash += getFileHash(depend); + mDependHash = haxe.crypto.Md5.encode(mDependHash); + } + + public static function getFileHash(inName:String) + { + if (mFileHashes.exists(inName)) + return mFileHashes.get(inName); + + var content = sys.io.File.getContent(inName); + var md5 = haxe.crypto.Md5.encode(content); + mFileHashes.set(inName,md5); + return md5; + } + + public function isOutOfDate(inObj:String) + { + if (!FileSystem.exists(inObj)) + return true; + var obj_stamp = FileSystem.stat(inObj).mtime.getTime(); + if (mGroup.isOutOfDate(obj_stamp)) + return true; + + var source_name = mDir+mName; + if (!FileSystem.exists(source_name)) + { + LogManager.error("Could not find source file \"" + source_name + "\""); + //throw "Could not find source '" + source_name + "'"; + } + var source_stamp = FileSystem.stat(source_name).mtime.getTime(); + if (obj_stamp < source_stamp) + return true; + for(depend in mDepends) + { + if (!FileSystem.exists(depend)) + { + LogManager.error("Could not find dependency \"" + depend + "\" for \"" + mName + "\""); + //throw "Could not find dependency '" + depend + "' for '" + mName + "'"; + } + if (FileSystem.stat(depend).mtime.getTime() > obj_stamp ) + return true; + } + return false; + } +} \ No newline at end of file diff --git a/tools/run/FileGroup.hx b/tools/run/FileGroup.hx new file mode 100644 index 000000000..67e80cce7 --- /dev/null +++ b/tools/run/FileGroup.hx @@ -0,0 +1,143 @@ +import haxe.io.Path; +import sys.FileSystem; + +class FileGroup +{ + public var mNewest:Float; + public var mCompilerFlags:Array; + public var mMissingDepends:Array; + public var mOptions:Array; + public var mPrecompiledHeader:String; + public var mPrecompiledHeaderDir:String; + public var mFiles:Array; + public var mHLSLs:Array; + public var mDir:String; + public var mId:String; + public var mDepends:Array; + public var mDependHash:String; + + public function new(inDir:String,inId:String) + { + mNewest = 0; + mFiles = []; + mCompilerFlags = []; + mPrecompiledHeader = ""; + mDepends = []; + mMissingDepends = []; + mOptions = []; + mHLSLs = []; + mDir = inDir; + mId = inId; + } + + public function addCompilerFlag(inFlag:String) + { + mCompilerFlags.push(inFlag); + } + + public function addDepend(inFile:String) + { + if (!FileSystem.exists(inFile)) + { + mMissingDepends.push(inFile); + return; + } + var stamp = FileSystem.stat(inFile).mtime.getTime(); + if (stamp>mNewest) + mNewest = stamp; + + mDepends.push(inFile); + } + + public function addHLSL(inFile:String,inProfile:String,inVariable:String,inTarget:String) + { + addDepend(inFile); + + mHLSLs.push( new HLSL(inFile,inProfile,inVariable,inTarget) ); + } + + public function addOptions(inFile:String) + { + mOptions.push(inFile); + } + + public function checkDependsExist() + { + if (mMissingDepends.length>0) + { + LogManager.error("Could not find dependencies: [ " + mMissingDepends.join (", ") + " ]"); + //throw "Could not find dependencies: " + mMissingDepends.join(","); + } + } + + public function checkOptions(inObjDir:String) + { + var changed = false; + for(option in mOptions) + { + if (!FileSystem.exists(option)) + { + mMissingDepends.push(option); + } + else + { + var contents = sys.io.File.getContent(option); + + var dest = inObjDir + "/" + Path.withoutDirectory(option); + var skip = false; + + if (FileSystem.exists(dest)) + { + var dest_content = sys.io.File.getContent(dest); + if (dest_content==contents) + skip = true; + } + if (!skip) + { + PathManager.mkdir(inObjDir); + var stream = sys.io.File.write(dest,true); + stream.writeString(contents); + stream.close(); + changed = true; + } + addDepend(dest); + } + } + return changed; + } + + public function getPchDir() + { + return "__pch/" + mId ; + } + + public function getPchName() + { + return Path.withoutDirectory(mPrecompiledHeader); + } + + public function isOutOfDate(inStamp:Float) + { + return inStamp; + public var mOutFlag:String; + public var mExt:String; + public var mNamePrefix:String; + public var mLibDir:String; + public var mRanLib:String; + public var mFromFile:String; + public var mLibs:Array; + public var mExpandArchives:Bool; + public var mRecreate:Bool; + + public function new(inExe:String) + { + mFlags = []; + mOutFlag = "-o"; + mExe = inExe; + mNamePrefix = ""; + mLibDir = ""; + mRanLib = ""; + mExpandArchives = false; + // Default to on... + mFromFile = "@"; + mLibs = []; + mRecreate = false; + } + + function isOutOfDate(inName:String, inObjs:Array) + { + if (!FileSystem.exists(inName)) + return true; + var stamp = FileSystem.stat(inName).mtime.getTime(); + for(obj in inObjs) + { + if (!FileSystem.exists(obj)) + { + LogManager.error("Could not find \"" + obj + "\" required by \"" + inName + "\""); + //throw "Could not find " + obj + " required by " + inName; + } + var obj_stamp = FileSystem.stat(obj).mtime.getTime(); + if (obj_stamp > stamp) + return true; + } + return false; + } + + public function link(inTarget:Target,inObjs:Array,inCompiler:Compiler) + { + var ext = inTarget.mExt=="" ? mExt : inTarget.mExt; + var file_name = mNamePrefix + inTarget.mOutput + ext; + + try + { + PathManager.mkdir(inTarget.mOutputDir); + } + catch (e:Dynamic) + { + LogManager.error("Unable to create output directory \"" + inTarget.mOutputDir + "\""); + //throw "Unable to create output directory " + inTarget.mOutputDir; + } + + var out_name = inTarget.mOutputDir + file_name; + + var libs = inTarget.mLibs.concat(mLibs); + var v18Added = false; + var isOutOfDateLibs = false; + + for(i in 0...libs.length) + { + var lib = libs[i]; + var parts = lib.split("{MSVC_VER}"); + if (parts.length==2) + { + var ver = ""; + if (BuildTool.isMsvc()) + { + var current = parts[0] + "-" + BuildTool.getMsvcVer() + parts[1]; + if (FileSystem.exists(current)) + { + LogManager.info("", "Using current compiler library " + current); + libs[i]=current; + } + else + { + var v18 = parts[0] + "-18" + parts[1]; + if (FileSystem.exists(v18)) + { + LogManager.info("", "Using msvc18 compatible library " + v18); + libs[i]=v18; + if (!v18Added) + { + v18Added=true; + libs.push( BuildTool.HXCPP + "/lib/Windows/libmsvccompat-18.lib"); + } + } + else + { + throw "Could not find compatible library for " + lib + ", " + v18 + " does not exist"; + } + } + } + else + libs[i] = parts[0] + parts[1]; + } + if (!isOutOfDateLibs) + { + var lib = libs[i]; + if (FileSystem.exists(lib)) + isOutOfDateLibs = isOutOfDate(out_name,[lib]); + } + } + + if (isOutOfDateLibs || isOutOfDate(out_name,inObjs) || isOutOfDate(out_name,inTarget.mDepends)) + { + var args = new Array(); + var out = mOutFlag; + if (out.substr(-1)==" ") + { + args.push(out.substr(0,out.length-1)); + out = ""; + } + // Build in temp dir, and then move out so all the crap windows + // creates stays out of the way + if (mLibDir!="") + { + PathManager.mkdir(mLibDir); + args.push(out + mLibDir + "/" + file_name); + } + else + { + if (mRecreate && FileSystem.exists(out_name)) + { + LogManager.info(" clean " + out_name ); + FileSystem.deleteFile(out_name); + } + args.push(out + out_name); + } + + args = args.concat(mFlags).concat(inTarget.mFlags); + + var objs = inObjs.copy(); + + if (mExpandArchives) + { + var isArchive = ~/\.a$/; + var libArgs = new Array(); + for(lib in libs) + { + if (isArchive.match(lib)) + { + var libName = Path.withoutDirectory(lib); + var libObjs = Setup.readStdout(mExe, ["t", lib ]); + var objDir = inCompiler.mObjDir + "/" + libName; + PathManager.mkdir(objDir); + ProcessManager.runCommand (objDir, mExe, ["x", lib]); + for(obj in libObjs) + objs.push( objDir+"/"+obj ); + } + else + libArgs.push(lib); + } + libs = libArgs; + } + + // Place list of obj files in a file called "all_objs" + if (mFromFile=="@") + { + var fname = inCompiler.mObjDir + "/all_objs"; + var fout = sys.io.File.write(fname,false); + for(obj in objs) + fout.writeString(obj + "\n"); + fout.close(); + args.push("@" + fname ); + } + else + args = args.concat(objs); + + args = args.concat(libs); + + var split = mExe.split (" "); + var exe = split.shift (); + args = split.concat (args); + + var result = ProcessManager.runCommand("", exe, args); + if (result!=0) + { + Sys.exit(result); + //throw "Error : " + result + " - build cancelled"; + } + + if (mRanLib!="") + { + args = [out_name]; + var result = ProcessManager.runCommand("", mRanLib, args); + if (result!=0) + { + Sys.exit(result); + //throw "Error : " + result + " - build cancelled"; + } + } + + if (mLibDir!="") + { + sys.io.File.copy( mLibDir+"/"+file_name, out_name ); + FileSystem.deleteFile( mLibDir+"/"+file_name ); + } + return out_name; + } + + return ""; + } +} \ No newline at end of file diff --git a/tools/run/LogManager.hx b/tools/run/LogManager.hx new file mode 100644 index 000000000..e2e2b86b1 --- /dev/null +++ b/tools/run/LogManager.hx @@ -0,0 +1,123 @@ +import haxe.io.Bytes; +import sys.io.Process; +#if neko +import neko.Lib; +#else +import cpp.Lib; +#end + +class LogManager +{ + public static var mute:Bool; + public static var verbose:Bool = false; + + private static var colorCodes:EReg = ~/\x1b\[[^m]+m/g; + private static var colorSupported:Null; + private static var sentWarnings = new Map(); + + public static function error(message:String, verboseMessage:String = "", e:Dynamic = null):Void + { + if (message != "" && !mute) + { + var output; + if (verbose && verboseMessage != "") + { + output = "\x1b[31;1mError:\x1b[0m\x1b[1m " + verboseMessage + "\x1b[0m\n"; + } + else + { + output = "\x1b[31;1mError:\x1b[0m \x1b[1m" + message + "\x1b[0m\n"; + } + Sys.stderr().write(Bytes.ofString(stripColor(output))); + } + + if (verbose && e != null) + { + Lib.rethrow(e); + } + + Sys.exit(1); + } + + public static function info(message:String, verboseMessage:String = ""):Void + { + if (!mute) + { + if (verbose && verboseMessage != "") + { + println(verboseMessage); + } + else if (message != "") + { + println(message); + } + } + } + + public static function print(message:String):Void + { + Sys.print(stripColor(message)); + } + + public static function println(message:String):Void + { + Sys.println(stripColor(message)); + } + + private static function stripColor(output:String):String + { + if (colorSupported == null) + { + if (!BuildTool.isWindows) + { + var result = -1; + try + { + var process = new Process ("tput", [ "colors" ]); + result = process.exitCode (); + process.close (); + } + catch (e:Dynamic) {}; + + colorSupported = (result == 0); + } + else + { + colorSupported = (Sys.getEnv("ANSICON") != null); + } + } + + if (colorSupported) + { + return output; + } + else + { + return colorCodes.replace(output, ""); + } + } + + public static function warn(message:String, verboseMessage:String = "", allowRepeat:Bool = false):Void + { + if (!mute) + { + var output = ""; + if (verbose && verboseMessage != "") + { + output = "\x1b[33;1mWarning:\x1b[0m \x1b[1m" + verboseMessage + "\x1b[0m"; + } + else if (message != "") + { + output = "\x1b[33;1mWarning:\x1b[0m \x1b[1m" + message + "\x1b[0m"; + } + + if (!allowRepeat && sentWarnings.exists (output)) + { + return; + } + + sentWarnings.set(output, true); + println(output); + } + } +} \ No newline at end of file diff --git a/tools/run/PathManager.hx b/tools/run/PathManager.hx new file mode 100644 index 000000000..049af9dbd --- /dev/null +++ b/tools/run/PathManager.hx @@ -0,0 +1,299 @@ +import sys.FileSystem; + +class PathManager +{ + private static var directoryCache = new Map(); + private static var haxelibPaths = new Map(); + + public static function combine(firstPath:String, secondPath:String):String + { + if (firstPath == null || firstPath == "") + { + return secondPath; + } + else if (secondPath != null && secondPath != "") + { + if (BuildTool.isWindows) + { + if (secondPath.indexOf (":") == 1) + { + return secondPath; + } + } + else + { + if (secondPath.substr (0, 1) == "/") + { + return secondPath; + } + } + + var firstSlash = (firstPath.substr(-1) == "/" || firstPath.substr(-1) == "\\"); + var secondSlash = (secondPath.substr(0, 1) == "/" || secondPath.substr(0, 1) == "\\"); + + if (firstSlash && secondSlash) + { + return firstPath + secondPath.substr(1); + } + else if (!firstSlash && !secondSlash) + { + return firstPath + "/" + secondPath; + } + else + { + return firstPath + secondPath; + } + } + else + { + return firstPath; + } + } + + public static function escape(path:String):String + { + if (!BuildTool.isWindows) + { + path = StringTools.replace(path, "\\ ", " "); + path = StringTools.replace(path, " ", "\\ "); + path = StringTools.replace(path, "\\'", "'"); + path = StringTools.replace(path, "'", "\\'"); + } + else + { + path = StringTools.replace(path, "^,", ","); + path = StringTools.replace(path, ",", "^,"); + } + return expand(path); + } + + public static function expand(path:String):String + { + if (path == null) + { + path = ""; + } + + if (!BuildTool.isWindows) + { + if (StringTools.startsWith(path, "~/")) + { + path = Sys.getEnv("HOME") + "/" + path.substr(2); + } + } + + return path; + } + + public static function getHaxelib (haxelib:String, version:String = "", validate:Bool = false, clearCache:Bool = false):String + { + var name = haxelib; + if (version != "") + { + name += ":" + version; + } + + if (clearCache) + { + haxelibPaths.remove(name); + } + + if (!haxelibPaths.exists(name)) + { + var cache = LogManager.verbose; + LogManager.verbose = false; + var output = ""; + + try + { + output = ProcessManager.runProcess(Sys.getEnv ("HAXEPATH"), "haxelib", [ "path", name ]); + } + catch (e:Dynamic) {} + + LogManager.verbose = cache; + + var lines = output.split("\n"); + var result = ""; + + for (i in 1...lines.length) + { + if (StringTools.trim(lines[i]) == "-D " + haxelib) + { + result = StringTools.trim(lines[i - 1]); + } + } + + if (validate) + { + if (result == "") + { + if (output.indexOf("does not have") > -1) + { + var directoryName = ""; + if (BuildTool.isWindows) + { + directoryName = "Windows"; + } + else if (BuildTool.isMac) + { + directoryName = BuildTool.is64 ? "Mac64" : "Mac"; + } + else + { + directoryName = BuildTool.is64 ? "Linux64" : "Linux"; + } + + LogManager.error ("haxelib \"" + haxelib + "\" does not have an \"ndll/" + directoryName + "\" directory"); + } + else + { + if (version != "") + { + LogManager.error("Could not find haxelib \"" + haxelib + "\" version \"" + version + "\", does it need to be installed?"); + } + else + { + LogManager.error("Could not find haxelib \"" + haxelib + "\", does it need to be installed?"); + } + } + } + } + + haxelibPaths.set(name,result); + } + + return haxelibPaths.get(name); + } + + public static function mkdir(directory:String):Void + { + directory = StringTools.replace(directory, "\\", "/"); + var total = ""; + + if (directory.substr(0, 1) == "/") + { + total = "/"; + } + + var parts = directory.split("/"); + var oldPath = ""; + + if (parts.length > 0 && parts[0].indexOf(":") > -1) + { + oldPath = Sys.getCwd(); + Sys.setCwd(parts[0] + "\\"); + parts.shift(); + } + + for (part in parts) + { + if (part != "." && part != "") + { + if (total != "" && total != "/") + { + total += "/"; + } + + total += part; + + if (!directoryCache.exists (total)) + { + //directoryCache.set(total, true); + if (!FileSystem.exists(total)) + { + LogManager.info("", "\x1b[1mCreating directory:\x1b[0m " + total); + FileSystem.createDirectory(total); + } + } + } + } + + if (oldPath != "") + { + Sys.setCwd(oldPath); + } + } + + public static function removeDirectory(directory:String):Void + { + if (FileSystem.exists(directory)) + { + var files; + try + { + files = FileSystem.readDirectory(directory); + } + catch (e:Dynamic) + { + return; + } + + for (file in FileSystem.readDirectory(directory)) + { + var path = directory + "/" + file; + try + { + if (FileSystem.isDirectory(path)) + { + removeDirectory(path); + } + else + { + FileSystem.deleteFile(path); + } + } + catch (e:Dynamic) {} + } + + LogManager.info("", "\x1b[1mRemoving directory:\x1b[0m " + directory); + + try + { + FileSystem.deleteDirectory(directory); + } + catch (e:Dynamic) {} + } + } + + static public function removeFile(file:String) + { + if (FileSystem.exists(file)) + { + LogManager.info("", "\x1b[1mRemoving file:\x1b[0m " + file); + FileSystem.deleteFile(file); + } + } + + static public function removeFilesWithExtension(inExt:String) + { + var contents = FileSystem.readDirectory("."); + for(item in contents) + { + if (item.length > inExt.length && item.substr(item.length-inExt.length)==inExt) + removeFile(item); + } + } + + public static function resetDirectoryCache():Void + { + directoryCache = new Map(); + } + + public static function standardize(path:String, trailingSlash:Bool = false):String + { + path = StringTools.replace (path, "\\", "/"); + path = StringTools.replace (path, "//", "/"); + path = StringTools.replace (path, "//", "/"); + + if (!trailingSlash && StringTools.endsWith(path, "/")) + { + path = path.substr(0, path.length - 1); + } + else if (trailingSlash && !StringTools.endsWith(path, "/")) + { + path += "/"; + } + + return path; + } +} \ No newline at end of file diff --git a/tools/run/ProcessManager.hx b/tools/run/ProcessManager.hx new file mode 100644 index 000000000..1013b6c1c --- /dev/null +++ b/tools/run/ProcessManager.hx @@ -0,0 +1,380 @@ +import haxe.io.BytesOutput; +import haxe.io.Eof; +import haxe.io.Path; +import sys.io.Process; +import sys.FileSystem; +#if neko +import neko.vm.Thread; +#else +import cpp.vm.Thread; +#end + +class ProcessManager +{ + private static function printCommand(command:String, args:Array):Void + { + var message = "\x1b[34;1m" + command + "\x1b[0m"; + for (arg in args) + { + if (StringTools.endsWith(arg, ".cpp") || StringTools.endsWith(arg, ".h")) + { + arg = "\x1b[1m" + arg + "\x1b[0m"; + } + + if (arg.indexOf(" ") > -1) + { + message += " \"" + arg + "\""; + } + else + { + message += " " + arg; + } + } + LogManager.info(message); + } + + public static function runCommand(path:String, command:String, args:Array, print:Bool = true, safeExecute:Bool = true, ignoreErrors:Bool = false):Int + { + if (print && !LogManager.verbose) + { + printCommand(command, args); + } + + command = PathManager.escape(command); + + if (safeExecute) + { + try + { + if (path != null && path != "" && !FileSystem.exists(FileSystem.fullPath(path)) && !FileSystem.exists(FileSystem.fullPath(new Path(path).dir))) + { + LogManager.error ("The specified target path \"" + path + "\" does not exist"); + return 1; + } + return _runCommand(path, command, args); + } + catch (e:Dynamic) + { + if (!ignoreErrors) + { + LogManager.error("", e); + return 1; + } + return 0; + } + } + else + { + return _runCommand(path, command, args); + } + } + + public static function runProcess(path:String, command:String, args:Array, waitForOutput:Bool = true, print:Bool = true, safeExecute:Bool = true, ignoreErrors:Bool = false):String + { + if (print && !LogManager.verbose) + { + printCommand(command, args); + } + + command = PathManager.escape(command); + + if (safeExecute) + { + try + { + if (path != null && path != "" && !FileSystem.exists(FileSystem.fullPath(path)) && !FileSystem.exists(FileSystem.fullPath(new Path(path).dir))) + { + LogManager.error("The specified target path \"" + path + "\" does not exist"); + } + return _runProcess(path, command, args, waitForOutput, ignoreErrors); + } + catch (e:Dynamic) + { + if (!ignoreErrors) + { + LogManager.error("", e); + } + return null; + } + } + else + { + return _runProcess(path, command, args, waitForOutput, ignoreErrors); + } + } + + public static function runProcessThreaded(path:String, command:String, args:Array, print:Bool = true, safeExecute:Bool = true, ignoreErrors:Bool = false):Int + { + if (print && !LogManager.verbose) + { + printCommand(command, args); + } + + command = PathManager.escape(command); + + if (safeExecute) + { + try + { + if (path != null && path != "" && !FileSystem.exists(FileSystem.fullPath(path)) && !FileSystem.exists(FileSystem.fullPath(new Path(path).dir))) + { + LogManager.error("The specified target path \"" + path + "\" does not exist"); + } + return _runProcessThreaded(path, command, args, ignoreErrors); + } + catch (e:Dynamic) + { + if (!ignoreErrors) + { + LogManager.error("", e); + } + return null; + } + } + else + { + return _runProcessThreaded(path, command, args, ignoreErrors); + } + } + + private static function _runCommand(path:String, command:String, args:Array):Int + { + var oldPath:String = ""; + + if (path != null && path != "") + { + LogManager.info("", "\x1b[1mChanging directory:\x1b[0m " + path + ""); + + oldPath = Sys.getCwd(); + Sys.setCwd(path); + } + + var argString = ""; + + for (arg in args) + { + if (arg.indexOf(" ") > -1) + { + argString += " \"" + arg + "\""; + } + else + { + argString += " " + arg; + } + } + + LogManager.info("", "\x1b[1mRunning command:\x1b[0m " + command + argString); + + var result = 0; + + if (args != null && args.length > 0) + { + result = Sys.command(command, args); + } + else + { + result = Sys.command(command); + } + + if (oldPath != "") + { + Sys.setCwd(oldPath); + } + + if (result != 0) + { + throw ("Error running: " + command + " " + args.join (" ") + " [" + path + "]"); + } + + return result; + } + + private static function _runProcess(path:String, command:String, args:Array, waitForOutput:Bool, ignoreErrors:Bool):String + { + var oldPath:String = ""; + + if (path != null && path != "") + { + LogManager.info("", "\x1b[1mChanging directory:\x1b[0m " + path + ""); + + oldPath = Sys.getCwd(); + Sys.setCwd(path); + } + + var argString = ""; + + for (arg in args) + { + if (arg.indexOf(" ") > -1) + { + argString += " \"" + arg + "\""; + } + else + { + argString += " " + arg; + } + } + + LogManager.info("", "\x1b[1mRunning process:\x1b[0m " + command + argString); + + var output = ""; + var result = 0; + + var process = new Process(command, args); + var buffer = new BytesOutput(); + + if (waitForOutput) + { + var waiting = true; + while (waiting) + { + try + { + var current = process.stdout.readAll(1024); + buffer.write(current); + if (current.length == 0) + { + waiting = false; + } + } + catch (e:Eof) + { + waiting = false; + } + } + + result = process.exitCode(); + process.close(); + + //if (result == 0) + //{ + output = buffer.getBytes().toString(); + if (output == "") + { + var error = process.stderr.readAll().toString(); + if (ignoreErrors) + { + output = error; + } + else + { + LogManager.error(error); + } + + return null; + + /*if (error != "") + { + LogManager.error(error); + }*/ + } + //} + } + + if (oldPath != "") + { + Sys.setCwd(oldPath); + } + + return output; + } + + private static function _runProcessThreaded(path:String, command:String, args:Array, ignoreErrors:Bool):Int + { + var oldPath:String = ""; + + if (path != null && path != "") + { + LogManager.info("", "\x1b[1mChanging directory:\x1b[0m " + path + ""); + + oldPath = Sys.getCwd(); + Sys.setCwd(path); + } + + var argString = ""; + + for (arg in args) + { + if (arg.indexOf(" ") > -1) + { + argString += " \"" + arg + "\""; + } + else + { + argString += " " + arg; + } + } + + LogManager.info("", "\x1b[1mRunning process:\x1b[0m " + command + argString); + + var output = new Array(); + var process = new Process(command, args); + var err = process.stderr; + var out = process.stdout; + var reader = BuildTool.helperThread.value; + + // Read stderr in separate thread to avoid blocking + if (reader==null) + { + var controller = Thread.current(); + BuildTool.helperThread.value = reader = Thread.create(function() + { + while(true) + { + var stream = Thread.readMessage(true); + var output:Array = null; + try + { + while(true) + { + var line = stream.readLine(); + if (output==null) + output = [ line ]; + else + output.push(line); + } + } + catch(e:Dynamic){ } + controller.sendMessage(output); + } + }); + } + + // Start-up the error reader + reader.sendMessage(err); + + try + { + while(true) + { + var line = out.readLine(); + output.push(line); + } + } + catch(e:Dynamic){ } + + var errOut:Array = Thread.readMessage(true); + + var code = process.exitCode(); + process.close(); + + if (code > 0 && !ignoreErrors) + { + LogManager.error(errOut.join ("\n")); + } + + if (errOut!=null && errOut.length>0) + output = output.concat(errOut); + + if (output.length>0) + { + if (BuildTool.printMutex!=null) + BuildTool.printMutex.acquire(); + LogManager.info(output.join("\n")); + if (BuildTool.printMutex!=null) + BuildTool.printMutex.release(); + } + + return code; + } +} \ No newline at end of file diff --git a/tools/run/Setup.hx b/tools/run/Setup.hx index 8302350df..c12e26215 100644 --- a/tools/run/Setup.hx +++ b/tools/run/Setup.hx @@ -1,10 +1,63 @@ +import haxe.io.Eof; +import sys.io.Process; import sys.FileSystem; import BuildTool; - class Setup { - public static function initHXCPPConfig(ioDefines:Hash ) + static function findAndroidNdkRoot(inDir:String) + { + var files:Array = null; + try + { + files = FileSystem.readDirectory(inDir); + } + catch (e:Dynamic) + { + LogManager.error('ANDROID_NDK_DIR "$inDir" does not point to a valid directory'); + //throw 'ANDROID_NDK_DIR "$inDir" does not point to a valid directory.'; + } + + var extract_version = ~/^android-ndk-r(\d+)([a-z]?)$/; + var bestMajor = 0; + var bestMinor = ""; + var result = ""; + for(file in files) + if (extract_version.match(file)) + { + var major = Std.parseInt( extract_version.matched(1) ); + var minor = extract_version.matched(2); + if ( major>bestMajor || (major==bestMajor && minor>bestMinor)) + { + bestMajor = major; + bestMinor = minor; + result = inDir + "/" + file; + } + } + + LogManager.info("", "Found NDK " + result); + + if (result=="") + { + LogManager.error('ANDROID_NDK_DIR "$inDir" does not contain matching NDK downloads'); + //throw 'ANDROID_NDK_DIR "$inDir" does not contain matching ndk downloads.'; + } + + return result; + } + + static public function getNdkVersion(inDirName:String):Int + { + var extract_version = ~/android-ndk-r(\d+)*/; + if (extract_version.match(inDirName)) + { + return Std.parseInt( extract_version.matched(1) ); + } + //throw 'Could not deduce NDK version from "$inDirName"'; + return 8; + } + + public static function initHXCPPConfig(ioDefines:Hash) { var env = Sys.environment(); // If the user has set it themselves, they mush know what they are doing... @@ -13,12 +66,13 @@ class Setup var home = ""; if (env.exists("HOME")) - home = env.get("HOME"); + home = env.get("HOME"); else if (env.exists("USERPROFILE")) - home = env.get("USERPROFILE"); + home = env.get("USERPROFILE"); else { - Sys.println("Warning: No 'HOME' variable set - .hxcpp_config.xml might be missing."); + LogManager.warn("No $HOME variable set, \".hxcpp_config.xml\" might be missing"); + //Sys.println("Warning: No 'HOME' variable set - .hxcpp_config.xml might be missing."); return; } @@ -27,216 +81,200 @@ class Setup if (BuildTool.HXCPP!="") { - var src = toPath(BuildTool.HXCPP + "build-tool/example.hxcpp_config.xml"); + var src = toPath(BuildTool.HXCPP + "/build-tool/example.hxcpp_config.xml"); if (!sys.FileSystem.exists(config)) { - try { - if (BuildTool.verbose) - BuildTool.println("Copy config: " + src + " -> " + config ); - + try + { + LogManager.info("", "Copying HXCPP config \"" + src + "\" to \"" + config + "\""); sys.io.File.copy(src,config); - } catch(e:Dynamic) + } + catch(e:Dynamic) { - Sys.println("Warning : could not create config: " + config ); + LogManager.warn("Could not create HXCPP config \"" + config + "\""); + //Sys.println("Warning : could not create config: " + config ); } } } } - static public function getNdkVersion(inDirName:String) : Int + public static function isRaspberryPi() { - var extract_version = ~/android-ndk-r(\d+)*/; - if (extract_version.match(inDirName)) - { - return Std.parseInt( extract_version.matched(1) ); - } - //throw 'Could not deduce NDK version from "$inDirName"'; - return 8; + var proc = new Process("uname",["-a"]); + var str = proc.stdout.readLine(); + proc.close(); + return str.split(" ")[1]=="raspberrypi"; } - static public function setupAndroidNdk(defines: Map) + public static function readStderr(inCommand:String,inArgs:Array) { - var root:String = null; - - if (!defines.exists("ANDROID_NDK_ROOT")) - { - if (defines.exists("ANDROID_NDK_DIR")) - { - root = Setup.findAndroidNdkRoot( defines.get("ANDROID_NDK_DIR") ); - if (BuildTool.verbose) - BuildTool.println("Using found ndk root " + root); - - Sys.putEnv("ANDROID_NDK_ROOT", root); - defines.set("ANDROID_NDK_ROOT", root); - } - else - throw "ANDROID_NDK_ROOT or ANDROID_NDK_DIR should be set"; - } - else - { - root = defines.get("ANDROID_NDK_ROOT"); - if (BuildTool.verbose) - BuildTool.println("Using specified ndk root " + root); - } - - // Find toolchain - if (!defines.exists("TOOLCHAIN_VERSION")) - { - try - { - var files = FileSystem.readDirectory(root+"/toolchains"); - - // Prefer clang? - var extract_version = ~/^arm-linux-androideabi-(\d.*)/; - var bestVer=""; - for(file in files) - { - if (extract_version.match(file)) - { - var ver = extract_version.matched(1); - if ( ver>bestVer || bestVer=="") - { - bestVer = ver; - } - } - } - if (bestVer!="") - { - defines.set("TOOLCHAIN_VERSION",bestVer); - if (BuildTool.verbose) - BuildTool.println("Found TOOLCHAIN_VERSION " + bestVer); - } - } - catch(e:Dynamic) { } - } - - // See what ANDROID_HOST to use ... - try - { - var prebuilt = root+"/toolchains/arm-linux-androideabi-" + defines.get("TOOLCHAIN_VERSION") + "/prebuilt"; - var files = FileSystem.readDirectory(prebuilt); - if (files.length==1) - { - defines.set("ANDROID_HOST", files[0]); - if (BuildTool.verbose) - { - BuildTool.println("Found ANDROID_HOST " + files[0]); - } - } - else if (BuildTool.verbose) - BuildTool.println("Could not work out ANDROID_HOST (" + files + ") - using default"); - } - catch(e:Dynamic) { } - - var found = false; - for(i in 6...20) - if (defines.exists("NDKV" + i)) - { - found = true; - if (BuildTool.verbose) - BuildTool.println("Using specified android NDK " + i); - break; - } - if (!found) - { - var version = Setup.getNdkVersion( defines.get("ANDROID_NDK_ROOT") ); - if (BuildTool.verbose) - BuildTool.println("Deduced android NDK " + version); - defines.set("NDKV" + version, "1" ); - } - - if (defines.exists("PLATFORM")) - { - BuildTool.log("Using specified android PLATFORM " + defines.get("PLATFORM") ); - } - else - { - var base = defines.get("ANDROID_NDK_ROOT") + "/platforms"; - var best = 0; - try - { - for(file in FileSystem.readDirectory(base)) - { - if (file.substr(0,8)=="android-") - { - var platform = Std.parseInt(file.substr(8)); - if (platform>best) - best = platform; - } - } - } catch(e:Dynamic) - { - } - - if (best==0) - throw "Could not find platform in " + base; + var result = new Array(); + var proc = new Process(inCommand,inArgs); + try + { + while(true) + { + var out = proc.stderr.readLine(); + result.push(out); + } + } catch(e:Dynamic){} + proc.close(); + return result; + } - BuildTool.log("Using biggest platform " + best); - defines.set("PLATFORM", "android-" + best ); - } + public static function readStdout(inCommand:String,inArgs:Array) + { + var result = new Array(); + var proc = new Process(inCommand,inArgs); + try + { + while(true) + { + var out = proc.stdout.readLine(); + result.push(out); + } + } catch(e:Dynamic){} + proc.close(); + return result; } + public static function setup(inWhat:String,ioDefines: Map) + { + if (inWhat=="androidNdk") + { + setupAndroidNdk(ioDefines); + } + else if (inWhat=="msvc") + { + setupMSVC(ioDefines, ioDefines.exists("HXCPP_M64")); + } + else + { + LogManager.error('Unknown setup feature "$inWhat"'); + //throw 'Unknown setup feature $inWhat'; + } + } - static function findAndroidNdkRoot(inDir:String) + static public function setupAndroidNdk(defines:Map) { - var files:Array = null; - try + var root:String = null; + + if (!defines.exists("ANDROID_NDK_ROOT")) { - files = FileSystem.readDirectory(inDir); + if (defines.exists("ANDROID_NDK_DIR")) + { + root = Setup.findAndroidNdkRoot( defines.get("ANDROID_NDK_DIR") ); + LogManager.info("", "Using found NDK root \"" + root + "\""); + + Sys.putEnv("ANDROID_NDK_ROOT", root); + defines.set("ANDROID_NDK_ROOT", root); + } + else + { + LogManager.error("Could not find ANDROID_NDK_ROOT or ANDROID_NDK_DIR variable"); + //throw "ANDROID_NDK_ROOT or ANDROID_NDK_DIR should be set"; + } } - catch (e:Dynamic) + else { - throw 'ANDROID_NDK_DIR "$inDir" does not point to a valid directory.'; + root = defines.get("ANDROID_NDK_ROOT"); + LogManager.info("", "Using specified NDK root \"" + root + "\""); } - var extract_version = ~/^android-ndk-r(\d+)([a-z]?)$/; - var bestMajor = 0; - var bestMinor = ""; - var result = ""; - for(file in files) - if (extract_version.match(file)) + // Find toolchain + if (!defines.exists("TOOLCHAIN_VERSION")) + { + try { - var major = Std.parseInt( extract_version.matched(1) ); - var minor = extract_version.matched(2); - if ( major>bestMajor || (major==bestMajor && minor>bestMinor)) + var files = FileSystem.readDirectory(root+"/toolchains"); + + // Prefer clang? + var extract_version = ~/^arm-linux-androideabi-(\d.*)/; + var bestVer=""; + for(file in files) { - bestMajor = major; - bestMinor = minor; - result = inDir + "/" + file; + if (extract_version.match(file)) + { + var ver = extract_version.matched(1); + if ( ver>bestVer || bestVer=="") + { + bestVer = ver; + } + } + } + if (bestVer!="") + { + defines.set("TOOLCHAIN_VERSION",bestVer); + LogManager.info("", "Found TOOLCHAIN_VERSION " + bestVer); } } + catch(e:Dynamic) { } + } + // See what ANDROID_HOST to use ... + try + { + var prebuilt = root+"/toolchains/arm-linux-androideabi-" + defines.get("TOOLCHAIN_VERSION") + "/prebuilt"; + var files = FileSystem.readDirectory(prebuilt); + if (files.length==1) + { + defines.set("ANDROID_HOST", files[0]); + LogManager.info("", "Found ANDROID_HOST " + files[0]); + } + else + { + LogManager.info("", "Could not work out ANDROID_HOST (" + files + ") - using default"); + } + } + catch(e:Dynamic) { } - if (BuildTool.verbose) + var found = false; + for(i in 6...20) + if (defines.exists("NDKV" + i)) + { + found = true; + LogManager.info("", "Using specified android NDK " + i); + break; + } + if (!found) { - var message = "Found NDK " + result; - BuildTool.println(message); + var version = Setup.getNdkVersion( defines.get("ANDROID_NDK_ROOT") ); + LogManager.info("", "Deduced android NDK " + version); + defines.set("NDKV" + version, "1" ); } - if (result=="") - throw 'ANDROID_NDK_DIR "$inDir" does not contain matching ndk downloads.'; + if (defines.exists("PLATFORM")) + { + LogManager.info("", "Using specified android PLATFORM " + defines.get("PLATFORM")); + } + else + { + var base = defines.get("ANDROID_NDK_ROOT") + "/platforms"; + var best = 0; + try + { + for(file in FileSystem.readDirectory(base)) + { + if (file.substr(0,8)=="android-") + { + var platform = Std.parseInt(file.substr(8)); + if (platform>best) + best = platform; + } + } + } catch(e:Dynamic) {} - return result; - } + if (best==0) + { + LogManager.error("Could not find NDK platform in \"" + base + "\""); + //throw "Could not find platform in " + base; + } - public static function setup(inWhat:String,ioDefines: Map) - { - if (inWhat=="androidNdk") - setupAndroidNdk(ioDefines); - else if (inWhat=="msvc") - setupMSVC(ioDefines, ioDefines.exists("HXCPP_M64")); - else - throw 'Unknown setup feature $inWhat'; + LogManager.info("", "Using newest NDK platform: " + best); + defines.set("PLATFORM", "android-" + best); + } } - static function toPath(inPath:String) - { - if (!BuildTool.isWindows) - return inPath; - var bits = inPath.split("/"); - return bits.join("\\"); - } - public static function setupBlackBerryNativeSDK(ioDefines:Hash) { if (ioDefines.exists ("BLACKBERRY_NDK_ROOT") && (!ioDefines.exists("QNX_HOST") || !ioDefines.exists("QNX_TARGET"))) @@ -263,11 +301,11 @@ class Setup switch (name) { case "QNX_HOST", "QNX_TARGET", "QNX_HOST_VERSION", "QNX_TARGET_VERSION": - var value = split[1]; - if (StringTools.startsWith (value, "${") && split.length > 2) - { - value = split[2].substr (0, split[2].length - 1); - } + var value = split[1]; + if (StringTools.startsWith (value, "${") && split.length > 2) + { + value = split[2].substr (0, split[2].length - 1); + } if (StringTools.startsWith(value, "\"")) { value = value.substr (1); @@ -287,7 +325,7 @@ class Setup { value = StringTools.replace (value, "$QNX_HOST_VERSION", Sys.getEnv("QNX_HOST_VERSION")); value = StringTools.replace (value, "$QNX_TARGET_VERSION", Sys.getEnv("QNX_TARGET_VERSION")); - value = StringTools.replace (value, "%QNX_HOST_VERSION%", Sys.getEnv("QNX_HOST_VERSION")); + value = StringTools.replace (value, "%QNX_HOST_VERSION%", Sys.getEnv("QNX_HOST_VERSION")); value = StringTools.replace (value, "%QNX_TARGET_VERSION%", Sys.getEnv("QNX_TARGET_VERSION")); } ioDefines.set(name,value); @@ -295,14 +333,14 @@ class Setup } } } - catch( ex:haxe.io.Eof ) + catch( ex:Eof ) {} fin.close(); } } } - public static function setupMSVC(ioDefines:Hash, in64:Bool ) + public static function setupMSVC(ioDefines:Hash, in64:Bool) { var detectMsvc = !ioDefines.exists("NO_AUTO_MSVC") && !ioDefines.exists("HXCPP_MSVC_CUSTOM"); @@ -324,17 +362,21 @@ class Setup for(env in Sys.environment().keys()) { if (env.substr(0,2)=="VS") - Sys.println("Found VS variable " + env); + { + LogManager.info("Found VS variable: " + env); + //Sys.println("Found VS variable " + env); + } } - throw "Could not find specified MSCV version " + ival; + LogManager.error("Could not find specified MSCV version: " + ival); + //throw "Could not find specified MSCV version " + ival; } ioDefines.set("HXCPP_MSVC", where ); Sys.putEnv("HXCPP_MSVC", where); - BuildTool.log('Using MSVC Ver $ival in $where ($varName)'); + LogManager.info("", 'Using MSVC Ver $ival in $where ($varName)'); } else { - BuildTool.log('Using specified MSVC Ver $val'); + LogManager.info("", 'Using specified MSVC Ver $val'); ioDefines.set("HXCPP_MSVC", val ); Sys.putEnv("HXCPP_MSVC", val); } @@ -351,7 +393,7 @@ class Setup xpCompat = true; } - var vc_setup_proc = new sys.io.Process("cmd.exe", ["/C", BuildTool.HXCPP + "build-tool\\msvc" + extra + "-setup.bat" ]); + var vc_setup_proc = new Process("cmd.exe", ["/C", BuildTool.HXCPP + "\\build-tool\\msvc" + extra + "-setup.bat" ]); var vars_found = false; var error_string = ""; var output = new Array(); @@ -384,90 +426,64 @@ class Setup } } } - } catch (e:Dynamic) { - }; - - vc_setup_proc.close(); - if (!vars_found || error_string!="") - { - for(o in output) - BuildTool.println(o); - if (error_string!="") - throw(error_string); - else - BuildTool.println("Missing HXCPP_VARS"); - - throw("Could not automatically setup MSVC"); - } - } - - - try - { - var proc = new sys.io.Process("cl.exe",[]); - var str = proc.stderr.readLine(); - proc.close(); - if (str>"") - { - var reg = ~/Version\s+(\d+)/i; - if (reg.match(str)) - { - var cl_version = Std.parseInt(reg.matched(1)); - if (BuildTool.verbose) - BuildTool.println("Using msvc cl version " + cl_version); - ioDefines.set("MSVC_VER", cl_version+""); - if (cl_version>=17) - ioDefines.set("MSVC17+","1"); - if (cl_version>=18) - ioDefines.set("MSVC18+","1"); - BuildTool.sAllowNumProcs = cl_version >= 14; - if (Std.parseInt(ioDefines.get("HXCPP_COMPILE_THREADS"))>1 && cl_version>=18) - ioDefines.set("HXCPP_FORCE_PDB_SERVER","1"); - } - } - } catch(e:Dynamic){} - //if (cl_version!="") BuildTool.println("Using cl version: " + cl_version); - } + } catch (e:Dynamic) { + }; - public static function isRaspberryPi() - { - var proc = new sys.io.Process("uname",["-a"]); - var str = proc.stdout.readLine(); - proc.close(); - return str.split(" ")[1]=="raspberrypi"; - } - - public static function readStderr(inCommand:String,inArgs:Array) - { - var result = new Array(); - var proc = new sys.io.Process(inCommand,inArgs); - try - { - while(true) + vc_setup_proc.close(); + if (!vars_found || error_string!="") { - var out = proc.stderr.readLine(); - result.push(out); + for(o in output) + { + LogManager.info(o); + //BuildTool.println(o); + } + if (error_string!="") + { + LogManager.error (error_string); + //throw(error_string); + } + else + { + LogManager.info("Missing HXCPP_VARS"); + //BuildTool.println("Missing HXCPP_VARS"); + } + + LogManager.error("Could not automatically setup MSVC"); + //throw("Could not automatically setup MSVC"); } - } catch(e:Dynamic){} - proc.close(); - return result; - } + } - public static function readStdout(inCommand:String,inArgs:Array) - { - var result = new Array(); - var proc = new sys.io.Process(inCommand,inArgs); try { - while(true) + var proc = new Process("cl.exe",[]); + var str = proc.stderr.readLine(); + proc.close(); + if (str>"") { - var out = proc.stdout.readLine(); - result.push(out); + var reg = ~/Version\s+(\d+)/i; + if (reg.match(str)) + { + var cl_version = Std.parseInt(reg.matched(1)); + LogManager.info("", "Using msvc cl version " + cl_version); + ioDefines.set("MSVC_VER", cl_version+""); + if (cl_version>=17) + ioDefines.set("MSVC17+","1"); + if (cl_version>=18) + ioDefines.set("MSVC18+","1"); + BuildTool.sAllowNumProcs = cl_version >= 14; + if (Std.parseInt(ioDefines.get("HXCPP_COMPILE_THREADS"))>1 && cl_version>=18) + ioDefines.set("HXCPP_FORCE_PDB_SERVER","1"); + } } } catch(e:Dynamic){} - proc.close(); - return result; + //if (cl_version!="") BuildTool.println("Using cl version: " + cl_version); } -} - + static function toPath(inPath:String) + { + if (!BuildTool.isWindows) + return inPath; + var bits = inPath.split("/"); + return bits.join("\\"); + } +} \ No newline at end of file diff --git a/tools/run/Stripper.hx b/tools/run/Stripper.hx new file mode 100644 index 000000000..28fdb7f71 --- /dev/null +++ b/tools/run/Stripper.hx @@ -0,0 +1,29 @@ +class Stripper +{ + public var mExe:String; + public var mFlags:Array; + + public function new(inExe:String) + { + mFlags = []; + mExe = inExe; + } + + public function strip(inTarget:String) + { + var args = new Array(); + args = args.concat(mFlags); + args.push(inTarget); + + var split = mExe.split(" "); + var exe = split.shift(); + args = split.concat(args); + + var result = ProcessManager.runCommand("", exe, args); + if (result!=0) + { + Sys.exit(result); + //throw "Error : " + result + " - build cancelled"; + } + } +} \ No newline at end of file diff --git a/tools/run/Target.hx b/tools/run/Target.hx new file mode 100644 index 000000000..1368aff59 --- /dev/null +++ b/tools/run/Target.hx @@ -0,0 +1,70 @@ +class Target +{ + public var mBuildDir:String; + public var mOutput:String; + public var mOutputDir:String; + public var mTool:String; + public var mToolID:String; + public var mFiles:Array; + public var mFileGroups:Array; + public var mDepends:Array; + public var mSubTargets:Array; + public var mLibs:Array; + public var mFlags:Array; + public var mErrors:Array; + public var mDirs:Array; + public var mExt:String; + + public function new(inOutput:String, inTool:String,inToolID:String) + { + mOutput = inOutput; + mOutputDir = ""; + mBuildDir = ""; + mToolID = inToolID; + mTool = inTool; + mFiles = []; + mDepends = []; + mLibs = []; + mFlags = []; + mExt = ""; + mSubTargets = []; + mFileGroups = []; + mFlags = []; + mErrors=[]; + mDirs=[]; + } + + public function addError(inError:String) + { + mErrors.push(inError); + } + + public function addFiles(inGroup:FileGroup) + { + mFiles = mFiles.concat(inGroup.mFiles); + mFileGroups.push(inGroup); + } + + public function checkError() + { + if (mErrors.length>0) + { + LogManager.error(mErrors.join(", ")); + //throw mErrors.join("/"); + } + } + + public function clean() + { + for(dir in mDirs) + { + LogManager.info("Remove " + dir + "..."); + PathManager.removeDirectory(dir); + } + } + + public function getKey() + { + return mOutput + mExt; + } +} \ No newline at end of file