diff --git a/.github/workflows/ci_cmake.yml b/.github/workflows/ci_cmake.yml deleted file mode 100644 index 219988e7d..000000000 --- a/.github/workflows/ci_cmake.yml +++ /dev/null @@ -1,122 +0,0 @@ -name: BuildCM - -on: - push: - branches: - - master - pull_request: - -jobs: - build_repo: - strategy: - fail-fast: false - matrix: - build_type : [ Release, Debug ] - os : [ macos-latest, ubuntu-24.04 ] - include: - - os: ubuntu-24.04 - cxx: g++ - cc: gcc - - os: macos-latest - cxx: clang++ - cc: clang - - name: "Repo • ${{ matrix.os }}: ${{ matrix.cxx }} ${{ matrix.build_type }}" - runs-on: ${{ matrix.os }} - env: - CC: ${{ matrix.cc }} - CXX : ${{ matrix.cxx }} - CCACHE_DIR : ${{github.workspace}}/build/.ccache - CCACHE_COMPRESS : true - CCACHE_COMPRESSLEVEL : 6 - BUILD_CONFIG : > - -G Ninja - -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} - -DBUILD_SHARED_LIBS=OFF - -DMPIEXEC_PREFLAGS='--bind-to;none;--allow-run-as-root' - -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/build/library - -DWITH_MAX_AM=2;2 - -DWITH_ERI_MAX_AM=2;2 - -DWITH_ERI3_MAX_AM=3;2 - -DENABLE_ERI=1 - -DENABLE_ERI3=1 - -DENABLE_ONEBODY=1 - -DDISABLE_ONEBODY_PROPERTY_DERIVS=ON - -DMULTIPOLE_MAX_ORDER=2 - -DLIBINT2_ENABLE_PYTHON=ON - - outputs: - should_skip: ${{ steps.skip_check.outputs.should_skip }} - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - # fetch-depth: 0 for git history to compute version - - - id: skip_check - name: Check if can skip - uses: fkirc/skip-duplicate-actions@v5 - with: - cancel_others: 'true' - - - name: Create Build Environment - if: ${{ steps.skip_check.outputs.should_skip != 'true' }} - # Some projects don't allow in-source building, so create a separate build directory - # We'll use this as our working directory for all subsequent commands - run: | - cmake -E make_directory ${{github.workspace}}/build/compiler - cmake -E make_directory ${{github.workspace}}/build/library - cmake -E make_directory ${{github.workspace}}/build/library_test - - - name: Install prerequisite MacOS packages - if: ${{ steps.skip_check.outputs.should_skip != 'true' && matrix.os == 'macos-latest' }} - run: | - brew install ninja gcc@11 gmp boost eigen bison ccache automake python@3.11 numpy scipy - echo "FC=/opt/homebrew/Cellar/gcc@11/11.5.0/bin/gfortran-11" >> $GITHUB_ENV - echo "EIGEN3_INCLUDE_DIR=/usr/local/include/eigen3" >> $GITHUB_ENV - pip3.11 install scipy scikit-build-core build pytest - - - name: Install prerequisite Ubuntu packages - if: ${{ steps.skip_check.outputs.should_skip != 'true' && matrix.os == 'ubuntu-24.04' }} - run: | - sudo apt-get update - sudo apt-get install ninja-build gfortran liblapack-dev libboost-dev libeigen3-dev ccache python3-numpy python3-scipy python3-pip - pip3 install --break-system-packages scikit-build-core build pytest - echo "FC=/usr/bin/gfortran" >> $GITHUB_ENV - echo "EIGEN3_INCLUDE_DIR=/usr/include/eigen3" >> $GITHUB_ENV - - - name: Prepare ccache timestamp - if: ${{ steps.skip_check.outputs.should_skip != 'true' }} - id: ccache_cache_timestamp - shell: cmake -P {0} - run: | - string(TIMESTAMP current_date "%Y-%m-%d-%H;%M;%S" UTC) - message("\"timestamp=${current_date}\" >> $GITHUB_OUTPUT") - - - name: Setup ccache cache files - if: ${{ steps.skip_check.outputs.should_skip != 'true' }} - uses: actions/cache@v3 - with: - path: ${{github.workspace}}/build/.ccache - key: ${{ matrix.config.name }}-ccache-${{ steps.ccache_cache_timestamp.outputs.timestamp }} - restore-keys: | - ${{ matrix.config.name }}-ccache- - - - name: Generate Libint generator - if: ${{ steps.skip_check.outputs.should_skip != 'true' }} - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash - working-directory: ${{github.workspace}}/build/compiler - run: | - git describe --tags - cmake -S ../.. -B build $BUILD_CONFIG --log-level=DEBUG - cmake --build build --target check-libint2compiler - - - name: Generate Libint library - if: ${{ steps.skip_check.outputs.should_skip != 'true' }} - shell: bash - working-directory: ${{github.workspace}}/build/compiler - run: | - cmake --build build --target libint-library-generate diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index e650d3f28..4437ceb76 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -13,15 +13,35 @@ jobs: matrix: build_type : [ Release, Debug ] os : [ macos-latest, ubuntu-24.04 ] + subproject : [ ON, OFF ] + exclude: + - build_type: Release + subproject: ON include: - os: ubuntu-24.04 cxx: g++ cc: gcc + compressor: gzip - os: macos-latest cxx: clang++ cc: clang - - name: "Repo • ${{ matrix.os }}: ${{ matrix.cxx }} ${{ matrix.build_type }}" + compressor: bzip2 + - build_type: Debug + build_shared_libs: OFF + do_fortran: ON + - build_type: Release + build_shared_libs: ON + os: ubuntu-24.04 + do_fortran: ON + - build_type: Release + build_shared_libs: ON + os: macos-latest + do_fortran: OFF + # someday when mac+fortran+shared is fixed (plus universal do_fortran: ON) + #- build_type: Release + # build_shared_libs: ON + + name: "Repo • ${{ matrix.os }}: ${{ matrix.cxx }} ${{ matrix.build_type }} shared=${{ matrix.build_shared_libs }} fetch=${{ matrix.subproject }}" runs-on: ${{ matrix.os }} env: CC: ${{ matrix.cc }} @@ -31,19 +51,31 @@ jobs: CCACHE_COMPRESSLEVEL : 6 BUILD_CONFIG : > -G Ninja - -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} - -DCMAKE_PREFIX_PATH=/usr/local/Cellar/eigen/3.3.9;/usr/local/opt/bison - -DBUILD_SHARED_LIBS=OFF - -DCMAKE_POSITION_INDEPENDENT_CODE=ON - -DMPIEXEC_PREFLAGS='--bind-to;none;--allow-run-as-root' - -DENABLE_FORTRAN=ON - -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/build/library/install - -DPython_EXECUTABLE=${{ matrix.os == 'macos-latest' && '/usr/local/Frameworks/Python.framework/Versions/3.11/bin/python3.11' || '/usr/bin/python3' }} + -D CMAKE_BUILD_TYPE=${{ matrix.build_type }} + -D BUILD_SHARED_LIBS=${{ matrix.build_shared_libs }} + -D LIBINT_BUILD_LIBRARY_AS_SUBPROJECT=${{ matrix.subproject }} + -D CMAKE_INSTALL_PREFIX=${{github.workspace}}/build/library + -D WITH_MAX_AM=2;2 + -D WITH_ERI_MAX_AM=2;2 + -D WITH_ERI3_MAX_AM=3;2 + -D ENABLE_ERI=1 + -D ENABLE_ERI3=1 + -D ENABLE_ONEBODY=1 + -D DISABLE_ONEBODY_PROPERTY_DERIVS=ON + -D MULTIPOLE_MAX_ORDER=2 + -D LIBINT2_REQUIRE_CXX_API_COMPILED=ON + -D LIBINT2_ENABLE_FORTRAN=${{ matrix.do_fortran }} + -D LIBINT2_ENABLE_PYTHON=ON + -D EXPORT_COMPRESSOR=${{ matrix.compressor }} + outputs: should_skip: ${{ steps.skip_check.outputs.should_skip }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + # fetch-depth: 0 for git history to compute version - id: skip_check name: Check if can skip @@ -53,8 +85,6 @@ jobs: - name: Create Build Environment if: ${{ steps.skip_check.outputs.should_skip != 'true' }} - # Some projects don't allow in-source building, so create a separate build directory - # We'll use this as our working directory for all subsequent commands run: | cmake -E make_directory ${{github.workspace}}/build/compiler cmake -E make_directory ${{github.workspace}}/build/library @@ -63,21 +93,12 @@ jobs: - name: Install prerequisite MacOS packages if: ${{ steps.skip_check.outputs.should_skip != 'true' && matrix.os == 'macos-latest' }} run: | - brew install ninja gcc@11 gmp boost eigen bison ccache automake python@3.11 numpy scipy - #echo "FC=/usr/local/bin/gfortran" >> $GITHUB_ENV + brew install ninja gcc@11 gmp boost eigen bison ccache automake python@3.13 numpy scipy scikit-image pytest echo "FC=/opt/homebrew/Cellar/gcc@11/11.5.0/bin/gfortran-11" >> $GITHUB_ENV echo "EIGEN3_INCLUDE_DIR=/usr/local/include/eigen3" >> $GITHUB_ENV - echo "GMP_INCLUDE_DIR=/opt/homebrew/Cellar/gmp/6.3.0/include" >> $GITHUB_ENV - echo "GMP_LIBRARY_DIR=/opt/homebrew/Cellar/gmp/6.3.0/lib" >> $GITHUB_ENV - echo "BOOST_INCLUDE_DIR=/opt/homebrew/Cellar/boost/1.89.0/include" >> $GITHUB_ENV - ls -l /opt/homebrew/Cellar/boost/1.89.0/include - brew info python@3.11 - ls -l /opt/homebrew/Cellar/python@3.11/* - brew info gcc@11 - ls -l /opt/homebrew/Cellar/gcc@11/*/bin - pip3.11 install scipy scikit-build-core build pytest + pip3.13 show pytest || pip3.13 install --break-system-packages pytest - - name: Install prerequisites Ubuntu packages + - name: Install prerequisite Ubuntu packages if: ${{ steps.skip_check.outputs.should_skip != 'true' && matrix.os == 'ubuntu-24.04' }} run: | sudo apt-get update @@ -103,104 +124,56 @@ jobs: restore-keys: | ${{ matrix.config.name }}-ccache- - - name: Generate configure script - if: ${{ steps.skip_check.outputs.should_skip != 'true' }} - shell: bash - working-directory: ${{github.workspace}} - run: ./autogen.sh && ls -l ${{github.workspace}}/configure - - - name: Generate Libint library + - name: Build Libint generator if: ${{ steps.skip_check.outputs.should_skip != 'true' }} # Use a bash shell so we can use the same syntax for environment variable # access regardless of the host operating system shell: bash working-directory: ${{github.workspace}}/build/compiler run: | - if [[ "${{ matrix.os }}" == "ubuntu-24.04" ]]; then - : - CPPFLAGS="-I$EIGEN3_INCLUDE_DIR" CXXFLAGS="-std=c++11 -Wno-enum-compare" ${{github.workspace}}/configure --with-max-am=2,1 --with-eri-max-am=2,2 --with-eri3-max-am=3,2 --with-eri2-max-am=3,2 --enable-eri=1 --enable-eri3=1 --enable-eri2=0 --enable-1body=1 --disable-1body-property-derivs --with-multipole-max-order=2 + git describe --tags + cmake -S ../.. -B build $BUILD_CONFIG --log-level=DEBUG + cmake --build build --target check-libint2compiler - fi - if [[ "${{ matrix.os }}" == "macos-latest" ]]; then - : - LDFLAGS="-L$GMP_LIBRARY_DIR" CPPFLAGS="-I$EIGEN3_INCLUDE_DIR -I$BOOST_INCLUDE_DIR -I$GMP_INCLUDE_DIR" CXXFLAGS="-std=c++11 -Wno-enum-compare" ${{github.workspace}}/configure --with-max-am=2,1 --with-eri-max-am=2,2 --with-eri3-max-am=3,2 --with-eri2-max-am=3,2 --enable-eri=1 --enable-eri3=1 --enable-eri2=0 --enable-1body=1 --disable-1body-property-derivs --with-multipole-max-order=2 - - fi - make -j3 - make check - cd src/bin/test_eri && ./stdtests.pl && cd ../../.. - make export - echo "ARTIFACT=`ls -1 libint*tgz`" >> $GITHUB_ENV + - name: Generate Libint library tarball + if: ${{ steps.skip_check.outputs.should_skip != 'true' }} + shell: bash + working-directory: ${{github.workspace}}/build/compiler + run: | + cmake --build build --target export + cd build && echo "ARTIFACT=`ls -1 libint*z*`" >> $GITHUB_ENV - - name: Archive Library Tarball - if: ${{ steps.skip_check.outputs.should_skip != 'true' && matrix.build_type == 'Release'}} + - name: Archive Libint library tarball + if: ${{ steps.skip_check.outputs.should_skip != 'true' && matrix.build_type == 'Release' }} uses: actions/upload-artifact@v4.4.0 with: if-no-files-found: error name: ${{ runner.os }}-${{ matrix.cxx }} - path: ${{github.workspace}}/build/compiler/${{ env.ARTIFACT }} + path: ${{github.workspace}}/build/compiler/build/${{ env.ARTIFACT }} retention-days: 1 - - name: Build+test+install Libint library - if: ${{ steps.skip_check.outputs.should_skip != 'true' }} + - name: Build Libint library (FetchContent=${{ matrix.subproject }}) + if: ${{ steps.skip_check.outputs.should_skip }} shell: bash - working-directory: ${{github.workspace}}/build/library - run: | - tar -xzf ../compiler/libint-2*.tgz - ls -l libint-2* - echo libint-2* | cut -d'-' -f2 | awk '{print "LIBINT_VERSION=" $0}' >> $GITHUB_ENV - echo LIBINT_VERSION=$LIBINT_VERSION - cd libint-2* - echo "LIBINT_EXPORTED_DIR=`pwd`" >> $GITHUB_ENV - if [[ "${{ matrix.os }}" == "macos-latest" ]]; then - cmake -S . -B build -DCMAKE_BUILD_TYPE=$BUILD_TYPE $BUILD_CONFIG -DPython_EXECUTABLE=/opt/homebrew/bin/python3.11 - else - cmake -S . -B build -DCMAKE_BUILD_TYPE=$BUILD_TYPE $BUILD_CONFIG - fi - cmake --build build --target check - cmake --build build --target install + working-directory: ${{github.workspace}}/build/compiler + run: cmake --build build - - name: Test built/installed Libint library + - name: Test Libint library - unit tests if: ${{ steps.skip_check.outputs.should_skip != 'true' }} shell: bash - working-directory: ${{github.workspace}}/build/library_test - run: | - cat > CMakeLists.txt < - -DBUILD_SHARED_LIBS=ON + -D BUILD_SHARED_LIBS=ON + -D LIBINT2_ENABLE_FORTRAN=ON testargs: "" - # note full paths depend on setup-miniconda: - # * Miniforge is miniconda3 vs. Miniconda is miniconda - runs-on: windows-latest lane: windows-clang-cl libargs: > - -GNinja - -DCMAKE_BUILD_TYPE=Release - -DBUILD_SHARED_LIBS=OFF - -DCMAKE_CXX_COMPILER=clang-cl - -DCMAKE_C_COMPILER=clang-cl - -DCMAKE_CXX_FLAGS="/source-charset:utf-8 /execution-charset:utf-8 /DUNICODE /D_UNICODE" + -G Ninja + -D CMAKE_BUILD_TYPE=Release + -D BUILD_SHARED_LIBS=OFF + -D CMAKE_CXX_COMPILER=clang-cl + -D CMAKE_C_COMPILER=clang-cl testargs: > - -GNinja - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_CXX_COMPILER=clang-cl - -DCMAKE_C_COMPILER=clang-cl + -G Ninja + -D CMAKE_BUILD_TYPE=Release + -D CMAKE_CXX_COMPILER=clang-cl + -D CMAKE_C_COMPILER=clang-cl - runs-on: macos-latest lane: macos-clang libargs: > - -DBUILD_SHARED_LIBS=ON + -D BUILD_SHARED_LIBS=OFF + -D LIBINT2_ENABLE_FORTRAN=ON + # return to shared when mac+fortran+shared is fixed testargs: "" - runs-on: ubuntu-latest lane: ubuntu-intel libargs: > - -DCMAKE_CXX_COMPILER=icpx - -DCMAKE_CXX_FLAGS="--gcc-toolchain=${CONDA_PREFIX} --sysroot=${CONDA_PREFIX}/${HOST}/sysroot -target ${HOST}" + -D CMAKE_CXX_COMPILER=icpx + -D CMAKE_CXX_FLAGS="--gcc-toolchain=${CONDA_PREFIX} --sysroot=${CONDA_PREFIX}/${HOST}/sysroot -target ${HOST}" testargs: > - -DCMAKE_CXX_COMPILER=icpx - -DCMAKE_CXX_FLAGS="--gcc-toolchain=${CONDA_PREFIX} --sysroot=${CONDA_PREFIX}/${HOST}/sysroot -target ${HOST}" + -D CMAKE_CXX_COMPILER=icpx + -D CMAKE_CXX_FLAGS="--gcc-toolchain=${CONDA_PREFIX} --sysroot=${CONDA_PREFIX}/${HOST}/sysroot -target ${HOST}" name: "Export • ${{ matrix.cfg.lane }}" runs-on: ${{ matrix.cfg.runs-on }} @@ -251,6 +224,10 @@ jobs: steps: # Note we're not checking out the repo. All src from Linux tarball generated above. + - uses: actions/download-artifact@v4.1.7 + with: + name: Linux-g++ + - name: Write a Conda Env File shell: bash -l {0} run: | @@ -262,19 +239,20 @@ jobs: - cmake - ninja - cxx-compiler + - fortran-compiler - python - boost - eigen - numpy - scipy - - pybind11 - - scikit-build-core - - build + - scikit-image - pytest + - pybind11 #- dpcpp_linux-64 EOF if [[ "${{ runner.os }}" == "Windows" ]]; then sed -i "s/- cxx/#- cxx/g" export.yaml + sed -i "s/- fortran/#- fortran/g" export.yaml fi if [[ "${{ matrix.cfg.lane }}" == "ubuntu-intel" ]]; then sed -i "s/#- dpcpp_linux-64/- dpcpp_linux-64/g" export.yaml @@ -304,23 +282,20 @@ jobs: with: arch: x64 - - uses: actions/download-artifact@v4.1.7 - with: - name: Linux-g++ - - name: Extract, Build, Install Libint Library shell: bash -l {0} run: | tar -zxf libint*tgz mkdir libint && mv libint-2*/* libint/ && cd libint/ cmake \ - -S. \ - -Bbuild \ - -GNinja \ - -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/installed" \ - -DCMAKE_CXX_COMPILER=${CXX} \ - -DLIBINT2_PYTHON=ON \ - -DCMAKE_PREFIX_PATH="${CONDA_PREFIX}" \ + -S . \ + -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}" \ ${{ matrix.cfg.libargs }} cmake --build build --target install libint2-python-test @@ -329,32 +304,3 @@ jobs: working-directory: ${{github.workspace}}/libint/build run: | cmake --build . --target check - - - name: Test Libint library - consume installation for SCF [from build+install] - shell: bash -l {0} - run: | - mkdir test_installed_library && cd test_installed_library - cat > CMakeLists.txt <angstrom conversion factor + +- 2025-05-14: 2.11.1 + - PR #369: gcc-15 produced incorrect exponential core integrals + - PR #367: can build/run tests in compiler tree even if build only shared libraries + - PR #366: build fixup for gcc-15 and clang-21 (HT @parona-source) + - 2025-04-24: 2.11.0 - PR #364: fix eritest segfaults with atypical L combinations - PR #365: use Gaussian fit of Slater geminal for exceptional parameter values diff --git a/CITATION b/CITATION index a790f8d8a..1d8ecd18d 100644 --- a/CITATION +++ b/CITATION @@ -18,7 +18,7 @@ The literature citation for the present version in bibtex format is: author = "E.~F.~Valeev", title = "Libint: A library for the evaluation of molecular integrals of many-body operators over Gaussian functions", howpublished = "http://libint.valeyev.net/", - note = "version 2.10.2", + note = "version 2.11.2", year = 2025 } diff --git a/CMakeLists.txt b/CMakeLists.txt index ae03fa5e8..fc9074829 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,9 @@ cmake_minimum_required(VERSION 3.19) # string(json cmake_policy(SET CMP0074 NEW) -if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0") +if (POLICY CMP0135) # Avoid warning about DOWNLOAD_EXTRACT_TIMESTAMP in CMake 3.24: cmake_policy(SET CMP0135 NEW) -endif() -if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.25.0") - # needed by DynamicVersion - cmake_policy(SET CMP0140 NEW) -endif() +endif () ############################# Version and Metadata ############################# @@ -17,10 +13,13 @@ include(DynamicVersion) dynamic_version( PROJECT_PREFIX Libint2Compiler_ GIT_ARCHIVAL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/.git_archival.txt + VERSION_FULL_MODE POST OUTPUT_COMMIT LibintRepository_COMMIT OUTPUT_VERSION LibintRepository_VERSION OUTPUT_DESCRIBE LibintRepository_DESCRIBE OUTPUT_DISTANCE LibintRepository_DISTANCE + OUTPUT_SHORT_HASH LibintRepository_SHORT_HASH + OUTPUT_VERSION_FULL LibintRepository_VERSION_FULL ) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build.") # foil Ninja Debug on Windows @@ -104,16 +103,26 @@ message(STATUS "Building using CMake ${CMAKE_VERSION} Generator ${CMAKE_GENERATO option_with_default(CMAKE_BUILD_TYPE "Build type (Release or Debug)" Release) ### compiler-only +option_with_print(LIBINT_BUILD_LIBRARY_AS_SUBPROJECT + "[EXPERT] Build generated library as a subproject: if FALSE will configure and build separately" OFF) ### library-only -option_with_default(LIBINT2_ENABLE_PYTHON +option_with_print(LIBINT2_REQUIRE_CXX_API + "C++11 Libint API: define library targets + test (requires Eigen3, Boost is optional but strongly recommended)" ON) +option_with_print(LIBINT2_REQUIRE_CXX_API_COMPILED + "Build C++11 Compiled (not just header-only) targets (requires Eigen3, Boost strongly recommended)" ON) +option_with_print(LIBINT2_ENABLE_FORTRAN + "Build Fortran03+ Libint interface (requires Fortran)" OFF) +option_with_print(LIBINT2_ENABLE_PYTHON "Build Python bindings (requires Python and Pybind11 and Eigen3)" OFF) -option_with_default(LIBINT2_PREFIX_PYTHON_INSTALL +option_with_print(LIBINT2_PREFIX_PYTHON_INSTALL "For LIBINT2_ENABLE_PYTHON=ON, whether to install the Python module in the Linux manner to CMAKE_INSTALL_PREFIX or to not install it. See target libint2-python-wheel for alternate installation in the Python manner to Python_EXECUTABLE's site-packages." OFF) - +option_with_print(BUILD_SHARED_LIBS + "Build Libint library as shared, not static" OFF) +option_with_print(LIBINT2_BUILD_SHARED_AND_STATIC_LIBS + "Build both shared and static Libint libraries in one shot. Uses -fPIC." OFF) option_with_print(LIBINT2_ENABLE_MPFR "Use GNU MPFR library for high-precision testing (EXPERTS ONLY). Consumed at library build-time." OFF) -## next one defined by `include(CTest)` # <<< Which Integrals Classes, Which Derivative Levels >>> @@ -272,12 +281,13 @@ option_with_print(LIBINT_PROFILE "Turn on profiling instrumentation of the library. (Generated code will require C++11!)" OFF) option_with_print(LIBINT2_ENABLE_MPFR "Use GNU MPFR library for high-precision testing (EXPERTS ONLY). Consumed at library build-time." OFF) +option_with_default(EXPORT_COMPRESSOR + "Export tarball with compression gzip or bzip2" gzip) # next one defined by `include(CTest)` message(STATUS "Showing option BUILD_TESTING: ${BUILD_TESTING}") # <<< Path >>> - ######################## Process & Validate Options ########################### include(autocmake_safeguards) include(CheckFunctionExists) @@ -309,6 +319,16 @@ booleanize01(LIBINT_ACCUM_INTS) booleanize01(LIBINT_FLOP_COUNT) booleanize01(LIBINT_PROFILE) +if (EXPORT_COMPRESSOR STREQUAL "gzip") + set(EXPORT_COMPRESSOR_CMD "cfz") + set(EXPORT_COMPRESSOR_EXT "tgz") +elseif (EXPORT_COMPRESSOR STREQUAL "bzip2") + set(EXPORT_COMPRESSOR_CMD "jcf") + set(EXPORT_COMPRESSOR_EXT "tbz2") +else() + message(FATAL_ERROR "No valid compressor; invoke CMake with -DEXPORT_COMPRESSOR=gzip|bzip2") +endif() + ################################## Dependencies ################################# diff --git a/INSTALL.md b/INSTALL.md index cc1fa1001..51465d935 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -73,13 +73,21 @@ cmake/ COPYING src/ tests/ ... ### Build Targets -| `--target ...` | incl. | steps | ( | see | above | ) | | (TARBALL) `--target ...` [^25] | -| -------------- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ------------------------------ | +| `--target ...` [^27] | incl. | steps | ( | see | above | ) | | (TARBALL) `--target ...` [^25] | +| -------------------- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ------------------------------ | | `build_libint` | 1 | - | - | - | - | - | - | n/a | | `check-libint2compiler` | 1 | 2 | - | - | - | - | - | n/a | +| `export` | 1 | - | 3 | - | - | - | - | n/a | +| `library` (default) [^26] | 1 | - | 3 | 4 | - | - | - | (default) [^26] | +| `check` | 1 | 2 | 3 | 4 | 5 | - | - | `check` | + +Use combined targets like `cmake --target check install` to avoid some unnecessary rebuilding (esp. of build_libint) that occurs with successive targets. The CMake dependency structure is imperfect. [^25]: (TARBALL) targets can include steps 4 onwards; the starting tarball itself is the product of step 3. +[^26]: See [see "Internal Targets" column in table](#consumption-targets) for individual library targets. + +[^27]: For FetchContent/`LIBINT_BUILD_LIBRARY_AS_SUBPROJECT=ON`, build target `export` aka `libint-library-export`. Then, as a separate command, build further targets like `check` or `install`; target plain `library` is not available. ----------------------------------------------------------------------------- @@ -259,6 +267,9 @@ Note that options, docs, and CMake components are focused on the C++ interface, ### Build Library What (L) (TARBALL) +* `LIBINT2_REQUIRE_CXX_API` - L - Build C++11 Libint API. Define header-only library target and check target (requires Eigen3; Boost recommended; [see prereq line](#prerequisites)). [Default=ON] +* `LIBINT2_REQUIRE_CXX_API_COMPILED` - L - Build C++11 Libint API. Define compiled (not just header-only) targets (requires Eigen3; Boost recommended). [Default=ON] +* `LIBINT2_ENABLE_FORTRAN` - L - Build Fortran03+ module/bindings (requires C and Fortran compilers and Python). [Default=OFF] * `LIBINT2_ENABLE_MPFR` - L - Use MPFR library to test Libint integrals in high precision (requires MPFR; experts only). [Default=OFF] * `LIBINT2_LOCAL_Eigen3_INSTALL` - L - Install an exported target with hard-coded Eigen3 dependency paths. This is potentially useful and important when consuming the compiled C++11 interface library so that the Libint library build and Libint consumer build use the same Eigen3 installation & ABI. This is at most a convenience when consuming the header-only C++11 interface library. See `LIBINT2_LOCAL_Eigen3_FIND`. [Default=OFF] * `LIBINT2_ENABLE_PYTHON` - L - Build Python bindings (requires Python and Eigen3; Boost and pybind11 recommended; [see prereq line](#prerequisites)). Can instead be enabled and built through separate CMake configuration after library build. [Default=OFF] @@ -267,6 +278,9 @@ Note that options, docs, and CMake components are focused on the C++ interface, ### Build Library How (G L) (TARBALL) * `CMAKE_BUILD_TYPE` — G L — [Standard CMake variable](https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html) [Default=Release] +* `BUILD_SHARED_LIBS` — L — Build Libint library as shared, not static. [Standard CMake variable](https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html) [Default=OFF] +* `LIBINT2_BUILD_SHARED_AND_STATIC_LIBS` — L — Build both shared and static Libint libraries in one shot. Uses `-fPIC`. [Default=OFF] +* `LIBINT_BUILD_LIBRARY_AS_SUBPROJECT` — G — If building compiler and library in continuous command, build generated library as a subproject (FetchContent); if OFF will configure and build separately (ExternalProject) (expert only). [Default=OFF] ### Detecting Dependencies (G L C) (TARBALL) @@ -350,6 +364,35 @@ Note that options, docs, and CMake components are focused on the C++ interface, * `LIBINT_FLOP_COUNT` - G - Support (approximate) FLOP counting by the library. (Generated code will require C++11!). [Default=OFF] * `LIBINT_PROFILE` - G - Turn on profiling instrumentation of the library. (Generated code will require C++11!). [Default=OFF] +----------------------------------------------------------------------------- + +# Consuming Libint + + +### Programming to Access Integrals + +* if you use C++11 or later (strongly recommended): read the [Libint Wiki](https://github.com/evaleev/libint/wiki/using-modern-CPlusPlus-API) +* if you use pre-2011 C++, C, Fortran, or any other language, refer to the [Libint Programmer's Manual](https://sourceforge.net/projects/libint/files/libint-for-beginners/progman-2.0.3-stable.pdf/download) for brief information on how to use the library in your code. + + +### Consumption Targets + +| Namespaced Target[^15] | CMake[^16] Component | Built by Default | Ensure Built | Ensure Excluded | Internal Target(s)[^17] | Alias[^18] | +| ---------------------- | -------------------- | ---------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | ------------ | +| | | yes | always | impossible | `int-obj` | | +| `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` | | + +[^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 src/lib/libint/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. + + +----------------------------------------------------------------------------- # GNU Autotools Update Guide @@ -405,14 +448,21 @@ Note that options, docs, and CMake components are focused on the C++ interface, * `--disable-1body-property-derivs` --> `-D DISABLE_ONEBODY_PROPERTY_DERIVS=ON` - +* `--enable-shared` --> `-D BUILD_SHARED=ON` --> `-D BUILD_SHARED_LIBS=ON` (standard CMake variable) +* `--enable-static` --> `-D BUILD_STATIC=ON` --> `-D BUILD_SHARED_LIBS=OFF` (standard CMake variable) +* `--enable-shared --enable-static` --> `-D BUILD_SHARED=ON -D BUILD_STATIC=ON` --> `-D LIBINT2_BUILD_SHARED_AND_STATIC_LIBS=ON` +* `-D REQUIRE_CXX_API=ON` --> `-D ENABLE_CXX11API=ON` --> `-D LIBINT2_REQUIRE_CXX_API=ON` * `--enable-mpfr` --> assumed present --> `-D ENABLE_MPFR=ON` --> `-D LIBINT2_ENABLE_MPFR=ON` +* (target) `libint2` --> `Libint2::int2` +* (target) `libint2_cxx` --> `Libint2::cxx` + * `ENV(CPPFLAGS)=-I/path/to/boost/includes` --> `-D BOOST_ROOT=/path/to/boost/prefix` * `-D LIBINT2_PYTHON=ON` --> `-D LIBINT2_ENABLE_PYTHON=ON` * `-D LIBINT_USE_BUNDLED_BOOST=ON` --> `-D CMAKE_DISABLE_FIND_PACKAGE_Boost=ON` (standard CMake variable) * `--with-boost` & `--with-boost-libdir` --> see `BOOST_ROOT` & `Boost_DIR` +* `-D ENABLE_FORTRAN=ON` --> `-D LIBINT2_ENABLE_FORTRAN=ON` * `-D LIBINT_LOCAL_Eigen3_INSTALL` --> `-D LIBINT2_LOCAL_Eigen3_INSTALL` * `-D LIBINT_LOCAL_Eigen3_FIND` --> `-D LIBINT2_LOCAL_Eigen3_FIND` diff --git a/cmake/modules/DynamicVersion.cmake b/cmake/modules/DynamicVersion.cmake index 6c1b88c2a..4c62477fa 100644 --- a/cmake/modules/DynamicVersion.cmake +++ b/cmake/modules/DynamicVersion.cmake @@ -1,5 +1,4 @@ -# copied from https://github.com/LecrisUT/CMakeExtraUtils/blob/main/cmake/DynamicVersion.md ~20 Dec 2023 -# * modified to add distance field and return +# copied from https://github.com/LecrisUT/CMakeExtraUtils/blob/main/cmake/DynamicVersion.md 15 Jan 2023 #[===[.md: # DynamicVersion @@ -15,6 +14,11 @@ Helper module to get the project's version dynamically. Format is compatible wit include_guard() list(APPEND CMAKE_MESSAGE_CONTEXT DynamicVersion) +if (POLICY CMP0140) + # Enable using return(PROPAGATE) + # TODO: Remove when cmake 3.25 is commonly distributed + cmake_policy(SET CMP0140 NEW) +endif () #[==============================================================================================[ # Preparations # @@ -37,8 +41,12 @@ function(dynamic_version) Main interface dynamic_version(PROJECT_PREFIX ) dynamic_version(PROJECT_PREFIX - [OUTPUT_VERSION ] [OUTPUT_DESCRIBE ] [OUTPUT_COMMIT ] - [OUTPUT_DISTANCE ] [PROJECT_SOURCE ] [GIT_ARCHIVAL_FILE ]) + [OUTPUT_VERSION ] [OUTPUT_VERSION_FULL ] + [OUTPUT_DESCRIBE ] [OUTPUT_COMMIT ] + [OUTPUT_DISTANCE ] [OUTPUT_SHORT_HASH ] + [VERSION_FULL_MODE ] + [PROJECT_SOURCE ] [GIT_ARCHIVAL_FILE ] + ) Fallbacks dynamic_version(... @@ -56,6 +64,12 @@ function(dynamic_version) `OUTPUT_VERSION` [Default: PROJECT_VERSION] Variable where to save the calculated version + `OUTPUT_VERSION_FULL` [Default: PROJECT_VERSION_FULL] + Variable where to save the full version in the format + + `VERSION_FULL_MODE` [Default: DEV] + Format of the `OUTPUT_VERSION_FULL`. Must be one of [`DEV`, `POST`] + `OUTPUT_DESCRIBE` [Default: GIT_DESCRIBE] Variable where to save the pure `git describe` output @@ -65,6 +79,9 @@ function(dynamic_version) `OUTPUT_DISTANCE` [Default: GIT_DISTANCE] Variable where to save the distance from git tag + `OUTPUT_SHORT_HASH` [Default: GIT_SHORT_HASH] + Variable where to save the shortened git commit hash + `PROJECT_SOURCE` [Default: `${CMAKE_CURRENT_SOURCE_DIR}`] Location of the project source. Has to be either an extracted git archive or a git clone @@ -118,9 +135,6 @@ function(dynamic_version) `${OUTPUT_FOLDER}/.git_commit` Current commit - `${OUTPUT_FOLDER}/.git_distance` - Current git distance from tag - ## See also - [pypa/setuptools_scm](https://github.com/pypa/setuptools_scm) @@ -133,9 +147,12 @@ function(dynamic_version) set(ARGS_OneValue PROJECT_PREFIX OUTPUT_VERSION + OUTPUT_VERSION_FULL + VERSION_FULL_MODE OUTPUT_DESCRIBE OUTPUT_COMMIT OUTPUT_DISTANCE + OUTPUT_SHORT_HASH PROJECT_SOURCE GIT_ARCHIVAL_FILE FALLBACK_VERSION @@ -154,6 +171,14 @@ function(dynamic_version) if (NOT DEFINED ARGS_OUTPUT_VERSION) set(ARGS_OUTPUT_VERSION PROJECT_VERSION) endif () + if (NOT DEFINED ARGS_OUTPUT_VERSION_FULL) + set(ARGS_OUTPUT_VERSION_FULL PROJECT_VERSION_FULL) + endif () + if (NOT DEFINED ARGS_VERSION_FULL_MODE) + set(ARGS_VERSION_FULL_MODE DEV) + elseif (NOT ARGS_VERSION_FULL_MODE MATCHES "(DEV|POST)") + message(FATAL_ERROR "Unsupported VERSION_FULL_MODE = ${ARGS_VERSION_FULL_MODE}") + endif () if (NOT DEFINED ARGS_OUTPUT_DESCRIBE) set(ARGS_OUTPUT_DESCRIBE GIT_DESCRIBE) endif () @@ -163,6 +188,9 @@ function(dynamic_version) if (NOT DEFINED ARGS_OUTPUT_DISTANCE) set(ARGS_OUTPUT_DISTANCE GIT_DISTANCE) endif () + if (NOT DEFINED ARGS_OUTPUT_SHORT_HASH) + set(ARGS_OUTPUT_SHORT_HASH GIT_SHORT_HASH) + endif () if (NOT DEFINED ARGS_PROJECT_SOURCE) set(ARGS_PROJECT_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}) endif () @@ -203,6 +231,7 @@ function(dynamic_version) PROJECT_SOURCE ${ARGS_PROJECT_SOURCE} GIT_ARCHIVAL_FILE ${ARGS_GIT_ARCHIVAL_FILE} TMP_FOLDER ${ARGS_TMP_FOLDER} + VERSION_FULL_MODE ${ARGS_VERSION_FULL_MODE} ) if (DEFINED ARGS_FALLBACK_VERSION) list(APPEND DynamicVersion_ARGS @@ -227,19 +256,29 @@ function(dynamic_version) COMMAND_ERROR_IS_FATAL ANY) # Copy all configured files - foreach (file IN ITEMS .DynamicVersion.json .version .git_describe .git_commit .git_distance) - if (EXISTS ${file}) - file(COPY_FILE ${ARGS_TMP_FOLDER}/${file} ${ARGS_OUTPUT_FOLDER}/${file}) + foreach (file IN ITEMS .DynamicVersion.json .version .git_describe .git_commit) + if (EXISTS ${ARGS_TMP_FOLDER}/${file}) + if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.21) + file(COPY_FILE ${ARGS_TMP_FOLDER}/${file} ${ARGS_OUTPUT_FOLDER}/${file}) + else () + file(COPY ${ARGS_TMP_FOLDER}/${file} DESTINATION ${ARGS_OUTPUT_FOLDER}/) + endif () endif () endforeach () # Check configuration state file(READ ${ARGS_TMP_FOLDER}/.DynamicVersion.json data) + # failed, mode, and version are always set if get_dynamic_version did not exit with failure string(JSON failed GET ${data} failed) - string(JSON ${ARGS_OUTPUT_VERSION} ERROR_VARIABLE _ GET ${data} version) - string(JSON ${ARGS_OUTPUT_DESCRIBE} ERROR_VARIABLE _ GET ${data} describe) - string(JSON ${ARGS_OUTPUT_COMMIT} ERROR_VARIABLE _ GET ${data} commit) + string(JSON ${ARGS_OUTPUT_VERSION} GET ${data} version) + string(JSON ${ARGS_OUTPUT_VERSION_FULL} GET ${data} version-full) + # Other outputs are optional, populate the variables if found + # These are populated if failed = false + string(JSON ${ARGS_OUTPUT_SHORT_HASH} ERROR_VARIABLE _ GET ${data} short-hash) string(JSON ${ARGS_OUTPUT_DISTANCE} ERROR_VARIABLE _ GET ${data} distance) + # These may not be populated depending on mode + string(JSON ${ARGS_OUTPUT_COMMIT} ERROR_VARIABLE _ GET ${data} commit) + string(JSON ${ARGS_OUTPUT_DESCRIBE} ERROR_VARIABLE _ GET ${data} describe) # Configure targets if (failed) @@ -259,15 +298,28 @@ function(dynamic_version) -P ${CMAKE_CURRENT_FUNCTION_LIST_FILE} COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ARGS_TMP_FOLDER}/.DynamicVersion.json ${ARGS_OUTPUT_FOLDER}/.DynamicVersion.json ) + set(extra_version_args) + # .git_describe might not be generated, e.g. if it's an sdist. Make it optional + if (EXISTS ${ARGS_OUTPUT_FOLDER}/.git_describe) + list(APPEND extra_version_args + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ARGS_TMP_FOLDER}/.git_describe ${ARGS_OUTPUT_FOLDER}/.git_describe + ) + endif () add_custom_target(${ARGS_PROJECT_PREFIX}Version ALL DEPENDS ${ARGS_PROJECT_PREFIX}DynamicVersion - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ARGS_TMP_FOLDER}/.git_describe ${ARGS_OUTPUT_FOLDER}/.git_describe COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ARGS_TMP_FOLDER}/.version ${ARGS_OUTPUT_FOLDER}/.version + ${extra_version_args} ) - add_custom_target(${ARGS_PROJECT_PREFIX}GitHash - DEPENDS ${ARGS_PROJECT_PREFIX}DynamicVersion - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ARGS_TMP_FOLDER}/.git_commit ${ARGS_OUTPUT_FOLDER}/.git_commit - ) + # .git_commit might not exist, make the target a no-op in that case + if (NOT EXISTS ${ARGS_OUTPUT_FOLDER}/.git_commit) + add_custom_target(${ARGS_PROJECT_PREFIX}GitHash + COMMAND ${CMAKE_COMMAND} -E true) + else () + add_custom_target(${ARGS_PROJECT_PREFIX}GitHash + DEPENDS ${ARGS_PROJECT_PREFIX}DynamicVersion + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ARGS_TMP_FOLDER}/.git_commit ${ARGS_OUTPUT_FOLDER}/.git_commit + ) + endif () endif () # This ensures that the project is reconfigured (at least at second run) whenever the version changes @@ -282,14 +334,18 @@ function(dynamic_version) # TODO: Remove when cmake 3.25 is commonly distributed set(${ARGS_OUTPUT_DESCRIBE} ${${ARGS_OUTPUT_DESCRIBE}} PARENT_SCOPE) set(${ARGS_OUTPUT_VERSION} ${${ARGS_OUTPUT_VERSION}} PARENT_SCOPE) + set(${ARGS_OUTPUT_VERSION_FULL} ${${ARGS_OUTPUT_VERSION_FULL}} PARENT_SCOPE) set(${ARGS_OUTPUT_COMMIT} ${${ARGS_OUTPUT_COMMIT}} PARENT_SCOPE) set(${ARGS_OUTPUT_DISTANCE} ${${ARGS_OUTPUT_DISTANCE}} PARENT_SCOPE) + set(${ARGS_OUTPUT_SHORT_HASH} ${${ARGS_OUTPUT_SHORT_HASH}} PARENT_SCOPE) endif () return(PROPAGATE ${ARGS_OUTPUT_DESCRIBE} ${ARGS_OUTPUT_VERSION} + ${ARGS_OUTPUT_VERSION_FULL} ${ARGS_OUTPUT_COMMIT} ${ARGS_OUTPUT_DISTANCE} + ${ARGS_OUTPUT_SHORT_HASH} ) endfunction() @@ -310,8 +366,8 @@ function(get_dynamic_version) ## Synopsis ```cmake get_dynamic_version(PROJECT_SOURCE GIT_ARCHIVAL_FILE - TMP_FOLDER - [FALLBACK_VERSION ] [FALLBACK_HASH ] + TMP_FOLDER VERSION_FULL_MODE + [FALLBACK_VERSION ] [FALLBACK_HASH ] ) ``` @@ -329,6 +385,7 @@ function(get_dynamic_version) ) set(ARGS_OneValue PROJECT_SOURCE + VERSION_FULL_MODE GIT_ARCHIVAL_FILE FALLBACK_VERSION FALLBACK_HASH @@ -359,18 +416,20 @@ function(get_dynamic_version) # Set fallback values if (DEFINED ARGS_FALLBACK_VERSION) string(JSON data SET - ${data} version ${ARGS_FALLBACK_VERSION}) - file(WRITE ${ARGS_TMP_FOLDER}/.DynamicVersion.json ${data}) + ${data} version \"${ARGS_FALLBACK_VERSION}\") + string(JSON data SET + ${data} version-full \"${ARGS_FALLBACK_VERSION}\") file(WRITE ${ARGS_TMP_FOLDER}/.version ${ARGS_FALLBACK_VERSION}) endif () if (DEFINED ARGS_FALLBACK_HASH) string(JSON data SET - ${data} commit ${ARGS_FALLBACK_HASH}) - file(WRITE ${ARGS_TMP_FOLDER}/.DynamicVersion.json ${data}) + ${data} commit \"${ARGS_FALLBACK_HASH}\") file(WRITE ${ARGS_TMP_FOLDER}/.git_commit ${ARGS_FALLBACK_HASH}) endif () + file(WRITE ${ARGS_TMP_FOLDER}/.DynamicVersion.json ${data}) + # Check git_archival.txt file is present and properly written if (NOT EXISTS ${ARGS_GIT_ARCHIVAL_FILE}) # If git_archival.txt is missing, project is ill-formed message(${error_message_type} @@ -379,8 +438,6 @@ function(get_dynamic_version) ) return() endif () - - # Get version dynamically from git_archival.txt file(STRINGS ${ARGS_GIT_ARCHIVAL_FILE} describe-name REGEX "^describe-name:.*") if (NOT describe-name) @@ -392,27 +449,65 @@ function(get_dynamic_version) return() endif () - # Try to get the version tag of the form `vX.Y.Z` or `X.Y.Z` (with arbitrary suffix) - if (describe-name MATCHES "^describe-name:[ ]?([v]?([0-9\\.]+).*)") - # First matched group is the full `git describe` of the latest tag - # Second matched group is only the version, i.e. `X.Y.Z` - string(JSON data SET - ${data} describe \"${CMAKE_MATCH_1}\") - file(WRITE ${ARGS_TMP_FOLDER}/.git_describe ${CMAKE_MATCH_1}) - string(JSON data SET - ${data} version \"${CMAKE_MATCH_2}\") - file(WRITE ${ARGS_TMP_FOLDER}/.version ${CMAKE_MATCH_2}) + # Try to get the version statically, and if it fails, get it from VCS + if (EXISTS ${ARGS_PROJECT_SOURCE}/PKG-INFO) + # Case1: Python sdist archive. Get everything from PKG-INFO file + set(mode pkg-info) + file(STRINGS ${ARGS_PROJECT_SOURCE}/PKG-INFO version + REGEX "^Version:[ ]?(([0-9\\.]+)([a-zA-Z0-9]*)?(\\.(dev|post)([0-9]+)\\+g([a-f0-9]+))?)$") + # Cannot use Regex match from here, need to run string(REGEX MATCH) again + # https://gitlab.kitware.com/cmake/cmake/-/issues/23770 + string(REGEX MATCH "^Version:[ ]?(([0-9\\.]+)([a-zA-Z0-9]*)?(\\.(dev|post)([0-9]+)\\+g([a-f0-9]+))?)$" version "${version}") + # Regex match groups: https://regex101.com/r/G4Ox4X/5 + # 1: Full version string + # 2: Version string + # 3: Version suffix (e.g. rc, alpha, etc.) + # 4: Development suffix + # 5: dev/post + # 6: git distance + # 7: short_hash + set(version-full ${CMAKE_MATCH_1}) + set(version ${CMAKE_MATCH_2}) + set(version-suffix ${CMAKE_MATCH_3}) + if (CMAKE_MATCH_4) + set(distance ${CMAKE_MATCH_6}) + set(short-hash ${CMAKE_MATCH_7}) + string(JSON data SET + ${data} dev-type \"${CMAKE_MATCH_5}\") + else () + set(distance 0) + endif () + message(DEBUG "Found version in PKG-INFO") + elseif (describe-name MATCHES "^describe-name:[ ]?(v?([0-9\\.]+)(-?[a-zA-z0-9]*)?(-([0-9]+)-g([a-f0-9]+))?)$") + # Case2: Git archive. Get everything from git_archival.txt file + set(mode git-archive) + # Regex match groups: https://regex101.com/r/osVZpm/4 + # 1: Git describe + # 2: Version string + # 3: Version suffix (e.g. rc, alpha, etc.) + # 4: Development suffix + # 5: git distance + # 6: short_hash + set(describe ${CMAKE_MATCH_1}) + set(version ${CMAKE_MATCH_2}) + set(version-suffix ${CMAKE_MATCH_3}) + if (CMAKE_MATCH_4) + set(distance ${CMAKE_MATCH_5}) + set(short-hash ${CMAKE_MATCH_6}) + else () + set(distance 0) + endif () # Get commit hash file(STRINGS ${ARGS_GIT_ARCHIVAL_FILE} node REGEX "^node:[ ]?(.*)") - string(JSON data SET - ${data} commit \"${CMAKE_MATCH_1}\") - file(WRITE ${ARGS_TMP_FOLDER}/.git_commit ${CMAKE_MATCH_1}) - message(DEBUG - "Found appropriate tag in .git_archival.txt file" - ) + # Cannot use Regex match from here, need to run string(REGEX MATCH) again + # https://gitlab.kitware.com/cmake/cmake/-/issues/23770 + string(REGEX MATCH "^node:[ ]?(.*)" node "${node}") + set(commit ${CMAKE_MATCH_1}) + message(DEBUG "Found version in git-archival.txt") else () - # If not it has to be computed from the git archive + # Default: Git repository. Call git commands + set(mode git) find_package(Git REQUIRED) # Test if project is a git repository execute_process(COMMAND ${GIT_EXECUTABLE} status @@ -426,54 +521,109 @@ function(get_dynamic_version) ) return() endif () - # Get most recent commit hash - execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse HEAD - WORKING_DIRECTORY ${ARGS_PROJECT_SOURCE} - OUTPUT_VARIABLE git-hash - OUTPUT_STRIP_TRAILING_WHITESPACE - COMMAND_ERROR_IS_FATAL ANY) # Get version and describe-name - execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --match=?[0-9.]* + execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --long --match=?[0-9.]* WORKING_DIRECTORY ${ARGS_PROJECT_SOURCE} OUTPUT_VARIABLE describe-name OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY) # Match any part containing digits and periods (strips out rc and so on) - if (NOT describe-name MATCHES "^([v]?([0-9\\.]+).*)") + if (NOT describe-name MATCHES "^(v?([0-9\\.]+)(-?[a-zA-z0-9]*)?(-([0-9]+)-g([a-f0-9]+))?)$") message(${error_message_type} "Version tag is ill-formatted\n" " Describe-name: ${describe-name}" ) return() endif () - string(JSON data SET - ${data} describe \"${CMAKE_MATCH_1}\") - file(WRITE ${ARGS_TMP_FOLDER}/.git_describe ${CMAKE_MATCH_1}) - string(JSON data SET - ${data} version \"${CMAKE_MATCH_2}\") - file(WRITE ${ARGS_TMP_FOLDER}/.version ${CMAKE_MATCH_2}) - string(JSON data SET - ${data} commit \"${git-hash}\") - file(WRITE ${ARGS_TMP_FOLDER}/.git_commit ${git-hash}) - # Get full describe with distance - execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --long --match=?[0-9.]* + # Regex match groups: https://regex101.com/r/GIfYI1/2 + # 1: Git describe + # 2: Version string + # 3: Version suffix (e.g. rc, alpha, etc.) + # 4: Development suffix + # 5: git distance + # 6: short_hash + set(describe ${CMAKE_MATCH_1}) + set(version ${CMAKE_MATCH_2}) + set(version-suffix ${CMAKE_MATCH_3}) + if (CMAKE_MATCH_4) + set(distance ${CMAKE_MATCH_5}) + set(short-hash ${CMAKE_MATCH_6}) + else () + set(distance 0) + endif () + # Get commit hash + execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse HEAD WORKING_DIRECTORY ${ARGS_PROJECT_SOURCE} - OUTPUT_VARIABLE describe-name-long + OUTPUT_VARIABLE commit OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY) - # Match version (as above) and distance - if (NOT describe-name-long MATCHES "^([v]?([0-9\\.]+)-([0-9]+)-.*)") - message(${error_message_type} - "Version tag is ill-formatted\n" - " Describe-name-long: ${describe-name-long}" - ) - return() + message(DEBUG "Found version git repo") + endif () + + # Construct the version_full if it was not already provided + if (NOT version-full) + string(REGEX REPLACE "[-_]" "" version-suffix-sanitized "${version-suffix}") + if (distance EQUAL 0) + # If the distance is 0, just use the original tag version with sanitized suffix + set(version-full "${version}${version-suffix-sanitized}") + else () + # Otherwise construct it according to VERSION_FULL_MODE + if (ARGS_VERSION_FULL_MODE STREQUAL DEV) + # In DEV mode, we bump the last digit of the version. If this is in version-suffix, like `-rcX`, then + # this must be bumped instead + if (version-suffix-sanitized MATCHES "([a-zA-Z]*)([0-9]+)") + math(EXPR bumped_number "${CMAKE_MATCH_2} + 1") + set(version-suffix-sanitized "${CMAKE_MATCH_1}${bumped_number}") + elseif (version MATCHES "([0-9\\.]*\\.)([0-9]+)") + math(EXPR bumped_number "${CMAKE_MATCH_2} + 1") + set(version "${CMAKE_MATCH_1}${bumped_number}") + else () + message(FATAL_ERROR "Assert False: version = ${version}") + endif () + set(version-full "${version}${version-suffix-sanitized}.dev${distance}+g${short-hash}") + elseif (ARGS_VERSION_FULL_MODE STREQUAL POST) + set(version-full "${version}${version-suffix-sanitized}.post${distance}+g${short-hash}") + else () + message(FATAL_ERROR "Assert False: VERSION_FULL_MODE = ${ARGS_VERSION_FULL_MODE}") + endif () endif () - string(JSON data SET - ${data} distance \"${CMAKE_MATCH_3}\") - file(WRITE ${ARGS_TMP_FOLDER}/.git_distance ${CMAKE_MATCH_3}) - message(DEBUG - "Found appropriate tag from git" + endif () + + # Construct the JSON data + string(JSON data SET ${data} + mode \"${mode}\" + ) + string(JSON data SET ${data} + version \"${version}\" + ) + file(WRITE ${ARGS_TMP_FOLDER}/.version ${version}) + string(JSON data SET ${data} + version-full \"${version-full}\" + ) + if (describe) + string(JSON data SET ${data} + describe \"${describe}\" + ) + file(WRITE ${ARGS_TMP_FOLDER}/.git_describe ${describe}) + endif () + if (commit) + string(JSON data SET ${data} + commit \"${commit}\" + ) + file(WRITE ${ARGS_TMP_FOLDER}/.git_commit ${commit}) + endif () + set(JSON data SET ${data} + version-full \"${version-full}\" + ) + string(JSON data SET ${data} + version-suffix \"${version-suffix}\" + ) + string(JSON data SET ${data} + distance ${distance} + ) + if (short-hash) + string(JSON data SET ${data} + short-hash \"${short-hash}\" ) endif () @@ -507,3 +657,5 @@ if (DynamicVersion_RUN) endif () get_dynamic_version(${DynamicVersion_ARGS}) endif () + +list(POP_BACK CMAKE_MESSAGE_CONTEXT) diff --git a/cmake/modules/int_computed.cmake.in b/cmake/modules/int_computed.cmake.in index 1511d08bb..51d79d527 100644 --- a/cmake/modules/int_computed.cmake.in +++ b/cmake/modules/int_computed.cmake.in @@ -28,6 +28,8 @@ set(LIBINT_MINOR_VERSION "@LIBINT_MINOR_VERSION@") set(LIBINT_MICRO_VERSION "@LIBINT_MICRO_VERSION@") set(LIBINT_VERSION ${LIBINT_MAJOR_VERSION}.${LIBINT_MINOR_VERSION}.${LIBINT_MICRO_VERSION}) +# for macros.tex +set(LIBINT_MMM_VERSION "${LIBINT_VERSION}") # <<< Dev Version >>> @@ -54,53 +56,31 @@ set(LIBINT2_SHELL_SET "@LIBINT2_SHELL_SET@") # <<< Features List >>> -if ((@LIBINT_CGSHELL_ORDERING@ EQUAL 1) AND (@LIBINT_SHELL_SET@ EQUAL 1)) - set(_ordering "ss") -elseif((@LIBINT_CGSHELL_ORDERING@ EQUAL 1) AND (@LIBINT_SHELL_SET@ EQUAL 2)) - set(_ordering "so") -elseif((@LIBINT_CGSHELL_ORDERING@ EQUAL 2) AND (@LIBINT_SHELL_SET@ EQUAL 1)) - set(_ordering "is") -elseif((@LIBINT_CGSHELL_ORDERING@ EQUAL 2) AND (@LIBINT_SHELL_SET@ EQUAL 2)) - set(_ordering "io") -elseif((@LIBINT_CGSHELL_ORDERING@ EQUAL 3) AND (@LIBINT_SHELL_SET@ EQUAL 1)) - set(_ordering "gs") -elseif((@LIBINT_CGSHELL_ORDERING@ EQUAL 3) AND (@LIBINT_SHELL_SET@ EQUAL 2)) - set(_ordering "go") -elseif((@LIBINT_CGSHELL_ORDERING@ EQUAL 4) AND (@LIBINT_SHELL_SET@ EQUAL 1)) - set(_ordering "os") -elseif((@LIBINT_CGSHELL_ORDERING@ EQUAL 4) AND (@LIBINT_SHELL_SET@ EQUAL 2)) - set(_ordering "oo") -elseif((@LIBINT_CGSHELL_ORDERING@ EQUAL 5) AND (@LIBINT_SHELL_SET@ EQUAL 1)) - set(_ordering "bs") -elseif((@LIBINT_CGSHELL_ORDERING@ EQUAL 5) AND (@LIBINT_SHELL_SET@ EQUAL 2)) - set(_ordering "bo") -elseif((@LIBINT_CGSHELL_ORDERING@ EQUAL 1) AND (@LIBINT_SHELL_SET@ EQUAL 1)) - set(_ordering "ss") -elseif((@LIBINT_CGSHELL_ORDERING@ EQUAL 1) AND (@LIBINT_SHELL_SET@ EQUAL 2)) - set(_ordering "so") -elseif((@LIBINT_CGSHELL_ORDERING@ EQUAL 2) AND (@LIBINT_SHELL_SET@ EQUAL 1)) - set(_ordering "is") -elseif((@LIBINT_CGSHELL_ORDERING@ EQUAL 2) AND (@LIBINT_SHELL_SET@ EQUAL 2)) - set(_ordering "io") -elseif((@LIBINT_CGSHELL_ORDERING@ EQUAL 3) AND (@LIBINT_SHELL_SET@ EQUAL 1)) - set(_ordering "gs") -elseif((@LIBINT_CGSHELL_ORDERING@ EQUAL 3) AND (@LIBINT_SHELL_SET@ EQUAL 2)) - set(_ordering "go") -elseif((@LIBINT_CGSHELL_ORDERING@ EQUAL 4) AND (@LIBINT_SHELL_SET@ EQUAL 1)) - set(_ordering "os") -elseif((@LIBINT_CGSHELL_ORDERING@ EQUAL 4) AND (@LIBINT_SHELL_SET@ EQUAL 2)) - set(_ordering "oo") -elseif((@LIBINT_CGSHELL_ORDERING@ EQUAL 5) AND (@LIBINT_SHELL_SET@ EQUAL 1)) - set(_ordering "bs") -elseif((@LIBINT_CGSHELL_ORDERING@ EQUAL 5) AND (@LIBINT_SHELL_SET@ EQUAL 2)) - set(_ordering "bo") +if (@LIBINT_CGSHELL_ORDERING@ EQUAL 1) + set(_o1st "s") +elseif(@LIBINT_CGSHELL_ORDERING@ EQUAL 2) + set(_o1st "i") +elseif(@LIBINT_CGSHELL_ORDERING@ EQUAL 3) + set(_o1st "g") +elseif(@LIBINT_CGSHELL_ORDERING@ EQUAL 4) + set(_o1st "o") +elseif(@LIBINT_CGSHELL_ORDERING@ EQUAL 5) + set(_o1st "b") else() - message(STATUS "int_computed.cmake: indeterminate orderings") + message(STATUS "int_computed.cmake: indeterminate orderings: cgshell") +endif() + +if (@LIBINT_SHELL_SET@ EQUAL 1) + set(_o2nd "s") +elseif(@LIBINT_SHELL_SET@ EQUAL 2) + set(_o2nd "o") +else() + message(STATUS "int_computed.cmake: indeterminate orderings: shell_set") endif() # for configuration.cc and libint2-config.cmake files set(Libint2_CONFIG_COMPONENTS "@Libint2_ERI_COMPONENTS@") -list(PREPEND Libint2_CONFIG_COMPONENTS "${_ordering}") +list(PREPEND Libint2_CONFIG_COMPONENTS "${_o1st}${_o2nd}") # <<< AM Components >>> diff --git a/cmake/modules/int_versions.cmake b/cmake/modules/int_versions.cmake index 35c6e9d13..460fd7ef9 100644 --- a/cmake/modules/int_versions.cmake +++ b/cmake/modules/int_versions.cmake @@ -13,10 +13,12 @@ # <<< Sortable Version >>> -message(DEBUG "LibintRepository_VERSION ${LibintRepository_VERSION}") -message(DEBUG "LibintRepository_COMMIT ${LibintRepository_COMMIT}") -message(DEBUG "LibintRepository_DISTANCE ${LibintRepository_DISTANCE}") -message(DEBUG "LibintRepository_DESCRIBE ${LibintRepository_DESCRIBE}") +message(DEBUG "LibintRepository_VERSION ${LibintRepository_VERSION}") +message(DEBUG "LibintRepository_VERSION_FULL ${LibintRepository_VERSION_FULL}") +message(DEBUG "LibintRepository_COMMIT ${LibintRepository_COMMIT}") +message(DEBUG "LibintRepository_SHORT_HASH ${LibintRepository_SHORT_HASH}") +message(DEBUG "LibintRepository_DISTANCE ${LibintRepository_DISTANCE}") +message(DEBUG "LibintRepository_DESCRIBE ${LibintRepository_DESCRIBE}") if (LibintRepository_DISTANCE STREQUAL "0") set(LIBINT_SORTABLE_VERSION "${LibintRepository_VERSION}") @@ -24,8 +26,10 @@ else() set(LIBINT_SORTABLE_VERSION "${LibintRepository_VERSION}.post${LibintRepository_DISTANCE}") endif() -string(SUBSTRING ${LibintRepository_COMMIT} 0 7 LIBINT_GIT_COMMIT) -message(DEBUG "LIBINT_GIT_COMMIT ${LIBINT_GIT_COMMIT}") +# short hash from DynVer is variable length from `git describe`. +# * use below for fixed length +# string(SUBSTRING ${LibintRepository_COMMIT} 0 7 LIBINT_GIT_COMMIT) +message(DEBUG "LIBINT_GIT_COMMIT ${LibintRepository_SHORT_HASH}") # Below goes into BibTeX citation. Currently year of export. For year of tag, parse: # `git show -s --no-notes --date=short --pretty='%cd' v2.7.2` responds: 2022-06-20 @@ -52,7 +56,7 @@ else() set(LIBINT_EXT_VERSION ${LIBINT_VERSION}) endif() -message(STATUS "Version: Full ${LIBINT_EXT_VERSION} Numeric ${LIBINT_VERSION} Sortable ${LIBINT_SORTABLE_VERSION}") +message(STATUS "Version: Full ${LIBINT_EXT_VERSION} Numeric ${LIBINT_VERSION} Sortable ${LIBINT_SORTABLE_VERSION} SCM ${LibintRepository_VERSION_FULL}") if (NOT(LibintRepository_VERSION STREQUAL LIBINT_VERSION)) message(AUTHOR_WARNING diff --git a/configure.ac b/configure.ac index e06e6a221..08b535d12 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -define([libint_mmm_version],[2.11.0]) +define([libint_mmm_version],[2.11.2]) define([libint_buildid],[]) define([libint_so_version],[2:3:0]) diff --git a/export/cmake/CMakeLists.txt.export b/export/cmake/CMakeLists.txt.export index d66d37625..580d0b9c1 100644 --- a/export/cmake/CMakeLists.txt.export +++ b/export/cmake/CMakeLists.txt.export @@ -8,7 +8,7 @@ project(Libint LANGUAGES CXX C) # Set Libint version =================================================================================================== set(LIBINT_MAJOR_VERSION 2) set(LIBINT_MINOR_VERSION 11) -set(LIBINT_MICRO_VERSION 0) # Sync this with python/CMakeLists.txt +set(LIBINT_MICRO_VERSION 2) # Sync this with python/CMakeLists.txt set(LIBINT_BUILDID ) set(LIBINT_VERSION "${LIBINT_MAJOR_VERSION}.${LIBINT_MINOR_VERSION}.${LIBINT_MICRO_VERSION}") if (LIBINT_BUILDID) diff --git a/include/libint2/config.h.cmake.in b/include/libint2/config.h.cmake.in index c9c871ec5..07aaf3828 100644 --- a/include/libint2/config.h.cmake.in +++ b/include/libint2/config.h.cmake.in @@ -41,6 +41,9 @@ /* Prefix for all names in API */ #cmakedefine LIBINT_API_PREFIX "@LIBINT_API_PREFIX@" +/* Max AM supported by Libint *in principle* */ +#cmakedefine LIBINT_HARD_MAX_AM @LIBINT_HARD_MAX_AM@ + /* Max AM (same for all derivatives; if not defined see LIBINT_MAX_AM_LIST) */ #cmakedefine LIBINT_MAX_AM @LIBINT_MAX_AM@ @@ -330,15 +333,15 @@ #if __has_cpp_attribute(maybe_unused) #define LIBINT_MAYBE_UNUSED [[maybe_unused]] #endif -#endif // __has_cpp_attribute +#endif /* __has_cpp_attribute */ #ifndef LIBINT_MAYBE_UNUSED #if defined __has_attribute # if __has_attribute (unused) # define LIBINT_MAYBE_UNUSED __attribute__ ((unused)) # endif -#endif // __has_attribute -#endif // LIBINT_MAYBE_UNUSED -#ifndef LIBINT_MAYBE_UNUSED // fallback +#endif /* __has_attribute */ +#endif /* LIBINT_MAYBE_UNUSED */ +#ifndef LIBINT_MAYBE_UNUSED /* fallback */ #define LIBINT_MAYBE_UNUSED #endif diff --git a/include/libint2/config2.h.cmake.in b/include/libint2/config2.h.cmake.in index 0344ee87b..66ea311f9 100644 --- a/include/libint2/config2.h.cmake.in +++ b/include/libint2/config2.h.cmake.in @@ -40,7 +40,7 @@ #define LIBINT2_ALIGN_SIZE @LIBINT2_ALIGN_SIZE@ /* User-defined real type */ -#cmakedefine LIBINT2_REALTYPE "@LIBINT2_REALTYPE@" +#cmakedefine LIBINT2_REALTYPE @LIBINT2_REALTYPE@ /* Specifies the ordering of solid harmonics Gaussians in a shell. Retired Jan 2023 in favor of becoming a generator-time-only option */ /* #cmakedefine LIBINT_SHGSHELL_ORDERING @LIBINT_SHGSHELL_ORDERING@ */ diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index d229945ff..cc8d79b91 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -6,11 +6,19 @@ endif() cmake_policy(SET CMP0079 NEW) if(NOT DEFINED LIBINT_VERSION) - # for indep build of project(libint2-python), version not available from project(Libint2) - set(LIBINT_VERSION "2.11.0") # keep synched to the configure.in and export/cmake/CMakeLists.txt.export + # for indep bld of project(libint2-python), version (for pyproject.toml) not available from project(Libint2) + list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules) + include(int_computed OPTIONAL) # cmake+cmake + + if(NOT DEFINED LIBINT_VERSION) + set(LIBINT_VERSION "2.11.2") # libtool+cmake + endif() endif() -project(libint2-python) +project( + libint2-python + VERSION ${LIBINT_VERSION} + ) if (NOT TARGET Python::Module) find_package(Python COMPONENTS Interpreter Development REQUIRED) @@ -48,10 +56,10 @@ if (pybind11_VERSION VERSION_GREATER_EQUAL 2.11.0) endif() pybind11_add_module( - libint2-python MODULE - #EXCLUDE_FROM_ALL - src/libint2/libint2.cc - src/libint2/engine.cc + libint2-python + MODULE + src/libint2/libint2.cc + src/libint2/engine.cc ) target_compile_features(libint2-python PRIVATE "cxx_std_17") @@ -64,9 +72,8 @@ endif() target_compile_options(libint2-python PRIVATE - # too many warnings on Windows - # $<$:/W4> - $<$>:-Wall> + #$<$:/W4> + $<$>:-Wall> ) #find_package(Eigen3 3.3 REQUIRED) @@ -74,23 +81,29 @@ target_compile_options(libint2-python set_target_properties( libint2-python PROPERTIES - #PREFIX "" - OUTPUT_NAME libint2 + #PREFIX "" + OUTPUT_NAME libint2 ) -if (TARGET libint2_obj) - set(libint2_python_target libint2_obj) +# future note: this whole block could likely be replaced by the below, but perhaps explicit better for now +# * `if(TARGET Libint2::cxx)\n target_link_libraries(libint2-python PRIVATE Libint2::cxx)\nelse()\n find_package(Libint2 ...` +if (TARGET Libint2::cxx) - if(MSVC) + + if (MSVC) target_compile_definitions(libint2-python PUBLIC _USE_MATH_DEFINES) target_compile_options(libint2-python PUBLIC "/EHsc") endif() - target_link_libraries(libint2-python PRIVATE libint2_obj) - target_link_libraries(libint2-python PRIVATE Boost::headers) + target_link_libraries( + libint2-python + PRIVATE + Libint2::cxx + Boost::headers + ) else() - find_package(Libint2 REQUIRED) - target_link_libraries(libint2-python PRIVATE Libint2::cxx) + find_package(Libint2 COMPONENTS CXX_ho REQUIRED) + target_link_libraries(libint2-python PRIVATE Libint2::cxx) endif() # if (Eigen3::Eigen) @@ -107,12 +120,39 @@ install(TARGETS libint2-python RUNTIME DESTINATION libint2 ) +# <<< Install >>> + +if (LIBINT2_PREFIX_PYTHON_INSTALL) + # * Note that this block is *Linux-style* install to `CMAKE_INSTALL_PREFIX`. + # * For *Python-style* install to `Python_EXECUTABLE`'s site-packages, use + # wheel target below from python/ directory. + # > make libint2-python-wheel + # > pip3 install dist/libint2-*.whl + + execute_process( + COMMAND ${Python_EXECUTABLE} -c + "import os, sys, sysconfig as s; spdir = s.get_path('platlib'); print(spdir.replace(os.path.commonpath([sys.prefix, spdir]), '').lstrip(os.path.sep));" + OUTPUT_VARIABLE LIBINT2_INSTALL_PYMODDIR + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + message(STATUS "Showing option LIBINT2_INSTALL_PYMODDIR: ${LIBINT2_INSTALL_PYMODDIR} (non-user-configurable until wanted)") + + install( + FILES $ + COMPONENT ${L2}_Python + DESTINATION ${LIBINT2_INSTALL_PYMODDIR} + ) +endif() + +# <<< Python Tooling >>> + add_custom_target( libint2-python-test DEPENDS libint2-python COMMAND ${Python_EXECUTABLE} -m pytest ${CMAKE_CURRENT_SOURCE_DIR}/tests -v WORKING_DIRECTORY ${PROJECT_BINARY_DIR} ) +add_custom_target(check-python DEPENDS libint2-python-test) add_custom_target( libint2-python-wheel diff --git a/python/pyproject.toml b/python/pyproject.toml index dcac8df35..d0ad403c0 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["scikit-build-core>=0.8.0", "pybind11>=2.6.0"] +requires = ["scikit-build-core>=0.8.0", "pybind11>=3.0.0"] build-backend = "scikit_build_core.build" [project] @@ -23,6 +23,7 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Topic :: Scientific/Engineering :: Chemistry", ] diff --git a/python/setup.py.in b/python/setup.py.in deleted file mode 100644 index 3368bbe73..000000000 --- a/python/setup.py.in +++ /dev/null @@ -1,66 +0,0 @@ -try: - import setuptools -except ImportError as e: - print( - "Error: %s\n" % str(e) + - "Python setuptools are not installed\n" + - "'pip install setuptools' to build libint Python bindings" - ) - import sys - sys.exit(1) - -from setuptools import setup, Extension -from setuptools.command.build_ext import build_ext -import os -import subprocess - -# sources+tests -os.sys.path.append("@PROJECT_SOURCE_DIR@") - -class CMakeExtension(Extension): - def __init__(self, name, sourcedir=''): - Extension.__init__(self, name, sources=[]) - self.sourcedir = os.path.abspath(sourcedir) - - -class CMakeBuild(build_ext): - def run(self): - for ext in self.extensions: - self.build_extension(ext) - - def build_extension(self, ext): - - ext_fullpath = self.get_ext_fullpath(ext.name) - ext_basename = os.path.basename(ext_fullpath) - ext_dirname = os.path.dirname(ext_fullpath) - project_binary_dir = "@PROJECT_BINARY_DIR@" - - if not os.path.exists(self.build_temp): - os.makedirs(self.build_temp) - - cfg = 'Debug' if self.debug else 'Release' - build_args = ['--config', cfg] - subprocess.check_call( - ['cmake', '--build', "@CMAKE_BINARY_DIR@", '--target', 'libint2-python'] + build_args, - #cwd=self.build_temp - ) - - if not os.path.exists(ext_dirname): - os.makedirs(ext_dirname) - self.copy_file( - os.path.join(project_binary_dir, ext_basename), - ext_fullpath - ) - - print() # Add an empty line for cleaner output - -setup( - name = 'libint2', - version = '@LIBINT_VERSION@', - description = 'libint2', - #packages=['libint2'], - #package_dir={'': 'src'}, - ext_modules = [ CMakeExtension("libint2") ], - cmdclass=dict(build_ext=CMakeBuild), - test_suite='tests', -) diff --git a/src/bin/CMakeLists.txt b/src/bin/CMakeLists.txt index 2bcf79f3a..58d0a77bb 100644 --- a/src/bin/CMakeLists.txt +++ b/src/bin/CMakeLists.txt @@ -2,11 +2,11 @@ add_subdirectory(libint) include(AddCustomTargetSubproject) add_custom_target_subproject( - libint2compiler - check + libint2compiler check # target check-libint2compiler USES_TERMINAL COMMAND ${CMAKE_CTEST_COMMAND} -V -R "libint2/compiler" ) +add_dependencies(check-libint2compiler build_libint) if (BUILD_TESTING) add_subdirectory(test_eri) diff --git a/src/bin/libint/CMakeLists.txt b/src/bin/libint/CMakeLists.txt index f9b82c565..ebb7983b7 100644 --- a/src/bin/libint/CMakeLists.txt +++ b/src/bin/libint/CMakeLists.txt @@ -38,16 +38,15 @@ add_library( target_compile_definitions( libint-libcompiler PUBLIC - __COMPILING_LIBINT2=1 - # MSVC does not include constants, unless _USE_MATH_DEFINES is defined. $<$:_USE_MATH_DEFINES> + # MSVC does not include constants, unless _USE_MATH_DEFINES is defined. ) target_compile_options( libint-libcompiler PUBLIC + $<$:/EHsc> # Set the exception handling model (allows "throw") - $<$:"/EHsc"> ) target_compile_features( @@ -85,7 +84,10 @@ add_executable( EXCLUDE_FROM_ALL build_libint.cc ) -target_link_libraries(build_libint libint-libcompiler) +target_link_libraries( + build_libint + libint-libcompiler + ) if(MSVC) # Increase stack size from 1 MB to 4 MB diff --git a/src/lib/libint/CMakeLists.txt b/src/lib/libint/CMakeLists.txt index d561db484..c1e476e06 100644 --- a/src/lib/libint/CMakeLists.txt +++ b/src/lib/libint/CMakeLists.txt @@ -1,39 +1,69 @@ list(APPEND CMAKE_MODULE_PATH ${PROJECT_BINARY_DIR}/cmake/modules) +include(GNUInstallDirs) include(int_computed) # for macros.tex and features # <<< Generate Library Source >>> -file(MAKE_DIRECTORY "${EXPORT_STAGE_DIR}/src") +file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/generated") add_custom_command( OUTPUT - "${EXPORT_STAGE_DIR}/src/libint2_params.h" + "${PROJECT_BINARY_DIR}/generated/libint2_params.h" + "${PROJECT_BINARY_DIR}/generated/HRRPart0bra0ket0pp.h" + "${PROJECT_BINARY_DIR}/generated/HRRPart0bra0ket0pp.cc" COMMAND $ - WORKING_DIRECTORY "${EXPORT_STAGE_DIR}/src" DEPENDS build_libint + WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/generated" COMMENT "Generating Libint2 library source" ) -add_custom_target(libint-library-generate DEPENDS "${EXPORT_STAGE_DIR}/src/libint2_params.h") +add_custom_target(libint-library-generate DEPENDS "${PROJECT_BINARY_DIR}/generated/libint2_params.h") + # <<< Add Metadata To The Library Source >>> +# the library source to be tarballed is mainly assembled through populate.cmake. +# These following configure_file's need a few extra substitution variables that +# aren't passed to populate. + configure_file( "features.cmake.in" "${EXPORT_STAGE_DIR}/features" @ONLY) +configure_file( + "${PROJECT_SOURCE_DIR}/doc/progman/macros.tex.in" + "${EXPORT_STAGE_DIR}/doc/macros.tex" + @ONLY) + +# position basis.h for local buildtree. +# * gets re-configured (CMakeLists.txt.export) for library export with its own +# CMAKE_INSTALL_PREFIX +# * gets re-re-positioned (end of this file) for case of continuous generator + +# library build (through EP) with outer CMAKE_INSTALL_PREFIX +set(DATADIR_ABSOLUTE ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/libint/${LIBINT_VERSION}) +configure_file( + "${PROJECT_SOURCE_DIR}/include/libint2/basis.h.in" # TODO basis.h.cmake.in after libtool retires + "include/libint2/basis.h" + @ONLY) + add_custom_command( OUTPUT ${EXPORT_STAGE_DIR}/CMakeLists.txt + ${EXPORT_STAGE_DIR}/include/libint2_params.h + ${EXPORT_STAGE_DIR}/include/HRRPart0bra0ket0pp.h + ${EXPORT_STAGE_DIR}/src/HRRPart0bra0ket0pp.cc + COMMAND ${CMAKE_COMMAND} + "-DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}" + "-DPROJECT_BINARY_DIR=${PROJECT_BINARY_DIR}" + "-DEXPORT_STAGE_DIR=${EXPORT_STAGE_DIR}" + -P ${CMAKE_CURRENT_SOURCE_DIR}/populate.cmake DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/populate.cmake" + "${PROJECT_BINARY_DIR}/generated/libint2_params.h" + "${PROJECT_BINARY_DIR}/generated/HRRPart0bra0ket0pp.h" + "${PROJECT_BINARY_DIR}/generated/HRRPart0bra0ket0pp.cc" libint-library-generate - COMMAND ${CMAKE_COMMAND} - "-DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}" - "-DPROJECT_BINARY_DIR=${PROJECT_BINARY_DIR}" - "-DEXPORT_STAGE_DIR=${EXPORT_STAGE_DIR}" - -P ${CMAKE_CURRENT_SOURCE_DIR}/populate.cmake COMMENT "Populating Libint2 library" ) add_custom_target(libint-library-populate DEPENDS ${EXPORT_STAGE_DIR}/CMakeLists.txt) @@ -41,25 +71,64 @@ add_custom_target(libint-library-populate DEPENDS ${EXPORT_STAGE_DIR}/CMakeLists # <<< Export The Library Source >>> +set(EXPORT_TARBALL "${EXPORT_STAGE_DIR}.${EXPORT_COMPRESSOR_EXT}") add_custom_command( OUTPUT - "${EXPORT_STAGE_DIR}.tgz" - COMMAND ${CMAKE_COMMAND} -E tar "cfz" "${EXPORT_STAGE_DIR}.tgz" "${EXPORT_STAGE_DIR}" + "${EXPORT_TARBALL}" + COMMAND ${CMAKE_COMMAND} -E tar ${EXPORT_COMPRESSOR_CMD} "${EXPORT_TARBALL}" "${EXPORT_STAGE_DIR}" DEPENDS libint-library-generate libint-library-populate + ${EXPORT_STAGE_DIR}/CMakeLists.txt WORKING_DIRECTORY "${EXPORT_STAGE_DIR}/.." - COMMENT "Exporting tarball of Libint2 library source" + COMMENT "Exporting tarball of Libint2 library source: ${EXPORT_TARBALL}" ) -add_custom_target(libint-library-export DEPENDS "${EXPORT_STAGE_DIR}.tgz") - - - # <<< Build Library >>> +if (LIBINT_BUILD_LIBRARY_AS_SUBPROJECT) + # rerun cmake if building as subproject to unpack and consume the library as subproject + add_custom_target(libint-library-export DEPENDS "${EXPORT_TARBALL}" + COMMAND ${CMAKE_COMMAND} -S "${CMAKE_SOURCE_DIR}" -B "${CMAKE_BINARY_DIR}") +else() + add_custom_target(libint-library-export DEPENDS "${EXPORT_TARBALL}") +endif() +add_custom_target(export DEPENDS libint-library-export) + + +# <<< Build Library >>> + +include(CheckLanguage) +check_language(C) +if(CMAKE_C_COMPILER) + enable_language(C) +else() + message(FATAL_ERROR "No C language support; invoke CMake with -D CMAKE_C_COMPILER=/path/to/C/compiler to resolve") +endif() + +if (LIBINT_BUILD_LIBRARY_AS_SUBPROJECT) + include(FetchContent) + + if (EXISTS "${EXPORT_TARBALL}") + message("Unpacking ${EXPORT_TARBALL} and setting up as a subproject") + FetchContent_Declare( + libint-library + URL "${EXPORT_TARBALL}" + ) + FetchContent_MakeAvailable(libint-library) + else() + message(WARNING "LIBINT_BUILD_LIBRARY_AS_SUBPROJECT=ON but library has not been exported yet; build target 'libint-library-export' first, this will make library build/test targets ('check', 'install') available. Don't run 'check' with CTEST_PARALLEL_LEVEL as this will build the library multiple times.") + endif() +else() include(ExternalProject) list(APPEND library_CMAKE_ARGS + -G${CMAKE_GENERATOR} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DBUILD_TESTING=${BUILD_TESTING} + -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} + -DLIBINT2_BUILD_SHARED_AND_STATIC_LIBS=${LIBINT2_BUILD_SHARED_AND_STATIC_LIBS} + -DLIBINT2_REQUIRE_CXX_API=${LIBINT2_REQUIRE_CXX_API} + -DLIBINT2_REQUIRE_CXX_API_COMPILED=${LIBINT2_REQUIRE_CXX_API_COMPILED} + -DLIBINT2_ENABLE_FORTRAN=${LIBINT2_ENABLE_FORTRAN} -DLIBINT2_ALIGN_SIZE=${LIBINT_ALIGN_SIZE} -DLIBINT2_REALTYPE=${LIBINT2_REALTYPE} -DLIBINT2_ENABLE_MPFR=${LIBINT2_ENABLE_MPFR} @@ -87,10 +156,13 @@ add_custom_target(libint-library-export DEPENDS "${EXPORT_STAGE_DIR}.tgz") if (LIBINT2_LOCAL_Eigen3_INSTALL) list(APPEND library_CMAKE_ARGS "-DLIBINT2_LOCAL_Eigen3_INSTALL=${LIBINT2_LOCAL_Eigen3_INSTALL}") endif() - - - - + if (Python_EXECUTABLE) + list(APPEND library_CMAKE_ARGS "-DPython_EXECUTABLE=${Python_EXECUTABLE}") + endif() + if (LIBINT2_ENABLE_FORTRAN AND CMAKE_Fortran_COMPILER) + # Note: not handling CMAKE_Fortran_COMPILER_ARG1 + list(APPEND library_CMAKE_ARGS "-DCMAKE_Fortran_COMPILER=${CMAKE_Fortran_COMPILER}") + endif() ExternalProject_Add( library @@ -99,7 +171,7 @@ add_custom_target(libint-library-export DEPENDS "${EXPORT_STAGE_DIR}.tgz") BUILD_ALWAYS 1 # download generalized to generating source by unpacking source tarball # * DOWNLOAD_DIR is tidier but fails on Windows - URL "${EXPORT_STAGE_DIR}.tgz" + URL "${EXPORT_TARBALL}" LOG_DOWNLOAD 1 CMAKE_ARGS "${library_CMAKE_ARGS}" CMAKE_CACHE_ARGS @@ -108,4 +180,42 @@ add_custom_target(libint-library-export DEPENDS "${EXPORT_STAGE_DIR}.tgz") -DCMAKE_CXX_COMPILER_ARG1:STRING=${CMAKE_CXX_COMPILER_ARG1} -DCMAKE_C_COMPILER_ARG1:STRING=${CMAKE_C_COMPILER_ARG1} -DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH} + TEST_COMMAND "" + USES_TERMINAL_CONFIGURE TRUE + USES_TERMINAL_BUILD TRUE + USES_TERMINAL_INSTALL TRUE + STEP_TARGETS + build + install + ) + ExternalProject_Get_property(library BINARY_DIR) + + # instead of running tests by default, replicate check-libint2 target here + # and use it to invoke library's check-libint2 target + if (BUILD_TESTING) + include(AddCustomTargetSubproject) + add_custom_target_subproject( + libint2 check # target check-libint2 + USES_TERMINAL + COMMAND ${CMAKE_CTEST_COMMAND} -V -R "libint2/" + WORKING_DIRECTORY ${BINARY_DIR} + DEPENDS + "library-build" + ) + + if (LIBINT2_ENABLE_PYTHON) + add_custom_target_subproject( + libint2 check-python + USES_TERMINAL + COMMAND ${CMAKE_COMMAND} --build ${BINARY_DIR} --target libint2-python-test + WORKING_DIRECTORY ${BINARY_DIR}/python + ) + endif() + endif() + + install( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/include/libint2/basis.h" + DESTINATION "${STAGED_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/libint2" ) +endif() diff --git a/src/lib/libint/CMakeLists.txt.export b/src/lib/libint/CMakeLists.txt.export index 72e043505..0b602d2d9 100644 --- a/src/lib/libint/CMakeLists.txt.export +++ b/src/lib/libint/CMakeLists.txt.export @@ -29,12 +29,25 @@ set(pnv libint2) # projectnameversion # See "TARBALL" labels in INSTALL.md for elaboration of options, dependencies, & targets. ################################### Options #################################### +include(GNUInstallDirs) +include(CTest) include(options) include(CheckFunctionExists) # <<< General >>> -option_with_default(CMAKE_BUILD_TYPE "Build type" Release) +option_with_default(CMAKE_BUILD_TYPE + "Build type" Release) +option_with_print(BUILD_SHARED_LIBS + "Build Libint library as shared, not static" OFF) +option_with_print(LIBINT2_BUILD_SHARED_AND_STATIC_LIBS + "Build both shared and static Libint libraries in one shot. Uses -fPIC." OFF) +option_with_print(LIBINT2_REQUIRE_CXX_API + "C++11 Libint API: define library targets + test (requires Eigen3, Boost is optional but strongly recommended)" ON) +option_with_print(LIBINT2_REQUIRE_CXX_API_COMPILED + "Build C++11 Compiled (not just header-only) targets (requires Eigen3)" OFF) +option_with_print(LIBINT2_ENABLE_FORTRAN + "Build Fortran03+ Libint interface (requires C and Fortran and Python)" OFF) option_with_print(LIBINT2_ENABLE_MPFR "Use GNU MPFR library for high-precision testing (requires MPFR. EXPERTS ONLY)" OFF) option_with_print(LIBINT2_ENABLE_PYTHON @@ -46,18 +59,41 @@ option_with_print(LIBINT2_LOCAL_Eigen3_INSTALL option_with_print(CMAKE_DISABLE_FIND_PACKAGE_Boost "When Boost required for C++11 API, disable its detection, thereby forcing use of bundled Boost (Standard CMake variable: https://cmake.org/cmake/help/latest/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName.html)" OFF) - check_function_exists(posix_memalign HAVE_POSIX_MEMALIGN) if (HAVE_POSIX_MEMALIGN) option_with_default(LIBINT2_ALIGN_SIZE "(EXPERT) if posix_memalign is available, this will specify alignment of Libint data, in units of sizeof(LIBINT2_REALTYPE). Default is to use built-in heuristics." 0) mark_as_advanced(LIBINT2_ALIGN_SIZE) +elseif (MSVC) + # works for Windows in memory.h + set(LIBINT2_ALIGN_SIZE "0" CACHE STRING "") endif() option_with_default(LIBINT2_REALTYPE "Specifies the floating-point data type used by the library." double) +option_with_print(LIBINT_USER_DEFINED_REAL_INCLUDES + "UNTESTED Additional #includes necessary to use the real type." OFF) include(int_userreal) +if ((LIBINT2_REQUIRE_CXX_API_COMPILED OR LIBINT2_ENABLE_PYTHON) AND NOT LIBINT2_REQUIRE_CXX_API) + set(LIBINT2_REQUIRE_CXX_API 1) + message(STATUS "Setting option LIBINT2_REQUIRE_CXX_API=ON as needed by LIBINT2_REQUIRE_CXX_API_COMPILED=${LIBINT2_REQUIRE_CXX_API_COMPILED} and/or LIBINT2_ENABLE_PYTHON=${LIBINT2_ENABLE_PYTHON}.") +endif() + +if (LIBINT2_ENABLE_FORTRAN) + include(CheckLanguage) + check_language(Fortran) + if (CMAKE_Fortran_COMPILER) + enable_language(Fortran) + else() + message(FATAL_ERROR "Given LIBINT2_ENABLE_FORTRAN=ON but could not find Fortran compiler. Provide via CMAKE_Fortran_COMPILER") + endif() +endif() + +# <<< Miscellaneous >>> + +# next one defined by `include(CTest)` +message(STATUS "Showing option BUILD_TESTING: ${BUILD_TESTING}") # <<< Ordering Conventions >>> @@ -77,7 +113,7 @@ message(STATUS "Setting option LIBINT2_SHELL_SET: ${LIBINT2_SHELL_SET} (read-onl include(autocmake_safeguards) -################################## Dependencies ################################# +# ==== Dependencies =========================================================== # See notes at https://github.com/evaleev/libint/blob/master/INSTALL.md#prerequisites @@ -93,7 +129,7 @@ if (LIBINT2_ENABLE_MPFR) message(VERBOSE "${Cyan}Found MPFR${ColourReset}: ${_loc} (found version ${MPFR_VERSION})") endif() -#if (LIBINT2_REQUIRE_CXX_API) +if (LIBINT2_REQUIRE_CXX_API) if (NOT TARGET Boost::headers) find_package(Boost 1.57) endif() @@ -116,16 +152,15 @@ endif() message(FATAL_ERROR "Failed to unpack the bundled Boost! The tar command output:\n${UNPACK_BOOST_OUTPUT}") endif() endif() -#endif() +endif() find_package(Eigen3 MODULE) if (TARGET Eigen3::Eigen) set(LIBINT_HAS_EIGEN 1) endif() -#if (LIBINT2_REQUIRE_CXX_API AND NOT ${LIBINT_HAS_CXX_API}) -if (NOT LIBINT_HAS_EIGEN) # TODO tmp wrong logic - message(FATAL_ERROR "C++ API cannot be built without Eigen3; configure (via CMake) and install Eigen3 and add the install prefix to CMAKE_PREFIX_PATH, or add -DLIBINT2_REQUIRE_CXX_API=OFF to the CMake command line if the C++ API is not required") +if (LIBINT2_REQUIRE_CXX_API AND NOT ${LIBINT_HAS_EIGEN}) + message(FATAL_ERROR "C++ API cannot be built without Eigen3; configure (via CMake) and install Eigen3 and add the install prefix to CMAKE_PREFIX_PATH, or add -D LIBINT2_REQUIRE_CXX_API=OFF to the CMake command line if the C++ API is not required") endif() # Python is optionally used for testing. @@ -147,14 +182,504 @@ configure_file( include/libint2/config2.h.cmake.in include/libint2/config2.h @ONLY) -# configuration.cc defines a string summary of capabilities. @ONLY is maximally -# deferred in case config2 changes the summary (as it used to when -# LIBINT_SHGSHELL_ORDERING was library-config-time selected). configure_file( + # configuration.cc defines a string summary of capabilities. @ONLY is maximally + # deferred in case config2 changes the summary (as it used to when + # LIBINT_SHGSHELL_ORDERING was library-config-time selected). src/configuration.cc.cmake.in src/configuration.cc @ONLY) +set(DATADIR_ABSOLUTE ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/libint/${LIBINT_VERSION}) +configure_file( + include/libint2/basis.h.in # temp until libtool dropped and moved to basis.h.cmake.in + include/libint2/basis.h + @ONLY) + +include(srclist.cmake) +list(LENGTH LIBINT2_LIBRARY_CXX_SRC _source_count) +message(STATUS "Loading ${_source_count} library source files from LIBINT2_LIBRARY_CXX_SRC") +message(DEBUG "LIBINT2_LIBRARY_CXX_SRC=${LIBINT2_LIBRARY_CXX_SRC}") + +# Notes: +# * __COMPILING_LIBINT2 is needed whenever using libint targets in the build tree +# * MSVC does not include constants, unless _USE_MATH_DEFINES is defined +# * /EHsc sets the exception handling model (allows "throw") +# * _CRT_* squashs some getenv, strdup, strncpy, ctime, fopen warnings + +# ==== pre-user-targets: plain/C++(compiled) ================================== + +add_library( + int-obj + OBJECT + "${LIBINT2_LIBRARY_CXX_SRC}" + src/configuration.cc + ) +target_compile_features( + int-obj + PUBLIC + "cxx_std_11" # N.B. PUBLIC to make int-{static/shared} require C++11 + ) +target_compile_definitions( + int-obj + PRIVATE + __COMPILING_LIBINT2=1 + ) +set_target_properties( + int-obj + PROPERTIES + UNITY_BUILD TRUE # always use unity build for int-obj + ) +if (MSVC) + set_target_properties( + int-obj + PROPERTIES + LINK_FLAGS "/STACK:4194304" + # Increase stack size from 1 MB to 4 MB + ) +endif() +target_include_directories( + int-obj + PRIVATE + ${PROJECT_SOURCE_DIR}/include/ + ${PROJECT_BINARY_DIR}/include/ + ) + +if (LIBINT2_REQUIRE_CXX_API_COMPILED) + + add_library( + int-cxx-obj + OBJECT + src/engine.cpp + ) + target_compile_features( + int-cxx-obj + PUBLIC + "cxx_std_11" + ) + target_compile_definitions( + int-cxx-obj + PRIVATE + __COMPILING_LIBINT2=1 + LIBINT2_DOES_NOT_INLINE_ENGINE=1 + $<$:_USE_MATH_DEFINES> + $<$:_CRT_NONSTDC_NO_DEPRECATE> + $<$:_CRT_NONSTDC_NO_WARNINGS> + $<$:_CRT_SECURE_NO_WARNINGS> + ) + target_include_directories( + int-cxx-obj + PRIVATE + ${PROJECT_SOURCE_DIR}/include/ + ${PROJECT_BINARY_DIR}/include/ + ) + target_link_libraries ( + int-cxx-obj + PRIVATE + Eigen3::Eigen + $<$:Boost::headers> + ) + +endif() + +# plan shared, static, or both, then set fpic accordingly + +if (LIBINT2_BUILD_SHARED_AND_STATIC_LIBS OR BUILD_SHARED_LIBS) + set(L2_BUILD_SHARED_LIBS 1) +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 ========= + +if (L2_BUILD_SHARED_LIBS) + + add_library( + int-shared + SHARED + $ + ) + target_compile_features( + int-shared + INTERFACE + "cxx_std_11" + ) + target_compile_definitions( + int-shared + INTERFACE + $ + PUBLIC + $<$:_USE_MATH_DEFINES> + $<$:_CRT_NONSTDC_NO_DEPRECATE> + $<$:_CRT_NONSTDC_NO_WARNINGS> + $<$:_CRT_SECURE_NO_WARNINGS> + ) + target_compile_options( + int-shared + PUBLIC + $<$:/EHsc> + ) + set_target_properties( + int-shared + PROPERTIES + OUTPUT_NAME "int2" + ) + if (APPLE) + set_target_properties( + int-shared + PROPERTIES + LINK_FLAGS "-undefined dynamic_lookup" + ) + endif() + target_include_directories( + int-shared + INTERFACE + $ + $ + ) + + if (LIBINT2_REQUIRE_CXX_API) + + add_library( + int-cxx-headeronly-shared + INTERFACE + ) + target_compile_features( + int-cxx-headeronly-shared + INTERFACE + "cxx_std_11" + ) + target_compile_definitions( + int-cxx-headeronly-shared + INTERFACE + $ + ) + if (NOT MSVC) + # TODO fix the DATADIR define escaping on Windows + # * below works fine in tests + # * but fails in Psi4 compile + # * prefix replacement in conda used instead on Windows + target_compile_definitions( + int-cxx-headeronly-shared + INTERFACE + $ + ) + endif() + target_link_libraries( + int-cxx-headeronly-shared + INTERFACE + int-shared + Eigen3::Eigen + $<$:Boost::headers> + ) + + if (LIBINT2_REQUIRE_CXX_API_COMPILED) + + add_library( + int-cxx-shared + SHARED + $ + ) + target_compile_definitions( + int-cxx-shared + INTERFACE + $ + PUBLIC + LIBINT2_DOES_NOT_INLINE_ENGINE=1 + LIBINT2_CONSTEXPR_STATICS=1 # LAB: needed for tests, but correct in general, EFV? + $<$:_USE_MATH_DEFINES> + ) + target_compile_options( + int-cxx-shared + PUBLIC + $<$:/EHsc> + ) + set_target_properties( + int-cxx-shared + PROPERTIES + #SOVERSION ${LIBINT_MAJOR_SOVERSION} + MACOSX_RPATH ON + OUTPUT_NAME "int2-cxx" + ) + if (APPLE) + set_target_properties( + int-cxx-shared + PROPERTIES + LINK_FLAGS "-undefined dynamic_lookup" + ) + endif() + target_link_libraries( + int-cxx-shared + INTERFACE + int-cxx-headeronly-shared + ) + + endif (LIBINT2_REQUIRE_CXX_API_COMPILED) + endif (LIBINT2_REQUIRE_CXX_API) +endif (L2_BUILD_SHARED_LIBS) + +if (L2_BUILD_STATIC_LIBS) + + add_library( + int-static + STATIC + $ + ) + target_compile_features( + int-static + INTERFACE + "cxx_std_11" + ) + target_compile_definitions( + int-static + INTERFACE + $ + PUBLIC + $<$:_USE_MATH_DEFINES> + $<$:_CRT_NONSTDC_NO_DEPRECATE> + $<$:_CRT_NONSTDC_NO_WARNINGS> + $<$:_CRT_SECURE_NO_WARNINGS> + ) + target_compile_options( + int-static + PUBLIC + $<$:/EHsc> + ) + set_target_properties( + int-static + PROPERTIES + OUTPUT_NAME "int2" + ) + target_include_directories( + int-static + INTERFACE + $ + $ + ) + + if (LIBINT2_REQUIRE_CXX_API) + + add_library( + int-cxx-headeronly-static + INTERFACE + ) + target_compile_features( + int-cxx-headeronly-static + INTERFACE + "cxx_std_11" + ) + target_compile_definitions( + int-cxx-headeronly-static + INTERFACE + $ + ) + target_link_libraries( + int-cxx-headeronly-static + INTERFACE + int-static + Eigen3::Eigen + $<$:Boost::headers> + ) + + if (LIBINT2_REQUIRE_CXX_API_COMPILED) + + add_library( + int-cxx-static + STATIC + $ + ) + target_compile_definitions( + int-cxx-static + INTERFACE + $ + PUBLIC + LIBINT2_DOES_NOT_INLINE_ENGINE=1 + LIBINT2_CONSTEXPR_STATICS=1 # LAB: needed for tests, but correct in general, EFV? + $<$:_USE_MATH_DEFINES> + ) + target_compile_options( + int-cxx-static + PUBLIC + $<$:/EHsc> + ) + set_target_properties( + int-cxx-static + PROPERTIES + OUTPUT_NAME "int2-cxx" + #EXPORT_NAME "int2-cxx" + ) + target_link_libraries( + int-cxx-static + INTERFACE + int-cxx-headeronly-static + ) + + endif (LIBINT2_REQUIRE_CXX_API_COMPILED) + endif (LIBINT2_REQUIRE_CXX_API) +endif (L2_BUILD_STATIC_LIBS) + + +# ==== aliases ================================================================ + +# permanent aliases +# * used for tests + +if (L2_BUILD_SHARED_LIBS) + add_library(${L2}::int2 ALIAS int-shared) + if (LIBINT2_REQUIRE_CXX_API) + add_library(${L2}::cxx ALIAS int-cxx-headeronly-shared) + if (LIBINT2_REQUIRE_CXX_API_COMPILED) + add_library(${L2}::int2-cxx ALIAS int-cxx-shared) + endif() + endif() +elseif (L2_BUILD_STATIC_LIBS) + add_library(${L2}::int2 ALIAS int-static) + if (LIBINT2_REQUIRE_CXX_API) + add_library(${L2}::cxx ALIAS int-cxx-headeronly-static) + if (LIBINT2_REQUIRE_CXX_API_COMPILED) + add_library(${L2}::int2-cxx ALIAS int-cxx-static) + endif() + endif() +endif() + +# legacy (pre-2.9.0) aliases + +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) + endif() +endif() + + +# ==== Fortran bindings ======================================================= + +if (LIBINT2_ENABLE_FORTRAN) + # specify the location of modules + set(BUILDTREE_FMODDIR "fortran/modules") + + # preprocess libint2.h ... this is a guess for UNIX systems only + # N.B. Requires C compiler! + if (UNIX) + file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/fortran) + + include(CheckLanguage) + check_language(C) + if (CMAKE_C_COMPILER) + enable_language(C) + else() + message(FATAL_ERROR "Given LIBINT2_ENABLE_FORTRAN=ON but could not find C compiler needed to generate Fortran bindings, provide via CMAKE_C_COMPILER") + endif() + + # preprocessed libint.h + add_custom_command( + OUTPUT + ${PROJECT_BINARY_DIR}/fortran/libint2.h.i + COMMAND ${CMAKE_C_COMPILER} -E + -D__COMPILING_LIBINT2 + -I${PROJECT_SOURCE_DIR}/include + -I${PROJECT_SOURCE_DIR}/src + -I${PROJECT_BINARY_DIR}/include + -I${PROJECT_BINARY_DIR}/include/libint2 + ${PROJECT_SOURCE_DIR}/include/libint2.h + -o ${PROJECT_BINARY_DIR}/fortran/libint2.h.i + DEPENDS + ${PROJECT_SOURCE_DIR}/include/libint2.h + COMMENT "Generating libint2.h.i" + ) + else() + message(FATAL_ERROR "Cannot run preprocessor on non-Unix systems, disable Fortran to proceed") + endif() + + # translated Libint_t + add_custom_command( + OUTPUT + ${PROJECT_BINARY_DIR}/fortran/libint2_types_f.h + COMMAND ${Python_EXECUTABLE} ${PROJECT_SOURCE_DIR}/fortran/c_to_f.py ${PROJECT_BINARY_DIR}/fortran/libint2.h.i ${PROJECT_BINARY_DIR}/fortran/libint2_types_f.h Libint_t + DEPENDS + ${PROJECT_BINARY_DIR}/fortran/libint2.h.i + COMMENT "Generating libint2_types_f.h" + ) + + # extracted defines from libint2_types.h + add_custom_command( + OUTPUT + ${PROJECT_BINARY_DIR}/fortran/fortran_incldefs.h + COMMAND ${Python_EXECUTABLE} ${PROJECT_SOURCE_DIR}/fortran/make_defs.py ${PROJECT_SOURCE_DIR}/include/libint2_types.h ${PROJECT_BINARY_DIR}/fortran/fortran_incldefs.h + DEPENDS + ${PROJECT_SOURCE_DIR}/include/libint2_types.h + COMMENT "Generating fortran_incldefs.h" + ) + + # build module + 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 + ) + set_target_properties( + libint_f + PROPERTIES + Fortran_MODULE_DIRECTORY ${PROJECT_BINARY_DIR}/${BUILDTREE_FMODDIR} + ) + if (BUILD_SHARED_LIBS) + set_target_properties(libint_f PROPERTIES POSITION_INDEPENDENT_CODE 1) + endif() + target_include_directories( + libint_f + PUBLIC + $ + $ + $ + $ + ) + + # Fortran tests merged into rest of tests + +endif (LIBINT2_ENABLE_FORTRAN) + + +# ==== Python bindings ======================================================== + +if (LIBINT2_ENABLE_PYTHON) + add_subdirectory(python EXCLUDE_FROM_ALL) +endif() + + +if (BUILD_TESTING) + add_subdirectory(tests) +endif() + configure_package_config_file( cmake/${pnv}-config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/${pnv}-config.cmake" diff --git a/src/lib/libint/engine.cpp b/src/lib/libint/engine.cpp new file mode 100644 index 000000000..b6d4735b1 --- /dev/null +++ b/src/lib/libint/engine.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2022-2024 Edward F. Valeev + * + * This file is part of Libint. + * + * Libint is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Libint is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Libint. If not, see . + * + */ + +#include + +// need to instantiate this just in case user constructs a libint2::Engine using +// default operator params +template __libint2_engine_inline libint2::any +libint2::Engine::enforce_params_type< + libint2::detail::default_operator_traits::oper_params_type>( + libint2::Operator oper, + const libint2::detail::default_operator_traits::oper_params_type& params, + bool throw_if_wrong_type); diff --git a/src/lib/libint/populate.cmake b/src/lib/libint/populate.cmake index fd18ee353..11227811f 100644 --- a/src/lib/libint/populate.cmake +++ b/src/lib/libint/populate.cmake @@ -1,5 +1,130 @@ set(LIBRARY_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src/lib/libint) +# ==== /doc =================================================================== + +file( + INSTALL + "${PROJECT_SOURCE_DIR}/doc/progman/progman.tex" + "${PROJECT_SOURCE_DIR}/doc/progman/refs.bib" + "${PROJECT_SOURCE_DIR}/doc/Libint_Logo3_alt.pdf" + "${PROJECT_SOURCE_DIR}/doc/Libint_Logo3_alt.eps" + DESTINATION "${EXPORT_STAGE_DIR}/doc" + ) + +file( + INSTALL + "${PROJECT_SOURCE_DIR}/doc/progman/" + DESTINATION "${EXPORT_STAGE_DIR}/doc" + FILES_MATCHING + PATTERN "*.cc" + ) + +# ==== /tests ================================================================= + +file( + INSTALL + "${PROJECT_SOURCE_DIR}/tests/" + DESTINATION "${EXPORT_STAGE_DIR}/tests" + FILES_MATCHING + PATTERN "*.c" + PATTERN "*.cc" + PATTERN "*.h" + PATTERN "*.hpp" + PATTERN "*.F90" + PATTERN "*.py" + PATTERN "*.xyz" + PATTERN "hftest.cmake" + PATTERN "CMakeLists.txt" + # PATTERN "ssss.nb" + ) + +file( + INSTALL + "${PROJECT_SOURCE_DIR}/export/fortran/fortran_example.F90" + DESTINATION "${EXPORT_STAGE_DIR}/tests/fortran" + ) + +file(READ "${PROJECT_SOURCE_DIR}/export/fortran/test.cc" _file_contents) +string(REPLACE "tests/unit" "unit" _file_contents "${_file_contents}") +file(WRITE "${EXPORT_STAGE_DIR}/tests/fortran/test.cc" "${_file_contents}") + +file(READ "${PROJECT_SOURCE_DIR}/export/fortran/test-eri.cc" _file_contents) +string(REPLACE "tests/unit" "unit" _file_contents "${_file_contents}") +string(REPLACE "tests/eri" "eri" _file_contents "${_file_contents}") +file(WRITE "${EXPORT_STAGE_DIR}/tests/fortran/test-eri.cc" "${_file_contents}") + +file( + INSTALL + "${PROJECT_SOURCE_DIR}/src/bin/test_eri/eri.h" + "${PROJECT_SOURCE_DIR}/src/bin/test_eri/prep_libint2.h" + DESTINATION "${EXPORT_STAGE_DIR}/tests/eri" + ) + +# ==== /lib/basis ============================================================= + +file( + INSTALL + "${PROJECT_SOURCE_DIR}/lib/basis/" + DESTINATION "${EXPORT_STAGE_DIR}/lib/basis" + FILES_MATCHING + PATTERN "*.g94" + ) + +# file(INSTALL) preserves symlinks, and tar -xf fails on them on Windows (either +# the symlink extracted before the target file or problems with the stars in +# filenames themselves). To make export tarballs broadly usable, we'll copy +# the symlinked files into real files, which is what libtool effectively did. +file( + COPY_FILE + "${PROJECT_SOURCE_DIR}/lib/basis/6-31gs.g94" + "${EXPORT_STAGE_DIR}/lib/basis/6-31gs.g94" + ) +file( + COPY_FILE + "${PROJECT_SOURCE_DIR}/lib/basis/6-31gss.g94" + "${EXPORT_STAGE_DIR}/lib/basis/6-31gss.g94" + ) +file( + COPY_FILE + "${PROJECT_SOURCE_DIR}/lib/basis/6-311gss.g94" + "${EXPORT_STAGE_DIR}/lib/basis/6-311gss.g94" + ) + +# ==== /fortran =============================================================== + +file( + INSTALL + "${PROJECT_SOURCE_DIR}/export/fortran/c_to_f.py" + "${PROJECT_SOURCE_DIR}/export/fortran/make_defs.py" + "${PROJECT_SOURCE_DIR}/export/fortran/libint_f.F90" + DESTINATION "${EXPORT_STAGE_DIR}/fortran" + ) + +# ==== /python ================================================================ + +file( + INSTALL + "${PROJECT_SOURCE_DIR}/python/" + DESTINATION "${EXPORT_STAGE_DIR}/python" + FILES_MATCHING + PATTERN "*.h" + PATTERN "*.cc" + PATTERN "*.py" + PATTERN "*.py.in" + PATTERN "*.toml" + PATTERN "CMakeLists.txt" + ) + +# ==== /external ============================================================== + +file( + INSTALL + "${PROJECT_SOURCE_DIR}/external/boost.tar.gz" + DESTINATION "${EXPORT_STAGE_DIR}/external" + ) + +# ==== /cmake ================================================================= + file( INSTALL "${PROJECT_SOURCE_DIR}/cmake/modules/autocmake_safeguards.cmake" @@ -10,6 +135,7 @@ file( "${PROJECT_SOURCE_DIR}/cmake/modules/int_checkboost.cmake" "${PROJECT_SOURCE_DIR}/cmake/modules/FindMultiprecision.cmake" "${PROJECT_SOURCE_DIR}/cmake/modules/FindEigen3.cmake" + "${PROJECT_SOURCE_DIR}/cmake/modules/AddCustomTargetSubproject.cmake" DESTINATION "${EXPORT_STAGE_DIR}/cmake/modules" ) @@ -19,13 +145,96 @@ file( DESTINATION "${EXPORT_STAGE_DIR}/cmake" ) -configure_file( - "${LIBRARY_SOURCE_DIR}/CMakeLists.txt.export" - "${EXPORT_STAGE_DIR}/CMakeLists.txt" - COPYONLY) +# ==== /include =============================================================== + +file( + INSTALL + "${PROJECT_SOURCE_DIR}/include/libint2.h" + "${PROJECT_SOURCE_DIR}/include/libint2.hpp" + DESTINATION "${EXPORT_STAGE_DIR}/include" + ) + +# Note that libint2_iface.h, libint2_params.h, libint2_types.h shift around. +# They're generated along with the integrals .h/.cc library src, then get +# exported to include/ (along with the integrals .h), then are finally +# installed (not with the integrals .h) into include/libint2/ . The +# __COMPILING_LIBINT define and the include/libint2/util/generated/libint2_*.h +# redirection headers take care of the "build tree"/"export" setup. +# In a cmake+cmake buildsystem, one could probably install these three headers +# to both locations and forego the define. +file( + INSTALL + "${PROJECT_BINARY_DIR}/generated/" + DESTINATION "${EXPORT_STAGE_DIR}/include" + FILES_MATCHING + PATTERN "*.h" + ) + +file( + INSTALL + "${PROJECT_SOURCE_DIR}/src/bin/libint/util_types.h" + DESTINATION "${EXPORT_STAGE_DIR}/include" + ) + +file( + INSTALL + "${LIBRARY_SOURCE_DIR}/" + DESTINATION "${EXPORT_STAGE_DIR}/include" + FILES_MATCHING + PATTERN "*.h" + ) + +# ==== /include/libint2 ======================================================= file( INSTALL + "${PROJECT_SOURCE_DIR}/include/libint2/" + DESTINATION "${EXPORT_STAGE_DIR}/include/libint2" + FILES_MATCHING + PATTERN "*.h" + PATTERN "*.h.cmake.in" + PATTERN "basis.h.in" # TODO basis.h.cmake.in after libtool retires + ) + +# ==== /src =================================================================== + +file( + INSTALL + "${PROJECT_SOURCE_DIR}/src/lib/libint/engine.cpp" "${PROJECT_SOURCE_DIR}/src/lib/libint/configuration.cc.cmake.in" DESTINATION "${EXPORT_STAGE_DIR}/src" ) + +file( + INSTALL + "${PROJECT_BINARY_DIR}/generated/" + DESTINATION "${EXPORT_STAGE_DIR}/src" + FILES_MATCHING + PATTERN "*.cc" + ) + +file(GLOB generated_sources_list RELATIVE "${EXPORT_STAGE_DIR}" "${EXPORT_STAGE_DIR}/src/*.cc") +file(WRITE ${EXPORT_STAGE_DIR}/srclist.cmake "set(LIBINT2_LIBRARY_CXX_SRC \"${generated_sources_list}\" )") + +# ==== / ====================================================================== + +configure_file( + "${PROJECT_SOURCE_DIR}/export/LICENSE.export" + "${EXPORT_STAGE_DIR}/LICENSE" + COPYONLY) + +file( + INSTALL + "${PROJECT_SOURCE_DIR}/INSTALL" + "${PROJECT_SOURCE_DIR}/INSTALL.md" + "${PROJECT_SOURCE_DIR}/COPYING" + "${PROJECT_SOURCE_DIR}/COPYING.LESSER" + "${PROJECT_SOURCE_DIR}/CITATION" + "${PROJECT_SOURCE_DIR}/README.md" + DESTINATION "${EXPORT_STAGE_DIR}" + ) + +configure_file( + "${LIBRARY_SOURCE_DIR}/CMakeLists.txt.export" + "${EXPORT_STAGE_DIR}/CMakeLists.txt" + COPYONLY) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 000000000..ca2b48249 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,315 @@ +include(AddCustomTargetSubproject) +add_custom_target_subproject( + libint2 check # target check-libint2 + USES_TERMINAL + COMMAND ${CMAKE_CTEST_COMMAND} -V -R "libint2/" + ) + +# Note: if forming compile line by hand rather than using targets, you'll need +# to include the header toggle if compiling within the build tree (as opposed +# to linking to installed targets): +# `target_compile_definitions(... PRIVATE -D__COMPILING_LIBINT2=1)` + +## Tests ======================================================================== + +add_executable( + eritest-libint2 + EXCLUDE_FROM_ALL + eri/test.cc + ) +target_include_directories( + eritest-libint2 + PRIVATE + eri # src/bin/test_eri/eri.h + # see note on eri.h at unit_tests-libint2 + ) +target_compile_definitions( + eritest-libint2 + PRIVATE + $<$:LIBINT_HAS_MPFR=1> + ) +target_link_libraries( + eritest-libint2 + PRIVATE + Libint2::int2 # N.B. plain library + $<$:Multiprecision::mpfr> + $<$:Multiprecision::gmpxx> + ) +add_test( # Test #1 + NAME libint2/eritest/build + COMMAND "${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target eritest-libint2 + ) +set_tests_properties( + libint2/eritest/build + PROPERTIES + FIXTURES_SETUP LIBINT2_ERITEST_EXEC + ) +add_test( # Test #2 + NAME libint2/eritest/run0 + COMMAND $ 0 2 + ) +add_test( # Test #3 + NAME libint2/eritest/run1 + COMMAND $ 1 1 + ) +add_test( # Test #4 + NAME libint2/eritest/run2 + COMMAND $ 2 1 + ) +add_test( # Test #5 + NAME libint2/eritest/run3 + COMMAND $ 3 1 + ) +add_test( # Test #6 + NAME libint2/eritest/run4 + COMMAND $ 4 1 + ) +set_tests_properties( + libint2/eritest/run0 + libint2/eritest/run1 + libint2/eritest/run2 + libint2/eritest/run3 + libint2/eritest/run4 + PROPERTIES + FIXTURES_REQUIRED LIBINT2_ERITEST_EXEC + ) + +if (LIBINT2_REQUIRE_CXX_API) + + set(utests_src + unit/catch.hpp + unit/fixture.h + unit/test-1body.cc + unit/test-2body.cc + unit/test-basis.cc + unit/test-core.cc + unit/test-core-ints.cc + unit/test-permute.cc + unit/test-precision.cc + unit/test-shell-order.cc + unit/test-util.cc + ) + # if have C, also test C bindings + include(CheckLanguage) + check_language(C) + if (CMAKE_C_COMPILER) + enable_language(C) + list(APPEND unit_tests-src + unit/c-api.c + unit/c-api-util.cc + unit/test-c-api.cc + ) + endif() + add_executable( + unit_tests-libint2 + EXCLUDE_FROM_ALL + unit/test.cc + ${utests_src} + ) + target_compile_definitions( + unit_tests-libint2 + PRIVATE + NO_LIBINT_COMPILER_CODE # src/bin/test_eri/eri.h + # note there's two ways to use eri.h, depending on the test src. eritest-libint2 uses the other. + $<$:LIBINT_HAS_MPFR=1> + ) + target_link_libraries( + unit_tests-libint2 + PRIVATE + $,Libint2::int2-cxx,Libint2::cxx> + # N.B. cxx compiled library if LIBINT2_REQUIRE_CXX_API_COMPILED=ON else header-only library + $<$:Multiprecision::mpfr> + $<$:Multiprecision::gmpxx> + $<$:Multiprecision::gmp> + # MPFR: numeric.h:175:23: error: cannot convert 'const char*' to 'double' in initialization: To to(ss.str().c_str()); + ) + add_test( # Test #7 + NAME libint2/unit/build + COMMAND "${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target unit_tests-libint2 + ) + set_tests_properties( + libint2/unit/build + PROPERTIES + FIXTURES_SETUP LIBINT2_UNIT_TESTS_EXEC + ) + add_test( # Test #8 + NAME libint2/unit/run + COMMAND $ + ) + add_test( # Test #9 + NAME libint2/unit/sho=gaussian/run + COMMAND $ --shgshell-order=gaussian + ) + set_tests_properties( + libint2/unit/run + libint2/unit/sho=gaussian/run + PROPERTIES + FIXTURES_REQUIRED LIBINT2_UNIT_TESTS_EXEC + ) + + add_executable( + hf-libint2 + EXCLUDE_FROM_ALL + hartree-fock/hartree-fock.cc + ) + target_link_libraries( + hf-libint2 + PRIVATE + $,Libint2::int2-cxx,Libint2::cxx> + # N.B. cxx compiled library if LIBINT2_REQUIRE_CXX_API_COMPILED=ON else header-only library + ) + add_test( # Test #10 + NAME libint2/hf/build + COMMAND "${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target hf-libint2 + ) + set_tests_properties( + libint2/hf/build + PROPERTIES + FIXTURES_SETUP LIBINT2_HFTEST_EXEC + ) + if (Python_Interpreter_FOUND) + add_test( # Test #11 + NAME libint2/hf/run + COMMAND ${CMAKE_COMMAND} + -DexecName=hf-libint2 + -DtestName=hartree-fock + -DtestArgs=${PROJECT_SOURCE_DIR}/tests/hartree-fock/h2o.xyz + -DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR} + -DPROJECT_BINARY_DIR=${PROJECT_BINARY_DIR} + -DpythonExec=${Python_EXECUTABLE} + -P ${PROJECT_SOURCE_DIR}/tests/hartree-fock/hftest.cmake + ) + else() + add_test( # Test #11 alt. + NAME libint2/hf/run + COMMAND $ ${PROJECT_SOURCE_DIR}/tests/hartree-fock/h2o.xyz + ) + endif() + set_tests_properties( + libint2/hf/run + PROPERTIES + FIXTURES_REQUIRED LIBINT2_HFTEST_EXEC + ) + + add_executable( + hf++-libint2 + EXCLUDE_FROM_ALL + hartree-fock/hartree-fock++.cc + ) + find_package(Threads) # for some reason clang does not link in threading support even though we are using C++ threads + target_link_libraries( + hf++-libint2 + PRIVATE + Libint2::cxx + Threads::Threads + # mostly errors for int2-cxx (excpet some Linux configurations) + # $,Libint2::int2-cxx,Libint2::cxx> + ) + add_test( # Test #12 + NAME libint2/hf++/build + COMMAND "${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target hf++-libint2 + ) + set_tests_properties( + libint2/hf++/build + PROPERTIES + FIXTURES_SETUP LIBINT2_HFXXTEST_EXEC + ) + if (Python_Interpreter_FOUND) + add_test( # Test #13 + NAME libint2/hf++/run + COMMAND ${CMAKE_COMMAND} + -DexecName=hf++-libint2 + -DtestName=hartree-fock++ + -DtestArgs=${PROJECT_SOURCE_DIR}/tests/hartree-fock/h2o_rotated.xyz + -DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR} + -DPROJECT_BINARY_DIR=${PROJECT_BINARY_DIR} + -DpythonExec=${Python_EXECUTABLE} + -P ${PROJECT_SOURCE_DIR}/tests/hartree-fock/hftest.cmake + ) + else() + add_test( # Test #13 alt. + NAME libint2/hf++/run + COMMAND $ ${PROJECT_SOURCE_DIR}/tests/hartree-fock/h2o_rotated.xyz + ) + endif() + set_tests_properties( + libint2/hf++/run + PROPERTIES + FIXTURES_REQUIRED LIBINT2_HFXXTEST_EXEC + ) + +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 + fortran/fortran_example.F90 + ) + target_link_libraries( + fortran_example-libint2 + PRIVATE + Libint2::int2 + libint_f + ) + add_test( # Test #14 + NAME libint2/fortran_example/build + COMMAND "${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target fortran_example-libint2 + ) + set_tests_properties( + libint2/fortran_example/build + PROPERTIES + FIXTURES_SETUP LIBINT2_FORTRAN_EXAMPLE_EXEC + ) + add_test( # Test #15 + NAME libint2/fortran_example/run + COMMAND $ + ) + set_tests_properties( + libint2/fortran_example/run + PROPERTIES + FIXTURES_REQUIRED LIBINT2_FORTRAN_EXAMPLE_EXEC + ) + + if (LIBINT2_REQUIRE_CXX_API) + + add_executable( + fortran_test-libint2 + 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 + ) + add_test( # Test #16 + NAME libint2/fortran_test/build + COMMAND "${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target fortran_test-libint2 + ) + set_tests_properties( + libint2/fortran_test/build + PROPERTIES + FIXTURES_SETUP LIBINT2_FORTRAN_TEST_EXEC + ) + add_test( # Test #17 + NAME libint2/fortran_test/run + COMMAND $ + ) + set_tests_properties( + libint2/fortran_test/run + PROPERTIES + FIXTURES_REQUIRED LIBINT2_FORTRAN_TEST_EXEC + ) + + endif (LIBINT2_REQUIRE_CXX_API) +endif (LIBINT2_ENABLE_FORTRAN) diff --git a/tests/hartree-fock/hftest.cmake b/tests/hartree-fock/hftest.cmake new file mode 100644 index 000000000..92442cd0e --- /dev/null +++ b/tests/hartree-fock/hftest.cmake @@ -0,0 +1,44 @@ + +macro(runtest) + + set(OUTPUT_FILE_NAME "${PROJECT_BINARY_DIR}/tests/${testName}.out") + + set(CHECK_CMD "${pythonExec}" "${PROJECT_SOURCE_DIR}/tests/hartree-fock/${testName}-validate.py") + if (testName STREQUAL "hartree-fock++") + set(CHECK_ARGS "${PROJECT_SOURCE_DIR}/features") + endif() + + execute_process(COMMAND + ${PROJECT_BINARY_DIR}/tests/${execName} ${testArgs} + OUTPUT_FILE "${OUTPUT_FILE_NAME}" + RESULT_VARIABLE TEST_RESULT) + + if(TEST_RESULT) + message(STATUS "\nOUTPUT of " ${PROJECT_BINARY_DIR}/tests/${execName} " with args " ${testArgs}) + execute_process(COMMAND + cat + ${OUTPUT_FILE_NAME} + RESULT_VARIABLE + CAT_RESULT + ) + message(FATAL_ERROR "Error running ${PROJECT_BINARY_DIR}/tests/${execName}") + endif(TEST_RESULT) + + execute_process(COMMAND + ${CHECK_CMD} ${CHECK_ARGS} ${OUTPUT_FILE_NAME} + RESULT_VARIABLE CHECK_RESULT) + + if(CHECK_RESULT) + message(STATUS "\nOUTPUT of " ${CHECK_CMD}) + execute_process(COMMAND + cat + ${OUTPUT_FILE_NAME} + RESULT_VARIABLE + CAT_RESULT + ) + message(FATAL_ERROR "Error running ${CHECK_CMD} with args " ${CHECK_ARGS} " " ${OUTPUT_FILE_NAME}) + endif(CHECK_RESULT) + +endmacro(runtest) + +runtest()