diff --git a/.github/workflows/ci_cmake.yml b/.github/workflows/ci_cmake.yml new file mode 100644 index 000000000..3edba671b --- /dev/null +++ b/.github/workflows/ci_cmake.yml @@ -0,0 +1,121 @@ +name: BuildCM + +on: + push: + branches: + - master + pull_request: + +jobs: + build_repo: + strategy: + fail-fast: false + matrix: + build_type : [ Release, Debug ] + os : [ macos-latest, ubuntu-20.04 ] + include: + - os: ubuntu-20.04 + cxx: g++-10 + cc: gcc-10 + - 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@10 boost eigen ccache python@3.11 numpy scipy + echo "FC=/usr/local/bin/gfortran-10" >> $GITHUB_ENV + echo "EIGEN3_INCLUDE_DIR=/usr/local/include/eigen3" >> $GITHUB_ENV + + - name: Install prerequisite Ubuntu packages + if: ${{ steps.skip_check.outputs.should_skip != 'true' && matrix.os == 'ubuntu-20.04' }} + run: | + sudo apt-get update + sudo apt-get install ninja-build g++-10 gfortran-10 liblapack-dev libboost-dev libeigen3-dev ccache python3-numpy python3-scipy + echo "FC=/usr/bin/gfortran-10" >> $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 ce187abc9..d313421ea 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -4,7 +4,7 @@ on: push: branches: - master - pull_request: + #pull_request: jobs: build_repo: diff --git a/CMakeLists.txt b/CMakeLists.txt index ceb598af6..0813855f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,10 @@ if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0") # 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() ############################# Version and Metadata ############################# @@ -103,9 +107,6 @@ option_with_default(LIBINT2_ENABLE_PYTHON option_with_default(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(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 >>> @@ -262,10 +263,15 @@ option_with_print(LIBINT_FLOP_COUNT "Support (approximate) FLOP counting by the library. (Generated code will require C++11!)" OFF) 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) +# next one defined by `include(CTest)` +message(STATUS "Showing option BUILD_TESTING: ${BUILD_TESTING}") - +# <<< Path >>> ######################## Process & Validate Options ########################### +include(autocmake_safeguards) include(CheckFunctionExists) include(CheckIncludeFileCXX) include(FeatureSummary) diff --git a/INSTALL.md b/INSTALL.md index 012d12fcf..725a0a6c3 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -58,6 +58,29 @@ The Libint build is structured into three parts: - (7) optional Python build alongside library or afterwards. optional testing requires library install +Command-line synopsis. See [table](#Build-Targets) for `--target` choices (steps refer to numbered bullets above) and [section](#Configuring-Libint) for `-D options` choices. + +```bash +>>> git clone https://github.com/evaleev/libint.git && cd libint +>>> ls +cmake/ COPYING src/ tests/ ... +>>> cmake -S. -Bbuild -GNinja -DCMAKE_INSTALL_PREFIX=/path/to/future/install-libint -D options ... +... +-- Generating done +-- Build files have been written to: /current/dir/build +>>> cmake --build build --target install +``` + +### Build Targets + +| `--target ...` | incl. | steps | ( | see | above | ) | | (TARBALL) `--target ...` [^25] | +| -------------- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ------------------------------ | +| `build_libint` | 1 | - | - | - | - | - | - | n/a | +| `check-libint2compiler` | 1 | 2 | - | - | - | - | - | n/a | + +[^25]: (TARBALL) targets can include steps 4 onwards; the starting tarball itself is the product of step 3. + + ----------------------------------------------------------------------------- # Prerequisites diff --git a/cmake/modules/AddCustomTargetSubproject.cmake b/cmake/modules/AddCustomTargetSubproject.cmake new file mode 100644 index 000000000..d575d9fc4 --- /dev/null +++ b/cmake/modules/AddCustomTargetSubproject.cmake @@ -0,0 +1,46 @@ +# Copyright 2020 Eduard F Valeyev +# Distributed under the OSI-approved BSD 3-Clause License. +# See https://opensource.org/licenses/BSD-3-Clause for details. + +# copy of https://github.com/BTAS/BTAS/blob/master/cmake/modules/AddCustomTargetSubproject.cmake +# +# add_custom_target_subproject(proj X ...) defines custom target X-proj and +# - if target X already exists, makes it depend on X-proj +# - else creates target X depending on X-proj +# +# use case: if custom target names (e.g. "check", "doc", etc.) clash +# with other project's target when used as a subproject +# +# example: add_custom_target_subproject(myproject check USES_TERMINAL COMMAND ${CMAKE_CTEST_COMMAND} -V) +# + +macro(add_custom_target_subproject _subproj _name) + + set(extra_args "${ARGN}") + add_custom_target(${_name}-${_subproj} ${extra_args}) + + # does the newly-created target get compiled by default? + list(FIND extra_args "ALL" extra_args_has_all) + if (NOT (extra_args_has_all EQUAL -1)) + set (target_built_by_default ON) + endif() + + if (TARGET ${_name}) + # is existing target ${_name} also compiled by default? + # warn if not, but this project's target is since that + # may indicate inconsistent creation of generic targets + get_target_property(supertarget_not_built_by_default ${_name} EXCLUDE_FROM_ALL) + if (target_built_by_default AND supertarget_not_built_by_default) + message(WARNING "Created target ${_name}-${_subproj} is built by default but \"super\"-target ${_name} is not; perhaps it should be?") + endif() + add_dependencies(${_name} ${_name}-${_subproj}) + else (TARGET ${_name}) + # use ALL if given + if (target_built_by_default) + add_custom_target(${_name} ALL DEPENDS ${_name}-${_subproj}) + else (target_built_by_default) + add_custom_target(${_name} DEPENDS ${_name}-${_subproj}) + endif(target_built_by_default) + endif (TARGET ${_name}) + +endmacro() diff --git a/cmake/modules/autocmake_safeguards.cmake b/cmake/modules/autocmake_safeguards.cmake new file mode 100644 index 000000000..cf7d56757 --- /dev/null +++ b/cmake/modules/autocmake_safeguards.cmake @@ -0,0 +1,27 @@ +# Downloaded from +# https://github.com/coderefinery/autocmake/blob/master/modules/safeguards.cmake +# * changed text of in-source message + +#.rst: +# +# Provides safeguards against in-source builds and bad build types. +# +# Variables used:: +# +# PROJECT_SOURCE_DIR +# PROJECT_BINARY_DIR +# CMAKE_BUILD_TYPE + +if(${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR}) + message(FATAL_ERROR "In-source builds not allowed. Please run CMake from top directory and specify a build directory (e.g., cmake -S. -Bbuild).") +endif() + +string(TOLOWER "${CMAKE_BUILD_TYPE}" cmake_build_type_tolower) +string(TOUPPER "${CMAKE_BUILD_TYPE}" cmake_build_type_toupper) + +if(NOT cmake_build_type_tolower STREQUAL "debug" AND + NOT cmake_build_type_tolower STREQUAL "release" AND + NOT cmake_build_type_tolower STREQUAL "minsizerel" AND + NOT cmake_build_type_tolower STREQUAL "relwithdebinfo") + message(FATAL_ERROR "Unknown build type \"${CMAKE_BUILD_TYPE}\". Allowed values are Debug, Release, MinSizeRel, RelWithDebInfo (case-insensitive).") +endif() diff --git a/include/libint2/config.h.cmake.in b/include/libint2/config.h.cmake.in index 6cf5ea2a5..723f28cb2 100644 --- a/include/libint2/config.h.cmake.in +++ b/include/libint2/config.h.cmake.in @@ -326,6 +326,22 @@ #define LIBINT_DEPRECATED(msg) LIBINT_XPRAGMA( LIBINT_CONCAT(message, msg) ) #endif +#ifdef __has_cpp_attribute +#if __has_cpp_attribute(maybe_unused) +#define LIBINT_MAYBE_UNUSED [[maybe_unused]] +#endif +#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 +#define LIBINT_MAYBE_UNUSED +#endif + #if @_EXPORT_MODE@ #include "libint2/config2.h" #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3ea7a4199..cae71bb62 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1 +1,2 @@ +add_subdirectory(bin) add_subdirectory(lib) diff --git a/src/bin/CMakeLists.txt b/src/bin/CMakeLists.txt new file mode 100644 index 000000000..2bcf79f3a --- /dev/null +++ b/src/bin/CMakeLists.txt @@ -0,0 +1,15 @@ +add_subdirectory(libint) + +include(AddCustomTargetSubproject) +add_custom_target_subproject( + libint2compiler + check + USES_TERMINAL + COMMAND ${CMAKE_CTEST_COMMAND} -V -R "libint2/compiler" + ) + +if (BUILD_TESTING) + add_subdirectory(test_eri) + # borrows main libint/test.cc from libtool layout + add_subdirectory(profile) +endif() diff --git a/src/bin/libint/CMakeLists.txt b/src/bin/libint/CMakeLists.txt new file mode 100644 index 000000000..f9b82c565 --- /dev/null +++ b/src/bin/libint/CMakeLists.txt @@ -0,0 +1,103 @@ +add_library( + libint-libcompiler + STATIC + algebra.cc + buildtest.cc + class_registry.cc + code.cc + codeblock.cc + comp_deriv_gauss.cc + comp_xyz.cc + context.cc + default_params.cc + dg.cc + dgarc.cc + dgvertex.cc + dims.cc + drtree.cc + extract.cc + flop.cc + gauss.cc + graph_registry.cc + iface.cc + iter.cc + memory.cc + multipole.cc + oper.cc + policy.cc + policy_spec.cc + prefactors.cc + purgeable.cc + rr.cc + strategy.cc + tactic.cc + task.cc + util.cc + ) + +target_compile_definitions( + libint-libcompiler + PUBLIC + __COMPILING_LIBINT2=1 + # MSVC does not include constants, unless _USE_MATH_DEFINES is defined. + $<$:_USE_MATH_DEFINES> + ) + +target_compile_options( + libint-libcompiler + PUBLIC + # Set the exception handling model (allows "throw") + $<$:"/EHsc"> + ) + +target_compile_features( + libint-libcompiler + PUBLIC + "cxx_std_11" + ) + +set_target_properties( + libint-libcompiler + PROPERTIES + CXX_EXTENSIONS OFF + UNITY_BUILD FALSE # do not use unity build for build_libint + LIBRARY_OUTPUT_NAME int2-libcompiler + ARCHIVE_OUTPUT_NAME int2-libcompiler + ) + +target_include_directories( + libint-libcompiler + PUBLIC + ${PROJECT_BINARY_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR}/include + ) + +target_link_libraries( + libint-libcompiler + PUBLIC + Boost::headers + Multiprecision::gmpxx + ) + +add_executable( + build_libint + EXCLUDE_FROM_ALL + build_libint.cc + ) +target_link_libraries(build_libint libint-libcompiler) + +if(MSVC) + # Increase stack size from 1 MB to 4 MB + set_target_properties( + build_libint + PROPERTIES + LINK_OPTIONS "/STACK:4194304" + ) +endif() + +set_target_properties( + build_libint + PROPERTIES + INSTALL_RPATH_USE_LINK_PATH TRUE + ) diff --git a/src/bin/profile/CMakeLists.txt b/src/bin/profile/CMakeLists.txt new file mode 100644 index 000000000..af20c491b --- /dev/null +++ b/src/bin/profile/CMakeLists.txt @@ -0,0 +1,54 @@ +add_executable( + libint-libcompiler-test + EXCLUDE_FROM_ALL + ../libint/test.cc + ) +target_link_libraries(libint-libcompiler-test libint-libcompiler) +target_compile_definitions( + libint-libcompiler-test + PRIVATE + # https://stackoverflow.com/a/65813178 + BOOST_BIND_GLOBAL_PLACEHOLDERS + ) + +add_executable( + libint-kernel-profile + EXCLUDE_FROM_ALL + profile.cc + ) +target_link_libraries(libint-kernel-profile libint-libcompiler) + +add_executable( + libint-chrono-util + EXCLUDE_FROM_ALL + chrono.cc + ) +target_link_libraries(libint-chrono-util libint-libcompiler) + +set_target_properties( + libint-libcompiler-test + libint-kernel-profile + libint-chrono-util + PROPERTIES + INSTALL_RPATH_USE_LINK_PATH TRUE + ) + +add_test( + NAME libint2/compiler/coretest/build + COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target libint-libcompiler-test + ) +set_tests_properties( + libint2/compiler/coretest/build + PROPERTIES + FIXTURES_SETUP LIBINT2_COMPILER_CORETEST_EXEC + ) + +add_test( + NAME libint2/compiler/coretest/run + COMMAND $ + ) +set_tests_properties( + libint2/compiler/coretest/run + PROPERTIES + FIXTURES_REQUIRED LIBINT2_COMPILER_CORETEST_EXEC + ) diff --git a/src/bin/test_eri/CMakeLists.txt b/src/bin/test_eri/CMakeLists.txt new file mode 100644 index 000000000..1f057f317 --- /dev/null +++ b/src/bin/test_eri/CMakeLists.txt @@ -0,0 +1,16 @@ +add_executable( + libint-compiler-eri-test-generate + EXCLUDE_FROM_ALL + generate_eri_code.cc + ) +target_link_libraries(libint-compiler-eri-test-generate libint-libcompiler) +target_include_directories( + libint-compiler-eri-test-generate + PRIVATE + ${PROJECT_SOURCE_DIR}/src/bin/ + ) +set_target_properties( + libint-compiler-eri-test-generate + PROPERTIES + INSTALL_RPATH_USE_LINK_PATH TRUE + ) diff --git a/src/lib/libint/CMakeLists.txt b/src/lib/libint/CMakeLists.txt index fe5696e45..ada10dbf9 100644 --- a/src/lib/libint/CMakeLists.txt +++ b/src/lib/libint/CMakeLists.txt @@ -2,7 +2,19 @@ list(APPEND CMAKE_MODULE_PATH ${PROJECT_BINARY_DIR}/cmake/modules) include(int_computed) # for macros.tex and features -add_custom_target(libint-library-generate DEPENDS "CMakeLists.txt.export") # TODO "${EXPORT_STAGE_DIR}/src/libint2_params.h") +# <<< Generate Library Source >>> + +file(MAKE_DIRECTORY "${EXPORT_STAGE_DIR}/src") +add_custom_command( + OUTPUT + "${EXPORT_STAGE_DIR}/src/libint2_params.h" + COMMAND build_libint + WORKING_DIRECTORY "${EXPORT_STAGE_DIR}/src" + DEPENDS + build_libint + COMMENT "Generating Libint2 library source" + ) +add_custom_target(libint-library-generate DEPENDS "${EXPORT_STAGE_DIR}/src/libint2_params.h") # <<< Add Metadata To The Library Source >>>