_maybe prog, trying static linking

This commit is contained in:
2026-03-02 23:39:36 +02:00
parent 1ab600b020
commit 60cdcbcba6
10 changed files with 167 additions and 30 deletions

View File

@@ -38,7 +38,7 @@ ArchitectureType WebPlatformTools::GetArchitecture() const
DotNetAOTModes WebPlatformTools::UseAOT() const
{
return DotNetAOTModes::None;//DotNetAOTModes::MonoAOTStatic;//DotNetAOTModes::NoDotnet;
return DotNetAOTModes::MonoAOTStatic;// DotNetAOTModes::None;//DotNetAOTModes::MonoAOTStatic;//DotNetAOTModes::NoDotnet;
}
PixelFormat WebPlatformTools::GetTextureFormat(CookingData& data, TextureBase* texture, PixelFormat format)
@@ -91,8 +91,9 @@ bool WebPlatformTools::OnPostProcess(CookingData& data)
// Move .wasm assemblies into the data files in order for dlopen to work (blocking)
{
Array<String> files;
Array<String> files, files2;
FileSystem::DirectoryGetFiles(files, data.OriginalOutputPath, TEXT("*.wasm"), DirectorySearchOption::AllDirectories);
FileSystem::DirectoryGetFiles(files, data.OriginalOutputPath, TEXT("*.so"), DirectorySearchOption::AllDirectories);
StringView gameWasm = StringUtils::GetFileNameWithoutExtension(gameJs);
for (const String& file : files)
{
@@ -100,6 +101,12 @@ bool WebPlatformTools::OnPostProcess(CookingData& data)
continue; // Skip the main game module
FileSystem::MoveFile(data.DataOutputPath / StringUtils::GetFileName(file), file, true);
}
for (const String& file : files2)
{
if (StringUtils::GetFileNameWithoutExtension(file) == gameWasm)
continue; // Skip the main game module
FileSystem::MoveFile(data.DataOutputPath / StringUtils::GetFileName(file), file, true);
}
}
// Pack data files into a single file using Emscripten's file_packager tool

View File

@@ -37,8 +37,8 @@ void PrecompileAssembliesStep::OnBuildStarted(CookingData& data)
if (cachedData != aotModeCacheValue)
{
LOG(Info, "AOT cache invalidation");
FileSystem::DeleteDirectory(data.ManagedCodeOutputPath); // Remove AOT cache
FileSystem::DeleteDirectory(data.DataOutputPath / TEXT("Dotnet")); // Remove deployed Dotnet libs (be sure to remove any leftovers from previous build)
//FileSystem::DeleteDirectory(data.ManagedCodeOutputPath); // Remove AOT cache
//FileSystem::DeleteDirectory(data.DataOutputPath / TEXT("Dotnet")); // Remove deployed Dotnet libs (be sure to remove any leftovers from previous build)
}
}
if (!FileSystem::DirectoryExists(data.ManagedCodeOutputPath))

View File

@@ -31,6 +31,6 @@
// Use AOT for Mono
#define USE_MONO_AOT 1
#define USE_MONO_AOT_MODE MONO_AOT_MODE_FULL
#define USE_MONO_AOT_MODE MONO_AOT_MODE_INTERP
#endif

View File

@@ -311,7 +311,6 @@ void MCore::UnloadDomain(const StringAnsi& domainName)
bool MCore::LoadEngine()
{
LOG(Info, "DotNet MCore::LoadEngine");
PROFILE_CPU();
PROFILE_MEM(ScriptingCSharp);
@@ -1788,7 +1787,6 @@ hostfxr_run_app_fn hostfxr_run_app;
bool InitHostfxr()
{
LOG(Info, "InitHostfxr");
const ::String csharpLibraryPath = Globals::BinariesFolder / TEXT("FlaxEngine.CSharp.dll");
const ::String csharpRuntimeConfigPath = Globals::BinariesFolder / TEXT("FlaxEngine.CSharp.runtimeconfig.json");
if (!FileSystem::FileExists(csharpLibraryPath))
@@ -2063,10 +2061,10 @@ static MonoAssembly* OnMonoAssemblyLoad(const char* aname)
String fileName = name;
if (!name.EndsWith(TEXT(".dll")) && !name.EndsWith(TEXT(".exe")))
fileName += TEXT(".dll");
String path = Globals::ProjectFolder / String(TEXT("/Dotnet/")) / fileName;
String path = Globals::ProjectFolder / String(TEXT("Dotnet/")) / fileName;
if (!FileSystem::FileExists(path))
{
path = Globals::ProjectFolder / String(TEXT("/Dotnet/shared/Microsoft.NETCore.App/")) / fileName;
path = Globals::ProjectFolder / String(TEXT("Dotnet/shared/Microsoft.NETCore.App/")) / fileName;
if (!FileSystem::FileExists(path))
{
path = fileName;
@@ -2219,7 +2217,6 @@ bool MonoAotPreloadTask::Run()
bool InitHostfxr()
{
LOG(Info, "InitHostfxr2");
#if DOTNET_HOST_MONO_DEBUG
// Enable detailed Mono logging
Platform::SetEnvironmentVariable(TEXT("MONO_LOG_LEVEL"), TEXT("debug"));
@@ -2238,8 +2235,7 @@ bool InitHostfxr()
#if defined(USE_MONO_AOT_MODE)
// Enable AOT mode (per-platform)
LOG(Info, "InitHostfxr mono_jit_set_aot_mode");
mono_jit_set_aot_mode(USE_MONO_AOT_MODE);
mono_jit_set_aot_mode(MONO_AOT_MODE_FULL);
#endif
// Platform-specific setup
@@ -2249,7 +2245,6 @@ bool InitHostfxr()
#endif
#ifdef USE_MONO_AOT_MODULE
LOG(Info, "InitHostfxr USE_MONO_AOT_MODULE");
// Wait for AOT module preloading
while (Platform::AtomicRead(&MonoAotPreloadServiceInstance.Ready) == 0)
Platform::Yield();
@@ -2281,7 +2276,6 @@ bool InitHostfxr()
#endif
// Setup debugger
LOG(Info, "InitHostfxr2 setup debugger");
{
int32 debuggerLogLevel = 0;
if (CommandLine::Options.MonoLog.IsTrue() || DOTNET_HOST_MONO_DEBUG)
@@ -2328,7 +2322,6 @@ bool InitHostfxr()
#endif
}
LOG(Info, "InitHostfxr2 set log handler");
// Connect to mono engine callback system
mono_trace_set_log_handler(OnLogCallback, nullptr);
mono_trace_set_print_handler(OnPrintCallback);
@@ -2362,18 +2355,15 @@ bool InitHostfxr()
#else
const char* monoVersion = ""; // ignored
#endif
LOG(Info, "InitHostfxr2 mono_jit_init_version");
MonoDomainHandle = mono_jit_init_version("Flax", monoVersion);
if (!MonoDomainHandle)
{
LOG(Fatal, "Failed to initialize Mono.");
return true;
}
LOG(Info, "InitHostfxr2 mono_gc_init_finalizer_thread");
mono_gc_init_finalizer_thread();
// Log info
LOG(Info, "InitHostfxr2 mono_get_runtime_build_info");
char* buildInfo = mono_get_runtime_build_info();
LOG(Info, "Mono runtime version: {0}", String(buildInfo));
mono_free(buildInfo);

View File

@@ -464,7 +464,6 @@ static void* OnMonoLinuxDlSym(void* handle, const char* name, char** err, void*
bool MCore::LoadEngine()
{
LOG(Info, "Mono MCore::LoadEngine");
PROFILE_CPU();
ASSERT(Globals::MonoPath.IsANSI());

View File

@@ -47,7 +47,6 @@ void MCore::UnloadDomain(const StringAnsi& domainName)
bool MCore::LoadEngine()
{
LOG(Info, "None MCore::LoadEngine");
MRootDomain = New<MDomain>("Root");
MDomains.Add(MRootDomain);
return false;

View File

@@ -66,7 +66,7 @@ namespace Flax.Build
public static void RunDotNetAOT()
{
Log.Info("Running .NET AOT in mode " + AOTMode);
Configuration.CustomDefines.Add("DOTNET_AOT_DEBUG");
//Configuration.CustomDefines.Add("DOTNET_AOT_DEBUG");
DotNetAOT.RunAOT();
}
@@ -387,7 +387,7 @@ namespace Flax.Build
buildToolchain.CompileCSharp(ref options);
platformToolsPath = options.PlatformToolsPath;
}
if (!wasm)
//if (!wasm)
{
// Check if core library has been modified
var options = new Toolchain.CSharpOptions
@@ -403,12 +403,28 @@ namespace Flax.Build
};
buildToolchain.CompileCSharp(ref options);
coreLibDirty = File.GetLastWriteTime(options.InputFiles[0]) > File.GetLastWriteTime(options.OutputFiles[0]);
Log.Info("corelibdirty:" + coreLibDirty + ", " + options.OutputFiles[0]);
}
if (!Directory.Exists(platformToolsPath))
throw new Exception("Missing platform tools " + platformToolsPath);
Log.Info("Platform tools found in: " + platformToolsPath);
// Workaround for unknown command "rm" when running on Windows
Utilities.WriteFileIfChanged(Path.Combine(aotAssembliesPath, "rm.bat"),
"""
@echo off
setlocal enabledelayedexpansion
set command=%*
set command=!command:~3!
del /F /Q /S %command%
rmdir /S /Q %command%
"""
);
var compileAssembly = (string assemblyPath) =>
{
//if (!assemblyPath.Contains("Newtonsoft"))
// return;
// Determinate whether use debug information for that assembly
var useDebug = configuration != TargetConfiguration.Release;
if (!dotnetAotDebug && !inputFiles.Contains(assemblyPath))
@@ -497,7 +513,7 @@ namespace Flax.Build
};
Log.Info("AOT: " + string.Join(", ", assembliesPaths));
Log.Info("");
if (false && Configuration.MaxConcurrency > 1 && Configuration.ConcurrencyProcessorScale > 0.0f && !dotnetAotDebug)
if (Configuration.MaxConcurrency > 1 && Configuration.ConcurrencyProcessorScale > 0.0f && !dotnetAotDebug)
{
// Multi-threaded
System.Threading.Tasks.Parallel.ForEach(assembliesPaths, compileAssembly);

View File

@@ -32,7 +32,7 @@ namespace Flax.Build.Platforms
public override string ExecutableFileExtension => ".html";
/// <inheritdoc />
public override string SharedLibraryFileExtension => ".wasm";
public override string SharedLibraryFileExtension => ".so";//".wasm";
/// <inheritdoc />
public override string StaticLibraryFileExtension => ".a";

View File

@@ -245,7 +245,7 @@ namespace Flax.Build.Platforms
{
switch (options.Action)
{
case CSharpOptions.ActionTypes.GetOutputFiles:
/*case CSharpOptions.ActionTypes.GetOutputFiles:
{
foreach (var inputFile in options.InputFiles)
{
@@ -264,7 +264,7 @@ namespace Flax.Build.Platforms
options.OutputFiles.Add(assemblyPath);
}
return false;
}
}*/
case CSharpOptions.ActionTypes.GetPlatformTools:
{
string arch = Platform.BuildTargetArchitecture switch
@@ -286,6 +286,120 @@ namespace Flax.Build.Platforms
options.PlatformToolsPath = Path.Combine(DotNetSdk.SelectVersionFolder(Path.Combine(DotNetSdk.Instance.RootPath, $"packs/Microsoft.NETCore.App.Runtime.AOT.{os}-{arch}.Cross.browser-wasm")), "tools");
return false;
}
case CSharpOptions.ActionTypes.MonoLink:
{
// Setup arguments
var args = new List<string>();
//args.AddRange(options.LinkEnv.CustomArgs);
{
args.Add(string.Format("-o \"{0}\"", options.OutputFiles[0].Replace('\\', '/')));
//AddSharedArgs(args, options, false, false);
// Setup memory
var initialMemory = Configuration.WebInitialMemory;
//if (options.CompileEnv.Sanitizers.HasFlag(Sanitizer.Address))
// initialMemory = Math.Max(initialMemory, 64); // Address Sanitizer needs more memory
/*args.Add($"-sINITIAL_MEMORY={initialMemory}MB");
args.Add("-sSTACK_SIZE=4MB");
args.Add("-sALLOW_MEMORY_GROWTH=1");
// Setup file access (Game Cooker packs files with file_packager tool)
args.Add("-sFORCE_FILESYSTEM");*/
//args.Add("-sLZ4");
// https://emscripten.org/docs/compiling/Dynamic-Linking.html#dynamic-linking
// TODO: use -sMAIN_MODULE=2 and -sSIDE_MODULE=2 to strip unused code (mark public APIs with EMSCRIPTEN_KEEPALIVE)
/*if (options.LinkEnv.Output == LinkerOutput.Executable)
{
args.Add("-sMAIN_MODULE");
args.Add("-sEXPORT_ALL");
}
else*/
{
args.Add("-sSIDE_MODULE");
}
}
args.Add("-Wl,--allow-multiple-definition"); // Multiple pthread-related definitions in dotnet runtime
args.Add("-Wl,--start-group");
// Input libraries
var libraryPaths = new HashSet<string>();
var dynamicLibExt = Platform.SharedLibraryFileExtension;
var executableExt = Platform.ExecutableFileExtension;
foreach (var library in options.InputFiles)
{
/*var dir = Path.GetDirectoryName(library);
var ext = Path.GetExtension(library);
if (library.StartsWith("--use-port="))
{
// Ports (https://emscripten.org/docs/compiling/Building-Projects.html#emscripten-ports)
args.Add(library);
}
else if (string.IsNullOrEmpty(dir))
{
args.Add(string.Format("\"-l{0}\"", library));
}
else if (ext == executableExt)
{
// Skip executable
}
else if (ext == dynamicLibExt)
{
// Link against dynamic library
//task.PrerequisiteFiles.Add(library);
libraryPaths.Add(dir);
args.Add(string.Format("\"-l{0}\"", GetLibName(library)));
}
else
{
//task.PrerequisiteFiles.Add(library);
args.Add(string.Format("\"-l{0}\"", GetLibName(library)));
libraryPaths.Add(dir); // FIXME
}*/
args.Add(library.Replace(Path.DirectorySeparatorChar, '/') + Platform.StaticLibraryFileExtension);
}
// Input files (link static libraries last)
/*task.PrerequisiteFiles.AddRange(options.LinkEnv.InputFiles);
foreach (var file in options.LinkEnv.InputFiles.Where(x => !x.EndsWith(".a")).Concat(options.LinkEnv.InputFiles.Where(x => x.EndsWith(".a"))))
{
args.Add(string.Format("\"{0}\"", file.Replace('\\', '/')));
}
// Additional lib paths
libraryPaths.AddRange(options.LinkEnv.LibraryPaths);
foreach (var path in libraryPaths)
{
args.Add(string.Format("-L\"{0}\"", path.Replace('\\', '/')));
}*/
args.Add("-Wl,--end-group");
// Use a response file (it can contain any commands that you would specify on the command line)
bool useResponseFile = true;
string responseFile = null;
if (useResponseFile)
{
responseFile = Path.Combine(options.AssembliesPath, Path.GetFileName(options.OutputFiles[0]) + ".response");
//task.PrerequisiteFiles.Add(responseFile);
Utilities.WriteFileIfChanged(responseFile, string.Join(Environment.NewLine, args));
args.Clear();
args.Add(string.Format("@\"{0}\"", responseFile));
}
//task.WorkingDirectory = options.WorkingDirectory;
//task.CommandPath = _compilerPath;
//task.CommandArguments = string.Join(" ", args);
int result = Utilities.Run(NativeCompilerPath, $"{string.Join(" ", args)}", null, Path.GetDirectoryName(options.OutputFiles[0]), Utilities.RunOptions.AppMustExist | Utilities.RunOptions.ConsoleLogOutput);
if (result != 0)
return true;
return false;
}
case CSharpOptions.ActionTypes.MonoCompile:
{
string binaryExtension = Platform.BuildPlatform.Target == TargetPlatform.Windows ? ".exe" : "";
@@ -298,11 +412,11 @@ namespace Flax.Build.Platforms
var outputFileDylib = options.OutputFiles[0];
var inputFileFolder = Path.GetDirectoryName(inputFile);
if (Path.GetFileNameWithoutExtension(inputFile) == "System.Private.CoreLib")
/*if (Path.GetFileNameWithoutExtension(inputFile) == "System.Private.CoreLib")
{
// Pre-compiled, skip
return false;
}
}*/
string outputFile;
{
@@ -320,15 +434,24 @@ namespace Flax.Build.Platforms
var llvmPath = "\"C:\\Program Files\\LLVM\\bin\"";//Path.Combine(EmscriptenSdk.Instance.EmscriptenPath, "bin");
var monoAotMode = "full";
if (useLLVM)
monoAotMode = "llvmonly";
//if ("mscorlib.dll" == "")
// monoAotMode = "interp";
var monoDebugMode = debugSymbols ? "soft-debug" : "nodebug";
var aotCompilerArgs = $"--verbose{(useLLVM ? " --llvm" : "")} --aot={monoAotMode},llvmonly,verbose,stats,print-skipped,{monoDebugMode}{(useLLVM ? ",llvm-outfile="+Path.GetFileName(outputFile) : "")} -O=float32";
var aotCompilerArgs = $"{(useLLVM ? "--llvm" : "")} --aot={monoAotMode},asmonly,verbose,stats,print-skipped,{monoDebugMode}{(useLLVM ? $",llvm-path={llvmPath},llvm-outfile=" + Path.GetFileName(outputFile) : "")} -O=float32";
//aotCompilerArgs += " --verbose";
//aotCompilerArgs += $" --aot-path=\"{inputFileFolder}\"";
//var aotCompilerArgs = $"{(useLLVM ? " --llvm" : "")} --aot=static,llvmonly,verbose,stats,print-skipped,llvm-path={llvmPath},{monoDebugMode}{(useLLVM ? ",llvm-outfile=" + Path.GetFileName(outputFile) : "")} -O=float32";
//var aotCompilerArgs = $"{(useLLVM ? " --llvm" : "")} --aot=static,llvmonly,verbose,stats,print-skipped,{monoDebugMode}{(useLLVM ? ",llvm-outfile=" + Path.GetFileName(outputFile) : "")} -O=float32";
//if (debugSymbols || options.EnableToolDebug)
// aotCompilerArgs = "--debug " + aotCompilerArgs;
var envVars = new Dictionary<string, string>();
envVars["MONO_PATH"] = options.AssembliesPath + ":" + options.ClassLibraryPath;
envVars["MONO_PATH"] = options.ClassLibraryPath.Replace('/', Path.DirectorySeparatorChar) + Path.PathSeparator + options.AssembliesPath.Replace('/', Path.DirectorySeparatorChar);
Log.Info("MONO_PATH: " + envVars["MONO_PATH"]);
if (options.EnableToolDebug)
{
envVars["MONO_LOG_LEVEL"] = "debug";

View File

@@ -500,6 +500,9 @@ namespace Flax.Build.Platforms
// List Include Files
//commonArgs.Add("/showIncludes");
commonArgs.Add("/permissive-");
commonArgs.Add("/Zc:externC-");
// Code Analysis
commonArgs.Add("/analyze-");