2019-08-23 11:56:54 -07:00
using System ;
2020-04-29 06:40:03 -07:00
using System.Collections ;
2019-08-23 11:56:54 -07:00
using System.Text ;
using System.IO ;
using System.Diagnostics ;
using Beefy ;
using Beefy.utils ;
using Beefy.widgets ;
using Beefy.gfx ;
using Beefy.res ;
using IDE.Compiler ;
using IDE.ui ;
using IDE.Util ;
using System.Threading ;
using System.Diagnostics ;
2020-04-16 00:33:29 -07:00
using IDE.util ;
2019-08-23 11:56:54 -07:00
namespace IDE
{
public class ProjectItem : ISerializable , RefCounted
{
public enum IncludeKind
{
Auto ,
Manual ,
Ignore
}
public enum CategoryKind
{
None ,
SimpleSource ,
}
public IncludeKind mIncludeKind ;
public Project mProject ;
public ProjectFolder mParentFolder ;
public String mName = new String ( ) ~ delete _ ;
public String mComment = new String ( ) ~ delete _ ;
2021-12-11 09:08:42 -08:00
public bool mDetached ;
2019-08-23 11:56:54 -07:00
2020-06-04 17:19:57 -07:00
public virtual bool IncludeInMap
2020-01-23 07:43:44 -08:00
{
get
{
2020-06-04 17:19:57 -07:00
return true ;
2020-01-23 07:43:44 -08:00
}
}
2019-08-23 11:56:54 -07:00
public ~ this ( )
{
Debug . Assert ( mRefCount = = 0 ) ;
}
public virtual void Serialize ( StructuredData data )
{
if ( ! String . IsNullOrEmpty ( mName ) )
data . Add ( "Name" , mName ) ;
if ( ! String . IsNullOrEmpty ( mComment ) )
data . Add ( "Comment" , mComment ) ;
}
public virtual void Deserialize ( StructuredData data )
{
data . GetString ( "Name" , mName ) ;
data . GetString ( "Comment" , mComment ) ;
}
public static int NameSort ( ProjectItem item1 , ProjectItem item2 )
{
return item1 . mName . CompareTo ( item2 . mName ) ;
}
public static int Compare ( ProjectItem left , ProjectItem right )
{
int32 leftType = ( left is ProjectFolder ) ? 0 : 1 ;
int32 rightType = ( right is ProjectFolder ) ? 0 : 1 ;
if ( leftType - rightType ! = 0 )
return leftType - rightType ;
return String . Compare ( left . mName , right . mName , true ) ;
}
public virtual void Dispose ( )
{
}
public virtual bool HasNonAuto ( )
{
return mIncludeKind ! = . Auto ;
}
public bool IsIgnored ( )
{
if ( mIncludeKind = = . Ignore )
return true ;
if ( mParentFolder = = null )
return false ;
return mParentFolder . IsIgnored ( ) ;
}
public virtual CategoryKind GetCategoryKind ( )
{
return . None ;
}
public virtual void Detach ( )
{
2021-12-11 09:08:42 -08:00
mDetached = true ;
2019-08-23 11:56:54 -07:00
ReleaseRef ( ) ;
}
}
public class ProjectFileItem : ProjectItem
{
public String mPath ~ delete _ ;
public bool mIsWatching ;
2020-06-04 17:19:57 -07:00
public override bool IncludeInMap
{
get
{
if ( ( mPath = = null ) | | ( mParentFolder . mPath = = null ) )
return true ;
String dirPath = scope . ( ) ;
Path . GetDirectoryPath ( mPath , dirPath ) ;
return Path . Equals ( dirPath , mParentFolder . mPath ) ;
}
}
2019-08-23 11:56:54 -07:00
public this ( )
{
}
public ~ this ( )
{
if ( ( mIsWatching ) & & ( ! IDEApp . sApp . mShuttingDown ) )
StopWatching ( ) ;
}
public void GetFullImportPath ( String outFullPath )
{
if ( mProject . IsSingleFile )
{
if ( gApp . mWorkspace . mCompositeFile . IsIncluded ( mName ) )
{
outFullPath . Append ( mName ) ;
return ;
}
}
if ( mPath ! = null )
{
mProject . GetProjectFullPath ( mPath , outFullPath ) ;
IDEUtils . FixFilePath ( outFullPath ) ;
}
else if ( mParentFolder ! = null )
{
mParentFolder . GetFullImportPath ( outFullPath ) ;
outFullPath . Append ( Path . DirectorySeparatorChar ) ;
outFullPath . Append ( mName ) ;
}
}
public override void Deserialize ( StructuredData data )
{
base . Deserialize ( data ) ;
if ( mPath = = null )
{
mPath = new String ( ) ;
data . GetString ( "Path" , mPath ) ;
if ( mPath . IsEmpty ) //TODO: Temporary
data . GetString ( "ImportPath" , mPath ) ;
IDEUtils . FixFilePath ( mPath ) ;
if ( ( mPath . IsEmpty ) & & ( mParentFolder ! = null ) )
{
mPath . Append ( mParentFolder . mPath ) ;
mPath . Append ( Path . DirectorySeparatorChar ) ;
mPath . Append ( mName ) ;
}
if ( mName . IsEmpty )
Path . GetFileName ( mPath , mName ) ;
}
//AddToResourceManager();
}
public override void Serialize ( StructuredData data )
{
bool wantName = true ;
if ( mPath ! = null )
{
String predictedPath = scope String ( ) ;
if ( mParentFolder ! = null )
{
predictedPath . Append ( mParentFolder . mPath ) ;
predictedPath . Append ( Path . DirectorySeparatorChar ) ;
predictedPath . Append ( mName ) ;
}
if ( mPath ! = predictedPath )
{
String writePath = scope . ( mPath ) ;
IDEUtils . CanonicalizeFilePath ( writePath ) ;
data . Add ( "Path" , writePath ) ;
String fileName = scope . ( ) ;
Path . GetFileName ( mPath , fileName ) ;
wantName = fileName ! = mName ;
}
}
if ( wantName )
data . Add ( "Name" , mName ) ;
}
public virtual void StartWatching ( )
{
#if ! CLI
Debug . Assert ( ! mIsWatching ) ;
var fullPath = scope String ( ) ;
GetFullImportPath ( fullPath ) ;
IDEApp . sApp . mFileWatcher . WatchFile ( fullPath , this ) ;
mIsWatching = true ;
#endif
}
public virtual void StopWatching ( )
{
#if ! CLI
Debug . Assert ( mIsWatching ) ;
var fullPath = scope String ( ) ;
GetFullImportPath ( fullPath ) ;
IDEApp . sApp . mFileWatcher . RemoveWatch ( fullPath , this ) ;
mIsWatching = false ;
#endif
}
public virtual void OnRename ( String oldPath , String newPath )
{
}
public virtual void Rename ( String newName , bool changePath = true )
{
bool wasWatching = mIsWatching ;
if ( ( wasWatching ) & & ( changePath ) )
StopWatching ( ) ;
String dirName = scope String ( ) ;
String fileName = scope String ( ) ;
Path . GetDirectoryPath ( mPath , dirName ) ;
Path . GetFileName ( mPath , fileName ) ;
bool didNameMatch = mName = = fileName ;
2020-01-23 07:43:44 -08:00
if ( IncludeInMap )
{
mParentFolder . mChildMap . Remove ( mName ) ;
mName . Set ( newName ) ;
2020-05-20 06:43:41 -07:00
bool added = mParentFolder . mChildMap . TryAdd ( mName , this ) ;
Debug . Assert ( added ) ;
2020-01-23 07:43:44 -08:00
}
2019-08-23 11:56:54 -07:00
if ( ( didNameMatch ) & & ( changePath ) )
{
String newPath = scope String ( ) ;
newPath . . Append ( dirName )
. . Append ( Path . DirectorySeparatorChar )
. . Append ( newName ) ;
OnRename ( mPath , newPath ) ;
mPath . Set ( newPath ) ;
}
if ( ( wasWatching ) & & ( changePath ) )
StartWatching ( ) ;
}
2021-01-21 05:19:27 -08:00
public void RecalcPath ( )
{
mPath . Clear ( ) ;
mPath . Append ( mParentFolder . mPath ) ;
mPath . Append ( Path . DirectorySeparatorChar ) ;
mPath . Append ( mName ) ;
}
2019-08-23 11:56:54 -07:00
}
public class ProjectSource : ProjectFileItem
{
// 'Unsaved content' is for when we compile from an unsaved file
//public string mUnsavedContent;
//public IdSpan mUnsavedCharIdData;
public FileEditData mEditData ;
public bool mHasChangedSinceLastCompile = true ;
2020-04-16 00:33:29 -07:00
public bool mWasBuiltWithOldHash ;
2019-08-23 11:56:54 -07:00
public bool mHasChangedSinceLastSuccessfulCompile = true ;
2020-01-15 08:33:16 -08:00
public bool mLoadFailed ;
2019-08-23 11:56:54 -07:00
public bool HasChangedSinceLastCompile
{
get
{
return mHasChangedSinceLastCompile ;
}
set
{
mHasChangedSinceLastCompile = value ;
if ( value )
mHasChangedSinceLastSuccessfulCompile = true ;
}
}
public bool IsBeefFile
{
get
{
return IDEApp . IsBeefFile ( mPath ) ;
}
}
2020-01-20 17:12:07 -08:00
public this ( )
{
}
2019-08-23 11:56:54 -07:00
public ~ this ( )
{
Dispose ( ) ;
}
public override CategoryKind GetCategoryKind ( )
{
if ( mIncludeKind ! = . Manual )
return . None ;
2019-08-27 08:04:41 -07:00
if ( mParentFolder . mPath = = null )
return . SimpleSource ;
2019-08-23 11:56:54 -07:00
var expectPath = scope String ( ) ;
expectPath . Append ( mParentFolder . mPath ) ;
expectPath . Append ( Path . DirectorySeparatorChar ) ;
expectPath . Append ( mName ) ;
if ( mPath ! = expectPath )
return . None ;
return . SimpleSource ;
}
2021-12-15 16:24:30 -05:00
public void ClearEditData ( )
2019-08-23 11:56:54 -07:00
{
if ( mEditData ! = null )
{
mEditData . mProjectSources . Remove ( this ) ;
mEditData . Deref ( ) ;
mEditData = null ;
}
}
2021-12-15 16:24:30 -05:00
public override void Dispose ( )
{
ClearEditData ( ) ;
}
2019-08-23 11:56:54 -07:00
public override void Detach ( )
{
Dispose ( ) ;
base . Detach ( ) ;
}
public override void Serialize ( StructuredData data )
{
if ( ( mProject . IsSingleFile ) & & ( mName = = CompositeFile . sMainFileName ) )
return ;
data . Add ( "Type" , ( mIncludeKind = = . Ignore ) ? "IgnoreSource" : "Source" ) ;
base . Serialize ( data ) ;
}
/ * public void AddToResourceManager ( )
{
ResImageInfo resInfo = new ResImageInfo ( ) ;
resInfo . mFilePath = mPath ;
resInfo . mResId = mResId ;
resInfo . mName = mName ;
BFApp . sApp . mResourceManager . mIdToResInfoMap [ mResId ] = resInfo ;
} * /
/ * public override void Dispose ( )
{
if ( mEditData ! = null )
{
//for (var entry in mEditData.mEditWidget.mEditWidgetContent.mUndoManager.)
//mEditData.mEditWidget.mEditWidgetContent.mUndoManager.Dispose();
mEditData . mEditWidget . mEditWidgetContent . mData . mUndoManager . WithActions ( scope ( undoAction ) = >
{
if ( undoAction is GlobalUndoAction )
{
var globalUndoAction = ( GlobalUndoAction ) undoAction ;
globalUndoAction . Detach ( ) ;
}
} ) ;
}
} * /
}
public class ProjectComposition : ProjectItem
{
public Composition mComposition ;
public override void Serialize ( StructuredData data )
{
base . Serialize ( data ) ;
using ( data . CreateObject ( "Composition" ) )
{
}
}
public override void Deserialize ( StructuredData data )
{
base . Deserialize ( data ) ;
using ( data . Open ( "Composition" ) )
{
}
}
}
public class ProjectFolder : ProjectFileItem
{
public List < ProjectItem > mChildItems = new List < ProjectItem > ( ) ~
{
for ( var projectItem in mChildItems )
{
projectItem . Detach ( ) ;
}
delete _ ;
} ;
public Dictionary < String , ProjectItem > mChildMap = new Dictionary < String , ProjectItem > ( ) ~ delete _ ;
//public String mLastImportDir = new String() ~ delete _;
public bool mAutoInclude ;
public bool mSortDirty ;
public this ( )
{
}
public ~ this ( )
{
if ( ( mIsWatching ) & & ( ! gApp . mShuttingDown ) )
StopWatching ( ) ;
}
2020-06-05 14:17:06 -07:00
public override void Dispose ( )
{
for ( var item in mChildItems )
{
item . Dispose ( ) ;
}
}
2021-01-03 11:51:53 -08:00
public void GetFullDisplayName ( String displayName )
{
if ( mParentFolder = = null )
return ;
if ( mParentFolder . mParentFolder ! = null )
{
mParentFolder . mParentFolder . GetFullDisplayName ( displayName ) ;
displayName . Append ( "/" ) ;
}
displayName . Append ( mName ) ;
}
2019-08-23 11:56:54 -07:00
public void GetRelDir ( String path )
{
if ( mPath ! = null )
{
path . Append ( mPath ) ;
return ;
}
if ( ( mParentFolder ! = null ) & & ( mParentFolder . mName . Length > 0 ) )
{
var relDirStr = scope String ( ) ;
mParentFolder . GetRelDir ( relDirStr ) ;
path . . Append ( relDirStr )
. . Append ( Path . DirectorySeparatorChar )
. . Append ( mName ) ;
}
else
path . Append ( mName ) ;
}
public virtual void SortItems ( )
{
if ( mSortDirty )
{
mChildItems . Sort ( scope = > ProjectItem . Compare ) ;
mSortDirty = false ;
}
for ( var item in mChildItems )
{
var projectFolder = item as ProjectFolder ;
if ( projectFolder ! = null )
projectFolder . SortItems ( ) ;
}
}
public void MarkAsUnsorted ( )
{
mSortDirty = true ;
}
public bool IsAutoInclude ( )
{
//return (mAutoInclude != .Never) &&
//((mAutoInclude == .Always) || (mIncludeKind == .Auto));
return mAutoInclude ;
}
public virtual void AddChildAtIndex ( int index , ProjectItem item )
{
item . mParentFolder = this ;
if ( ( mIsWatching ) & & ( var projectFileItem = item as ProjectFileItem ) )
{
projectFileItem . StartWatching ( ) ;
}
mChildItems . Insert ( index , item ) ;
2020-01-23 07:43:44 -08:00
if ( item . IncludeInMap )
{
bool added = mChildMap . TryAdd ( item . mName , item ) ;
Debug . Assert ( added ) ;
}
2019-08-23 11:56:54 -07:00
}
public virtual void InsertChild ( ProjectItem item , ProjectItem insertBefore )
{
int pos = ( insertBefore ! = null ) ? mChildItems . IndexOf ( insertBefore ) : mChildItems . Count ;
AddChildAtIndex ( pos , item ) ;
}
public virtual void AddChild ( ProjectItem item , ProjectItem addAfter = null )
{
int pos = ( addAfter ! = null ) ? ( mChildItems . IndexOf ( addAfter ) + 1 ) : mChildItems . Count ;
AddChildAtIndex ( pos , item ) ;
}
public virtual void RemoveChild ( ProjectItem item )
{
var projectFileItem = item as ProjectFileItem ;
if ( projectFileItem ! = null )
{
if ( projectFileItem . mIsWatching )
projectFileItem . StopWatching ( ) ;
}
2020-01-23 07:43:44 -08:00
if ( item . IncludeInMap )
mChildMap . Remove ( item . mName ) ;
2019-08-23 11:56:54 -07:00
mChildItems . Remove ( item ) ;
item . mParentFolder = null ;
}
public override bool HasNonAuto ( )
{
if ( mAutoInclude ! = ( mIncludeKind = = . Auto ) )
return true ;
if ( mIncludeKind ! = . Auto )
return true ;
for ( let child in mChildItems )
{
if ( child . HasNonAuto ( ) )
return true ;
}
return false ;
}
public bool HasAlias ( )
{
if ( mPath = = null )
return false ;
if ( ! mPath . EndsWith ( mName ) )
return true ;
if ( mPath . Length > mName . Length )
{
// Make sure it's not just a partial match
char8 slashChar = mPath [ mPath . Length - mName . Length ] ;
return ( slashChar = = '\\' ) | | ( slashChar = = '/' ) ;
}
return false ;
}
public override void Serialize ( StructuredData data )
{
if ( ! HasNonAuto ( ) )
return ;
if ( mParentFolder ! = null )
{
2021-01-03 06:25:06 -08:00
data . Add ( "Type" , ( mIncludeKind = = . Ignore ) ? "IgnoreFolder" : ( mIncludeKind = = . Auto ) ? "AutoFolder" : "Folder" ) ;
2019-08-23 11:56:54 -07:00
base . Serialize ( data ) ;
if ( mAutoInclude ! = ( mIncludeKind = = . Auto ) )
2019-09-30 12:23:27 -07:00
data . ConditionalAdd ( "AutoInclude" , mAutoInclude , mIncludeKind = = . Auto ) ;
2019-08-23 11:56:54 -07:00
}
if ( ! mChildItems . IsEmpty )
{
for ( CategoryKind categoryKind = . None ; categoryKind < = . SimpleSource ; categoryKind + + )
{
IDisposable arrayCloseItem = null ;
for ( ProjectItem item in mChildItems )
{
if ( ! item . HasNonAuto ( ) )
continue ;
if ( item . GetCategoryKind ( ) ! = categoryKind )
continue ;
if ( categoryKind = = . SimpleSource )
{
if ( ( mProject . IsSingleFile ) & & ( item . mName = = CompositeFile . sMainFileName ) )
continue ;
if ( arrayCloseItem = = null )
arrayCloseItem = data . CreateArray ( "Source" , true ) ;
data . Add ( item . mName ) ;
}
else
{
if ( arrayCloseItem = = null )
arrayCloseItem = data . CreateArray ( "Items" ) ;
using ( data . CreateObject ( ) )
item . Serialize ( data ) ;
}
}
if ( arrayCloseItem ! = null )
arrayCloseItem . Dispose ( ) ;
}
}
}
public override void Deserialize ( StructuredData data )
{
base . Deserialize ( data ) ;
//mLastImportDir.Clear();
//data.GetString("LastImportDir", mLastImportDir);
//var outer = data.Current;
2019-09-05 08:18:24 -07:00
bool doPopulate = false ;
2019-09-30 12:23:27 -07:00
bool autoInclude = data . GetBool ( "AutoInclude" , mIncludeKind = = . Auto ) ;
2019-08-23 11:56:54 -07:00
if ( ( autoInclude ) & & ( ! mAutoInclude ) )
2019-09-05 08:18:24 -07:00
doPopulate = true ;
mAutoInclude = autoInclude ;
2019-08-23 11:56:54 -07:00
for ( data . Enumerate ( "Items" ) )
{
ProjectItem projectItem = null ;
String type = scope String ( ) ;
data . GetString ( "Type" , type ) ;
String name = scope String ( ) ;
data . GetString ( "Name" , name ) ;
mChildMap . TryGetValue ( name , out projectItem ) ;
if ( projectItem = = null )
{
if ( type = = "Source" )
{
projectItem = new ProjectSource ( ) ;
projectItem . mIncludeKind = . Manual ;
}
else if ( type = = "IgnoreSource" )
{
projectItem = new ProjectSource ( ) ;
projectItem . mIncludeKind = . Ignore ;
}
else if ( type = = "Folder" )
{
projectItem = new ProjectFolder ( ) ;
projectItem . mIncludeKind = . Manual ;
}
2021-01-03 06:25:06 -08:00
else if ( type = = "AutoFolder" )
{
projectItem = new ProjectFolder ( ) ;
projectItem . mIncludeKind = . Auto ;
}
2019-08-23 11:56:54 -07:00
else if ( type = = "IgnoreFolder" )
{
projectItem = new ProjectFolder ( ) ;
projectItem . mIncludeKind = . Ignore ;
}
else
continue ;
projectItem . mProject = mProject ;
projectItem . mParentFolder = this ;
projectItem . Deserialize ( data ) ;
AddChild ( projectItem ) ;
}
else
{
if ( ( type = = "IgnoreSource" ) | |
( type = = "IgnoreFolder" ) )
projectItem . mIncludeKind = . Ignore ;
projectItem . Deserialize ( data ) ;
}
}
for ( data . Enumerate ( "Source" ) )
{
let projectItem = new ProjectSource ( ) ;
data . GetCurString ( projectItem . mName ) ;
projectItem . mIncludeKind = . Manual ;
projectItem . mProject = mProject ;
projectItem . mParentFolder = this ;
var path = new String ( )
. . Append ( mPath )
. . Append ( Path . DirectorySeparatorChar )
. . Append ( projectItem . mName ) ;
projectItem . mPath = path ;
AddChild ( projectItem ) ;
}
2019-09-05 08:18:24 -07:00
if ( doPopulate )
Populate ( mPath ) ;
2019-08-23 11:56:54 -07:00
}
public void Populate ( String relDir )
{
mAutoInclude = true ;
var dirPath = scope String ( mProject . mProjectDir ) ;
dirPath . Append ( Path . DirectorySeparatorChar ) ;
dirPath . Append ( relDir ) ;
for ( let fileEntry in Directory . EnumerateFiles ( dirPath ) )
{
String fileName = scope String ( ) ;
fileEntry . GetFileName ( fileName ) ;
2021-01-03 06:25:06 -08:00
if ( ( ! gApp . IsFilteredOut ( fileName ) ) & & ( ! mChildMap . ContainsKey ( fileName ) ) )
2019-08-23 11:56:54 -07:00
{
let projectItem = new ProjectSource ( ) ;
projectItem . mProject = mProject ;
projectItem . mName . Set ( fileName ) ;
projectItem . mPath = new String ( relDir ) ;
projectItem . mPath . Append ( Path . DirectorySeparatorChar ) ;
projectItem . mPath . Append ( fileName ) ;
AddChild ( projectItem ) ;
}
}
for ( let fileEntry in Directory . EnumerateDirectories ( dirPath ) )
{
String dirName = scope String ( ) ;
fileEntry . GetFileName ( dirName ) ;
2019-09-05 08:18:24 -07:00
// Why was this here?
/ * if ( dirName = = "build" )
continue ; * /
if ( mChildMap . ContainsKey ( dirName ) )
2019-08-23 11:56:54 -07:00
continue ;
let newRelDir = scope String ( relDir ) ;
if ( ! newRelDir . IsEmpty )
newRelDir . Append ( Path . DirectorySeparatorChar ) ;
newRelDir . Append ( dirName ) ;
let projectFolder = new ProjectFolder ( ) ;
projectFolder . mProject = mProject ;
projectFolder . mName . Set ( dirName ) ;
projectFolder . mPath = new String ( relDir )
. . Append ( Path . DirectorySeparatorChar )
. . Append ( dirName ) ;
AddChild ( projectFolder ) ;
projectFolder . Populate ( newRelDir ) ;
}
}
public override void StartWatching ( )
{
//base.StartWatching();
Debug . Assert ( ! mIsWatching ) ;
mIsWatching = true ;
// Add self as a watch
var fullPath = scope String ( ) ;
GetFullImportPath ( fullPath ) ;
fullPath . Append ( Path . DirectorySeparatorChar ) ;
IDEApp . sApp . mFileWatcher . WatchFile ( fullPath , this ) ;
for ( var child in mChildItems )
if ( let childFileItem = child as ProjectFileItem )
if ( ! childFileItem . mIsWatching )
childFileItem . StartWatching ( ) ;
}
public override void StopWatching ( )
{
base . StopWatching ( ) ;
var fullPath = scope String ( ) ;
GetFullImportPath ( fullPath ) ;
fullPath . Append ( Path . DirectorySeparatorChar ) ;
IDEApp . sApp . mFileWatcher . RemoveWatch ( fullPath , this ) ;
for ( var child in mChildItems )
if ( let childFileItem = child as ProjectFileItem )
if ( childFileItem . mIsWatching )
childFileItem . StopWatching ( ) ;
}
public override void OnRename ( String oldPath , String newPath )
{
for ( var child in mChildItems )
if ( let childFileItem = child as ProjectFileItem )
{
if ( childFileItem . mPath . StartsWith ( oldPath , . OrdinalIgnoreCase ) )
{
var newChildPath = scope String ( ) ;
newChildPath . Append ( newPath ) ;
newChildPath . Append ( childFileItem . mPath , oldPath . Length ) ;
childFileItem . OnRename ( childFileItem . mPath , newChildPath ) ;
2021-12-13 10:36:31 -03:00
String oldFullName = scope String ( ) ;
mProject . GetProjectFullPath ( childFileItem . mPath , oldFullName ) ;
String newFullName = scope String ( ) ;
mProject . GetProjectFullPath ( newChildPath , newFullName ) ;
IDEApp . sApp . FileRenamed ( childFileItem , oldFullName , newFullName ) ;
2019-08-23 11:56:54 -07:00
childFileItem . mPath . Set ( newChildPath ) ;
}
}
}
}
[Reflect(.StaticFields | .NonStaticFields | .ApplyToInnerTypes)]
public class Project
{
class ConfigWriteData
{
public String mPlatform ;
public String mOutputDir ;
public StructuredData mData ;
}
public enum BuildKind
{
case Normal ;
case Test ;
2019-10-23 07:12:36 -07:00
case StaticLib ;
case DynamicLib ;
2022-01-14 06:23:36 -05:00
case Intermediate ;
2020-05-15 06:28:01 -07:00
case NotSupported ;
2019-08-23 11:56:54 -07:00
}
public enum COptimizationLevel
{
O0 ,
O1 ,
O2 ,
O3 ,
Ofast ,
Og ,
FromWorkspace
}
public enum CCompilerType
{
Clang ,
GCC
}
public enum CLibType
{
None ,
Dynamic ,
Static ,
DynamicDebug ,
StaticDebug ,
SystemMSVCRT ,
}
public enum BeefLibType
{
Dynamic ,
DynamicDebug ,
Static ,
}
public enum TargetType
{
case BeefConsoleApplication ,
2020-03-21 07:10:16 -07:00
BeefGUIApplication ,
2019-08-27 08:04:41 -07:00
BeefLib ,
CustomBuild ,
2020-09-27 22:20:26 -07:00
BeefTest ,
2019-08-27 08:04:41 -07:00
C_ConsoleApplication ,
2020-03-21 07:10:16 -07:00
C_GUIApplication ,
2019-10-23 07:12:36 -07:00
BeefApplication_StaticLib ,
2021-06-28 09:44:47 -07:00
BeefApplication_DynamicLib ,
BeefLib_Static ,
BeefLib_Dynamic ;
2019-08-23 11:56:54 -07:00
public bool IsBeef
{
2019-10-23 07:12:36 -07:00
get
{
switch ( this )
{
case BeefConsoleApplication ,
2020-03-21 07:10:16 -07:00
BeefGUIApplication ,
2019-10-23 07:12:36 -07:00
BeefLib ,
BeefTest :
return true ;
default :
return false ;
}
}
}
public bool IsBeefApplication
{
get
{
switch ( this )
{
case BeefConsoleApplication ,
2020-03-21 07:10:16 -07:00
BeefGUIApplication :
2019-10-23 07:12:36 -07:00
return true ;
default :
return false ;
2019-08-23 11:56:54 -07:00
}
}
}
2021-06-28 09:44:47 -07:00
public bool IsBeefApplicationOrLib
{
get
{
switch ( this )
{
case BeefConsoleApplication ,
BeefGUIApplication ,
BeefLib :
return true ;
default :
return false ;
}
}
}
2022-06-24 10:29:40 -07:00
public bool IsLib
{
get
{
switch ( this )
{
case BeefLib :
return true ;
default :
return false ;
}
}
}
2019-08-23 11:56:54 -07:00
}
public class WindowsOptions
{
[Reflect]
public String mIconFile = new String ( ) ~ delete _ ;
[Reflect]
public String mManifestFile = new String ( ) ~ delete _ ;
[Reflect]
public String mDescription = new String ( ) ~ delete _ ;
[Reflect]
public String mComments = new String ( ) ~ delete _ ;
[Reflect]
public String mCompany = new String ( ) ~ delete _ ;
[Reflect]
public String mProduct = new String ( ) ~ delete _ ;
[Reflect]
public String mCopyright = new String ( ) ~ delete _ ;
[Reflect]
public String mFileVersion = new String ( ) ~ delete _ ;
[Reflect]
public String mProductVersion = new String ( ) ~ delete _ ;
public bool HasVersionInfo ( )
{
return
! mDescription . IsWhiteSpace | |
! mComments . IsWhiteSpace | |
! mCompany . IsWhiteSpace | |
! mProduct . IsWhiteSpace | |
! mCopyright . IsWhiteSpace | |
! mFileVersion . IsWhiteSpace | |
! mProductVersion . IsWhiteSpace ;
}
public void Deserialize ( StructuredData data )
{
data . GetString ( "IconFile" , mIconFile ) ;
data . GetString ( "ManifestFile" , mManifestFile ) ;
data . GetString ( "Description" , mDescription ) ;
data . GetString ( "Comments" , mComments ) ;
data . GetString ( "Company" , mCompany ) ;
data . GetString ( "Product" , mProduct ) ;
data . GetString ( "Copyright" , mCopyright ) ;
data . GetString ( "FileVersion" , mFileVersion ) ;
data . GetString ( "ProductVersion" , mProductVersion ) ;
2025-02-10 20:06:22 -08:00
String resolvedProductVersion = scope String ( ) ;
if ( gApp . ResolveConfigString ( null , null , null , null , mProductVersion , "custom properties" , resolvedProductVersion ) )
{
mProductVersion . Clear ( ) ;
mProductVersion . Append ( resolvedProductVersion ) ;
}
2019-08-23 11:56:54 -07:00
}
public void Serialize ( StructuredData data )
{
data . ConditionalAdd ( "IconFile" , mIconFile ) ;
data . ConditionalAdd ( "ManifestFile" , mManifestFile ) ;
data . ConditionalAdd ( "Description" , mDescription ) ;
data . ConditionalAdd ( "Comments" , mComments ) ;
data . ConditionalAdd ( "Company" , mCompany ) ;
data . ConditionalAdd ( "Product" , mProduct ) ;
data . ConditionalAdd ( "Copyright" , mCopyright ) ;
data . ConditionalAdd ( "FileVersion" , mFileVersion ) ;
data . ConditionalAdd ( "ProductVersion" , mProductVersion ) ;
}
}
public class LinuxOptions
{
[Reflect]
public String mOptions = new String ( ) ~ delete _ ;
public void Deserialize ( StructuredData data )
{
data . GetString ( "Options" , mOptions ) ;
}
public void Serialize ( StructuredData data )
{
data . ConditionalAdd ( "Options" , mOptions ) ;
}
}
2022-02-08 17:02:35 -05:00
public class WasmOptions
{
[Reflect]
2022-03-24 11:59:00 -07:00
public bool mEnableThreads = false ;
2022-02-08 17:02:35 -05:00
public void Deserialize ( StructuredData data )
{
2022-03-24 11:59:00 -07:00
mEnableThreads = data . GetBool ( "EnableThreads" , false ) ;
2022-02-08 17:02:35 -05:00
}
public void Serialize ( StructuredData data )
{
2022-03-24 11:59:00 -07:00
data . ConditionalAdd ( "EnableThreads" , mEnableThreads , false ) ;
2022-02-08 17:02:35 -05:00
}
}
2019-08-23 11:56:54 -07:00
public class GeneralOptions
{
[Reflect]
2024-10-21 09:18:07 -04:00
public String mProjectNameDecl ; // Points to mProjectNameDecl in Project
[Reflect]
2019-08-23 11:56:54 -07:00
public TargetType mTargetType ;
[Reflect]
public List < String > mAliases = new . ( ) ~ DeleteContainerAndItems ! ( _ ) ;
2024-10-21 09:18:07 -04:00
[Reflect]
public SemVer mVersion = new SemVer ( "" ) ~ delete _ ;
2019-08-23 11:56:54 -07:00
}
public class BeefGlobalOptions
{
[Reflect]
public String mStartupObject = new String ( "" ) ~ delete _ ;
[Reflect]
public String mDefaultNamespace = new String ( ) ~ delete _ ;
[Reflect]
public List < String > mPreprocessorMacros = new List < String > ( ) ~ DeleteContainerAndItems ! ( _ ) ;
[Reflect]
public List < DistinctBuildOptions > mDistinctBuildOptions = new List < DistinctBuildOptions > ( ) ~ DeleteContainerAndItems ! ( _ ) ;
}
public enum BuildCommandTrigger
{
Never ,
IfFilesChanged ,
Always ,
}
public class ProjectBuildOptions
{
[Reflect]
public BuildKind mBuildKind ;
[Reflect]
public String mTargetDirectory = new String ( "$(BuildDir)" ) ~ delete _ ;
[Reflect]
public String mTargetName = new String ( "$(ProjectName)" ) ~ delete _ ;
[Reflect]
public String mOtherLinkFlags = new String ( "" ) ~ delete _ ;
[Reflect]
public CLibType mCLibType = . Static ;
[Reflect]
public BeefLibType mBeefLibType = . Static ;
[Reflect]
public int32 mStackSize ;
[Reflect]
public BuildCommandTrigger mBuildCommandsOnCompile = . Always ;
[Reflect]
public BuildCommandTrigger mBuildCommandsOnRun = . Always ;
[Reflect]
2020-03-30 14:08:51 -07:00
public List < String > mLibPaths = new List < String > ( ) ~ DeleteContainerAndItems ! ( _ ) ;
[Reflect]
2019-12-21 05:48:44 -08:00
public List < String > mLinkDependencies = new List < String > ( ) ~ DeleteContainerAndItems ! ( _ ) ;
[Reflect]
2019-08-23 11:56:54 -07:00
public List < String > mPreBuildCmds = new List < String > ( ) ~ DeleteContainerAndItems ! ( _ ) ;
[Reflect]
public List < String > mPostBuildCmds = new List < String > ( ) ~ DeleteContainerAndItems ! ( _ ) ;
2020-03-28 14:27:22 -07:00
[Reflect]
public List < String > mCleanCmds = new List < String > ( ) ~ DeleteContainerAndItems ! ( _ ) ;
2019-08-23 11:56:54 -07:00
}
public class DebugOptions
{
[Reflect]
public String mCommand = new String ( "$(TargetPath)" ) ~ delete _ ;
[Reflect]
public String mCommandArguments = new String ( "" ) ~ delete _ ;
[Reflect]
public String mWorkingDirectory = new String ( "$(ProjectDir)" ) ~ delete _ ;
[Reflect]
public List < String > mEnvironmentVars = new List < String > ( ) ~ DeleteContainerAndItems ! ( _ ) ;
}
public class BeefOptions
{
[Reflect]
public List < String > mPreprocessorMacros = new List < String > ( ) ~ DeleteContainerAndItems ! ( _ ) ;
[Reflect]
2019-10-23 07:12:36 -07:00
public BuildOptions . RelocType mRelocType ;
[Reflect]
public BuildOptions . PICLevel mPICLevel ;
[Reflect]
2019-08-23 11:56:54 -07:00
public BuildOptions . BfOptimizationLevel ? mOptimizationLevel ;
[Reflect]
public BuildOptions . LTOType ? mLTOType ;
[Reflect]
public bool mMergeFunctions ;
[Reflect]
public bool mCombineLoads ;
[Reflect]
public bool mVectorizeLoops ;
[Reflect]
public bool mVectorizeSLP ;
[Reflect]
public List < DistinctBuildOptions > mDistinctBuildOptions = new List < DistinctBuildOptions > ( ) ~ DeleteContainerAndItems ! ( _ ) ;
}
public class COptions
{
[Reflect]
public CCompilerType mCompilerType = CCompilerType . Clang ;
[Reflect]
public String mOtherCFlags = new String ( "" ) ~ delete _ ;
[Reflect]
public String mOtherCPPFlags = new String ( "" ) ~ delete _ ;
[Reflect]
public List < String > mIncludePaths = new List < String > ( ) ~ DeleteContainerAndItems ! ( _ ) ;
[Reflect]
public bool mEnableBeefInterop ;
[Reflect]
public List < String > mPreprocessorMacros = new List < String > ( ) ~ DeleteContainerAndItems ! ( _ ) ;
[Reflect]
public bool mDisableExceptions ;
[Reflect]
public BuildOptions . SIMDSetting ? mSIMD ;
[Reflect]
public bool mGenerateLLVMAsm ;
[Reflect]
public bool mNoOmitFramePointers ;
[Reflect]
public bool mDisableInlining ;
[Reflect]
public bool mStrictAliasing ;
[Reflect]
public bool mFastMath ;
[Reflect]
public bool mDisableRTTI ;
[Reflect]
public COptimizationLevel mOptimizationLevel = . FromWorkspace ;
[Reflect]
public bool mEmitDebugInfo ;
[Reflect]
public String mAddressSanitizer = new String ( "" ) ~ delete _ ; // TODO: Add proper options
[Reflect]
public bool mAllWarnings ;
[Reflect]
public bool mEffectiveCPPViolations ;
[Reflect]
public bool mPedantic ;
[Reflect]
public bool mWarningsAsErrors ;
[Reflect]
public List < String > mSpecificWarningsAsErrors = new List < String > ( ) ~ DeleteContainerAndItems ! ( _ ) ;
[Reflect]
public List < String > mDisableSpecificWarnings = new List < String > ( ) ~ DeleteContainerAndItems ! ( _ ) ;
public ~ this ( )
{
}
}
public class Options
{
[Reflect]
public ProjectBuildOptions mBuildOptions = new ProjectBuildOptions ( ) ~ delete _ ;
[Reflect]
public BeefOptions mBeefOptions = new BeefOptions ( ) ~ delete _ ;
[Reflect]
public COptions mCOptions = new COptions ( ) ~ delete _ ;
[Reflect]
public DebugOptions mDebugOptions = new DebugOptions ( ) ~ delete _ ;
public List < String > mClangObjectFiles ~ DeleteContainerAndItems ! ( _ ) ;
public Options Duplicate ( )
{
var newOptions = new Options ( ) ;
Set ! ( newOptions . mBuildOptions . mTargetDirectory , mBuildOptions . mTargetDirectory ) ;
Set ! ( newOptions . mBuildOptions . mTargetName , mBuildOptions . mTargetName ) ;
Set ! ( newOptions . mBuildOptions . mOtherLinkFlags , mBuildOptions . mOtherLinkFlags ) ;
Set ! ( newOptions . mBuildOptions . mCLibType , mBuildOptions . mCLibType ) ;
2020-03-30 14:08:51 -07:00
Set ! ( newOptions . mBuildOptions . mLibPaths , mBuildOptions . mLibPaths ) ;
2019-12-21 05:48:44 -08:00
Set ! ( newOptions . mBuildOptions . mLinkDependencies , mBuildOptions . mLinkDependencies ) ;
2019-08-23 11:56:54 -07:00
Set ! ( newOptions . mBuildOptions . mPreBuildCmds , mBuildOptions . mPreBuildCmds ) ;
Set ! ( newOptions . mBuildOptions . mPostBuildCmds , mBuildOptions . mPostBuildCmds ) ;
2020-03-28 14:27:22 -07:00
Set ! ( newOptions . mBuildOptions . mCleanCmds , mBuildOptions . mCleanCmds ) ;
2019-08-23 11:56:54 -07:00
Set ! ( newOptions . mBeefOptions . mPreprocessorMacros , mBeefOptions . mPreprocessorMacros ) ;
Set ! ( newOptions . mBeefOptions . mOptimizationLevel , mBeefOptions . mOptimizationLevel ) ;
Set ! ( newOptions . mBeefOptions . mLTOType , mBeefOptions . mLTOType ) ;
2019-10-23 07:12:36 -07:00
Set ! ( newOptions . mBeefOptions . mRelocType , mBeefOptions . mRelocType ) ;
Set ! ( newOptions . mBeefOptions . mPICLevel , mBeefOptions . mPICLevel ) ;
2019-08-23 11:56:54 -07:00
Set ! ( newOptions . mBeefOptions . mMergeFunctions , mBeefOptions . mMergeFunctions ) ;
Set ! ( newOptions . mBeefOptions . mCombineLoads , mBeefOptions . mCombineLoads ) ;
Set ! ( newOptions . mBeefOptions . mVectorizeLoops , mBeefOptions . mVectorizeLoops ) ;
Set ! ( newOptions . mBeefOptions . mVectorizeSLP , mBeefOptions . mVectorizeSLP ) ;
for ( var prev in mBeefOptions . mDistinctBuildOptions )
newOptions . mBeefOptions . mDistinctBuildOptions . Add ( prev . Duplicate ( ) ) ;
Set ! ( newOptions . mCOptions . mCompilerType , mCOptions . mCompilerType ) ;
Set ! ( newOptions . mCOptions . mOtherCFlags , mCOptions . mOtherCFlags ) ;
Set ! ( newOptions . mCOptions . mOtherCPPFlags , mCOptions . mOtherCPPFlags ) ;
Set ! ( newOptions . mCOptions . mIncludePaths , mCOptions . mIncludePaths ) ;
Set ! ( newOptions . mCOptions . mEnableBeefInterop , mCOptions . mEnableBeefInterop ) ;
Set ! ( newOptions . mCOptions . mPreprocessorMacros , mCOptions . mPreprocessorMacros ) ;
Set ! ( newOptions . mCOptions . mDisableExceptions , mCOptions . mDisableExceptions ) ;
Set ! ( newOptions . mCOptions . mSIMD , mCOptions . mSIMD ) ;
Set ! ( newOptions . mCOptions . mGenerateLLVMAsm , mCOptions . mGenerateLLVMAsm ) ;
Set ! ( newOptions . mCOptions . mNoOmitFramePointers , mCOptions . mNoOmitFramePointers ) ;
Set ! ( newOptions . mCOptions . mDisableInlining , mCOptions . mDisableInlining ) ;
Set ! ( newOptions . mCOptions . mStrictAliasing , mCOptions . mStrictAliasing ) ;
Set ! ( newOptions . mCOptions . mFastMath , mCOptions . mFastMath ) ;
Set ! ( newOptions . mCOptions . mDisableRTTI , mCOptions . mDisableRTTI ) ;
Set ! ( newOptions . mCOptions . mOptimizationLevel , mCOptions . mOptimizationLevel ) ;
Set ! ( newOptions . mCOptions . mEmitDebugInfo , mCOptions . mEmitDebugInfo ) ;
Set ! ( newOptions . mCOptions . mAddressSanitizer , mCOptions . mAddressSanitizer ) ;
Set ! ( newOptions . mCOptions . mAllWarnings , mCOptions . mAllWarnings ) ;
Set ! ( newOptions . mCOptions . mEffectiveCPPViolations , mCOptions . mEffectiveCPPViolations ) ;
Set ! ( newOptions . mCOptions . mPedantic , mCOptions . mPedantic ) ;
Set ! ( newOptions . mCOptions . mWarningsAsErrors , mCOptions . mWarningsAsErrors ) ;
Set ! ( newOptions . mCOptions . mSpecificWarningsAsErrors , mCOptions . mSpecificWarningsAsErrors ) ;
Set ! ( newOptions . mCOptions . mDisableSpecificWarnings , mCOptions . mDisableSpecificWarnings ) ;
Set ! ( newOptions . mDebugOptions . mCommand , mDebugOptions . mCommand ) ;
Set ! ( newOptions . mDebugOptions . mCommandArguments , mDebugOptions . mCommandArguments ) ;
Set ! ( newOptions . mDebugOptions . mWorkingDirectory , mDebugOptions . mWorkingDirectory ) ;
Set ! ( newOptions . mDebugOptions . mEnvironmentVars , mDebugOptions . mEnvironmentVars ) ;
return newOptions ;
}
}
public class Config
{
2021-01-04 04:56:44 -08:00
public Dictionary < String , Options > mPlatforms = new Dictionary < String , Options > ( ) ~ DeleteDictionaryAndKeysAndValues ! ( _ ) ;
2019-08-23 11:56:54 -07:00
}
public class Dependency
{
2021-02-25 08:10:21 -08:00
public VerSpec mVerSpec ~ _ . Dispose ( ) ;
2019-08-23 11:56:54 -07:00
public String mProjectName ~ delete _ ;
2024-10-21 09:18:07 -04:00
public bool mDependencyChecked ;
2019-08-23 11:56:54 -07:00
}
2021-02-25 08:10:21 -08:00
public enum DeferState
{
None ,
ReadyToLoad ,
Pending ,
Searching
}
public class VerReference
{
public String mSrcProjectName ~ delete _ ;
public VerSpec mVerSpec ~ _ . Dispose ( ) ;
}
2024-10-21 09:18:07 -04:00
public class ManagedInfo
{
public SemVer mVersion = new . ( "" ) ~ delete _ ;
public String mInfo ~ delete _ ;
}
2019-08-23 11:56:54 -07:00
public Monitor mMonitor = new Monitor ( ) ~ delete _ ;
public String mNamespace = new String ( ) ~ delete _ ;
public String mProjectDir = new String ( ) ~ delete _ ;
public String mProjectName = new String ( ) ~ delete _ ;
2024-10-21 09:18:07 -04:00
public String mProjectNameDecl = mProjectName ~ { if ( mProjectNameDecl ! = mProjectName ) delete _ ; }
2019-08-23 11:56:54 -07:00
public String mProjectPath = new String ( ) ~ delete _ ;
2024-10-21 09:18:07 -04:00
public ManagedInfo mManagedInfo ~ delete _ ;
2021-02-25 08:10:21 -08:00
public DeferState mDeferState ;
2019-08-23 11:56:54 -07:00
//public String mLastImportDir = new String() ~ delete _;
public bool mHasChanged ;
public bool mNeedsTargetRebuild ;
2019-08-27 08:04:41 -07:00
public bool mForceCustomCommands ;
2019-08-23 11:56:54 -07:00
public bool mEnabled = true ;
public bool mLocked ;
public bool mLockedDefault ;
2020-09-06 06:14:39 -07:00
public bool mDeleted ;
2019-08-23 11:56:54 -07:00
public int32 [ ] mColorDialogCustomColors ;
public ProjectFolder mRootFolder ~ mRootFolder . ReleaseRef ( ) ;
public int32 mCurResVer ;
public int32 mLastGeneratedResVer ;
2021-01-04 04:56:44 -08:00
public Dictionary < String , Config > mConfigs = new Dictionary < String , Config > ( ) ~ DeleteDictionaryAndKeysAndValues ! ( _ ) ;
2019-08-23 11:56:54 -07:00
public GeneralOptions mGeneralOptions = new GeneralOptions ( ) ~ delete _ ;
public BeefGlobalOptions mBeefGlobalOptions = new BeefGlobalOptions ( ) ~ delete _ ;
// Platform-dependent options
public WindowsOptions mWindowsOptions = new WindowsOptions ( ) ~ delete _ ;
public LinuxOptions mLinuxOptions = new LinuxOptions ( ) ~ delete _ ;
2022-02-08 17:02:35 -05:00
public WasmOptions mWasmOptions = new WasmOptions ( ) ~ delete _ ;
2019-08-23 11:56:54 -07:00
public List < Dependency > mDependencies = new List < Dependency > ( ) ~ DeleteContainerAndItems ! ( _ ) ;
public bool mLastDidBuild ;
public bool mFailed ;
public bool mNeedsCreate ;
2019-10-05 10:26:26 -07:00
public List < String > mCurBfOutputFileNames ~ DeleteContainerAndItems ! ( _ ) ;
2019-08-23 11:56:54 -07:00
public String ProjectFileName
{
get
{
Debug . Assert ( ! mProjectPath . IsEmpty ) ;
return mProjectPath ;
}
}
public bool IsSingleFile
{
get
{
return ( mProjectPath . IsEmpty ) & & ( ! mProjectDir . IsEmpty ) ;
}
}
public bool IsDebugSession
{
get
{
return gApp . mWorkspace . IsDebugSession ;
}
}
2019-11-28 09:12:49 -08:00
public bool IsEmpty
{
get
{
return mRootFolder . mChildItems . IsEmpty ;
}
}
2024-10-21 09:18:07 -04:00
public SemVer Version
{
get
{
if ( mManagedInfo ! = null )
return mManagedInfo . mVersion ;
return mGeneralOptions . mVersion ;
}
}
2019-08-23 11:56:54 -07:00
void SetupDefaultOptions ( Options options )
{
options . mBuildOptions . mOtherLinkFlags . Set ( "$(LinkFlags)" ) ;
}
2020-08-31 11:32:33 -07:00
public static void GetSanitizedName ( String projectName , String outName , bool allowDot = false )
{
for ( let c in projectName . RawChars )
{
2023-12-31 06:23:18 -05:00
if ( @c . Index = = 0 )
{
if ( c . IsNumber )
outName . Append ( "_" ) ;
}
2020-08-31 11:32:33 -07:00
if ( ( c . IsLetterOrDigit ) | | ( c = = '_' ) )
outName . Append ( c ) ;
else if ( c = = '-' )
outName . Append ( '_' ) ;
else if ( ( c = = '.' ) & & ( allowDot ) )
outName . Append ( c ) ;
}
}
2019-08-23 11:56:54 -07:00
public this ( )
{
mRootFolder = new ProjectFolder ( ) ;
mRootFolder . mProject = this ;
if ( gApp . mWorkspace . IsDebugSession )
mGeneralOptions . mTargetType = . CustomBuild ;
SetupDefaultConfigs ( ) ;
2024-10-21 09:18:07 -04:00
mGeneralOptions . mProjectNameDecl = mProjectNameDecl ;
2019-08-23 11:56:54 -07:00
mBeefGlobalOptions . mStartupObject . Set ( "Program" ) ;
}
public void SetupDefaultConfigs ( )
{
List < String > platforms = scope List < String > ( ) ;
2019-10-14 17:49:10 -07:00
if ( IDEApp . sPlatform32Name ! = null )
platforms . Add ( IDEApp . sPlatform32Name ) ;
if ( IDEApp . sPlatform64Name ! = null )
platforms . Add ( IDEApp . sPlatform64Name ) ;
2019-08-23 11:56:54 -07:00
List < String > configs = scope List < String > ( ) ;
configs . Add ( "Debug" ) ;
configs . Add ( "Release" ) ;
configs . Add ( "Paranoid" ) ;
configs . Add ( "Test" ) ;
for ( let platformName in platforms )
{
for ( let configName in configs )
{
CreateConfig ( configName , platformName ) ;
}
}
}
public ~ this ( )
{
}
public void GetProjectRelPath ( String fullPath , String outRelPath )
{
Debug . Assert ( ( Object ) fullPath ! = outRelPath ) ;
Path . GetRelativePath ( fullPath , mProjectDir , outRelPath ) ;
IDEUtils . FixFilePath ( outRelPath ) ;
}
public void GetProjectFullPath ( String relPath , String outAbsPath )
{
Debug . Assert ( ( Object ) relPath ! = outAbsPath ) ;
Path . GetAbsolutePath ( relPath , mProjectDir , outAbsPath ) ;
}
public void DeferLoad ( StringView path )
{
2021-02-25 08:10:21 -08:00
if ( ! path . IsEmpty )
{
mProjectPath . Set ( path ) ;
mDeferState = . ReadyToLoad ;
}
else
mDeferState = . Pending ;
2019-08-23 11:56:54 -07:00
}
public bool Load ( StringView path )
{
scope AutoBeefPerf ( "Project.Load" ) ;
2021-02-25 08:10:21 -08:00
mDeferState = . None ;
2019-08-23 11:56:54 -07:00
mLastGeneratedResVer = 0 ;
mCurResVer = 0 ;
StructuredData structuredData = scope StructuredData ( ) ;
if ( ! mProjectPath . IsEmpty )
{
mProjectDir . Clear ( ) ;
2019-09-20 09:21:29 -07:00
mProjectPath . Clear ( ) ;
if ( ! Environment . IsFileSystemCaseSensitive )
{
Path . GetActualPathName ( path , mProjectPath ) ;
}
if ( mProjectPath . IsEmpty )
{
mProjectPath . Set ( path ) ;
IDEUtils . FixFilePath ( mProjectPath ) ;
}
2019-08-23 11:56:54 -07:00
Path . GetDirectoryPath ( mProjectPath , mProjectDir ) ;
if ( structuredData . Load ( ProjectFileName ) case . Err )
return false ;
2024-10-21 09:18:07 -04:00
String managedText = scope . ( ) ;
if ( File . ReadAllText ( scope $"{mProjectDir}/BeefManaged.toml" , managedText ) case . Ok )
{
mManagedInfo = new . ( ) ;
mManagedInfo . mInfo = new . ( managedText ) ;
StructuredData msd = scope . ( ) ;
if ( msd . LoadFromString ( managedText ) case . Ok )
{
if ( mManagedInfo . mVersion . mVersion = = null )
mManagedInfo . mVersion . mVersion = new . ( ) ;
msd . GetString ( "Version" , mManagedInfo . mVersion . mVersion ) ;
}
}
2019-08-23 11:56:54 -07:00
}
else
{
if ( gApp . StructuredLoad ( structuredData , "Project" ) case . Err )
return false ;
}
//Console.WriteLine(structuredData.ToJSON(true));
Deserialize ( structuredData ) ;
/ * if ( ! mIsLegacyProject )
{
Save ( ) ;
} * /
2023-04-25 09:59:32 -07:00
if ( mProjectName ! = null )
{
2023-05-05 15:03:24 -03:00
gApp . mWorkspace . mProjectFileEntries . Add ( new . ( path , mProjectName ) ) ;
2023-04-25 09:59:32 -07:00
}
2019-08-23 11:56:54 -07:00
return true ;
}
public void Serialize ( StructuredData data )
{
mRootFolder . SortItems ( ) ;
//data.Add("LastImportDir", mLastImportDir);
String deferredCreateObject = scope String ( ) ;
bool isOpened = false ;
void DeferCreateObject ( String name )
{
deferredCreateObject . Set ( name ) ;
}
void FinishCreate ( )
{
if ( ! deferredCreateObject . IsEmpty )
{
data . CreateObject ( "General" ) ;
isOpened = true ;
}
}
void TryClose ( )
{
if ( isOpened )
{
isOpened = false ;
}
}
void WriteStrings ( String name , List < String > strs )
{
if ( ! strs . IsEmpty )
{
using ( data . CreateArray ( name ) )
{
for ( var str in strs )
data . Add ( str ) ;
}
}
}
void WriteDistinctOptions ( List < DistinctBuildOptions > distinctBuildOptions )
{
if ( distinctBuildOptions . IsEmpty )
return ;
using ( data . CreateArray ( "DistinctOptions" ) )
{
for ( let typeOptions in distinctBuildOptions )
{
// This '.Deleted' can only happen if we're editing the properties but haven't committed yet
if ( typeOptions . mCreateState = = . Deleted )
continue ;
using ( data . CreateObject ( ) )
typeOptions . Serialize ( data ) ;
}
data . RemoveIfEmpty ( ) ;
}
}
if ( ! IsSingleFile )
data . Add ( "FileVersion" , 1 ) ;
using ( data . CreateObject ( "Project" ) )
{
if ( ! IsSingleFile )
2024-10-21 09:18:07 -04:00
data . Add ( "Name" , mProjectNameDecl ) ;
data . ConditionalAdd ( "Version" , mGeneralOptions . mVersion . mVersion ) ;
2019-08-23 11:56:54 -07:00
data . ConditionalAdd ( "TargetType" , mGeneralOptions . mTargetType , GetDefaultTargetType ( ) ) ;
data . ConditionalAdd ( "StartupObject" , mBeefGlobalOptions . mStartupObject , IsSingleFile ? "Program" : "" ) ;
2020-08-31 11:32:33 -07:00
var defaultNamespace = scope String ( ) ;
GetSanitizedName ( mProjectName , defaultNamespace , true ) ;
data . ConditionalAdd ( "DefaultNamespace" , mBeefGlobalOptions . mDefaultNamespace , defaultNamespace ) ;
2019-08-23 11:56:54 -07:00
WriteStrings ( "Aliases" , mGeneralOptions . mAliases ) ;
WriteStrings ( "ProcessorMacros" , mBeefGlobalOptions . mPreprocessorMacros ) ;
WriteDistinctOptions ( mBeefGlobalOptions . mDistinctBuildOptions ) ;
data . RemoveIfEmpty ( ) ;
}
bool isDefaultDependencies = false ;
if ( mDependencies . Count = = 1 )
{
var dep = mDependencies [ 0 ] ;
if ( ( dep . mProjectName = = "corlib" ) & &
2021-02-25 08:10:21 -08:00
( dep . mVerSpec case . SemVer ( let semVer ) ) & &
2019-08-23 11:56:54 -07:00
( semVer . mVersion = = "*" ) )
{
isDefaultDependencies = true ;
}
}
if ( ! isDefaultDependencies )
{
using ( data . CreateObject ( "Dependencies" , true ) )
{
for ( var dependency in mDependencies )
{
//let verSpecStr = scope String();
//dependency.mVerSpec.Serialize(data);
//data.Add(dependency.mProjectName, verSpecStr);
dependency . mVerSpec . Serialize ( dependency . mProjectName , data ) ;
}
}
}
using ( data . CreateObject ( "Platform" ) )
{
using ( data . CreateObject ( "Windows" ) )
{
mWindowsOptions . Serialize ( data ) ;
data . RemoveIfEmpty ( ) ;
}
using ( data . CreateObject ( "Linux" ) )
{
mLinuxOptions . Serialize ( data ) ;
data . RemoveIfEmpty ( ) ;
}
2022-02-08 17:02:35 -05:00
using ( data . CreateObject ( "Wasm" ) )
{
mWasmOptions . Serialize ( data ) ;
data . RemoveIfEmpty ( ) ;
}
2019-08-23 11:56:54 -07:00
data . RemoveIfEmpty ( ) ;
}
using ( data . CreateObject ( "Configs" ) )
{
for ( var configKeyValue in mConfigs )
{
var config = configKeyValue . value ;
let configName = configKeyValue . key ;
# unwarn
bool isRelease = configName . Contains ( "Release" ) ;
bool isParanoid = configName . Contains ( "Paranoid" ) ;
bool isDebug = isParanoid | | configName . Contains ( "Debug" ) ;
bool isTest = configName . Contains ( "Test" ) ;
using ( data . CreateObject ( configName ) )
{
for ( var platformKeyValue in config . mPlatforms )
{
//let platformName = platformKeyValue.Key;
var options = platformKeyValue . value ;
using ( data . CreateObject ( platformKeyValue . key ) )
{
2022-01-28 08:19:11 -05:00
BuildKind defaultBuildKind = . Normal ;
BuildOptions . RelocType defaultRelocType = . NotSet ;
let platformType = Workspace . PlatformType . GetFromName ( platformKeyValue . key ) ;
switch ( platformType )
{
case . Linux ,
. Windows ,
2022-02-08 17:02:35 -05:00
. macOS ,
. Wasm :
2022-01-28 08:19:11 -05:00
defaultBuildKind = isTest ? . Test : . Normal ;
default :
defaultBuildKind = . StaticLib ;
}
if ( platformType = = . Android )
defaultRelocType = . PIC ;
2019-08-23 11:56:54 -07:00
// Build
2022-01-28 08:19:11 -05:00
data . ConditionalAdd ( "BuildKind" , options . mBuildOptions . mBuildKind , defaultBuildKind ) ;
2019-08-23 11:56:54 -07:00
data . ConditionalAdd ( "TargetDirectory" , options . mBuildOptions . mTargetDirectory , "$(BuildDir)" ) ;
data . ConditionalAdd ( "TargetName" , options . mBuildOptions . mTargetName , "$(ProjectName)" ) ;
data . ConditionalAdd ( "OtherLinkFlags" , options . mBuildOptions . mOtherLinkFlags , "$(LinkFlags)" ) ;
data . ConditionalAdd ( "CLibType" , options . mBuildOptions . mCLibType , isRelease ? . Static : . StaticDebug ) ;
data . ConditionalAdd ( "BeefLibType" , options . mBuildOptions . mBeefLibType , isRelease ? . Static : . Dynamic ) ;
data . ConditionalAdd ( "StackSize" , options . mBuildOptions . mStackSize , 0 ) ;
data . ConditionalAdd ( "BuildCommandsOnCompile" , options . mBuildOptions . mBuildCommandsOnCompile , . Always ) ;
data . ConditionalAdd ( "BuildCommandsOnRun" , options . mBuildOptions . mBuildCommandsOnRun , . Always ) ;
2020-03-30 14:08:51 -07:00
WriteStrings ( "LibPaths" , options . mBuildOptions . mLibPaths ) ;
2019-12-21 05:48:44 -08:00
WriteStrings ( "LinkDependencies" , options . mBuildOptions . mLinkDependencies ) ;
2019-08-23 11:56:54 -07:00
WriteStrings ( "PreBuildCmds" , options . mBuildOptions . mPreBuildCmds ) ;
WriteStrings ( "PostBuildCmds" , options . mBuildOptions . mPostBuildCmds ) ;
2020-03-28 14:27:22 -07:00
WriteStrings ( "CleanCmds" , options . mBuildOptions . mCleanCmds ) ;
2019-08-23 11:56:54 -07:00
// DebugOptions
data . ConditionalAdd ( "DebugCommand" , options . mDebugOptions . mCommand , "$(TargetPath)" ) ;
data . ConditionalAdd ( "DebugCommandArguments" , options . mDebugOptions . mCommandArguments ) ;
data . ConditionalAdd ( "DebugWorkingDirectory" , options . mDebugOptions . mWorkingDirectory , "$(ProjectDir)" ) ;
WriteStrings ( "EnvironmentVars" , options . mDebugOptions . mEnvironmentVars ) ;
// BeefOptions
bool hasDefaultPreprocs = false ;
if ( isRelease )
{
if ( ( options . mBeefOptions . mPreprocessorMacros . Count = = 1 ) & &
( options . mBeefOptions . mPreprocessorMacros [ 0 ] = = "RELEASE" ) )
hasDefaultPreprocs = true ;
}
else if ( isParanoid )
{
if ( ( options . mBeefOptions . mPreprocessorMacros . Count = = 2 ) & &
( options . mBeefOptions . mPreprocessorMacros [ 0 ] = = "DEBUG" ) & &
( options . mBeefOptions . mPreprocessorMacros [ 1 ] = = "PARANOID" ) )
hasDefaultPreprocs = true ;
}
else if ( isDebug )
{
if ( ( options . mBeefOptions . mPreprocessorMacros . Count = = 1 ) & &
( options . mBeefOptions . mPreprocessorMacros [ 0 ] = = "DEBUG" ) )
hasDefaultPreprocs = true ;
}
else if ( isTest )
{
if ( ( options . mBeefOptions . mPreprocessorMacros . Count = = 1 ) & &
( options . mBeefOptions . mPreprocessorMacros [ 0 ] = = "TEST" ) )
hasDefaultPreprocs = true ;
}
else
hasDefaultPreprocs = options . mBeefOptions . mPreprocessorMacros . Count = = 0 ;
if ( ! hasDefaultPreprocs )
{
using ( data . CreateArray ( "PreprocessorMacros" ) )
{
for ( var macro in options . mBeefOptions . mPreprocessorMacros )
data . Add ( macro ) ;
}
}
2022-01-28 08:19:11 -05:00
data . ConditionalAdd ( "RelocType" , options . mBeefOptions . mRelocType , defaultRelocType ) ;
2019-10-23 07:12:36 -07:00
data . ConditionalAdd ( "PICLevel" , options . mBeefOptions . mPICLevel , . NotSet ) ;
2019-08-23 11:56:54 -07:00
data . ConditionalAdd ( "OptimizationLevel" , options . mBeefOptions . mOptimizationLevel ) ;
data . ConditionalAdd ( "LTOType" , options . mBeefOptions . mLTOType ) ;
data . ConditionalAdd ( "MergeFunctions" , options . mBeefOptions . mMergeFunctions ) ;
data . ConditionalAdd ( "CombineLoads" , options . mBeefOptions . mCombineLoads ) ;
data . ConditionalAdd ( "VectorizeLoops" , options . mBeefOptions . mVectorizeLoops ) ;
data . ConditionalAdd ( "VectorizeSLP" , options . mBeefOptions . mVectorizeSLP ) ;
WriteDistinctOptions ( options . mBeefOptions . mDistinctBuildOptions ) ;
#if IDE_C_SUPPORT
using ( data . CreateObject ( "COptions" ) )
{
data . ConditionalAdd ( "CompilerType" , options . mCOptions . mCompilerType ) ;
data . ConditionalAdd ( "OtherCFlags" , options . mCOptions . mOtherCFlags ) ;
data . ConditionalAdd ( "OtherCPPFlags" , options . mCOptions . mOtherCPPFlags ) ;
if ( options . mCOptions . mIncludePaths . Count > 0 )
{
using ( data . CreateArray ( "IncludePaths" ) )
{
for ( var includePath in options . mCOptions . mIncludePaths )
data . Add ( includePath ) ;
}
}
data . ConditionalAdd ( "EnableBeefInterop" , options . mCOptions . mEnableBeefInterop ) ;
if ( options . mCOptions . mPreprocessorMacros . Count > 0 )
{
using ( data . CreateArray ( "PreprocessorMacros" ) )
{
for ( var macro in options . mCOptions . mPreprocessorMacros )
data . Add ( macro ) ;
}
}
data . ConditionalAdd ( "DisableExceptions" , options . mCOptions . mDisableExceptions ) ;
data . ConditionalAdd ( "SIMD" , options . mCOptions . mSIMD , . FromWorkspace ) ;
data . ConditionalAdd ( "GenerateLLVMAsm" , options . mCOptions . mGenerateLLVMAsm ) ;
data . ConditionalAdd ( "NoOmitFramePointers" , options . mCOptions . mNoOmitFramePointers ) ;
data . ConditionalAdd ( "DisableInlining" , options . mCOptions . mDisableInlining ) ;
data . ConditionalAdd ( "StrictAliasing" , options . mCOptions . mStrictAliasing ) ;
data . ConditionalAdd ( "FastMath" , options . mCOptions . mFastMath ) ;
data . ConditionalAdd ( "DisableRTTI" , options . mCOptions . mDisableRTTI ) ;
data . ConditionalAdd ( "OptimizationLevel" , options . mCOptions . mOptimizationLevel , . FromWorkspace ) ;
data . ConditionalAdd ( "EmitDebugInfo" , options . mCOptions . mEmitDebugInfo ) ;
//if (options.mCOptions.mAddressSanitizer)
//data.Add("AddressSanitizer", options.mCOptions.mAddressSanitizer);
data . ConditionalAdd ( "AllWarnings" , options . mCOptions . mAllWarnings ) ;
data . ConditionalAdd ( "EffectiveCPPViolations" , options . mCOptions . mEffectiveCPPViolations ) ;
data . ConditionalAdd ( "Pedantic" , options . mCOptions . mPedantic ) ;
data . ConditionalAdd ( "WarningsAsErrors" , options . mCOptions . mWarningsAsErrors ) ;
if ( options . mCOptions . mSpecificWarningsAsErrors . Count > 0 )
{
using ( data . CreateArray ( "SpecificWarningsAsErrors" ) )
{
for ( var warning in options . mCOptions . mSpecificWarningsAsErrors )
data . Add ( warning ) ;
}
}
if ( options . mCOptions . mDisableSpecificWarnings . Count > 0 )
{
using ( data . CreateArray ( "DisableSpecificWarnings" ) )
{
for ( var warning in options . mCOptions . mDisableSpecificWarnings )
data . Add ( warning ) ;
}
}
}
#endif
data . RemoveIfEmpty ( ) ;
}
}
data . RemoveIfEmpty ( ) ;
}
}
data . RemoveIfEmpty ( ) ;
}
/ * data . Add ( "LinkFlags" , mLinkFlags ) ;
if ( mCompileFlags ! = null )
{
using ( data . CreateArray ( "CompileFlags" ) )
{
foreach ( var str in mCompileFlags )
data . Add ( str ) ;
}
} * /
bool isDefaultProjectFolder = true ;
if ( ! IsSingleFile )
{
if ( mRootFolder . mPath ! = "src" )
isDefaultProjectFolder = false ;
if ( ! mRootFolder . mAutoInclude )
isDefaultProjectFolder = false ;
}
bool IsDefaultFolder ( ProjectFolder folder )
{
if ( folder . mParentFolder ! = null )
{
if ( ! folder . mAutoInclude )
return false ;
if ( folder . mIncludeKind ! = . Auto )
return false ;
}
for ( var childItem in folder . mChildItems )
{
if ( var childFolder = childItem as ProjectFolder )
{
if ( ! IsDefaultFolder ( childFolder ) )
return false ;
}
if ( var childSource = childItem as ProjectSource )
{
if ( ( IsSingleFile ) & & ( childSource . mName = = CompositeFile . sMainFileName ) )
{
// Ignore
}
else
{
if ( childSource . mIncludeKind ! = . Auto )
return false ;
if ( ! childSource . mComment . IsEmpty )
return false ;
}
}
}
return true ;
}
if ( ! IsDefaultFolder ( mRootFolder ) )
isDefaultProjectFolder = false ;
if ( ! isDefaultProjectFolder )
{
using ( data . CreateObject ( "ProjectFolder" ) )
{
mRootFolder . Serialize ( data ) ;
data . RemoveIfEmpty ( ) ;
}
}
}
TargetType GetDefaultTargetType ( )
{
if ( mBeefGlobalOptions . mStartupObject . IsEmpty )
return TargetType . BeefLib ;
return TargetType . BeefConsoleApplication ;
}
public void Deserialize ( StructuredData data )
{
//mLastImportDir.Clear();
//data.GetString("LastImportDir", mLastImportDir);
/ * mLinkFlags = data . GetString ( "LinkFlags" ) ;
using ( data . Open ( "CompileFlags" ) )
{
if ( data . IsArray )
{
mCompileFlags = new List < string > ( ) ;
for ( int i = 0 ; i < data . Count ; i + + )
mCompileFlags . Add ( data . GetString ( i ) ) ;
}
} * /
void ReadStrings ( String name , List < String > strs )
{
for ( data . Enumerate ( name ) )
{
String cmd = new String ( ) ;
data . GetCurString ( cmd ) ;
strs . Add ( cmd ) ;
}
}
2021-06-28 09:44:47 -07:00
bool isBeefDynLib = false ;
2019-08-23 11:56:54 -07:00
using ( data . Open ( "Project" ) )
{
if ( ! IsSingleFile )
2024-10-21 09:18:07 -04:00
{
var projectName = data . GetString ( "Name" , . . scope . ( ) ) ;
if ( ( ! mProjectName . IsEmpty ) & & ( projectName ! = mProjectName ) )
{
// If the name we specified clashes with the delclared project name in the config
if ( mProjectNameDecl = = = mProjectName )
{
mProjectNameDecl = new . ( projectName ) ;
mGeneralOptions . mProjectNameDecl = mProjectNameDecl ;
gApp . mWorkspace . ClearProjectNameCache ( ) ;
}
else
mProjectNameDecl . Set ( projectName ) ;
}
else
mProjectName . Set ( projectName ) ;
}
data . GetString ( "Version" , mGeneralOptions . mVersion . mVersion ) ;
2019-08-23 11:56:54 -07:00
ReadStrings ( "Aliases" , mGeneralOptions . mAliases ) ;
data . GetString ( "StartupObject" , mBeefGlobalOptions . mStartupObject , IsSingleFile ? "Program" : "" ) ;
2020-08-31 11:32:33 -07:00
var defaultNamespace = scope String ( ) ;
GetSanitizedName ( mProjectName , defaultNamespace , true ) ;
data . GetString ( "DefaultNamespace" , mBeefGlobalOptions . mDefaultNamespace , defaultNamespace ) ;
2019-08-23 11:56:54 -07:00
ReadStrings ( "ProcessorMacros" , mBeefGlobalOptions . mPreprocessorMacros ) ;
for ( data . Enumerate ( "DistinctOptions" ) )
{
var typeOptions = new DistinctBuildOptions ( ) ;
typeOptions . Deserialize ( data ) ;
mBeefGlobalOptions . mDistinctBuildOptions . Add ( typeOptions ) ;
}
2020-03-21 07:10:16 -07:00
var targetTypeName = scope String ( ) ;
data . GetString ( "TargetType" , targetTypeName ) ;
switch ( targetTypeName )
{ // Handle Legacy names first
case "BeefWindowsApplication" :
mGeneralOptions . mTargetType = . BeefGUIApplication ;
case "C_WindowsApplication" :
mGeneralOptions . mTargetType = . C_GUIApplication ;
2021-06-28 09:44:47 -07:00
case "BeefDynLib" :
mGeneralOptions . mTargetType = . BeefLib ;
isBeefDynLib = true ;
2020-03-21 07:10:16 -07:00
default :
mGeneralOptions . mTargetType = data . GetEnum < TargetType > ( "TargetType" , GetDefaultTargetType ( ) ) ;
}
2019-08-23 11:56:54 -07:00
}
using ( data . Open ( "Platform" ) )
{
using ( data . Open ( "Windows" ) )
mWindowsOptions . Deserialize ( data ) ;
using ( data . Open ( "Linux" ) )
mLinuxOptions . Deserialize ( data ) ;
2022-02-08 17:02:35 -05:00
using ( data . Open ( "Wasm" ) )
mWasmOptions . Deserialize ( data ) ;
2019-08-23 11:56:54 -07:00
}
if ( ! data . Contains ( "Dependencies" ) )
{
var dep = new Project . Dependency ( ) ;
dep . mProjectName = new . ( "corlib" ) ;
2021-02-25 08:10:21 -08:00
dep . mVerSpec = . SemVer ( new . ( "*" ) ) ;
2019-08-23 11:56:54 -07:00
mDependencies . Add ( dep ) ;
}
else
{
for ( let depName in data . Enumerate ( "Dependencies" ) )
{
var dep = new Dependency ( ) ;
defer { delete dep ; }
if ( dep . mVerSpec . Parse ( data ) case . Err )
{
var err = scope String ( ) ;
err . AppendF ( "Unable to parse version specifier for {0} in {1}" , depName , mProjectPath ) ;
gApp . Fail ( err ) ;
continue ;
}
dep . mProjectName = new String ( depName ) ;
mDependencies . Add ( dep ) ;
dep = null ;
}
}
for ( var dep in mDependencies )
{
switch ( gApp . AddProject ( dep . mProjectName , dep . mVerSpec ) )
{
case . Ok ( let project ) :
case . Err ( let err ) :
2024-10-21 09:18:07 -04:00
// Give an error later
2019-08-23 11:56:54 -07:00
}
}
2021-01-04 04:56:44 -08:00
DeleteDictionaryAndKeysAndValues ! ( mConfigs ) ;
2019-08-23 11:56:54 -07:00
mConfigs = new Dictionary < String , Config > ( ) ;
for ( var configNameSV in data . Enumerate ( "Configs" ) )
{
let configName = scope String ( configNameSV ) ;
Config config = new Config ( ) ;
# unwarn
bool isRelease = configName . Contains ( "Release" ) ;
bool isParanoid = configName . Contains ( "Paranoid" ) ;
bool isDebug = isParanoid | | configName . Contains ( "Debug" ) ;
bool isTest = configName . Contains ( "Test" ) ;
mConfigs [ new String ( configName ) ] = config ;
for ( var platformName in data . Enumerate ( ) )
{
Options options = new Options ( ) ;
config . mPlatforms [ new String ( platformName ) ] = options ;
2022-01-28 08:19:11 -05:00
BuildKind defaultBuildKind = . Normal ;
BuildOptions . RelocType defaultRelocType = . NotSet ;
let platformType = Workspace . PlatformType . GetFromName ( platformName ) ;
switch ( platformType )
{
case . Linux ,
. Windows ,
2022-02-08 17:02:35 -05:00
. macOS ,
. Wasm :
2022-01-28 08:19:11 -05:00
defaultBuildKind = isTest ? . Test : . Normal ;
default :
defaultBuildKind = . StaticLib ;
}
if ( platformType = = . Android )
defaultRelocType = . PIC ;
2019-08-23 11:56:54 -07:00
// Build
2022-01-28 08:19:11 -05:00
options . mBuildOptions . mBuildKind = data . GetEnum < BuildKind > ( "BuildKind" , defaultBuildKind ) ;
2021-06-28 09:44:47 -07:00
if ( ( isBeefDynLib ) & & ( options . mBuildOptions . mBuildKind = = . Normal ) )
options . mBuildOptions . mBuildKind = . DynamicLib ;
2019-08-23 11:56:54 -07:00
data . GetString ( "TargetDirectory" , options . mBuildOptions . mTargetDirectory , "$(BuildDir)" ) ;
data . GetString ( "TargetName" , options . mBuildOptions . mTargetName , "$(ProjectName)" ) ;
data . GetString ( "OtherLinkFlags" , options . mBuildOptions . mOtherLinkFlags , "$(LinkFlags)" ) ;
options . mBuildOptions . mCLibType = data . GetEnum < CLibType > ( "CLibType" , isRelease ? . Static : . StaticDebug ) ;
options . mBuildOptions . mBeefLibType = data . GetEnum < BeefLibType > ( "BeefLibType" , isRelease ? . Static : . Dynamic ) ;
options . mBuildOptions . mStackSize = data . GetInt ( "StackSize" ) ;
options . mBuildOptions . mBuildCommandsOnCompile = data . GetEnum < BuildCommandTrigger > ( "BuildCommandsOnCompile" , . Always ) ;
options . mBuildOptions . mBuildCommandsOnRun = data . GetEnum < BuildCommandTrigger > ( "BuildCommandsOnRun" , . Always ) ;
2020-03-30 14:08:51 -07:00
ReadStrings ( "LibPaths" , options . mBuildOptions . mLibPaths ) ;
2019-12-21 05:48:44 -08:00
ReadStrings ( "LinkDependencies" , options . mBuildOptions . mLinkDependencies ) ;
2019-08-23 11:56:54 -07:00
ReadStrings ( "PreBuildCmds" , options . mBuildOptions . mPreBuildCmds ) ;
ReadStrings ( "PostBuildCmds" , options . mBuildOptions . mPostBuildCmds ) ;
2020-03-28 14:27:22 -07:00
ReadStrings ( "CleanCmds" , options . mBuildOptions . mCleanCmds ) ;
2019-08-23 11:56:54 -07:00
// DebugOptions
data . GetString ( "DebugCommand" , options . mDebugOptions . mCommand , "$(TargetPath)" ) ;
data . GetString ( "DebugCommandArguments" , options . mDebugOptions . mCommandArguments ) ;
data . GetString ( "DebugWorkingDirectory" , options . mDebugOptions . mWorkingDirectory , "$(ProjectDir)" ) ;
ReadStrings ( "EnvironmentVars" , options . mDebugOptions . mEnvironmentVars ) ;
// BeefOptions
2021-01-02 09:08:25 -08:00
ClearAndDeleteItems ( options . mBeefOptions . mPreprocessorMacros ) ;
2019-08-23 11:56:54 -07:00
if ( data . Contains ( "PreprocessorMacros" ) )
{
for ( var _preproc in data . Enumerate ( "PreprocessorMacros" ) )
{
var str = new String ( ) ;
data . GetCurString ( str ) ;
options . mBeefOptions . mPreprocessorMacros . Add ( str ) ;
}
}
else
{
if ( isRelease )
options . mBeefOptions . mPreprocessorMacros . Add ( new String ( "RELEASE" ) ) ;
if ( isDebug )
options . mBeefOptions . mPreprocessorMacros . Add ( new String ( "DEBUG" ) ) ;
if ( isParanoid )
options . mBeefOptions . mPreprocessorMacros . Add ( new String ( "PARANOID" ) ) ;
if ( isTest )
options . mBeefOptions . mPreprocessorMacros . Add ( new String ( "TEST" ) ) ;
}
2022-01-28 08:19:11 -05:00
options . mBeefOptions . mRelocType = data . GetEnum < BuildOptions . RelocType > ( "RelocType" , defaultRelocType ) ;
2019-10-23 07:12:36 -07:00
options . mBeefOptions . mPICLevel = data . GetEnum < BuildOptions . PICLevel > ( "PICLevel" ) ;
2019-08-23 11:56:54 -07:00
if ( data . Contains ( "OptimizationLevel" ) )
options . mBeefOptions . mOptimizationLevel = data . GetEnum < BuildOptions . BfOptimizationLevel > ( "OptimizationLevel" ) ;
if ( data . Contains ( "LTOType" ) )
options . mBeefOptions . mLTOType = data . GetEnum < BuildOptions . LTOType > ( "LTOType" ) ;
options . mBeefOptions . mMergeFunctions = data . GetBool ( "MergeFunctions" ) ;
options . mBeefOptions . mCombineLoads = data . GetBool ( "CombineLoads" ) ;
options . mBeefOptions . mVectorizeLoops = data . GetBool ( "VectorizeLoops" ) ;
options . mBeefOptions . mVectorizeSLP = data . GetBool ( "VectorizeSLP" ) ;
for ( data . Enumerate ( "DistinctOptions" ) )
{
var typeOptions = new DistinctBuildOptions ( ) ;
typeOptions . Deserialize ( data ) ;
options . mBeefOptions . mDistinctBuildOptions . Add ( typeOptions ) ;
}
#if IDE_C_SUPPORT
using ( data . Open ( "COptions" ) )
{
options . mCOptions . mCompilerType = data . GetEnum < CCompilerType > ( "CompilerType" , . Clang ) ;
data . GetString ( "OtherCFlags" , options . mCOptions . mOtherCFlags ) ;
data . GetString ( "OtherCPPFlags" , options . mCOptions . mOtherCPPFlags ) ;
DeleteAndClearItems ! ( options . mCOptions . mIncludePaths ) ;
using ( data . Open ( "IncludePaths" ) )
{
for ( int32 i = 0 ; i < data . Count ; i + + )
{
var str = new String ( ) ;
data . GetString ( i , str ) ;
options . mCOptions . mIncludePaths . Add ( str ) ;
}
}
options . mCOptions . mEnableBeefInterop = data . GetBool ( "EnableBeefInterop" ) ;
DeleteAndClearItems ! ( options . mCOptions . mPreprocessorMacros ) ;
using ( data . Open ( "PreprocessorMacros" ) )
{
for ( int32 i = 0 ; i < data . Count ; i + + )
{
var str = new String ( ) ;
data . GetString ( i , str ) ;
options . mCOptions . mPreprocessorMacros . Add ( str ) ;
}
}
data . GetBool ( "DisableExceptions" , options . mCOptions . mDisableExceptions ) ;
options . mCOptions . mSIMD = data . GetEnum < SIMDSetting > ( "SIMD" , SIMDSetting . FromWorkspace ) ;
options . mCOptions . mGenerateLLVMAsm = data . GetBool ( "GenerateLLVMAsm" ) ;
options . mCOptions . mNoOmitFramePointers = data . GetBool ( "NoOmitFramePointers" ) ;
options . mCOptions . mDisableInlining = data . GetBool ( "DisableInlining" ) ;
options . mCOptions . mStrictAliasing = data . GetBool ( "StrictAliasing" ) ;
options . mCOptions . mFastMath = data . GetBool ( "FastMath" ) ;
options . mCOptions . mDisableRTTI = data . GetBool ( "DisableRTTI" ) ;
options . mCOptions . mOptimizationLevel = data . GetEnum < COptimizationLevel > ( "OptimizationLevel" , . FromWorkspace ) ;
options . mCOptions . mEmitDebugInfo = data . GetBool ( "EmitDebugInfo" , isRelease ? false : true ) ;
data . GetString ( "AddressSanitizer" , options . mCOptions . mAddressSanitizer ) ;
options . mCOptions . mAllWarnings = data . GetBool ( "AllWarnings" ) ;
options . mCOptions . mEffectiveCPPViolations = data . GetBool ( "EffectiveCPPViolations" ) ;
options . mCOptions . mPedantic = data . GetBool ( "Pedantic" ) ;
options . mCOptions . mWarningsAsErrors = data . GetBool ( "WarningsAsErrors" ) ;
using ( data . Open ( "SpecificWarningsAsErrors" ) )
{
for ( int32 i = 0 ; i < data . Count ; i + + )
{
var str = new String ( ) ;
data . GetString ( i , str ) ;
options . mCOptions . mSpecificWarningsAsErrors . Add ( str ) ;
}
}
using ( data . Open ( "DisableSpecificWarnings" ) )
{
for ( int32 i = 0 ; i < data . Count ; i + + )
{
var str = new String ( ) ;
data . GetString ( i , str ) ;
options . mCOptions . mDisableSpecificWarnings . Add ( str ) ;
}
}
}
#endif
}
}
SetupDefaultConfigs ( ) ;
if ( ! IsSingleFile )
{
mRootFolder . mPath = new String ( "src" ) ;
2020-06-04 17:19:57 -07:00
using ( data . Open ( "ProjectFolder" ) )
mRootFolder . Deserialize ( data ) ;
/ * if ( Directory . Exists ( scope String ( mProjectDir , "/src" ) ) )
2019-08-23 11:56:54 -07:00
{
mRootFolder . Populate ( "src" ) ;
2020-06-04 17:19:57 -07:00
} * /
2019-08-23 11:56:54 -07:00
}
else
{
mRootFolder . mPath = new String ( ) ;
Path . GetDirectoryPath ( gApp . mWorkspace . mCompositeFile . FilePath , mRootFolder . mPath ) ;
mRootFolder . mIncludeKind = . Manual ;
let srcFile = new ProjectSource ( ) ;
srcFile . mIncludeKind = . Manual ;
srcFile . mProject = this ;
srcFile . mParentFolder = mRootFolder ;
srcFile . mPath = new String ( CompositeFile . sMainFileName ) ;
srcFile . mName . Set ( CompositeFile . sMainFileName ) ;
mRootFolder . AddChild ( srcFile ) ;
2020-06-04 17:19:57 -07:00
using ( data . Open ( "ProjectFolder" ) )
mRootFolder . Deserialize ( data ) ;
2019-08-23 11:56:54 -07:00
}
mRootFolder . StartWatching ( ) ;
}
2024-10-21 09:18:07 -04:00
public void CheckDependenciesLoaded ( )
{
for ( var dep in mDependencies )
{
if ( ! dep . mDependencyChecked )
{
var project = gApp . mWorkspace . FindProject ( dep . mProjectName ) ;
if ( project ! = null )
{
var projectVersion = project . Version ;
if ( ! projectVersion . mVersion . IsEmpty )
{
if ( dep . mVerSpec case . Git ( let url , let ver ) )
{
if ( ! SemVer . IsVersionMatch ( projectVersion , ver ) )
gApp . OutputLineSmart ( $"WARNING: Project '{mProjectName}' has version constraint '{ver}' for '{dep.mProjectName}' which is not satisfied by selected version '{projectVersion}'" ) ;
}
}
}
else
{
gApp . OutputLineSmart ( "ERROR: Unable to load project '{0}' specified in project '{1}'" , dep . mProjectName , mProjectName ) ;
}
dep . mDependencyChecked = true ;
}
}
}
2019-09-05 08:18:24 -07:00
public void FinishCreate ( bool allowCreateDir = true )
2019-08-23 11:56:54 -07:00
{
if ( ! mRootFolder . mIsWatching )
{
String fullPath = scope String ( ) ;
mRootFolder . GetFullImportPath ( fullPath ) ;
2019-09-05 08:18:24 -07:00
if ( Directory . Exists ( fullPath ) )
{
mRootFolder . Populate ( "src" ) ;
}
else if ( ! allowCreateDir )
{
return ;
}
else
Directory . CreateDirectory ( fullPath ) . IgnoreError ( ) ;
2019-08-23 11:56:54 -07:00
mRootFolder . StartWatching ( ) ;
}
mNeedsCreate = false ;
}
public void SetupDefault ( )
{
mRootFolder . mPath = new String ( "src" ) ;
mRootFolder . mAutoInclude = true ;
if ( Directory . Exists ( scope String ( mProjectDir , "/src" ) ) )
{
mRootFolder . Populate ( "src" ) ;
mRootFolder . StartWatching ( ) ;
2020-08-27 08:52:28 -07:00
}
SetupDefault ( mBeefGlobalOptions ) ;
2019-08-23 11:56:54 -07:00
}
public void Save ( )
{
if ( mNeedsCreate )
FinishCreate ( ) ;
StructuredData aData = scope StructuredData ( ) ;
aData . CreateNew ( ) ;
Serialize ( aData ) ;
String tomlString = scope String ( ) ;
aData . ToTOML ( tomlString ) ;
if ( ! mProjectPath . IsEmpty )
{
if ( ! gApp . SafeWriteTextFile ( ProjectFileName , tomlString ) )
return ;
}
else
{
// If it's just the FileVersion then don't save anything...
/ * if ( tomlString . Count ( '\n' ) < 2 )
tomlString . Clear ( ) ; * /
gApp . StructuredSave ( "Project" , tomlString ) ;
}
mHasChanged = false ;
}
public Options GetOptions ( String configName , String platformName )
{
Config config ;
mConfigs . TryGetValue ( configName , out config ) ;
if ( config = = null )
return null ;
Options options ;
config . mPlatforms . TryGetValue ( platformName , out options ) ;
return options ;
}
public Options GetOptions ( String configName , String platformName , bool createOnDemand )
{
var options = GetOptions ( configName , platformName ) ;
if ( ( options = = null ) & & ( createOnDemand ) )
options = CreateConfig ( configName , platformName ) ;
return options ;
}
public void SetChanged ( )
{
gApp . MarkDirty ( ) ;
mHasChanged = true ;
}
delegate String ProjectItemStringDelegate < T > ( T projectItem ) ;
void SourceIterate < T > ( String sourceText , ProjectItem projectItem , ProjectItemStringDelegate < T > theDelegate ) where T : ProjectItem
{
if ( projectItem is T )
sourceText . Append ( theDelegate ( ( T ) projectItem ) , Environment . NewLine ) ;
if ( projectItem is ProjectFolder )
{
var projectFolder = ( ProjectFolder ) projectItem ;
for ( var childItem in projectFolder . mChildItems )
SourceIterate < T > ( sourceText , childItem , theDelegate ) ;
}
}
delegate void ProjectItemStructuredDataDelegate < T > ( ConfigWriteData data , T projectItem ) ;
void ConfigIterate < T > ( ConfigWriteData data , ProjectItem projectItem , ProjectItemStructuredDataDelegate < T > theDelegate ) where T : ProjectItem
{
if ( projectItem is T )
theDelegate ( data , ( T ) projectItem ) ;
data . mData = null ;
data . mOutputDir = null ;
data . mPlatform = null ;
if ( projectItem is ProjectFolder )
{
var projectFolder = ( ProjectFolder ) projectItem ;
for ( var childItem in projectFolder . mChildItems )
ConfigIterate < T > ( data , childItem , theDelegate ) ;
}
}
void WriteItemConfigData ( ConfigWriteData data , ProjectItem item )
{
StructuredData aData = data . mData ;
if ( ! ( item is ProjectFolder ) )
{
ProjectSource aProjectImage = item as ProjectSource ;
if ( aProjectImage ! = null )
{
using ( aData . CreateObject ( ) )
{
aData . Add ( "Type" , "Image" ) ;
aData . Add ( "Name" , aProjectImage . mName ) ;
String imageFullPath = scope String ( ) ;
GetProjectFullPath ( aProjectImage . mPath , imageFullPath ) ;
String imageRelPath = scope String ( ) ;
Path . GetRelativePath ( imageFullPath , data . mOutputDir , imageRelPath ) ;
IDEUtils . CanonicalizeFilePath ( imageRelPath ) ;
aData . Add ( "Path" , imageRelPath ) ;
}
}
}
}
public void UpdateResConfigData ( )
{
}
public void Update ( )
{
}
2020-05-08 07:10:35 -07:00
public void WithProjectItems ( delegate void ( ProjectItem ) func )
2019-08-23 11:56:54 -07:00
{
List < int32 > idxStack = scope List < int32 > ( ) ;
List < ProjectFolder > folderStack = scope List < ProjectFolder > ( ) ;
folderStack . Add ( mRootFolder ) ;
idxStack . Add ( 0 ) ;
while ( folderStack . Count > 0 )
{
int32 curIdx = idxStack [ idxStack . Count - 1 ] + + ;
ProjectFolder curFolder = folderStack [ folderStack . Count - 1 ] ;
if ( curIdx > = curFolder . mChildItems . Count )
{
folderStack . RemoveAt ( folderStack . Count - 1 ) ;
idxStack . RemoveAt ( idxStack . Count - 1 ) ;
continue ;
}
var projectItem = curFolder . mChildItems [ curIdx ] ;
if ( projectItem is ProjectFolder )
{
folderStack . Add ( ( ProjectFolder ) projectItem ) ;
idxStack . Add ( 0 ) ;
continue ;
}
func ( projectItem ) ;
}
}
2024-10-21 09:18:07 -04:00
public VerSpec * GetDependency ( String projectName , bool checkRecursively = true )
2019-08-23 11:56:54 -07:00
{
2020-05-12 06:44:09 -07:00
HashSet < Project > checkedProject = scope . ( ) ;
2024-10-21 09:18:07 -04:00
VerSpec * CheckDependency ( Project project )
2020-05-12 06:44:09 -07:00
{
if ( ! checkedProject . Add ( project ) )
2024-10-21 09:18:07 -04:00
return null ;
2020-05-12 06:44:09 -07:00
for ( var dependency in project . mDependencies )
{
if ( dependency . mProjectName = = projectName )
2024-10-21 09:18:07 -04:00
return & dependency . mVerSpec ;
2020-05-12 06:44:09 -07:00
let depProject = gApp . mWorkspace . FindProject ( dependency . mProjectName ) ;
2024-10-21 09:18:07 -04:00
if ( ( depProject ! = null ) & & ( checkRecursively ) )
{
var verSpec = CheckDependency ( depProject ) ;
if ( verSpec ! = null )
return verSpec ;
}
2020-05-12 06:44:09 -07:00
}
2024-10-21 09:18:07 -04:00
return null ;
2020-05-12 06:44:09 -07:00
}
return CheckDependency ( this ) ;
2019-08-23 11:56:54 -07:00
}
2024-10-21 09:18:07 -04:00
public bool HasDependency ( String projectName , bool checkRecursively = true ) = > GetDependency ( projectName , checkRecursively ) ! = null ;
2019-08-23 11:56:54 -07:00
public void SetupDefault ( Options options , String configName , String platformName )
{
bool isRelease = configName . Contains ( "Release" ) ;
bool isParanoid = configName . Contains ( "Paranoid" ) ;
bool isDebug = isParanoid | | configName . Contains ( "Debug" ) ;
bool isTest = configName . Contains ( "Test" ) ;
2019-10-23 07:12:36 -07:00
let platformType = Workspace . PlatformType . GetFromName ( platformName ) ;
2019-08-23 11:56:54 -07:00
if ( isRelease )
options . mBeefOptions . mPreprocessorMacros . Add ( new String ( "RELEASE" ) ) ;
if ( isDebug )
options . mBeefOptions . mPreprocessorMacros . Add ( new String ( "DEBUG" ) ) ;
if ( isParanoid )
options . mBeefOptions . mPreprocessorMacros . Add ( new String ( "PARANOID" ) ) ;
if ( isTest )
options . mBeefOptions . mPreprocessorMacros . Add ( new String ( "TEST" ) ) ;
options . mBuildOptions . mCLibType = isRelease ? . Static : . StaticDebug ;
options . mBuildOptions . mBeefLibType = isRelease ? . Static : . Dynamic ;
options . mBuildOptions . mStackSize = 0 ;
2019-10-23 07:12:36 -07:00
switch ( platformType )
{
case . Linux ,
. Windows ,
2022-02-08 17:02:35 -05:00
. macOS ,
. Wasm :
2019-10-23 07:12:36 -07:00
options . mBuildOptions . mBuildKind = isTest ? . Test : . Normal ;
default :
options . mBuildOptions . mBuildKind = . StaticLib ;
}
if ( platformType = = . Android )
{
options . mBeefOptions . mRelocType = . PIC ;
}
2019-08-23 11:56:54 -07:00
options . mBuildOptions . mOtherLinkFlags . Set ( "$(LinkFlags)" ) ;
if ( gApp . mWorkspace . IsDebugSession )
{
options . mBuildOptions . mTargetName . Clear ( ) ;
options . mDebugOptions . mWorkingDirectory . Clear ( ) ;
options . mBuildOptions . mBuildCommandsOnCompile = . Always ;
options . mBuildOptions . mBuildCommandsOnRun = . Never ;
}
}
public void SetupDefault ( GeneralOptions generalOptions )
{
}
public void SetupDefault ( BeefGlobalOptions generalOptions )
{
2020-08-31 11:32:33 -07:00
generalOptions . mDefaultNamespace . Clear ( ) ;
GetSanitizedName ( mProjectName , generalOptions . mDefaultNamespace , true ) ;
2020-08-27 08:52:28 -07:00
generalOptions . mStartupObject . Set ( scope String ( ) . . AppendF ( "{}.Program" , generalOptions . mDefaultNamespace ) ) ;
2019-08-23 11:56:54 -07:00
}
public Options CreateConfig ( String configName , String platformName )
{
String * configKeyPtr = null ;
Config * configPtr = null ;
Config config = null ;
if ( mConfigs . TryAdd ( configName , out configKeyPtr , out configPtr ) )
{
config = new Config ( ) ;
* configPtr = config ;
* configKeyPtr = new String ( configName ) ;
}
else
config = * configPtr ;
String * platformKeyPtr = null ;
Options * optionsPtr = null ;
Options options = null ;
if ( config . mPlatforms . TryAdd ( platformName , out platformKeyPtr , out optionsPtr ) )
{
options = new Options ( ) ;
* optionsPtr = options ;
* platformKeyPtr = new String ( platformName ) ;
SetupDefault ( options , configName , platformName ) ;
}
return * optionsPtr ;
}
}
}