forked from LeenkxTeam/LNXSDK
		
	
		
			
				
	
	
		
			325 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
			
		
		
	
	
			325 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
| import haxe.io.Path;
 | |
| import sys.FileSystem;
 | |
| import haxe.crypto.Md5;
 | |
| 
 | |
| using StringTools;
 | |
| 
 | |
| class Linker
 | |
| {
 | |
|    public var mExe:String;
 | |
|    public var mFlags:Array<String>;
 | |
|    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 mFromFileNeedsQuotes:Bool;
 | |
|    public var mLibs:Array<String>;
 | |
|    public var mExpandArchives:Bool;
 | |
|    public var mRecreate:Bool;
 | |
|    public var mLastOutName:String;
 | |
|    public var mAddLibPath:String;
 | |
| 
 | |
|    public function new(inExe:String)
 | |
|    {
 | |
|       mFlags = [];
 | |
|       mOutFlag = "-o";
 | |
|       mAddLibPath = "-L";
 | |
|       mExe = inExe;
 | |
|       mNamePrefix = "";
 | |
|       mLibDir = "";
 | |
|       mRanLib = "";
 | |
|       mExpandArchives = false;
 | |
|       // Default to on...
 | |
|       mFromFile = "@";
 | |
|       mFromFileNeedsQuotes = true;
 | |
|       mLibs = [];
 | |
|       mRecreate = false;
 | |
|    }
 | |
| 
 | |
|    function isOutOfDate(inName:String, inObjs:Array<String>)
 | |
|    {
 | |
|       if (!FileSystem.exists(inName))
 | |
|          return true;
 | |
|       var stamp = FileSystem.stat(inName).mtime.getTime();
 | |
|       for(obj in inObjs)
 | |
|       {
 | |
|          if (!FileSystem.exists(obj))
 | |
|          {
 | |
|             Log.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;
 | |
|    }
 | |
| 
 | |
|    function getSimpleFilename(inTarget:Target)
 | |
|    {
 | |
|       var ext = inTarget.getExt(mExt);
 | |
|       // Remove arch from ext ...
 | |
|       var idx = ext.indexOf('.');
 | |
|       if (idx>0)
 | |
|          ext = ext.substr(idx);
 | |
| 
 | |
|       return mNamePrefix + inTarget.mOutput + ext;
 | |
|    }
 | |
|    public function getUnstrippedFilename(inObjDir, inTarget:Target)
 | |
|    {
 | |
|       if (inTarget.mFullUnstrippedName!=null)
 | |
|       {
 | |
|          PathManager.mkdir( inTarget.mFullUnstrippedName, true );
 | |
|          return inTarget.mFullUnstrippedName;
 | |
|       }
 | |
|       return inObjDir + "/" + getSimpleFilename(inTarget);
 | |
|    }
 | |
| 
 | |
|    public function link(inTarget:Target,inObjs:Array<String>,inCompiler:Compiler,extraDeps:Array<String> )
 | |
|    {
 | |
|       var ext = inTarget.getExt(mExt);
 | |
|       var file_name = mNamePrefix + inTarget.mOutput + ext;
 | |
| 
 | |
|       var tmpDir = inCompiler.mObjDir;
 | |
| 
 | |
|       try
 | |
|       {
 | |
|          PathManager.mkdir(inTarget.mOutputDir);
 | |
|       }
 | |
|       catch (e:Dynamic)
 | |
|       {
 | |
|          Log.error("Unable to create output directory \"" + inTarget.mOutputDir + "\"");
 | |
|          //throw "Unable to create output directory " + inTarget.mOutputDir;
 | |
|       }
 | |
| 
 | |
|       var out_name = Path.normalize(PathManager.combine( inTarget.mBuildDir, inTarget.mOutputDir + file_name));
 | |
|       var hashFile = out_name + ".hash";
 | |
|       if (inTarget.mFullOutputName!=null)
 | |
|       {
 | |
|          PathManager.mkdir( inTarget.mFullOutputName, true );
 | |
|          out_name = inTarget.mFullOutputName;
 | |
|       }
 | |
| 
 | |
|       mLastOutName = out_name;
 | |
| 
 | |
| 
 | |
|       var lastLib = "";
 | |
|       var libs = new Array<String>();
 | |
|       for(l in inTarget.mAutoLibs)
 | |
|          if (l!=lastLib)
 | |
|          {
 | |
|             libs.push(l);
 | |
|             lastLib = l;
 | |
|          }
 | |
| 
 | |
|       for(l in inTarget.mLibs)
 | |
|          if (l!=lastLib)
 | |
|          {
 | |
|             libs.push(l);
 | |
|             lastLib = l;
 | |
|          }
 | |
| 
 | |
|       for(l in mLibs)
 | |
|          if (l!=lastLib)
 | |
|          {
 | |
|             libs.push(l);
 | |
|             lastLib = l;
 | |
|          }
 | |
| 
 | |
|       var v18Added = false;
 | |
|       var isOutOfDateLibs = false;
 | |
| 
 | |
|       var md5 = Md5.encode(inObjs.join(";"));
 | |
|       if (!FileSystem.exists(hashFile) || sys.io.File.getContent(hashFile)!=md5)
 | |
|          isOutOfDateLibs = true;
 | |
| 
 | |
|       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))
 | |
|                {
 | |
|                   Log.info("", " - \x1b[1mUsing current compiler library:\x1b[0m " + current);
 | |
|                   libs[i]=current;
 | |
|                }
 | |
|                else
 | |
|                {
 | |
|                   var v18 = parts[0] + "-18" + parts[1];
 | |
|                   if (FileSystem.exists(v18))
 | |
|                   {
 | |
|                      Log.info("", " - \x1b[1mUsing MSVC18 compatible library:\x1b[0m " + v18);
 | |
|                      libs[i]=v18;
 | |
|                      if (!v18Added)
 | |
|                      {
 | |
|                         v18Added=true;
 | |
|                         libs.push( BuildTool.HXCPP + "/lib/Windows/libmsvccompat-18.lib");
 | |
|                      }
 | |
|                   }
 | |
|                   else
 | |
|                   {
 | |
|                      Log.error("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 (BuildTool.isMingw())
 | |
|          {
 | |
|             var libMatch = ~/^([a-zA-Z0-9_]+).lib$/;
 | |
|             if (libMatch.match(libs[i]))
 | |
|                libs[i] = "-l" + libMatch.matched(1);
 | |
|          }
 | |
| 
 | |
|       }
 | |
| 
 | |
|       if (isOutOfDateLibs || isOutOfDate(out_name,inObjs) || isOutOfDate(out_name,inTarget.mDepends) || isOutOfDate(out_name,extraDeps) )
 | |
|       {
 | |
|          var args = new Array<String>();
 | |
|          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))
 | |
|             {
 | |
|                Log.info("\x1b[1mClean: \x1b[0m" + 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<String>();
 | |
|             for(lib in libs)
 | |
|             {
 | |
|                if (isArchive.match(lib))
 | |
|                {
 | |
|                   var libName = Path.withoutDirectory(lib);
 | |
|                   var libObjs = ProcessManager.readStdout(mExe, ["t", lib ]);
 | |
|                   var objDir = tmpDir + "/" + libName + ".unpack";
 | |
|                   PathManager.mkdir(objDir);
 | |
|                   ProcessManager.runCommand (objDir, mExe, ["x", lib], true, true, false, " - Unpack : " + lib);
 | |
|                   for(obj in libObjs)
 | |
|                      objs.push( objDir+"/"+obj );
 | |
|                }
 | |
|                else
 | |
|                   libArgs.push(lib);
 | |
|             }
 | |
|             libs = libArgs;
 | |
|          }
 | |
| 
 | |
|          var here = Path.normalize(Sys.getCwd()) + "/";
 | |
|          var hereLen = here.length;
 | |
|          for(oid in 0...objs.length)
 | |
|          {
 | |
|             var obj = Path.normalize( objs[oid] );
 | |
|             if (obj.startsWith(here))
 | |
|                objs[oid] = obj.substr(hereLen);
 | |
|          }
 | |
| 
 | |
|          // Place list of obj files in a file called "all_objs"
 | |
|          if (mFromFile!="")
 | |
|          {
 | |
|             PathManager.mkdir(tmpDir);
 | |
|             var fname = tmpDir + "/all_objs";
 | |
| 
 | |
|             var local = Path.normalize(fname);
 | |
|             if (local.startsWith(here))
 | |
|                fname = local.substr(hereLen);
 | |
| 
 | |
|             var fout = sys.io.File.write(fname,false);
 | |
|             if (mFromFileNeedsQuotes)
 | |
|             {
 | |
|                for(obj in objs)
 | |
|                   fout.writeString('"' + obj + '"\n');
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                for(obj in objs)
 | |
|                   fout.writeString(obj + '\n');
 | |
|             }
 | |
|             fout.close();
 | |
|             var parts = mFromFile.split(" ");
 | |
|             var last = parts.pop();
 | |
|             args = args.concat(parts);
 | |
|             args.push(last + fname );
 | |
|          }
 | |
|          else
 | |
|             args = args.concat(objs);
 | |
| 
 | |
|          for(libpath in inTarget.mLibPaths)
 | |
|          {
 | |
|             var path = Path.normalize(libpath);
 | |
|             if (path.startsWith(here))
 | |
|                path = path.substr(hereLen);
 | |
|             args.push( mAddLibPath + path );
 | |
|          }
 | |
| 
 | |
|          args = args.concat(libs);
 | |
| 
 | |
|          var result = ProcessManager.runCommand("", mExe, args, true, true, false,
 | |
|              "\x1b[1mLink: \x1b[0m" + out_name);
 | |
|          if (result!=0)
 | |
|          {
 | |
|             Tools.exit(result);
 | |
|             //throw "Error : " + result + " - build cancelled";
 | |
|          }
 | |
| 
 | |
|          if (mRanLib!="")
 | |
|          {
 | |
|             args = [out_name];
 | |
|             var result = ProcessManager.runCommand("", mRanLib, args, true, true, false, "\x1b[1mRanlib:\x1b[0m " + out_name);
 | |
|             if (result!=0)
 | |
|             {
 | |
|                Tools.exit(result);
 | |
|                //throw "Error : " + result + " - build cancelled";
 | |
|             }
 | |
|          }
 | |
| 
 | |
|          if (mLibDir!="")
 | |
|          {
 | |
|             sys.io.File.copy( mLibDir+"/"+file_name, out_name );
 | |
|             FileSystem.deleteFile( mLibDir+"/"+file_name );
 | |
|          }
 | |
| 
 | |
|          sys.io.File.saveContent(hashFile,md5);
 | |
|          return out_name;
 | |
|       }
 | |
| 
 | |
|       return "";
 | |
|    }
 | |
| }
 |