Skip to content

Commit 7a59bd3

Browse files
author
pv
committed
CMAKE switch from externalproject to fetchcontent
1 parent 8804b1c commit 7a59bd3

File tree

2 files changed

+97
-177
lines changed

2 files changed

+97
-177
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ _build/
2626
*.manifest
2727
*.spec
2828

29+
# Third party dependencies
30+
.third_party/
31+
2932
# IDE
3033
.vscode/
3134
.idea/

CMakeLists.txt

Lines changed: 94 additions & 177 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,18 @@
11
cmake_minimum_required(VERSION 3.15...3.26)
2-
32
project(compas_libigl LANGUAGES CXX)
43

54
set(CMAKE_CXX_STANDARD 20)
5+
set(CMAKE_CXX_EXTENSIONS OFF)
66

77
option(ENABLE_PRECOMPILED_HEADERS "Enable precompiled headers" OFF)
88
option(MULTITHREADED_COMPILATION "Enable multi-threaded compilation (Ninja only)" ON)
99

10-
# Set build options
1110
if(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")
1714
endif()
1815

19-
# Specify the compiler standard flag
20-
set(CMAKE_CXX_EXTENSIONS OFF)
21-
22-
# Set the use of a pre-compile header
2316
if(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()
3728
endif()
3829

3930
if(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()
4634
endif()
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+
)
9663
endif()
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+
)
12486
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)
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+
)
150103
else()
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+
)
153109
endif()
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)
200126
find_package(nanobind CONFIG REQUIRED)
201127
find_package(Threads REQUIRED)
202128

203-
# Create a shared precompiled header library
129+
# === Precompiled headers ===
204130
if (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
)
212138
endif()
213139

214-
# Function to add a nanobind module with include directories
140+
# === Function to add nanobind modules ===
215141
function(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)
236157
endfunction()
237158

238-
# Add modules
159+
# === Add your modules ===
239160
add_nanobind_module(_nanobind src/nanobind.cpp)
240161
add_nanobind_module(_types_std src/types_std.cpp)
241162
add_nanobind_module(_boundaries src/boundaries.cpp)
@@ -249,10 +170,6 @@ add_nanobind_module(_parametrisation src/parametrisation.cpp)
249170
add_nanobind_module(_planarize src/planarize.cpp)
250171
add_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

Comments
 (0)