11cmake_minimum_required (VERSION 3.15...3.26)
2-
32project (compas_libigl LANGUAGES CXX)
43
54set (CMAKE_CXX_STANDARD 20)
5+ set (CMAKE_CXX_EXTENSIONS OFF )
66
77option (ENABLE_PRECOMPILED_HEADERS "Enable precompiled headers" OFF )
88option (MULTITHREADED_COMPILATION "Enable multi-threaded compilation (Ninja only)" ON )
99
10- # Set build options
1110if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES )
1211 message (STATUS "Setting build type to 'Release' as none was specified." )
1312 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" )
13+ set_property (CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo" )
1714endif ()
1815
19- # Specify the compiler standard flag
20- set (CMAKE_CXX_EXTENSIONS OFF )
21-
22- # Set the use of a pre-compile header
2316if (MULTITHREADED_COMPILATION)
2417 include (ProcessorCount)
2518 ProcessorCount(N)
@@ -29,178 +22,111 @@ if(MULTITHREADED_COMPILATION)
2922 if (CMAKE_GENERATOR MATCHES "^Ninja" )
3023 set (CMAKE_JOB_POOL_COMPILE compile)
3124 set (CMAKE_JOB_POOL_LINK link)
32- set (CMAKE_JOB_POOLS
33- "compile=${N} "
34- "link=2" )
25+ set (CMAKE_JOB_POOLS "compile=${N} " "link=2" )
3526 endif ()
3627 endif ()
3728endif ()
3829
3930if (UNIX AND NOT APPLE )
40- # Install to share/bin|lib
4131 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)
32+ set (CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX} /share/${PROJECT_NAME} " CACHE PATH "Install prefix" FORCE)
4533 endif ()
4634endif ()
4735
48- include (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} )
56-
57- # Set source directories for external dependencies
58- set (EIGEN_SOURCE_DIR "${EXTERNAL_DIR} /eigen" )
59- set (LIBIGL_SOURCE_DIR "${EXTERNAL_DIR} /libigl" )
60- set (CLIPPER2_SOURCE_DIR "${EXTERNAL_DIR} /clipper2" )
61-
62- # Download Eigen first
63- if (NOT EXISTS "${EIGEN_SOURCE_DIR} /Eigen" )
64- message (STATUS "Downloading Eigen..." )
65- ExternalProject_Add(
66- eigen_download
67- PREFIX ${EXTERNAL_DIR}
68- URL https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.tar.gz
69- SOURCE_DIR "${EIGEN_SOURCE_DIR} "
70- CONFIGURE_COMMAND ""
71- BUILD_COMMAND ""
72- INSTALL_COMMAND ""
73- LOG_DOWNLOAD ON
74- UPDATE_COMMAND ""
75- PATCH_COMMAND ""
76- )
77- endif ()
78-
79- # Download libigl after Eigen
80- if (NOT EXISTS "${LIBIGL_SOURCE_DIR} /include/igl" )
81- message (STATUS "Downloading libigl..." )
82- ExternalProject_Add(
83- libigl_download
84- DEPENDS eigen_download
85- PREFIX ${EXTERNAL_DIR}
86- URL https://github.com/libigl/libigl/archive/refs/heads/main.zip
87- SOURCE_DIR "${LIBIGL_SOURCE_DIR} "
88- CONFIGURE_COMMAND ""
89- BUILD_COMMAND ""
90- INSTALL_COMMAND ""
91- LOG_DOWNLOAD ON
92- UPDATE_COMMAND ""
93- PATCH_COMMAND ""
94- DOWNLOAD_EXTRACT_TIMESTAMP TRUE
95- )
36+ # Use custom directory for 3rd-party dependencies (optional but persistent)
37+ set (FETCHCONTENT_BASE_DIR "${CMAKE_SOURCE_DIR} /.third_party" )
38+ set (FETCHCONTENT_QUIET OFF )
39+ set (FETCHCONTENT_UPDATES_DISCONNECTED ON )
40+
41+ include (FetchContent)
42+
43+ # === Eigen ===
44+ # Check if Eigen already exists
45+ set (EIGEN_DIR "${FETCHCONTENT_BASE_DIR} /eigen-src" )
46+ if (EXISTS "${EIGEN_DIR} " )
47+ message (STATUS "Using existing Eigen from ${EIGEN_DIR} " )
48+ set (eigen_SOURCE_DIR "${EIGEN_DIR} " )
49+ set (eigen_BINARY_DIR "${FETCHCONTENT_BASE_DIR} /eigen-build" )
50+ FetchContent_Declare(
51+ eigen
52+ URL https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.tar.gz
53+ SOURCE_DIR "${eigen_SOURCE_DIR} "
54+ BINARY_DIR "${eigen_BINARY_DIR} "
55+ DOWNLOAD_EXTRACT_TIMESTAMP TRUE
56+ )
57+ else ()
58+ FetchContent_Declare(
59+ eigen
60+ URL https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.tar.gz
61+ DOWNLOAD_EXTRACT_TIMESTAMP TRUE
62+ )
9663endif ()
97-
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- )
64+ FetchContent_MakeAvailable(eigen)
65+
66+ # === libigl ===
67+ # Check if libigl already exists
68+ set (LIBIGL_DIR "${FETCHCONTENT_BASE_DIR} /libigl-src" )
69+ if (EXISTS "${LIBIGL_DIR} " )
70+ message (STATUS "Using existing libigl from ${LIBIGL_DIR} " )
71+ set (libigl_SOURCE_DIR "${LIBIGL_DIR} " )
72+ set (libigl_BINARY_DIR "${FETCHCONTENT_BASE_DIR} /libigl-build" )
73+ FetchContent_Declare(
74+ libigl
75+ GIT_REPOSITORY https://github.com/libigl/libigl.git
76+ GIT_TAG main
77+ SOURCE_DIR "${libigl_SOURCE_DIR} "
78+ BINARY_DIR "${libigl_BINARY_DIR} "
79+ )
80+ else ()
81+ FetchContent_Declare(
82+ libigl
83+ GIT_REPOSITORY https://github.com/libigl/libigl.git
84+ GIT_TAG main
85+ )
12486endif ()
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)
87+ FetchContent_MakeAvailable(libigl)
88+
89+ # === Clipper2 ===
90+ # Check if Clipper2 already exists
91+ set (CLIPPER2_DIR "${FETCHCONTENT_BASE_DIR} /clipper2-src" )
92+ if (EXISTS "${CLIPPER2_DIR} " )
93+ message (STATUS "Using existing Clipper2 from ${CLIPPER2_DIR} " )
94+ set (clipper2_SOURCE_DIR "${CLIPPER2_DIR} " )
95+ set (clipper2_BINARY_DIR "${FETCHCONTENT_BASE_DIR} /clipper2-build" )
96+ FetchContent_Declare(
97+ clipper2
98+ URL https://github.com/AngusJohnson/Clipper2/releases/download/Clipper2_1.5.3/Clipper2_1.5.3.zip
99+ SOURCE_DIR "${clipper2_SOURCE_DIR} "
100+ BINARY_DIR "${clipper2_BINARY_DIR} "
101+ DOWNLOAD_EXTRACT_TIMESTAMP TRUE
102+ )
150103else ()
151- # If the static library already exists, create a dummy target
152- add_custom_target (clipper2_build)
104+ FetchContent_Declare(
105+ clipper2
106+ URL https://github.com/AngusJohnson/Clipper2/releases/download/Clipper2_1.5.3/Clipper2_1.5.3.zip
107+ DOWNLOAD_EXTRACT_TIMESTAMP TRUE
108+ )
153109endif ()
110+ FetchContent_MakeAvailable(clipper2)
154111
155- # No additional target needed as clipper2_build is already defined by ExternalProject_Add
112+ # Build Clipper2 as a static library
113+ file (GLOB CLIPPER2_SRC "${clipper2_SOURCE_DIR} /CPP/Clipper2Lib/src/*.cpp" )
156114
157- # Create a custom target for all external dependencies
158- add_custom_target (external_downloads ALL )
159- if (TARGET eigen_download)
160- add_dependencies (external_downloads eigen_download)
161- endif ()
162- if (TARGET libigl_download)
163- add_dependencies (external_downloads libigl_download)
164- endif ()
165- if (TARGET clipper2_download)
166- add_dependencies (external_downloads clipper2_download)
167- endif ()
115+ add_library (clipper2_static STATIC ${CLIPPER2_SRC} )
116+ target_include_directories (clipper2_static PUBLIC "${clipper2_SOURCE_DIR} /CPP/Clipper2Lib/include" )
117+ set_target_properties (clipper2_static PROPERTIES POSITION_INDEPENDENT_CODE ON )
168118
169- # Add include directories for external dependencies
170- set (EIGEN_INCLUDE_DIR " ${EIGEN_SOURCE_DIR} " )
171- set (LIBIGL_INCLUDE_DIR " ${LIBIGL_SOURCE_DIR } /include" )
172- set (CLIPPER2_INCLUDE_DIR " ${CLIPPER2_SOURCE_DIR } /CPP/Clipper2Lib/include" )
119+ # === Include paths ===
120+ set (EIGEN_INCLUDE_DIR ${eigen_SOURCE_DIR} )
121+ set (LIBIGL_INCLUDE_DIR ${libigl_SOURCE_DIR } /include )
122+ set (CLIPPER2_INCLUDE_DIR ${clipper2_SOURCE_DIR } /CPP/Clipper2Lib/include )
173123
174- if (NOT SKBUILD)
175- message (WARNING "\
176- This CMake file is meant to be executed using 'scikit-build'. Running
177- it directly will almost certainly not produce the desired result. If
178- you are a user trying to install this package, please use the command
179- below, which will install all necessary build dependencies, compile
180- the package in an isolated environment, and then install it.
181- =====================================================================
182- $ pip install .
183- =====================================================================
184- If you are a software developer, and this is your own package, then
185- it is usually much more efficient to install the build dependencies
186- in your environment once and use the following command that avoids
187- a costly creation of a new virtual environment at every compilation:
188- =====================================================================
189- $ pip install --no-build-isolation -ve .
190- =====================================================================
191- You may optionally add -Ceditable.rebuild=true to auto-rebuild when
192- the package is imported. Otherwise, you need to re-run the above
193- after editing C++ files." )
194- endif ()
195-
196- # Find Python and nanobind
197- find_package (Python 3.8
198- REQUIRED COMPONENTS Interpreter Development.Module
199- OPTIONAL_COMPONENTS Development.SABIModule)
124+ # === Python & nanobind ===
125+ find_package (Python 3.8 REQUIRED COMPONENTS Interpreter Development.Module OPTIONAL_COMPONENTS Development.SABIModule)
200126find_package (nanobind CONFIG REQUIRED)
201127find_package (Threads REQUIRED)
202128
203- # Create a shared precompiled header library
129+ # === Precompiled headers ===
204130if (ENABLE_PRECOMPILED_HEADERS)
205131 add_library (compas_pch INTERFACE )
206132 target_precompile_headers(compas_pch INTERFACE src/compas.hpp)
@@ -211,14 +137,11 @@ if (ENABLE_PRECOMPILED_HEADERS)
211137 )
212138endif ()
213139
214- # Function to add a nanobind module with include directories
140+ # === Function to add nanobind modules ===
215141function (add_nanobind_module module_name source_file)
216142 nanobind_add_module(${module_name} STABLE_ABI NB_STATIC ${source_file} )
143+ add_dependencies (${module_name} clipper2_static)
217144
218- # Ensure external dependencies are downloaded and built first
219- add_dependencies (${module_name} external_downloads clipper2_build)
220-
221- # Add include directories and link PCH if enabled
222145 if (ENABLE_PRECOMPILED_HEADERS)
223146 target_link_libraries (${module_name} PRIVATE compas_pch)
224147 else ()
@@ -229,13 +152,11 @@ function(add_nanobind_module module_name source_file)
229152 )
230153 endif ()
231154
232- # Link Clipper2 directly using the static library path
233- target_link_libraries (${module_name} PRIVATE Threads::Threads ${CLIPPER2_STATIC_LIB} )
234-
155+ target_link_libraries (${module_name} PRIVATE Threads::Threads clipper2_static)
235156 install (TARGETS ${module_name} LIBRARY DESTINATION compas_libigl)
236157endfunction ()
237158
238- # Add modules
159+ # === Add your modules ===
239160add_nanobind_module(_nanobind src/nanobind.cpp)
240161add_nanobind_module(_types_std src/types_std.cpp)
241162add_nanobind_module(_boundaries src/boundaries.cpp)
@@ -249,10 +170,6 @@ add_nanobind_module(_parametrisation src/parametrisation.cpp)
249170add_nanobind_module(_planarize src/planarize.cpp)
250171add_nanobind_module(_mapping src/mapping.cpp)
251172
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 )
173+ # === Install clipper2 static lib and headers ===
174+ install (TARGETS clipper2_static ARCHIVE DESTINATION lib)
175+ install (DIRECTORY "${clipper2_SOURCE_DIR} /CPP/Clipper2Lib/include/clipper2" DESTINATION include )
0 commit comments