File size: 6,204 Bytes
3374e90
 
 
 
 
 
 
6fef38a
 
 
 
 
3374e90
 
 
 
 
 
6fef38a
 
 
 
 
 
 
 
3374e90
6fef38a
3374e90
 
6fef38a
 
3374e90
6fef38a
3374e90
 
 
 
 
 
 
 
6fef38a
3374e90
 
 
 
 
 
 
 
 
 
 
 
 
 
6fef38a
3374e90
 
 
6fef38a
 
 
3374e90
 
 
 
 
6fef38a
3374e90
6fef38a
3374e90
 
 
6fef38a
3374e90
 
 
 
 
 
 
6fef38a
3374e90
 
 
6fef38a
3374e90
 
 
 
 
 
 
6fef38a
 
 
 
 
 
 
 
 
 
 
3374e90
6fef38a
 
3374e90
 
 
 
 
 
6fef38a
 
3374e90
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6fef38a
3374e90
 
 
 
 
 
 
 
 
 
6fef38a
3374e90
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
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 "")