krystv commited on
Commit
6fef38a
Β·
verified Β·
1 Parent(s): ceb06e0

fix: make static C++ linking opt-in for cross-platform app embedding

Browse files
Files changed (1) hide show
  1. 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
- # ── Release Optimization Flags ────────────────────────────────────────────
9
- # Full static binary, size-optimized, no debug symbols in release mode.
10
- if(CMAKE_BUILD_TYPE STREQUAL "Release")
11
- # Strip all debug symbols from the final binary
12
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ffunction-sections -fdata-sections")
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
- # This CMake is designed to be self-contained and reusable.
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 the Rust library first: cargo build -p bex-runtime --release
30
- # 2. Set BEX_ENGINE_ROOT if this directory is not inside the bex-engine repo
31
  #
32
- # The Rust library exports a pure C ABI via bex_engine.h β€” no bridge crate needed.
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 the crates/ directory."
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 the Rust library name ─────────────────────────────────────────
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
- if(WIN32)
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
- if(BEX_LINK_MODE STREQUAL "static")
107
- if(WIN32)
108
- target_link_libraries(bex_engine_lib INTERFACE
109
- "${BEX_LIB_PATH}"
110
- ${BEX_WINDOWS_SYS_LIBS}
111
- )
112
- else()
113
- target_link_libraries(bex_engine_lib INTERFACE
114
- "${BEX_LIB_PATH}"
115
- dl
116
- pthread
117
- m
118
- )
119
- target_link_directories(bex_engine_lib INTERFACE "${RUST_TARGET_DIR}/deps")
120
- endif()
121
  else()
122
- if(WIN32)
123
- target_link_libraries(bex_engine_lib INTERFACE
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
- # ── Static Linking for Release ────────────────────────────────────────────
144
- # Produce a fully static binary in release mode (no runtime dependencies).
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 "")