fix: make static C++ linking opt-in for cross-platform app embedding
Browse files- cpp-cli/CMakeLists.txt +44 -78
cpp-cli/CMakeLists.txt
CHANGED
|
@@ -5,50 +5,48 @@ set(CMAKE_CXX_STANDARD 17)
|
|
| 5 |
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
| 6 |
set(CMAKE_CXX_EXTENSIONS OFF)
|
| 7 |
|
| 8 |
-
# ββ
|
| 9 |
-
#
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} -s -Wl,--gc-sections -Wl,--strip-all")
|
| 14 |
-
# Optimize for size
|
| 15 |
-
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Os")
|
| 16 |
-
endif()
|
| 17 |
|
| 18 |
# ββ Build Configuration ββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 19 |
if(NOT CMAKE_BUILD_TYPE)
|
| 20 |
set(CMAKE_BUILD_TYPE Release)
|
| 21 |
endif()
|
| 22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
# ββ Bex Engine Integration βββββββββββββββββββββββββββββββββββββββββββββββ
|
| 24 |
-
#
|
| 25 |
-
# Copy this directory into any C++ project and it will automatically
|
| 26 |
-
# find and link the Rust Bex Engine static library.
|
| 27 |
#
|
| 28 |
# Requirements:
|
| 29 |
-
# 1. Build
|
| 30 |
-
# 2. Set BEX_ENGINE_ROOT if
|
| 31 |
#
|
| 32 |
-
# The Rust library exports a pure C ABI via bex_engine.h β no
|
| 33 |
|
| 34 |
-
# Find the Bex Engine root directory
|
| 35 |
if(NOT BEX_ENGINE_ROOT)
|
| 36 |
-
# Default: assume we're inside bex-engine/cpp-cli/
|
| 37 |
get_filename_component(_BEX_ROOT "${CMAKE_SOURCE_DIR}/.." ABSOLUTE)
|
| 38 |
if(EXISTS "${_BEX_ROOT}/Cargo.toml")
|
| 39 |
set(BEX_ENGINE_ROOT "${_BEX_ROOT}")
|
| 40 |
else()
|
| 41 |
message(FATAL_ERROR
|
| 42 |
"Cannot find Bex Engine root. Set -DBEX_ENGINE_ROOT=/path/to/bex-engine\n"
|
| 43 |
-
"The bex-engine directory should contain Cargo.toml and
|
| 44 |
)
|
| 45 |
endif()
|
| 46 |
endif()
|
| 47 |
|
| 48 |
message(STATUS "Bex Engine root: ${BEX_ENGINE_ROOT}")
|
| 49 |
|
| 50 |
-
# ββ Rust Target Directory ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 51 |
-
# CMake uses "Release" / "Debug", but Rust uses "release" / "debug"
|
| 52 |
if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
|
| 53 |
set(RUST_PROFILE "release")
|
| 54 |
else()
|
|
@@ -57,25 +55,25 @@ endif()
|
|
| 57 |
|
| 58 |
set(RUST_TARGET_DIR "${BEX_ENGINE_ROOT}/target/${RUST_PROFILE}")
|
| 59 |
|
| 60 |
-
# ββ Detect
|
| 61 |
-
# bex-runtime compiles as both cdylib and staticlib. The produced filename
|
| 62 |
-
# differs by platform/toolchain: Windows (MSVC) -> "bex_runtime.lib"/.dll,
|
| 63 |
-
# GNU toolchain -> "libbex_runtime.a"/.so. Prefer static when available.
|
| 64 |
-
|
| 65 |
if(WIN32)
|
| 66 |
set(RUST_STATIC_LIB "${RUST_TARGET_DIR}/bex_runtime.lib")
|
| 67 |
set(RUST_SHARED_LIB "${RUST_TARGET_DIR}/bex_runtime.dll")
|
|
|
|
|
|
|
|
|
|
| 68 |
else()
|
| 69 |
set(RUST_STATIC_LIB "${RUST_TARGET_DIR}/libbex_runtime.a")
|
| 70 |
set(RUST_SHARED_LIB "${RUST_TARGET_DIR}/libbex_runtime.so")
|
| 71 |
endif()
|
| 72 |
|
|
|
|
| 73 |
if(EXISTS "${RUST_STATIC_LIB}")
|
| 74 |
-
set(BEX_LINK_MODE "static")
|
| 75 |
set(BEX_LIB_PATH "${RUST_STATIC_LIB}")
|
| 76 |
message(STATUS "Found Rust static library: ${BEX_LIB_PATH}")
|
| 77 |
elseif(EXISTS "${RUST_SHARED_LIB}")
|
| 78 |
-
set(BEX_LINK_MODE "shared")
|
| 79 |
set(BEX_LIB_PATH "${RUST_SHARED_LIB}")
|
| 80 |
message(STATUS "Found Rust shared library: ${BEX_LIB_PATH}")
|
| 81 |
else()
|
|
@@ -83,70 +81,43 @@ else()
|
|
| 83 |
"Rust library not found at ${RUST_STATIC_LIB} or ${RUST_SHARED_LIB}\n"
|
| 84 |
"Build it first: cd ${BEX_ENGINE_ROOT} && cargo build -p bex-runtime --release"
|
| 85 |
)
|
| 86 |
-
set(BEX_LINK_MODE "static")
|
| 87 |
set(BEX_LIB_PATH "${RUST_STATIC_LIB}")
|
| 88 |
endif()
|
| 89 |
|
| 90 |
-
|
| 91 |
-
set(BEX_WINDOWS_SYS_LIBS bcrypt userenv ntdll advapi32)
|
| 92 |
-
endif()
|
| 93 |
-
|
| 94 |
-
# ββ C Header Location ββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 95 |
set(BEX_INCLUDE_DIR "${CMAKE_SOURCE_DIR}")
|
| 96 |
|
| 97 |
-
# ββ Bex Engine Library (Imported Target) βββββββββββββββββββββββββββββββββ
|
| 98 |
-
# Create an INTERFACE library target so other projects can simply do:
|
| 99 |
-
# target_link_libraries(myapp PRIVATE bex::engine)
|
| 100 |
-
# target_include_directories(myapp PRIVATE ${BEX_INCLUDE_DIR})
|
| 101 |
add_library(bex_engine_lib INTERFACE)
|
| 102 |
add_library(bex::engine ALIAS bex_engine_lib)
|
| 103 |
|
| 104 |
target_include_directories(bex_engine_lib INTERFACE "${BEX_INCLUDE_DIR}")
|
| 105 |
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
m
|
| 118 |
-
)
|
| 119 |
-
target_link_directories(bex_engine_lib INTERFACE "${RUST_TARGET_DIR}/deps")
|
| 120 |
-
endif()
|
| 121 |
else()
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
"${BEX_LIB_PATH}"
|
| 125 |
-
)
|
| 126 |
-
else()
|
| 127 |
-
target_link_libraries(bex_engine_lib INTERFACE
|
| 128 |
-
"${BEX_LIB_PATH}"
|
| 129 |
-
dl
|
| 130 |
-
pthread
|
| 131 |
-
m
|
| 132 |
-
)
|
| 133 |
-
endif()
|
| 134 |
endif()
|
| 135 |
|
| 136 |
-
# ββ Executable: bexcli βββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 137 |
add_executable(bexcli bexcli.cpp)
|
| 138 |
-
|
| 139 |
target_include_directories(bexcli PRIVATE "${BEX_INCLUDE_DIR}")
|
| 140 |
-
|
| 141 |
target_link_libraries(bexcli PRIVATE bex_engine_lib)
|
| 142 |
|
| 143 |
-
#
|
| 144 |
-
|
| 145 |
-
if(CMAKE_BUILD_TYPE STREQUAL "Release" AND NOT WIN32)
|
| 146 |
target_link_options(bexcli PRIVATE -static)
|
| 147 |
endif()
|
| 148 |
|
| 149 |
-
# ββ Helper Target: Build Rust Library ββββββββββββββββββββββββββββββββββββ
|
| 150 |
add_custom_target(rustlib
|
| 151 |
COMMAND ${CMAKE_COMMAND} -E env cargo build -p bex-runtime --release
|
| 152 |
WORKING_DIRECTORY ${BEX_ENGINE_ROOT}
|
|
@@ -154,19 +125,13 @@ add_custom_target(rustlib
|
|
| 154 |
VERBATIM
|
| 155 |
)
|
| 156 |
|
| 157 |
-
# Make bexcli depend on rustlib if the library file doesn't exist yet
|
| 158 |
if(NOT EXISTS "${BEX_LIB_PATH}")
|
| 159 |
add_dependencies(bexcli rustlib)
|
| 160 |
endif()
|
| 161 |
|
| 162 |
-
# ββ Install Rules (for integration into other projects) ββββββββββββββββββ
|
| 163 |
install(TARGETS bexcli RUNTIME DESTINATION bin)
|
| 164 |
-
install(FILES
|
| 165 |
-
"${CMAKE_SOURCE_DIR}/bex_engine.h"
|
| 166 |
-
DESTINATION include/bex
|
| 167 |
-
)
|
| 168 |
|
| 169 |
-
# ββ Print Configuration Summary ββββββββββββββββββββββββββββββββββββββββββ
|
| 170 |
message(STATUS "")
|
| 171 |
message(STATUS "=== Bex CLI Configuration (Pure C ABI) ===")
|
| 172 |
message(STATUS " Build type: ${CMAKE_BUILD_TYPE}")
|
|
@@ -176,6 +141,7 @@ message(STATUS " Rust target dir: ${RUST_TARGET_DIR}")
|
|
| 176 |
message(STATUS " Link mode: ${BEX_LINK_MODE}")
|
| 177 |
message(STATUS " Library path: ${BEX_LIB_PATH}")
|
| 178 |
message(STATUS " Include dir: ${BEX_INCLUDE_DIR}")
|
|
|
|
| 179 |
message(STATUS " FFI: Pure C ABI (bex_engine.h)")
|
| 180 |
message(STATUS "==========================================")
|
| 181 |
message(STATUS "")
|
|
|
|
| 5 |
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
| 6 |
set(CMAKE_CXX_EXTENSIONS OFF)
|
| 7 |
|
| 8 |
+
# ββ Build Options βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 9 |
+
# Fully static linking is NOT safe as a default for arbitrary apps/platforms.
|
| 10 |
+
# glibc, Wasmtime, TLS stacks, and system libraries can make static builds
|
| 11 |
+
# brittle or impossible depending on the target. Keep it opt-in.
|
| 12 |
+
option(BEX_FORCE_STATIC_EXE "Force fully static bexcli executable on Unix" OFF)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
|
| 14 |
# ββ Build Configuration ββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 15 |
if(NOT CMAKE_BUILD_TYPE)
|
| 16 |
set(CMAKE_BUILD_TYPE Release)
|
| 17 |
endif()
|
| 18 |
|
| 19 |
+
# ββ Release Optimization Flags ββββββββββββββββββββββββββββββββββββββββββββ
|
| 20 |
+
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
| 21 |
+
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ffunction-sections -fdata-sections -Os")
|
| 22 |
+
if(NOT WIN32)
|
| 23 |
+
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} -Wl,--gc-sections")
|
| 24 |
+
endif()
|
| 25 |
+
endif()
|
| 26 |
+
|
| 27 |
# ββ Bex Engine Integration βββββββββββββββββββββββββββββββββββββββββββββββ
|
| 28 |
+
# Reusable CMake integration for any C/C++ app.
|
|
|
|
|
|
|
| 29 |
#
|
| 30 |
# Requirements:
|
| 31 |
+
# 1. Build Rust library first: cargo build -p bex-runtime --release
|
| 32 |
+
# 2. Set BEX_ENGINE_ROOT if cpp-cli/ is copied outside the repo.
|
| 33 |
#
|
| 34 |
+
# The Rust library exports a pure C ABI via bex_engine.h β no cxx bridge.
|
| 35 |
|
|
|
|
| 36 |
if(NOT BEX_ENGINE_ROOT)
|
|
|
|
| 37 |
get_filename_component(_BEX_ROOT "${CMAKE_SOURCE_DIR}/.." ABSOLUTE)
|
| 38 |
if(EXISTS "${_BEX_ROOT}/Cargo.toml")
|
| 39 |
set(BEX_ENGINE_ROOT "${_BEX_ROOT}")
|
| 40 |
else()
|
| 41 |
message(FATAL_ERROR
|
| 42 |
"Cannot find Bex Engine root. Set -DBEX_ENGINE_ROOT=/path/to/bex-engine\n"
|
| 43 |
+
"The bex-engine directory should contain Cargo.toml and crates/."
|
| 44 |
)
|
| 45 |
endif()
|
| 46 |
endif()
|
| 47 |
|
| 48 |
message(STATUS "Bex Engine root: ${BEX_ENGINE_ROOT}")
|
| 49 |
|
|
|
|
|
|
|
| 50 |
if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
|
| 51 |
set(RUST_PROFILE "release")
|
| 52 |
else()
|
|
|
|
| 55 |
|
| 56 |
set(RUST_TARGET_DIR "${BEX_ENGINE_ROOT}/target/${RUST_PROFILE}")
|
| 57 |
|
| 58 |
+
# ββ Detect Rust library name ββββββββββββββββββββββββββββββββββββββββββββ
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
if(WIN32)
|
| 60 |
set(RUST_STATIC_LIB "${RUST_TARGET_DIR}/bex_runtime.lib")
|
| 61 |
set(RUST_SHARED_LIB "${RUST_TARGET_DIR}/bex_runtime.dll")
|
| 62 |
+
elseif(APPLE)
|
| 63 |
+
set(RUST_STATIC_LIB "${RUST_TARGET_DIR}/libbex_runtime.a")
|
| 64 |
+
set(RUST_SHARED_LIB "${RUST_TARGET_DIR}/libbex_runtime.dylib")
|
| 65 |
else()
|
| 66 |
set(RUST_STATIC_LIB "${RUST_TARGET_DIR}/libbex_runtime.a")
|
| 67 |
set(RUST_SHARED_LIB "${RUST_TARGET_DIR}/libbex_runtime.so")
|
| 68 |
endif()
|
| 69 |
|
| 70 |
+
# Prefer static Rust archive when present, but do not force a fully static executable.
|
| 71 |
if(EXISTS "${RUST_STATIC_LIB}")
|
| 72 |
+
set(BEX_LINK_MODE "static-rustlib")
|
| 73 |
set(BEX_LIB_PATH "${RUST_STATIC_LIB}")
|
| 74 |
message(STATUS "Found Rust static library: ${BEX_LIB_PATH}")
|
| 75 |
elseif(EXISTS "${RUST_SHARED_LIB}")
|
| 76 |
+
set(BEX_LINK_MODE "shared-rustlib")
|
| 77 |
set(BEX_LIB_PATH "${RUST_SHARED_LIB}")
|
| 78 |
message(STATUS "Found Rust shared library: ${BEX_LIB_PATH}")
|
| 79 |
else()
|
|
|
|
| 81 |
"Rust library not found at ${RUST_STATIC_LIB} or ${RUST_SHARED_LIB}\n"
|
| 82 |
"Build it first: cd ${BEX_ENGINE_ROOT} && cargo build -p bex-runtime --release"
|
| 83 |
)
|
| 84 |
+
set(BEX_LINK_MODE "static-rustlib")
|
| 85 |
set(BEX_LIB_PATH "${RUST_STATIC_LIB}")
|
| 86 |
endif()
|
| 87 |
|
| 88 |
+
# ββ C Header Location βββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
set(BEX_INCLUDE_DIR "${CMAKE_SOURCE_DIR}")
|
| 90 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
add_library(bex_engine_lib INTERFACE)
|
| 92 |
add_library(bex::engine ALIAS bex_engine_lib)
|
| 93 |
|
| 94 |
target_include_directories(bex_engine_lib INTERFACE "${BEX_INCLUDE_DIR}")
|
| 95 |
|
| 96 |
+
target_link_libraries(bex_engine_lib INTERFACE "${BEX_LIB_PATH}")
|
| 97 |
+
|
| 98 |
+
if(WIN32)
|
| 99 |
+
target_link_libraries(bex_engine_lib INTERFACE bcrypt userenv ntdll advapi32 ws2_32 user32)
|
| 100 |
+
elseif(APPLE)
|
| 101 |
+
target_link_libraries(bex_engine_lib INTERFACE
|
| 102 |
+
"-framework Security"
|
| 103 |
+
"-framework CoreFoundation"
|
| 104 |
+
pthread
|
| 105 |
+
m
|
| 106 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 107 |
else()
|
| 108 |
+
target_link_libraries(bex_engine_lib INTERFACE dl pthread m)
|
| 109 |
+
target_link_directories(bex_engine_lib INTERFACE "${RUST_TARGET_DIR}/deps")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
endif()
|
| 111 |
|
|
|
|
| 112 |
add_executable(bexcli bexcli.cpp)
|
|
|
|
| 113 |
target_include_directories(bexcli PRIVATE "${BEX_INCLUDE_DIR}")
|
|
|
|
| 114 |
target_link_libraries(bexcli PRIVATE bex_engine_lib)
|
| 115 |
|
| 116 |
+
# Optional fully-static Unix executable for environments that explicitly want it.
|
| 117 |
+
if(BEX_FORCE_STATIC_EXE AND NOT WIN32 AND NOT APPLE)
|
|
|
|
| 118 |
target_link_options(bexcli PRIVATE -static)
|
| 119 |
endif()
|
| 120 |
|
|
|
|
| 121 |
add_custom_target(rustlib
|
| 122 |
COMMAND ${CMAKE_COMMAND} -E env cargo build -p bex-runtime --release
|
| 123 |
WORKING_DIRECTORY ${BEX_ENGINE_ROOT}
|
|
|
|
| 125 |
VERBATIM
|
| 126 |
)
|
| 127 |
|
|
|
|
| 128 |
if(NOT EXISTS "${BEX_LIB_PATH}")
|
| 129 |
add_dependencies(bexcli rustlib)
|
| 130 |
endif()
|
| 131 |
|
|
|
|
| 132 |
install(TARGETS bexcli RUNTIME DESTINATION bin)
|
| 133 |
+
install(FILES "${CMAKE_SOURCE_DIR}/bex_engine.h" DESTINATION include/bex)
|
|
|
|
|
|
|
|
|
|
| 134 |
|
|
|
|
| 135 |
message(STATUS "")
|
| 136 |
message(STATUS "=== Bex CLI Configuration (Pure C ABI) ===")
|
| 137 |
message(STATUS " Build type: ${CMAKE_BUILD_TYPE}")
|
|
|
|
| 141 |
message(STATUS " Link mode: ${BEX_LINK_MODE}")
|
| 142 |
message(STATUS " Library path: ${BEX_LIB_PATH}")
|
| 143 |
message(STATUS " Include dir: ${BEX_INCLUDE_DIR}")
|
| 144 |
+
message(STATUS " Force static exe: ${BEX_FORCE_STATIC_EXE}")
|
| 145 |
message(STATUS " FFI: Pure C ABI (bex_engine.h)")
|
| 146 |
message(STATUS "==========================================")
|
| 147 |
message(STATUS "")
|