Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
90954d7
wip build for wasm
brendan-duncan Aug 12, 2025
7c16399
wip wasm build updates
brendan-duncan Aug 13, 2025
5882484
temp disable build from unity
brendan-duncan Aug 13, 2025
2db9ee9
add ktx port
brendan-duncan Aug 17, 2025
3485f96
fix wasm build
brendan-duncan Aug 22, 2025
2119030
fix generated path
brendan-duncan Aug 22, 2025
631bc48
generated path for webgl
brendan-duncan Aug 22, 2025
aac411e
use generated-WebGL instead of generated-Web
brendan-duncan Aug 23, 2025
36a29d9
update wasm cmake
brendan-duncan Aug 23, 2025
83417d9
Merge branch 'experiment_wasm' of https://github.com/brendan-duncan/c…
brendan-duncan Aug 23, 2025
efa3aef
install directly to plugins folder
brendan-duncan Aug 23, 2025
ecd5adf
install libs to plugins folder
brendan-duncan Aug 24, 2025
eb2ef24
Use custom JS webrequest for wasm
brendan-duncan Aug 24, 2025
454d6f8
fix editor build
brendan-duncan Aug 24, 2025
5d82a09
re-enable building for non-web
brendan-duncan Aug 24, 2025
88951ab
Change UnityTaskProcessor to use std::thread instead of System::Threa…
brendan-duncan Aug 25, 2025
25900c3
clean up printf
brendan-duncan Aug 25, 2025
6d768f7
Use a threadpool for UnityTaskProcessor wasm
brendan-duncan Aug 26, 2025
c0cb50e
Use main thread for UnityPrepareRenderResources wasm
brendan-duncan Aug 26, 2025
d69ac2b
change thread pool size to 4
brendan-duncan Aug 27, 2025
83c7aee
Add option to build wasm64
brendan-duncan Aug 27, 2025
497e9a7
Fix ezvcpkg dependency finding
brendan-duncan Aug 28, 2025
5561549
fix cors issue with google servers
brendan-duncan Aug 29, 2025
c6ce3c4
Build webgl native library from Unity build
brendan-duncan Aug 29, 2025
d02fa4f
disable wip wasm builder
brendan-duncan Aug 29, 2025
babb24b
Fix in-unity build of CesiumForUnityNative library for web
brendan-duncan Aug 29, 2025
947f34d
exclude libjpeg-turbo and add a meta file for libastcenc-none-static.…
brendan-duncan Aug 30, 2025
f1dc060
Fix web build failing first time
brendan-duncan Aug 30, 2025
966739e
WIP build on mac
brendan-duncan Sep 1, 2025
4f97617
add web builder to Package.cs
brendan-duncan Sep 1, 2025
c83ad80
Add EM_CONFIG to VCPKG_ENV_PASSTHROUGH_UNTRACKED
brendan-duncan Sep 4, 2025
a1b0ff2
Mark web static libs as WebGL Only
brendan-duncan Sep 4, 2025
f414f13
marge updates
brendan-duncan Sep 21, 2025
846cd22
Copy emscripten if unity path contains spaces
brendan-duncan Sep 22, 2025
53b7a05
print error if temp path has spaces
brendan-duncan Sep 22, 2025
400627a
delete temp emspcripten directory
brendan-duncan Sep 23, 2025
9c9b0f0
Use drive map instead of copy for emscripten path with space
brendan-duncan Sep 30, 2025
d94ce4d
Merge branch 'main' into experiment_wasm
brendan-duncan Oct 5, 2025
d8dd7ef
Clean up emsdk temp drive map
brendan-duncan Oct 6, 2025
bd504cc
Use ports to fix openssl and cpp-httplib build errors
brendan-duncan Oct 11, 2025
cf8d035
Merge branch 'main' into experiment_wasm
brendan-duncan Oct 19, 2025
b11d7a4
code cleanup
brendan-duncan Oct 20, 2025
f08c06f
code cleanup
brendan-duncan Oct 20, 2025
8d8dd53
revert mat changes
brendan-duncan Oct 20, 2025
1fc0742
code cleanup
brendan-duncan Oct 20, 2025
2aff99b
code cleanup
brendan-duncan Oct 20, 2025
5c54ac6
code cleanup
brendan-duncan Oct 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@
[submodule "Documentation~/doxygen-awesome-css"]
path = Documentation~/doxygen-awesome-css
url = https://github.com/jothepro/doxygen-awesome-css.git
[submodule "native~/extern/blend2d"]
path = native~/extern/blend2d
url = https://github.com/blend2d/blend2d
16 changes: 16 additions & 0 deletions Build~/Package.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,22 @@ public void Run()

Console.WriteLine("**** Adding generated files (for the Android Player) to the package");
AddGeneratedFiles("!UNITY_EDITOR && UNITY_ANDROID", generatedRuntimePath, Path.Combine(outputPackagePath, "Runtime", "generated"));

Console.WriteLine("**** Compiling for Web Player");
unity.Run(new[]
{
"-batchmode",
"-nographics",
"-projectPath",
Utility.ProjectRoot,
"-buildTarget",
"WebGL",
"-executeMethod",
"CesiumForUnity.BuildCesiumForUnity.CompileForWebAndExit"
});

Console.WriteLine("**** Adding generated files (for the Android Player) to the package");
AddGeneratedFiles("!UNITY_EDITOR && UNITY_ANDROID", generatedRuntimePath, Path.Combine(outputPackagePath, "Runtime", "generated"));
}
else if (OperatingSystem.IsMacOS())
{
Expand Down
19 changes: 19 additions & 0 deletions Editor/BuildCesiumForUnity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,25 @@ public static void CompileForAndroidAndExit()
EditorApplication.Exit(0);
}

public static void CompileForWebAndExit()
{
CompileCesiumForUnityNative.ExitAfterCompile = true;

string buildPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(buildPath);
try
{
PlayerSettings.SetScriptingBackend(BuildTargetGroup.WebGL, ScriptingImplementation.IL2CPP);
PlayerSettings.WebGL.threadsSupport = true;
BuildPlayer(BuildTargetGroup.WebGL, BuildTarget.WebGL, Path.Combine(buildPath, "WebGL"));
}
finally
{
Directory.Delete(buildPath, true);
}
EditorApplication.Exit(0);
}

public static void CompileForUWPAndExit()
{
CompileCesiumForUnityNative.ExitAfterCompile = true;
Expand Down
163 changes: 162 additions & 1 deletion Editor/CompileCesiumForUnityNative.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using UnityEditor.Build.Reporting;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.IO;
using System.Text;
using System;
Expand Down Expand Up @@ -122,6 +123,8 @@ private static string GetSharedLibraryFilename(string baseName, BuildTarget targ
return $"lib{baseName}.a";
case BuildTarget.StandaloneOSX:
return $"lib{baseName}.dylib";
case BuildTarget.WebGL:
return $"lib{baseName}.a";
default:
// Assume Linux-ish
return $"lib{baseName}.so";
Expand Down Expand Up @@ -432,8 +435,103 @@ private static string GetInstallDirectoryForPlatform(PlatformToBuild platform, s
return Path.Combine(packagePath, "Plugins", GetDirectoryNameForPlatform(platform));
}

// Web builds use static libraries (.a files) that need to be marked as only
// compatible with WebGL. This is normally done in OnPostprocessAllAssets, but
// that only includes the main libCesiumForUnityNative.a library, not the other
// static libraries.
private static void SetWebGLStaticLibrariesPlatform(string webglPluginsPath)
{
if (!Directory.Exists(webglPluginsPath))
return;

// Find all static library files (.a) in the directory and its subdirectories.
string[] libraryFiles = Directory.GetFiles(webglPluginsPath, "*.a", SearchOption.AllDirectories);
if (libraryFiles.Length == 0)
return;

AssetDatabase.StartAssetEditing();

foreach (string filePath in libraryFiles)
{
// Application.datapath is the <project>/Assets folder. We need to strip off that
// part and prepend "Packages" to get the correct asset path.
string assetPath = "Packages" + filePath.Substring(Application.dataPath.Length + 2);

// Get the importer for the asset.
PluginImporter importer = AssetImporter.GetAtPath(assetPath) as PluginImporter;

if (importer != null)
{
// Disable "Any Platform" to enable platform-specific settings.
importer.SetCompatibleWithAnyPlatform(false);

// Exclude from all platforms before enabling the desired one.
// This ensures the library is ONLY active on WebGL.
importer.SetCompatibleWithPlatform(BuildTarget.Android, false);
importer.SetCompatibleWithPlatform(BuildTarget.iOS, false);
importer.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows, false);
importer.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows64, false);
importer.SetCompatibleWithPlatform(BuildTarget.StandaloneOSX, false);
importer.SetCompatibleWithPlatform(BuildTarget.StandaloneLinux64, false);
importer.SetCompatibleWithEditor(false);

// We need to exclude libastcenc-none-static.a as it's being installed, but conflicts with
// Unity's symbols.
bool supportsWebGL = !assetPath.EndsWith("libastcenc-none-static.a");

importer.SetCompatibleWithPlatform(BuildTarget.WebGL, supportsWebGL);

importer.SaveAndReimport();
}
}

AssetDatabase.StopAssetEditing();
}

internal static void BuildNativeLibrary(LibraryToBuild library)
{
var emscriptenDir = "";
var deleteTemporaryEmscriptenDir = false;

if (library.Platform == BuildTarget.WebGL)
{
// Find the Emscripten that ships with the Unity WebGL platform
var editorDir = EditorApplication.applicationContentsPath;
emscriptenDir = Path.Combine(editorDir, "PlaybackEngines", "WebGLSupport", "BuildTools", "Emscripten");
if (!Directory.Exists(emscriptenDir))
{
// Check for editor built from source
editorDir = new FileInfo(Path.Combine(editorDir, "..", "..", "..", "..")).FullName;
emscriptenDir = Path.Combine(editorDir, "WebGLSupport", "BuildTools", "Emscripten");
if (!Directory.Exists(emscriptenDir))
{
// Check for editor built from source on mac
editorDir = new FileInfo(Path.Combine(editorDir, "..")).FullName;
emscriptenDir = Path.Combine(editorDir, "WebGLSupport", "BuildTools", "Emscripten");
if (!Directory.Exists(emscriptenDir))
{
UnityEngine.Debug.LogError($"Emscripten directory does not exist at: {emscriptenDir}. Cannot build Web version of CesiumForUnityNative.");
return;
}
}
}

if (emscriptenDir.Contains(' '))
{
// Some ezvcpkg libraries like openssl fail to build if the path to compilation tools contains spaces.
// The default Unity install path on Windows does contain spaces as it's put into "Program Files".
// Use subst to map the Emscripten directory to a drive letter, eliminating the space.
// When the process finishes, we will delete the mapping.
char driveLetter = 'M';
if (!Directory.Exists(driveLetter + ":\\"))
{
Process.Start("subst", driveLetter + ": \"" + emscriptenDir + "\"").WaitForExit();
deleteTemporaryEmscriptenDir = true;
}
emscriptenDir = driveLetter + ":\\";
}
}

if (library.CleanBuild && library.BuildDirectory.Length > 2 && Directory.Exists(library.BuildDirectory))
Directory.Delete(library.BuildDirectory, true);
Directory.CreateDirectory(library.BuildDirectory);
Expand All @@ -454,6 +552,13 @@ internal static void BuildNativeLibrary(LibraryToBuild library)
{
startInfo.FileName = File.Exists("/Applications/CMake.app/Contents/bin/cmake") ? "/Applications/CMake.app/Contents/bin/cmake" : "cmake";
}
else if (library.Platform == BuildTarget.WebGL)
{
if (SystemInfo.operatingSystemFamily == OperatingSystemFamily.Windows)
startInfo.FileName = $"{emscriptenDir}/emscripten/emcmake.bat";
else
startInfo.FileName = $"{emscriptenDir}/emscripten/emcmake";
}
else
{
startInfo.FileName = "cmake";
Expand All @@ -464,6 +569,30 @@ internal static void BuildNativeLibrary(LibraryToBuild library)
startInfo.RedirectStandardOutput = true;
ConfigureEnvironmentVariables(startInfo.Environment, library);

var EM_CONFIG = "";
if (library.Platform == BuildTarget.WebGL)
{
startInfo.EnvironmentVariables["EMSDK"] = emscriptenDir;
startInfo.EnvironmentVariables["EMCC_SKIP_SANITY_CHECK"] = "1";
startInfo.EnvironmentVariables["EM_FROZEN_CACHE"] = "1";
startInfo.EnvironmentVariables["EM_WORKAROUND_PYTHON_BUG_34780"] = "1";
startInfo.EnvironmentVariables["EM_WORKAROUND_WIN7_BAD_ERRORLEVEL_BUG"] = "1";
startInfo.EnvironmentVariables["PYTHONUTF8"] = "1";

EM_CONFIG = Path.Combine(emscriptenDir, ".emscripten");
startInfo.EnvironmentVariables["EM_CONFIG"] = EM_CONFIG;
startInfo.EnvironmentVariables["EM_PYTHON"] = Path.Combine(emscriptenDir, "python",
(SystemInfo.operatingSystemFamily == OperatingSystemFamily.Linux) ? "python3" :
(SystemInfo.operatingSystemFamily == OperatingSystemFamily.Windows) ? Path.Combine("python.exe") :
(SystemInfo.operatingSystemFamily == OperatingSystemFamily.MacOSX) ? Path.Combine("bin", "python3") :
"python");

var path = startInfo.EnvironmentVariables.ContainsKey("PATH") ? startInfo.EnvironmentVariables["PATH"] : "";
if (path == "")
path = Environment.GetEnvironmentVariable("Path");
startInfo.EnvironmentVariables["PATH"] = $"{emscriptenDir}/emscripten;{emscriptenDir}/node;{emscriptenDir}/python;{emscriptenDir}/python/bin;{path}";
}

List<string> args = new List<string>()
{
"-B",
Expand All @@ -475,6 +604,16 @@ internal static void BuildNativeLibrary(LibraryToBuild library)
$"-DCMAKE_INSTALL_PREFIX=\"{library.InstallDirectory}\"",
$"-DREINTEROP_GENERATED_DIRECTORY={library.GeneratedDirectoryName}",
};

if (library.Platform == BuildTarget.WebGL)
{
args.Insert(0, "cmake");
args.Add("-DBUILD_SHARED_LIB=OFF");
args.Add("-DCESIUM_ENABLE_CLANG_TIDY=OFF");
var generatedInclude = Path.Combine(library.SourceDirectory, "Runtime", library.GeneratedDirectoryName, "include");
args.Add($"-DCMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES=\"{generatedInclude}\"");
}

args.AddRange(library.ExtraConfigureArgs);

if (library.Toolchain != null)
Expand All @@ -484,6 +623,9 @@ internal static void BuildNativeLibrary(LibraryToBuild library)

RunAndLog(startInfo, log, logFilename);

if (library.Platform == BuildTarget.WebGL)
startInfo.FileName = "cmake";

args = new List<string>()
{
"--build",
Expand All @@ -499,13 +641,32 @@ internal static void BuildNativeLibrary(LibraryToBuild library)
startInfo.Arguments = string.Join(' ', args);
RunAndLog(startInfo, log, logFilename);

if (library.Platform == BuildTarget.iOS)
// Refresh the asset database for platforms that use static linking so the Unity
// builder can find the libraries.
if (library.Platform == BuildTarget.iOS || library.Platform == BuildTarget.WebGL)
AssetDatabase.Refresh();

if (library.Platform == BuildTarget.WebGL)
SetWebGLStaticLibrariesPlatform(library.InstallDirectory);
}
}
finally
{
EditorUtility.ClearProgressBar();
if (deleteTemporaryEmscriptenDir)
{
try
{
var driveLetter = emscriptenDir[0];
UnityEngine.Debug.Log("Deleting temporary Emscripten drive mapping: " + driveLetter + ":");
Process.Start("subst", driveLetter + ": /D").WaitForExit();
}
catch (Exception)
{
// Ignore any errors here.
UnityEngine.Debug.LogWarning("Failed to delete temporary Emscripten drive mapping: " + emscriptenDir);
}
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions Editor/ConfigureReinterop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ internal partial class ConfigureReinterop
public const string CppOutputPath = "../native~/Runtime/generated-WSA";
#elif UNITY_64
public const string CppOutputPath = "../native~/Editor/generated-Standalone";
#elif UNITY_WEBGL
public const string CppOutputPath = "../native~/Editor/generated-WebGL";
#else
public const string CppOutputPath = "../native~/Editor/generated-Unknown";
#endif
Expand Down
3 changes: 2 additions & 1 deletion Runtime/CesiumRuntime.asmdef
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"iOS",
"macOSStandalone",
"WSA",
"WindowsStandalone64"
"WindowsStandalone64",
"WebGL"
],
"excludePlatforms": [],
"allowUnsafeCode": true,
Expand Down
4 changes: 3 additions & 1 deletion Runtime/ConfigureReinterop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ internal partial class ConfigureReinterop
public const string CppOutputPath = "../native~/Runtime/generated-WSA";
#elif UNITY_64
public const string CppOutputPath = "../native~/Runtime/generated-Standalone";
#elif UNITY_WEBGL
public const string CppOutputPath = "../native~/Runtime/generated-WebGL";
#else
public const string CppOutputPath = "../native~/Runtime/generated-Unknown";
#endif
Expand All @@ -45,7 +47,7 @@ internal partial class ConfigureReinterop
public const string BaseNamespace = "DotNet";

// The name of the DLL or SO containing the C++ code.
#if UNITY_IOS && !UNITY_EDITOR
#if (UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR
public const string NativeLibraryName = "__Internal";
#else
public const string NativeLibraryName = "CesiumForUnityNative-Runtime";
Expand Down
Loading