From fb9e3b06cb8510f4ac47610cdf114ea6cd3c8eaa Mon Sep 17 00:00:00 2001 From: Growl Date: Tue, 23 Jun 2026 12:49:46 +0800 Subject: [PATCH 1/5] CMake: Make libint2 Fortran interface explicit --- cmake/libint2-config.cmake.in | 3 +++ export/CMakeLists.txt.export | 36 ++++++++++++++++++++++++----------- export/tests/CMakeLists.txt | 10 ++-------- 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/cmake/libint2-config.cmake.in b/cmake/libint2-config.cmake.in index dce83a3f4..54c4da929 100644 --- a/cmake/libint2-config.cmake.in +++ b/cmake/libint2-config.cmake.in @@ -40,6 +40,7 @@ # oo - search for + orca = orca # bs - search for bagel + standard = bagel # bo - search for + orca +# Fortran - require the Fortran interface target @PACKAGE_INIT@ @@ -55,6 +56,8 @@ list(PREPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) # check library language component include(CMakeFindDependencyMacro) +set(${L2}_Fortran_FOUND @LIBINT2_ENABLE_FORTRAN@) + if(NOT TARGET Eigen3::Eigen) set(Eigen3_CONFIG @Eigen3_CONFIG@) if (NOT Eigen3_CONFIG OR NOT EXISTS ${Eigen3_CONFIG}) diff --git a/export/CMakeLists.txt.export b/export/CMakeLists.txt.export index 5474b1ff1..3e938c8b9 100644 --- a/export/CMakeLists.txt.export +++ b/export/CMakeLists.txt.export @@ -125,6 +125,10 @@ set(LIBINT2_INSTALL_DATADIR "${CMAKE_INSTALL_DATADIR}/libint/${LIBINT_VERSION}" set(LIBINT2_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/libint2" CACHE PATH "LIBINT2 CMAKE install directory") +if(NOT CMAKE_INSTALL_Fortran_MODULES) + set(CMAKE_INSTALL_Fortran_MODULES "${LIBINT2_INSTALL_INCLUDEDIR}") +endif() + # ==== Dependencies =========================================================== @@ -668,21 +672,13 @@ if (LIBINT2_ENABLE_FORTRAN) ) # build module - add_library( - libint_f - OBJECT - fortran/libint_f.F90 - ) + add_library(libint_f OBJECT fortran/libint_f.F90) set_source_files_properties( fortran/libint_f.F90 PROPERTIES OBJECT_DEPENDS "${PROJECT_BINARY_DIR}/fortran/libint2_types_f.h;${PROJECT_BINARY_DIR}/fortran/fortran_incldefs.h" ) - target_compile_definitions( - libint_f - PRIVATE - __COMPILING_LIBINT2 - ) + target_compile_definitions(libint_f PRIVATE __COMPILING_LIBINT2) set_target_properties( libint_f PROPERTIES @@ -700,6 +696,21 @@ if (LIBINT2_ENABLE_FORTRAN) $ ) + add_library(int_f STATIC $) + set_target_properties(int_f PROPERTIES OUTPUT_NAME "int2_f") + if (L2_BUILD_SHARED_LIBS) + target_link_libraries(int_f INTERFACE int-shared) + else() + target_link_libraries(int_f INTERFACE int-static) + endif() + target_include_directories( + int_f + INTERFACE + $ + $ + $ + ) + # Fortran tests merged into rest of tests endif (LIBINT2_ENABLE_FORTRAN) @@ -733,6 +744,9 @@ endif() if (L2_BUILD_STATIC_LIBS) list(APPEND _libint2_install_targets int-static) endif() +if (LIBINT2_ENABLE_FORTRAN) + list(APPEND _libint2_install_targets int_f) +endif() install( TARGETS ${_libint2_install_targets} @@ -839,7 +853,7 @@ endif() if (LIBINT2_ENABLE_FORTRAN) install( DIRECTORY ${PROJECT_BINARY_DIR}/${BUILDTREE_FMODDIR}/ - DESTINATION "${LIBINT2_INSTALL_INCLUDEDIR}" + DESTINATION "${CMAKE_INSTALL_Fortran_MODULES}" ) endif() diff --git a/export/tests/CMakeLists.txt b/export/tests/CMakeLists.txt index ca2b48249..4995eec13 100644 --- a/export/tests/CMakeLists.txt +++ b/export/tests/CMakeLists.txt @@ -242,10 +242,6 @@ endif (LIBINT2_REQUIRE_CXX_API) if (LIBINT2_ENABLE_FORTRAN) - # Note: if forming compile line by hand rather than using targets, you'll - # need to include the Fortran module file directory: - # `target_include_directories(... PRIVATE $)` - add_executable( fortran_example-libint2 EXCLUDE_FROM_ALL @@ -254,8 +250,7 @@ if (LIBINT2_ENABLE_FORTRAN) target_link_libraries( fortran_example-libint2 PRIVATE - Libint2::int2 - libint_f + int_f ) add_test( # Test #14 NAME libint2/fortran_example/build @@ -283,14 +278,13 @@ if (LIBINT2_ENABLE_FORTRAN) EXCLUDE_FROM_ALL fortran/test.cc fortran/test-eri.cc - $ ) target_link_libraries( fortran_test-libint2 PRIVATE $,Libint2::int2-cxx,Libint2::cxx> # N.B. cxx compiled library if LIBINT2_REQUIRE_CXX_API_COMPILED=ON else header-only library - libint_f + int_f ) add_test( # Test #16 NAME libint2/fortran_test/build From 6e4e62700cb61147edc4f69f380384a353db88bb Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 13 Aug 2026 17:01:03 -0400 Subject: [PATCH 2/5] CMake: fix Fortran interface target install, PIC, and naming Follow-up to the Libint2 Fortran interface work in this branch: * decide PIC for the libint_f objects from L2_BUILD_SHARED_LIBS rather than BUILD_SHARED_LIBS, matching int-obj. With LIBINT2_BUILD_SHARED_AND_STATIC_LIBS=ON and BUILD_SHARED_LIBS=OFF the now-installed libint2_f.a was built without -fPIC while interface-linking the shared libint2. * install the generated Fortran headers (fortran_incldefs.h, libint2_types_f.h) into /libint2/fortran and add that directory to the target's INSTALL_INTERFACE. fortran_example.F90, the canonical consumer example, #includes fortran_incldefs.h, so downstream users of the installed target could not compile. * name the public consumption target Libint2::fortran, as INSTALL.md already advertised, aliased to int_f in the build tree and in libint2-config.cmake, the same way Libint2::int2 and Libint2::cxx are handled. int_f remains the exported internal target. This also makes a namespaced name available to add_subdirectory/FetchContent users. * rename CMAKE_INSTALL_Fortran_MODULES to LIBINT2_INSTALL_FMODDIR and make it a cache entry, out of the reserved CMAKE_ namespace. It is declared the way GNUInstallDirs declares its own path variables, because a plain set(... CACHE PATH) rewrites a relative -D value into an absolute path below the build directory. * forward LIBINT2_INSTALL_FMODDIR to the library ExternalProject and add it to the staging-area install directories, so the packaging use case works in the one-shot generator + library build. * resolve the fortran component from the imported target instead of the configure-time option, deferring check_required_components() until after the targets file is included, and move its doc line out of the ordering-code table. --- CMakeLists.txt | 3 ++- INSTALL.md | 7 ++--- cmake/libint2-config.cmake.in | 17 +++++++++--- export/CMakeLists.txt.export | 49 ++++++++++++++++++++++++++++++----- export/tests/CMakeLists.txt | 4 +-- src/lib/libint/CMakeLists.txt | 13 +++++++++- 6 files changed, 75 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 528b9e865..4011e39ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,7 +82,8 @@ set(pnv libint2) # projectnameversion # build libint-library-export target before library build targets appear # - (4) unpack the export tarball and build the library and install into \/library-install-stage/ # - duration depends on number of integrals requested; runs in parallel -# - consumes language-interface and the CMAKE_INSTALL_[DATA|INCLUDE|LIB]DIR paths options +# - consumes language-interface, the CMAKE_INSTALL_[DATA|INCLUDE|LIB]DIR paths +# options, and LIBINT2_INSTALL_FMODDIR # - the default build target includes this final library build # - (5) optionally testable # - (6) install into CMAKE_INSTALL_PREFIX diff --git a/INSTALL.md b/INSTALL.md index dd4178010..bb3e38082 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -51,7 +51,7 @@ The Libint build is structured into three parts: or dependency (FetchContent or ExternalProject) - (4) unpack the export tarball and build the library and install into \/library-install-stage/ - duration depends on number of integrals requested; runs in parallel - - consumes language-interface and the CMAKE_INSTALL_[DATA|INCLUDE|LIB]DIR paths options + - consumes language-interface, the CMAKE_INSTALL_[DATA|INCLUDE|LIB]DIR paths options, and LIBINT2_INSTALL_FMODDIR - the default build target includes this final library build - (5) optionally testable - (6) install into CMAKE_INSTALL_PREFIX @@ -329,6 +329,7 @@ Note that options, docs, and CMake components are focused on the C++ interface, ### Install Paths (L) (TARBALL) +* `LIBINT2_INSTALL_FMODDIR` - L - For `LIBINT2_ENABLE_FORTRAN=ON`, the directory below `CMAKE_INSTALL_PREFIX` into which `libint_f.mod` is installed and which the `Libint2::fortran` target adds to its interface. Distribution packages that keep Fortran modules in a compiler-specific location (e.g. `lib64/gfortran/modules`) can set it at configure time rather than relocating the module after install. [Default=`CMAKE_INSTALL_INCLUDEDIR`] * `LIBINT2_PREFIX_PYTHON_INSTALL` - L - For `LIBINT2_ENABLE_PYTHON=ON`, whether to install the Python module in the Linux manner to `CMAKE_INSTALL_PREFIX` or to not install it. Note: not a path; the installation sub-path below `CMAKE_INSTALL_PREFIX` is determined by querying `Python_EXECUTABLE`. For alternate installation in the Python manner to `Python_EXECUTABLE`'s site-packages, see target libint2-python-wheel. [Default=OFF] @@ -383,13 +384,13 @@ Note that options, docs, and CMake components are focused on the C++ interface, | `Libint2::int2` | `C` | yes | always | impossible | `int-{static,shared}` | `libint2` | | `Libint2::cxx` | `CXX_ho` | yes | `LIBINT2_REQUIRE_CXX_API=ON` | `LIBINT2_REQUIRE_CXX_API=OFF` & withhold Eigen3 & `LIBINT2_REQUIRE_CXX_API_COMPILED=OFF` & `LIBINT2_ENABLE_PYTHON=OFF` | `int-cxx-headeronly-{static,shared}` | `libint2_cxx` | | `Libint2::int2-cxx` | `CXX` | yes | `LIBINT2_REQUIRE_CXX_API_COMPILED=ON` | `LIBINT2_REQUIRE_CXX_API_COMPILED=OFF` | `int-cxx-{static,shared}` | | -| Fortran local[^19] | (NYI) | no | `LIBINT2_ENABLE_FORTRAN=ON` | `LIBINT2_ENABLE_FORTRAN=OFF` | `libint_f` | | +| `Libint2::fortran` | `fortran` | no | `LIBINT2_ENABLE_FORTRAN=ON` | `LIBINT2_ENABLE_FORTRAN=OFF` | `int_f`, `libint_f`[^19] | | [^15]: Targets for library consumer use. These are available after `find_package(Libint2)` or `add_subdirectory()`. [^16]: Ensure target found in installation after `find_package(Libint2 COMPONENTS ...)`. [^17]: Targets in export/CMakeLists.txt.export . Names subject to change. Use namespaced target names in any consuming code. [^18]: Deprecated legacy aliases. Update any uses to namespaced target. -[^19]: The `libint_f` internal target defines the Fortran interface to Libint2. One must also link to `Libint2::int2` or `Libint2::cxx`. At present, it is not exported, and a namespaced target is not defined. +[^19]: `libint_f` compiles the Fortran module; `int_f` archives it and carries the usage requirements, so linking `Libint2::fortran` alone brings in the Fortran module directory, the generated Fortran headers, and the Libint2 C library. Set `LIBINT2_INSTALL_FMODDIR` to control where `libint_f.mod` is installed. ----------------------------------------------------------------------------- diff --git a/cmake/libint2-config.cmake.in b/cmake/libint2-config.cmake.in index 54c4da929..244d31e2a 100644 --- a/cmake/libint2-config.cmake.in +++ b/cmake/libint2-config.cmake.in @@ -26,6 +26,7 @@ # eri_HH_dD - search for library including 2-body integrals with 2 centers # eri_hh_dD - ditto # g12_hhhh_dD - search for library including F12 integrals with Gaussian factors +# fortran - search for library including the fortran interface target # # cart shell_set used_by # -------- --------- ------- @@ -40,7 +41,6 @@ # oo - search for + orca = orca # bs - search for bagel + standard = bagel # bo - search for + orca -# Fortran - require the Fortran interface target @PACKAGE_INIT@ @@ -56,8 +56,6 @@ list(PREPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) # check library language component include(CMakeFindDependencyMacro) -set(${L2}_Fortran_FOUND @LIBINT2_ENABLE_FORTRAN@) - if(NOT TARGET Eigen3::Eigen) set(Eigen3_CONFIG @Eigen3_CONFIG@) if (NOT Eigen3_CONFIG OR NOT EXISTS ${Eigen3_CONFIG}) @@ -96,7 +94,9 @@ foreach(_eri @Libint2_CONFIG_COMPONENTS@) # Libint2_CONFIG_COMPONENTS set(${L2}_${_eri}_FOUND 1) endforeach() -check_required_components(${L2}) +# N.B. check_required_components() is deferred to the end of this file so that +# the language components can be resolved from the imported targets below +# rather than from configure-time options # Import library targets if(NOT TARGET ${L2}::int-shared AND NOT TARGET ${L2}::int-static) @@ -123,3 +123,12 @@ elseif (TARGET ${L2}::int-cxx-headeronly-static) add_library(${L2}::cxx ALIAS ${L2}::int-cxx-headeronly-static) endif() endif() + +if (TARGET ${L2}::int_f) + if (NOT TARGET ${L2}::fortran) + add_library(${L2}::fortran ALIAS ${L2}::int_f) + endif() + set(${L2}_fortran_FOUND 1) +endif() + +check_required_components(${L2}) diff --git a/export/CMakeLists.txt.export b/export/CMakeLists.txt.export index 3e938c8b9..18a93d6db 100644 --- a/export/CMakeLists.txt.export +++ b/export/CMakeLists.txt.export @@ -124,10 +124,23 @@ set(LIBINT2_INSTALL_DATADIR "${CMAKE_INSTALL_DATADIR}/libint/${LIBINT_VERSION}" CACHE PATH "LIBINT2 DATA install directory") set(LIBINT2_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/libint2" CACHE PATH "LIBINT2 CMAKE install directory") - -if(NOT CMAKE_INSTALL_Fortran_MODULES) - set(CMAKE_INSTALL_Fortran_MODULES "${LIBINT2_INSTALL_INCLUDEDIR}") +# N.B. `set(... CACHE PATH)` would rewrite a relative -D value (e.g. the +# `lib64/gfortran/modules` a distro packager wants) into an absolute path +# below the build dir, so declare the type the way GNUInstallDirs does: +# only default it when unset, then retype an -D-supplied entry in place. +if (NOT DEFINED LIBINT2_INSTALL_FMODDIR) + set(LIBINT2_INSTALL_FMODDIR "${LIBINT2_INSTALL_INCLUDEDIR}" + CACHE PATH "LIBINT2 Fortran module install directory") +endif() +get_property(_l2_fmoddir_type CACHE LIBINT2_INSTALL_FMODDIR PROPERTY TYPE) +if (_l2_fmoddir_type STREQUAL "UNINITIALIZED") + file(TO_CMAKE_PATH "${LIBINT2_INSTALL_FMODDIR}" _l2_fmoddir) + set_property(CACHE LIBINT2_INSTALL_FMODDIR PROPERTY TYPE PATH) + set_property(CACHE LIBINT2_INSTALL_FMODDIR PROPERTY VALUE "${_l2_fmoddir}") + set_property(CACHE LIBINT2_INSTALL_FMODDIR PROPERTY HELPSTRING "LIBINT2 Fortran module install directory") + unset(_l2_fmoddir) endif() +unset(_l2_fmoddir_type) # ==== Dependencies =========================================================== @@ -684,7 +697,10 @@ if (LIBINT2_ENABLE_FORTRAN) PROPERTIES Fortran_MODULE_DIRECTORY ${PROJECT_BINARY_DIR}/${BUILDTREE_FMODDIR} ) - if (BUILD_SHARED_LIBS) + # N.B. use L2_BUILD_SHARED_LIBS (set above from LIBINT2_BUILD_SHARED_AND_STATIC_LIBS + # or BUILD_SHARED_LIBS), same as int-obj, since these objects end up in the + # installed int_f archive that may be linked against the shared libint2 + if (L2_BUILD_SHARED_LIBS) set_target_properties(libint_f PROPERTIES POSITION_INDEPENDENT_CODE 1) endif() target_include_directories( @@ -708,9 +724,18 @@ if (LIBINT2_ENABLE_FORTRAN) INTERFACE $ $ - $ + # generated Fortran headers (fortran_incldefs.h, libint2_types_f.h); + # the build-tree counterpart is ${PROJECT_BINARY_DIR}/fortran above + $ + $ ) + # permanent alias, so that consuming code can use the same target name + # whether libint2 is found or added as a subproject. + # N.B. the install-tree counterpart is created + # in cmake/libint2-config.cmake.in, same as for ${L2}::int2 and ${L2}::cxx + add_library(${L2}::fortran ALIAS int_f) + # Fortran tests merged into rest of tests endif (LIBINT2_ENABLE_FORTRAN) @@ -849,11 +874,21 @@ if (LIBINT2_REQUIRE_CXX_API) endif() endif() -# Fortran modules +# Fortran modules and generated Fortran headers if (LIBINT2_ENABLE_FORTRAN) install( DIRECTORY ${PROJECT_BINARY_DIR}/${BUILDTREE_FMODDIR}/ - DESTINATION "${CMAKE_INSTALL_Fortran_MODULES}" + DESTINATION "${LIBINT2_INSTALL_FMODDIR}" + ) + # fortran_incldefs.h is #include'd by consumers of the libint_f module + # (see tests/fortran/fortran_example.F90), so it must be installed along + # with the module file; libint2_types_f.h is its companion + install( + FILES + ${PROJECT_BINARY_DIR}/fortran/fortran_incldefs.h + ${PROJECT_BINARY_DIR}/fortran/libint2_types_f.h + DESTINATION "${LIBINT2_INSTALL_INCLUDEDIR}/libint2/fortran" + COMPONENT ${L2}_Development ) endif() diff --git a/export/tests/CMakeLists.txt b/export/tests/CMakeLists.txt index 4995eec13..0e3fb6476 100644 --- a/export/tests/CMakeLists.txt +++ b/export/tests/CMakeLists.txt @@ -250,7 +250,7 @@ if (LIBINT2_ENABLE_FORTRAN) target_link_libraries( fortran_example-libint2 PRIVATE - int_f + Libint2::fortran ) add_test( # Test #14 NAME libint2/fortran_example/build @@ -284,7 +284,7 @@ if (LIBINT2_ENABLE_FORTRAN) PRIVATE $,Libint2::int2-cxx,Libint2::cxx> # N.B. cxx compiled library if LIBINT2_REQUIRE_CXX_API_COMPILED=ON else header-only library - int_f + Libint2::fortran ) add_test( # Test #16 NAME libint2/fortran_test/build diff --git a/src/lib/libint/CMakeLists.txt b/src/lib/libint/CMakeLists.txt index 5cfc69e45..827b33cd7 100644 --- a/src/lib/libint/CMakeLists.txt +++ b/src/lib/libint/CMakeLists.txt @@ -171,6 +171,9 @@ else() # Note: not handling CMAKE_Fortran_COMPILER_ARG1 list(APPEND library_CMAKE_ARGS "-DCMAKE_Fortran_COMPILER=${CMAKE_Fortran_COMPILER}") endif() + if (LIBINT2_ENABLE_FORTRAN AND LIBINT2_INSTALL_FMODDIR) + list(APPEND library_CMAKE_ARGS "-DLIBINT2_INSTALL_FMODDIR=${LIBINT2_INSTALL_FMODDIR}") + endif() ExternalProject_Add( library @@ -222,7 +225,15 @@ else() endif() # install library from ExternalProject staging area into CMAKE_INSTALL_PREFIX - foreach(_dir ${CMAKE_INSTALL_INCLUDEDIR} ${CMAKE_INSTALL_LIBDIR} ${CMAKE_INSTALL_DATADIR}) + # N.B. LIBINT2_INSTALL_FMODDIR defaults to CMAKE_INSTALL_INCLUDEDIR but a packager + # may point it outside the three dirs below (e.g. lib64/gfortran/modules while + # CMAKE_INSTALL_LIBDIR=lib), in which case the staged modules need their own pass + set(_stage_dirs ${CMAKE_INSTALL_INCLUDEDIR} ${CMAKE_INSTALL_LIBDIR} ${CMAKE_INSTALL_DATADIR}) + if (LIBINT2_ENABLE_FORTRAN AND LIBINT2_INSTALL_FMODDIR) + list(APPEND _stage_dirs ${LIBINT2_INSTALL_FMODDIR}) + endif() + list(REMOVE_DUPLICATES _stage_dirs) + foreach(_dir ${_stage_dirs}) install( DIRECTORY "${LIBRARY_INSTALL_STAGE_DIR}/${_dir}/" DESTINATION "${_dir}" From ebf6fe9b424c8abec407766e0324a53dd52cb270 Mon Sep 17 00:00:00 2001 From: SY Wang Date: Fri, 14 Aug 2026 06:43:28 +0800 Subject: [PATCH 3/5] Enable PIC always --- export/CMakeLists.txt.export | 37 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/export/CMakeLists.txt.export b/export/CMakeLists.txt.export index 18a93d6db..f524a2998 100644 --- a/export/CMakeLists.txt.export +++ b/export/CMakeLists.txt.export @@ -318,7 +318,19 @@ if (LIBINT2_REQUIRE_CXX_API_COMPILED) endif() -# plan shared, static, or both, then set fpic accordingly +if (TARGET int-cxx-obj) + set(tgts int-obj int-cxx-obj) +else() + set(tgts int-obj) +endif() +set_target_properties( + ${tgts} + PROPERTIES + POSITION_INDEPENDENT_CODE ON +) + + +# ==== 6 user targets: plain/C++(headers)/C++(compiled) shared/static ========= if (LIBINT2_BUILD_SHARED_AND_STATIC_LIBS OR BUILD_SHARED_LIBS) set(L2_BUILD_SHARED_LIBS 1) @@ -326,22 +338,6 @@ endif() if (LIBINT2_BUILD_SHARED_AND_STATIC_LIBS OR (NOT BUILD_SHARED_LIBS)) set(L2_BUILD_STATIC_LIBS 1) endif() -if (L2_BUILD_SHARED_LIBS OR (LIBINT2_ENABLE_PYTHON AND NOT MSVC)) - if (TARGET int-cxx-obj) - set(tgts int-obj int-cxx-obj) - else() - set(tgts int-obj) - endif() - - set_target_properties( - ${tgts} - PROPERTIES - POSITION_INDEPENDENT_CODE 1 - ) -endif() - - -# ==== 6 user targets: plain/C++(headers)/C++(compiled) shared/static ========= set(export_properties "Libint2_VERSION" @@ -696,13 +692,8 @@ if (LIBINT2_ENABLE_FORTRAN) libint_f PROPERTIES Fortran_MODULE_DIRECTORY ${PROJECT_BINARY_DIR}/${BUILDTREE_FMODDIR} + POSITION_INDEPENDENT_CODE ON ) - # N.B. use L2_BUILD_SHARED_LIBS (set above from LIBINT2_BUILD_SHARED_AND_STATIC_LIBS - # or BUILD_SHARED_LIBS), same as int-obj, since these objects end up in the - # installed int_f archive that may be linked against the shared libint2 - if (L2_BUILD_SHARED_LIBS) - set_target_properties(libint_f PROPERTIES POSITION_INDEPENDENT_CODE 1) - endif() target_include_directories( libint_f PUBLIC From 46863f73ade2b4d2204ffe2c8ca2765c1ac11a09 Mon Sep 17 00:00:00 2001 From: SY Wang Date: Sat, 15 Aug 2026 23:10:45 +0800 Subject: [PATCH 4/5] CMake: Unify exported Libint2 targets No longer export `int2-static` and `int2-shared`; only export `Libint2::int2` as public target, consistent with INSTALL.md --- cmake/libint2-config.cmake.in | 28 +------- export/CMakeLists.txt.export | 120 ++++++++++++++++++++-------------- 2 files changed, 72 insertions(+), 76 deletions(-) diff --git a/cmake/libint2-config.cmake.in b/cmake/libint2-config.cmake.in index 244d31e2a..d53ca3af7 100644 --- a/cmake/libint2-config.cmake.in +++ b/cmake/libint2-config.cmake.in @@ -99,35 +99,11 @@ endforeach() # rather than from configure-time options # Import library targets -if(NOT TARGET ${L2}::int-shared AND NOT TARGET ${L2}::int-static) +if(NOT TARGET ${L2}::int2) include("${CMAKE_CURRENT_LIST_DIR}/${pnv}-targets.cmake") endif() -# Create convenience aliases matching the build-tree names -if (TARGET ${L2}::int-shared) - if (NOT TARGET ${L2}::int2) - add_library(${L2}::int2 ALIAS ${L2}::int-shared) - endif() -elseif (TARGET ${L2}::int-static) - if (NOT TARGET ${L2}::int2) - add_library(${L2}::int2 ALIAS ${L2}::int-static) - endif() -endif() - -if (TARGET ${L2}::int-cxx-headeronly-shared) - if (NOT TARGET ${L2}::cxx) - add_library(${L2}::cxx ALIAS ${L2}::int-cxx-headeronly-shared) - endif() -elseif (TARGET ${L2}::int-cxx-headeronly-static) - if (NOT TARGET ${L2}::cxx) - add_library(${L2}::cxx ALIAS ${L2}::int-cxx-headeronly-static) - endif() -endif() - -if (TARGET ${L2}::int_f) - if (NOT TARGET ${L2}::fortran) - add_library(${L2}::fortran ALIAS ${L2}::int_f) - endif() +if (TARGET ${L2}::fortran) set(${L2}_fortran_FOUND 1) endif() diff --git a/export/CMakeLists.txt.export b/export/CMakeLists.txt.export index f524a2998..be54a8947 100644 --- a/export/CMakeLists.txt.export +++ b/export/CMakeLists.txt.export @@ -585,41 +585,47 @@ endif (L2_BUILD_STATIC_LIBS) # ==== aliases ================================================================ -# permanent aliases -# * used for tests - +# Select one canonical implementation for the public CMake API. When both +# shared and static libraries are built, keep the static variant as an +# additional artifact rather than exposing linkage-specific imported targets. if (L2_BUILD_SHARED_LIBS) - add_library(${L2}::int2 ALIAS int-shared) + set(_int_target int-shared) if (LIBINT2_REQUIRE_CXX_API) - add_library(${L2}::cxx ALIAS int-cxx-headeronly-shared) + set(_cxx_target int-cxx-headeronly-shared) if (LIBINT2_REQUIRE_CXX_API_COMPILED) - add_library(${L2}::int2-cxx ALIAS int-cxx-shared) + set(_cxx_compiled_target int-cxx-shared) endif() endif() elseif (L2_BUILD_STATIC_LIBS) - add_library(${L2}::int2 ALIAS int-static) + set(_int_target int-static) if (LIBINT2_REQUIRE_CXX_API) - add_library(${L2}::cxx ALIAS int-cxx-headeronly-static) + set(_cxx_target int-cxx-headeronly-static) if (LIBINT2_REQUIRE_CXX_API_COMPILED) - add_library(${L2}::int2-cxx ALIAS int-cxx-static) + set(_cxx_compiled_target int-cxx-static) endif() endif() +else() + message(FATAL_ERROR "Neither shared nor static Libint library is enabled") endif() -# legacy (pre-2.9.0) aliases +set_target_properties(${_int_target} PROPERTIES EXPORT_NAME int2) +add_library(${L2}::int2 ALIAS ${_int_target}) -if (L2_BUILD_SHARED_LIBS) - add_library(libint2 ALIAS int-shared) - if (LIBINT2_REQUIRE_CXX_API) - add_library(libint2_cxx ALIAS int-cxx-headeronly-shared) - endif() -elseif (L2_BUILD_STATIC_LIBS) - add_library(libint2 ALIAS int-static) - if (LIBINT2_REQUIRE_CXX_API) - add_library(libint2_cxx ALIAS int-cxx-headeronly-static) +if (LIBINT2_REQUIRE_CXX_API) + set_target_properties(${_cxx_target} PROPERTIES EXPORT_NAME cxx) + add_library(${L2}::cxx ALIAS ${_cxx_target}) + if (LIBINT2_REQUIRE_CXX_API_COMPILED) + set_target_properties(${_cxx_compiled_target} PROPERTIES EXPORT_NAME int2-cxx) + add_library(${L2}::int2-cxx ALIAS ${_cxx_compiled_target}) endif() endif() +# legacy (pre-2.9.0) aliases +add_library(libint2 ALIAS ${_int_target}) +if (LIBINT2_REQUIRE_CXX_API) + add_library(libint2_cxx ALIAS ${_cxx_target}) +endif() + # ==== Fortran bindings ======================================================= @@ -703,13 +709,14 @@ if (LIBINT2_ENABLE_FORTRAN) $ ) - add_library(int_f STATIC $) - set_target_properties(int_f PROPERTIES OUTPUT_NAME "int2_f") - if (L2_BUILD_SHARED_LIBS) - target_link_libraries(int_f INTERFACE int-shared) - else() - target_link_libraries(int_f INTERFACE int-static) - endif() + add_library(int_f $) + set_target_properties( + int_f + PROPERTIES + OUTPUT_NAME "int2_f" + EXPORT_NAME fortran + ) + target_link_libraries(int_f INTERFACE ${_int_target}) target_include_directories( int_f INTERFACE @@ -723,8 +730,6 @@ if (LIBINT2_ENABLE_FORTRAN) # permanent alias, so that consuming code can use the same target name # whether libint2 is found or added as a subproject. - # N.B. the install-tree counterpart is created - # in cmake/libint2-config.cmake.in, same as for ${L2}::int2 and ${L2}::cxx add_library(${L2}::fortran ALIAS int_f) # Fortran tests merged into rest of tests @@ -752,14 +757,8 @@ configure_package_config_file( # <<< Install >>> -# install library targets -set(_libint2_install_targets) -if (L2_BUILD_SHARED_LIBS) - list(APPEND _libint2_install_targets int-shared) -endif() -if (L2_BUILD_STATIC_LIBS) - list(APPEND _libint2_install_targets int-static) -endif() +# install public library targets +set(_libint2_install_targets ${_int_target}) if (LIBINT2_ENABLE_FORTRAN) list(APPEND _libint2_install_targets int_f) endif() @@ -772,6 +771,22 @@ install( ARCHIVE DESTINATION "${LIBINT2_INSTALL_LIBDIR}" ) +# If both linkage variants are requested, install the non-canonical library as +# an additional artifact without adding a linkage-specific imported target. +if (L2_BUILD_SHARED_LIBS AND L2_BUILD_STATIC_LIBS) + if (_int_target STREQUAL "int-shared") + set(_int_secondary_target int-static) + else() + set(_int_secondary_target int-shared) + endif() + install( + TARGETS ${_int_secondary_target} + RUNTIME DESTINATION "${LIBINT2_INSTALL_BINDIR}" + LIBRARY DESTINATION "${LIBINT2_INSTALL_LIBDIR}" + ARCHIVE DESTINATION "${LIBINT2_INSTALL_LIBDIR}" + ) +endif() + # install public API headers from source tree # only install libint2.h, libint2.hpp at include/ root # and the libint2/ subdirectory (C++ API headers) @@ -841,23 +856,28 @@ install( # CXX API targets if (LIBINT2_REQUIRE_CXX_API) - set(_cxx_targets) - if (L2_BUILD_SHARED_LIBS) - list(APPEND _cxx_targets int-cxx-headeronly-shared) - if (LIBINT2_REQUIRE_CXX_API_COMPILED) - list(APPEND _cxx_targets int-cxx-shared) - endif() + set(_cxx_targets ${_cxx_target}) + if (LIBINT2_REQUIRE_CXX_API_COMPILED) + list(APPEND _cxx_targets ${_cxx_compiled_target}) endif() - if (L2_BUILD_STATIC_LIBS) - list(APPEND _cxx_targets int-cxx-headeronly-static) - if (LIBINT2_REQUIRE_CXX_API_COMPILED) - list(APPEND _cxx_targets int-cxx-static) + install( + TARGETS ${_cxx_targets} + EXPORT ${pnv}-targets + RUNTIME DESTINATION "${LIBINT2_INSTALL_BINDIR}" + LIBRARY DESTINATION "${LIBINT2_INSTALL_LIBDIR}" + ARCHIVE DESTINATION "${LIBINT2_INSTALL_LIBDIR}" + ) + + # Preserve the additional compiled artifact in dual-linkage builds without + # exposing another public CMake target. + if (LIBINT2_REQUIRE_CXX_API_COMPILED AND L2_BUILD_SHARED_LIBS AND L2_BUILD_STATIC_LIBS) + if (_cxx_compiled_target STREQUAL "int-cxx-shared") + set(_cxx_secondary_target int-cxx-static) + else() + set(_cxx_secondary_target int-cxx-shared) endif() - endif() - if (_cxx_targets) install( - TARGETS ${_cxx_targets} - EXPORT ${pnv}-targets + TARGETS ${_cxx_secondary_target} RUNTIME DESTINATION "${LIBINT2_INSTALL_BINDIR}" LIBRARY DESTINATION "${LIBINT2_INSTALL_LIBDIR}" ARCHIVE DESTINATION "${LIBINT2_INSTALL_LIBDIR}" From d8280e8569fdef1bcb4b82924dc18d2b0f0c5dae Mon Sep 17 00:00:00 2001 From: SY Wang Date: Sat, 15 Aug 2026 23:19:12 +0800 Subject: [PATCH 5/5] Try to fix workflows --- .github/workflows/cmake.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index a6b861416..a1a0893aa 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -97,8 +97,9 @@ jobs: - name: Install prerequisite MacOS packages if: ${{ steps.skip_check.outputs.should_skip != 'true' && matrix.os == 'macos-15' }} run: | - brew install ninja gcc@11 gmp boost eigen@3 bison ccache automake python - echo "FC=/opt/homebrew/Cellar/gcc@11/11.5.0/bin/gfortran-11" >> $GITHUB_ENV + brew untap aws/tap || true + brew install ninja gcc gmp boost eigen@3 bison ccache automake python + echo "FC=$(brew --prefix gcc)/bin/gfortran" >> $GITHUB_ENV /opt/homebrew/bin/pip3 install --break-system-packages pytest numpy scipy scikit-image /opt/homebrew/bin/pip3 show pytest numpy scipy scikit-image @@ -217,6 +218,7 @@ jobs: libargs: > -D BUILD_SHARED_LIBS=ON -D LIBINT2_ENABLE_FORTRAN=ON + -D CMAKE_EXE_LINKER_FLAGS="-Wl,-rpath-link,${CONDA_PREFIX}/lib" testargs: "" - runs-on: windows-latest @@ -324,7 +326,6 @@ jobs: -B build \ -G Ninja \ -D CMAKE_INSTALL_PREFIX="${{github.workspace}}/installed" \ - -D CMAKE_CXX_COMPILER=${CXX} \ -D LIBINT2_REQUIRE_CXX_API_COMPILED=ON \ -D LIBINT2_ENABLE_PYTHON=ON \ -D CMAKE_PREFIX_PATH="${CONDA_PREFIX}" \