diff --git a/.github/workflows/manifold.yml b/.github/workflows/manifold.yml index 51c526a35..0a98b9adb 100644 --- a/.github/workflows/manifold.yml +++ b/.github/workflows/manifold.yml @@ -213,7 +213,7 @@ jobs: pip install trimesh pytest - name: Install TBB if: matrix.parallelization == 'ON' - run: brew install tbb onedpl + run: brew install tbb - uses: actions/checkout@v4 - uses: jwlawson/actions-setup-cmake@v2 - name: Build @@ -232,24 +232,60 @@ jobs: sudo cmake --install . cd .. ./scripts/test-cmake.sh + LDFLAGS=-Wl,-rpath,/usr/local/lib ./scripts/test-pkgconfig.sh - build_nix: + build_mac_builtin_tbb: timeout-minutes: 30 - strategy: - matrix: - # variant: [none, tbb, js] - # disabling js variant for now - variant: [none, tbb] - runs-on: ubuntu-latest + runs-on: macos-latest + steps: + - name: Install common dependencies + run: | + brew install pkg-config googletest + pip install trimesh pytest + - uses: actions/checkout@v4 + - uses: jwlawson/actions-setup-cmake@v2 + - name: Build + run: | + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DMANIFOLD_DEBUG=ON -DMANIFOLD_PYBIND=OFF -DMANIFOLD_PAR=ON .. && make + - name: Test + run: | + cd build/test + ./manifold_test + cd ../../ + - name: test cmake consumer + run: | + cd build + sudo cmake --install . + cd .. + ./scripts/test-cmake.sh + LDFLAGS=-Wl,-rpath,/usr/local/lib ./scripts/test-pkgconfig.sh + + build_mac_builtin_tbb_subdir: + timeout-minutes: 30 + runs-on: macos-latest steps: + - name: Install common dependencies + run: | + brew install pkg-config googletest + pip install trimesh pytest - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v22 - - run: nix build -L '.?submodules=1#manifold-${{matrix.variant}}' + - uses: jwlawson/actions-setup-cmake@v2 + - name: test cmake consumer + run: | + cd .. + ./manifold/scripts/test-cmake-subdir.sh - build_nix_python: + build_nix: timeout-minutes: 30 + strategy: + matrix: + variant: [manifold-none, manifold-tbb, manifold-js, manifold3d] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v22 - - run: nix build -L '.?submodules=1#manifold3d' + - uses: DeterminateSystems/nix-installer-action@main + - uses: DeterminateSystems/magic-nix-cache-action@main + - run: nix build -L '.?submodules=1#${{matrix.variant}}' + diff --git a/CMakeLists.txt b/CMakeLists.txt index 268a4d3a4..c7f84ef7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,9 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_VERBOSE_MAKEFILE ON) +include(GNUInstallDirs) +include(CMakeDependentOption) + # Define Manifold version set(MANIFOLD_VERSION_MAJOR 2) set(MANIFOLD_VERSION_MINOR 5) @@ -31,20 +34,6 @@ set( "${MANIFOLD_VERSION_MAJOR}.${MANIFOLD_VERSION_MINOR}.${MANIFOLD_VERSION_PATCH}" ) -# Correct MANIFOLD_PAR values to on/off (previous NONE/TBB values should still -# work this way) -if(DEFINED MANIFOLD_PAR) - if( - "${MANIFOLD_PAR}" STREQUAL "" - OR "${MANIFOLD_PAR}" STREQUAL "NONE" - OR "${MANIFOLD_PAR}" STREQUAL "OFF" - ) - set(MANIFOLD_PAR OFF) - else() - set(MANIFOLD_PAR ON) - endif() -endif() - # Primary user facing options option(MANIFOLD_CROSS_SECTION "Build CrossSection for 2D support" ON) option(MANIFOLD_DEBUG "Enable debug tracing/timing" OFF) @@ -57,12 +46,12 @@ option(MANIFOLD_EXPORT "Build mesh export (via assimp) utility library" OFF) option(MANIFOLD_PAR "Enable Parallel backend" OFF) option( MANIFOLD_OPTIMIZED - "Force Optimized build, even with debugging enabled" + "Force optimized build, even with debugging enabled" OFF ) option(MANIFOLD_TEST "Enable testing suite" ON) -option(BUILD_SHARED_LIBS "Build shared library" ON) -include(CMakeDependentOption) +option(MANIFOLD_PYBIND "Build python bindings" OFF) +# MANIFOLD_CBIND is only available when MANIFOLD_CROSS_SECTION is enabled cmake_dependent_option( MANIFOLD_CBIND "Build C (FFI) bindings" @@ -70,7 +59,7 @@ cmake_dependent_option( "MANIFOLD_CROSS_SECTION" OFF ) -option(MANIFOLD_PYBIND "Build python bindings" OFF) +# MANIFOLD_JSBIND is only available when building with Emscripten cmake_dependent_option( MANIFOLD_JSBIND "Build js binding" @@ -78,26 +67,33 @@ cmake_dependent_option( "EMSCRIPTEN" OFF ) - +# These three options can force the build to avoid using the system version of +# the dependency +# This will either use the provided source directory via +# FETCHCONTENT_SOURCE_DIR_XXX, or fetch the source from GitHub. +# Note that the dependency will be built as static dependency to avoid dynamic +# library conflict. +# When the system package is unavailable, the option will be automatically set +# to true. +option(MANIFOLD_USE_BUILTIN_TBB "Use builtin tbb" OFF) +option(MANIFOLD_USE_BUILTIN_CLIPPER2 "Use builtin clipper2" OFF) +option(MANIFOLD_USE_BUILTIN_NANOBIND "Use builtin nanobind" OFF) + +# default to Release build +option(CMAKE_BUILD_TYPE "Build type" Release) +# default to building shared library +option(BUILD_SHARED_LIBS "Build shared library" ON) # Set some option values in the CMake cache -if(NOT MANIFOLD_FLAGS) - set(MANIFOLD_FLAGS "") -endif() set(MANIFOLD_FLAGS "" CACHE STRING "Manifold compiler flags") # Development options option(TRACY_ENABLE "Use tracy profiling" OFF) option(TRACY_MEMORY_USAGE "Track memory allocation with tracy (expensive)" OFF) +option(MANIFOLD_FUZZ "Enable fuzzing tests" OFF) mark_as_advanced(TRACY_ENABLE) mark_as_advanced(TRACY_MEMORY_USAGE) - -# fuzztest is a rather large dependency -option(MANIFOLD_FUZZ "Enable fuzzing tests" OFF) mark_as_advanced(MANIFOLD_FUZZ) -# Define some paths for CMake -include(GNUInstallDirs) - # Always build position independent code for relocatability set(CMAKE_POSITION_INDEPENDENT_CODE ON) @@ -111,32 +107,34 @@ if(MANIFOLD_FUZZ) # enable fuzztest fuzzing mode set(FUZZTEST_FUZZING_MODE ON) # address sanitizer required - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") + add_compile_options(-fsanitize=address) endif() if(TRACY_ENABLE) option(CMAKE_BUILD_TYPE "Build type" RelWithDebInfo) - if(TRACY_MEMORY_USAGE) - list(APPEND MANIFOLD_FLAGS -DTRACY_MEMORY_USAGE) - endif() - if(NOT MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer") - endif() -else() - option(CMAKE_BUILD_TYPE "Build type" Release) endif() if(EMSCRIPTEN) message("Building for Emscripten") + add_link_options(-sALLOW_MEMORY_GROWTH=1) + add_link_options(-sMAXIMUM_MEMORY=4294967296) + if(MANIFOLD_PAR) + set(CMAKE_THREAD_LIBS_INIT "-pthread") + add_compile_options(-pthread) + # PTHREAD_POOL_SIZE is set to 4 for OK-ish performance, in general we are + # not getting too much speedup for very large number of cores, and a lot of + # CPUs now have 4 cores... + add_link_options(-sPTHREAD_POOL_SIZE=4) + # mimalloc is needed for good performance + add_link_options(-sMALLOC=mimalloc) + # The default stack size apparently causes problem when parallelization is + # enabled. + add_link_options(-sSTACK_SIZE=10MB) + endif() if(MANIFOLD_DEBUG) list(APPEND MANIFOLD_FLAGS -fexceptions) - string( - APPEND - CMAKE_EXE_LINKER_FLAGS - "-sALLOW_MEMORY_GROWTH=1 -fexceptions -sDISABLE_EXCEPTION_CATCHING=0 " - ) - else() - string(APPEND CMAKE_EXE_LINKER_FLAGS "-sALLOW_MEMORY_GROWTH=1 ") + add_link_options(-fexceptions) + add_link_options(-sDISABLE_EXCEPTION_CATCHING=0) endif() set(MANIFOLD_PYBIND OFF) set(BUILD_SHARED_LIBS OFF) @@ -153,23 +151,20 @@ endif() if(MSVC) list(APPEND MANIFOLD_FLAGS /DNOMINMAX /bigobj) else() - if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - list(APPEND WARNING_FLAGS -Wall -Wno-unknown-warning-option -Wno-unused) - else() - list( - APPEND - WARNING_FLAGS - -Wall - -Wno-unknown-warning-option - -Wno-unused - -Wno-shorten-64-to-32 - ) - endif() + list( + APPEND + WARNING_FLAGS + -Wall + -Wno-unknown-warning-option + -Wno-unused + -Wno-shorten-64-to-32 + ) if(CMAKE_SYSTEM_NAME STREQUAL "Windows") if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") list(APPEND WARNING_FLAGS -Wno-format) endif() - else() + elseif(PROJECT_IS_TOP_LEVEL) + # only do -Werror if we are the top level project list(APPEND WARNING_FLAGS -Werror) endif() list(APPEND MANIFOLD_FLAGS ${WARNING_FLAGS}) @@ -180,19 +175,20 @@ else() ) list(APPEND MANIFOLD_FLAGS -O3) endif() -endif() - -if(CODE_COVERAGE AND NOT MSVC) - list( - APPEND - COVERAGE_FLAGS - -coverage - -fno-inline-small-functions - -fkeep-inline-functions - -fkeep-static-functions - ) - list(APPEND MANIFOLD_FLAGS ${COVERAGE_FLAGS}) - add_link_options("-coverage") + if("${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo") + list(APPEND MANIFOLD_FLAGS -fno-omit-frame-pointer) + endif() + if(CODE_COVERAGE) + list( + APPEND + MANIFOLD_FLAGS + -coverage + -fno-inline-small-functions + -fkeep-inline-functions + -fkeep-static-functions + ) + add_link_options(-coverage) + endif() endif() # RPath settings @@ -210,100 +206,8 @@ if("${isSystemDir}" STREQUAL "-1") set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) endif("${isSystemDir}" STREQUAL "-1") -# Dependencies -include(FetchContent) - -function(logmissingdep PKG) - if(NOT MANIFOLD_DOWNLOADS) - if(ARGC EQUAL 3) - set(MSG "${ARGV2} enabled, but ${PKG} was not found ") - string(APPEND MSG "and dependency downloading is disabled. ") - else() - set(MSG "${PKG} not found, and dependency downloading disabled. ") - endif() - string(APPEND MSG "Please install ${PKG} and reconfigure.\n") - message(FATAL_ERROR ${MSG}) - endif() -endfunction() - -# If we're building parallel, we need the requisite libraries -if(MANIFOLD_PAR) - find_package(Threads REQUIRED) - find_package(TBB QUIET) - find_package(PkgConfig QUIET) - if(NOT TBB_FOUND AND PKG_CONFIG_FOUND) - pkg_check_modules(TBB tbb) - endif() - if(NOT TBB_FOUND) - logmissingdep("TBB" , "Parallel mode") - message(STATUS "TBB not found, downloading from source") - set(TBB_TEST OFF CACHE INTERNAL "" FORCE) - set(TBB_STRICT OFF CACHE INTERNAL "" FORCE) - FetchContent_Declare( - TBB - GIT_REPOSITORY https://github.com/oneapi-src/oneTBB.git - GIT_TAG v2021.11.0 - GIT_PROGRESS TRUE - ) - FetchContent_MakeAvailable(TBB) - set_property(DIRECTORY ${tbb_SOURCE_DIR} PROPERTY EXCLUDE_FROM_ALL YES) - # note: we do want to install tbb to the user machine when built from - # source - if(NOT EMSCRIPTEN) - install(TARGETS tbb) - endif() - endif() -endif() - -# If we're building cross_section, we need Clipper2 -if(MANIFOLD_CROSS_SECTION) - find_package(Clipper2 QUIET) - if(NOT Clipper2_FOUND AND PKG_CONFIG_FOUND) - pkg_check_modules(Clipper2 Clipper2) - endif() - if(Clipper2_FOUND) - add_library(Clipper2 SHARED IMPORTED) - set_property( - TARGET Clipper2 - PROPERTY IMPORTED_LOCATION ${Clipper2_LINK_LIBRARIES} - ) - if(WIN32) - set_property( - TARGET Clipper2 - PROPERTY IMPORTED_IMPLIB ${Clipper2_LINK_LIBRARIES} - ) - endif() - target_include_directories(Clipper2 INTERFACE ${Clipper2_INCLUDE_DIRS}) - else() - logmissingdep("Clipper2" , "cross_section") - message(STATUS "clipper2 not found, downloading from source") - set(CLIPPER2_UTILS OFF) - set(CLIPPER2_EXAMPLES OFF) - set(CLIPPER2_TESTS OFF) - set( - CLIPPER2_USINGZ - "OFF" - CACHE STRING - "Preempt cache default of USINGZ (we only use 2d)" - ) - FetchContent_Declare( - Clipper2 - GIT_REPOSITORY https://github.com/AngusJohnson/Clipper2.git - GIT_TAG ff378668baae3570e9d8070aa9eb339bdd5a6aba - GIT_PROGRESS TRUE - SOURCE_SUBDIR CPP - ) - FetchContent_MakeAvailable(Clipper2) - if(NOT EMSCRIPTEN) - install(TARGETS Clipper2) - endif() - endif() -endif() - -# If we're supporting mesh I/O, we need assimp -if(MANIFOLD_EXPORT) - find_package(assimp REQUIRED) -endif() +include(${PROJECT_SOURCE_DIR}/cmake/manifoldDeps.cmake) +include(${PROJECT_SOURCE_DIR}/cmake/configHelper.cmake) add_subdirectory(src) add_subdirectory(bindings) @@ -311,55 +215,7 @@ add_subdirectory(samples) add_subdirectory(test) add_subdirectory(extras) -# configuration summary, idea from openscad -# https://github.com/openscad/openscad/blob/master/cmake/Modules/info.cmake -message(STATUS "====================================") -message(STATUS "Manifold Build Configuration Summary") -message(STATUS "====================================") -message(STATUS " ") -if(MXECROSS) - message(STATUS "Environment: MXE") -elseif(APPLE) - message(STATUS "Environment: macOS") -elseif(WIN32) - if(MINGW) - message(STATUS "Environment: msys2") - else() - message(STATUS "Environment: Windows") - endif() -elseif(LINUX) - message(STATUS "Environment: Linux") -elseif(UNIX) - message(STATUS "Environment: Unknown Unix") -else() - message(STATUS "Environment: Unknown") -endif() -message(STATUS " ") -message(STATUS "CMAKE_VERSION: ${CMAKE_VERSION}") -message(STATUS "CMAKE_TOOLCHAIN_FILE: ${CMAKE_TOOLCHAIN_FILE}") -message(STATUS "CMAKE_GENERATOR: ${CMAKE_GENERATOR}") -message(STATUS "CPACK_CMAKE_GENERATOR: ${CPACK_CMAKE_GENERATOR}") -message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") -message(STATUS "CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}") -message(STATUS "CMAKE_CXX_COMPILER_ID: ${CMAKE_CXX_COMPILER_ID}") -message(STATUS "CMAKE_CXX_COMPILER_VERSION: ${CMAKE_CXX_COMPILER_VERSION}") -if(APPLE) - message(STATUS "CMAKE_OSX_DEPLOYMENT_TARGET: ${CMAKE_OSX_DEPLOYMENT_TARGET}") - message(STATUS "CMAKE_OSX_ARCHITECTURES: ${CMAKE_OSX_ARCHITECTURES}") -endif() -message(STATUS "BUILD_SHARED_LIBS: ${BUILD_SHARED_LIBS}") -message(STATUS " ") -message(STATUS "MANIFOLD_PAR: ${MANIFOLD_PAR}") -message(STATUS "MANIFOLD_CROSS_SECTION: ${MANIFOLD_CROSS_SECTION}") -message(STATUS "MANIFOLD_EXPORT: ${MANIFOLD_EXPORT}") -message(STATUS "MANIFOLD_TEST: ${MANIFOLD_TEST}") -message(STATUS "MANIFOLD_FUZZ: ${MANIFOLD_FUZZ}") -message(STATUS "MANIFOLD_DEBUG: ${MANIFOLD_DEBUG}") -message(STATUS "MANIFOLD_CBIND: ${MANIFOLD_CBIND}") -message(STATUS "MANIFOLD_PYBIND: ${MANIFOLD_PYBIND}") -message(STATUS "MANIFOLD_JSBIND: ${MANIFOLD_JSBIND}") -message(STATUS "MANIFOLD_FLAGS: ${MANIFOLD_FLAGS}") -message(STATUS " ") +include(${PROJECT_SOURCE_DIR}/cmake/info.cmake) # If it's an EMSCRIPTEN build, we're done if(EMSCRIPTEN) @@ -368,13 +224,13 @@ endif() # CMake exports configure_file( - manifoldConfig.cmake.in + cmake/manifoldConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/manifoldConfig.cmake @ONLY ) include(CMakePackageConfigHelpers) write_basic_package_version_file( - ${CMAKE_BINARY_DIR}/cmake/manifoldConfigVersion.cmake + ${CMAKE_CURRENT_BINARY_DIR}/cmake/manifoldConfigVersion.cmake VERSION ${MANIFOLD_VERSION} COMPATIBILITY SameMajorVersion ) @@ -398,34 +254,52 @@ install( # install public headers set( MANIFOLD_PUBLIC_HDRS - include/manifold/common.h - include/manifold/iters.h - include/manifold/linalg.h - include/manifold/manifold.h - include/manifold/optional_assert.h - include/manifold/parallel.h - include/manifold/polygon.h - include/manifold/vec_view.h + common.h + iters.h + linalg.h + manifold.h + optional_assert.h + polygon.h + vec_view.h + $<$:cross_section.h> + $<$:meshIO.h> ) - -if(MANIFOLD_CROSS_SECTION) - list(APPEND MANIFOLD_PUBLIC_HDRS include/manifold/cross_section.h) -endif() - -if(MANIFOLD_EXPORT) - list(APPEND MANIFOLD_PUBLIC_HDRS include/manifold/meshIO.h) -endif() +list(TRANSFORM MANIFOLD_PUBLIC_HDRS PREPEND include/manifold/) install( FILES ${MANIFOLD_PUBLIC_HDRS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/manifold ) +# note that the path ${CMAKE_CURRENT_BINARY_DIR}/include is included when we +# build the manifold target (as ${PROJECT_SOURCE_DIR}/include), so users can +# include manifold/version.h without installing our library. +configure_file( + cmake/version.h.in + ${CMAKE_CURRENT_BINARY_DIR}/include/manifold/version.h + @ONLY +) +set_source_files_properties( + ${CMAKE_CURRENT_BINARY_DIR}/include/manifold/version.h + PROPERTIES GENERATED TRUE +) +install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/include/manifold/version.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/manifold +) + # PkgConfig file +if(MANIFOLD_PAR) + set(TEMPLATE_OPTIONAL_TBB "tbb") +endif() if(MANIFOLD_CROSS_SECTION) set(TEMPLATE_OPTIONAL_CLIPPER "Clipper2") endif() -configure_file(manifold.pc.in ${CMAKE_CURRENT_BINARY_DIR}/manifold.pc @ONLY) +configure_file( + cmake/manifold.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/manifold.pc + @ONLY +) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/manifold.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig diff --git a/Doxyfile b/Doxyfile index 0e25175d6..2988011d1 100644 --- a/Doxyfile +++ b/Doxyfile @@ -971,10 +971,10 @@ INPUT = include/manifold/manifold.h \ include/manifold/common.h \ include/manifold/meshIO.h \ include/manifold/linalg.h \ - include/manifold/parallel.h \ include/manifold/vec_view.h \ include/manifold/iters.h \ include/manifold/optional_assert.h \ + src/parallel.h \ src/manifold.cpp \ src/constructors.cpp \ src/polygon.cpp \ diff --git a/README.md b/README.md index 2c17d47cb..cd4b51707 100644 --- a/README.md +++ b/README.md @@ -112,13 +112,30 @@ CMake flags (usage e.g. `-DMANIFOLD_DEBUG=ON`): - `TRACY_ENABLE=[, ON]`: Enable integration with tracy profiler. See profiling section below. -Offline building (with missing dependencies): +Dependency version override: +- `MANIFOLD_USE_BUILTIN_TBB=[, ON]`: Use builtin version of tbb. +- `MANIFOLD_USE_BUILTIN_CLIPPER2=[, ON]`: Use builtin version of clipper2. +- `MANIFOLD_USE_BUILTIN_NANOBIND=[, ON]`: Use builtin version of nanobind. + +> Note: These three options can force the build to avoid using the system +> version of the dependency. This will either use the provided source directory +> via `FETCHCONTENT_SOURCE_DIR_*` (see below), or fetch the source from GitHub. +> Note that the dependency will be built as static dependency to avoid dynamic +> library conflict. When the system package is unavailable, the option will be +> automatically set to true. + +Offline building (with missing dependencies/dependency version override): - `MANIFOLD_DOWNLOADS=[OFF, ]`: Automatically download missing dependencies. Need to set `FETCHCONTENT_SOURCE_DIR_*` if the dependency `*` is missing. - `FETCHCONTENT_SOURCE_DIR_TBB`: path to tbb source (if `MANIFOLD_PAR` is enabled). - `FETCHCONTENT_SOURCE_DIR_CLIPPER2`: path to tbb source (if `MANIFOLD_CROSS_SECTION` is enabled). +- `FETCHCONTENT_SOURCE_DIR_NANOBIND`: path to nanobind source (if `MANIFOLD_PYBIND` is enabled). - `FETCHCONTENT_SOURCE_DIR_GOOGLETEST`: path to googletest source (if `MANIFOLD_TEST` is enabled). +> Note: When `FETCHCONTENT_SOURCE_DIR_*` is set, CMake will use the provided +> source directly without downloading regardless of the value of +> `MANIFOLD_DOWNLOADS`. + The build instructions used by our CI are in [manifold.yml](https://github.com/elalish/manifold/blob/master/.github/workflows/manifold.yml), which is a good source to check if something goes wrong and for instructions specific to other platforms, like Windows. ### WASM diff --git a/bindings/CMakeLists.txt b/bindings/CMakeLists.txt index dcf8429c4..bf7614498 100644 --- a/bindings/CMakeLists.txt +++ b/bindings/CMakeLists.txt @@ -16,7 +16,7 @@ if(NOT MANIFOLD_CROSS_SECTION) return() endif() -if(NOT EMSCRIPTEN AND MANIFOLD_CBIND) +if(MANIFOLD_CBIND) add_subdirectory(c) endif() diff --git a/bindings/c/CMakeLists.txt b/bindings/c/CMakeLists.txt index 6c65476c4..2f3150d06 100644 --- a/bindings/c/CMakeLists.txt +++ b/bindings/c/CMakeLists.txt @@ -1,4 +1,17 @@ -# this is a shared library for FFI bindings +# Copyright 2024 The Manifold Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include @@ -7,25 +20,13 @@ include_directories( add_library( manifoldc - SHARED manifoldc.cpp conv.cpp box.cpp cross.cpp rect.cpp ) - -if(MSVC) - set_target_properties(manifoldc PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) - set_target_properties( - manifoldc - PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin - ) - set_target_properties( - manifoldc - PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin - ) -endif() +exportlib(manifoldc) if(MANIFOLD_EXPORT) target_sources(manifoldc PRIVATE meshIOc.cpp) @@ -38,10 +39,9 @@ target_include_directories( manifoldc PUBLIC $ - $ + $ ) target_compile_options(manifoldc PRIVATE ${MANIFOLD_FLAGS}) -target_compile_features(manifoldc PRIVATE cxx_std_17) install(TARGETS manifoldc EXPORT manifoldTargets) install( diff --git a/bindings/python/CMakeLists.txt b/bindings/python/CMakeLists.txt index 4dd16ad15..a285a6bac 100644 --- a/bindings/python/CMakeLists.txt +++ b/bindings/python/CMakeLists.txt @@ -12,58 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -if(NOT MANIFOLD_PYBIND) - return() -endif() - -project(python) - -if(Python_VERSION VERSION_LESS 3.12) - find_package(Python COMPONENTS Interpreter Development.Module REQUIRED) -else() - find_package(Python COMPONENTS Interpreter Development.SABIModule REQUIRED) -endif() -if(Python_VERSION VERSION_GREATER_EQUAL 3.11) - set(MANIFOLD_PYBIND_STUBGEN ON) -else() - # stubgen does not support version less than 3.11 - set(MANIFOLD_PYBIND_STUBGEN OFF) - message("Python version too old, stub will not be generated") -endif() - -execute_process( - COMMAND "${Python_EXECUTABLE}" -m nanobind --version - OUTPUT_STRIP_TRAILING_WHITESPACE - OUTPUT_VARIABLE NB_VERSION -) -# we are fine with 2.0.0 -if(NB_VERSION VERSION_GREATER_EQUAL 2.0.0) - message("Found nanobind, version ${NB_VERSION}") - execute_process( - COMMAND "${Python_EXECUTABLE}" -m nanobind --cmake_dir - OUTPUT_STRIP_TRAILING_WHITESPACE - OUTPUT_VARIABLE nanobind_ROOT - ) - find_package(nanobind CONFIG REQUIRED) -else() - message(STATUS "nanobind not found, downloading from source") - include(FetchContent) - FetchContent_Declare( - nanobind - GIT_REPOSITORY https://github.com/wjakob/nanobind.git - GIT_TAG - 784efa2a0358a4dc5432c74f5685ee026e20f2b6 # v2.2.0 - GIT_PROGRESS TRUE - ) - FetchContent_MakeAvailable(nanobind) - set(NB_VERSION 2.2.0) -endif() - -if(NB_VERSION VERSION_LESS 2.1.0) - message("Nanobind version too old, stub will not be generated") - set(MANIFOLD_PYBIND_STUBGEN OFF) -endif() - nanobind_add_module(manifold3d NB_STATIC STABLE_ABI LTO autogen_docstrings.inl manifold3d.cpp ) @@ -84,19 +32,18 @@ target_compile_options( manifold3d PRIVATE ${MANIFOLD_FLAGS} -DMODULE_NAME=manifold3d ) -target_compile_features(manifold3d PUBLIC cxx_std_17) set_target_properties(manifold3d PROPERTIES OUTPUT_NAME "manifold3d") message(Python_EXECUTABLE = ${Python_EXECUTABLE}) # ideally we should generate a dependency file from python... set( DOCSTRING_DEPS - ${CMAKE_SOURCE_DIR}/src/manifold.cpp - ${CMAKE_SOURCE_DIR}/src/constructors.cpp - ${CMAKE_SOURCE_DIR}/src/sort.cpp - ${CMAKE_SOURCE_DIR}/src/cross_section/cross_section.cpp - ${CMAKE_SOURCE_DIR}/src/polygon.cpp - ${CMAKE_SOURCE_DIR}/include/manifold/common.h + ${PROJECT_SOURCE_DIR}/src/manifold.cpp + ${PROJECT_SOURCE_DIR}/src/constructors.cpp + ${PROJECT_SOURCE_DIR}/src/sort.cpp + ${PROJECT_SOURCE_DIR}/src/cross_section/cross_section.cpp + ${PROJECT_SOURCE_DIR}/src/polygon.cpp + ${PROJECT_SOURCE_DIR}/include/manifold/common.h ${CMAKE_CURRENT_SOURCE_DIR}/gen_docs.py ${CMAKE_CURRENT_SOURCE_DIR}/docstring_override.txt ) diff --git a/bindings/wasm/CMakeLists.txt b/bindings/wasm/CMakeLists.txt index e2431082d..190e6142a 100644 --- a/bindings/wasm/CMakeLists.txt +++ b/bindings/wasm/CMakeLists.txt @@ -12,15 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -project(wasm) - add_executable(manifoldjs bindings.cpp) set_source_files_properties( bindings.cpp PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bindings.js ) -target_link_libraries(manifoldjs manifold) +target_link_libraries( + manifoldjs + PRIVATE manifold $<$:TBB::tbb> +) target_compile_options(manifoldjs PRIVATE ${MANIFOLD_FLAGS}) target_link_options( manifoldjs @@ -34,7 +35,6 @@ target_link_options( -sEXPORT_ES6=1 ) -target_compile_features(manifoldjs PUBLIC cxx_std_17) set_target_properties(manifoldjs PROPERTIES OUTPUT_NAME "manifold") file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/examples/built) @@ -46,28 +46,18 @@ add_custom_target( DEPENDS manifoldjs ${CMAKE_CURRENT_SOURCE_DIR}/manifold*.d.ts ) -# copy WASM build back here for publishing to npm add_custom_command( TARGET js_deps POST_BUILD + # copy WASM build back here for publishing to npm COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/manifold.* ${CMAKE_CURRENT_SOURCE_DIR} -) - -# copy WASM build and TS declarations for Vite to package into ManifoldCAD.org -add_custom_command( - TARGET js_deps - POST_BUILD + # copy WASM build and TS declarations for Vite to package into ManifoldCAD.org COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/manifold* ${CMAKE_CURRENT_SOURCE_DIR}/examples/built/ -) - -# copy TS declarations to public so they can be accessed by our editor -add_custom_command( - TARGET js_deps - POST_BUILD + # copy TS declarations to public so they can be accessed by our editor COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/manifold*.d.ts ${CMAKE_CURRENT_SOURCE_DIR}/examples/public/ diff --git a/cmake/configHelper.cmake b/cmake/configHelper.cmake new file mode 100644 index 000000000..cddf0b32d --- /dev/null +++ b/cmake/configHelper.cmake @@ -0,0 +1,39 @@ +# Copyright 2024 The Manifold Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +function(exportbin TARGET) + if(MSVC) + set_target_properties( + ${TARGET} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin + ) + endif() +endfunction() + +function(exportlib TARGET) + add_library(manifold::${TARGET} ALIAS ${TARGET}) + set_target_properties( + ${TARGET} + PROPERTIES VERSION "${MANIFOLD_VERSION}" SOVERSION ${MANIFOLD_VERSION_MAJOR} + ) + if(MSVC) + set_target_properties( + ${TARGET} + PROPERTIES + WINDOWS_EXPORT_ALL_SYMBOLS ON + LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib + ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib + ) + endif() +endfunction() diff --git a/cmake/info.cmake b/cmake/info.cmake new file mode 100644 index 000000000..2687bd6cf --- /dev/null +++ b/cmake/info.cmake @@ -0,0 +1,90 @@ +# Copyright 2024 The Manifold Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# configuration summary, idea from openscad +# https://github.com/openscad/openscad/blob/master/cmake/Modules/info.cmake + +get_target_property(MANIFOLD_COMPILE_OPTIONS manifold COMPILE_OPTIONS) +get_target_property(MANIFOLD_LINK_OPTIONS manifold LINK_OPTIONS) +if(MANIFOLD_LINK_OPTIONS STREQUAL "MANIFOLD_LINK_OPTIONS-NOTFOUND") + set(MANIFOLD_LINK_OPTIONS "") +endif() + +message(STATUS "====================================") +message(STATUS "Manifold Build Configuration Summary") +message(STATUS "====================================") +message(STATUS " ") +if(MXECROSS) + message(STATUS "Environment: MXE") +elseif(APPLE) + message(STATUS "Environment: macOS") +elseif(WIN32) + if(MINGW) + message(STATUS "Environment: msys2") + else() + message(STATUS "Environment: Windows") + endif() +elseif(LINUX) + message(STATUS "Environment: Linux") +elseif(UNIX) + message(STATUS "Environment: Unknown Unix") +else() + message(STATUS "Environment: Unknown") +endif() +message(STATUS " ") +message(STATUS "CMAKE_VERSION: ${CMAKE_VERSION}") +message(STATUS "CMAKE_TOOLCHAIN_FILE: ${CMAKE_TOOLCHAIN_FILE}") +message(STATUS "CMAKE_GENERATOR: ${CMAKE_GENERATOR}") +message(STATUS "CPACK_CMAKE_GENERATOR: ${CPACK_CMAKE_GENERATOR}") +message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") +message(STATUS "CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}") +message(STATUS "CMAKE_CXX_COMPILER_ID: ${CMAKE_CXX_COMPILER_ID}") +message(STATUS "CMAKE_CXX_COMPILER_VERSION: ${CMAKE_CXX_COMPILER_VERSION}") +if(APPLE) + message( + STATUS + "CMAKE_OSX_DEPLOYMENT_TARGET: ${CMAKE_OSX_DEPLOYMENT_TARGET}" + ) + message(STATUS "CMAKE_OSX_ARCHITECTURES: ${CMAKE_OSX_ARCHITECTURES}") +endif() +message(STATUS "BUILD_SHARED_LIBS: ${BUILD_SHARED_LIBS}") +message(STATUS " ") +message(STATUS "MANIFOLD_VERSION: ${MANIFOLD_VERSION}") +message(STATUS "MANIFOLD_PAR: ${MANIFOLD_PAR}") +message(STATUS "MANIFOLD_CROSS_SECTION: ${MANIFOLD_CROSS_SECTION}") +message(STATUS "MANIFOLD_EXPORT: ${MANIFOLD_EXPORT}") +message(STATUS "MANIFOLD_TEST: ${MANIFOLD_TEST}") +message(STATUS "MANIFOLD_DEBUG: ${MANIFOLD_DEBUG}") +message(STATUS "MANIFOLD_CBIND: ${MANIFOLD_CBIND}") +message(STATUS "MANIFOLD_PYBIND: ${MANIFOLD_PYBIND}") +message(STATUS "MANIFOLD_JSBIND: ${MANIFOLD_JSBIND}") +message(STATUS "MANIFOLD_FLAGS: ${MANIFOLD_FLAGS}") +# these two include global flags added through add_compile_options and +# add_link_options +message(STATUS "MANIFOLD_COMPILE_OPTIONS: ${MANIFOLD_COMPILE_OPTIONS}") +message(STATUS "MANIFOLD_LINK_OPTIONS: ${MANIFOLD_LINK_OPTIONS}") +message(STATUS "MANIFOLD_DOWNLOADS: ${MANIFOLD_DOWNLOADS}") +message(STATUS "MANIFOLD_USE_BUILTIN_TBB: ${MANIFOLD_USE_BUILTIN_TBB}") +message( + STATUS + "MANIFOLD_USE_BUILTIN_CLIPPER2: ${MANIFOLD_USE_BUILTIN_CLIPPER2}" +) +message( + STATUS + "MANIFOLD_USE_BUILTIN_NANOBIND: ${MANIFOLD_USE_BUILTIN_NANOBIND}" +) +message(STATUS "MANIFOLD_FUZZ: ${MANIFOLD_FUZZ}") +message(STATUS "TRACY_ENABLE: ${TRACY_ENABLE}") +message(STATUS "TRACY_MEMORY_USAGE: ${TRACY_MEMORY_USAGE}") +message(STATUS " ") diff --git a/manifold.pc.in b/cmake/manifold.pc.in similarity index 76% rename from manifold.pc.in rename to cmake/manifold.pc.in index edd066175..6d0da0d85 100644 --- a/manifold.pc.in +++ b/cmake/manifold.pc.in @@ -7,6 +7,6 @@ Name: manifold@PCFILE_LIB_SUFFIX@ Description: Geometry library for topological robustness Version: @MANIFOLD_VERSION@ URL: https://github.com/elalish/manifold -Requires-private: tbb @TEMPLATE_OPTIONAL_CLIPPER@ +Requires-private: @TEMPLATE_OPTIONAL_TBB@ @TEMPLATE_OPTIONAL_CLIPPER@ Libs: -L${libdir} -lmanifold@PCFILE_LIB_SUFFIX@ -Cflags: -I${includedir} +Cflags: -I${includedir} -std=c++17 diff --git a/manifoldConfig.cmake.in b/cmake/manifoldConfig.cmake.in similarity index 79% rename from manifoldConfig.cmake.in rename to cmake/manifoldConfig.cmake.in index 93cfb0280..b4d3feb2e 100644 --- a/manifoldConfig.cmake.in +++ b/cmake/manifoldConfig.cmake.in @@ -12,12 +12,14 @@ if(_FIND_ROOT STREQUAL "/") endif() set(MANIFOLD_CROSS_SECTION "@MANIFOLD_CROSS_SECTION@") -if(MANIFOLD_CROSS_SECTION) +set(MANIFOLD_USE_BUILTIN_CLIPPER2 "@MANIFOLD_USE_BUILTIN_CLIPPER2@") +if(MANIFOLD_CROSS_SECTION AND NOT MANIFOLD_USE_BUILTIN_CLIPPER2) set(Clipper2_ROOT "${_FIND_ROOT}") find_package(Clipper2 REQUIRED) endif() set(MANIFOLD_PAR "@MANIFOLD_PAR@") -if(MANIFOLD_PAR STREQUAL "ON") +set(MANIFOLD_USE_BUILTIN_TBB "@MANIFOLD_USE_BUILTIN_TBB@") +if(MANIFOLD_PAR STREQUAL "ON" AND NOT MANIFOLD_USE_BUILTIN_TBB) find_package(TBB REQUIRED) endif() set(MANIFOLD_EXPORT "@MANIFOLD_EXPORT@") diff --git a/cmake/manifoldDeps.cmake b/cmake/manifoldDeps.cmake new file mode 100644 index 000000000..a0e1af0ec --- /dev/null +++ b/cmake/manifoldDeps.cmake @@ -0,0 +1,232 @@ +# Copyright 2024 The Manifold Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +include(FetchContent) + +function(logmissingdep PKG) + # if this is already in FETCHCONTENT_SOURCE_DIR_X, we don't have to + # download... + if(DEFINED FETCHCONTENT_SOURCE_DIR_${PKG}) + return() + endif() + if(NOT MANIFOLD_DOWNLOADS) + if(ARGC EQUAL 3) + set(MSG "${ARGV2} enabled, but ${PKG} was not found ") + string(APPEND MSG "and dependency downloading is disabled. ") + else() + set(MSG "${PKG} not found, and dependency downloading disabled. ") + endif() + string(APPEND MSG "Please install ${PKG} and reconfigure.\n") + message(FATAL_ERROR ${MSG}) + else() + message(STATUS "${PKG} not found, downloading from source") + endif() +endfunction() + +set(OLD_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS}) +# we build fetched dependencies as static library +set(BUILD_SHARED_LIBS OFF) + +# If we're building parallel, we need tbb +if(MANIFOLD_PAR) + find_package(Threads REQUIRED) + if(NOT MANIFOLD_USE_BUILTIN_TBB) + find_package(TBB QUIET) + find_package(PkgConfig QUIET) + if(NOT TBB_FOUND AND PKG_CONFIG_FOUND) + pkg_check_modules(TBB tbb) + endif() + endif() + if(TBB_FOUND) + if(NOT TARGET TBB::tbb) + if(NOT TARGET tbb) + add_library(TBB::tbb SHARED IMPORTED) + set_property( + TARGET TBB::tbb + PROPERTY IMPORTED_LOCATION ${TBB_LINK_LIBRARIES} + ) + target_include_directories(TBB::tbb INTERFACE ${TBB_INCLUDE_DIRS}) + else() + add_library(TBB::tbb ALIAS tbb) + endif() + endif() + else() + logmissingdep("TBB" , "Parallel mode") + set(MANIFOLD_USE_BUILTIN_TBB ON) + set(TBB_TEST OFF CACHE INTERNAL "" FORCE) + set(TBB_STRICT OFF CACHE INTERNAL "" FORCE) + FetchContent_Declare( + TBB + GIT_REPOSITORY https://github.com/oneapi-src/oneTBB.git + GIT_TAG v2021.11.0 + GIT_PROGRESS TRUE + EXCLUDE_FROM_ALL + ) + FetchContent_MakeAvailable(TBB) + endif() +endif() + +# If we're building cross_section, we need Clipper2 +if(MANIFOLD_CROSS_SECTION) + if(NOT MANIFOLD_USE_BUILTIN_CLIPPER2) + find_package(Clipper2 QUIET) + if(NOT Clipper2_FOUND AND PKG_CONFIG_FOUND) + pkg_check_modules(Clipper2 Clipper2) + endif() + endif() + if(Clipper2_FOUND) + add_library(Clipper2 SHARED IMPORTED) + set_property( + TARGET Clipper2 + PROPERTY IMPORTED_LOCATION ${Clipper2_LINK_LIBRARIES} + ) + if(WIN32) + set_property( + TARGET Clipper2 + PROPERTY IMPORTED_IMPLIB ${Clipper2_LINK_LIBRARIES} + ) + endif() + target_include_directories(Clipper2 INTERFACE ${Clipper2_INCLUDE_DIRS}) + else() + logmissingdep("Clipper2" , "cross_section") + set(MANIFOLD_USE_BUILTIN_CLIPPER2 ON) + set(CLIPPER2_UTILS OFF) + set(CLIPPER2_EXAMPLES OFF) + set(CLIPPER2_TESTS OFF) + set( + CLIPPER2_USINGZ + OFF + CACHE BOOL + "Preempt cache default of USINGZ (we only use 2d)" + ) + FetchContent_Declare( + Clipper2 + GIT_REPOSITORY https://github.com/AngusJohnson/Clipper2.git + GIT_TAG ff378668baae3570e9d8070aa9eb339bdd5a6aba + GIT_PROGRESS TRUE + SOURCE_SUBDIR CPP + EXCLUDE_FROM_ALL + ) + FetchContent_MakeAvailable(Clipper2) + endif() + if(NOT TARGET Clipper2::Clipper2) + add_library(Clipper2::Clipper2 ALIAS Clipper2) + endif() +endif() + +if(TRACY_ENABLE) + logmissingdep("tracy" , "TRACY_ENABLE") + FetchContent_Declare( + tracy + GIT_REPOSITORY https://github.com/wolfpld/tracy.git + GIT_TAG v0.10 + GIT_SHALLOW TRUE + GIT_PROGRESS TRUE + EXCLUDE_FROM_ALL + ) + FetchContent_MakeAvailable(tracy) +endif() + +# If we're supporting mesh I/O, we need assimp +if(MANIFOLD_EXPORT) + find_package(assimp REQUIRED) +endif() + +if(MANIFOLD_PYBIND) + if(Python_VERSION VERSION_LESS 3.12) + find_package(Python COMPONENTS Interpreter Development.Module REQUIRED) + else() + find_package(Python COMPONENTS Interpreter Development.SABIModule REQUIRED) + endif() + if(Python_VERSION VERSION_GREATER_EQUAL 3.11) + set(MANIFOLD_PYBIND_STUBGEN ON) + else() + # stubgen does not support version less than 3.11 + set(MANIFOLD_PYBIND_STUBGEN OFF) + message("Python version too old, stub will not be generated") + endif() + + if(NOT MANIFOLD_USE_BUILTIN_NANOBIND) + execute_process( + COMMAND "${Python_EXECUTABLE}" -m nanobind --version + OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE NB_VERSION + ) + endif() + # we are fine with 2.0.0 + if(NB_VERSION VERSION_GREATER_EQUAL 2.0.0) + message("Found nanobind, version ${NB_VERSION}") + execute_process( + COMMAND "${Python_EXECUTABLE}" -m nanobind --cmake_dir + OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE nanobind_ROOT + ) + find_package(nanobind CONFIG REQUIRED) + else() + logmissingdep("nanobind" , "MANIFOLD_PYBIND") + set(MANIFOLD_USE_BUILTIN_NANOBIND ON) + FetchContent_Declare( + nanobind + GIT_REPOSITORY https://github.com/wjakob/nanobind.git + GIT_TAG + 784efa2a0358a4dc5432c74f5685ee026e20f2b6 # v2.2.0 + GIT_PROGRESS TRUE + EXCLUDE_FROM_ALL + ) + FetchContent_MakeAvailable(nanobind) + set(NB_VERSION 2.2.0) + endif() + + if(NB_VERSION VERSION_LESS 2.1.0) + message("Nanobind version too old, stub will not be generated") + set(MANIFOLD_PYBIND_STUBGEN OFF) + endif() +endif() + +if(MANIFOLD_TEST) + find_package(GTest QUIET) + if(NOT GTest_FOUND) + logmissingdep("GTest" , "MANIFOLD_TEST") + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + # Prevent installation of GTest with your project + set(INSTALL_GTEST OFF CACHE BOOL "" FORCE) + set(INSTALL_GMOCK OFF CACHE BOOL "" FORCE) + include(FetchContent) + FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG v1.14.0 + GIT_SHALLOW TRUE + GIT_PROGRESS TRUE + FIND_PACKAGE_ARGS NAMES GTest gtest + EXCLUDE_FROM_ALL + ) + FetchContent_MakeAvailable(googletest) + endif() + if(NOT TARGET GTest::gtest_main) + add_library(GTest::gtest_main ALIAS gtest_main) + endif() +endif() + +if(MANIFOLD_FUZZ) + logmissingdep("fuzztest" , "MANIFOLD_FUZZ") + FetchContent_Declare( + fuzztest + GIT_REPOSITORY https://github.com/google/fuzztest.git + GIT_TAG 2606e04a43e5a7730e437a849604a61f1cb0ff28 + GIT_PROGRESS TRUE + ) + FetchContent_MakeAvailable(fuzztest) +endif() + +set(BUILD_SHARED_LIBS ${OLD_BUILD_SHARED_LIBS}) diff --git a/cmake/version.h.in b/cmake/version.h.in new file mode 100644 index 000000000..f708f90c9 --- /dev/null +++ b/cmake/version.h.in @@ -0,0 +1,19 @@ +// Copyright 2024 The Manifold Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#define MANIFOLD_VERSION_MAJOR @MANIFOLD_VERSION_MAJOR@ +#define MANIFOLD_VERSION_MINOR @MANIFOLD_VERSION_MINOR@ +#define MANIFOLD_VERSION_PATCH @MANIFOLD_VERSION_PATCH@ diff --git a/extras/CMakeLists.txt b/extras/CMakeLists.txt index 427d61d1c..ec69f2f2b 100644 --- a/extras/CMakeLists.txt +++ b/extras/CMakeLists.txt @@ -19,30 +19,33 @@ endif() add_executable(perfTest perf_test.cpp) target_link_libraries(perfTest manifold) target_compile_options(perfTest PRIVATE ${MANIFOLD_FLAGS}) -target_compile_features(perfTest PUBLIC cxx_std_17) +exportbin(perfTest) if(MANIFOLD_PAR AND NOT MSVC) add_executable(stlTest stl_test.cpp) - target_link_libraries(stlTest manifold) + target_link_libraries(stlTest PRIVATE manifold TBB::tbb) target_compile_options(stlTest PRIVATE ${MANIFOLD_FLAGS}) - target_compile_features(stlTest PUBLIC cxx_std_17) endif() add_executable(largeSceneTest large_scene_test.cpp) target_link_libraries(largeSceneTest manifold) target_compile_options(largeSceneTest PRIVATE ${MANIFOLD_FLAGS}) -target_compile_features(largeSceneTest PUBLIC cxx_std_17) +exportbin(largeSceneTest) if(MANIFOLD_DEBUG) add_executable(minimizeTestcase minimize_testcase.cpp) - target_link_libraries(minimizeTestcase manifold) + target_link_libraries( + minimizeTestcase + manifold + $<$:TBB::tbb> + ) target_compile_options(minimizeTestcase PRIVATE ${MANIFOLD_FLAGS}) - target_compile_features(minimizeTestcase PUBLIC cxx_std_17) + exportbin(minimizeTestcase) endif() if(MANIFOLD_EXPORT) add_executable(convertFile convert_file.cpp) target_link_libraries(convertFile manifold manifold) target_compile_options(convertFile PRIVATE ${MANIFOLD_FLAGS}) - target_compile_features(convertFile PUBLIC cxx_std_17) + exportbin(convertFile) endif() diff --git a/extras/stl_test.cpp b/extras/stl_test.cpp index 4d2c7f502..3f5873d23 100644 --- a/extras/stl_test.cpp +++ b/extras/stl_test.cpp @@ -10,7 +10,7 @@ #include #include -#include "manifold/parallel.h" +#include "../src/parallel.h" static constexpr size_t g_Iterations = 5; static constexpr size_t g_IterationsDiscard = 1; diff --git a/flake.lock b/flake.lock index f6676b347..da17620ff 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "clipper2-src": { "flake": false, "locked": { - "lastModified": 1715688111, - "narHash": "sha256-iy2QV8IVEEIPijWIpzIQtqIQeTU4bfiH41pC0X6m72U=", + "lastModified": 1728932753, + "narHash": "sha256-m/uKGB3BHFRk0wrd71+/oURqxIR1/qQngm77No41la0=", "owner": "AngusJohnson", "repo": "Clipper2", - "rev": "ff378668baae3570e9d8070aa9eb339bdd5a6aba", + "rev": "ed98928c66707988d4eb2c49a31c41380a08931c", "type": "github" }, "original": { @@ -21,11 +21,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1701680307, - "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", + "lastModified": 1726560853, + "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", + "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", "type": "github" }, "original": { @@ -34,6 +34,23 @@ "type": "github" } }, + "gersemi-src": { + "flake": false, + "locked": { + "lastModified": 1729957417, + "narHash": "sha256-t9W27lwNKRFAraynAGEawFb1qCW9/b3RCm/jeb9zJXg=", + "owner": "BlankSpruce", + "repo": "gersemi", + "rev": "27f279333ec3308f9910d53fe4dd69d622e4bc55", + "type": "github" + }, + "original": { + "owner": "BlankSpruce", + "ref": "0.17.0", + "repo": "gersemi", + "type": "github" + } + }, "gtest-src": { "flake": false, "locked": { @@ -53,11 +70,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1726937504, - "narHash": "sha256-bvGoiQBvponpZh8ClUcmJ6QnsNKw0EMrCQJARK3bI1c=", + "lastModified": 1731139594, + "narHash": "sha256-IigrKK3vYRpUu+HEjPL/phrfh7Ox881er1UEsZvw9Q4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9357f4f23713673f310988025d9dc261c20e70c6", + "rev": "76612b17c0ce71689921ca12d9ffdc9c23ce40b2", "type": "github" }, "original": { @@ -66,12 +83,31 @@ "type": "indirect" } }, + "onetbb-src": { + "flake": false, + "locked": { + "lastModified": 1730395391, + "narHash": "sha256-XOlC1+rf65oEGKDba9N561NuFo1YJhn3Q1CTGtvkn7A=", + "owner": "oneapi-src", + "repo": "oneTBB", + "rev": "0c0ff192a2304e114bc9e6557582dfba101360ff", + "type": "github" + }, + "original": { + "owner": "oneapi-src", + "ref": "v2022.0.0", + "repo": "oneTBB", + "type": "github" + } + }, "root": { "inputs": { "clipper2-src": "clipper2-src", "flake-utils": "flake-utils", + "gersemi-src": "gersemi-src", "gtest-src": "gtest-src", - "nixpkgs": "nixpkgs" + "nixpkgs": "nixpkgs", + "onetbb-src": "onetbb-src" } }, "systems": { diff --git a/flake.nix b/flake.nix index 2a1a8a5e9..1671ce390 100644 --- a/flake.nix +++ b/flake.nix @@ -9,141 +9,197 @@ url = "github:AngusJohnson/Clipper2"; flake = false; }; - outputs = { self, nixpkgs, flake-utils, gtest-src, clipper2-src }: + inputs.onetbb-src = { + url = "github:oneapi-src/oneTBB/v2022.0.0"; + flake = false; + }; + inputs.gersemi-src = { + url = "github:BlankSpruce/gersemi/0.17.0"; + flake = false; + }; + outputs = + { self + , nixpkgs + , flake-utils + , gtest-src + , clipper2-src + , onetbb-src + , gersemi-src + }: flake-utils.lib.eachDefaultSystem (system: - let - pkgs = import nixpkgs { - inherit system; - config.allowUnfree = true; - }; - clipper2 = pkgs.clipper2.overrideAttrs (_: _: { - version = "14052024"; - src = clipper2-src; - }); - manifold = - { parallel-backend ? "none" - , doCheck ? true - , build-tools ? [ ] - , ... - }: pkgs.stdenv.mkDerivation { - inherit doCheck; - pname = "manifold-${parallel-backend}"; - version = "2.5.1"; - src = self; - nativeBuildInputs = (with pkgs; [ - cmake - ninja - (python3.withPackages - (ps: with ps; [ nanobind trimesh pytest ])) - gtest - pkg-config - ]) ++ build-tools; - buildInputs = with pkgs; [ - clipper2 - assimp - ]; - cmakeFlags = [ - "-DMANIFOLD_CBIND=ON" - "-DMANIFOLD_EXPORT=ON" - "-DBUILD_SHARED_LIBS=ON" - "-DMANIFOLD_PAR=${pkgs.lib.strings.toUpper parallel-backend}" - ]; - checkPhase = '' - cd test - ./manifold_test - cd ../ - ''; - }; - parallelBackends = [ - { parallel-backend = "none"; } - { - parallel-backend = "tbb"; - build-tools = with pkgs; [ tbb pkg-config ]; - } + let + manifold-version = "2.5.1"; + pkgs = import nixpkgs { + inherit system; + overlays = [ + (final: prev: { + clipper2 = prev.clipper2.overrideAttrs (_: { + version = clipper2-src.rev; + src = clipper2-src; + }); + # https://github.com/NixOS/nixpkgs/pull/343743#issuecomment-2424163602 + binaryen = + let + testsuite = final.fetchFromGitHub { + owner = "WebAssembly"; + repo = "testsuite"; + rev = "e05365077e13a1d86ffe77acfb1a835b7aa78422"; + hash = "sha256-yvZ5AZTPUA6nsD3xpFC0VLthiu2CxVto66RTXBXXeJM="; + }; + in + prev.binaryen.overrideAttrs (_: rec { + version = "119"; + src = pkgs.fetchFromGitHub { + owner = "WebAssembly"; + repo = "binaryen"; + rev = "version_${version}"; + hash = "sha256-JYXtN3CW4qm/nnjGRvv3GxQ0x9O9wHtNYQLqHIYTTOA="; + }; + preConfigure = '' + if [ $doCheck -eq 1 ]; then + sed -i '/googletest/d' third_party/CMakeLists.txt + rmdir test/spec/testsuite + ln -s ${testsuite} test/spec/testsuite + else + cmakeFlagsArray=($cmakeFlagsArray -DBUILD_TESTS=0) + fi + ''; + }); + }) ]; - in - { - packages = (builtins.listToAttrs - (map - (x: { - name = "manifold-" + x.parallel-backend; - value = manifold x; - }) - parallelBackends)) // { - manifold-js = pkgs.buildEmscriptenPackage { - name = "manifold-js"; - version = "2.5.1"; - src = self; - nativeBuildInputs = (with pkgs; [ cmake python39 ]); - buildInputs = [ pkgs.nodejs ]; - configurePhase = '' - cp -r ${clipper2-src} clipper2 - chmod -R +w clipper2 - mkdir -p .emscriptencache - export EM_CACHE=$(pwd)/.emscriptencache - mkdir build - cd build - emcmake cmake -DCMAKE_BUILD_TYPE=Release \ - -DFETCHCONTENT_SOURCE_DIR_GOOGLETEST=${gtest-src} \ - -DFETCHCONTENT_SOURCE_DIR_CLIPPER2=../clipper2 .. - ''; - buildPhase = '' - emmake make -j''${NIX_BUILD_CORES} - ''; - checkPhase = '' - cd test - node manifold_test.js - cd ../ - ''; - installPhase = '' - mkdir -p $out - cp {extras,wasm}/*.js $out/ - cp {extras,wasm}/*.wasm $out/ - ''; - }; - # but how should we make it work with other python versions? - manifold3d = with pkgs.python3Packages; buildPythonPackage { - pname = "manifold3d"; - version = "2.5.1"; - src = self; - propagatedBuildInputs = [ - numpy - ]; - buildInputs = with pkgs; [ - tbb - clipper2 - ]; - nativeBuildInputs = with pkgs; [ - cmake - ninja - setuptools - scikit-build-core - pyproject-metadata - pathspec - pkg-config - ]; - checkInputs = [ - nanobind - trimesh - pytest - ]; - format = "pyproject"; - dontUseCmakeConfigure = true; - doCheck = true; - checkPhase = '' - python3 bindings/python/examples/run_all.py - python3 -m pytest - ''; - }; - }; - devShell = pkgs.mkShell { - buildInputs = with pkgs; [ + }; + onetbb = pkgs.tbb_2021_11.overrideAttrs (_: { + version = onetbb-src.rev; + src = onetbb-src; + }); + gersemi = with pkgs.python3Packages; buildPythonPackage { + pname = "gersemi"; + version = "0.17.0"; + src = gersemi-src; + propagatedBuildInputs = [ + appdirs + lark + pyyaml + ]; + doCheck = true; + }; + manifold = + { parallel ? true }: pkgs.stdenv.mkDerivation { + pname = "manifold-${if parallel then "tbb" else "none"}"; + version = manifold-version; + src = self; + nativeBuildInputs = (with pkgs; [ cmake - tbb + ninja + (python3.withPackages + (ps: with ps; [ nanobind trimesh pytest ])) gtest + ]) ++ (if parallel then [ onetbb ] else [ ]); + buildInputs = with pkgs; [ + clipper2 + assimp ]; + cmakeFlags = [ + "-DMANIFOLD_CBIND=ON" + "-DMANIFOLD_EXPORT=ON" + "-DBUILD_SHARED_LIBS=ON" + "-DMANIFOLD_PAR=${if parallel then "ON" else "OFF"}" + ]; + checkPhase = '' + cd test + ./manifold_test + cd ../ + ''; }; - } + manifold-emscripten = { doCheck ? true }: pkgs.buildEmscriptenPackage { + name = "manifold-js"; + version = manifold-version; + src = self; + nativeBuildInputs = (with pkgs; [ cmake python39 ]); + buildInputs = [ pkgs.nodejs ]; + configurePhase = '' + cp -r ${clipper2-src} clipper2 + chmod -R +w clipper2 + mkdir -p .emscriptencache + export EM_CACHE=$(pwd)/.emscriptencache + mkdir build + cd build + emcmake cmake -DCMAKE_BUILD_TYPE=Release \ + -DFETCHCONTENT_SOURCE_DIR_GOOGLETEST=${gtest-src} \ + -DFETCHCONTENT_SOURCE_DIR_CLIPPER2=../clipper2 .. + ''; + buildPhase = '' + emmake make -j''${NIX_BUILD_CORES} + ''; + checkPhase = if doCheck then '' + cd test + node manifold_test.js + cd ../ + '' else ""; + installPhase = '' + mkdir -p $out + cp bindings/wasm/manifold.* $out/ + ''; + }; + in + { + packages = { + manifold-tbb = manifold { }; + manifold-none = manifold { parallel = false; }; + manifold-js = manifold-emscripten { }; + # but how should we make it work with other python versions? + manifold3d = with pkgs.python3Packages; buildPythonPackage { + pname = "manifold3d"; + version = manifold-version; + src = self; + propagatedBuildInputs = [ numpy ]; + buildInputs = [ onetbb pkgs.clipper2 ]; + nativeBuildInputs = with pkgs; [ + cmake + ninja + setuptools + scikit-build-core + pyproject-metadata + pathspec + ]; + checkInputs = [ nanobind trimesh pytest ]; + format = "pyproject"; + dontUseCmakeConfigure = true; + doCheck = true; + checkPhase = '' + python3 bindings/python/examples/run_all.py + python3 -m pytest + ''; + }; + }; + devShell = pkgs.mkShell { + buildInputs = with pkgs; [ + (python3.withPackages (ps: with ps; [ + # test dependencies + trimesh + numpy + pytest + + # formatting tools + gersemi + black + ])) + + ninja + cmake + onetbb + gtest + assimp + clipper2 + pkg-config + + # useful tools + clang-tools_18 + clang_18 + tracy + ]; + }; + } ); } diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index c66db5a8f..7e2dd51be 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -34,4 +34,3 @@ target_include_directories(samples PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) target_link_libraries(samples PUBLIC manifold) target_compile_options(samples PRIVATE ${MANIFOLD_FLAGS}) -target_compile_features(samples PUBLIC cxx_std_17) diff --git a/scripts/format.sh b/scripts/format.sh index 723d3f2f5..2d8538727 100755 --- a/scripts/format.sh +++ b/scripts/format.sh @@ -19,16 +19,11 @@ $CLANG_FORMAT -i include/manifold/*.h black bindings/python/examples/*.py -for f in $(find -name CMakeLists.txt); do - # skip build directories - if [[ $f != *build* ]]; then - gersemi -i $f - fi -done - -for f in $(find -name '*.cmake.in'); do - # skip build directories - if [[ $f != *build* ]]; then - gersemi -i $f - fi +for pattern in 'CMakeLists.txt' '*.cmake*'; do + for f in $(find -name ${pattern}); do + # skip build directories + if [[ $f != *build* && $f != *node_modules* ]]; then + gersemi -i $f + fi + done done diff --git a/scripts/test-cmake-subdir.sh b/scripts/test-cmake-subdir.sh new file mode 100755 index 000000000..b719a9bce --- /dev/null +++ b/scripts/test-cmake-subdir.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +mkdir cmake-consumer +cd cmake-consumer + +cat < CMakeLists.txt +cmake_minimum_required(VERSION 3.18) +project(testing LANGUAGES CXX) +set(MANIFOLD_PAR ON) +add_subdirectory(manifold EXCLUDE_FROM_ALL) +add_executable(testing test.cpp) +target_link_libraries(testing PRIVATE manifold::manifold) +EOT + +cat < test.cpp +#include +#include +int main() { manifold::Manifold foo; return 0; } +EOT + +cp -r ../manifold ./ +mkdir build +cd build +cmake .. +make +./testing + diff --git a/scripts/test-cmake.sh b/scripts/test-cmake.sh index 905ae1a3c..456632cb2 100755 --- a/scripts/test-cmake.sh +++ b/scripts/test-cmake.sh @@ -12,7 +12,7 @@ EOT cat < test.cpp #include -#include +#include int main() { manifold::Manifold foo; return 0; } EOT diff --git a/scripts/test-pkgconfig.sh b/scripts/test-pkgconfig.sh index e447e0dac..e3f7ccd29 100755 --- a/scripts/test-pkgconfig.sh +++ b/scripts/test-pkgconfig.sh @@ -3,15 +3,15 @@ mkdir make-consumer cd make-consumer cat <<'EOT' > Makefile -CXXFLAGS=$(shell pkg-config --cflags manifold) -LDFLAGS=$(shell pkg-config --libs manifold) +override CXXFLAGS += $(shell pkg-config --cflags manifold) +override LDFLAGS += $(shell pkg-config --libs manifold) testing : testing.cpp EOT cat < testing.cpp #include -#include +#include int main() { manifold::Manifold foo; return 0; } EOT diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fbc187804..72b174441 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# For private headers -include_directories("${CMAKE_CURRENT_SOURCE_DIR}") - set( MANIFOLD_SRCS boolean3.cpp @@ -32,6 +29,9 @@ set( smoothing.cpp sort.cpp subdivision.cpp + # optional source files + $<$:cross_section/cross_section.cpp> + $<$:meshIO/meshIO.cpp> ) set( @@ -42,6 +42,7 @@ set( hashtable.h impl.h mesh_fixes.h + parallel.h quickhull.h shared.h sparse.h @@ -51,62 +52,33 @@ set( vec.h ) -if(MANIFOLD_CROSS_SECTION) - list(APPEND MANIFOLD_SRCS cross_section/cross_section.cpp) -endif() - -if(MANIFOLD_EXPORT) - list(APPEND MANIFOLD_SRCS meshIO/meshIO.cpp) -endif() - -# Dependency libraries -if(MANIFOLD_CROSS_SECTION) - if(TARGET Clipper2::Clipper2) - list(APPEND MANIFOLD_LIBS Clipper2::Clipper2) - else() - list(APPEND MANIFOLD_LIBS Clipper2) - endif() -endif() -if(MANIFOLD_PAR) - if(TARGET TBB::tbb) - list(APPEND MANIFOLD_LIBS TBB::tbb) - else() - list(APPEND MANIFOLD_LIBS ${TBB_LINK_LIBRARIES}) - endif() -endif() -if(MANIFOLD_EXPORT) - list(APPEND MANIFOLD_LIBS assimp::assimp) -endif() - # Include directories -set(MANIFOLD_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/include) -if(TBB_INCLUDE_DIRS) - list(APPEND MANIFOLD_INCLUDE_DIRS ${TBB_INCLUDE_DIRS}) -endif() +set(MANIFOLD_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/include) add_library(manifold ${MANIFOLD_SRCS} ${MANIFOLD_PRIVATE_HDRS}) -add_library(manifold::manifold ALIAS manifold) -set_property(TARGET manifold PROPERTY VERSION "${MANIFOLD_VERSION}") -set_property(TARGET manifold PROPERTY SOVERSION ${MANIFOLD_VERSION_MAJOR}) -if(MSVC) - set_target_properties( - ${PROJECT_NAME} - PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON - ) -endif() -target_link_libraries(manifold PUBLIC ${MANIFOLD_LIBS}) -if(MANIFOLD_FLAGS) - target_compile_options(manifold PRIVATE ${MANIFOLD_FLAGS}) -endif() -target_include_directories( + +target_link_libraries(manifold PUBLIC $<$:TracyClient>) + +target_link_libraries( manifold - PUBLIC - $ - $ - PRIVATE ${MANIFOLD_INCLUDE_DIRS} + PRIVATE + # optional dependencies + $<$:TBB::tbb> + $<$:Clipper2::Clipper2> + $<$:assimp::assimp> ) -set(OPTIONS MANIFOLD_DEBUG MANIFOLD_CROSS_SECTION MANIFOLD_EXPORT) +target_compile_options(manifold PRIVATE ${MANIFOLD_FLAGS}) +# make sure users use appropriate c++ standard when including our headers +target_compile_features(manifold PUBLIC cxx_std_17) +set( + OPTIONS + MANIFOLD_DEBUG + MANIFOLD_CROSS_SECTION + MANIFOLD_EXPORT + TRACY_ENABLE + TRACY_MEMORY_USAGE +) foreach(OPT IN LISTS OPTIONS) if(${${OPT}}) target_compile_options(manifold PUBLIC -D${OPT}) @@ -118,27 +90,15 @@ else() target_compile_options(manifold PUBLIC -DMANIFOLD_PAR=-1) endif() -target_compile_features(manifold PUBLIC cxx_std_17) +target_include_directories( + manifold + PUBLIC + $ + $ + $ + PRIVATE ${MANIFOLD_INCLUDE_DIRS} +) -install(TARGETS manifold EXPORT manifoldTargets) +exportlib(manifold) -# Tracy Support -if(TRACY_ENABLE) - if(NOT MANIFOLD_DOWNLOADS) - message( - WARNING - "Downloading is disabled, but tracy requires download - skipping.\n" - ) - return() - endif() - include(FetchContent) - FetchContent_Declare( - tracy - GIT_REPOSITORY https://github.com/wolfpld/tracy.git - GIT_TAG v0.10 - GIT_SHALLOW TRUE - GIT_PROGRESS TRUE - ) - FetchContent_MakeAvailable(tracy) - target_link_libraries(manifold PUBLIC TracyClient) -endif() +install(TARGETS manifold EXPORT manifoldTargets) diff --git a/src/boolean3.cpp b/src/boolean3.cpp index ab383f6ce..1fca99db4 100644 --- a/src/boolean3.cpp +++ b/src/boolean3.cpp @@ -16,7 +16,7 @@ #include -#include "manifold/parallel.h" +#include "./parallel.h" using namespace manifold; diff --git a/src/boolean_result.cpp b/src/boolean_result.cpp index f53b7460d..44faf73e9 100644 --- a/src/boolean_result.cpp +++ b/src/boolean_result.cpp @@ -17,8 +17,8 @@ #include #include "./boolean3.h" +#include "./parallel.h" #include "./utils.h" -#include "manifold/parallel.h" #if (MANIFOLD_PAR == 1) && __has_include() #define TBB_PREVIEW_CONCURRENT_ORDERED_CONTAINERS 1 diff --git a/src/collider.h b/src/collider.h index 6c303fb5c..80de94b7c 100644 --- a/src/collider.h +++ b/src/collider.h @@ -13,11 +13,11 @@ // limitations under the License. #pragma once +#include "./parallel.h" #include "./sparse.h" #include "./utils.h" #include "./vec.h" #include "manifold/common.h" -#include "manifold/parallel.h" #ifdef _MSC_VER #include diff --git a/src/constructors.cpp b/src/constructors.cpp index 92e0af974..17df744ee 100644 --- a/src/constructors.cpp +++ b/src/constructors.cpp @@ -14,7 +14,7 @@ #include "./csg_tree.h" #include "./impl.h" -#include "manifold/parallel.h" +#include "./parallel.h" #include "manifold/polygon.h" namespace manifold { diff --git a/src/csg_tree.cpp b/src/csg_tree.cpp index f04a9e95b..8f98fe298 100644 --- a/src/csg_tree.cpp +++ b/src/csg_tree.cpp @@ -25,7 +25,7 @@ #include "./csg_tree.h" #include "./impl.h" #include "./mesh_fixes.h" -#include "manifold/parallel.h" +#include "./parallel.h" constexpr int kParallelThreshold = 4096; diff --git a/src/edge_op.cpp b/src/edge_op.cpp index 20f2fd0f5..d22577a2a 100644 --- a/src/edge_op.cpp +++ b/src/edge_op.cpp @@ -13,7 +13,7 @@ // limitations under the License. #include "./impl.h" -#include "manifold/parallel.h" +#include "./parallel.h" namespace { using namespace manifold; diff --git a/src/face_op.cpp b/src/face_op.cpp index 15cab42a8..b1a6b16c7 100644 --- a/src/face_op.cpp +++ b/src/face_op.cpp @@ -20,7 +20,7 @@ #include #include "./impl.h" -#include "manifold/parallel.h" +#include "./parallel.h" #include "manifold/polygon.h" namespace manifold { diff --git a/src/impl.cpp b/src/impl.cpp index 1718bcb1e..9582b2c12 100644 --- a/src/impl.cpp +++ b/src/impl.cpp @@ -20,8 +20,8 @@ #include "./hashtable.h" #include "./mesh_fixes.h" +#include "./parallel.h" #include "./svd.h" -#include "manifold/parallel.h" namespace { using namespace manifold; diff --git a/src/manifold.cpp b/src/manifold.cpp index 92ac4d957..a36dd460b 100644 --- a/src/manifold.cpp +++ b/src/manifold.cpp @@ -19,7 +19,7 @@ #include "./boolean3.h" #include "./csg_tree.h" #include "./impl.h" -#include "manifold/parallel.h" +#include "./parallel.h" namespace { using namespace manifold; diff --git a/include/manifold/parallel.h b/src/parallel.h similarity index 100% rename from include/manifold/parallel.h rename to src/parallel.h diff --git a/src/polygon.cpp b/src/polygon.cpp index 639d3ed3c..60f510a98 100644 --- a/src/polygon.cpp +++ b/src/polygon.cpp @@ -19,9 +19,9 @@ #include #include "./collider.h" +#include "./parallel.h" #include "./utils.h" #include "manifold/optional_assert.h" -#include "manifold/parallel.h" namespace { using namespace manifold; diff --git a/src/properties.cpp b/src/properties.cpp index 9f6d8bfeb..32f79e5b6 100644 --- a/src/properties.cpp +++ b/src/properties.cpp @@ -15,8 +15,8 @@ #include #include "./impl.h" +#include "./parallel.h" #include "./tri_dist.h" -#include "manifold/parallel.h" namespace { using namespace manifold; diff --git a/src/sdf.cpp b/src/sdf.cpp index 51d880580..64dd7094d 100644 --- a/src/sdf.cpp +++ b/src/sdf.cpp @@ -14,10 +14,10 @@ #include "./hashtable.h" #include "./impl.h" +#include "./parallel.h" #include "./utils.h" #include "./vec.h" #include "manifold/manifold.h" -#include "manifold/parallel.h" namespace { using namespace manifold; diff --git a/src/shared.h b/src/shared.h index b1e807370..3f3336141 100644 --- a/src/shared.h +++ b/src/shared.h @@ -14,10 +14,10 @@ #pragma once +#include "./parallel.h" #include "./sparse.h" #include "./utils.h" #include "./vec.h" -#include "manifold/parallel.h" namespace manifold { diff --git a/src/smoothing.cpp b/src/smoothing.cpp index 5c1d7e811..57d81b462 100644 --- a/src/smoothing.cpp +++ b/src/smoothing.cpp @@ -13,7 +13,7 @@ // limitations under the License. #include "./impl.h" -#include "manifold/parallel.h" +#include "./parallel.h" namespace { using namespace manifold; diff --git a/src/sort.cpp b/src/sort.cpp index a1c78e083..f394aa526 100644 --- a/src/sort.cpp +++ b/src/sort.cpp @@ -16,7 +16,7 @@ #include #include "./impl.h" -#include "manifold/parallel.h" +#include "./parallel.h" namespace { using namespace manifold; diff --git a/src/sparse.h b/src/sparse.h index 9eedb16a3..a25ea6114 100644 --- a/src/sparse.h +++ b/src/sparse.h @@ -13,11 +13,11 @@ // limitations under the License. #pragma once +#include "./parallel.h" #include "./utils.h" #include "./vec.h" #include "manifold/common.h" #include "manifold/optional_assert.h" -#include "manifold/parallel.h" namespace { template diff --git a/src/subdivision.cpp b/src/subdivision.cpp index 83b66d442..c8631d79c 100644 --- a/src/subdivision.cpp +++ b/src/subdivision.cpp @@ -13,7 +13,7 @@ // limitations under the License. #include "./impl.h" -#include "manifold/parallel.h" +#include "./parallel.h" template <> struct std::hash { diff --git a/src/utils.h b/src/utils.h index bd8b4a721..12d6a5847 100644 --- a/src/utils.h +++ b/src/utils.h @@ -33,7 +33,7 @@ #endif #endif -#include "manifold/parallel.h" +#include "./parallel.h" #if __has_include() #include diff --git a/src/vec.h b/src/vec.h index 48c6d4e10..b59b4b6ad 100644 --- a/src/vec.h +++ b/src/vec.h @@ -21,7 +21,7 @@ #endif #include -#include "manifold/parallel.h" +#include "./parallel.h" #include "manifold/vec_view.h" namespace manifold { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e7faabded..53d571265 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -18,33 +18,6 @@ endif() enable_testing() -find_package(GTest QUIET) -if(NOT GTest_FOUND) - if(NOT MANIFOLD_DOWNLOADS) - message( - WARNING - "Downloading is disabled, but testing requires googletest - skipping.\n" - ) - return() - endif() - - set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) - # Prevent installation of GTest with your project - set(INSTALL_GTEST OFF CACHE BOOL "" FORCE) - set(INSTALL_GMOCK OFF CACHE BOOL "" FORCE) - - include(FetchContent) - FetchContent_Declare( - googletest - GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG v1.14.0 - GIT_SHALLOW TRUE - GIT_PROGRESS TRUE - FIND_PACKAGE_ARGS NAMES GTest gtest - ) - FetchContent_MakeAvailable(googletest) -endif() - # put fast/simple tests files first to run earlier set( SOURCE_FILES @@ -58,73 +31,42 @@ set( hull_test.cpp samples_test.cpp boolean_complex_test.cpp + $<$:cross_section_test.cpp> + $<$:manifoldc_test.cpp> ) -if(MANIFOLD_CROSS_SECTION) - list(APPEND SOURCE_FILES cross_section_test.cpp) -endif() +add_executable(manifold_test ${SOURCE_FILES}) +target_link_libraries( + manifold_test + PRIVATE + GTest::gtest_main + manifold + samples + $<$:manifoldc> + $<$:TBB::tbb> +) -if(MANIFOLD_CBIND AND NOT EMSCRIPTEN) - list(APPEND SOURCE_FILES manifoldc_test.cpp) +if(EMSCRIPTEN) + target_link_options( + manifold_test + PRIVATE + -sASSERTIONS=1 + -sDEMANGLE_SUPPORT=1 + --bind + --preload-file + ${CMAKE_CURRENT_SOURCE_DIR}/polygons@/polygons + ) endif() -if(NOT TARGET GTest::gtest_main) - add_library(GTest::gtest_main ALIAS gtest_main) -endif() +target_compile_options(manifold_test PRIVATE ${MANIFOLD_FLAGS}) +exportbin(manifold_test) -add_executable(manifold_test ${SOURCE_FILES}) -target_link_libraries(manifold_test GTest::gtest_main manifold samples) +add_test(test_all manifold_test) if(MANIFOLD_FUZZ) - FetchContent_Declare( - fuzztest - GIT_REPOSITORY https://github.com/google/fuzztest.git - # note that if commit hash is used, it cannot be a shallow clone - GIT_TAG 2606e04a43e5a7730e437a849604a61f1cb0ff28 - GIT_PROGRESS TRUE - ) - FetchContent_MakeAvailable(fuzztest) fuzztest_setup_fuzzing_flags() add_executable(polygon_fuzz polygon_fuzz.cpp) target_link_libraries(polygon_fuzz PUBLIC manifold) link_fuzztest(polygon_fuzz) gtest_discover_tests(polygon_fuzz) endif() - -if(MANIFOLD_CBIND AND NOT EMSCRIPTEN) - target_link_libraries(manifold_test manifoldc) -endif() - -target_compile_options(manifold_test PRIVATE ${MANIFOLD_FLAGS}) -target_compile_features(manifold_test PUBLIC cxx_std_17) - -add_test(test_all manifold_test) -target_precompile_headers(manifold_test INTERFACE test.h) - -if(EMSCRIPTEN) - list( - APPEND - EMSCRIPTEN_LINK_FLAGS - -sASSERTIONS=1 - -sDEMANGLE_SUPPORT=1 - --bind - --preload-file - ${CMAKE_CURRENT_SOURCE_DIR}/polygons@/polygons - ) - list(JOIN EMSCRIPTEN_LINK_FLAGS " " EMSCRIPTEN_LINK_FLAGS) - set_target_properties( - manifold_test - PROPERTIES LINK_FLAGS ${EMSCRIPTEN_LINK_FLAGS} - ) -endif() - -if(MSVC) - set_target_properties( - manifold_test - PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin - ) - set_target_properties( - manifold_test - PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin - ) -endif()