Files
2026-08-16 18:33:03 +07:00

138 lines
6.0 KiB
CMake

cmake_minimum_required(VERSION 3.14)
project(trellis2.cpp VERSION 0.1.0 LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
# ─────────────────────────────────────────────────────────────────────────
# External ggml option
#
# When OFF (default): vendor ggml as a subdirectory — the upstream behavior.
# When ON : skip the bundled ggml and resolve `find_package(ggml CONFIG)`
# against an installed ggml. Lets a downstream project link multiple
# ggml-based libraries against a single shared ggml so they don't
# ship duplicate copies into the same process.
# ─────────────────────────────────────────────────────────────────────────
option(TRELLIS2_USE_EXTERNAL_GGML "Consume external ggml via find_package() instead of the bundled submodule" OFF)
# libFuzzer harnesses (clang only). The sanitizer flags apply globally — set
# BEFORE any target so the whole tree (ggml, stb decode, preprocessing,
# loaders) is instrumented. Harness targets live in fuzz/ (added at the end).
option(TRELLIS2_FUZZ "Build libFuzzer harnesses (requires clang)" OFF)
set(TRELLIS2_FUZZ_SANITIZERS "address,undefined" CACHE STRING
"Sanitizers for the fuzz build")
if(TRELLIS2_FUZZ)
add_compile_options(-fsanitize=${TRELLIS2_FUZZ_SANITIZERS} -fsanitize=fuzzer-no-link -fno-omit-frame-pointer -g -O1)
add_link_options(-fsanitize=${TRELLIS2_FUZZ_SANITIZERS})
endif()
# ggml options — enable Metal on Apple (bundled-ggml path only)
option(TRELLIS2_METAL "Enable Metal backend" ON)
if(APPLE AND TRELLIS2_METAL AND NOT TRELLIS2_USE_EXTERNAL_GGML)
set(GGML_METAL ON CACHE BOOL "" FORCE)
set(GGML_METAL_EMBED_LIBRARY ON CACHE BOOL "" FORCE)
endif()
if(TRELLIS2_USE_EXTERNAL_GGML)
find_package(ggml CONFIG REQUIRED)
set(TRELLIS2_GGML_TARGET ggml::ggml)
else()
add_subdirectory(ggml)
set(TRELLIS2_GGML_TARGET ggml)
endif()
add_library(trellis2
trellis2.cpp trellis2.h
trellis2_capi.cpp trellis2_capi.h
mesh_export.cpp mesh_export.h
print_remesh.cpp print_remesh.h
third_party/xatlas/xatlas.cpp)
target_include_directories(trellis2 PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/stb
)
# trellis2_capi.cpp reuses the example isosurface extractor for the demo path;
# mesh_export.cpp vendors xatlas for the optional chart-based UV unwrap.
target_include_directories(trellis2 PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/examples
${CMAKE_CURRENT_SOURCE_DIR}/third_party/xatlas)
find_package(Threads REQUIRED) # xatlas uses std::thread
if(TRELLIS2_USE_EXTERNAL_GGML AND DEFINED GGML_INCLUDE_DIR)
target_include_directories(trellis2 PUBLIC ${GGML_INCLUDE_DIR})
endif()
target_link_libraries(trellis2 PUBLIC ${TRELLIS2_GGML_TARGET} PRIVATE Threads::Threads)
target_compile_features(trellis2 PUBLIC cxx_std_14)
# CGAL Alpha Wrap turns arbitrary TRELLIS triangle soups into watertight,
# intersection-free 2-manifolds for printing. Auto-detect it so ordinary builds
# retain no CGAL dependency; the C API reports whether the backend is present.
option(TRELLIS2_CGAL "Enable CGAL Alpha Wrap print remeshing when available" ON)
option(TRELLIS2_FETCH_PRINT_REMESH_DEPS
"Fetch the project-pinned CGAL and Boost headers for print remeshing" OFF)
set(TRELLIS2_PRINT_REMESH_DEPS_DIR "${CMAKE_BINARY_DIR}/_deps/print-remesh" CACHE PATH
"Directory containing project-pinned CGAL and Boost headers")
if(TRELLIS2_CGAL)
if(TRELLIS2_FETCH_PRINT_REMESH_DEPS)
find_program(TRELLIS2_BASH_EXECUTABLE bash)
if(NOT TRELLIS2_BASH_EXECUTABLE)
message(FATAL_ERROR "bash is required to fetch print-remesh dependencies")
endif()
execute_process(
COMMAND "${TRELLIS2_BASH_EXECUTABLE}"
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/fetch_print_remesh_deps.sh"
"${TRELLIS2_PRINT_REMESH_DEPS_DIR}"
RESULT_VARIABLE TRELLIS2_PRINT_REMESH_DEPS_RESULT)
if(NOT TRELLIS2_PRINT_REMESH_DEPS_RESULT EQUAL 0)
message(FATAL_ERROR "Failed to fetch pinned print-remesh dependencies")
endif()
set(CGAL_DIR "${TRELLIS2_PRINT_REMESH_DEPS_DIR}/cgal" CACHE PATH
"CGAL package directory" FORCE)
set(Boost_INCLUDE_DIR "${TRELLIS2_PRINT_REMESH_DEPS_DIR}/boost" CACHE PATH
"Boost header directory" FORCE)
set(Boost_DIR "${TRELLIS2_PRINT_REMESH_DEPS_DIR}/boost-cmake" CACHE PATH
"Header-only Boost CMake package directory" FORCE)
endif()
find_package(CGAL 5.5 QUIET)
if(CGAL_FOUND)
target_link_libraries(trellis2 PRIVATE CGAL::CGAL)
target_compile_definitions(trellis2 PRIVATE TRELLIS2_USE_CGAL=1)
target_compile_features(trellis2 PRIVATE cxx_std_17)
set(TRELLIS2_HAVE_CGAL ON)
message(STATUS "CGAL Alpha Wrap print remeshing: enabled")
elseif(TRELLIS2_FETCH_PRINT_REMESH_DEPS)
message(FATAL_ERROR "The project-pinned CGAL print-remesh dependencies were fetched but not found")
else()
message(STATUS "CGAL Alpha Wrap print remeshing: unavailable (CGAL >= 5.5 not found)")
endif()
endif()
set_property(TARGET trellis2 PROPERTY POSITION_INDEPENDENT_CODE ON)
if(BUILD_SHARED_LIBS)
target_compile_definitions(trellis2 PUBLIC TRELLIS2_SHARED)
target_compile_definitions(trellis2 PRIVATE TRELLIS2_BUILD)
endif()
option(TRELLIS2_BUILD_EXAMPLES "Build example executables" ON)
if(TRELLIS2_BUILD_EXAMPLES AND CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
add_subdirectory(examples)
endif()
option(TRELLIS2_BUILD_TESTS "Build test executables" OFF)
if(TRELLIS2_BUILD_TESTS)
enable_testing()
add_subdirectory(tests)
endif()
if(TRELLIS2_FUZZ)
add_subdirectory(fuzz)
endif()