Added SDK

This commit is contained in:
Andrew Zambazos
2026-06-11 14:01:22 +12:00
commit c0395a49bd
2155 changed files with 451005 additions and 0 deletions
+157
View File
@@ -0,0 +1,157 @@
include(CMakeParseArguments)
include(Platform)
include(embed_files)
if (${UL_ENABLE_STATIC_BUILD})
include(StaticLibs)
endif ()
set(SDK_ROOT "${UL_SDK_PATH}")
set(ULTRALIGHT_INCLUDE_DIR "${SDK_ROOT}/include")
set(ULTRALIGHT_BINARY_DIR "${SDK_ROOT}/bin")
set(ULTRALIGHT_INSPECTOR_DIR "${SDK_ROOT}/inspector")
set(ULTRALIGHT_RESOURCES_DIR "${SDK_ROOT}/resources")
set(ULTRALIGHT_LIBRARY_DIR "${SDK_ROOT}/bin"
"${SDK_ROOT}/lib")
get_filename_component(INFO_PLIST_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Info.plist.in" REALPATH)
get_filename_component(ENTITLEMENTS_PLIST_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Entitlements.plist" REALPATH)
macro(add_console_app)
set(APP_NAME ${ARGV0})
set(options "NEEDS_INSPECTOR" "EMBED_FILES")
set(oneValueArgs "")
set(multiValueArgs "SOURCES")
cmake_parse_arguments("ARGS"
"${options}"
"${oneValueArgs}"
"${multiValueArgs}"
${ARGN})
include_directories("${ULTRALIGHT_INCLUDE_DIR}")
link_directories("${ULTRALIGHT_LIBRARY_DIR}")
link_libraries(UltralightCore Ultralight WebCore AppCore)
if (${UL_ENABLE_STATIC_BUILD})
add_definitions(-DULTRALIGHT_STATIC_BUILD)
link_libraries(${UL_STATIC_LIBS})
endif ()
if (UL_PLATFORM MATCHES "macos")
set(CMAKE_INSTALL_RPATH ".")
endif ()
add_executable(${APP_NAME} ${ARGS_SOURCES})
# Always link to the C++ standard library
set_target_properties(${APP_NAME} PROPERTIES LINKER_LANGUAGE CXX)
set(INSTALL_PATH "${INSTALL_DIR}/${APP_NAME}")
install(TARGETS ${APP_NAME}
RUNTIME DESTINATION "${INSTALL_PATH}"
BUNDLE DESTINATION "${INSTALL_PATH}")
install(DIRECTORY "${ULTRALIGHT_BINARY_DIR}/" DESTINATION "${INSTALL_PATH}")
install(DIRECTORY "${ULTRALIGHT_RESOURCES_DIR}" DESTINATION "${INSTALL_PATH}/assets")
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/assets/" DESTINATION "${INSTALL_PATH}/assets" OPTIONAL)
# Conditionally embed additional assets based on EMBED_FILES
if (ARGS_EMBED_FILES)
endif ()
endmacro ()
macro(add_app)
set(APP_NAME ${ARGV0})
set(prefix "ARGS")
set(options "NEEDS_INSPECTOR" "EMBED_FILES")
set(oneValueArgs "")
set(multiValueArgs "SOURCES")
cmake_parse_arguments(${prefix}
"${options}"
"${oneValueArgs}"
"${multiValueArgs}"
${ARGN})
include_directories("${ULTRALIGHT_INCLUDE_DIR}")
link_directories("${ULTRALIGHT_LIBRARY_DIR}")
link_libraries(UltralightCore AppCore Ultralight WebCore)
if (${UL_ENABLE_STATIC_BUILD})
add_definitions(-DULTRALIGHT_STATIC_BUILD)
link_libraries(${UL_STATIC_LIBS} ${APPCORE_STATIC_LIBS})
endif ()
add_executable(${APP_NAME} WIN32 MACOSX_BUNDLE ${ARGS_SOURCES})
# Always link to the C++ standard library
set_target_properties(${APP_NAME} PROPERTIES LINKER_LANGUAGE CXX)
if (ARGS_EMBED_FILES)
set(EMBEDDED_FOLDERS "${CMAKE_CURRENT_SOURCE_DIR}/assets/"
"${ULTRALIGHT_RESOURCES_DIR}")
if (ARGS_NEEDS_INSPECTOR)
list(APPEND EMBEDDED_FOLDERS "${ULTRALIGHT_INSPECTOR_DIR}")
endif ()
embed_files(${APP_NAME} FOLDERS ${EMBEDDED_FOLDERS})
endif ()
set(INSTALL_PATH "${INSTALL_DIR}/${APP_NAME}")
if (UL_PLATFORM MATCHES "macos")
# Include Entitlements.plist
set_source_files_properties(${ENTITLEMENTS_PLIST_PATH} PROPERTIES MACOSX_PACKAGE_LOCATION "Contents")
# Enable High-DPI on macOS through our custom Info.plist template
set_target_properties(${APP_NAME} PROPERTIES
BUNDLE True
MACOSX_BUNDLE_GUI_IDENTIFIER ultralight.${APP_NAME}
MACOSX_BUNDLE_BUNDLE_NAME ${APP_NAME}
MACOSX_BUNDLE_EXECUTABLE_NAME ${APP_NAME}
MACOSX_BUNDLE_BUNDLE_VERSION "1.0"
MACOSX_BUNDLE_SHORT_VERSION_STRING "1.0"
MACOSX_BUNDLE_INFO_PLIST ${INFO_PLIST_PATH}
)
# Set the install destination for the app bundle
set(BUNDLE_INSTALL_PATH "${INSTALL_PATH}/${APP_NAME}.app")
set(BUNDLE_EXEC_PATH "${BUNDLE_INSTALL_PATH}/Contents/MacOS")
set(BUNDLE_RESOURCE_PATH "${BUNDLE_INSTALL_PATH}/Contents/Resources")
set(BUNDLE_ASSETS_PATH "${BUNDLE_RESOURCE_PATH}/assets")
install(TARGETS ${APP_NAME} BUNDLE DESTINATION "${INSTALL_PATH}")
install(DIRECTORY "${ULTRALIGHT_BINARY_DIR}/" DESTINATION "${BUNDLE_EXEC_PATH}")
if (NOT ARGS_EMBED_FILES)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/assets/" DESTINATION "${BUNDLE_ASSETS_PATH}" OPTIONAL)
install(DIRECTORY "${ULTRALIGHT_RESOURCES_DIR}" DESTINATION "${BUNDLE_ASSETS_PATH}")
if (ARGS_NEEDS_INSPECTOR)
install(DIRECTORY "${ULTRALIGHT_INSPECTOR_DIR}" DESTINATION "${BUNDLE_ASSETS_PATH}")
endif()
endif()
else ()
if (UL_PLATFORM MATCHES "windows")
# Use main instead of WinMain for Windows subsystem executables
set_target_properties(${APP_NAME} PROPERTIES LINK_FLAGS "/ENTRY:mainCRTStartup")
endif()
set(ASSETS_PATH "${INSTALL_PATH}/assets")
set(BIN_PATH "${INSTALL_PATH}")
install(TARGETS ${APP_NAME} RUNTIME DESTINATION "${INSTALL_PATH}")
install(DIRECTORY "${ULTRALIGHT_BINARY_DIR}/" DESTINATION "${BIN_PATH}")
if (NOT ARGS_EMBED_FILES)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/assets/" DESTINATION "${ASSETS_PATH}" OPTIONAL)
install(DIRECTORY "${ULTRALIGHT_RESOURCES_DIR}" DESTINATION "${ASSETS_PATH}")
if (ARGS_NEEDS_INSPECTOR)
install(DIRECTORY "${ULTRALIGHT_INSPECTOR_DIR}" DESTINATION "${ASSETS_PATH}")
endif()
endif()
endif ()
endmacro ()
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.files.downloads.read-write</key>
<true/>
</dict>
</plist>
+22
View File
@@ -0,0 +1,22 @@
include(BundleUtilities)
# Set bundle to the full path name of the executable already
# existing in the install tree:
set(bundle "@BUNDLE_PATH@")
# Set other_libs to a list of full path names to additional
# libraries that cannot be reached by dependency analysis.
# (Dynamically loaded PlugIns, for example.)
set(other_libs "")
# Set dirs to a list of directories where prerequisite libraries
# may be found:
set(dirs
"@CMAKE_RUNTIME_OUTPUT_DIRECTORY@"
"@CMAKE_LIBRARY_OUTPUT_DIRECTORY@"
"@ULTRALIGHT_BINARY_DIR@"
"/usr/local/opt/llvm@11/lib/"
)
fixup_bundle("${bundle}" "${other_libs}" "${dirs}")
+38
View File
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
<key>CFBundleGetInfoString</key>
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
<key>CFBundleIconFile</key>
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
<key>CFBundleIdentifier</key>
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
<key>CFBundleName</key>
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
<key>NSHighResolutionCapable</key>
<string>true</string>
<key>NSAppSandbox</key>
<true/>
</dict>
</plist>
+21
View File
@@ -0,0 +1,21 @@
if (NOT UL_PLATFORM)
if(CMAKE_SYSTEM_NAME MATCHES "Windows")
set(UL_PLATFORM "windows")
elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin")
set(UL_PLATFORM "macos")
elseif (CMAKE_SYSTEM_NAME MATCHES "Linux")
set(UL_PLATFORM "linux")
else ()
message(FATAL_ERROR "Unable to detect target platform. Please manually specify UL_PLATFORM when running CMake.")
endif ()
endif ()
if (UL_PLATFORM MATCHES "macos")
SET(CMAKE_SKIP_BUILD_RPATH FALSE)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
SET(CMAKE_INSTALL_RPATH "@executable_path/")
elseif (UL_PLATFORM MATCHES "linux")
SET(CMAKE_SKIP_BUILD_RPATH FALSE)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
SET(CMAKE_INSTALL_RPATH "$\{ORIGIN\}")
endif ()
+55
View File
@@ -0,0 +1,55 @@
function(embed_files TARGET)
cmake_parse_arguments(EMBED_FILES "" "" "FOLDERS" ${ARGN})
set(EMBED_FILES_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/EmbeddedFiles")
set(EMBED_FILES_HEADER "${EMBED_FILES_OUTPUT_DIR}/EmbeddedFiles.h")
set(EMBED_FILES_RC "${EMBED_FILES_OUTPUT_DIR}/data.rc")
# Find the Python executable
find_package(Python COMPONENTS Interpreter)
if(Python_FOUND)
set(PYTHON_EXECUTABLE ${Python_EXECUTABLE})
else()
find_program(PYTHON_EXECUTABLE NAMES python python2 python3)
endif()
if(NOT PYTHON_EXECUTABLE)
message(FATAL_ERROR "Python executable not found.")
endif()
# Find the embed_files.py script
find_file(EMBED_FILES_SCRIPT NAMES embed_files.py PATHS ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_MODULE_PATH})
if(NOT EMBED_FILES_SCRIPT)
message(FATAL_ERROR "embed_files.py script not found.")
endif()
# Add the output directory to the target's include directories
target_include_directories(${TARGET} PRIVATE ${EMBED_FILES_OUTPUT_DIR})
# Create a custom target to run the embed_files.py script unconditionally
add_custom_target(${TARGET}_embed_files
COMMAND ${CMAKE_COMMAND} -E make_directory ${EMBED_FILES_OUTPUT_DIR}
COMMAND ${PYTHON_EXECUTABLE} ${EMBED_FILES_SCRIPT} ${EMBED_FILES_FOLDERS} ${EMBED_FILES_OUTPUT_DIR}
BYPRODUCTS ${EMBED_FILES_HEADER} ${EMBED_FILES_RC}
COMMENT "Embedding files for target ${TARGET}"
VERBATIM
)
if (${ALLINONE_BUILD})
add_dependencies(${TARGET}_embed_files GenerateSDK)
endif ()
# Add the custom target as a dependency of the main target
add_dependencies(${TARGET} ${TARGET}_embed_files)
# Add the output header as a source file to the target
target_sources(${TARGET} PRIVATE ${EMBED_FILES_HEADER})
# Add the RC file to the target's source files on Windows
if(WIN32)
target_sources(${TARGET} PRIVATE ${EMBED_FILES_RC})
endif()
target_compile_definitions(${TARGET} PRIVATE UL_EMBED_FILES=1)
endfunction()
+158
View File
@@ -0,0 +1,158 @@
# embed_files.py
import os
import sys
import hashlib
import shutil
import platform
def embed_files(folder_paths, out_dir):
"""
Embeds files from the specified folder paths into a C++ application using the best available method
for each platform:
- Windows (MSVC/Clang-CL): Resource files (RC)
- MacOS / Linux (GCC/Clang): Inline assembly (.incbin)
Generates a C++ header (EmbeddedFiles.h) and, on Windows, a resource file (data.rc).
The embedded files can be retrieved via the GetEmbeddedFiles() function.
Args:
folder_paths (list): List of folder paths containing the files to be embedded.
out_dir (str): Output directory where the generated files will be stored.
"""
files_to_embed = []
output_hash = hashlib.sha256()
symbol_counter = 0
for folder_path in folder_paths:
if folder_path.endswith('/'):
base_path = folder_path
else:
base_path = os.path.dirname(folder_path) + '/'
for root, _, files in os.walk(folder_path):
for file in files:
abs_path = os.path.join(root, file)
abs_path = abs_path.replace('\\', '/') # Replace backslashes with forward slashes
rel_path = os.path.relpath(abs_path, base_path)
rel_path = rel_path.replace('\\', '/') # Replace backslashes with forward slashes
symbol_name = f"FILE_{symbol_counter}"
files_to_embed.append((abs_path, rel_path, symbol_name))
output_hash.update(str((abs_path, os.path.getmtime(abs_path))).encode())
symbol_counter += 1
output_header = os.path.join(out_dir, "EmbeddedFiles.h")
if not os.path.exists(out_dir):
os.makedirs(out_dir)
output_hash_hex = output_hash.hexdigest()
# Check if the hash has changed
hash_file = os.path.join(out_dir, "output_hash.txt")
if os.path.exists(hash_file):
with open(hash_file, "r") as f:
old_hash = f.read().strip()
if old_hash == output_hash_hex:
print("No changes detected in files_to_embed. Skipping file generation.")
return
output_header_content = """
#pragma once
#include <unordered_map>
#include <string>
#include <cstddef>
#include <cstdint>
using EmbeddedFilesMap = const std::unordered_map<std::string, std::pair<const uint8_t*, size_t>>;
"""
if platform.system() == "Windows":
# Windows: Use resource files (RC)
rc_file = os.path.join(out_dir, "data.rc")
rc_content = "#include \"winres.h\"\n"
for abs_path, rel_path, symbol_name in files_to_embed:
rc_content += """{symbol_name} RCDATA \"{abs_path}\"\n""".format(symbol_name=symbol_name, abs_path=abs_path)
with open(rc_file, "w") as f:
f.write(rc_content)
output_header_content += """
#include <windows.h>
inline std::pair<const uint8_t*, size_t> GetEmbeddedFileData(const char* resourceName) {
HRSRC hResource = FindResource(NULL, resourceName, RT_RCDATA);
if (hResource) {
HGLOBAL hData = LoadResource(NULL, hResource);
if (hData) {
const uint8_t* data = static_cast<const uint8_t*>(LockResource(hData));
size_t size = SizeofResource(NULL, hResource);
return std::make_pair(data, size);
}
}
return std::make_pair(nullptr, 0);
}
"""
output_header_content += """
inline EmbeddedFilesMap& GetEmbeddedFiles() {
static EmbeddedFilesMap embedded_files = {
"""
for _, rel_path, symbol_name in files_to_embed:
output_header_content += """
{{ "{rel_path}", GetEmbeddedFileData("{symbol_name}") }},""".format(rel_path=rel_path, symbol_name=symbol_name)
output_header_content += """
};
return embedded_files;
}
"""
else:
# MacOS / Linux: Use inline assembly (.incbin)
section = "__TEXT,__const" if platform.system() == "Darwin" else ".rodata,\\\"a\\\",@progbits"
for abs_path, rel_path, symbol_name in files_to_embed:
output_header_content += """
__asm__(".section {section}");
__asm__(".balign 16");
__asm__(".globl __binary_{symbol_name}_start");
__asm__("__binary_{symbol_name}_start:");
__asm__(".incbin \\"{abs_path}\\"");
__asm__(".globl __binary_{symbol_name}_end");
__asm__("__binary_{symbol_name}_end:");
extern const uint8_t __binary_{symbol_name}_start[] __asm__("__binary_{symbol_name}_start") __attribute__((aligned(16)));
extern const uint8_t __binary_{symbol_name}_end[] __asm__("__binary_{symbol_name}_end") __attribute__((aligned(16)));
""".format(section=section, symbol_name=symbol_name, abs_path=abs_path)
output_header_content += """
inline EmbeddedFilesMap& GetEmbeddedFiles() {
static EmbeddedFilesMap embedded_files = {
"""
for _, rel_path, symbol_name in files_to_embed:
output_header_content += """
{{ "{rel_path}", {{ __binary_{symbol_name}_start, static_cast<size_t>(__binary_{symbol_name}_end - __binary_{symbol_name}_start) }} }},""".format(rel_path=rel_path, symbol_name=symbol_name)
output_header_content += """
};
return embedded_files;
}
"""
with open(output_header, "w") as f:
f.write(output_header_content)
# Write the updated hash to the hash file
with open(hash_file, "w") as f:
f.write(output_hash_hex)
if __name__ == "__main__":
if len(sys.argv) < 3:
print("Usage: python2 embed_files.py <folder_path_1> [<folder_path_2> ...] <output_directory>")
sys.exit(1)
folder_paths = sys.argv[1:-1]
out_dir = sys.argv[-1]
embed_files(folder_paths, out_dir)