pluginengine01 / cpp-cli /CMakeLists.txt
krystv's picture
fix: make static C++ linking opt-in for cross-platform app embedding
6fef38a verified
cmake_minimum_required(VERSION 3.16)
project(bexcli LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# ── Build Options ───────────────────────────────────────────────────────
# Fully static linking is NOT safe as a default for arbitrary apps/platforms.
# glibc, Wasmtime, TLS stacks, and system libraries can make static builds
# brittle or impossible depending on the target. Keep it opt-in.
option(BEX_FORCE_STATIC_EXE "Force fully static bexcli executable on Unix" OFF)
# ── Build Configuration ──────────────────────────────────────────────────
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
# ── Release Optimization Flags ────────────────────────────────────────────
if(CMAKE_BUILD_TYPE STREQUAL "Release")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ffunction-sections -fdata-sections -Os")
if(NOT WIN32)
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} -Wl,--gc-sections")
endif()
endif()
# ── Bex Engine Integration ───────────────────────────────────────────────
# Reusable CMake integration for any C/C++ app.
#
# Requirements:
# 1. Build Rust library first: cargo build -p bex-runtime --release
# 2. Set BEX_ENGINE_ROOT if cpp-cli/ is copied outside the repo.
#
# The Rust library exports a pure C ABI via bex_engine.h β€” no cxx bridge.
if(NOT BEX_ENGINE_ROOT)
get_filename_component(_BEX_ROOT "${CMAKE_SOURCE_DIR}/.." ABSOLUTE)
if(EXISTS "${_BEX_ROOT}/Cargo.toml")
set(BEX_ENGINE_ROOT "${_BEX_ROOT}")
else()
message(FATAL_ERROR
"Cannot find Bex Engine root. Set -DBEX_ENGINE_ROOT=/path/to/bex-engine\n"
"The bex-engine directory should contain Cargo.toml and crates/."
)
endif()
endif()
message(STATUS "Bex Engine root: ${BEX_ENGINE_ROOT}")
if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
set(RUST_PROFILE "release")
else()
set(RUST_PROFILE "debug")
endif()
set(RUST_TARGET_DIR "${BEX_ENGINE_ROOT}/target/${RUST_PROFILE}")
# ── Detect Rust library name ────────────────────────────────────────────
if(WIN32)
set(RUST_STATIC_LIB "${RUST_TARGET_DIR}/bex_runtime.lib")
set(RUST_SHARED_LIB "${RUST_TARGET_DIR}/bex_runtime.dll")
elseif(APPLE)
set(RUST_STATIC_LIB "${RUST_TARGET_DIR}/libbex_runtime.a")
set(RUST_SHARED_LIB "${RUST_TARGET_DIR}/libbex_runtime.dylib")
else()
set(RUST_STATIC_LIB "${RUST_TARGET_DIR}/libbex_runtime.a")
set(RUST_SHARED_LIB "${RUST_TARGET_DIR}/libbex_runtime.so")
endif()
# Prefer static Rust archive when present, but do not force a fully static executable.
if(EXISTS "${RUST_STATIC_LIB}")
set(BEX_LINK_MODE "static-rustlib")
set(BEX_LIB_PATH "${RUST_STATIC_LIB}")
message(STATUS "Found Rust static library: ${BEX_LIB_PATH}")
elseif(EXISTS "${RUST_SHARED_LIB}")
set(BEX_LINK_MODE "shared-rustlib")
set(BEX_LIB_PATH "${RUST_SHARED_LIB}")
message(STATUS "Found Rust shared library: ${BEX_LIB_PATH}")
else()
message(WARNING
"Rust library not found at ${RUST_STATIC_LIB} or ${RUST_SHARED_LIB}\n"
"Build it first: cd ${BEX_ENGINE_ROOT} && cargo build -p bex-runtime --release"
)
set(BEX_LINK_MODE "static-rustlib")
set(BEX_LIB_PATH "${RUST_STATIC_LIB}")
endif()
# ── C Header Location ───────────────────────────────────────────────────
set(BEX_INCLUDE_DIR "${CMAKE_SOURCE_DIR}")
add_library(bex_engine_lib INTERFACE)
add_library(bex::engine ALIAS bex_engine_lib)
target_include_directories(bex_engine_lib INTERFACE "${BEX_INCLUDE_DIR}")
target_link_libraries(bex_engine_lib INTERFACE "${BEX_LIB_PATH}")
if(WIN32)
target_link_libraries(bex_engine_lib INTERFACE bcrypt userenv ntdll advapi32 ws2_32 user32)
elseif(APPLE)
target_link_libraries(bex_engine_lib INTERFACE
"-framework Security"
"-framework CoreFoundation"
pthread
m
)
else()
target_link_libraries(bex_engine_lib INTERFACE dl pthread m)
target_link_directories(bex_engine_lib INTERFACE "${RUST_TARGET_DIR}/deps")
endif()
add_executable(bexcli bexcli.cpp)
target_include_directories(bexcli PRIVATE "${BEX_INCLUDE_DIR}")
target_link_libraries(bexcli PRIVATE bex_engine_lib)
# Optional fully-static Unix executable for environments that explicitly want it.
if(BEX_FORCE_STATIC_EXE AND NOT WIN32 AND NOT APPLE)
target_link_options(bexcli PRIVATE -static)
endif()
add_custom_target(rustlib
COMMAND ${CMAKE_COMMAND} -E env cargo build -p bex-runtime --release
WORKING_DIRECTORY ${BEX_ENGINE_ROOT}
COMMENT "Building Rust bex-runtime library (pure C ABI)..."
VERBATIM
)
if(NOT EXISTS "${BEX_LIB_PATH}")
add_dependencies(bexcli rustlib)
endif()
install(TARGETS bexcli RUNTIME DESTINATION bin)
install(FILES "${CMAKE_SOURCE_DIR}/bex_engine.h" DESTINATION include/bex)
message(STATUS "")
message(STATUS "=== Bex CLI Configuration (Pure C ABI) ===")
message(STATUS " Build type: ${CMAKE_BUILD_TYPE}")
message(STATUS " Rust profile: ${RUST_PROFILE}")
message(STATUS " Engine root: ${BEX_ENGINE_ROOT}")
message(STATUS " Rust target dir: ${RUST_TARGET_DIR}")
message(STATUS " Link mode: ${BEX_LINK_MODE}")
message(STATUS " Library path: ${BEX_LIB_PATH}")
message(STATUS " Include dir: ${BEX_INCLUDE_DIR}")
message(STATUS " Force static exe: ${BEX_FORCE_STATIC_EXE}")
message(STATUS " FFI: Pure C ABI (bex_engine.h)")
message(STATUS "==========================================")
message(STATUS "")