356 lines
12 KiB
CMake
356 lines
12 KiB
CMake
# wgpu-native WebGPU Implementation Configuration
|
|
|
|
if(TARGET mbgl-vendor-wgpu)
|
|
return()
|
|
endif()
|
|
|
|
if(NOT MLN_WITH_WEBGPU)
|
|
return()
|
|
endif()
|
|
|
|
message(STATUS "Configuring wgpu-native WebGPU implementation")
|
|
|
|
set(_mln_wgpu_source_dir "${PROJECT_SOURCE_DIR}/vendor/wgpu-native")
|
|
if ("${MLN_WEBGPU_IMPL_FFI_BUNDLED_WEBGPU_HEADER}" STREQUAL "")
|
|
set(WEBGPU_H_DIR ${_mln_wgpu_source_dir}/ffi/webgpu-headers)
|
|
else()
|
|
set(WEBGPU_H_DIR ${MLN_WEBGPU_IMPL_WEBGPU_HEADER_DIR})
|
|
endif()
|
|
|
|
# Check if wgpu-native exists
|
|
if(NOT EXISTS "${WEBGPU_H_DIR}/webgpu.h")
|
|
message(FATAL_ERROR
|
|
"wgpu-native not found at ${_mln_wgpu_source_dir}. "
|
|
"Please ensure the wgpu-native submodule is initialized: "
|
|
"git submodule update --init --recursive vendor/wgpu-native")
|
|
endif()
|
|
|
|
# wgpu-native provides pre-built binaries or can be built from source
|
|
# We'll look for prebuilt binaries first, then fall back to building from source
|
|
|
|
# Platform-specific library names and paths
|
|
if(APPLE)
|
|
if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
|
|
include("${CMAKE_CURRENT_LIST_DIR}/wgpu.ios.cmake")
|
|
else()
|
|
if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm64|aarch64")
|
|
set(_wgpu_lib_arch "aarch64-apple-darwin")
|
|
else()
|
|
set(_wgpu_lib_arch "x86_64-apple-darwin")
|
|
endif()
|
|
endif()
|
|
set(_wgpu_lib_name "libwgpu_native.a")
|
|
elseif(ANDROID)
|
|
include("${CMAKE_CURRENT_LIST_DIR}/wgpu.android.cmake")
|
|
elseif(WIN32)
|
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|
set(_wgpu_lib_arch "x86_64-pc-windows-msvc")
|
|
else()
|
|
set(_wgpu_lib_arch "i686-pc-windows-msvc")
|
|
endif()
|
|
set(_wgpu_lib_name "wgpu_native.lib")
|
|
else() # Linux
|
|
if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64")
|
|
set(_wgpu_lib_arch "aarch64-unknown-linux-gnu")
|
|
else()
|
|
set(_wgpu_lib_arch "x86_64-unknown-linux-gnu")
|
|
endif()
|
|
set(_wgpu_lib_name "libwgpu_native.a")
|
|
endif()
|
|
|
|
# Look for prebuilt wgpu-native library
|
|
# Search platform-specific path first to prefer cross-compiled libraries
|
|
set(_wgpu_lib_search_paths
|
|
"${_mln_wgpu_source_dir}/target/${_wgpu_lib_arch}/release"
|
|
)
|
|
if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
|
|
mln_wgpu_ios_append_search_paths(_wgpu_lib_search_paths)
|
|
endif()
|
|
list(APPEND _wgpu_lib_search_paths
|
|
"${_mln_wgpu_source_dir}/target/release"
|
|
"${_mln_wgpu_source_dir}/lib"
|
|
"${_mln_wgpu_source_dir}/build/release"
|
|
)
|
|
|
|
# Resolve the exact archive/import library filename emitted by wgpu-native.
|
|
macro(mln_wgpu_find_exact_library out_var out_description)
|
|
foreach(_search_path ${_wgpu_lib_search_paths})
|
|
if(EXISTS "${_search_path}/${_wgpu_lib_name}")
|
|
set(${out_var} "${_search_path}/${_wgpu_lib_name}" CACHE FILEPATH "${out_description}")
|
|
break()
|
|
endif()
|
|
endforeach()
|
|
endmacro()
|
|
|
|
# On Android/iOS, use manual path search since find_library may not work with cross-compilation toolchains
|
|
if (NOT MLN_WEBGPU_IMPL_FFI)
|
|
macro(mln_wgpu_find_library)
|
|
if(ANDROID OR CMAKE_SYSTEM_NAME STREQUAL "iOS")
|
|
mln_wgpu_find_exact_library(WGPU_LIBRARY "wgpu-native library")
|
|
else()
|
|
find_library(WGPU_LIBRARY
|
|
NAMES wgpu_native libwgpu_native
|
|
PATHS ${_wgpu_lib_search_paths}
|
|
NO_DEFAULT_PATH
|
|
NO_CMAKE_FIND_ROOT_PATH
|
|
)
|
|
endif()
|
|
endmacro()
|
|
|
|
mln_wgpu_find_library()
|
|
mln_wgpu_find_exact_library(WGPU_STATIC_LIBRARY "wgpu-native static library")
|
|
endif()
|
|
|
|
if(NOT MLN_WEBGPU_IMPL_FFI AND (NOT WGPU_LIBRARY OR MLN_WGPU_NATIVE_VERSION))
|
|
# Use a specific version of WGPU. This is required when to a rust application
|
|
# which uses wgpu directly instead of wgpu-native
|
|
if (MLN_WGPU_NATIVE_VERSION)
|
|
execute_process(
|
|
COMMAND git checkout ${MLN_WGPU_NATIVE_VERSION}
|
|
WORKING_DIRECTORY ${_mln_wgpu_source_dir}
|
|
RESULT_VARIABLE _git_checkout_wgpu_result
|
|
OUTPUT_VARIABLE _git_checkout_wgpu_output
|
|
ERROR_VARIABLE _git_checkout_wgpu_error
|
|
)
|
|
|
|
if(NOT _git_checkout_wgpu_result EQUAL 0)
|
|
message(FATAL_ERROR "Failed to checkout wgpu-native version '${MLN_WGPU_NATIVE_VERSION}': ${_git_checkout_wgpu_error}\n")
|
|
endif()
|
|
endif()
|
|
|
|
message(STATUS "Pre-built wgpu-native library not found, attempting to build from source...")
|
|
|
|
# Check if cargo is available
|
|
find_program(CARGO_EXECUTABLE cargo)
|
|
|
|
if(NOT CARGO_EXECUTABLE)
|
|
message(FATAL_ERROR
|
|
"wgpu-native library not found and cargo is not available to build it. "
|
|
"Please either:\n"
|
|
" 1. Install Rust and cargo (https://rustup.rs/), or\n"
|
|
" 2. Download pre-built wgpu-native binaries from https://github.com/gfx-rs/wgpu-native/releases\n"
|
|
" and place them in ${_mln_wgpu_source_dir}/target/release/")
|
|
endif()
|
|
|
|
# Build wgpu-native using cargo
|
|
message(STATUS "Building wgpu-native with cargo (this may take a few minutes)...")
|
|
|
|
# For cross-compilation targets (iOS, Android), pass --target and platform-specific features
|
|
set(_cargo_extra_args "")
|
|
if(_wgpu_lib_arch AND NOT _wgpu_lib_arch MATCHES "apple-darwin$")
|
|
list(APPEND _cargo_extra_args --target ${_wgpu_lib_arch})
|
|
endif()
|
|
if(_wgpu_cargo_features)
|
|
list(APPEND _cargo_extra_args ${_wgpu_cargo_features})
|
|
endif()
|
|
|
|
set(_cargo_env_prefix "")
|
|
if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
|
|
mln_wgpu_ios_setup_cargo_env(_cargo_env_prefix)
|
|
endif()
|
|
|
|
execute_process(
|
|
COMMAND ${_cargo_env_prefix} ${CARGO_EXECUTABLE} build --release ${_cargo_extra_args}
|
|
WORKING_DIRECTORY ${_mln_wgpu_source_dir}
|
|
RESULT_VARIABLE _cargo_result
|
|
OUTPUT_VARIABLE _cargo_output
|
|
ERROR_VARIABLE _cargo_error
|
|
)
|
|
|
|
if(NOT _cargo_result EQUAL 0)
|
|
message(FATAL_ERROR
|
|
"Failed to build wgpu-native:\n${_cargo_error}\n"
|
|
"You can try building manually:\n"
|
|
" cd ${_mln_wgpu_source_dir} && cargo build --release")
|
|
endif()
|
|
|
|
# Try to find the library again
|
|
mln_wgpu_find_library()
|
|
mln_wgpu_find_exact_library(WGPU_STATIC_LIBRARY "wgpu-native static library")
|
|
|
|
if(NOT WGPU_LIBRARY)
|
|
message(FATAL_ERROR "Failed to locate wgpu-native library after building")
|
|
endif()
|
|
|
|
message(STATUS "Successfully built wgpu-native: ${WGPU_LIBRARY}")
|
|
else()
|
|
message(STATUS "Found wgpu-native library: ${WGPU_LIBRARY}")
|
|
endif()
|
|
|
|
if(WGPU_STATIC_LIBRARY)
|
|
message(STATUS "Found wgpu-native static library: ${WGPU_STATIC_LIBRARY}")
|
|
elseif(MLN_CREATE_AMALGAMATION)
|
|
message(FATAL_ERROR
|
|
"MLN_CREATE_AMALGAMATION=ON requires a static wgpu-native library, "
|
|
"but none was found in: ${_wgpu_lib_search_paths}")
|
|
endif()
|
|
|
|
# Create compatibility shims for Dawn header paths if they don't exist
|
|
set(_webgpu-cpp-output_dir "${CMAKE_CURRENT_BINARY_DIR}/webgpu-cpp")
|
|
set(_compat_shim_dir "${_webgpu-cpp-output_dir}/webgpu")
|
|
set(_compat_shim_header "${_compat_shim_dir}/webgpu_cpp.h")
|
|
set(_compat_shim_webgpu_h "${_compat_shim_dir}/webgpu.h")
|
|
set(_compat_shim_wgpu_h "${_compat_shim_dir}/wgpu.h")
|
|
file(MAKE_DIRECTORY "${_compat_shim_dir}")
|
|
|
|
# Generate WebGPU-Cpp wrapper if needed
|
|
set(_webgpu_cpp_header "${_webgpu-cpp-output_dir}/webgpu.hpp")
|
|
|
|
if(NOT EXISTS "${_webgpu_cpp_header}")
|
|
message(STATUS "Generating WebGPU-Cpp wrapper...")
|
|
|
|
# Check if Python 3 is available
|
|
find_program(PYTHON_EXECUTABLE python3 python)
|
|
if(NOT PYTHON_EXECUTABLE)
|
|
message(FATAL_ERROR
|
|
"Python is required to generate WebGPU-Cpp wrapper. "
|
|
"Please install Python 3.")
|
|
endif()
|
|
|
|
# Run the generator script using the local webgpu.h from wgpu-native
|
|
execute_process(
|
|
COMMAND ${PYTHON_EXECUTABLE} generate.py
|
|
--use-init-macros
|
|
--header ${WEBGPU_H_DIR}/webgpu.h
|
|
--output ${_webgpu_cpp_header}
|
|
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/vendor/webgpu-cpp"
|
|
RESULT_VARIABLE _gen_result
|
|
OUTPUT_VARIABLE _gen_output
|
|
ERROR_VARIABLE _gen_error
|
|
)
|
|
|
|
if(NOT _gen_result EQUAL 0)
|
|
message(FATAL_ERROR
|
|
"Failed to generate WebGPU-Cpp wrapper:\n${_gen_error}")
|
|
endif()
|
|
|
|
message(STATUS "Successfully generated WebGPU-Cpp wrapper")
|
|
endif()
|
|
|
|
if(NOT EXISTS "${_compat_shim_header}")
|
|
message(STATUS "Creating WebGPU-Cpp compatibility shim...")
|
|
|
|
file(WRITE "${_compat_shim_header}"
|
|
"#pragma once
|
|
// Compatibility shim for Dawn header paths
|
|
// This file allows MapLibre code to use #include <webgpu/webgpu_cpp.h>
|
|
// for both Dawn and wgpu-native backends
|
|
|
|
// Include the WebGPU-Cpp wrapper
|
|
// TODO: remove this workaround as soon as https://github.com/eliemichel/WebGPU-Cpp/issues/35 is fixed
|
|
#ifndef _NULLABLE
|
|
#define _NULLABLE WGPU_NULLABLE
|
|
#endif
|
|
#include \"${_webgpu_cpp_header}\"
|
|
|
|
#undef _NULLABLE
|
|
")
|
|
|
|
message(STATUS "Successfully created WebGPU-Cpp compatibility shim")
|
|
endif()
|
|
|
|
if(NOT EXISTS "${_compat_shim_webgpu_h}")
|
|
message(STATUS "Creating webgpu.h compatibility shim...")
|
|
|
|
file(WRITE "${_compat_shim_webgpu_h}"
|
|
"#pragma once
|
|
// Compatibility shim for Dawn header paths
|
|
// This file allows MapLibre code to use #include <webgpu/webgpu.h>
|
|
// for both Dawn and wgpu-native backends
|
|
|
|
// Include the actual webgpu.h header
|
|
#include <webgpu.h>
|
|
")
|
|
|
|
message(STATUS "Successfully created webgpu.h compatibility shim")
|
|
endif()
|
|
|
|
# Also create wgpu.h shim for wgpu-native specific includes
|
|
if(NOT EXISTS "${_compat_shim_wgpu_h}")
|
|
message(STATUS "Creating wgpu.h compatibility shim...")
|
|
|
|
file(WRITE "${_compat_shim_wgpu_h}"
|
|
"#pragma once
|
|
// Compatibility shim for wgpu-native specific header
|
|
// This file allows MapLibre code to use #include <webgpu/wgpu.h>
|
|
// for both Dawn and wgpu-native backends
|
|
|
|
// Include the actual wgpu.h header
|
|
#include <wgpu.h>
|
|
")
|
|
|
|
message(STATUS "Successfully created wgpu.h compatibility shim")
|
|
endif()
|
|
|
|
# Create interface library
|
|
add_library(mbgl-vendor-wgpu INTERFACE)
|
|
|
|
# For the ffi we don't link the wgpu library, because we link in the final stage with the rust wgpu version
|
|
target_link_libraries(mbgl-vendor-wgpu INTERFACE ${WGPU_LIBRARY})
|
|
|
|
# Add include directories for webgpu.h, wgpu.h, and C++ wrapper
|
|
target_include_directories(mbgl-vendor-wgpu
|
|
SYSTEM INTERFACE
|
|
${_webgpu-cpp-output_dir} # For webgpu.hpp webgpu/webgpu_cpp.h compatibility shim
|
|
${WEBGPU_H_DIR}
|
|
${_mln_wgpu_source_dir}/ffi # wgpu.h
|
|
)
|
|
|
|
# Platform-specific system libraries that wgpu-native needs
|
|
if (NOT MLN_WEBGPU_IMPL_FFI)
|
|
if(APPLE)
|
|
target_link_libraries(mbgl-vendor-wgpu INTERFACE
|
|
"-framework Foundation"
|
|
"-framework QuartzCore"
|
|
"-framework Metal"
|
|
)
|
|
elseif(WIN32)
|
|
target_link_libraries(mbgl-vendor-wgpu INTERFACE
|
|
d3d12
|
|
dxgi
|
|
d3dcompiler
|
|
ws2_32
|
|
userenv
|
|
bcrypt
|
|
ntdll
|
|
)
|
|
elseif(ANDROID)
|
|
mln_wgpu_android_link_library(mbgl-vendor-wgpu)
|
|
else() # Linux
|
|
# wgpu-native on Linux might need these depending on the build configuration
|
|
find_package(Threads REQUIRED)
|
|
target_link_libraries(mbgl-vendor-wgpu INTERFACE
|
|
Threads::Threads
|
|
${CMAKE_DL_LIBS}
|
|
)
|
|
endif()
|
|
endif()
|
|
|
|
# Suppress warnings from wgpu headers
|
|
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
|
|
target_compile_options(mbgl-vendor-wgpu INTERFACE
|
|
-Wno-strict-aliasing
|
|
-Wno-error=strict-aliasing
|
|
)
|
|
endif()
|
|
|
|
if (NOT MLN_WEBGPU_IMPL_FFI)
|
|
set_target_properties(
|
|
mbgl-vendor-wgpu
|
|
PROPERTIES
|
|
INTERFACE_MAPLIBRE_NAME "wgpu-native"
|
|
INTERFACE_MAPLIBRE_URL "https://github.com/gfx-rs/wgpu-native"
|
|
INTERFACE_MAPLIBRE_AUTHOR "gfx-rs developers"
|
|
INTERFACE_MAPLIBRE_LICENSE "${PROJECT_SOURCE_DIR}/vendor/wgpu-native/LICENSE.MIT"
|
|
)
|
|
else()
|
|
set_target_properties(
|
|
mbgl-vendor-wgpu
|
|
PROPERTIES
|
|
INTERFACE_MAPLIBRE_NAME "wgpu-ffi"
|
|
INTERFACE_MAPLIBRE_URL "https://github.com/maplibre/maplibre-native"
|
|
INTERFACE_MAPLIBRE_AUTHOR "Maplibre Contributors"
|
|
INTERFACE_MAPLIBRE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE.md"
|
|
)
|
|
endif()
|