From 27e386eca1ccd232be3c3e7d5953f72600bc7cf1 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Wed, 13 Dec 2023 03:41:30 -0500 Subject: [PATCH 01/17] git and ref in configuration.cc --- CMakeLists.txt | 60 +++++ cmake/modules/.git_archival.txt | 4 + cmake/modules/DynamicVersion.cmake | 375 +++++++++++++++++++++++++++ cmake/modules/int_versions.cmake | 66 +++++ include/libint2/util/configuration.h | 76 +++++- src/lib/libint/configuration.cc | 43 ++- 6 files changed, 619 insertions(+), 5 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 cmake/modules/.git_archival.txt create mode 100644 cmake/modules/DynamicVersion.cmake create mode 100644 cmake/modules/int_versions.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..b5620d7ef --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,60 @@ +cmake_minimum_required(VERSION 3.19) # string(json +cmake_policy(SET CMP0074 NEW) +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() + +############################# Version and Metadata ############################# + +# can't use PROJECT_SOURCE_DIR etc. before project() call +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) +include(DynamicVersion) +dynamic_version( + PROJECT_PREFIX Libint2Compiler_ + GIT_ARCHIVAL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/.git_archival.txt + OUTPUT_COMMIT LibintRepository_COMMIT + OUTPUT_VERSION LibintRepository_VERSION + OUTPUT_DESCRIBE LibintRepository_DESCRIBE + OUTPUT_DISTANCE LibintRepository_DISTANCE + ) + +project( + Libint2Compiler + VERSION ${LibintRepository_VERSION} + DESCRIPTION + "Libint: A library for the evaluation of molecular integrals of many-body operators over Gaussian functions" + HOMEPAGE_URL "http://libint.valeyev.net" + LANGUAGES CXX + ) + # * http://libint.valeyev.net/ redirects to https://github.com/evaleev/libint + +set(${PROJECT_NAME}_AUTHORS "Edward F. Valeev") +set(${PROJECT_NAME}_LICENSE "GPL-3.0 for generator; LGPL-3.0 for generated") + +# along with project(... VERSION) above scanned by dynamic_version() from `git +# describe`, these are the authoritative version source (formerly in configure.ac) +set(LIBINT_BUILDID "post999") +set(LIBINT_SOVERSION "2:3:0") + +include(int_versions) + +set(L2 Libint2) # Namespace +set(pnv libint2) # projectnameversion + +################################### Overview ################################### + +# CMake build overview: +# +# >>> ls +# cmake/ COPYING src/ tests/ ... +# >>> cmake -S. -Bbuild -GNinja -DCMAKE_INSTALL_PREFIX=/path/to/install-libint ... +# ... +# -- Generating done +# -- Build files have been written to: /current/dir/build +# >>> cmake --build build --target install + +################################## Main Project ################################# + +# STRICTLY TEMPORARY FOR DEMONSTRATION PURPOSES +configure_file(src/lib/libint/configuration.cc configuration.cc @ONLY) diff --git a/cmake/modules/.git_archival.txt b/cmake/modules/.git_archival.txt new file mode 100644 index 000000000..9d376cd1d --- /dev/null +++ b/cmake/modules/.git_archival.txt @@ -0,0 +1,4 @@ +node: $Format:%H$ +node-date: $Format:%cI$ +describe-name: $Format:%(describe:tags=true,match=?[0-9.]*)$ +ref-names: $Format:%D$ diff --git a/cmake/modules/DynamicVersion.cmake b/cmake/modules/DynamicVersion.cmake new file mode 100644 index 000000000..bd4e684ad --- /dev/null +++ b/cmake/modules/DynamicVersion.cmake @@ -0,0 +1,375 @@ +# from https://github.com/LecrisUT/CMakeExtraUtils/commits/main on 11 Dec 2023 at 26450da +# * 12 Dec 2023 added distance variable and field + +## Helper to get dynamic version +# Format is made compatible with python's setuptools_scm (https://github.com/pypa/setuptools_scm#git-archives) + +function(dynamic_version) + # Configure project to use dynamic versioning + # + # Named arguments:: + # PROJECT_PREFIX (string): Prefix to be used for namespacing targets, typically ${PROJECT_NAME} + # OUTPUT_VERSION (string) [PROJECT_VERSION]: Variable where to save the calculated version + # OUTPUT_DESCRIBE (string) [GIT_DESCRIBE]: Variable where to save the pure git_describe + # OUTPUT_COMMIT (string) [GIT_COMMIT]: Variable where to save the git commit + # OUTPUT_DISTANCE (string) [GIT_DISTANCE]: Variable where to save the distance from git tag + # PROJECT_SOURCE (path) [${CMAKE_CURRENT_SOURCE_DIR}]: Location of the project source. + # (either extracted git archive or git clone) + # GIT_ARCHIVAL_FILE (path) [${PROJECT_SOURCE}/.git_archival.txt]: Location of .git_archival.txt + # FALLBACK_VERSION (string): Fallback version + # FALLBACK_HASH (string): Fallback git hash. If not defined target GitHash will not be created if project is not a + # git repo + # TMP_FOLDER (path) [${CMAKE_CURRENT_BINARY_DIR}/tmp]: Temporary path to store temporary files + # OUTPUT_FOLDER (path) [${CMAKE_CURRENT_BINARY_DIR}]: Path where to store generated files + # + # Options:: + # ALLOW_FAILS: Do not return with FATAL_ERROR. Developer is responsible for setting appropriate version if fails + # + # Targets:: + # ${PROJECT_PREFIX}Version: Target that recalculates the dynamic version each time + # ${PROJECT_PREFIX}GitHash: + # + # Generated files:: + # (Note: files are regenerated only when they change) + # ${OUTPUT_FOLDER}/.DynamicVersion.json: All computed data of DynamicVersion + # ${OUTPUT_FOLDER}/.version: Extracted version + # ${OUTPUT_FOLDER}/.git_describe: Computed git describe + # ${OUTPUT_FOLDER}/.git_commit: Current commit + + set(ARGS_Options "") + set(ARGS_OneValue "") + set(ARGS_MultiValue "") + list(APPEND ARGS_Options + ALLOW_FAILS + ) + list(APPEND ARGS_OneValue + PROJECT_PREFIX + OUTPUT_VERSION + OUTPUT_DESCRIBE + OUTPUT_COMMIT + OUTPUT_DISTANCE + PROJECT_SOURCE + GIT_ARCHIVAL_FILE + FALLBACK_VERSION + FALLBACK_HASH + TMP_FOLDER + OUTPUT_FOLDER + ) + + cmake_parse_arguments(ARGS "${ARGS_Options}" "${ARGS_OneValue}" "${ARGS_MultiValue}" ${ARGN}) + + set(DynamicVersion_ARGS "") + + # Set default values + if (NOT DEFINED ARGS_OUTPUT_VERSION) + set(ARGS_OUTPUT_VERSION PROJECT_VERSION) + endif () + if (NOT DEFINED ARGS_OUTPUT_DESCRIBE) + set(ARGS_OUTPUT_DESCRIBE GIT_DESCRIBE) + endif () + if (NOT DEFINED ARGS_OUTPUT_COMMIT) + set(ARGS_OUTPUT_COMMIT GIT_COMMIT) + endif () + if (NOT DEFINED ARGS_OUTPUT_DISTANCE) + set(ARGS_OUTPUT_DISTANCE GIT_DISTANCE) + endif () + if (NOT DEFINED ARGS_PROJECT_SOURCE) + set(ARGS_PROJECT_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}) + endif () + if (NOT DEFINED ARGS_GIT_ARCHIVAL_FILE) + set(ARGS_GIT_ARCHIVAL_FILE ${ARGS_PROJECT_SOURCE}/.git_archival.txt) + endif () + if (DEFINED ARGS_FALLBACK_VERSION OR ARGS_ALLOW_FAILS) + # If we have a fallback version or it is specified it is ok if this fails, don't make messages FATAL_ERROR + set(error_message_type AUTHOR_WARNING) + else () + # Otherwise it should + set(error_message_type FATAL_ERROR) + endif () + if (NOT ARGS_PROJECT_PREFIX) + message(AUTHOR_WARNING + "DynamicVersion: No PROJECT_PREFIX was given. Please provide one to avoid target name clashes") + elseif (NOT ARGS_PROJECT_PREFIX MATCHES ".*_$") + # Append an underscore _ to the prefix if not provided + message(AUTHOR_WARNING + "DynamicVersion: PROJECT_PREFIX did not contain an underscore, please add it for clarity") + set(ARGS_PROJECT_PREFIX ${ARGS_PROJECT_PREFIX}_) + endif () + if (NOT DEFINED ARGS_TMP_FOLDER) + set(ARGS_TMP_FOLDER ${CMAKE_CURRENT_BINARY_DIR}/tmp) + endif () + if (NOT DEFINED ARGS_OUTPUT_FOLDER) + set(ARGS_OUTPUT_FOLDER ${CMAKE_CURRENT_BINARY_DIR}) + endif () + if (ARGS_OUTPUT_FOLDER EQUAL ARGS_TMP_FOLDER) + message(FATAL_ERROR + "DynamicVersion misconfigured: Cannot have both OUTPUT_FOLDER and TMP_FOLDER point to the same path") + endif () + + list(APPEND DynamicVersion_ARGS + PROJECT_SOURCE ${ARGS_PROJECT_SOURCE} + GIT_ARCHIVAL_FILE ${ARGS_GIT_ARCHIVAL_FILE} + TMP_FOLDER ${ARGS_TMP_FOLDER} + ) + if (DEFINED ARGS_FALLBACK_VERSION) + list(APPEND DynamicVersion_ARGS + FALLBACK_VERSION ${ARGS_FALLBACK_VERSION}) + endif () + if (DEFINED ARGS_FALLBACK_HASH) + list(APPEND DynamicVersion_ARGS + FALLBACK_HASH ${ARGS_FALLBACK_HASH}) + endif () + if (ARGS_ALLOW_FAILS) + list(APPEND DynamicVersion_ARGS ALLOW_FAILS) + endif () + # Normalize DynamicVersion_ARGS to be passed as string + list(JOIN DynamicVersion_ARGS "\\;" DynamicVersion_ARGS) + + # Execute get_dynamic_version once to know the current configuration + execute_process(COMMAND ${CMAKE_COMMAND} + -DDynamicVersion_RUN:BOOL=True + # Note: DynamicVersion_ARGS cannot be escaped with "" + -DDynamicVersion_ARGS:STRING=${DynamicVersion_ARGS} + -P ${CMAKE_CURRENT_FUNCTION_LIST_FILE} + COMMAND_ERROR_IS_FATAL ANY) + + # Copy all configured files + foreach (file IN ITEMS .DynamicVersion.json .version .git_describe .git_commit) + if (EXISTS ${file}) + file(COPY_FILE ${ARGS_TMP_FOLDER}/${file} ${ARGS_OUTPUT_FOLDER}/${file}) + endif () + endforeach () + + # Check configuration state + file(READ ${ARGS_TMP_FOLDER}/.DynamicVersion.json data) + 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_DISTANCE} ERROR_VARIABLE _ GET ${data} distance) + + # Configure targets + if (failed) + # If configuration failed, create dummy targets + add_custom_target(${ARGS_PROJECT_PREFIX}Version + COMMAND ${CMAKE_COMMAND} -E true) + add_custom_target(${ARGS_PROJECT_PREFIX}GitHash + COMMAND ${CMAKE_COMMAND} -E true) + else () + # Otherwise create the targets outputting to the appropriate files + add_custom_target(${ARGS_PROJECT_PREFIX}DynamicVersion ALL + BYPRODUCTS ${ARGS_TMP_FOLDER}/.DynamicVersion.json ${ARGS_TMP_FOLDER}/.git_describe ${ARGS_TMP_FOLDER}/.version + COMMAND ${CMAKE_COMMAND} + -DDynamicVersion_RUN:BOOL=True + # Note: For some reason DynamicVersion_ARGS needs "" here, but it doesn't in execute_process + -DDynamicVersion_ARGS:STRING="${DynamicVersion_ARGS}" + -P ${CMAKE_CURRENT_FUNCTION_LIST_FILE} + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ARGS_TMP_FOLDER}/.DynamicVersion.json ${ARGS_OUTPUT_FOLDER}/.DynamicVersion.json + ) + 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 + ) + 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 () + + # This ensures that the project is reconfigured (at least at second run) whenever the version changes + set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} APPEND + PROPERTY CMAKE_CONFIGURE_DEPENDS ${ARGS_OUTPUT_FOLDER}/.version) + + message(VERBOSE + "DynamicVersion: Calculated version = ${${ARGS_OUTPUT_VERSION}}") + + if (CMAKE_VERSION VERSION_LESS 3.25) + # 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_COMMIT} ${${ARGS_OUTPUT_COMMIT}} PARENT_SCOPE) + set(${ARGS_OUTPUT_DISTANCE} ${${ARGS_OUTPUT_DISTANCE}} PARENT_SCOPE) + endif () + return(PROPAGATE + ${ARGS_OUTPUT_DESCRIBE} + ${ARGS_OUTPUT_VERSION} + ${ARGS_OUTPUT_COMMIT} + ${ARGS_OUTPUT_DISTANCE} + ) +endfunction() + +function(get_dynamic_version) + # Compute the dynamic version + # + # Named arguments:: + # PROJECT_SOURCE (path): Location of the project source. + # (either extracted git archive or git clone) + # GIT_ARCHIVAL_FILE (path): Location of .git_archival.txt + # FALLBACK_VERSION (string): Fallback version + # FALLBACK_HASH (string): Fallback git hash. If not defined target GitHash will not be created if project is not a + # git repo + # TMP_FOLDER (path): Temporary path to store temporary files + + set(ARGS_Options "") + set(ARGS_OneValue "") + set(ARGS_MultiValue "") + list(APPEND ARGS_OneValue + PROJECT_SOURCE + GIT_ARCHIVAL_FILE + FALLBACK_VERSION + FALLBACK_HASH + TMP_FOLDER + ) + list(APPEND ARGS_Options + ALLOW_FAILS + ) + + cmake_parse_arguments(ARGS "${ARGS_Options}" "${ARGS_OneValue}" "${ARGS_MultiValue}" ${ARGN}) + + if (DEFINED ARGS_FALLBACK_VERSION OR ARGS_ALLOW_FAILS) + # If we have a fallback version or it is specified it is ok if this fails, don't make messages FATAL_ERROR + set(error_message_type AUTHOR_WARNING) + else () + # Otherwise it should fail + set(error_message_type FATAL_ERROR) + endif () + + set(data "{}") + # Default set + string(JSON data SET ${data} failed true) + if (ARGS_ALLOW_FAILS) + string(JSON data SET ${data} allow-fails true) + else () + string(JSON data SET ${data} allow-fails false) + endif () + + # 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}) + 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}) + file(WRITE ${ARGS_TMP_FOLDER}/.git_commit ${ARGS_FALLBACK_HASH}) + endif () + + + if (NOT EXISTS ${ARGS_GIT_ARCHIVAL_FILE}) + # If git_archival.txt is missing, project is ill-formed + message(${error_message_type} + "DynamicVersion: Missing file .git_archival.txt\n" + " .git_archival.txt: ${ARGS_GIT_ARCHIVAL_FILE}") + return() + endif () + + # Get version dynamically from git_archival.txt + file(STRINGS ${ARGS_GIT_ARCHIVAL_FILE} describe-name + REGEX "^describe-name:.*") + if (NOT describe-name) + # If git_archival.txt does not contain the field "describe-name:", it is ill-formed + message(${error_message_type} + "DynamicVersion: Missing string \"describe-name\" in .git_archival.txt\n" + " .git_archival.txt: ${ARGS_GIT_ARCHIVAL_FILE}") + 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}) + # 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 "DynamicVersion: Found appropriate tag in .git_archival.txt file") + else () + # If not it has to be computed from the git archive + find_package(Git REQUIRED) + # Test if project is a git repository + execute_process(COMMAND ${GIT_EXECUTABLE} status + WORKING_DIRECTORY ${ARGS_PROJECT_SOURCE} + RESULT_VARIABLE git_status_result + OUTPUT_QUIET) + if (NOT git_status_result EQUAL 0) + message(${error_message_type} + "DynamicVersion: Project source is neither a git repository nor a git archive:\n" + " Source: ${ARGS_PROJECT_SOURCE}") + 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.]* + 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\\.]+).*)") + message(${error_message_type} + "DynamicVersion: 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}) + # Get full describe with distance + execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --long --match=?[0-9.]* + WORKING_DIRECTORY ${ARGS_PROJECT_SOURCE} + OUTPUT_VARIABLE describe-name-long + 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} + "DynamicVersion: Version tag is ill-formatted\n" + " Describe-name-long: ${describe-name-long}") + return() + endif () + string(JSON data SET + ${data} distance \"${CMAKE_MATCH_3}\") + file(WRITE ${ARGS_TMP_FOLDER}/.git_distance ${CMAKE_MATCH_3}) + string(JSON data SET + ${data} commit \"${git-hash}\") + file(WRITE ${ARGS_TMP_FOLDER}/.git_commit ${git-hash}) + message(DEBUG "DynamicVersion: Found appropriate tag from git") + endif () + + # Mark success and output results + string(JSON data SET ${data} failed false) + message(DEBUG + "DynamicVersion: Computed data:\n" + " data = ${data}") + file(WRITE ${ARGS_TMP_FOLDER}/.DynamicVersion.json ${data}) +endfunction() + +# Logic to run get_dynamic_version() by running this script +if (DynamicVersion_RUN) + if (NOT DEFINED DynamicVersion_ARGS) + message(FATAL_ERROR + "DynamicVersion: DynamicVersion_ARGS not defined") + endif () + get_dynamic_version(${DynamicVersion_ARGS}) +endif () + diff --git a/cmake/modules/int_versions.cmake b/cmake/modules/int_versions.cmake new file mode 100644 index 000000000..c2064a800 --- /dev/null +++ b/cmake/modules/int_versions.cmake @@ -0,0 +1,66 @@ +# top-level CMakeLists.txt has defined: +# * PROJECT_VERSION_{MAJOR|MINOR|PATCH} through `project(... VERSION)` +# * LIBINT_BUILDID +# * LIBINT_SOVERSION +# * LibintRepository_{VERSION|DESCRIBE|COMMIT|DISTANCE} through `dynamic_version()` + +# note that 3rd version integer is PATCH in CMake and MICRO in Libint +# see also int_computed.cmake.in for transmitting these values to the library's CMake +# note that with the dynamic/git scheme, it's important for repo to be up-to-date with tags + + +# <<< 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}") + +if (LibintRepository_DISTANCE STREQUAL "0") + set(LIBINT_SORTABLE_VERSION "${LibintRepository_VERSION}") +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}") + +string(TIMESTAMP LIBINT_VERSION_YEAR "%Y") +message(DEBUG "LIBINT_VERSION_YEAR ${LIBINT_VERSION_YEAR}") + + +# <<< Build Version >>> + +set(LIBINT_MAJOR_VERSION ${PROJECT_VERSION_MAJOR}) +set(LIBINT_MINOR_VERSION ${PROJECT_VERSION_MINOR}) +set(LIBINT_MICRO_VERSION ${PROJECT_VERSION_PATCH}) + +set(LIBINT_VERSION ${LIBINT_MAJOR_VERSION}.${LIBINT_MINOR_VERSION}.${LIBINT_MICRO_VERSION}) + + +# <<< Dev Version >>> + +if (LIBINT_BUILDID) + set(LIBINT_EXT_VERSION ${LIBINT_VERSION}-${LIBINT_BUILDID}) +else() + set(LIBINT_EXT_VERSION ${LIBINT_VERSION}) +endif() + +message(STATUS "Version: Full ${LIBINT_EXT_VERSION} Numeric ${LIBINT_VERSION} Sortable ${LIBINT_SORTABLE_VERSION}") + +if (NOT(LibintRepository_VERSION STREQUAL LIBINT_VERSION)) + message(AUTHOR_WARNING + "Version processing has gone wrong: ${LibintRepository_VERSION STREQUAL} != ${LIBINT_VERSION}") +endif() + + +# <<< ABI Version >>> + +string(REPLACE ":" ";" LIBINT_SOVERSION_LIST ${LIBINT_SOVERSION}) + +list(GET LIBINT_SOVERSION_LIST 0 LIBINT_CURRENT_SOVERSION) +list(GET LIBINT_SOVERSION_LIST 1 LIBINT_REVISION_SOVERSION) +list(GET LIBINT_SOVERSION_LIST 2 LIBINT_AGE_SOVERSION) + +math(EXPR LIBINT_MAJOR_SOVERSION "${LIBINT_CURRENT_SOVERSION} - ${LIBINT_AGE_SOVERSION}") +message(STATUS "SO Version: Full ${LIBINT_SOVERSION} Major ${LIBINT_MAJOR_SOVERSION}") diff --git a/include/libint2/util/configuration.h b/include/libint2/util/configuration.h index bcecdb205..1aa7de1df 100644 --- a/include/libint2/util/configuration.h +++ b/include/libint2/util/configuration.h @@ -24,12 +24,38 @@ /* Runtime accessor for the library configuration: integral derivatives, AM, orderings, etc. @return the semicolon-separated strings from CMake components */ -const char* configuration_accessor(); +const char *configuration_accessor(); + +/* Get the major, minor, and micro version of Libint */ +void libint_version(int *, int *, int *); + +/* Get the version of Libint as a string + @return the version string. At release, strictly "M.m.p" (no alpha/rc/etc.). + Beyond release (ext=True), returns "M.m.p.postD" where D is distance from + release. Beyond release (ext=False), returns most recent release, "M.m.p". */ +const char *libint_version_string(bool ext = true); + +/* Get the git commit at which library was generated + @return the commit as a 7-char abbreviated string */ +const char *libint_commit(void); + +/* Literature citation + @return the citation string including description and version */ +const char *libint_reference(void); + +/* Literature citation DOI + @return the string of DOI for latest tag */ +const char *libint_reference_doi(void); + +/* BibTeX for citing Libint + @return the string for literature citation */ +const char *libint_bibtex(void); #ifdef __cplusplus #include #include #include +#include #include namespace libint2 { @@ -57,6 +83,54 @@ inline bool supports(std::string component) { (std::find(seglist.begin(), seglist.end(), component) != seglist.end()); return tf; } + +/// Get the major, minor, and micro version of Libint */ +/// @return the components of the last release +inline std::tuple libint_version() { + int vmajor, vminor, vmicro; + ::libint_version(&vmajor, &vminor, &vmicro); + return std::make_tuple(vmajor, vminor, vmicro); +} + +/// Get the version of Libint as a string +/// @param[in] whether to return the simple-sortable last release or a +/// per-commit version +/// @return the version string. At release, strictly "M.m.p" (no alpha/rc/etc.). +/// Beyond release (ext=True), returns "M.m.p.postD" where D is distance from +/// release. Beyond release (ext=False), returns most recent release, "M.m.p". +inline std::string libint_version_string(bool ext = true) { + std::string version = ::libint_version_string(ext); + return version; +} + +/// Get the git commit at which library was generated +/// @return the commit as a 7-char abbreviated string +inline std::string libint_commit(void) { + std::string commit = ::libint_commit(); + return commit; +} + +/// Literature citation +/// @return the citation string including description and version +inline std::string libint_reference(void) { + std::string ref = ::libint_reference(); + return ref; +} + +/// Literature citation DOI +/// @return the string of DOI for latest tag +inline std::string libint_reference_doi(void) { + std::string ref = ::libint_reference_doi(); + return ref; +} + +/// BibTeX for citing Libint +/// @return the string for literature citation +inline std::string libint_bibtex(void) { + std::string ref = ::libint_bibtex(); + return ref; +} + } // namespace libint2 #endif /* C++ guard */ diff --git a/src/lib/libint/configuration.cc b/src/lib/libint/configuration.cc index 1ce3108e7..7529b0cbc 100644 --- a/src/lib/libint/configuration.cc +++ b/src/lib/libint/configuration.cc @@ -18,10 +18,45 @@ * */ -/* Runtime accessor for the library configuration: - integral derivatives, AM, orderings, etc. - @return the semicolon-separated strings from CMake components */ -const char* configuration_accessor() { +const char *configuration_accessor(void) { // return "@Libint2_CONFIG_COMPONENTS@"; return "(nyi)"; } + +void libint_version(int *major, int *minor, int *micro) { + *major = -1; + *minor = -1; + *micro = -1; + sscanf(libint_version_string(ext = false), "%d.%d.%d", major, minor, micro); +} + +const char *libint_version_string(bool ext) { + if (ext) + return "@LIBINT_SORTABLE_VERSION@"; + else + return "@LIBINT_VERSION@"; +} + +const char *libint_commit(void) { return "@LIBINT_GIT_COMMIT@"; } + +const char *libint_reference(void) { + std::string ref; + ref = + "Libint: A library for the evaluation of molecular integrals of " + "many-body operators over Gaussian functions, Version " + + std::string(libint_version_string()) + + " Edward F. Valeev, http://libint.valeyev.net/"; + return ref.c_str(); +} + +const char *libint_reference_doi(void) { + return "10.5281/zenodo.10369117"; // 2.8.0 +} + +const char *libint_bibtex(void) { + return "@Misc{Libint2,\n author = {E.~F.~Valeev},\n title = " + "{\\textsc{Libint}: A library for the evaluation of molecular " + "integrals of many-body operators over Gaussian functions},\n " + "howpublished = {http://libint.valeyev.net/},\n note = {version " + "@Libint2_VERSION@},\n year = {@LIBINT_VERSION_YEAR@}\n}\n"; +} From 8edc1e721f80f37459ce2c2343a585bfa11ac6ac Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Wed, 13 Dec 2023 23:02:22 -0500 Subject: [PATCH 02/17] fns compile --- CMakeLists.txt | 3 ++- INSTALL.md | 24 ++++++++++++++++++++++ cmake/modules/int_versions.cmake | 6 ++++++ include/libint2/util/configuration.h | 12 ++++++----- src/lib/libint/configuration.cc | 30 ++++++++++++++++------------ tests/unit/test.cc | 5 +++++ 6 files changed, 61 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b5620d7ef..cffb5362b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ project( Libint2Compiler VERSION ${LibintRepository_VERSION} DESCRIPTION - "Libint: A library for the evaluation of molecular integrals of many-body operators over Gaussian functions" + "A library for the evaluation of molecular integrals of many-body operators over Gaussian functions" HOMEPAGE_URL "http://libint.valeyev.net" LANGUAGES CXX ) @@ -36,6 +36,7 @@ set(${PROJECT_NAME}_LICENSE "GPL-3.0 for generator; LGPL-3.0 for generated") # describe`, these are the authoritative version source (formerly in configure.ac) set(LIBINT_BUILDID "post999") set(LIBINT_SOVERSION "2:3:0") +set(LIBINT_DOI "10.5281/zenodo.10369117") # 2.8.0 include(int_versions) diff --git a/INSTALL.md b/INSTALL.md index 33c868df6..b6acf48a7 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -130,3 +130,27 @@ Eventually, these will be CMake Components, too. bs - library integrals use ordering bagel + standard = bagel bo - library integrals use ordering + orca ``` + +### Interfacing + +Eventually (approximately 2.9.0 CMake-based), additional functions will be available to retrive Libint version, commit, and literature citation. Below are outputs at the libtool stage. + +``` +auto Mmp = libint2::libint_version(); +printf("Version: Numeric=%s Sortable=%s Commit=%s\n", libint2::libint_version_string(false).c_str(), libint2::libint_version_string(true).c_str(), libint2::libint_commit().c_str()); +printf("Version: Major=%d minor=%d patch=%d\n", std::get<0>(Mmp), std::get<1>(Mmp), std::get<2>(Mmp)); +printf("Citation: DOI=%s Ref=%s\n", libint2::libint_reference_doi().c_str(), libint2::libint_reference().c_str()); +printf("Citation: BibTex=%s\n", libint2::libint_bibtex().c_str()); +``` +``` +Version: Numeric=2.8.0 Sortable= Commit= +Version: Major=2 minor=8 patch=0 +Citation: DOI= Ref=Libint: , Version Edward F. Valeev, http://libint.valeyev.net/ +Citation: BibTex=@Misc{Libint2, + author = {E.~F.~Valeev}, + title = {\textsc{Libint}: }, + howpublished = {http://libint.valeyev.net/}, + note = {version }, + year = {} +} +``` diff --git a/cmake/modules/int_versions.cmake b/cmake/modules/int_versions.cmake index c2064a800..973e51b46 100644 --- a/cmake/modules/int_versions.cmake +++ b/cmake/modules/int_versions.cmake @@ -1,7 +1,9 @@ # top-level CMakeLists.txt has defined: # * PROJECT_VERSION_{MAJOR|MINOR|PATCH} through `project(... VERSION)` +# * Libint2Compiler_DESCRIPTION through `project(... DESCRIPTION)` # * LIBINT_BUILDID # * LIBINT_SOVERSION +# * LIBINT_DOI # * LibintRepository_{VERSION|DESCRIBE|COMMIT|DISTANCE} through `dynamic_version()` # note that 3rd version integer is PATCH in CMake and MICRO in Libint @@ -25,9 +27,13 @@ endif() string(SUBSTRING ${LibintRepository_COMMIT} 0 7 LIBINT_GIT_COMMIT) message(DEBUG "LIBINT_GIT_COMMIT ${LIBINT_GIT_COMMIT}") +# 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 string(TIMESTAMP LIBINT_VERSION_YEAR "%Y") message(DEBUG "LIBINT_VERSION_YEAR ${LIBINT_VERSION_YEAR}") +set(LIBINT_DESCRIPTION "${Libint2Compiler_DESCRIPTION}") +message(DEBUG "LIBINT_DESCRIPTION ${LIBINT_DESCRIPTION}") # <<< Build Version >>> diff --git a/include/libint2/util/configuration.h b/include/libint2/util/configuration.h index 1aa7de1df..63fbb3c3a 100644 --- a/include/libint2/util/configuration.h +++ b/include/libint2/util/configuration.h @@ -21,6 +21,8 @@ #ifndef _libint2_include_libint2_util_configuration_h_ #define _libint2_include_libint2_util_configuration_h_ +#include + /* Runtime accessor for the library configuration: integral derivatives, AM, orderings, etc. @return the semicolon-separated strings from CMake components */ @@ -31,9 +33,9 @@ void libint_version(int *, int *, int *); /* Get the version of Libint as a string @return the version string. At release, strictly "M.m.p" (no alpha/rc/etc.). - Beyond release (ext=True), returns "M.m.p.postD" where D is distance from - release. Beyond release (ext=False), returns most recent release, "M.m.p". */ -const char *libint_version_string(bool ext = true); + Beyond release (arg=true), returns "M.m.p.postD" where D is distance from + release. Beyond release (arg=false), returns most recent release, "M.m.p". */ +const char *libint_version_string(bool); /* Get the git commit at which library was generated @return the commit as a 7-char abbreviated string */ @@ -96,8 +98,8 @@ inline std::tuple libint_version() { /// @param[in] whether to return the simple-sortable last release or a /// per-commit version /// @return the version string. At release, strictly "M.m.p" (no alpha/rc/etc.). -/// Beyond release (ext=True), returns "M.m.p.postD" where D is distance from -/// release. Beyond release (ext=False), returns most recent release, "M.m.p". +/// Beyond release (ext=true), returns "M.m.p.postD" where D is distance from +/// release. Beyond release (ext=false), returns most recent release, "M.m.p". inline std::string libint_version_string(bool ext = true) { std::string version = ::libint_version_string(ext); return version; diff --git a/src/lib/libint/configuration.cc b/src/lib/libint/configuration.cc index 7529b0cbc..aa4edc5e6 100644 --- a/src/lib/libint/configuration.cc +++ b/src/lib/libint/configuration.cc @@ -18,6 +18,11 @@ * */ +#include + +#include +#include + const char *configuration_accessor(void) { // return "@Libint2_CONFIG_COMPONENTS@"; return "(nyi)"; @@ -27,7 +32,7 @@ void libint_version(int *major, int *minor, int *micro) { *major = -1; *minor = -1; *micro = -1; - sscanf(libint_version_string(ext = false), "%d.%d.%d", major, minor, micro); + std::sscanf(libint_version_string(false), "%d.%d.%d", major, minor, micro); } const char *libint_version_string(bool ext) { @@ -40,23 +45,22 @@ const char *libint_version_string(bool ext) { const char *libint_commit(void) { return "@LIBINT_GIT_COMMIT@"; } const char *libint_reference(void) { - std::string ref; - ref = - "Libint: A library for the evaluation of molecular integrals of " - "many-body operators over Gaussian functions, Version " + - std::string(libint_version_string()) + - " Edward F. Valeev, http://libint.valeyev.net/"; - return ref.c_str(); -} + std::string ref = "Libint: @LIBINT_DESCRIPTION@, Version " + + std::string(libint_version_string(true)) + + " Edward F. Valeev, http://libint.valeyev.net/"; -const char *libint_reference_doi(void) { - return "10.5281/zenodo.10369117"; // 2.8.0 + auto slen = ref.length(); + char *cref = new char[slen + 1]; + std::memcpy(cref, ref.c_str(), slen); + cref[slen] = '\0'; + return cref; } +const char *libint_reference_doi(void) { return "@LIBINT_DOI@"; } + const char *libint_bibtex(void) { return "@Misc{Libint2,\n author = {E.~F.~Valeev},\n title = " - "{\\textsc{Libint}: A library for the evaluation of molecular " - "integrals of many-body operators over Gaussian functions},\n " + "{\\textsc{Libint}: @LIBINT_DESCRIPTION@},\n " "howpublished = {http://libint.valeyev.net/},\n note = {version " "@Libint2_VERSION@},\n year = {@LIBINT_VERSION_YEAR@}\n}\n"; } diff --git a/tests/unit/test.cc b/tests/unit/test.cc index cf8a09aa3..98beb47b4 100644 --- a/tests/unit/test.cc +++ b/tests/unit/test.cc @@ -66,6 +66,11 @@ int main(int argc, char* argv[]) { libint2::configuration_accessor().c_str()); printf("Supports: dddd=%d mmmm=%d FF=%d\n", libint2::supports("eri_dddd_d0"), libint2::supports("eri_mmmm_d0"), libint2::supports("eri_FF_d0")); + auto Mmp = libint2::libint_version(); + printf("Version: Numeric=%s Sortable=%s Commit=%s\n", libint2::libint_version_string(false).c_str(), libint2::libint_version_string(true).c_str(), libint2::libint_commit().c_str()); + printf("Version: Major=%d minor=%d patch=%d\n", std::get<0>(Mmp), std::get<1>(Mmp), std::get<2>(Mmp)); + printf("Citation: DOI=%s Ref=%s\n", libint2::libint_reference_doi().c_str(), libint2::libint_reference().c_str()); + printf("Citation: BibTex=%s\n", libint2::libint_bibtex().c_str()); #ifdef LIBINT_HAS_MPFR // default to 256 bits of precision for mpf_class From 1d6e952a198efc5d6e5b1976eace88d4b62240ae Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Sun, 17 Dec 2023 21:29:39 -0500 Subject: [PATCH 03/17] prelim --- CMakeLists.txt | 136 ++++++++++++++++++++++ INSTALL.md | 131 +++++++++++++++++++++ cmake/modules/int_am.cmake | 4 + cmake/modules/options.cmake | 187 ++++++++++++++++++++++++++++++ include/libint2/config.h.cmake.in | 185 +++++++++++++++++++++++++++++ 5 files changed, 643 insertions(+) create mode 100644 cmake/modules/int_am.cmake create mode 100644 cmake/modules/options.cmake create mode 100644 include/libint2/config.h.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index cffb5362b..1b100b1d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,7 +55,143 @@ set(pnv libint2) # projectnameversion # -- Build files have been written to: /current/dir/build # >>> cmake --build build --target install +# The Libint build is structured into three parts: +# +# * generator/compiler +# - (1) build src/bin/libint/ into compiler executable `build_libint` +# - pretty quick, runs in parallel +# - consumes all the enable/max/opt/orderings integral options +# - (2) optionally testable +# * export +# - (3) run `build_libint` to generate library source (C++) files (that upon +# compilation can become a Libint2 library) and combine them with other +# static source files in src/lib/libint/ and general static files (e.g., +# include/ and docs/) into an independent tarball ready for distribution +# (with its own CMake configuration, tests, etc.). +# - really slow for non-trivial angular momenta; runs in serial +# - consumes no options +# - build target `export` to stop after this step and collect source tarball +# * library +# - can be built as a subproject (FetchContent) or completely insulated (bare +# ExternalProject; default; -or- a tarball start). For FetchContent, must +# build libint-library-export target before library build targets appear +# - (4) unpack the export tarball and build the library and install into \/library-install-stage/ +# - duration depends on number of integrals requested; runs in parallel +# - consumes language-interface and the CMAKE_INSTALL_[DATA|INCLUDE|LIB]DIR paths options +# - the default build target includes this final library build +# - (5) optionally testable +# - (6) install into CMAKE_INSTALL_PREFIX +# - (7) optional Python build alongside library or afterwards. Optional testing requires library install + +#################################### Guide ##################################### + +# See INSTALL.md for elaboration of steps above, options below, & translations from libtool. + +################################### Options #################################### +include(options) +include(GNUInstallDirs) +include(CTest) +message(STATUS "Building using CMake ${CMAKE_VERSION} Generator ${CMAKE_GENERATOR}") + + +# <<< Which Integrals Classes, Which Derivative Levels >>> + +option_with_default(ENABLE_ONEBODY + "Compile with support for up to N-th derivatives of 1-body integrals (-1 for OFF)" 0) +option_with_default(ENABLE_ERI + "Compile with support for up to N-th derivatives of 4-center electron repulsion integrals (-1 for OFF)" 0) +option_with_default(ENABLE_ERI3 + "Compile with support for up to N-th derivatives of 3-center electron repulsion integrals (-1 for OFF)" -1) +option_with_default(ENABLE_ERI2 + "Compile with support for up to N-th derivatives of 2-center electron repulsion integrals (-1 for OFF)" -1) +option_with_default(ENABLE_G12 + "Compile with support for N-th derivatives of MP2-F12 energies with Gaussian factors (-1 for OFF)" -1) +option_with_default(ENABLE_G12DKH + "Compile with support for N-th derivatives of DKH-MP2-F12 energies with Gaussian factors (-1 for OFF)" -1) + +option_with_print(DISABLE_ONEBODY_PROPERTY_DERIVS + "Disable geometric derivatives of 1-body property integrals (all but overlap, kinetic, elecpot). + These derivatives are disabled by default to save compile time. (enable with OFF) + Note that the libtool build won't enable this- if forcibly enabled, build_libint balks." ON) +option_with_print(ENABLE_T1G12_SUPPORT + "Enable Ti,G12 integrals when G12 integrals are enabled. Irrelevant when `ENABLE_G12=OFF`. (disable with OFF)" ON) + +# <<< Ordering Conventions >>> + +option_with_print(ERI3_PURE_SH + "Assume the 'unpaired' center of 3-center ERIs will be transformed to pure solid harmonics" OFF) +option_with_print(ERI2_PURE_SH + "Assume the 2-center ERIs will be transformed to pure solid harmonics" OFF) + +# <<< How High Angular Momentum >>> + +# example for "semicolon-separated string": `-DENABLE_ERI3=2 -DWITH_ERI3_MAX_AM="5;4;3"` + +# special considerations for high-AM library builds: +# * high MAX_AM generates a large number of source files. If unity builds are disabled, more than +# ~20k files may require `ulimit -s 65535` for linking the library target on Linux to avert +# "ld: Argument list too long". +# * Ninja builds use beyond max threads and can run out of memory, resulting in errorless stops or +# "CMake Error: Generator: execution of make failed". Throttle it to physical threads with +# `export CMAKE_BUILD_PARALLEL_LEVEL=N`. + +option_with_default(WITH_MAX_AM + "Support Gaussians of angular momentum up to N. + Can specify values for each derivative level as a semicolon-separated string. + If ERI3 ints are enabled, this option also controls the AM of the paired centers." 4) +option_with_default(WITH_OPT_AM + "Optimize maximally for up to angular momentum N (N <= max-am). + Can specify values for each derivative level as a semicolon-separated string. (default: (libint_max_am/2)+1)" -1) + +option_with_default(MULTIPOLE_MAX_ORDER + "Maximum order of spherical multipole integrals. There is no maximum" 4) +option_with_default(WITH_ONEBODY_MAX_AM + "Support 1-body ints for Gaussians of angular momentum up to N. + Can specify values for each derivative level as a semicolon-separated string. (default: max_am)" -1) +option_with_default(WITH_ONEBODY_OPT_AM + "Optimize 1-body ints maximally for up to angular momentum N (N <= max-am). + Can specify values for each derivative level as a semicolon-separated string (default: (max_am/2)+1)" -1) + +option_with_default(WITH_ERI_MAX_AM + "Support 4-center ERIs for Gaussians of angular momentum up to N. + Can specify values for each derivative level as a semicolon-separated string. (default: max_am)" -1) +option_with_default(WITH_ERI_OPT_AM + "Optimize 4-center ERIs maximally for up to angular momentum N (N <= max-am). + Can specify values for each derivative level as a semicolon-separated string (default: (max_am/2)+1)" -1) + +option_with_default(WITH_ERI3_MAX_AM + "Support 3-center ERIs for Gaussians of angular momentum up to N. + Can specify values for each derivative level as a semicolon-separated string. (default: max_am) + This option controls only the single fitting center; the paired centers use WITH_MAX_AM." -1) +option_with_default(WITH_ERI3_OPT_AM + "Optimize 3-center ERIs maximally for up to angular momentum N (N <= max-am). + Can specify values for each derivative level as a semicolon-separated string. (default: (max_am/2)+1)" -1) + +option_with_default(WITH_ERI2_MAX_AM + "Support 2-center ERIs for Gaussians of angular momentum up to N. + Can specify values for each derivative level as a semicolon-separated string. (default: max_am)" -1) +option_with_default(WITH_ERI2_OPT_AM + "Optimize 2-center ERIs maximally for up to angular momentum N (N <= max-am). + Can specify values for each derivative level as a semicolon-separated string. (default: (max_am/2)+1)" -1) + +option_with_default(WITH_G12_MAX_AM + "Support integrals for G12 methods of angular momentum up to N. (default: max_am)" -1) +option_with_default(WITH_G12_OPT_AM + "Optimize G12 integrals for up to angular momentum N (N <= max-am). (default: (max_am/2)+1)" -1) + +option_with_default(WITH_G12DKH_MAX_AM + "Support integrals for relativistic G12 methods of angular momentum up to N. (default: max_am)" -1) +option_with_default(WITH_G12DKH_OPT_AM + "Optimize G12DKH integrals for up to angular momentum N (N <= max-am). (default: (max_am/2)+1)" -1) + +booleanize01(ERI3_PURE_SH) +booleanize01(ERI2_PURE_SH) +booleanize01(DISABLE_ONEBODY_PROPERTY_DERIVS) +booleanize01(SUPPORT_T1G12) + ################################## Main Project ################################# +configure_file(include/libint2/config.h.cmake.in include/libint2/config.h @ONLY) + # STRICTLY TEMPORARY FOR DEMONSTRATION PURPOSES configure_file(src/lib/libint/configuration.cc configuration.cc @ONLY) diff --git a/INSTALL.md b/INSTALL.md index b6acf48a7..7de1720d4 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,3 +1,134 @@ +# Configuring Libint + +* Notes + * Codes "G", "L", or "C" for each option indicate whether it is consumed by the _g_enerator, the _l_ibrary, the library _c_onsumer, or a combination. + * If your final target is the export tarball, use options that include the letter "G". + * If you're building a library from an export TARBALL, use options that include the letter "L". + * For a continuous generator->export->library build, options supplied at the top level will be properly handed off to generator and library build. + * See [Update Guide](gnu-autotools-update-guide) for new names for old options. + + +### Which Integrals Classes, Which Derivative Levels (G) + +* `ENABLE_ONEBODY` — G — Compile with support for up to N-th derivatives of 1-body integrals. Use -1 for OFF. [Default=0] +* `ENABLE_ERI` — G — Compile with support for up to N-th derivatives of 4-center electron repulsion integrals. Use -1 for OFF. [Default=0] +* `ENABLE_ERI3` — G — Compile with support for up to N-th derivatives of 3-center electron repulsion integrals. Use -1 for OFF. [Default=-1] +* `ENABLE_ERI2` — G — Compile with support for up to N-th derivatives of 2-center electron repulsion integrals. Use -1 for OFF. [Default=-1] +* `ENABLE_G12` — G — Compile with support for N-th derivatives of MP2-F12 energies with Gaussian factors. Use -1 for OFF. [Default=-1] +* `ENABLE_G12DKH` — G — Compile with support for N-th derivatives of DKH-MP2-F12 energies with Gaussian factors. Use -1 for OFF. [Default=-1] + +* `DISABLE_ONEBODY_PROPERTY_DERIVS` — G — Disable geometric derivatives of 1-body property integrals (all but overlap, kinetic, elecpot). + These derivatives are disabled by default to save compile time. Use OFF to enable. + Note that the libtool build won't enable this- if forcibly enabled, build_libint balks. [Default=ON] + +* `ENABLE_T1G12_SUPPORT` — G — Enable [Ti,G12] integrals when G12 integrals are enabled. Irrelevant when `ENABLE_G12=OFF`. Use OFF to disable. [Default=ON] + + +### Which Ordering Conventions (G) + +* `ERI3_PURE_SH` — G — Assume the 'unpaired' center of 3-center ERIs will be transformed to pure solid harmonics. [Default=OFF] +* `ERI2_PURE_SH` — G — Assume the 2-center ERIs will be transformed to pure solid harmonics. [Default=OFF] + + +### How High Angular Momentum (G) + +* Notes + * example for "semicolon-separated string": `-DENABLE_ERI3=2 -DWITH_ERI3_MAX_AM="5;4;3"`. cmake configuration prints: + + ``` + -- Setting option ENABLE_ERI3: 2 + -- Setting option WITH_ERI3_MAX_AM: 5;4;3 + ``` + + * special considerations for high-AM library (L) builds: + * high MAX_AM generates a large number of source files. If unity builds are disabled, more than + ~20k files may require `ulimit -s 65535` for linking the library target on Linux to avert + "ld: Argument list too long". + * Ninja builds use beyond max threads and can run out of memory, resulting in errorless stops or + "CMake Error: Generator: execution of make failed". Throttle it to physical threads with + `export CMAKE_BUILD_PARALLEL_LEVEL=N`. + +* `WITH_MAX_AM` — G — Support Gaussians of angular momentum up to N. Can specify values for each derivative level as a semicolon-separated string. Specify values greater or equal to `WITH__MAX_AM`; often mirrors `WITH_ERI3_MAX_AM`. [Default=4] +* `WITH_OPT_AM` — G — Optimize maximally for up to angular momentum N (N <= WITH_MAX_AM). Can specify values for each derivative level as a semicolon-separated string. [Default=-1 -> `(WITH_MAX_AM/2)+1`] + +* `MULTIPOLE_MAX_ORDER` — G — Maximum order of spherical multipole integrals. There is no maximum. [Default=4] + +* `WITH_ONEBODY_MAX_AM` — G — Support 1-body ints for Gaussians of angular momentum up to N. Can specify values for each derivative level as a semicolon-separated string. [Default=-1 -> `WITH_MAX_AM`] +* `WITH_ONEBODY_OPT_AM` — G — Optimize 1-body ints maximally for up to angular momentum N (N <= max-am). Can specify values for each derivative level as a semicolon-separated string. [Default=-1 -> `WITH_OPT_AM`] + +* `WITH_ERI_MAX_AM` — G — Support 4-center ERIs for Gaussians of angular momentum up to N. Can specify values for each derivative level as a semicolon-separated string. [Default=-1 -> `WITH_MAX_AM`] +* `WITH_ERI_OPT_AM` — G — Optimize 4-center ERIs maximally for up to angular momentum N (N <= max-am). Can specify values for each derivative level as a semicolon-separated string. [Default=-1 -> `WITH_OPT_AM`] + +* `WITH_ERI3_MAX_AM` — G — Support 3-center ERIs for Gaussians of angular momentum up to N. Can specify values for each derivative level as a semicolon-separated string. This option controls only the single fitting center; the paired centers use WITH_MAX_AM. [Default=-1 -> `WITH_MAX_AM`] +* `WITH_ERI3_OPT_AM` — G — Optimize 3-center ERIs maximally for up to angular momentum N (N <= max-am). Can specify values for each derivative level as a semicolon-separated string. [Default=-1 -> `WITH_OPT_AM`] + +* `WITH_ERI2_MAX_AM` — G — Support 2-center ERIs for Gaussians of angular momentum up to N. Can specify values for each derivative level as a semicolon-separated string. [Default=-1 -> `WITH_MAX_AM`] +* `WITH_ERI2_OPT_AM` — G — Optimize 2-center ERIs maximally for up to angular momentum N (N <= max-am). Can specify values for each derivative level as a semicolon-separated string. [Default=-1 -> `WITH_OPT_AM`] + +* `WITH_G12_MAX_AM` — G — Support integrals for G12 methods of angular momentum up to N. No specification with per-derivative list. [Default=-1 -> `WITH_MAX_AM`] +* `WITH_G12_OPT_AM` — G — Optimize G12 integrals for up to angular momentum N (N <= max-am). No specification with per-derivative list. [Default=-1 `WITH_OPT_AM`] + +* `WITH_G12DKH_MAX_AM` — G — Support integrals for relativistic G12 methods of angular momentum up to N. No specification with per-derivative list. [Default=-1 -> `WITH_MAX_AM`] +* `WITH_G12DKH_OPT_AM` — G — Optimize G12DKH integrals for up to angular momentum N (N <= max-am). No specification with per-derivative list. [Default=-1 `WITH_OPT_AM`] + + +### Compilers and Flags (G L) (TARBALL) + + +# GNU Autotools Update Guide + +* Notes + * Multiple option names can be from any long-lived branch but usually libtool+cmake --> final cmake+cmake. + +* `--enable-1body=N` --> `-D ENABLE_ONEBODY=N` +* `--enable-eri=N` --> `-D ENABLE_ERI=N` +* `--disable-eri` --> `-D ENABLE_ERI=-1` +* `--enable-eri3=N` --> `-D ENABLE_ERI3=N` +* `--enable-eri2=N` --> `-D ENABLE_ERI2=N` + +* `--enable-eri3-pure-sh` --> `-D ERI3_PURE_SH=ON` +* `--enable-eri2-pure-sh` --> `-D ERI2_PURE_SH=ON` + +* `--with-max-am=N` --> `-D WITH_MAX_AM=N` +* `--with-max-am=N0,N1,N2` --> `-D WITH_MAX_AM="N0;N1;N2"` (notice semicolons and quotes. This is standard CMake list syntax) +* `--with-opt-am=N` --> `-D WITH_OPT_AM=N` +* `--with-opt-am=N0,N1,N2` --> `-D WITH_OPT_AM="N0;N1;N2"` + +* `--with-multipole-max-order=N` --> `-D MULTIPOLE_MAX_ORDER=N` + +* `--with-1body-max-am=N` --> `-D WITH_ONEBODY_MAX_AM=N` +* `--with-1body-max-am=N0,N1,N2` --> `-D WITH_ONEBODY_MAX_AM="N0;N1;N2"` +* `--with-1body-opt-am=N` --> `-D WITH_ONEBODY_OPT_AM=N` +* `--with-1body-opt-am=N0,N1,N2` --> `-D WITH_ONEBODY_OPT_AM="N0;N1;N2"` + +* `--with-eri-max-am=N` --> `-D WITH_ERI_MAX_AM=N` +* `--with-eri-max-am=N0,N1,N2` --> `-D WITH_ERI_MAX_AM="N0;N1;N2"` +* `--with-eri-opt-am=N` --> `-D WITH_ERI_OPT_AM=N` +* `--with-eri-opt-am=N0,N1,N2` --> `-D WITH_ERI_OPT_AM="N0;N1;N2"` + +* `--with-eri3-max-am=N` --> `-D WITH_ERI3_MAX_AM=N` +* `--with-eri3-max-am=N0,N1,N2` --> `-D WITH_ERI3_MAX_AM="N0;N1;N2"` +* `--with-eri3-opt-am=N` --> `-D WITH_ERI3_OPT_AM=N` +* `--with-eri3-opt-am=N0,N1,N2` --> `-D WITH_ERI3_OPT_AM="N0;N1;N2"` + +* `--with-eri2-max-am=N` --> `-D WITH_ERI2_MAX_AM=N` +* `--with-eri2-max-am=N0,N1,N2` --> `-D WITH_ERI2_MAX_AM="N0;N1;N2"` +* `--with-eri2-opt-am=N` --> `-D WITH_ERI2_OPT_AM=N` +* `--with-eri2-opt-am=N0,N1,N2` --> `-D WITH_ERI2_OPT_AM="N0;N1;N2"` + +* `--enable-g12=N` --> `-D ENABLE_G12=N` +* `--enable-g12dkh=N` --> `-D ENABLE_G12DKH` +* `--disable-t1g12-support` --> `-D ENABLE_T1G12_SUPPORT=OFF` +* `--with-g12-max-am=N` --> `-D WITH_G12_MAX_AM=N` +* `--with-g12-opt-am=N` --> `-D WITH_G12_OPT_AM=N` +* `--with-g12dkh-max-am=N` --> `-D WITH_G12DKH_MAX_AM=N` +* `--with-g12dkh-opt-am=N` --> `-D WITH_G12DKH_OPT_AM=N` + +* `--disable-1body-property-derivs` --> `-D DISABLE_ONEBODY_PROPERTY_DERIVS=ON` + + + + ### Run-Time Compatibility Functions are provided to check the library configuration and solid harmonics orderings at runtime: diff --git a/cmake/modules/int_am.cmake b/cmake/modules/int_am.cmake new file mode 100644 index 000000000..8774c900b --- /dev/null +++ b/cmake/modules/int_am.cmake @@ -0,0 +1,4 @@ +# handle the defaulting and setting of the following variables +# * ENABLE_[ONEBODY|ERI2|ERI3|ERI|G12|G12DKH] +# * [LIBINT|ONEBODY|ERI2|ERI3|ERI|G12|G12DKH]_[MAX|OPT]_AM[|_LIST] + diff --git a/cmake/modules/options.cmake b/cmake/modules/options.cmake new file mode 100644 index 000000000..921dc7371 --- /dev/null +++ b/cmake/modules/options.cmake @@ -0,0 +1,187 @@ +### based on https://github.com/psi4/psi4/blob/master/cmake/psi4OptionsTools.cmake + +#Macro for printing an option in a consistent manner +# +#Syntax: print_option(