-
-
Notifications
You must be signed in to change notification settings - Fork 31
Expand file tree
/
Copy pathCMakeLists.txt
More file actions
367 lines (335 loc) · 18.1 KB
/
Copy pathCMakeLists.txt
File metadata and controls
367 lines (335 loc) · 18.1 KB
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
cmake_minimum_required(VERSION 3.18)
project(trellis_cpp VERSION 0.6.0 LANGUAGES CXX C)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
find_package(Git QUIET)
set(TRELLIS_GIT_COMMIT "")
set(TRELLIS_GIT_DIRTY 0)
set(TRELLIS_APP_VERSION "v${PROJECT_VERSION}")
string(TIMESTAMP TRELLIS_BUILD_TIMESTAMP_UTC "%Y-%m-%dT%H:%M:%SZ" UTC)
if(GIT_FOUND AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
execute_process(
COMMAND "${GIT_EXECUTABLE}" rev-parse HEAD
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
OUTPUT_VARIABLE TRELLIS_GIT_COMMIT
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
RESULT_VARIABLE TRELLIS_GIT_COMMIT_RESULT)
if(TRELLIS_GIT_COMMIT_RESULT EQUAL 0)
execute_process(
COMMAND "${GIT_EXECUTABLE}" status --porcelain --untracked-files=no
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
OUTPUT_VARIABLE TRELLIS_GIT_STATUS
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET)
if(NOT "${TRELLIS_GIT_STATUS}" STREQUAL "")
set(TRELLIS_GIT_DIRTY 1)
endif()
else()
set(TRELLIS_GIT_COMMIT "")
endif()
execute_process(
COMMAND "${GIT_EXECUTABLE}" tag --sort=-v:refname
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
OUTPUT_VARIABLE TRELLIS_GIT_TAGS
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET)
if(NOT "${TRELLIS_GIT_TAGS}" STREQUAL "")
string(REPLACE "\n" ";" TRELLIS_GIT_TAG_LIST "${TRELLIS_GIT_TAGS}")
list(GET TRELLIS_GIT_TAG_LIST 0 TRELLIS_LATEST_TAG)
if(NOT "${TRELLIS_LATEST_TAG}" STREQUAL "")
set(TRELLIS_APP_VERSION "${TRELLIS_LATEST_TAG}")
endif()
endif()
endif()
if(NOT TRELLIS_APP_VERSION MATCHES "^v")
set(TRELLIS_APP_VERSION "v${TRELLIS_APP_VERSION}")
endif()
set(TRELLIS_BUILD_BACKEND "cpu")
# --- vendored ggml submodule, built in-tree --------------------------------
# Backend is selected at configure time with the upstream flags
# (-DGGML_CUDA=ON / -DGGML_VULKAN=ON); the matching ggml-<backend> target then
# exists and we link it. DiT/sparse tensor names exceed the default 64 chars,
# so raise GGML_MAX_NAME for both ggml and our own sources (the header guards
# it with #ifndef, so a compile definition is enough — no submodule patch).
set(GGML_DIR ${CMAKE_SOURCE_DIR}/thirdparty/ggml)
add_compile_definitions(GGML_MAX_NAME=128)
# Colocate ggml's shared libs with our executables so they're found via $ORIGIN
# both in the build tree and once packaged.
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
add_subdirectory(thirdparty/ggml)
set(GGML_RPATH "$ORIGIN")
set(CMAKE_INSTALL_RPATH "$ORIGIN")
# --- CUDA language (for the custom deformable-conv kernel) ------------------
if(TARGET ggml-cuda)
set(TRELLIS_BUILD_BACKEND "cuda")
if(EXISTS /usr/local/cuda-13.3/bin/nvcc AND NOT CMAKE_CUDA_COMPILER)
set(CMAKE_CUDA_COMPILER /usr/local/cuda-13.3/bin/nvcc)
endif()
enable_language(CUDA)
if(NOT CMAKE_CUDA_ARCHITECTURES)
set(CMAKE_CUDA_ARCHITECTURES 86 120)
endif()
set(CMAKE_CUDA_RUNTIME_LIBRARY Shared) # match ggml's shared cudart (avoid 2 runtimes -> invalid device ordinal)
find_package(CUDAToolkit)
endif()
# --- core library ----------------------------------------------------------
add_library(trellis_core STATIC
src/trellis_model.cpp
src/dit.cpp
src/flow_runner.cpp
src/ss_decoder.cpp
src/mesh_glb.cpp
src/dinov3.cpp
src/sparse.cpp
src/shape_decoder.cpp
src/dual_grid.cpp
src/preprocess.cpp
src/uv_bake.cpp
src/birefnet.cpp
thirdparty/xatlas/xatlas.cpp
thirdparty/meshoptimizer/simplifier.cpp
src/tri_bvh.cpp
src/remesh_dc.cpp
src/decimate_qem.cpp
)
target_include_directories(trellis_core PUBLIC include ${GGML_DIR}/include ${CMAKE_SOURCE_DIR}/thirdparty/stb ${CMAKE_SOURCE_DIR}/thirdparty/xatlas ${CMAKE_SOURCE_DIR}/thirdparty/meshoptimizer ${CMAKE_SOURCE_DIR}/thirdparty/fqms)
target_compile_definitions(trellis_core PRIVATE TRELLIS_GIT_COMMIT="${TRELLIS_GIT_COMMIT}" TRELLIS_GIT_DIRTY=${TRELLIS_GIT_DIRTY} TRELLIS_BUILD_TIMESTAMP="${TRELLIS_BUILD_TIMESTAMP_UTC}" TRELLIS_APP_VERSION="${TRELLIS_APP_VERSION}")
target_link_libraries(trellis_core PUBLIC ggml ggml-base ggml-cpu)
# --- WebP textures (reference-parity GLB export) ---------------------------
# Optional lossy-WebP textures via EXT_texture_webp. The exporter only advertises
# the extension when WebP encoding is actually used for the embedded textures.
option(TRELLIS_WEBP "Encode GLB textures as WebP (EXT_texture_webp)" ON)
if(TRELLIS_WEBP)
include(FetchContent)
set(WEBP_BUILD_ANIM_UTILS OFF CACHE BOOL "" FORCE)
set(WEBP_BUILD_CWEBP OFF CACHE BOOL "" FORCE)
set(WEBP_BUILD_DWEBP OFF CACHE BOOL "" FORCE)
set(WEBP_BUILD_GIF2WEBP OFF CACHE BOOL "" FORCE)
set(WEBP_BUILD_IMG2WEBP OFF CACHE BOOL "" FORCE)
set(WEBP_BUILD_VWEBP OFF CACHE BOOL "" FORCE)
set(WEBP_BUILD_WEBPINFO OFF CACHE BOOL "" FORCE)
set(WEBP_BUILD_WEBPMUX OFF CACHE BOOL "" FORCE)
set(WEBP_BUILD_EXTRAS OFF CACHE BOOL "" FORCE)
set(WEBP_BUILD_LIBWEBPMUX OFF CACHE BOOL "" FORCE)
set(BUILD_SHARED_LIBS_SAVED ${BUILD_SHARED_LIBS})
set(BUILD_SHARED_LIBS OFF)
FetchContent_Declare(libwebp
URL https://github.com/webmproject/libwebp/archive/refs/tags/v1.5.0.tar.gz
DOWNLOAD_EXTRACT_TIMESTAMP TRUE)
FetchContent_MakeAvailable(libwebp)
set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_SAVED})
target_compile_definitions(trellis_core PRIVATE TRELLIS_HAVE_WEBP)
target_link_libraries(trellis_core PUBLIC webp)
message(STATUS "trellis.cpp: WebP texture encoding enabled")
endif()
if(TARGET ggml-cuda)
target_compile_definitions(trellis_core PUBLIC TRELLIS_USE_CUDA)
target_link_libraries(trellis_core PUBLIC ggml-cuda)
target_sources(trellis_core PRIVATE src/deform_conv.cu)
# Self-contained CUDA QEM decimation (mirrors the CPU port; uses cub for scan/sort/RLE).
target_sources(trellis_core PRIVATE src/decimate_qem.cu)
if(MSVC)
# CUDA 13.3 CCCL requires MSVC's conforming preprocessor for host compilation.
target_compile_options(trellis_core PRIVATE "$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=/Zc:preprocessor>")
endif()
target_compile_definitions(trellis_core PUBLIC TRELLIS_HAVE_GPU_DECIMATE)
set_target_properties(trellis_core PROPERTIES CUDA_ARCHITECTURES "${CMAKE_CUDA_ARCHITECTURES}" CUDA_RUNTIME_LIBRARY Shared)
target_link_libraries(trellis_core PUBLIC CUDA::cudart)
message(STATUS "trellis.cpp: CUDA backend enabled (${GGML_CUDA_LIB})")
else()
# No CUDA kernel in this build. Run BiRefNet's deformable conv on the GPU via a
# Vulkan compute shader when ggml is using Vulkan, or a HIP kernel when ggml is
# using HIP (both are minutes on the CPU at the larger decoder scales); otherwise
# on the CPU, std::thread-parallel over output channels (deform_conv_cpu.cpp) --
# no OpenMP/libomp dependency.
# HIP compiles deform_conv.cu below (issue #20); mirror the CUDA branch and skip
# the CPU source there so deform_conv2d_run has a single definition.
if(NOT TARGET ggml-hip)
target_sources(trellis_core PRIVATE src/deform_conv_cpu.cpp)
endif()
if(TARGET ggml-vulkan)
set(TRELLIS_BUILD_BACKEND "vulkan")
find_package(Vulkan REQUIRED COMPONENTS glslc)
set(DEFORM_SPV_H ${CMAKE_CURRENT_BINARY_DIR}/deform_conv_comp.h)
add_custom_command(
OUTPUT ${DEFORM_SPV_H}
COMMAND ${Vulkan_GLSLC_EXECUTABLE} -O -mfmt=c --target-env=vulkan1.2
-o ${DEFORM_SPV_H} ${CMAKE_CURRENT_SOURCE_DIR}/src/deform_conv.comp
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/deform_conv.comp
COMMENT "glslc deform_conv.comp -> SPIR-V (C array)")
add_custom_target(trellis_deform_spv DEPENDS ${DEFORM_SPV_H})
target_sources(trellis_core PRIVATE src/deform_conv_vk.cpp)
add_dependencies(trellis_core trellis_deform_spv)
target_include_directories(trellis_core PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(trellis_core PUBLIC Vulkan::Vulkan)
set_source_files_properties(src/deform_conv_cpu.cpp PROPERTIES
COMPILE_DEFINITIONS TRELLIS_DEFORM_VULKAN)
set_source_files_properties(src/deform_conv_vk.cpp PROPERTIES
COMPILE_DEFINITIONS "TRELLIS_DEFORM_SPV_HEADER=\"deform_conv_comp.h\"")
# Self-contained Vulkan QEM decimation: same four per-round compute kernels as the CUDA/HIP
# port, driven from the host (adjacency/edges/compaction). The shader needs 64-bit atomics
# (GL_EXT_shader_atomic_int64), so compile against vulkan1.2 like deform_conv.
set(DECIMATE_SPV_H ${CMAKE_CURRENT_BINARY_DIR}/decimate_qem_comp.h)
add_custom_command(
OUTPUT ${DECIMATE_SPV_H}
COMMAND ${Vulkan_GLSLC_EXECUTABLE} -O -mfmt=c --target-env=vulkan1.2
-o ${DECIMATE_SPV_H} ${CMAKE_CURRENT_SOURCE_DIR}/src/decimate_qem.comp
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/decimate_qem.comp
COMMENT "glslc decimate_qem.comp -> SPIR-V (C array)")
add_custom_target(trellis_decimate_spv DEPENDS ${DECIMATE_SPV_H})
target_sources(trellis_core PRIVATE src/decimate_qem_vk.cpp)
add_dependencies(trellis_core trellis_decimate_spv)
# Target-level so the dispatch block in decimate_qem.cpp is active too (mirrors how the CUDA
# path defines TRELLIS_HAVE_GPU_DECIMATE for the whole library).
target_compile_definitions(trellis_core PRIVATE TRELLIS_HAVE_VK_DECIMATE)
set_source_files_properties(src/decimate_qem_vk.cpp PROPERTIES
COMPILE_DEFINITIONS "TRELLIS_DECIMATE_SPV_HEADER=\"decimate_qem_comp.h\"")
endif()
endif()
if(TARGET ggml-vulkan)
set(TRELLIS_BUILD_BACKEND "vulkan")
target_link_libraries(trellis_core PUBLIC ggml-vulkan)
message(STATUS "trellis.cpp: Vulkan backend enabled")
endif()
if(TARGET ggml-metal)
# macOS/Apple Silicon: ggml's Metal backend (GGML_METAL defaults ON for
# Apple builds). The generic device-enumeration path in make_backend() picks
# the Metal GPU automatically; the two custom kernels (deform_conv,
# decimate_qem) run their CPU fallbacks on this backend.
set(TRELLIS_BUILD_BACKEND "metal")
target_link_libraries(trellis_core PUBLIC ggml-metal)
message(STATUS "trellis.cpp: Metal backend enabled")
endif()
if(TARGET ggml-hip)
set(TRELLIS_BUILD_BACKEND "hip")
target_link_libraries(trellis_core PUBLIC ggml-hip)
# Compile the self-contained QEM decimation kernel as HIP (ggml enabled the HIP
# language via its subdirectory). hipcub headers live under the ROCm include root.
enable_language(HIP)
if(NOT DEFINED ROCM_PATH)
if(DEFINED ENV{ROCM_PATH})
set(ROCM_PATH $ENV{ROCM_PATH})
else()
set(ROCM_PATH /opt/rocm)
endif()
endif()
# Enabling HIP makes every target that links trellis_core (which now carries a HIP object)
# require HIP_ARCHITECTURES. Set the default globally so all subsequently-defined targets
# (the executables below) and trellis_core itself inherit the configured GPU target(s).
# The GPU decimation kernel must be built for the same arch(es) as the rest of
# the backend. Prefer the user-provided GPU_TARGETS / AMDGPU_TARGETS (exactly
# what ggml itself compiles for) over an auto-detected CMAKE_HIP_ARCHITECTURES:
# on some toolchains CMAKE_HIP_ARCHITECTURES is pre-set to a value that omits the
# user's GPU, so the old `if(NOT CMAKE_HIP_ARCHITECTURES)` guard skipped the
# GPU_TARGETS the user passed and built the kernel for the wrong arch — hence the
# runtime "device kernel image is invalid" launch error (issue #14), after which
# decimation silently fell back to the slow CPU path.
if(DEFINED GPU_TARGETS AND NOT "${GPU_TARGETS}" STREQUAL "")
set(TRELLIS_HIP_ARCH "${GPU_TARGETS}")
elseif(DEFINED AMDGPU_TARGETS AND NOT "${AMDGPU_TARGETS}" STREQUAL "")
set(TRELLIS_HIP_ARCH "${AMDGPU_TARGETS}")
elseif(CMAKE_HIP_ARCHITECTURES)
set(TRELLIS_HIP_ARCH "${CMAKE_HIP_ARCHITECTURES}")
else()
set(TRELLIS_HIP_ARCH "gfx1151")
endif()
if(NOT CMAKE_HIP_ARCHITECTURES)
set(CMAKE_HIP_ARCHITECTURES "${TRELLIS_HIP_ARCH}")
endif()
# Both the QEM decimation kernel and BiRefNet's deformable conv (issue #20) build
# as HIP so ROCm users get GPU BiRefNet instead of the minutes-long CPU fallback.
set_source_files_properties(src/decimate_qem.cu src/deform_conv.cu PROPERTIES LANGUAGE HIP)
target_sources(trellis_core PRIVATE src/decimate_qem.cu src/deform_conv.cu)
target_compile_definitions(trellis_core PUBLIC TRELLIS_HAVE_GPU_DECIMATE)
target_include_directories(trellis_core PRIVATE ${ROCM_PATH}/include)
# Force the resolved arch(es) onto the HIP objects (and everything linking
# trellis_core), overriding any auto-detected default.
set_target_properties(trellis_core PROPERTIES HIP_ARCHITECTURES "${TRELLIS_HIP_ARCH}")
set_source_files_properties(src/decimate_qem.cu src/deform_conv.cu PROPERTIES HIP_ARCHITECTURES "${TRELLIS_HIP_ARCH}")
message(STATUS "trellis.cpp: HIP/ROCm backend enabled (GPU decimation + BiRefNet deform via HIP, arch ${TRELLIS_HIP_ARCH})")
endif()
target_compile_definitions(trellis_core PRIVATE TRELLIS_BUILD_BACKEND="${TRELLIS_BUILD_BACKEND}")
# --- executables -----------------------------------------------------------
add_executable(trellis-smoke src/smoke_test.cpp)
target_link_libraries(trellis-smoke PRIVATE trellis_core)
set_target_properties(trellis-smoke PROPERTIES BUILD_RPATH "${GGML_RPATH}")
add_executable(trellis-decode-replay src/decode_replay.cpp)
target_link_libraries(trellis-decode-replay PRIVATE trellis_core)
set_target_properties(trellis-decode-replay PROPERTIES BUILD_RPATH "${GGML_RPATH}")
add_executable(trellis-test-ss-flow src/test_ss_flow.cpp)
target_link_libraries(trellis-test-ss-flow PRIVATE trellis_core)
set_target_properties(trellis-test-ss-flow PROPERTIES BUILD_RPATH "${GGML_RPATH}")
add_executable(trellis-test-shape-flow src/test_shape_flow.cpp)
target_link_libraries(trellis-test-shape-flow PRIVATE trellis_core)
set_target_properties(trellis-test-shape-flow PROPERTIES BUILD_RPATH "${GGML_RPATH}")
# Manual CUDA regression for the >2 Gi half2 mask-stride overflow in
# high-token-count 1024-cascade FlashAttention. The default case needs
# about 8.1 GiB of VRAM, so keep it out of the routine test suite.
if(TARGET ggml-cuda)
add_executable(trellis-test-fa-mask-overflow src/test_fa_mask_overflow.cpp)
target_link_libraries(trellis-test-fa-mask-overflow PRIVATE trellis_core)
set_target_properties(trellis-test-fa-mask-overflow PROPERTIES BUILD_RPATH "${GGML_RPATH}")
# Small CUDA regression for trellis's V-range protection around the tensor-core
# FlashAttention kernels. The optional `raw` mode demonstrates the backend bug.
add_executable(trellis-test-fa-bf16-range src/test_fa_bf16_range.cpp)
target_link_libraries(trellis-test-fa-bf16-range PRIVATE trellis_core)
set_target_properties(trellis-test-fa-bf16-range PROPERTIES BUILD_RPATH "${GGML_RPATH}")
endif()
add_executable(trellis-test-ss-sample src/test_ss_sample.cpp)
target_link_libraries(trellis-test-ss-sample PRIVATE trellis_core)
set_target_properties(trellis-test-ss-sample PROPERTIES BUILD_RPATH "${GGML_RPATH}")
add_executable(trellis-test-birefnet src/test_birefnet.cpp)
target_link_libraries(trellis-test-birefnet PRIVATE trellis_core)
set_target_properties(trellis-test-birefnet PROPERTIES BUILD_RPATH "${GGML_RPATH}")
add_executable(trellis-test-preprocess src/test_preprocess.cpp)
target_link_libraries(trellis-test-preprocess PRIVATE trellis_core)
set_target_properties(trellis-test-preprocess PROPERTIES BUILD_RPATH "${GGML_RPATH}")
add_executable(trellis-test-deform src/test_deform.cpp)
target_link_libraries(trellis-test-deform PRIVATE trellis_core)
set_target_properties(trellis-test-deform PROPERTIES BUILD_RPATH "${GGML_RPATH}")
add_executable(trellis-test-ss-dec src/test_ss_dec.cpp)
target_link_libraries(trellis-test-ss-dec PRIVATE trellis_core)
set_target_properties(trellis-test-ss-dec PROPERTIES BUILD_RPATH "${GGML_RPATH}")
add_executable(trellis-test-slat-shape src/test_slat_shape.cpp)
target_link_libraries(trellis-test-slat-shape PRIVATE trellis_core)
set_target_properties(trellis-test-slat-shape PROPERTIES BUILD_RPATH "${GGML_RPATH}")
add_executable(trellis-test-dinov3 src/test_dinov3.cpp)
target_link_libraries(trellis-test-dinov3 PRIVATE trellis_core)
set_target_properties(trellis-test-dinov3 PROPERTIES BUILD_RPATH "${GGML_RPATH}")
add_executable(trellis-test-sparse-conv src/test_sparse_conv.cpp)
target_link_libraries(trellis-test-sparse-conv PRIVATE trellis_core)
set_target_properties(trellis-test-sparse-conv PROPERTIES BUILD_RPATH "${GGML_RPATH}")
add_executable(trellis-test-bigop src/test_bigop.cpp)
target_link_libraries(trellis-test-bigop PRIVATE trellis_core)
set_target_properties(trellis-test-bigop PROPERTIES BUILD_RPATH "${GGML_RPATH}")
add_executable(trellis-test-c2s src/test_c2s.cpp)
target_link_libraries(trellis-test-c2s PRIVATE trellis_core)
set_target_properties(trellis-test-c2s PROPERTIES BUILD_RPATH "${GGML_RPATH}")
add_executable(trellis-test-sparse-degenerate src/test_sparse_degenerate.cpp)
target_link_libraries(trellis-test-sparse-degenerate PRIVATE trellis_core)
set_target_properties(trellis-test-sparse-degenerate PROPERTIES BUILD_RPATH "${GGML_RPATH}")
add_executable(trellis-test-shape-dec src/test_shape_dec.cpp)
target_link_libraries(trellis-test-shape-dec PRIVATE trellis_core)
set_target_properties(trellis-test-shape-dec PROPERTIES BUILD_RPATH "${GGML_RPATH}")
add_executable(trellis-cli src/trellis_cli_main.cpp src/trellis_cli.cpp src/trellis_args.cpp)
target_link_libraries(trellis-cli PRIVATE trellis_core)
set_target_properties(trellis-cli PROPERTIES BUILD_RPATH "${GGML_RPATH}")
# Resident HTTP server (keeps the process warm; wraps trellis_run).
find_package(Threads REQUIRED)
add_executable(post-replay src/post_replay.cpp)
target_link_libraries(post-replay PRIVATE trellis_core Threads::Threads)
set_target_properties(post-replay PROPERTIES BUILD_RPATH "${GGML_RPATH}")
add_executable(trellis-server src/trellis-server.cpp src/trellis_cli.cpp src/trellis_args.cpp)
target_include_directories(trellis-server PRIVATE ${CMAKE_SOURCE_DIR}/thirdparty/cpp-httplib)
target_link_libraries(trellis-server PRIVATE trellis_core Threads::Threads)
set_target_properties(trellis-server PROPERTIES BUILD_RPATH "${GGML_RPATH}")
add_executable(trellis-test-ss-full src/test_ss_full.cpp)
target_link_libraries(trellis-test-ss-full PRIVATE trellis_core)
set_target_properties(trellis-test-ss-full PROPERTIES BUILD_RPATH "${GGML_RPATH}")