Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
25 changes: 22 additions & 3 deletions .github/workflows/wheel.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,35 @@ jobs:
- name: Build wheels
uses: pypa/cibuildwheel@v3.4.1
env:
CIBW_BUILD: "cp310-*"
CIBW_BUILD_FRONTEND: "build[uv]"
CIBW_ARCHS_LINUX: auto64
CIBW_ARCHS_WINDOWS: auto64
CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28
CIBW_SKIP: "*-musllinux* pp*"
CIBW_TEST_COMMAND: "pytest -s --pdb {project}/modules"
CIBW_TEST_REQUIRES: pytest
CIBW_SKIP: "*-musllinux*"
MACOSX_DEPLOYMENT_TARGET: 13.00
CIBW_BUILD_VERBOSITY: 2

- name: Test wheel on supported Python versions
shell: bash
run: |
set -euxo pipefail
wheels=(wheelhouse/*.whl)
if [[ ${#wheels[@]} -ne 1 || ! -f "${wheels[0]}" ]]; then
echo "Expected exactly one wheel, found: ${wheels[*]}" >&2
exit 1
fi

for python_version in 3.10 3.11 3.12 3.13 3.14; do
uv run \
--isolated \
--no-project \
--python "$python_version" \
--with pytest \
--with "${wheels[0]}" \
python -m pytest -s modules
done

- uses: actions/upload-artifact@v4
with:
name: wheels-${{matrix.os}}
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ LagrangeOptions.cmake
# The MetaBuild equivalent
/META/META.user.yaml
/META/META.lock
/META/build

/external
/dist
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ else()
endif()

# Check required CMake version
cmake_minimum_required(VERSION 3.25.0)
cmake_minimum_required(VERSION 3.26.0)

cmake_policy(SET CMP0054 NEW) # Only interpret if() arguments as variables or keywords when unquoted.
cmake_policy(SET CMP0076 NEW) # target_sources() command converts relative paths to absolute.
Expand Down
84 changes: 83 additions & 1 deletion cmake/lagrange/lagrange_add_module.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,86 @@
# OF ANY KIND, either express or implied. See the License for the specific language
# governing permissions and limitations under the License.
#
function(lagrange_add_module_component module_name)
get_filename_component(component_dir "${CMAKE_CURRENT_SOURCE_DIR}" REALPATH)
get_filename_component(component "${component_dir}" NAME)
get_filename_component(extras_dir "${component_dir}" DIRECTORY)
get_filename_component(module_dir "${extras_dir}" DIRECTORY)
get_filename_component(detected_module_name "${module_dir}" NAME)
if(NOT detected_module_name STREQUAL module_name)
message(FATAL_ERROR
"Component '${component}' is under module '${detected_module_name}', not '${module_name}'"
)
endif()

set(module_target "lagrange_${module_name}")
if(NOT TARGET ${module_target})
message(FATAL_ERROR "Cannot add component '${component}': lagrange::${module_name} does not exist")
endif()
if(TARGET lagrange::${module_name}::${component})
return()
endif()
if(NOT component MATCHES "^[A-Za-z_]+$")
message(FATAL_ERROR
"Invalid component name '${component}' for lagrange::${module_name}; "
"component names may contain letters and underscores only"
)
endif()

file(GLOB_RECURSE component_sources CONFIGURE_DEPENDS "*.cpp" "*.h")
if(NOT component_sources)
message(FATAL_ERROR "Component '${component}' for lagrange::${module_name} has no sources")
endif()

get_target_property(module_type ${module_target} TYPE)
if(module_type STREQUAL "STATIC_LIBRARY")
set(component_type STATIC)
elseif(module_type STREQUAL "SHARED_LIBRARY")
set(component_type SHARED)
else()
message(FATAL_ERROR "Compiled components require a static or shared base module")
endif()

string(TOUPPER "${module_name}" uc_module_name)
string(TOUPPER "${component}" uc_component)
set(component_target "lagrange_${module_name}_${component}")
add_library(${component_target} ${component_type} ${component_sources})
add_library(lagrange::${module_name}::${component} ALIAS ${component_target})
target_link_libraries(${component_target} PUBLIC ${module_target})
target_include_directories(${component_target} PRIVATE "${module_dir}/src")
target_compile_definitions(
${component_target}
PUBLIC "LAGRANGE_${uc_module_name}_WITH_${uc_component}"
)
if(module_type STREQUAL "SHARED_LIBRARY")
target_compile_definitions(${component_target} PRIVATE "lagrange_${module_name}_EXPORTS")
endif()
target_compile_features(${component_target} PUBLIC cxx_std_17)
lagrange_add_warnings(${component_target})
target_code_coverage(${component_target} PUBLIC AUTO ALL EXCLUDE "${FETCHCONTENT_BASE_DIR}/*")

set_target_properties(
${component_target}
PROPERTIES
POSITION_INDEPENDENT_CODE ON
FOLDER "${LAGRANGE_IDE_PREFIX}Lagrange/Modules/Components"
)
get_target_property(warnings_as_errors ${module_target} COMPILE_WARNING_AS_ERROR)
if(NOT warnings_as_errors STREQUAL "warnings_as_errors-NOTFOUND")
set_target_properties(
${component_target}
PROPERTIES COMPILE_WARNING_AS_ERROR "${warnings_as_errors}"
)
endif()

get_target_property(install_components ${module_target} LAGRANGE_MODULE_INSTALL_COMPONENTS)
if(install_components)
lagrange_install(${component_target})
endif()
set_target_properties(${component_target} PROPERTIES EXPORT_NAME "${module_name}::${component}")
message(STATUS "Lagrange: enabling component 'lagrange::${module_name}::${component}'")
endfunction()

function(lagrange_add_module)
# Retrieve module name
get_filename_component(module_path "${CMAKE_CURRENT_SOURCE_DIR}" REALPATH)
Expand Down Expand Up @@ -80,7 +160,9 @@ function(lagrange_add_module)

# Create install rules
if(LAGRANGE_INSTALL AND NOT OPTIONS_NO_INSTALL)
set_target_properties(lagrange_${module_name} PROPERTIES LAGRANGE_MODULE_INSTALL_COMPONENTS TRUE)
lagrange_install(lagrange_${module_name})
else()
set_target_properties(lagrange_${module_name} PROPERTIES LAGRANGE_MODULE_INSTALL_COMPONENTS FALSE)
endif()

endfunction()
87 changes: 76 additions & 11 deletions cmake/lagrange/lagrange_include_modules.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,86 @@
# OF ANY KIND, either express or implied. See the License for the specific language
# governing permissions and limitations under the License.
#
function(lagrange_include_modules)
# Includes one module and any requested optional components.
# Usage: lagrange_include_module(<module> [COMPONENTS <component>...]).
function(lagrange_include_module name)
set(options "")
set(oneValueArgs "")
set(multiValueArgs COMPONENTS)
cmake_parse_arguments(PARSE_ARGV 1 OPTIONS "${options}" "${oneValueArgs}" "${multiValueArgs}")
if(OPTIONS_UNPARSED_ARGUMENTS)
message(FATAL_ERROR
"Unexpected arguments for lagrange_include_module(${name}): ${OPTIONS_UNPARSED_ARGUMENTS}"
)
endif()

if(LAGRANGE_ALLOWLIST AND NOT (${name} IN_LIST LAGRANGE_ALLOWLIST))
message(FATAL_ERROR "Lagrange module '${name}' is not allowed in this project")
endif()
if(${name} IN_LIST LAGRANGE_BLOCKLIST)
message(FATAL_ERROR "Lagrange module '${name}' is excluded from this project")
endif()

get_property(lagrange_module_path GLOBAL PROPERTY __lagrange_module_path)
get_property(lagrange_source_dir GLOBAL PROPERTY __lagrange_source_dir)
get_property(lagrange_binary_dir GLOBAL PROPERTY __lagrange_binary_dir)
set(CMAKE_MODULE_PATH ${lagrange_module_path})
foreach(name IN ITEMS ${ARGN})
if(LAGRANGE_ALLOWLIST AND NOT (${name} IN_LIST LAGRANGE_ALLOWLIST))
message(FATAL_ERROR "Lagrange module '${name}' is not allowed in this project")
if(NOT TARGET lagrange::${name})
add_subdirectory(
${lagrange_source_dir}/modules/${name}
${lagrange_binary_dir}/modules/lagrange_${name}
)
endif()

foreach(component IN LISTS OPTIONS_COMPONENTS)
if(TARGET lagrange::${name}::${component})
continue()
endif()
if(${name} IN_LIST LAGRANGE_BLOCKLIST)
message(FATAL_ERROR "Lagrange module '${name}' is excluded from this project")
if(NOT component MATCHES "^[A-Za-z_]+$")
message(FATAL_ERROR
"Invalid component name '${component}' for lagrange::${name}; "
"component names may contain letters and underscores only"
)
endif()

if(NOT TARGET lagrange::${name})
get_property(lagrange_source_dir GLOBAL PROPERTY __lagrange_source_dir)
get_property(lagrange_binary_dir GLOBAL PROPERTY __lagrange_binary_dir)
add_subdirectory(${lagrange_source_dir}/modules/${name} ${lagrange_binary_dir}/modules/lagrange_${name})
set(component_source_dir "${lagrange_source_dir}/modules/${name}/extras/${component}")
if(NOT EXISTS "${component_source_dir}/CMakeLists.txt")
file(GLOB available_component_dirs LIST_DIRECTORIES TRUE
"${lagrange_source_dir}/modules/${name}/extras/*"
)
set(available_components "")
foreach(component_dir IN LISTS available_component_dirs)
if(IS_DIRECTORY "${component_dir}")
get_filename_component(available_component "${component_dir}" NAME)
list(APPEND available_components "${available_component}")
endif()
endforeach()
message(FATAL_ERROR
"Unknown component '${component}' for lagrange::${name}. "
"Available components: ${available_components}"
)
endif()
add_subdirectory(
"${component_source_dir}"
"${lagrange_binary_dir}/modules/lagrange_${name}/extras/${component}"
)
if(NOT TARGET lagrange::${name}::${component})
message(FATAL_ERROR
"Component '${component}' did not create lagrange::${name}::${component}"
)
endif()
endforeach()
endfunction()

# Includes multiple base modules; use lagrange_include_module() for optional components.
function(lagrange_include_modules)
set(module_names ${ARGN})
if("COMPONENTS" IN_LIST module_names)
message(FATAL_ERROR
"lagrange_include_modules() accepts module names only; use "
"lagrange_include_module(<module> COMPONENTS ...) for components"
)
endif()
foreach(name IN LISTS module_names)
lagrange_include_module(${name})
endforeach()
endfunction()
16 changes: 10 additions & 6 deletions cmake/recipes/external/clipper2.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@ option(CLIPPER2_EXAMPLES "Build examples" OFF)
option(CLIPPER2_TESTS "Build tests" OFF)

include(CPM)
CPMAddPackage(
NAME clipper2
GITHUB_REPOSITORY AngusJohnson/Clipper2
GIT_TAG Clipper2_1.4.0
SOURCE_SUBDIR CPP
)
block()
set(BUILD_SHARED_LIBS OFF)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
CPMAddPackage(
NAME clipper2
GITHUB_REPOSITORY AngusJohnson/Clipper2
GIT_TAG Clipper2_1.4.0
SOURCE_SUBDIR CPP
)
endblock()

add_library(Clipper2::Clipper2 ALIAS Clipper2)

Expand Down
2 changes: 1 addition & 1 deletion cmake/recipes/external/nanobind.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ include(CPM)
CPMAddPackage(
NAME nanobind
GITHUB_REPOSITORY wjakob/nanobind
GIT_TAG v2.13.0
GIT_TAG v3.0.0
DOWNLOAD_ONLY ON
)

Expand Down
8 changes: 6 additions & 2 deletions cmake/recipes/external/python.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@
# OF ANY KIND, either express or implied. See the License for the specific language
# governing permissions and limitations under the License.
#
if(TARGET Python::Module)
if(TARGET Python::Module AND TARGET Python::SABIModule)
return()
endif()

set(Python_FIND_VIRTUALENV FIRST)
find_package(Python 3.9 COMPONENTS Interpreter Development.Module REQUIRED)
find_package(
Python 3.10
COMPONENTS Interpreter Development.Module Development.SABIModule
REQUIRED
)
3 changes: 2 additions & 1 deletion cmake/recipes/external/quadprog.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ CPMAddPackage(
GIT_TAG 8e6e38ad5b257d1795a9ef995e4fd7db72ccf551
)

add_library(quadprog
add_library(quadprog STATIC
${quadprog_SOURCE_DIR}/QuadProgPP.cpp
${quadprog_SOURCE_DIR}/QuadProgPP.h
)
add_library(quadprog::quadprog ALIAS quadprog)
set_target_properties(quadprog PROPERTIES FOLDER third_party)
set_target_properties(quadprog PROPERTIES POSITION_INDEPENDENT_CODE ON)

include(GNUInstallDirs)
target_include_directories(quadprog SYSTEM INTERFACE
Expand Down
2 changes: 1 addition & 1 deletion cmake/recipes/external/texture_signal_processing.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ include(CPM)
CPMAddPackage(
NAME texture_signal_processing
GITHUB_REPOSITORY jdumas/TextureSignalProcessing
GIT_TAG 4689f674deadde94511b6f4c00b6dedf3790527e # adobe/lagrange branch
GIT_TAG 72de1412d5a579f83407eac86dd428a7032d4e34 # adobe/lagrange branch
)

add_library(texture_signal_processing::texture_signal_processing INTERFACE IMPORTED GLOBAL)
Expand Down
2 changes: 1 addition & 1 deletion cmake/recipes/external/xatlas.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ include(CPM)
CPMAddPackage(
NAME xatlas
GITHUB_REPOSITORY jdumas/xatlas
GIT_TAG 649fae81dd20801db55338bc86e0a7eab745ddf4
GIT_TAG 3d2c0a44096feb59e20b05a8a399169f3829f210
DOWNLOAD_ONLY ON
)

Expand Down
1 change: 1 addition & 0 deletions docs/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ set(DOXYGEN_EXCLUDE_FOLDERS
)
list(JOIN DOXYGEN_EXCLUDE_FOLDERS " " DOXYGEN_EXCLUDE_FOLDERS)

set(DOXYGEN_PREDEFINED_FILE ${CMAKE_CURRENT_SOURCE_DIR}/doxyfile-predefined.txt)
set(DOXYGEN_LAYOUT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/DoxygenLayout.xml)
set(DOXYGEN_WORKING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../..)
set(DOXYGEN_INPUT_DIR modules)
Expand Down
8 changes: 6 additions & 2 deletions docs/cpp/Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -2484,9 +2484,13 @@ INCLUDE_FILE_PATTERNS =
# is assumed. To prevent a macro definition from being undefined via #undef or
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
#
# The PREDEFINED tag itself is defined in doxyfile-predefined.txt, which is
# generated by scripts/generate_export_headers.py (via @INCLUDE below) so it
# always lists every module's LA_<MODULE>_API export macro without requiring
# fragile in-place edits of this file.

PREDEFINED = LA_IGNORE_DOCUMENTATION_WARNING_BEGIN= \
LA_IGNORE_DOCUMENTATION_WARNING_END=
@INCLUDE = @DOXYGEN_PREDEFINED_FILE@

# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
Expand Down
Loading
Loading