2020-04-29 06:40:03 -07:00
using System.Collections ;
2019-08-27 08:04:41 -07:00
using System ;
using IDE.Compiler ;
using System.IO ;
using System.Diagnostics ;
using Beefy ;
using IDE.util ;
2022-01-28 08:19:11 -05:00
using IDE.Util ;
2024-10-18 09:13:24 -04:00
using Beefy.theme.dark ;
2019-08-27 08:04:41 -07:00
namespace IDE
{
2020-05-13 12:28:20 -07:00
enum CompileKind
{
case Normal ;
case RunAfter ;
case DebugAfter ;
2022-03-21 11:14:19 -07:00
case DebugComptime ;
2020-05-13 12:28:20 -07:00
case Test ;
2023-02-20 16:21:56 -05:00
case WhileRunning ;
2020-05-13 12:28:20 -07:00
public bool WantsRunAfter
{
get
{
return ( this = = . RunAfter ) | | ( this = = . DebugAfter ) ;
}
}
}
2019-08-27 08:04:41 -07:00
class BuildContext
{
2019-09-28 09:48:37 -07:00
public int32 mUpdateCnt ;
2019-08-27 08:04:41 -07:00
public Project mHotProject ;
public Workspace . Options mWorkspaceOptions ;
2021-02-25 10:14:22 -08:00
public Dictionary < Project , String > mImpLibMap = new . ( ) ~ DeleteDictionaryAndValues ! ( _ ) ;
public Dictionary < Project , String > mTargetPathMap = new . ( ) ~ DeleteDictionaryAndValues ! ( _ ) ;
2020-05-21 11:47:15 -07:00
public ScriptManager . Context mScriptContext = new . ( ) ~ _ . ReleaseLastRef ( ) ;
2019-08-27 08:04:41 -07:00
public ScriptManager mScriptManager ~ delete _ ;
public bool Failed
{
get
{
if ( mScriptManager ! = null )
return mScriptManager . mFailed ;
return false ;
}
}
public enum CustomBuildCommandResult
{
NoCommands ,
HadCommands ,
Failed
}
2019-10-15 12:28:21 -07:00
Workspace . PlatformType mPlatformType ;
Workspace . ToolsetType mToolset ;
int mPtrSize ;
public this ( )
{
Workspace . Options workspaceOptions = gApp . GetCurWorkspaceOptions ( ) ;
mToolset = workspaceOptions . mToolsetType ;
2022-01-28 08:19:11 -05:00
mPlatformType = Workspace . PlatformType . GetFromName ( gApp . mPlatformName , workspaceOptions . mTargetTriple ) ;
2019-10-15 12:28:21 -07:00
mPtrSize = Workspace . PlatformType . GetPtrSizeByName ( gApp . mPlatformName ) ;
}
2019-08-27 08:04:41 -07:00
public CustomBuildCommandResult QueueProjectCustomBuildCommands ( Project project , String targetPath , Project . BuildCommandTrigger trigger , List < String > cmdList )
{
if ( cmdList . IsEmpty )
return . NoCommands ;
if ( trigger = = . Never )
return . NoCommands ;
2020-05-12 06:44:09 -07:00
List < Project > depProjectList = scope . ( ) ;
gApp . GetDependentProjectList ( project , depProjectList ) ;
2019-08-27 08:04:41 -07:00
if ( ( trigger = = . IfFilesChanged ) & & ( ! project . mForceCustomCommands ) )
{
int64 highestDateTime = 0 ;
int64 targetDateTime = File . GetLastWriteTime ( targetPath ) . Get ( ) . ToFileTime ( ) ;
bool forceRebuild = false ;
2020-05-12 06:44:09 -07:00
for ( var depName in depProjectList )
2019-08-27 08:04:41 -07:00
{
var depProject = gApp . mWorkspace . FindProject ( depName . mProjectName ) ;
if ( depProject ! = null )
{
if ( depProject . mLastDidBuild )
forceRebuild = true ;
}
}
project . WithProjectItems ( scope [ & ] ( projectItem ) = >
{
var projectSource = projectItem as ProjectSource ;
var importPath = scope String ( ) ;
projectSource . GetFullImportPath ( importPath ) ;
Result < DateTime > fileDateTime = File . GetLastWriteTime ( importPath ) ;
if ( fileDateTime case . Ok )
{
let date = fileDateTime . Get ( ) . ToFileTime ( ) ;
/ * if ( date > targetDateTime )
Console . WriteLine ( "Custom build higher time: {0}" , importPath ) ; * /
highestDateTime = Math . Max ( highestDateTime , date ) ;
}
} ) ;
if ( ( highestDateTime < = targetDateTime ) & & ( ! forceRebuild ) )
return . NoCommands ;
project . mLastDidBuild = true ;
}
Workspace . Options workspaceOptions = gApp . GetCurWorkspaceOptions ( ) ;
Project . Options options = gApp . GetCurProjectOptions ( project ) ;
bool didCommands = false ;
2021-02-25 10:14:22 -08:00
//let targetName = scope String("Project ", project.mProjectName);
2019-08-27 08:04:41 -07:00
//Console.WriteLine("Executing custom command {0} {1} {2}", highestDateTime, targetDateTime, forceRebuild);
for ( let origCustomCmd in cmdList )
{
bool isCommand = false ;
for ( let c in origCustomCmd . RawChars )
{
2020-06-22 08:49:23 -07:00
if ( ( c = = '\"' ) | | ( c = = '$' ) | | ( c = = '\n' ) )
2019-08-27 08:04:41 -07:00
break ;
if ( c = = '(' )
isCommand = true ;
}
String customCmd = scope String ( ) ;
if ( isCommand )
{
customCmd . Append ( origCustomCmd ) ;
}
else
{
customCmd . Append ( "%exec " ) ;
2019-10-14 17:49:10 -07:00
gApp . ResolveConfigString ( gApp . mPlatformName , workspaceOptions , project , options , origCustomCmd , "custom command" , customCmd ) ;
2020-06-22 08:49:23 -07:00
// For multi-line execs
customCmd . Replace ( '\n' , '\v' ) ;
2019-08-27 08:04:41 -07:00
}
if ( customCmd . IsWhiteSpace )
continue ;
if ( mScriptManager = = null )
{
2020-05-21 11:47:15 -07:00
mScriptManager = new . ( mScriptContext ) ;
2020-01-06 13:49:35 -08:00
mScriptManager . mIsBuildScript = true ;
2019-08-27 08:04:41 -07:00
mScriptManager . mSoftFail = true ;
mScriptManager . mVerbosity = gApp . mVerbosity ;
didCommands = true ;
}
2021-02-25 10:14:22 -08:00
let scriptCmd = new IDEApp . ScriptCmd ( ) ;
scriptCmd . mCmd = new String ( customCmd ) ;
scriptCmd . mPath = new $"project {project.mProjectName}" ;
gApp . mExecutionQueue . Add ( scriptCmd ) ;
2019-08-27 08:04:41 -07:00
continue ;
}
2019-08-29 14:19:07 -07:00
return didCommands ? . HadCommands : . NoCommands ;
2019-08-27 08:04:41 -07:00
}
2019-10-23 07:12:36 -07:00
bool QueueProjectGNUArchive ( Project project , String targetPath , Workspace . Options workspaceOptions , Project . Options options , String objectsArg )
{
#if BF_PLATFORM_WINDOWS
String llvmDir = scope String ( IDEApp . sApp . mInstallDir ) ;
IDEUtils . FixFilePath ( llvmDir ) ;
llvmDir . Append ( "llvm/" ) ;
#else
2019-11-26 13:11:17 -08:00
//String llvmDir = "";
2019-10-23 07:12:36 -07:00
#endif
//String error = scope String();
2020-09-27 22:20:26 -07:00
bool isTest = options . mBuildOptions . mBuildKind = = . Test ;
bool isExe = ( ( project . mGeneralOptions . mTargetType ! = Project . TargetType . BeefLib ) & & ( project . mGeneralOptions . mTargetType ! = Project . TargetType . BeefTest ) ) | | ( isTest ) ;
2021-06-29 06:02:15 -07:00
if ( ( options . mBuildOptions . mBuildKind = = . StaticLib ) | | ( options . mBuildOptions . mBuildKind = = . DynamicLib ) )
{
// Okay
}
else if ( ! isExe )
2019-10-23 07:12:36 -07:00
return true ;
2022-03-01 12:57:22 -08:00
String projectBuildDir = scope String ( ) ;
gApp . GetProjectBuildDir ( project , projectBuildDir ) ;
File . WriteAll ( scope $"{projectBuildDir}/ObjectArgs.txt" , . ( ( . ) objectsArg . Ptr , objectsArg . Length ) ) . IgnoreError ( ) ;
2022-11-07 09:57:27 -08:00
String arCmds = null ; //-O2 -Rpass=inline
2019-10-23 07:12:36 -07:00
//(doClangCPP ? "-lc++abi " : "") +
2022-11-07 09:57:27 -08:00
String arArgs = scope . ( ) ;
2019-10-23 07:12:36 -07:00
2022-11-07 09:57:27 -08:00
bool useArCmds = false ;
2024-11-03 06:33:06 -05:00
if ( objectsArg . Contains ( ".lib" , true ) )
useArCmds = true ;
2022-11-07 09:57:27 -08:00
if ( useArCmds )
2021-07-01 12:42:03 -07:00
{
2022-11-07 09:57:27 -08:00
arCmds = scope : : String ( "" ) ;
arCmds . AppendF ( "CREATE {}\n" , targetPath ) ;
2021-07-01 12:42:03 -07:00
2022-11-07 09:57:27 -08:00
void AddObject ( StringView obj )
{
if ( obj . IsEmpty )
return ;
2021-07-01 12:42:03 -07:00
2022-11-07 09:57:27 -08:00
if ( obj . EndsWith ( ".lib" , . OrdinalIgnoreCase ) )
arCmds . AppendF ( "ADDLIB {}\n" , obj ) ;
else
arCmds . AppendF ( "ADDMOD {}\n" , obj ) ;
}
bool inQuote = false ;
int lastEnd = - 1 ;
for ( int i < objectsArg . Length )
2021-07-01 12:42:03 -07:00
{
2022-11-07 09:57:27 -08:00
var c = objectsArg [ i ] ;
if ( c = = '"' )
{
if ( inQuote )
AddObject ( objectsArg . Substring ( lastEnd + 1 , i - lastEnd - 1 ) ) ;
inQuote = ! inQuote ;
lastEnd = i ;
}
else if ( ( c = = ' ' ) & & ( ! inQuote ) )
{
2021-07-01 12:42:03 -07:00
AddObject ( objectsArg . Substring ( lastEnd + 1 , i - lastEnd - 1 ) ) ;
2022-11-07 09:57:27 -08:00
lastEnd = i ;
}
2021-07-01 12:42:03 -07:00
}
2022-11-07 09:57:27 -08:00
AddObject ( objectsArg . Substring ( lastEnd + 1 ) ) ;
for ( let obj in objectsArg . Split ( ' ' ) )
2021-07-01 12:42:03 -07:00
{
2022-11-07 09:57:27 -08:00
if ( ! obj . IsEmpty )
{
}
2021-07-01 12:42:03 -07:00
}
2022-11-07 09:57:27 -08:00
arCmds . AppendF ( "SAVE\n" ) ;
2021-07-01 12:42:03 -07:00
}
2022-11-07 09:57:27 -08:00
else
2019-10-23 07:12:36 -07:00
{
2023-02-07 13:07:14 -08:00
arArgs . AppendF ( $"-qc " ) ;
String fixedTargetPath = scope . ( targetPath ) ;
IDEUtils . FixFilePath ( fixedTargetPath ) ;
#if BF_PLATFORM_WINDOWS
fixedTargetPath . Replace ( "\\" , "\\\\" ) ;
#endif
IDEUtils . AppendWithOptionalQuotes ( arArgs , fixedTargetPath ) ;
2022-11-07 09:57:27 -08:00
void AddObject ( StringView obj )
2019-10-23 07:12:36 -07:00
{
2022-11-07 09:57:27 -08:00
if ( obj . IsEmpty )
return ;
arArgs . Append ( " " ) ;
2023-02-07 13:07:14 -08:00
String fixedObjPath = scope . ( obj ) ;
IDEUtils . FixFilePath ( fixedObjPath ) ;
#if BF_PLATFORM_WINDOWS
fixedObjPath . Replace ( "\\" , "\\\\" ) ;
#endif
IDEUtils . AppendWithOptionalQuotes ( arArgs , fixedObjPath ) ;
2019-10-23 07:12:36 -07:00
}
2022-11-07 09:57:27 -08:00
bool inQuote = false ;
int lastEnd = - 1 ;
for ( int i < objectsArg . Length )
{
var c = objectsArg [ i ] ;
if ( c = = '"' )
{
if ( inQuote )
AddObject ( objectsArg . Substring ( lastEnd + 1 , i - lastEnd - 1 ) ) ;
inQuote = ! inQuote ;
lastEnd = i ;
}
else if ( ( c = = ' ' ) & & ( ! inQuote ) )
{
AddObject ( objectsArg . Substring ( lastEnd + 1 , i - lastEnd - 1 ) ) ;
lastEnd = i ;
}
}
AddObject ( objectsArg . Substring ( lastEnd + 1 ) ) ;
2019-10-23 07:12:36 -07:00
}
2022-02-08 17:02:35 -05:00
UpdateCacheStr ( project , "" , workspaceOptions , options , null , null ) ;
2019-10-23 07:12:36 -07:00
if ( project . mNeedsTargetRebuild )
{
if ( File . Delete ( targetPath ) case . Err )
{
gApp . OutputLine ( "Failed to delete {0}" , targetPath ) ;
return false ;
}
String arPath = scope . ( ) ;
#if BF_PLATFORM_WINDOWS
arPath . Clear ( ) ;
arPath . Append ( gApp . mInstallDir ) ;
arPath . Append ( @"llvm\bin\llvm-ar.exe" ) ;
2019-10-29 05:01:04 -07:00
#elif BF_PLATFORM_MACOS
arPath . Append ( "llvm/bin/llvm-ar" ) ;
2019-10-23 07:12:36 -07:00
#else
arPath . Append ( "/usr/bin/ar" ) ;
#endif
String workingDir = scope String ( ) ;
workingDir . Append ( gApp . mInstallDir ) ;
String scriptPath = scope . ( ) ;
if ( Path . GetTempFileName ( scriptPath ) case . Err )
{
return false ;
}
if ( File . WriteAllText ( scriptPath , arCmds ) case . Err )
{
gApp . OutputLine ( "Failed to write archive script {0}" , scriptPath ) ;
return false ;
}
2022-11-07 09:57:27 -08:00
if ( arCmds ! = null )
arArgs . Append ( "-M" ) ;
var runCmd = gApp . QueueRun ( arPath , arArgs , workingDir , . UTF8 ) ;
2022-03-01 12:57:22 -08:00
runCmd . mReference = new String ( project . mProjectName ) ;
2019-10-23 07:12:36 -07:00
runCmd . mOnlyIfNotFailed = true ;
2022-11-07 09:57:27 -08:00
if ( arCmds ! = null )
runCmd . mStdInData = new . ( arCmds ) ;
2019-10-23 07:12:36 -07:00
var tagetCompletedCmd = new IDEApp . TargetCompletedCmd ( project ) ;
tagetCompletedCmd . mOnlyIfNotFailed = true ;
gApp . mExecutionQueue . Add ( tagetCompletedCmd ) ;
project . mLastDidBuild = true ;
}
2021-07-19 10:50:31 -07:00
else
{
var tagetCompletedCmd = new IDEApp . TargetCompletedCmd ( project ) ;
tagetCompletedCmd . mOnlyIfNotFailed = true ;
gApp . mExecutionQueue . Add ( tagetCompletedCmd ) ;
}
2019-10-23 07:12:36 -07:00
return true ;
}
2020-06-23 07:33:43 -07:00
void WSLPathFix ( String str )
{
for ( int i = 1 ; i < str . Length - 1 ; i + + )
{
if ( str [ i ] = = ':' )
{
if ( str [ i - 1 ] . IsLetter )
{
int j = i ;
for ( ; j < str . Length ; j + + )
{
char8 cj = str [ j ] ;
if ( cj = = '\\' )
str [ j ] = '/' ;
if ( ( cj . IsWhiteSpace ) | | ( cj = = '"' ) )
break ;
}
str . Remove ( i ) ;
str [ i - 1 ] = str [ i - 1 ] . ToLower ;
str . Insert ( i - 1 , "/mnt/" ) ;
}
}
}
}
2019-08-27 08:04:41 -07:00
bool QueueProjectGNULink ( Project project , String targetPath , Workspace . Options workspaceOptions , Project . Options options , String objectsArg )
{
2022-01-14 06:23:36 -05:00
if ( options . mBuildOptions . mBuildKind = = . Intermediate )
return true ;
2019-08-27 08:04:41 -07:00
bool isDebug = gApp . mConfigName . IndexOf ( "Debug" , true ) ! = - 1 ;
2020-06-23 07:33:43 -07:00
bool isMinGW = false ;
2019-08-27 08:04:41 -07:00
#if BF_PLATFORM_WINDOWS
2020-06-23 07:33:43 -07:00
bool isWSL = mPlatformType = = . Linux ;
2019-08-27 08:04:41 -07:00
String llvmDir = scope String ( IDEApp . sApp . mInstallDir ) ;
IDEUtils . FixFilePath ( llvmDir ) ;
llvmDir . Append ( "llvm/" ) ;
#else
String llvmDir = "" ;
2020-06-23 07:33:43 -07:00
bool isWSL = false ;
2019-08-27 08:04:41 -07:00
#endif
//String error = scope String();
2020-09-27 22:20:26 -07:00
bool isTest = options . mBuildOptions . mBuildKind = = . Test ;
bool isExe = ( ( project . mGeneralOptions . mTargetType ! = Project . TargetType . BeefLib ) & & ( project . mGeneralOptions . mTargetType ! = Project . TargetType . BeefTest ) ) | | ( isTest ) ;
2021-06-28 09:44:47 -07:00
bool isDynLib = ( project . mGeneralOptions . mTargetType = = Project . TargetType . BeefLib ) & & ( options . mBuildOptions . mBuildKind = = . DynamicLib ) ;
2020-06-30 12:13:20 -07:00
2021-06-28 05:47:37 -07:00
if ( options . mBuildOptions . mBuildKind = = . StaticLib )
isExe = false ;
2020-06-30 12:13:20 -07:00
if ( isExe | | isDynLib )
2019-08-27 08:04:41 -07:00
{
2019-10-15 17:27:09 -07:00
CopyLibFiles ( targetPath , workspaceOptions , options ) ;
2019-08-27 08:04:41 -07:00
String linkLine = scope String ( isDebug ? "-g " : "-g -O2 " ) ; //-O2 -Rpass=inline
//(doClangCPP ? "-lc++abi " : "") +
linkLine . Append ( "-o " ) ;
IDEUtils . AppendWithOptionalQuotes ( linkLine , targetPath ) ;
linkLine . Append ( " " ) ;
/ * if ( options . mBuildOptions . mLinkerType = = Project . LinkerType . GCC )
{
// ...
}
else
{
linkLine . Append ( "--target=" ) ;
GetTargetName ( workspaceOptions , linkLine ) ;
linkLine . Append ( " " ) ;
} * /
2020-06-30 12:13:20 -07:00
if ( isDynLib )
{
linkLine . Append ( "-shared " ) ;
}
2020-05-04 15:06:05 -07:00
if ( ( mPlatformType = = . Windows ) & &
( ( project . mGeneralOptions . mTargetType = = Project . TargetType . BeefGUIApplication ) | |
( project . mGeneralOptions . mTargetType = = Project . TargetType . C_GUIApplication ) ) )
2019-08-27 08:04:41 -07:00
{
linkLine . Append ( "-mwindows " ) ;
}
2019-10-15 12:28:21 -07:00
if ( mPlatformType = = . Linux )
linkLine . Append ( "-no-pie " ) ;
2019-08-27 08:04:41 -07:00
2020-05-21 13:30:30 -07:00
if ( mPlatformType = = . macOS )
linkLine . Append ( "-Wl,-no_compact_unwind " ) ;
2019-08-27 08:04:41 -07:00
linkLine . Append ( objectsArg ) ;
//var destDir = scope String();
//Path.GetDirectoryName();
//TODO: Make an option
if ( options . mBuildOptions . mCLibType = = Project . CLibType . Static )
{
2021-05-31 08:50:17 -07:00
if ( mPlatformType ! = . macOS )
linkLine . Append ( "-static-libgcc " ) ;
linkLine . Append ( "-static-libstdc++ " ) ;
2019-08-27 08:04:41 -07:00
}
else
{
2020-06-23 07:33:43 -07:00
if ( isMinGW )
{
String [ ] mingwFiles ;
String fromDir ;
if ( mPtrSize = = 4 )
{
fromDir = scope : : String ( llvmDir , "i686-w64-mingw32/bin/" ) ;
2020-08-29 11:56:10 -07:00
mingwFiles = scope : : String [ ] ( "libgcc_s_dw2-1.dll" , "libstdc++-6.dll" ) ;
2020-06-23 07:33:43 -07:00
}
else
{
fromDir = scope : : String ( llvmDir , "x86_64-w64-mingw32/bin/" ) ;
2020-08-29 11:56:10 -07:00
mingwFiles = scope : : String [ ] ( "libgcc_s_seh-1.dll" , "libstdc++-6.dll" , "libwinpthread-1.dll" ) ;
2020-06-23 07:33:43 -07:00
}
for ( var mingwFile in mingwFiles )
{
String fromPath = scope String ( fromDir , mingwFile ) ;
//string toPath = projectBuildDir + "/" + mingwFile;
String toPath = scope String ( ) ;
Path . GetDirectoryPath ( targetPath , toPath ) ;
toPath . Append ( "/" , mingwFile ) ;
if ( ! File . Exists ( toPath ) )
2019-08-27 08:04:41 -07:00
{
2020-06-23 07:33:43 -07:00
if ( File . Copy ( fromPath , toPath ) case . Err )
{
gApp . OutputLineSmart ( "ERROR: Failed to copy mingw file {0}" , fromPath ) ;
return false ;
}
2019-08-27 08:04:41 -07:00
}
2020-06-23 07:33:43 -07:00
}
}
2019-08-27 08:04:41 -07:00
}
2020-07-01 05:29:25 -07:00
List < String > libPaths = scope . ( ) ;
defer ClearAndDeleteItems ( libPaths ) ;
List < String > depPaths = scope . ( ) ;
defer ClearAndDeleteItems ( depPaths ) ;
AddLinkDeps ( project , options , workspaceOptions , linkLine , libPaths , depPaths ) ;
for ( var libPath in libPaths )
{
IDEUtils . AppendWithOptionalQuotes ( linkLine , libPath ) ;
linkLine . Append ( " " ) ;
}
2019-08-27 08:04:41 -07:00
2020-06-23 07:33:43 -07:00
String gccExePath ;
String clangExePath ;
if ( isMinGW )
{
gccExePath = "c:/mingw/bin/g++.exe" ;
clangExePath = scope String ( llvmDir , "bin/clang++.exe" ) ;
}
else
{
gccExePath = "/usr/bin/c++" ;
clangExePath = scope String ( "/usr/bin/c++" ) ;
if ( File . Exists ( "/usr/bin/clang++" ) )
{
gccExePath = "/usr/bin/clang++" ;
clangExePath = scope String ( "/usr/bin/clang++" ) ;
}
else
{
gccExePath = "/usr/bin/c++" ;
clangExePath = scope String ( "/usr/bin/c++" ) ;
}
}
2019-08-27 08:04:41 -07:00
2022-02-08 17:02:35 -05:00
UpdateCacheStr ( project , linkLine , workspaceOptions , options , depPaths , libPaths ) ;
2019-08-27 08:04:41 -07:00
if ( project . mNeedsTargetRebuild )
{
if ( File . Delete ( targetPath ) case . Err )
{
gApp . OutputLine ( "Failed to delete {0}" , targetPath ) ;
return false ;
}
if ( workspaceOptions . mToolsetType = = . GNU )
{
2019-10-15 12:28:21 -07:00
if ( mPtrSize = = 4 )
2019-08-27 08:04:41 -07:00
{
}
else
{
2019-10-17 06:47:50 -07:00
/ * IDEUtils . AppendWithOptionalQuotes ( linkLine , scope String ( "-L" , llvmDir , "/x86_64-w64-mingw32/lib" ) ) ;
2019-08-27 08:04:41 -07:00
linkLine . Append ( " " ) ;
IDEUtils . AppendWithOptionalQuotes ( linkLine , scope String ( "-L" , llvmDir , "/lib/gcc/x86_64-w64-mingw32/5.2.0" ) ) ;
2019-10-17 06:47:50 -07:00
linkLine . Append ( " " ) ; * /
2019-08-27 08:04:41 -07:00
}
}
else // Microsoft
{
2019-10-15 12:28:21 -07:00
if ( mPtrSize = = 4 )
2019-08-27 08:04:41 -07:00
{
//linkLine.Append("-L\"C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.10586.0\\ucrt\\x86\" ");
for ( var libPath in gApp . mSettings . mVSSettings . mLib32Paths )
{
linkLine . AppendF ( "-L\"{0}\" " , libPath ) ;
}
}
else
{
/ * linkLine . Append ( "-L\"C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\lib\\amd64\" " ) ;
linkLine . Append ( "-L\"C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\atlmfc\\lib\\amd64\" " ) ;
linkLine . Append ( "-L\"C:\\Program Files (x86)\\Windows Kits\\10\\lib\\10.0.14393.0\\ucrt\\x64\" " ) ;
linkLine . Append ( "-L\"C:\\Program Files (x86)\\Windows Kits\\10\\lib\\10.0.14393.0\\um\\x64\" " ) ; * /
for ( var libPath in gApp . mSettings . mVSSettings . mLib64Paths )
{
linkLine . AppendF ( "-L\"{0}\" " , libPath ) ;
}
}
}
if ( options . mBuildOptions . mOtherLinkFlags . Length ! = 0 )
{
var linkFlags = scope String ( ) ;
2019-10-14 17:49:10 -07:00
gApp . ResolveConfigString ( gApp . mPlatformName , workspaceOptions , project , options , options . mBuildOptions . mOtherLinkFlags , "link flags" , linkFlags ) ;
2019-08-27 08:04:41 -07:00
linkLine . Append ( linkFlags , " " ) ;
}
String compilerExePath = ( workspaceOptions . mToolsetType = = . GNU ) ? gccExePath : clangExePath ;
String workingDir = scope String ( ) ;
if ( ! llvmDir . IsEmpty )
{
workingDir . Append ( llvmDir , "bin" ) ;
}
else
{
workingDir . Append ( gApp . mInstallDir ) ;
}
2020-06-23 07:33:43 -07:00
if ( isWSL )
{
linkLine . Insert ( 0 , " " ) ;
linkLine . Insert ( 0 , compilerExePath ) ;
compilerExePath = "wsl.exe" ;
WSLPathFix ( linkLine ) ;
}
2019-08-27 08:04:41 -07:00
var runCmd = gApp . QueueRun ( compilerExePath , linkLine , workingDir , . UTF8 ) ;
2022-03-01 12:57:22 -08:00
runCmd . mReference = new . ( project . mProjectName ) ;
2019-08-27 08:04:41 -07:00
runCmd . mOnlyIfNotFailed = true ;
var tagetCompletedCmd = new IDEApp . TargetCompletedCmd ( project ) ;
tagetCompletedCmd . mOnlyIfNotFailed = true ;
gApp . mExecutionQueue . Add ( tagetCompletedCmd ) ;
String logStr = scope String ( ) ;
logStr . AppendF ( "IDE Process {0}\r\n" , Platform . BfpProcess_GetCurrentId ( ) ) ;
logStr . Append ( linkLine ) ;
String targetLogPath = scope String ( targetPath , ".build.txt" ) ;
2020-06-16 08:30:02 -07:00
if ( Utils . WriteTextFile ( targetLogPath , logStr ) case . Err )
gApp . OutputErrorLine ( "Failed to write {}" , targetLogPath ) ;
2019-08-27 08:04:41 -07:00
project . mLastDidBuild = true ;
}
}
2021-07-19 10:50:31 -07:00
else
{
var tagetCompletedCmd = new IDEApp . TargetCompletedCmd ( project ) ;
tagetCompletedCmd . mOnlyIfNotFailed = true ;
gApp . mExecutionQueue . Add ( tagetCompletedCmd ) ;
}
2019-08-27 08:04:41 -07:00
return true ;
}
2020-08-06 09:24:37 -07:00
bool QueueProjectWasmLink ( Project project , String targetPath , Workspace . Options workspaceOptions , Project . Options options , String objectsArg )
{
//bool isDebug = gApp.mConfigName.IndexOf("Debug", true) != -1;
//bool isMinGW = false;
//String error = scope String();
2020-09-27 22:20:26 -07:00
bool isTest = options . mBuildOptions . mBuildKind = = . Test ;
bool isExe = ( ( project . mGeneralOptions . mTargetType ! = Project . TargetType . BeefLib ) & & ( project . mGeneralOptions . mTargetType ! = Project . TargetType . BeefTest ) ) | | ( isTest ) ;
2021-06-28 09:44:47 -07:00
bool isDynLib = ( project . mGeneralOptions . mTargetType = = Project . TargetType . BeefLib ) & & ( options . mBuildOptions . mBuildKind = = . DynamicLib ) ;
2020-08-06 09:24:37 -07:00
2023-07-27 07:15:34 -07:00
if ( workspaceOptions . mToolsetType ! = . GNU )
{
gApp . OutputErrorLine ( "Workspace Build Toolset options must be set to GNU for WASM builds" ) ;
return false ;
}
2020-08-06 09:24:37 -07:00
if ( isExe | | isDynLib )
{
2022-03-24 11:59:00 -07:00
var actualTargetPath = Path . GetActualPathName ( targetPath , . . scope . ( ) ) ;
2020-08-06 09:24:37 -07:00
String linkLine = scope String ( ) ;
linkLine . Append ( "-o " ) ;
2022-03-24 11:59:00 -07:00
IDEUtils . AppendWithOptionalQuotes ( linkLine , actualTargetPath ) ;
2020-08-06 09:24:37 -07:00
linkLine . Append ( " " ) ;
linkLine . Append ( objectsArg ) ;
List < String > libPaths = scope . ( ) ;
defer ClearAndDeleteItems ( libPaths ) ;
List < String > depPaths = scope . ( ) ;
defer ClearAndDeleteItems ( depPaths ) ;
AddLinkDeps ( project , options , workspaceOptions , linkLine , libPaths , depPaths ) ;
for ( var libPath in libPaths )
{
IDEUtils . AppendWithOptionalQuotes ( linkLine , libPath ) ;
linkLine . Append ( " " ) ;
}
2022-02-08 20:07:04 -03:00
if ( options . mBuildOptions . mOtherLinkFlags . Length ! = 0 )
{
var linkFlags = scope String ( ) ;
gApp . ResolveConfigString ( gApp . mPlatformName , workspaceOptions , project , options , options . mBuildOptions . mOtherLinkFlags , "link flags" , linkFlags ) ;
linkLine . Append ( linkFlags , " " ) ;
}
2022-02-08 17:02:35 -05:00
UpdateCacheStr ( project , linkLine , workspaceOptions , options , depPaths , libPaths ) ;
2024-10-18 09:13:24 -04:00
String emsdkPath = scope . ( gApp . mSettings . mEmscriptenPath ) ;
2020-08-06 09:24:37 -07:00
if ( project . mNeedsTargetRebuild )
{
if ( File . Delete ( targetPath ) case . Err )
{
gApp . OutputLine ( "Failed to delete {0}" , targetPath ) ;
return false ;
}
String compilerExePath = scope String ( ) ;
2022-02-08 17:02:35 -05:00
if ( gApp . mSettings . mEmscriptenPath . IsEmpty )
{
2024-10-18 09:13:24 -04:00
// Set for auto-install without prompting
gApp . mSettings . mEmscriptenPendingInstall = true ;
#if CLI
gApp . Fail ( "Emscripten path not configured. Check Wasm configuration in File\\Preferences\\Settings." ) ;
2022-02-08 17:02:35 -05:00
return false ;
2024-10-18 09:13:24 -04:00
#else
if ( gApp . mSettings . mEmscriptenPendingInstall )
{
2024-10-21 09:11:28 -04:00
String wasmPath = Path . GetAbsolutePath ( "../wasm" , gApp . mInstallDir , . . scope . ( ) ) ;
if ( ! Directory . Exists ( wasmPath ) )
Path . GetAbsolutePath ( "../../wasm" , gApp . mInstallDir , wasmPath . . Clear ( ) ) ;
2024-10-18 09:13:24 -04:00
IDEUtils . FixFilePath ( wasmPath ) ;
var runCmd = gApp . QueueRun ( scope $"{wasmPath}/fetch_wasm.bat" , "" , wasmPath , . UTF8 ) ;
runCmd . mOnlyIfNotFailed = true ;
var installedCmd = new IDEApp . EmsdkInstalledCmd ( ) ;
installedCmd . mPath = new $"{wasmPath}/emsdk" ;
IDEUtils . FixFilePath ( installedCmd . mPath ) ;
installedCmd . mOnlyIfNotFailed = true ;
gApp . mExecutionQueue . Add ( installedCmd ) ;
emsdkPath . Set ( installedCmd . mPath ) ;
}
else
{
DarkDialog dlg = new DarkDialog ( "Install Emscripten" , "Beef uses Emscripten for WASM support. Would you like to have that installed or would you like to set it up yourself?" , DarkTheme . sDarkTheme . mIconError ) ;
dlg . mWindowFlags | = . Modal ;
dlg . AddOkCancelButtons ( new ( dlg ) = >
{
gApp . mSettings . mEmscriptenPendingInstall = true ;
gApp . [ Friend ] Compile ( ) ;
} ,
new ( dlg ) = >
{
gApp . OutputErrorLine ( "Emscripten path not configured. Check Wasm configuration in File\\Preferences\\Settings." ) ;
} ) ;
( ( DarkButton ) dlg . mButtons [ 0 ] ) . Label = "Install" ;
( ( DarkButton ) dlg . mButtons [ 1 ] ) . Label = "Cancel" ;
dlg . PopupWindow ( gApp . GetActiveWindow ( ) ) ;
IDEApp . Beep ( . Error ) ;
return false ;
}
#endif
2022-02-08 17:02:35 -05:00
}
2024-10-18 09:13:24 -04:00
compilerExePath . Append ( emsdkPath ) ;
if ( ( ! compilerExePath . EndsWith ( '\\' ) ) & & ( ! compilerExePath . EndsWith ( '/' ) ) )
compilerExePath . Append ( "/" ) ;
2020-08-06 09:24:37 -07:00
2024-10-18 09:13:24 -04:00
if ( ! gApp . mSettings . mEmscriptenPendingInstall )
2020-08-06 09:24:37 -07:00
{
2024-10-18 09:13:24 -04:00
if ( ! File . Exists ( scope $"{gApp.mInstallDir}/Beef{IDEApp.sRTVersionStr}RT32_wasm.a" ) )
{
gApp . OutputErrorLine ( "Wasm runtime libraries not found. Build with 'wasm/build_wasm.bat'." ) ;
return false ;
}
2020-08-06 09:24:37 -07:00
}
2022-02-08 17:02:35 -05:00
compilerExePath . Append ( @"/upstream/emscripten/emcc.bat" ) ;
//linkLine.Append(" c:\\Beef\\wasm\\BeefRT.a -s STRICT=1 -s USE_PTHREADS=1 -s ALIASING_FUNCTION_POINTERS=1 -s ASSERTIONS=0 -s DISABLE_EXCEPTION_CATCHING=0 -s DEMANGLE_SUPPORT=0 -s EVAL_CTORS=1 -s WASM=1 -s \"EXPORTED_FUNCTIONS=['_BeefMain','_BeefDone','_pthread_mutexattr_init','_pthread_mutex_init','_emscripten_futex_wake','_calloc','_sbrk']\"");
2024-10-18 09:13:24 -04:00
linkLine . Append ( "-s DISABLE_EXCEPTION_CATCHING=0" ) ;
2022-02-07 14:28:32 -05:00
2022-02-08 17:02:35 -05:00
if ( project . mWasmOptions . mEnableThreads )
2023-06-15 18:48:56 +04:00
linkLine . Append ( " -pthread" ) ;
2020-08-06 09:24:37 -07:00
2022-02-08 17:02:35 -05:00
if ( workspaceOptions . mEmitDebugInfo ! = . No )
2023-07-27 07:15:34 -07:00
linkLine . Append ( " -gseparate-dwarf" ) ;
2022-02-08 17:02:35 -05:00
2022-02-09 21:38:14 -03:00
if ( ! workspaceOptions . mRuntimeChecks )
linkLine . Append ( " -s ASSERTIONS=0" ) ;
2022-02-08 17:02:35 -05:00
linkLine . Replace ( '\\' , '/' ) ;
2022-03-24 11:59:00 -07:00
var targetDir = Path . GetDirectoryPath ( actualTargetPath , . . scope . ( ) ) ;
var runCmd = gApp . QueueRun ( compilerExePath , linkLine , targetDir , . UTF8 ) ;
2022-03-01 12:57:22 -08:00
runCmd . mReference = new . ( project . mProjectName ) ;
2020-08-06 09:24:37 -07:00
runCmd . mOnlyIfNotFailed = true ;
var tagetCompletedCmd = new IDEApp . TargetCompletedCmd ( project ) ;
tagetCompletedCmd . mOnlyIfNotFailed = true ;
gApp . mExecutionQueue . Add ( tagetCompletedCmd ) ;
String logStr = scope String ( ) ;
logStr . AppendF ( "IDE Process {0}\r\n" , Platform . BfpProcess_GetCurrentId ( ) ) ;
logStr . Append ( linkLine ) ;
String targetLogPath = scope String ( targetPath , ".build.txt" ) ;
if ( Utils . WriteTextFile ( targetLogPath , logStr ) case . Err )
gApp . OutputErrorLine ( "Failed to write {}" , targetLogPath ) ;
project . mLastDidBuild = true ;
}
}
2021-07-19 10:50:31 -07:00
else
{
var tagetCompletedCmd = new IDEApp . TargetCompletedCmd ( project ) ;
tagetCompletedCmd . mOnlyIfNotFailed = true ;
gApp . mExecutionQueue . Add ( tagetCompletedCmd ) ;
}
2020-08-06 09:24:37 -07:00
return true ;
}
2019-08-27 08:04:41 -07:00
public static void GetPdbPath ( String targetPath , Workspace . Options workspaceOptions , Project . Options options , String outPdbPath )
{
int lastDotPos = targetPath . LastIndexOf ( '.' ) ;
2019-09-18 13:02:01 -07:00
if ( lastDotPos = = - 1 )
return ;
2019-08-27 08:04:41 -07:00
outPdbPath . Append ( targetPath , 0 , lastDotPos ) ;
if ( workspaceOptions . mToolsetType = = . LLVM )
outPdbPath . Append ( "_lld" ) ;
outPdbPath . Append ( ".pdb" ) ;
}
2022-06-02 17:57:09 -07:00
public static void GetRtLibNames ( Workspace . PlatformType platformType , Workspace . Options workspaceOptions , Project . Options options , bool dynName , String outRt , String outDbg , String outAlloc )
2024-03-16 07:23:29 -04:00
{
if ( workspaceOptions . mRuntimeKind = = . Disabled )
return ;
2019-10-29 09:06:51 -07:00
if ( ( platformType = = . Linux ) | | ( platformType = = . macOS ) | | ( platformType = = . iOS ) )
2019-10-15 14:39:47 -07:00
{
if ( options . mBuildOptions . mBeefLibType = = . DynamicDebug )
2019-10-29 05:01:04 -07:00
outRt . Append ( "libBeefRT_d.a" ) ;
2019-10-15 14:39:47 -07:00
else
2019-10-29 05:01:04 -07:00
outRt . Append ( "libBeefRT.a" ) ;
2019-10-15 14:39:47 -07:00
return ;
}
2019-08-27 08:04:41 -07:00
if ( ( ! dynName ) | | ( options . mBuildOptions . mBeefLibType ! = . Static ) )
{
outRt . Append ( "Beef" , IDEApp . sRTVersionStr , "RT" ) ;
2019-10-14 17:49:10 -07:00
outRt . Append ( ( Workspace . PlatformType . GetPtrSizeByName ( gApp . mPlatformName ) = = 4 ) ? "32" : "64" ) ;
2019-08-27 08:04:41 -07:00
switch ( options . mBuildOptions . mBeefLibType )
{
case . Dynamic :
case . DynamicDebug : outRt . Append ( "_d" ) ;
case . Static :
switch ( options . mBuildOptions . mCLibType )
{
case . None :
case . Dynamic , . SystemMSVCRT : outRt . Append ( "_s" ) ;
case . DynamicDebug : outRt . Append ( "_sd" ) ;
case . Static : outRt . Append ( "_ss" ) ;
case . StaticDebug : outRt . Append ( "_ssd" ) ;
}
}
outRt . Append ( dynName ? ".dll" : ".lib" ) ;
}
2023-10-10 20:09:17 +04:00
if ( ( workspaceOptions . mEnableObjectDebugFlags )
| | ( workspaceOptions . mAllocType = = . Debug )
| | ( workspaceOptions . mAllocType = = . Stomp )
| | ( workspaceOptions . mAllocStackTraceDepth > 0 ) )
2019-08-27 08:04:41 -07:00
{
outDbg . Append ( "Beef" , IDEApp . sRTVersionStr , "Dbg" ) ;
2019-10-14 17:49:10 -07:00
outDbg . Append ( ( Workspace . PlatformType . GetPtrSizeByName ( gApp . mPlatformName ) = = 4 ) ? "32" : "64" ) ;
2019-08-27 08:04:41 -07:00
if ( options . mBuildOptions . mBeefLibType = = . DynamicDebug )
outDbg . Append ( "_d" ) ;
outDbg . Append ( dynName ? ".dll" : ".lib" ) ;
}
2022-06-02 17:57:09 -07:00
if ( ( workspaceOptions . mAllocType = = . TCMalloc ) | | ( workspaceOptions . mAllocType = = . TCMalloc_Debug ) | |
( workspaceOptions . mAllocType = = . JEMalloc ) | | ( workspaceOptions . mAllocType = = . JEMalloc_Debug ) )
{
outAlloc . Append ( ( ( workspaceOptions . mAllocType = = . TCMalloc ) | | ( workspaceOptions . mAllocType = = . TCMalloc_Debug ) ) ? "TCMalloc" : "JEMalloc" ) ;
outAlloc . Append ( ( Workspace . PlatformType . GetPtrSizeByName ( gApp . mPlatformName ) = = 4 ) ? "32" : "64" ) ;
if ( ( workspaceOptions . mAllocType = = . TCMalloc_Debug ) | | ( workspaceOptions . mAllocType = = . JEMalloc_Debug ) )
outAlloc . Append ( "_d" ) ;
outAlloc . Append ( dynName ? ".dll" : ".lib" ) ;
}
2019-08-27 08:04:41 -07:00
}
2019-10-15 14:39:47 -07:00
bool CopyLibFiles ( String targetPath , Workspace . Options workspaceOptions , Project . Options options )
{
List < String > stdLibFileNames = scope . ( 2 ) ;
String fromDir ;
fromDir = scope String ( gApp . mInstallDir ) ;
bool AddLib ( String dllName )
{
stdLibFileNames . Add ( dllName ) ;
String fromPath = scope String ( fromDir , dllName ) ;
String toPath = scope String ( ) ;
Path . GetDirectoryPath ( targetPath , toPath ) ;
toPath . Append ( "/" , dllName ) ;
2019-10-15 17:27:09 -07:00
if ( File . CopyIfNewer ( fromPath , toPath ) case . Err ( let err ) )
2019-10-15 14:39:47 -07:00
{
2019-10-15 17:27:09 -07:00
gApp . OutputLine ( "Failed to copy lib file '{0}' to '{1}'" , fromPath , toPath ) ;
2019-10-15 14:39:47 -07:00
return false ;
}
return true ;
}
String rtName = scope String ( ) ;
String dbgName = scope String ( ) ;
2022-06-02 17:57:09 -07:00
String allocName = scope String ( ) ;
GetRtLibNames ( mPlatformType , workspaceOptions , options , true , rtName , dbgName , allocName ) ;
2019-10-15 14:39:47 -07:00
if ( ! rtName . IsEmpty )
if ( ! AddLib ( rtName ) )
return false ;
if ( ! dbgName . IsEmpty )
if ( ! AddLib ( dbgName ) )
return false ;
2022-06-02 17:57:09 -07:00
if ( ! allocName . IsEmpty )
if ( ! AddLib ( allocName ) )
2019-10-15 14:39:47 -07:00
return false ;
return true ;
}
2020-07-01 05:29:25 -07:00
void AddLinkDeps ( Project project , Project . Options options , Workspace . Options workspaceOptions , String linkLine , List < String > libPaths , List < String > depPaths )
{
void AddLibPath ( StringView libPathIn , Project project , Project . Options projectOptions )
{
var libPath = new String ( ) ;
if ( gApp . ResolveConfigString ( gApp . mPlatformName , workspaceOptions , project , projectOptions , libPathIn , "lib paths" , libPath ) )
{
IDEUtils . FixFilePath ( libPath ) ;
libPaths . Add ( libPath ) ;
}
2022-08-24 14:49:05 -07:00
else
delete libPath ;
2020-07-01 05:29:25 -07:00
}
defer ClearAndDeleteItems ( depPaths ) ;
void AddDepPath ( StringView depPathIn , Project project , Project . Options projectOptions )
{
var depPath = new String ( ) ;
if ( gApp . ResolveConfigString ( gApp . mPlatformName , workspaceOptions , project , projectOptions , depPathIn , "dep paths" , depPath ) )
{
IDEUtils . FixFilePath ( depPath ) ;
depPaths . Add ( depPath ) ;
}
2022-08-24 14:49:05 -07:00
else
delete depPath ;
2020-07-01 05:29:25 -07:00
}
for ( let libPath in options . mBuildOptions . mLibPaths )
AddLibPath ( libPath , project , options ) ;
for ( let depPath in options . mBuildOptions . mLinkDependencies )
AddDepPath ( depPath , project , options ) ;
List < Project > depProjectList = scope List < Project > ( ) ;
gApp . GetDependentProjectList ( project , depProjectList ) ;
if ( depProjectList . Count > 0 )
{
for ( var depProject in depProjectList )
{
var depOptions = gApp . GetCurProjectOptions ( depProject ) ;
if ( depOptions ! = null )
{
if ( depOptions . mClangObjectFiles ! = null )
{
var argBuilder = scope IDEApp . ArgBuilder ( linkLine , true ) ;
for ( var fileName in depOptions . mClangObjectFiles )
{
argBuilder . AddFileName ( fileName ) ;
argBuilder . AddSep ( ) ;
}
}
}
2022-08-26 09:01:40 -07:00
bool depIsDynLib = ( depProject . mGeneralOptions . mTargetType = = Project . TargetType . BeefLib ) & & ( depOptions ? . mBuildOptions . mBuildKind = = . DynamicLib ) ;
2021-06-28 09:44:47 -07:00
if ( depIsDynLib )
2020-07-01 05:29:25 -07:00
{
if ( mImpLibMap . TryGetValue ( depProject , var libPath ) )
{
IDEUtils . AppendWithOptionalQuotes ( linkLine , libPath ) ;
linkLine . Append ( " " ) ;
}
}
if ( depProject . mGeneralOptions . mTargetType = = . BeefLib )
{
let depProjectOptions = gApp . GetCurProjectOptions ( depProject ) ;
2022-08-26 09:01:40 -07:00
if ( depProjectOptions ! = null )
{
var linkFlags = scope String ( ) ;
gApp . ResolveConfigString ( gApp . mPlatformName , workspaceOptions , depProject , depProjectOptions , depProjectOptions . mBuildOptions . mOtherLinkFlags , "link flags" , linkFlags ) ;
if ( ! linkFlags . IsWhiteSpace )
linkLine . Append ( linkFlags , " " ) ;
for ( let libPath in depProjectOptions . mBuildOptions . mLibPaths )
AddLibPath ( libPath , depProject , depProjectOptions ) ;
for ( let depPath in depProjectOptions . mBuildOptions . mLinkDependencies )
AddDepPath ( depPath , depProject , depProjectOptions ) ;
}
2020-07-01 05:29:25 -07:00
}
}
}
}
2022-02-08 17:02:35 -05:00
void UpdateCacheStr ( Project project , StringView linkLine , Workspace . Options workspaceOptions , Project . Options options , List < String > depPaths , List < String > libPaths )
{
String cacheStr = scope String ( ) ;
void AddBuildFileDependency ( StringView filePath , bool resolveString = false )
{
var filePath ;
if ( ( resolveString ) & & ( filePath . Contains ( '$' ) ) )
{
String resolvedFilePath = scope : : String ( ) ;
gApp . ResolveConfigString ( gApp . mPlatformName , workspaceOptions , project , options , filePath , "link flags" , resolvedFilePath ) ;
filePath = resolvedFilePath ;
}
int64 fileTime = 0 ;
if ( ! filePath . IsEmpty )
fileTime = File . GetLastWriteTime ( filePath ) . GetValueOrDefault ( ) . ToFileTime ( ) ;
cacheStr . AppendF ( "{}\t{}\n" , filePath , fileTime ) ;
}
cacheStr . AppendF ( "Args\t{}\n" , linkLine ) ;
cacheStr . AppendF ( "Toolset\t{}\n" , workspaceOptions . mToolsetType ) ;
AddBuildFileDependency ( project . mWindowsOptions . mIconFile ) ;
AddBuildFileDependency ( project . mWindowsOptions . mManifestFile ) ;
switch ( mPlatformType )
{
case . Windows :
cacheStr . AppendF ( "Description\t{}\n" , project . mWindowsOptions . mDescription ) ;
cacheStr . AppendF ( "Comments\t{}\n" , project . mWindowsOptions . mComments ) ;
cacheStr . AppendF ( "Company\t{}\n" , project . mWindowsOptions . mCompany ) ;
cacheStr . AppendF ( "Product\t{}\n" , project . mWindowsOptions . mProduct ) ;
cacheStr . AppendF ( "Copyright\t{}\n" , project . mWindowsOptions . mCopyright ) ;
cacheStr . AppendF ( "FileVersion\t{}\n" , project . mWindowsOptions . mFileVersion ) ;
cacheStr . AppendF ( "ProductVersion\t{}\n" , project . mWindowsOptions . mProductVersion ) ;
case . Linux :
cacheStr . AppendF ( "Options\t{}\n" , project . mLinuxOptions . mOptions ) ;
case . Wasm :
cacheStr . AppendF ( "EnableThreads\t{}\n" , project . mWasmOptions . mEnableThreads ) ;
default :
}
if ( depPaths ! = null )
for ( var linkDep in depPaths )
AddBuildFileDependency ( linkDep , true ) ;
if ( libPaths ! = null )
for ( var linkDep in libPaths )
AddBuildFileDependency ( linkDep , true ) ;
String projectBuildDir = scope String ( ) ;
gApp . GetProjectBuildDir ( project , projectBuildDir ) ;
String prevCacheStr = scope . ( ) ;
gApp . mBfBuildCompiler . GetBuildValue ( projectBuildDir , "Link" , prevCacheStr ) ;
if ( prevCacheStr ! = cacheStr )
{
project . mNeedsTargetRebuild = true ;
gApp . mBfBuildCompiler . SetBuildValue ( projectBuildDir , "Link" , cacheStr ) ;
gApp . mBfBuildCompiler . WriteBuildCache ( projectBuildDir ) ;
}
}
2019-08-27 08:04:41 -07:00
bool QueueProjectMSLink ( Project project , String targetPath , String configName , Workspace . Options workspaceOptions , Project . Options options , String objectsArg )
{
2022-05-02 08:58:03 -07:00
if ( options . mBuildOptions . mBuildKind = = . Intermediate )
return true ;
2019-10-15 12:28:21 -07:00
bool is64Bit = mPtrSize = = 8 ;
2019-10-14 17:49:10 -07:00
2019-08-27 08:04:41 -07:00
String llvmDir = scope String ( IDEApp . sApp . mInstallDir ) ;
IDEUtils . FixFilePath ( llvmDir ) ;
llvmDir . Append ( "llvm/" ) ;
2020-09-27 22:20:26 -07:00
bool isTest = options . mBuildOptions . mBuildKind = = . Test ;
bool isExe = ( ( project . mGeneralOptions . mTargetType ! = Project . TargetType . BeefLib ) & & ( project . mGeneralOptions . mTargetType ! = Project . TargetType . BeefTest ) ) | | ( isTest ) ;
2021-06-28 09:44:47 -07:00
if ( options . mBuildOptions . mBuildKind = = . DynamicLib )
isExe = true ;
2021-06-29 06:02:15 -07:00
2019-08-27 08:04:41 -07:00
if ( isExe )
{
String linkLine = scope String ( ) ;
linkLine . Append ( "-out:" ) ;
IDEUtils . AppendWithOptionalQuotes ( linkLine , targetPath ) ;
linkLine . Append ( " " ) ;
2020-09-27 22:20:26 -07:00
if ( isTest )
2019-08-27 08:04:41 -07:00
linkLine . Append ( "-subsystem:console " ) ;
2020-03-21 07:10:16 -07:00
else if ( project . mGeneralOptions . mTargetType = = . BeefGUIApplication )
2019-08-27 08:04:41 -07:00
linkLine . Append ( "-subsystem:windows " ) ;
2020-03-21 07:10:16 -07:00
else if ( project . mGeneralOptions . mTargetType = = . C_GUIApplication )
2019-08-27 08:04:41 -07:00
linkLine . Append ( "-subsystem:console " ) ;
2021-06-28 09:44:47 -07:00
else if ( project . mGeneralOptions . mTargetType = = . BeefLib )
2019-08-27 08:04:41 -07:00
{
linkLine . Append ( "-dll " ) ;
if ( targetPath . EndsWith ( ".dll" , . InvariantCultureIgnoreCase ) )
{
linkLine . Append ( "-implib:\"" ) ;
linkLine . Append ( targetPath , 0 , targetPath . Length - 4 ) ;
linkLine . Append ( ".lib\" " ) ;
}
}
linkLine . Append ( objectsArg ) ;
2019-10-15 14:39:47 -07:00
CopyLibFiles ( targetPath , workspaceOptions , options ) ;
2019-08-27 08:04:41 -07:00
2020-03-30 14:08:51 -07:00
List < String > libPaths = scope . ( ) ;
defer ClearAndDeleteItems ( libPaths ) ;
List < String > depPaths = scope . ( ) ;
defer ClearAndDeleteItems ( depPaths ) ;
2020-07-01 05:29:25 -07:00
AddLinkDeps ( project , options , workspaceOptions , linkLine , libPaths , depPaths ) ;
2019-08-27 08:04:41 -07:00
2019-09-28 09:48:37 -07:00
/ * if ( File . Delete ( targetPath ) . Failed ( true ) )
{
OutputLine ( "Failed to delete {0}" , targetPath ) ;
return false ;
} * /
2019-08-27 08:04:41 -07:00
2024-03-16 07:23:29 -04:00
var clibType = options . mBuildOptions . mCLibType ;
if ( workspaceOptions . mRuntimeKind = = . Disabled )
clibType = . None ;
switch ( clibType )
2019-09-28 09:48:37 -07:00
{
case . None :
2024-03-16 07:23:29 -04:00
linkLine . Append ( "-nodefaultlib chkstk.obj " ) ;
2019-09-28 09:48:37 -07:00
case . Dynamic :
//linkLine.Append((workspaceOptions.mMachineType == .x86) ? "-defaultlib:msvcprt " : "-defaultlib:msvcrt ");
linkLine . Append ( "-defaultlib:msvcrt " ) ;
case . Static :
//linkLine.Append((workspaceOptions.mMachineType == .x86) ? "-defaultlib:libcpmt " : "-defaultlib:libcmt ");
linkLine . Append ( "-defaultlib:libcmt " ) ;
case . DynamicDebug :
//linkLine.Append((workspaceOptions.mMachineType == .x86) ? "-defaultlib:msvcprtd " : "-defaultlib:msvcrtd ");
linkLine . Append ( "-defaultlib:msvcrtd " ) ;
case . StaticDebug :
//linkLine.Append((workspaceOptions.mMachineType == .x86) ? "-defaultlib:libcpmtd " : "-defaultlib:libcmtd ");
linkLine . Append ( "-defaultlib:libcmtd " ) ;
case . SystemMSVCRT :
linkLine . Append ( "-nodefaultlib " ) ;
String minRTModName = scope String ( ) ;
2020-03-21 07:10:16 -07:00
if ( ( project . mGeneralOptions . mTargetType = = . BeefGUIApplication ) | |
( project . mGeneralOptions . mTargetType = = . C_GUIApplication ) )
2019-09-28 09:48:37 -07:00
minRTModName . Append ( "g" ) ;
if ( options . mBuildOptions . mBeefLibType = = . DynamicDebug )
minRTModName . Append ( "d" ) ;
if ( ! minRTModName . IsEmpty )
minRTModName . Insert ( 0 , "_" ) ;
2019-08-27 08:04:41 -07:00
2019-10-14 17:49:10 -07:00
if ( ! is64Bit )
2021-02-25 10:14:22 -08:00
linkLine . Append ( "-libpath:\"" , gApp . mInstallDir , "lib\\x86\" \"" , gApp . mInstallDir , "lib\\x86\\msvcrt.lib\" Beef" , IDEApp . sRTVersionStr , "MinRT32" , minRTModName , ".lib " ) ;
2019-09-28 09:48:37 -07:00
else
2021-02-25 10:14:22 -08:00
linkLine . Append ( "-libpath:\"" , gApp . mInstallDir , "lib\\x64\" \"" , gApp . mInstallDir , "lib\\x64\\msvcrt.lib\" Beef" , IDEApp . sRTVersionStr , "MinRT64" , minRTModName , ".lib " ) ;
2021-02-03 09:00:49 -08:00
linkLine . Append ( "ntdll.lib user32.lib kernel32.lib gdi32.lib winmm.lib shell32.lib ole32.lib rpcrt4.lib version.lib comdlg32.lib -ignore:4049 -ignore:4217 " ) ;
2019-09-28 09:48:37 -07:00
}
2020-03-30 14:08:51 -07:00
for ( var libPath in libPaths )
{
IDEUtils . AppendWithOptionalQuotes ( linkLine , libPath ) ;
linkLine . Append ( " " ) ;
}
2019-09-28 09:48:37 -07:00
linkLine . Append ( "-nologo " ) ;
2020-07-18 07:05:22 -07:00
2021-06-28 09:44:47 -07:00
if ( ( project . mGeneralOptions . mTargetType = = . BeefLib ) & & ( workspaceOptions . mAllowHotSwapping ) & & ( is64Bit ) )
2020-07-01 12:46:04 -07:00
{
2020-07-18 07:05:22 -07:00
// This helps to ensure that DLLs have enough hot swapping space after them
2020-07-01 12:46:04 -07:00
int nameHash = targetPath . GetHashCode ( ) ;
int64 wantAddress = ( ( ( nameHash & 0x3FFFF ) + 0x10 ) < < 28 ) ;
linkLine . AppendF ( "-base:0x{0:X} -dynamicbase:no " , wantAddress ) ;
}
2019-09-28 09:48:37 -07:00
// Incremental just seems to be slower for Beef. Test on larger projects to verify
linkLine . Append ( "-incremental:no " ) ;
2019-08-27 08:04:41 -07:00
2019-09-28 09:48:37 -07:00
if ( options . mBuildOptions . mStackSize > 0 )
linkLine . AppendF ( "-stack:{} " , options . mBuildOptions . mStackSize ) ;
2019-08-27 08:04:41 -07:00
2019-09-28 09:48:37 -07:00
linkLine . Append ( "-pdb:" ) ;
let pdbName = scope String ( ) ;
GetPdbPath ( targetPath , workspaceOptions , options , pdbName ) ;
IDEUtils . AppendWithOptionalQuotes ( linkLine , pdbName ) ;
linkLine . Append ( " " ) ;
2019-08-27 08:04:41 -07:00
2019-09-28 09:48:37 -07:00
//TODO: Only add -debug if we have some debug info?
//if (isDebug)
if ( workspaceOptions . mEmitDebugInfo ! = . No )
linkLine . Append ( "-debug " ) ;
2019-08-27 08:04:41 -07:00
2019-09-28 09:48:37 -07:00
if ( workspaceOptions . mBfOptimizationLevel . IsOptimized ( ) )
//linkLine.Append("-opt:ref -verbose ");
linkLine . Append ( "-opt:ref " ) ;
else
linkLine . Append ( "-opt:noref " ) ;
2019-10-14 17:49:10 -07:00
if ( ! is64Bit )
2019-09-28 09:48:37 -07:00
{
for ( var libPath in gApp . mSettings . mVSSettings . mLib32Paths )
2019-08-27 08:04:41 -07:00
{
2019-09-28 09:48:37 -07:00
linkLine . AppendF ( "-libpath:\"{0}\" " , libPath ) ;
2019-08-27 08:04:41 -07:00
}
2019-09-28 09:48:37 -07:00
linkLine . Append ( "-libpath:\"" , gApp . mInstallDir , "lib\\x86\" " ) ;
}
else
{
for ( var libPath in gApp . mSettings . mVSSettings . mLib64Paths )
2019-08-27 08:04:41 -07:00
{
2019-09-28 09:48:37 -07:00
linkLine . AppendF ( "-libpath:\"{0}\" " , libPath ) ;
2019-08-27 08:04:41 -07:00
}
2019-09-28 09:48:37 -07:00
linkLine . Append ( "-libpath:\"" , gApp . mInstallDir , "lib\\x64\" " ) ;
}
2019-08-27 08:04:41 -07:00
2019-09-28 09:48:37 -07:00
String targetDir = scope String ( ) ;
Path . GetDirectoryPath ( targetPath , targetDir ) ;
linkLine . Append ( "-libpath:" ) ;
IDEUtils . AppendWithOptionalQuotes ( linkLine , targetDir ) ;
linkLine . Append ( " " ) ;
2019-08-27 08:04:41 -07:00
2019-09-28 09:48:37 -07:00
if ( options . mBuildOptions . mOtherLinkFlags . Length ! = 0 )
{
var linkFlags = scope String ( ) ;
2019-10-14 17:49:10 -07:00
gApp . ResolveConfigString ( gApp . mPlatformName , workspaceOptions , project , options , options . mBuildOptions . mOtherLinkFlags , "link flags" , linkFlags ) ;
2019-09-28 09:48:37 -07:00
linkLine . Append ( linkFlags , " " ) ;
}
let winOptions = project . mWindowsOptions ;
2022-02-08 17:02:35 -05:00
UpdateCacheStr ( project , linkLine , workspaceOptions , options , depPaths , libPaths ) ;
2019-09-28 09:48:37 -07:00
if ( project . mNeedsTargetRebuild )
{
2022-02-08 17:02:35 -05:00
String projectBuildDir = scope String ( ) ;
gApp . GetProjectBuildDir ( project , projectBuildDir ) ;
2019-08-27 08:04:41 -07:00
if ( ( ! String . IsNullOrWhiteSpace ( project . mWindowsOptions . mIconFile ) ) | |
( ! String . IsNullOrWhiteSpace ( project . mWindowsOptions . mManifestFile ) ) | |
( winOptions . HasVersionInfo ( ) ) )
2019-09-28 09:48:37 -07:00
{
2019-08-27 08:04:41 -07:00
String resOutPath = scope String ( ) ;
resOutPath . Append ( projectBuildDir , "\\Resource.res" ) ;
String iconPath = scope String ( ) ;
2019-10-14 17:49:10 -07:00
gApp . ResolveConfigString ( gApp . mPlatformName , workspaceOptions , project , options , winOptions . mIconFile , "icon file" , iconPath ) ;
2019-08-27 08:04:41 -07:00
// Generate resource
Result < void > CreateResourceFile ( )
{
ResourceGen resGen = scope ResourceGen ( ) ;
if ( resGen . Start ( resOutPath ) case . Err )
{
gApp . OutputErrorLine ( "Failed to create resource file '{0}'" , resOutPath ) ;
return . Err ;
}
if ( ! iconPath . IsWhiteSpace )
{
Path . GetAbsolutePath ( scope String ( iconPath ) , project . mProjectDir , iconPath . . Clear ( ) ) ;
if ( resGen . AddIcon ( iconPath ) case . Err )
{
gApp . OutputErrorLine ( "Failed to add icon" ) ;
return . Err ;
}
}
let targetFileName = scope String ( ) ;
Path . GetFileName ( targetPath , targetFileName ) ;
if ( resGen . AddVersion ( winOptions . mDescription , winOptions . mComments , winOptions . mCompany , winOptions . mProduct ,
winOptions . mCopyright , winOptions . mFileVersion , winOptions . mProductVersion , targetFileName ) case . Err )
{
gApp . OutputErrorLine ( "Failed to add version" ) ;
return . Err ;
}
String manifestPath = scope String ( ) ;
2019-10-14 17:49:10 -07:00
gApp . ResolveConfigString ( gApp . mPlatformName , workspaceOptions , project , options , winOptions . mManifestFile , "manifest file" , manifestPath ) ;
2019-08-27 08:04:41 -07:00
if ( ! manifestPath . IsWhiteSpace )
{
Path . GetAbsolutePath ( scope String ( manifestPath ) , project . mProjectDir , manifestPath . . Clear ( ) ) ;
if ( resGen . AddManifest ( manifestPath ) case . Err )
{
gApp . OutputErrorLine ( "Failed to add manifest file" ) ;
return . Err ;
}
}
Try ! ( resGen . Finish ( ) ) ;
return . Ok ;
}
if ( CreateResourceFile ( ) case . Err )
{
gApp . OutputErrorLine ( "Failed to generate resource file: {0}" , resOutPath ) ;
return false ;
}
IDEUtils . AppendWithOptionalQuotes ( linkLine , resOutPath ) ;
}
String linkerPath = scope String ( ) ;
if ( workspaceOptions . mToolsetType = = . LLVM )
{
linkerPath . Clear ( ) ;
linkerPath . Append ( gApp . mInstallDir ) ;
linkerPath . Append ( @"llvm\bin\lld-link.exe" ) ;
//linkerPath = @"C:\Program Files\LLVM\bin\lld-link.exe";
var ltoType = workspaceOptions . mLTOType ;
if ( options . mBeefOptions . mLTOType ! = null )
ltoType = options . mBeefOptions . mLTOType . Value ;
if ( ltoType = = . Thin )
{
linkLine . Append ( " /lldltocache:" ) ;
String ltoPath = scope String ( ) ;
Path . GetDirectoryPath ( targetPath , ltoPath ) ;
ltoPath . Append ( "/ltocache" ) ;
IDEUtils . AppendWithOptionalQuotes ( linkLine , ltoPath ) ;
}
2020-10-30 14:57:53 -07:00
if ( ( mPlatformType = = . Windows ) & & ( ! is64Bit ) )
linkLine . Append ( " /safeseh:no" ) ;
2019-08-27 08:04:41 -07:00
}
2021-02-25 10:14:22 -08:00
else
{
let binPath = ( ! is64Bit ) ? gApp . mSettings . mVSSettings . mBin32Path : gApp . mSettings . mVSSettings . mBin64Path ;
if ( binPath . IsWhiteSpace )
{
gApp . OutputErrorLine ( "Visual Studio tool path not configured. Check Visual Studio configuration in File\\Preferences\\Settings." ) ;
return false ;
}
linkerPath . Append ( binPath ) ;
linkerPath . Append ( "/link.exe" ) ;
}
2020-05-15 17:01:56 -07:00
if ( options . mBuildOptions . mBeefLibType ! = . DynamicDebug )
{
linkLine . Append ( " /ignore:4099" ) ;
}
2022-04-16 06:27:54 -07:00
int targetDotPos = targetPath . LastIndexOf ( '.' ) ;
if ( targetDotPos ! = - 1 )
{
var writeEmitCmd = new IDEApp . WriteEmitCmd ( ) ;
writeEmitCmd . mPath = new . ( targetPath , 0 , targetDotPos ) ;
writeEmitCmd . mPath . Append ( "__emit.zip" ) ;
writeEmitCmd . mProjectName = new . ( project . mProjectName ) ;
gApp . mExecutionQueue . Add ( writeEmitCmd ) ;
}
2019-08-27 08:04:41 -07:00
var runCmd = gApp . QueueRun ( linkerPath , linkLine , gApp . mInstallDir , . UTF16WithBom ) ;
2022-03-01 12:57:22 -08:00
runCmd . mReference = new . ( project . mProjectName ) ;
2021-01-03 06:24:49 -08:00
runCmd . mEnvVars = new . ( ) { ( new String ( "VSLANG" ) , new String ( "1033" ) ) } ;
2019-08-27 08:04:41 -07:00
runCmd . mOnlyIfNotFailed = true ;
2022-04-16 06:27:54 -07:00
2019-08-27 08:04:41 -07:00
var tagetCompletedCmd = new IDEApp . TargetCompletedCmd ( project ) ;
tagetCompletedCmd . mOnlyIfNotFailed = true ;
gApp . mExecutionQueue . Add ( tagetCompletedCmd ) ;
String logStr = scope String ( ) ;
logStr . AppendF ( "IDE Process {0}\r\n" , Platform . BfpProcess_GetCurrentId ( ) ) ;
logStr . Append ( linkLine ) ;
String targetLogPath = scope String ( targetPath , ".build.txt" ) ;
2020-06-16 08:30:02 -07:00
if ( Utils . WriteTextFile ( targetLogPath , logStr ) case . Err )
gApp . OutputErrorLine ( "Failed to write {}" , targetLogPath ) ;
2019-08-27 08:04:41 -07:00
project . mLastDidBuild = true ;
}
}
2021-07-19 10:50:31 -07:00
else
{
var tagetCompletedCmd = new IDEApp . TargetCompletedCmd ( project ) ;
tagetCompletedCmd . mOnlyIfNotFailed = true ;
gApp . mExecutionQueue . Add ( tagetCompletedCmd ) ;
}
2019-08-27 08:04:41 -07:00
return true ;
}
2020-05-13 12:28:20 -07:00
public bool QueueProjectCompile ( Project project , Project hotProject , IDEApp . BuildCompletedCmd completedCompileCmd , List < String > hotFileNames , CompileKind compileKind )
2019-08-27 08:04:41 -07:00
{
project . mLastDidBuild = false ;
TestManager . ProjectInfo testProjectInfo = null ;
if ( gApp . mTestManager ! = null )
testProjectInfo = gApp . mTestManager . GetProjectInfo ( project ) ;
var configSelection = gApp . GetCurConfigSelection ( project ) ;
Project . Options options = gApp . GetCurProjectOptions ( project ) ;
if ( options = = null )
return true ;
Workspace . Options workspaceOptions = gApp . GetCurWorkspaceOptions ( ) ;
2019-10-05 10:26:26 -07:00
BfCompiler bfCompiler = gApp . mBfBuildCompiler ;
2022-05-13 13:24:32 -07:00
BfSystem bfSystem = gApp . mBfBuildSystem ;
bfSystem . Lock ( 0 ) ;
2019-08-27 08:04:41 -07:00
var bfProject = gApp . mBfBuildSystem . mProjectMap [ project ] ;
2019-10-05 10:26:26 -07:00
bool bfHadOutputChanges = false ;
2019-08-27 08:04:41 -07:00
List < String > bfFileNames = scope List < String > ( ) ;
2020-02-21 06:52:08 -08:00
if ( hotProject = = null )
{
if ( project . mCurBfOutputFileNames = = null )
{
2022-01-28 08:19:11 -05:00
BfCompiler . UsedOutputFlags usedOutputFlags = . FlushQueuedHotFiles ;
if ( options . mBuildOptions . mBuildKind = = . StaticLib )
usedOutputFlags = . SkipImports ;
2020-02-21 06:52:08 -08:00
project . mCurBfOutputFileNames = new . ( ) ;
2022-01-28 08:19:11 -05:00
bfCompiler . GetOutputFileNames ( bfProject , usedOutputFlags , out bfHadOutputChanges , project . mCurBfOutputFileNames ) ;
2020-02-21 06:52:08 -08:00
}
for ( var fileName in project . mCurBfOutputFileNames )
bfFileNames . Add ( fileName ) ;
}
else
2019-10-05 10:26:26 -07:00
{
2022-01-28 08:19:11 -05:00
bfCompiler . GetOutputFileNames ( bfProject , . FlushQueuedHotFiles , out bfHadOutputChanges , bfFileNames ) ;
2020-02-21 06:52:08 -08:00
defer : : ClearAndDeleteItems ( bfFileNames ) ;
2019-10-05 10:26:26 -07:00
}
2022-05-13 13:24:32 -07:00
bfSystem . Unlock ( ) ;
2019-08-27 08:04:41 -07:00
if ( bfHadOutputChanges )
project . mNeedsTargetRebuild = true ;
List < ProjectSource > allFileNames = scope List < ProjectSource > ( ) ;
List < String > clangAllObjNames = scope List < String > ( ) ;
2019-10-05 10:26:26 -07:00
2019-08-27 08:04:41 -07:00
gApp . GetClangFiles ( project . mRootFolder , allFileNames ) ;
String workspaceBuildDir = scope String ( ) ;
gApp . GetWorkspaceBuildDir ( workspaceBuildDir ) ;
String projectBuildDir = scope String ( ) ;
gApp . GetProjectBuildDir ( project , projectBuildDir ) ;
if ( ! projectBuildDir . IsEmpty )
Directory . CreateDirectory ( projectBuildDir ) . IgnoreError ( ) ;
String targetPath = scope String ( ) ;
String outputDir = scope String ( ) ;
String absOutputDir = scope String ( ) ;
2024-10-25 07:41:53 -04:00
if ( ( testProjectInfo ! = null ) & & ( mPlatformType ! = . Wasm ) )
2019-08-27 08:04:41 -07:00
{
absOutputDir . Append ( projectBuildDir ) ;
outputDir = absOutputDir ;
targetPath . Append ( outputDir , "/" , project . mProjectName ) ;
2020-06-30 12:13:20 -07:00
if ( mPlatformType = = . Windows )
targetPath . Append ( ".exe" ) ;
2019-08-27 08:04:41 -07:00
Debug . Assert ( testProjectInfo . mTestExePath = = null ) ;
testProjectInfo . mTestExePath = new String ( targetPath ) ;
}
else
{
2019-10-14 17:49:10 -07:00
gApp . ResolveConfigString ( gApp . mPlatformName , workspaceOptions , project , options , options . mBuildOptions . mTargetDirectory , "target directory" , outputDir ) ;
2019-08-27 08:04:41 -07:00
Path . GetAbsolutePath ( project . mProjectDir , outputDir , absOutputDir ) ;
outputDir = absOutputDir ;
2019-10-14 17:49:10 -07:00
gApp . ResolveConfigString ( gApp . mPlatformName , workspaceOptions , project , options , "$(TargetPath)" , "target path" , targetPath ) ;
2019-08-27 08:04:41 -07:00
}
IDEUtils . FixFilePath ( targetPath ) ;
if ( ! File . Exists ( targetPath ) )
{
project . mNeedsTargetRebuild = true ;
String targetDir = scope String ( ) ;
2020-04-26 08:46:45 -07:00
Path . GetDirectoryPath ( targetPath , targetDir ) . IgnoreError ( ) ;
2019-08-27 08:04:41 -07:00
if ( ! targetDir . IsEmpty )
Directory . CreateDirectory ( targetDir ) . IgnoreError ( ) ;
}
2021-06-28 09:44:47 -07:00
if ( project . mGeneralOptions . mTargetType = = . BeefLib )
2019-08-27 08:04:41 -07:00
{
if ( targetPath . EndsWith ( ".dll" , . InvariantCultureIgnoreCase ) )
{
String libPath = new . ( ) ;
libPath . Append ( targetPath , 0 , targetPath . Length - 4 ) ;
libPath . Append ( ".lib" ) ;
mImpLibMap . Add ( project , libPath ) ;
}
}
2021-02-25 10:14:22 -08:00
mTargetPathMap [ project ] = new String ( targetPath ) ;
2019-08-29 14:19:07 -07:00
if ( hotProject = = null )
2019-08-27 08:04:41 -07:00
{
2020-05-13 12:28:20 -07:00
switch ( QueueProjectCustomBuildCommands ( project , targetPath , compileKind . WantsRunAfter ? options . mBuildOptions . mBuildCommandsOnRun : options . mBuildOptions . mBuildCommandsOnCompile , options . mBuildOptions . mPreBuildCmds ) )
2019-08-29 14:19:07 -07:00
{
case . NoCommands :
case . HadCommands :
case . Failed :
completedCompileCmd . mFailed = true ;
}
2019-08-27 08:04:41 -07:00
}
if ( project . mGeneralOptions . mTargetType = = . CustomBuild )
{
2021-07-19 10:50:31 -07:00
var tagetCompletedCmd = new IDEApp . TargetCompletedCmd ( project ) ;
tagetCompletedCmd . mOnlyIfNotFailed = true ;
gApp . mExecutionQueue . Add ( tagetCompletedCmd ) ;
2019-08-27 08:04:41 -07:00
return true ;
}
#if IDE_C_SUPPORT
bool buildAll = false ;
String buildStringFilePath = scope String ( ) ;
mDepClang . GetBuildStringFileName ( projectBuildDir , project , buildStringFilePath ) ;
String newBuildString = scope String ( ) ;
GetClangBuildString ( project , options , workspaceOptions , true , newBuildString ) ;
String clangBuildString = scope String ( ) ;
GetClangBuildString ( project , options , workspaceOptions , false , clangBuildString ) ;
newBuildString . Append ( "|" , clangBuildString ) ;
if ( mDepClang . mDoDependencyCheck )
{
String prependStr = scope String ( ) ;
options . mCOptions . mCompilerType . ToString ( prependStr ) ;
prependStr . Append ( "|" ) ;
newBuildString . Insert ( 0 , prependStr ) ;
String oldBuildString ;
mDepClang . mProjectBuildString . TryGetValue ( project , out oldBuildString ) ;
if ( oldBuildString = = null )
{
oldBuildString = new String ( ) ;
File . ReadAllText ( buildStringFilePath , oldBuildString ) . IgnoreError ( ) ;
mDepClang . mProjectBuildString [ project ] = oldBuildString ;
}
if ( newBuildString ! = oldBuildString )
{
buildAll = true ;
if ( case . Err = File . WriteAllText ( buildStringFilePath , newBuildString ) )
OutputLine ( "Failed to write {0}" , buildStringFilePath ) ;
delete oldBuildString ;
mDepClang . mProjectBuildString [ project ] = new String ( newBuildString ) ;
}
}
using ( mDepClang . mMonitor . Enter ( ) )
{
if ( options . mClangObjectFiles = = null )
options . mClangObjectFiles = new List < String > ( ) ;
else
ClearAndDeleteItems ( options . mClangObjectFiles ) ;
for ( var projectSource in allFileNames )
{
var fileEntry = mDepClang . GetProjectEntry ( projectSource ) ;
Debug . Assert ( ( fileEntry ! = null ) | | ( ! mDepClang . mCompileWaitsForQueueEmpty ) ) ;
String filePath = scope String ( ) ;
projectSource . GetFullImportPath ( filePath ) ;
String baseName = scope String ( ) ;
Path . GetFileNameWithoutExtension ( filePath , baseName ) ;
String objName = stack String ( ) ;
objName . Append ( projectBuildDir , "/" , baseName , ( options . mCOptions . mGenerateLLVMAsm ? ".ll" : ".obj" ) ) ;
if ( filePath . Contains ( "test2.cpp" ) )
{
2020-10-30 14:57:53 -07:00
\ NOP ! ( ) ;
2019-08-27 08:04:41 -07:00
}
bool needsRebuild = true ;
if ( ( ! buildAll ) & & ( fileEntry ! = null ) )
{
mDepClang . SetEntryObjFileName ( fileEntry , objName ) ;
mDepClang . SetEntryBuildStringFileName ( fileEntry , buildStringFilePath ) ;
needsRebuild = mDepClang . DoesEntryNeedRebuild ( fileEntry ) ;
}
if ( needsRebuild )
{
if ( hotProject ! = null )
{
OutputLine ( "Hot swap detected disallowed C/C++ change: {0}" , filePath ) ;
return false ;
}
project . mNeedsTargetRebuild = true ;
var runCmd = CompileSource ( project , workspaceOptions , options , filePath ) ;
runCmd . mParallelGroup = 1 ;
}
options . mClangObjectFiles . Add ( new String ( objName ) ) ;
if ( hotProject ! = null )
continue ;
clangAllObjNames . Add ( objName ) ;
IdSpan sourceCharIdData ;
String sourceCode = scope String ( ) ;
FindProjectSourceContent ( projectSource , out sourceCharIdData , true , sourceCode ) ;
mWorkspace . ProjectSourceCompiled ( projectSource , sourceCode , sourceCharIdData ) ;
sourceCharIdData . Dispose ( ) ;
String * fileEntryPtr ;
if ( completedCompileCmd . mClangCompiledFiles . Add ( filePath , out fileEntryPtr ) )
* fileEntryPtr = new String ( filePath ) ;
}
}
#endif
String llvmDir = scope String ( IDEApp . sApp . mInstallDir ) ;
IDEUtils . FixFilePath ( llvmDir ) ;
llvmDir . Append ( "llvm/" ) ;
if ( hotProject ! = null )
{
if ( ( hotProject = = project ) | | ( hotProject . HasDependency ( project . mProjectName ) ) )
{
for ( var fileName in bfFileNames )
hotFileNames . Add ( new String ( fileName ) ) ;
}
return true ;
}
String objectsArg = scope String ( ) ;
var argBuilder = scope IDEApp . ArgBuilder ( objectsArg , workspaceOptions . mToolsetType ! = . GNU ) ;
for ( var bfFileName in bfFileNames )
{
argBuilder . AddFileName ( bfFileName ) ;
argBuilder . AddSep ( ) ;
}
for ( var objName in clangAllObjNames )
{
IDEUtils . AppendWithOptionalQuotes ( objectsArg , objName ) ;
objectsArg . Append ( " " ) ;
}
2020-08-06 09:24:37 -07:00
if ( mPlatformType = = . Wasm )
{
if ( ! QueueProjectWasmLink ( project , targetPath , workspaceOptions , options , objectsArg ) )
return false ;
}
else if ( workspaceOptions . mToolsetType = = . GNU )
2019-08-27 08:04:41 -07:00
{
2019-10-23 07:12:36 -07:00
if ( ( options . mBuildOptions . mBuildKind = = . StaticLib ) | | ( options . mBuildOptions . mBuildKind = = . DynamicLib ) )
{
if ( ! QueueProjectGNUArchive ( project , targetPath , workspaceOptions , options , objectsArg ) )
return false ;
}
else if ( ! QueueProjectGNULink ( project , targetPath , workspaceOptions , options , objectsArg ) )
2019-08-27 08:04:41 -07:00
return false ;
}
else // MS
{
2019-10-15 12:28:21 -07:00
if ( mPlatformType ! = . Windows )
{
gApp . OutputErrorLine ( "Project '{}' cannot be linked with the Windows Toolset for platform '{}'" , project . mProjectName , mPlatformType ) ;
return false ;
}
2021-06-29 06:02:15 -07:00
else
{
if ( options . mBuildOptions . mBuildKind = = . StaticLib )
{
if ( ! QueueProjectGNUArchive ( project , targetPath , workspaceOptions , options , objectsArg ) )
return false ;
}
else
{
if ( ! QueueProjectMSLink ( project , targetPath , configSelection . mConfig , workspaceOptions , options , objectsArg ) )
return false ;
}
}
2019-08-27 08:04:41 -07:00
}
return true ;
}
2021-02-25 10:14:22 -08:00
public bool QueueProjectPostBuild ( Project project , Project hotProject , IDEApp . BuildCompletedCmd completedCompileCmd , List < String > hotFileNames , CompileKind compileKind )
{
if ( hotProject ! = null )
return true ;
Project . Options options = gApp . GetCurProjectOptions ( project ) ;
if ( options = = null )
return true ;
String targetPath = null ;
mTargetPathMap . TryGetValue ( project , out targetPath ) ;
if ( targetPath = = null )
return false ;
switch ( QueueProjectCustomBuildCommands ( project , targetPath , compileKind . WantsRunAfter ? options . mBuildOptions . mBuildCommandsOnRun : options . mBuildOptions . mBuildCommandsOnCompile , options . mBuildOptions . mPostBuildCmds ) )
{
case . NoCommands :
case . HadCommands :
case . Failed :
completedCompileCmd . mFailed = true ;
}
return true ;
}
2019-08-27 08:04:41 -07:00
}
}