Skip to content

Commit 9b6597d

Browse files
CHANGE skeleton for wrapping the libigl library.
1 parent 39b7942 commit 9b6597d

File tree

9 files changed

+186
-42
lines changed

9 files changed

+186
-42
lines changed

.gitignore

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,28 @@ external
88
*.egg-info
99
.vscode
1010
.vs
11+
§
12+
13+
# Build directories
14+
build/
15+
_build/
16+
_skbuild/
17+
dist/
18+
*.egg-info/
19+
20+
# Python cache
21+
__pycache__/
22+
*.py[cod]
23+
24+
# External dependencies
25+
external/
26+
27+
# IDE files
28+
.vscode/
29+
.idea/
30+
*.swp
31+
*.swo
32+
33+
# OS files
34+
.DS_Store
35+
Thumbs.db

CMakeLists.txt

Lines changed: 85 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,61 @@
11
cmake_minimum_required(VERSION 3.15...3.26)
22

3-
project(nanobind_example LANGUAGES CXX)
3+
project(coompas_libigl LANGUAGES CXX)
44

5+
set(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)
15+
16+
# =====================================================================
17+
# Set maximum heap size for MSVC
18+
# =====================================================================
19+
20+
if(MSVC)
21+
set(CMAKE_GENERATOR_PLATFORM x64)
22+
add_compile_options(/Zm1200)
23+
endif()
24+
25+
# =====================================================================
26+
# Build size reduction.
27+
# =====================================================================
28+
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
35+
endif()
36+
endif()
37+
38+
# =====================================================================
39+
# Dependencies
40+
# =====================================================================
541
include(ExternalProject)
642

743
# Define source directories for external dependencies
844
set(EXTERNAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external")
945
set(EIGEN_SOURCE_DIR "${EXTERNAL_DIR}/eigen")
1046
set(LIBIGL_SOURCE_DIR "${EXTERNAL_DIR}/libigl")
11-
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
12-
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
13-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
1447

15-
# Create a custom target for all external dependencies
16-
add_custom_target(external_downloads ALL)
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})
1752

18-
# Download and configure Eigen
19-
if(NOT EXISTS "${EIGEN_SOURCE_DIR}")
53+
# Download Eigen first
54+
if(NOT EXISTS "${EIGEN_SOURCE_DIR}/Eigen")
2055
message(STATUS "Downloading Eigen...")
2156
ExternalProject_Add(
2257
eigen_download
58+
PREFIX ${EXTERNAL_DIR}
2359
URL https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.tar.gz
2460
SOURCE_DIR "${EIGEN_SOURCE_DIR}"
2561
CONFIGURE_COMMAND ""
@@ -29,14 +65,15 @@ if(NOT EXISTS "${EIGEN_SOURCE_DIR}")
2965
UPDATE_COMMAND ""
3066
PATCH_COMMAND ""
3167
)
32-
add_dependencies(external_downloads eigen_download)
3368
endif()
3469

35-
# Download and configure libigl
36-
if(NOT EXISTS "${LIBIGL_SOURCE_DIR}")
70+
# Download libigl after Eigen
71+
if(NOT EXISTS "${LIBIGL_SOURCE_DIR}/include/igl")
3772
message(STATUS "Downloading libigl...")
3873
ExternalProject_Add(
3974
libigl_download
75+
DEPENDS eigen_download
76+
PREFIX ${EXTERNAL_DIR}
4077
URL https://github.com/libigl/libigl/archive/refs/heads/main.zip
4178
SOURCE_DIR "${LIBIGL_SOURCE_DIR}"
4279
CONFIGURE_COMMAND ""
@@ -47,6 +84,14 @@ if(NOT EXISTS "${LIBIGL_SOURCE_DIR}")
4784
PATCH_COMMAND ""
4885
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
4986
)
87+
endif()
88+
89+
# Create a custom target for all external dependencies
90+
add_custom_target(external_downloads ALL)
91+
if(TARGET eigen_download)
92+
add_dependencies(external_downloads eigen_download)
93+
endif()
94+
if(TARGET libigl_download)
5095
add_dependencies(external_downloads libigl_download)
5196
endif()
5297

@@ -77,28 +122,39 @@ if (NOT SKBUILD)
77122
after editing C++ files.")
78123
endif()
79124

125+
# Enhanced PCH configuration
126+
if (ENABLE_PRECOMPILED_HEADERS)
127+
set(CMAKE_PCH_INSTANTIATE_TEMPLATES ON)
128+
set(CMAKE_PCH_WARN_INVALID ON)
129+
endif()
130+
80131
# Find Python and nanobind
81132
find_package(Python 3.8
82133
REQUIRED COMPONENTS Interpreter Development.Module
83134
OPTIONAL_COMPONENTS Development.SABIModule)
84135
find_package(nanobind CONFIG REQUIRED)
85136
find_package(Threads REQUIRED)
86137

87-
# Add nanobind module
88-
nanobind_add_module(
89-
nanobind_example_ext
90-
STABLE_ABI
91-
NB_STATIC
92-
src/nanobind_example_ext.cpp
93-
)
94-
95-
# Add dependencies and include directories
96-
add_dependencies(nanobind_example_ext external_downloads)
97-
target_include_directories(nanobind_example_ext PRIVATE
98-
${EIGEN_INCLUDE_DIR}
99-
${LIBIGL_INCLUDE_DIR}
100-
)
101-
target_link_libraries(nanobind_example_ext PRIVATE Threads::Threads)
102-
103-
# Install directive for scikit-build-core
104-
install(TARGETS nanobind_example_ext LIBRARY DESTINATION nanobind_example)
138+
# Function to add a nanobind module with include directories
139+
function(add_nanobind_module module_name source_file)
140+
nanobind_add_module(${module_name} STABLE_ABI NB_STATIC ${source_file})
141+
142+
# Ensure external dependencies are downloaded first
143+
add_dependencies(${module_name} external_downloads)
144+
145+
# Add include directories
146+
target_include_directories(${module_name} SYSTEM PRIVATE
147+
${EIGEN_INCLUDE_DIR}
148+
${LIBIGL_INCLUDE_DIR}
149+
)
150+
151+
if (ENABLE_PRECOMPILED_HEADERS)
152+
target_precompile_headers(${module_name} PRIVATE src/compas.h)
153+
endif()
154+
155+
target_link_libraries(${module_name} PRIVATE Threads::Threads)
156+
install(TARGETS ${module_name} LIBRARY DESTINATION coompas_libigl)
157+
endfunction()
158+
159+
# Add modules
160+
add_nanobind_module(_libigl src/nanobind.cpp)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ requires = ["scikit-build-core >=0.10", "nanobind >=1.3.2"]
33
build-backend = "scikit_build_core.build"
44

55
[project]
6-
name = "nanobind-example"
6+
name = "compas_libigl"
77
version = "0.0.1"
88
description = "An example minimal project that compiles bindings using nanobind and scikit-build"
99
readme = "README.md"

src/compas.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#pragma once
2+
3+
// STL includes
4+
#include <vector>
5+
#include <string>
6+
#include <memory>
7+
#include <algorithm>
8+
#include <cmath>
9+
#include <iostream>
10+
11+
// Nanobind includes
12+
#include <nanobind/nanobind.h>
13+
#include <nanobind/stl/string.h>
14+
#include <nanobind/stl/vector.h>
15+
#include <nanobind/stl/pair.h>
16+
#include <nanobind/eigen/dense.h>
17+
18+
// Eigen includes
19+
#include <Eigen/Core>
20+
#include <Eigen/Dense>
21+
#include <Eigen/Sparse>
22+
#include <Eigen/Geometry>
23+
24+
// libigl includes
25+
#include <igl/cotmatrix.h>
26+
#include <igl/massmatrix.h>
27+
#include <igl/invert_diag.h>
28+
#include <igl/gaussian_curvature.h>
29+
#include <igl/principal_curvature.h>
30+
#include <igl/boundary_loop.h>
31+
#include <igl/map_vertices_to_circle.h>
32+
#include <igl/harmonic.h>
33+
#include <igl/doublearea.h>
34+
#include <igl/grad.h>
35+
#include <igl/per_vertex_normals.h>
36+
#include <igl/per_face_normals.h>
37+
#include <igl/vertex_triangle_adjacency.h>
38+
#include <igl/edge_topology.h>
39+
#include <igl/is_edge_manifold.h>
40+
#include <igl/is_vertex_manifold.h>
41+
#include <igl/boundary_facets.h>
42+
#include <igl/edges.h>
43+
#include <igl/remove_unreferenced.h>
44+
45+
namespace nb = nanobind;

src/coompas_libigl/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
"""COMPAS libigl integration package"""
2+
3+
try:
4+
from ._libigl import add, __doc__
5+
except ImportError as e:
6+
raise ImportError("Could not import the required dependencies to run compas_libigl: {}".format(e))
7+
8+
__all__ = ['add']

src/nanobind.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include <nanobind/nanobind.h>
2+
#include "compas.h"
3+
4+
namespace nb = nanobind;
5+
6+
using namespace nb::literals;
7+
8+
NB_MODULE(_libigl, m) {
9+
m.doc() = "COMPAS libigl bindings for geometry processing";
10+
11+
m.def("add", [](int a, int b) { return a + b; }, "a"_a, "b"_a,
12+
"Add two numbers\n\n"
13+
"Args:\n"
14+
" a: First number\n"
15+
" b: Second number\n\n"
16+
"Returns:\n"
17+
" Sum of a and b");
18+
}

src/nanobind_example/__init__.py

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/nanobind_example_ext.cpp

Lines changed: 0 additions & 10 deletions
This file was deleted.

tests/test_basic.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import nanobind_example as m
1+
import compas_libigl as m
22

33
def test_add():
44
assert m.add(1, 2) == 3
5+
6+
print(m.add(1, 2))
7+
print(m.__doc__)

0 commit comments

Comments
 (0)