@@ -3,52 +3,61 @@ cmake_minimum_required(VERSION 3.15...3.26)
33project (compas_libigl LANGUAGES CXX)
44
55set (CMAKE_CXX_STANDARD 20)
6- set (CMAKE_CXX_STANDARD_REQUIRED ON )
7- set (CMAKE_CXX_EXTENSIONS OFF )
8- set (CMAKE_BUILD_TYPE Release)
9-
10- # =====================================================================
11- # Set this flag to ON for developing to reduce build time.
12- # Set this flag to OFF for publishing for file size reduction.
13- # =====================================================================
14- option (ENABLE_PRECOMPILED_HEADERS "Enable precompiled headers for the build" ON )
156
16- # =====================================================================
17- # Set maximum heap size for MSVC
18- # =====================================================================
7+ option (ENABLE_PRECOMPILED_HEADERS "Enable precompiled headers" OFF )
8+ option (MULTITHREADED_COMPILATION "Enable multi-threaded compilation (Ninja only)" ON )
199
20- if (MSVC )
21- set (CMAKE_GENERATOR_PLATFORM x64)
22- add_compile_options (/Zm1200)
10+ # Set build options
11+ if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES )
12+ message (STATUS "Setting build type to 'Release' as none was specified." )
13+ set (CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE)
14+ # Set the possible values of build type for cmake-gui
15+ set_property (CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
16+ "Debug" "Release" "MinSizeRel" "RelWithDebInfo" )
2317endif ()
2418
25- # =====================================================================
26- # Build size reduction.
27- # =====================================================================
19+ # Specify the compiler standard flag
20+ set (CMAKE_CXX_EXTENSIONS OFF )
2821
29- if (NOT ENABLE_PRECOMPILED_HEADERS)
30- set (CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE )
31- if (MSVC )
32- set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /O1" ) # Optimize for size on MSVC
33- else ()
34- set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Os" ) # Optimize for size on GCC/Clang
22+ # Set the use of a pre-compile header
23+ if (MULTITHREADED_COMPILATION)
24+ include (ProcessorCount)
25+ ProcessorCount(N)
26+ if (NOT N EQUAL 0)
27+ message (STATUS "Using ${N} build jobs." )
28+ set (CMAKE_PARALLEL_LEVEL ${N} )
29+ if (CMAKE_GENERATOR MATCHES "^Ninja" )
30+ set (CMAKE_JOB_POOL_COMPILE compile)
31+ set (CMAKE_JOB_POOL_LINK link)
32+ set (CMAKE_JOB_POOLS
33+ "compile=${N} "
34+ "link=2" )
3535 endif ()
36+ endif ()
37+ endif ()
38+
39+ if (UNIX AND NOT APPLE )
40+ # Install to share/bin|lib
41+ if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
42+ set (CMAKE_INSTALL_PREFIX
43+ "${CMAKE_INSTALL_PREFIX} /share/${PROJECT_NAME} "
44+ CACHE PATH "Install prefix" FORCE)
45+ endif ()
3646endif ()
3747
38- # =====================================================================
39- # Dependencies
40- # =====================================================================
4148include (ExternalProject)
49+ include (CMakeDependentOption)
50+
51+ # Create directories to store external dependencies
52+ if (NOT DEFINED EXTERNAL_DIR)
53+ set (EXTERNAL_DIR "${CMAKE_SOURCE_DIR} /external" )
54+ endif ()
55+ file (MAKE_DIRECTORY ${EXTERNAL_DIR} )
4256
43- # Define source directories for external dependencies
44- set (EXTERNAL_DIR "${CMAKE_CURRENT_SOURCE_DIR} /external" )
57+ # Set source directories for external dependencies
4558set (EIGEN_SOURCE_DIR "${EXTERNAL_DIR} /eigen" )
4659set (LIBIGL_SOURCE_DIR "${EXTERNAL_DIR} /libigl" )
47-
48- # Create directories if they don't exist
49- file (MAKE_DIRECTORY ${EXTERNAL_DIR} )
50- file (MAKE_DIRECTORY ${EIGEN_SOURCE_DIR} )
51- file (MAKE_DIRECTORY ${LIBIGL_SOURCE_DIR} )
60+ set (CLIPPER2_SOURCE_DIR "${EXTERNAL_DIR} /clipper2" )
5261
5362# Download Eigen first
5463if (NOT EXISTS "${EIGEN_SOURCE_DIR} /Eigen" )
@@ -86,6 +95,65 @@ if(NOT EXISTS "${LIBIGL_SOURCE_DIR}/include/igl")
8695 )
8796endif ()
8897
98+ # ------------------------------------------------------------------------------
99+ # Clipper2 (static library)
100+ # ------------------------------------------------------------------------------
101+
102+ # Define paths for Clipper2
103+ set (CLIPPER2_LIB_DIR "${CMAKE_BINARY_DIR} /clipper2_static_lib" )
104+ file (MAKE_DIRECTORY ${CLIPPER2_LIB_DIR} )
105+ set (CLIPPER2_STATIC_LIB "${CLIPPER2_LIB_DIR} /libClipper2.a" )
106+ set (CLIPPER2_INCLUDE_DIR "${CLIPPER2_SOURCE_DIR} /CPP/Clipper2Lib/include" )
107+
108+ # Only download Clipper2 if source directory doesn't exist
109+ if (NOT EXISTS "${CLIPPER2_SOURCE_DIR} /CPP/Clipper2Lib/include/clipper2" )
110+ message (STATUS "Downloading clipper2..." )
111+ ExternalProject_Add(
112+ clipper2_download
113+ PREFIX ${EXTERNAL_DIR}
114+ URL https://github.com/AngusJohnson/Clipper2/releases/download/Clipper2_1.5.3/Clipper2_1.5.3.zip
115+ SOURCE_DIR "${CLIPPER2_SOURCE_DIR} "
116+ CONFIGURE_COMMAND ""
117+ BUILD_COMMAND ""
118+ INSTALL_COMMAND ""
119+ LOG_DOWNLOAD ON
120+ UPDATE_COMMAND ""
121+ PATCH_COMMAND ""
122+ DOWNLOAD_EXTRACT_TIMESTAMP TRUE
123+ )
124+ endif ()
125+
126+ # Only build Clipper2 if the static library doesn't exist
127+ if (NOT EXISTS "${CLIPPER2_STATIC_LIB} " )
128+ # Custom command to build the Clipper2 static library
129+ add_custom_command (
130+ OUTPUT ${CLIPPER2_STATIC_LIB}
131+ COMMAND ${CMAKE_CXX_COMPILER} -c -fPIC
132+ "${CLIPPER2_SOURCE_DIR} /CPP/Clipper2Lib/src/clipper.engine.cpp"
133+ "${CLIPPER2_SOURCE_DIR} /CPP/Clipper2Lib/src/clipper.offset.cpp"
134+ "${CLIPPER2_SOURCE_DIR} /CPP/Clipper2Lib/src/clipper.rectclip.cpp"
135+ -I"${CLIPPER2_SOURCE_DIR} /CPP/Clipper2Lib/include"
136+ COMMAND ${CMAKE_AR} cr "${CLIPPER2_STATIC_LIB} " clipper.engine.o clipper.offset.o clipper.rectclip.o
137+ COMMAND ${CMAKE_RANLIB} "${CLIPPER2_STATIC_LIB} "
138+ WORKING_DIRECTORY ${CLIPPER2_LIB_DIR}
139+ COMMENT "Building Clipper2 static library"
140+ )
141+
142+ # Custom target to trigger the Clipper2 build
143+ add_custom_target (clipper2_build ALL DEPENDS ${CLIPPER2_STATIC_LIB} )
144+
145+ # Make clipper2_build depend on the downloads
146+ if (TARGET clipper2_download)
147+ add_dependencies (clipper2_build clipper2_download)
148+ endif ()
149+ add_dependencies (clipper2_build external_downloads)
150+ else ()
151+ # If the static library already exists, create a dummy target
152+ add_custom_target (clipper2_build)
153+ endif ()
154+
155+ # No additional target needed as clipper2_build is already defined by ExternalProject_Add
156+
89157# Create a custom target for all external dependencies
90158add_custom_target (external_downloads ALL )
91159if (TARGET eigen_download)
@@ -94,10 +162,14 @@ endif()
94162if (TARGET libigl_download)
95163 add_dependencies (external_downloads libigl_download)
96164endif ()
165+ if (TARGET clipper2_download)
166+ add_dependencies (external_downloads clipper2_download)
167+ endif ()
97168
98169# Add include directories for external dependencies
99170set (EIGEN_INCLUDE_DIR "${EIGEN_SOURCE_DIR} " )
100171set (LIBIGL_INCLUDE_DIR "${LIBIGL_SOURCE_DIR} /include" )
172+ set (CLIPPER2_INCLUDE_DIR "${CLIPPER2_SOURCE_DIR} /CPP/Clipper2Lib/include" )
101173
102174if (NOT SKBUILD)
103175 message (WARNING "\
@@ -114,7 +186,6 @@ if (NOT SKBUILD)
114186 in your environment once and use the following command that avoids
115187 a costly creation of a new virtual environment at every compilation:
116188 =====================================================================
117- $ pip install nanobind scikit-build-core[pyproject]
118189 $ pip install --no-build-isolation -ve .
119190 =====================================================================
120191 You may optionally add -Ceditable.rebuild=true to auto-rebuild when
@@ -136,15 +207,16 @@ if (ENABLE_PRECOMPILED_HEADERS)
136207 target_include_directories (compas_pch INTERFACE
137208 ${EIGEN_INCLUDE_DIR}
138209 ${LIBIGL_INCLUDE_DIR}
210+ ${CLIPPER2_INCLUDE_DIR}
139211 )
140212endif ()
141213
142214# Function to add a nanobind module with include directories
143215function (add_nanobind_module module_name source_file)
144216 nanobind_add_module(${module_name} STABLE_ABI NB_STATIC ${source_file} )
145217
146- # Ensure external dependencies are downloaded first
147- add_dependencies (${module_name} external_downloads)
218+ # Ensure external dependencies are downloaded and built first
219+ add_dependencies (${module_name} external_downloads clipper2_build )
148220
149221 # Add include directories and link PCH if enabled
150222 if (ENABLE_PRECOMPILED_HEADERS)
@@ -153,10 +225,13 @@ function(add_nanobind_module module_name source_file)
153225 target_include_directories (${module_name} SYSTEM PRIVATE
154226 ${EIGEN_INCLUDE_DIR}
155227 ${LIBIGL_INCLUDE_DIR}
228+ ${CLIPPER2_INCLUDE_DIR}
156229 )
157230 endif ()
158231
159- target_link_libraries (${module_name} PRIVATE Threads::Threads)
232+ # Link Clipper2 directly using the static library path
233+ target_link_libraries (${module_name} PRIVATE Threads::Threads ${CLIPPER2_STATIC_LIB} )
234+
160235 install (TARGETS ${module_name} LIBRARY DESTINATION compas_libigl)
161236endfunction ()
162237
@@ -173,3 +248,11 @@ add_nanobind_module(_meshing src/meshing.cpp)
173248add_nanobind_module(_parametrisation src/parametrisation.cpp)
174249add_nanobind_module(_planarize src/planarize.cpp)
175250add_nanobind_module(_mapping src/mapping.cpp)
251+
252+ # Install the Clipper2 static library
253+ install (FILES "${CLIPPER2_STATIC_LIB} "
254+ DESTINATION lib)
255+
256+ # Install Clipper2 headers
257+ install (DIRECTORY "${CLIPPER2_SOURCE_DIR} /CPP/Clipper2Lib/include/clipper2"
258+ DESTINATION include )
0 commit comments