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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 65 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ endif()
# ##############################################################################
option(AL_PYTHON_BINDINGS "Build Python bindings" OFF)

# When ON, the al C++ library is not built here; instead it is located with
# find_package(al-core CONFIG). Enables a two-stage build where libimas-core
# (the C/C++ library) and imas-core (the Python wrapper) are packaged
# separately, e.g. as two conda packages.
option(AL_USE_INSTALLED_CORE
"Link Python bindings against a pre-installed al-core (find_package)" OFF)


# Configuration options for shared libraries
# ##############################################################################
Expand Down Expand Up @@ -127,8 +134,31 @@ if(WIN32)
find_package(dlfcn-win32 CONFIG REQUIRED)
endif()

# build AL_CORE library only if backend is enabled
if(AL_BACKEND_HDF5 OR AL_BACKEND_MDSPLUS OR AL_BACKEND_UDA OR AL_BACKEND_UDAFAT OR AL_PYTHON_BINDINGS)
# Two-stage build entry: locate a pre-installed al-core instead of building it.
# Exposes target `al-core::al` and an unqualified alias `al` so the python/
# subdirectory and any consumers can link to `al` transparently.
if(AL_USE_INSTALLED_CORE)
find_package(al-core CONFIG)
if(NOT al-core_FOUND)
message(FATAL_ERROR
"AL_USE_INSTALLED_CORE=ON requires an installed al-core that ships "
"al-coreConfig.cmake (introduced in IMAS-Core 5.7.1 or later). "
"find_package(al-core CONFIG) could not locate it.\n"
"Point CMAKE_PREFIX_PATH (or al-core_DIR) at an install prefix that "
"contains lib/cmake/al-core/al-coreConfig.cmake — typically the "
"stage-1 install tree of this branch. Releases built before this "
"change (e.g. IMAS-Core/5.6.0) only ship al-core.pc and will NOT "
"satisfy AL_USE_INSTALLED_CORE; either install stage 1 from source "
"or wait for a release that includes the CMake package config.")
endif()
if(NOT TARGET al)
add_library(al ALIAS al-core::al)
endif()
endif()

# build AL_CORE library only if backend is enabled and we are not reusing an
# already-installed al-core
if((AL_BACKEND_HDF5 OR AL_BACKEND_MDSPLUS OR AL_BACKEND_UDA OR AL_BACKEND_UDAFAT OR AL_PYTHON_BINDINGS) AND NOT AL_USE_INSTALLED_CORE)

# Core dependencies
set(Boost_USE_MULTITHREADED FALSE)
Expand Down Expand Up @@ -199,14 +229,43 @@ add_dependencies( imas_print_version al )
# ##############################################################################

# Install al library
include(GNUInstallDirs)
install(
TARGETS al
EXPORT al-coreTargets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT core
)

# Export CMake package config so downstream projects (notably the Python
# wrapper built with AL_USE_INSTALLED_CORE=ON) can `find_package(al-core CONFIG)`.
include(CMakePackageConfigHelpers)
set(_al_core_cmake_dir ${CMAKE_INSTALL_LIBDIR}/cmake/al-core)
install(
EXPORT al-coreTargets
FILE al-coreTargets.cmake
NAMESPACE al-core::
DESTINATION ${_al_core_cmake_dir}
)
configure_package_config_file(
${CMAKE_CURRENT_SOURCE_DIR}/cmake/al-coreConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/al-coreConfig.cmake
INSTALL_DESTINATION ${_al_core_cmake_dir}
)
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/al-coreConfigVersion.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion
)
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/al-coreConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/al-coreConfigVersion.cmake
DESTINATION ${_al_core_cmake_dir}
)

# TODO: put public heades in a separate directory?
install(
FILES ${PUBLIC_HEADER_FILES}
Expand Down Expand Up @@ -240,14 +299,15 @@ install(DIRECTORY common TYPE DATA)
# Install Dummy
install(TARGETS imas_print_version DESTINATION bin)

# Scikit-build-core entry point for python bindings
endif() # AL core library: (AL_BACKEND_* OR AL_PYTHON_BINDINGS) AND NOT AL_USE_INSTALLED_CORE

# Scikit-build-core entry point for python bindings — works whether `al` was
# just built here or imported via find_package(al-core).
# ##############################################################################
if(AL_PYTHON_BINDINGS)
include(skbuild.cmake)
endif()

endif() # AL core library (AL_BACKEND_HDF5 OR AL_BACKEND_MDSPLUS OR AL_BACKEND_UDA OR AL_BACKEND_UDAFAT OR AL_PYTHON_BINDINGS)


# MDSplus models
# ##############################################################################
Expand Down
8 changes: 8 additions & 0 deletions cmake/al-coreConfig.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@PACKAGE_INIT@

include(CMakeFindDependencyMacro)
find_dependency(Boost COMPONENTS filesystem)

include("${CMAKE_CURRENT_LIST_DIR}/al-coreTargets.cmake")

check_required_components(al-core)
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ AL_BACKEND_UDA = { env = "AL_BACKEND_UDA", default = "ON" }
AL_BACKEND_MDSPLUS = { env = "AL_BACKEND_MDSPLUS", default = "OFF" }
AL_BUILD_MDSPLUS_MODELS = { env = "AL_BUILD_MDSPLUS_MODELS", default = "OFF" }
AL_PYTHON_BINDINGS = "ON"
AL_USE_INSTALLED_CORE = { env = "AL_USE_INSTALLED_CORE", default = "OFF" }
DOWNLOAD_DEPENDENCIES = { env = "DOWNLOAD_DEPENDENCIES", default = "ON" }
DD_GIT_REPOSITORY = { env = "DD_GIT_REPOSITORY", default = "EMPTY" }
DD_VERSION = { env = "DD_VERSION", default = "EMPTY" }
Expand Down
8 changes: 8 additions & 0 deletions python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ python_add_library(al_defs MODULE ${al_defs_source} WITH_SOABI)
target_link_libraries(_al_lowlevel PRIVATE Python::NumPy al)
target_link_libraries(al_defs PRIVATE Python::NumPy al)

if(AL_USE_INSTALLED_CORE)
# libal is provided externally (e.g. the libimas-core conda package).
# Install only the Python extensions — the dynamic linker resolves libal
# at load time via the host's normal library search path / rpath.
install(TARGETS _al_lowlevel al_defs DESTINATION imas_core)
return()
endif()

# Handling RPATH in macOS:
if(APPLE)
set_target_properties(al PROPERTIES INSTALL_RPATH "@loader_path")
Expand Down
37 changes: 27 additions & 10 deletions skbuild.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,36 @@ elseif(NOT ${AL_PYTHON_BINDINGS} MATCHES "[Oo][Nn]")
message(FATAL_ERROR "AL_PYTHON_BINDINGS=${AL_PYTHON_BINDINGS} not e|editable|no-build-isolation|[Oo][Nn]")
endif()

add_custom_command(
TARGET al POST_BUILD
COMMAND
${CMAKE_COMMAND} -E env
if(AL_USE_INSTALLED_CORE)
# `al` is an ALIAS to an imported target — it is not built in this tree,
# so it cannot carry a POST_BUILD hook. Drive pip wheel from the custom
# target itself, and put it in ALL so `cmake --build` triggers it.
add_custom_target(al-python-bindings ALL
COMMAND
${CMAKE_COMMAND} -E env
CMAKE_ARGS=${CMAKE_ARGS}
SKBUILD_BUILD_DIR=${CMAKE_CURRENT_BINARY_DIR}/{wheel_tag}
SKBUILD_BUILD_DIR=${CMAKE_CURRENT_BINARY_DIR}/{wheel_tag}
${Python_EXECUTABLE}
-m pip wheel
-m pip wheel
${CMAKE_CURRENT_SOURCE_DIR}
${PIP_OPTIONS}
--wheel-dir ${CMAKE_CURRENT_BINARY_DIR}/dist/
)
add_custom_target(al-python-bindings DEPENDS al)
${PIP_OPTIONS}
--wheel-dir ${CMAKE_CURRENT_BINARY_DIR}/dist/
)
else()
add_custom_command(
TARGET al POST_BUILD
COMMAND
${CMAKE_COMMAND} -E env
CMAKE_ARGS=${CMAKE_ARGS}
SKBUILD_BUILD_DIR=${CMAKE_CURRENT_BINARY_DIR}/{wheel_tag}
${Python_EXECUTABLE}
-m pip wheel
${CMAKE_CURRENT_SOURCE_DIR}
${PIP_OPTIONS}
--wheel-dir ${CMAKE_CURRENT_BINARY_DIR}/dist/
)
add_custom_target(al-python-bindings DEPENDS al)
endif()
set_target_properties(
al-python-bindings PROPERTIES DIST_FOLDER ${CMAKE_CURRENT_BINARY_DIR}/dist/)
install(CODE "execute_process(COMMAND ${Python_EXECUTABLE}
Expand Down
Loading