diff --git a/CMakeLists.txt b/CMakeLists.txt index 0813855f0..0288607d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,8 @@ dynamic_version( OUTPUT_DISTANCE LibintRepository_DISTANCE ) +set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build.") # foil Ninja Debug on Windows + project( Libint2Compiler VERSION ${LibintRepository_VERSION} @@ -99,6 +101,8 @@ message(STATUS "Building using CMake ${CMAKE_VERSION} Generator ${CMAKE_GENERATO # <<< General >>> +option_with_default(CMAKE_BUILD_TYPE "Build type (Release or Debug)" Release) + ### compiler-only ### library-only diff --git a/INSTALL.md b/INSTALL.md index 725a0a6c3..c8ed17886 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -266,6 +266,7 @@ 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] ### Detecting Dependencies (G L C) (TARBALL) diff --git a/cmake/modules/DynamicVersion.cmake b/cmake/modules/DynamicVersion.cmake index bd4e684ad..6c1b88c2a 100644 --- a/cmake/modules/DynamicVersion.cmake +++ b/cmake/modules/DynamicVersion.cmake @@ -1,48 +1,136 @@ -# from https://github.com/LecrisUT/CMakeExtraUtils/commits/main on 11 Dec 2023 at 26450da -# * 12 Dec 2023 added distance variable and field +# copied from https://github.com/LecrisUT/CMakeExtraUtils/blob/main/cmake/DynamicVersion.md ~20 Dec 2023 +# * modified to add distance field and return -## Helper to get dynamic version -# Format is made compatible with python's setuptools_scm (https://github.com/pypa/setuptools_scm#git-archives) +#[===[.md: +# DynamicVersion + +Helper module to get the project's version dynamically. Format is compatible with python's +[`setuptools_scm`](https://github.com/pypa/setuptools_scm#git-archives) + +## Commands + +- {command}`dynamic_version` + +]===] + +include_guard() +list(APPEND CMAKE_MESSAGE_CONTEXT DynamicVersion) + +#[==============================================================================================[ +# Preparations # +]==============================================================================================] + +# No specific preparations + +#[==============================================================================================[ +# Main interface # +]==============================================================================================] 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 + #[===[.md: + # dynamic_version + + Configure project to use dynamic versioning + + ## Synopsis + ```cmake + Main interface + dynamic_version(PROJECT_PREFIX ) + dynamic_version(PROJECT_PREFIX + [OUTPUT_VERSION ] [OUTPUT_DESCRIBE ] [OUTPUT_COMMIT ] + [OUTPUT_DISTANCE ] [PROJECT_SOURCE ] [GIT_ARCHIVAL_FILE ]) + + Fallbacks + dynamic_version(... + [ALLOW_FAILS] [FALLBACK_VERSION ] [FALLBACK_HASH ]) + + Additional configurations + dynamic_version(... + [TMP_FOLDER ] [FALLBACK_VERSION ] [FALLBACK_HASH ]) + ``` + + ## Options + `PROJECT_PREFIX` + Prefix to be used for namespacing targets, typically ${PROJECT_NAME} + + `OUTPUT_VERSION` [Default: PROJECT_VERSION] + Variable where to save the calculated version + + `OUTPUT_DESCRIBE` [Default: GIT_DESCRIBE] + Variable where to save the pure `git describe` output + + `OUTPUT_COMMIT` [Default: GIT_COMMIT] + Variable where to save the current git commit hash + + `OUTPUT_DISTANCE` [Default: GIT_DISTANCE] + Variable where to save the distance from git tag + + `PROJECT_SOURCE` [Default: `${CMAKE_CURRENT_SOURCE_DIR}`] + Location of the project source. Has to be either an extracted git archive or a git clone + + `GIT_ARCHIVAL_FILE` [Default: `${PROJECT_SOURCE}/.git_archival.txt`] + Location of `.git_archival.txt` file. See [pypa/setuptools_scm](https://github.com/pypa/setuptools_scm#git-archives) + for more details + + `FALLBACK_VERSION` + Fallback version to be set if version cannot be dynamically determined. Implies `ALLOW_FAILS` + + `FALLBACK_HASH` + Fallback git hash to be used in `OUTPUT_COMMIT` if commit cannot be determined. + If not defined target GitHash will not be created if project is not a git repo + + `ALLOW_FAILS` + Do not return with `FATAL_ERROR` if version cannot be dynamically determined. CMakeLists author is responsible + for setting appropriate version if fails + + ### Additional configuration options + + `TMP_FOLDER` [Default: `${CMAKE_CURRENT_BINARY_DIR}/tmp`] + Temporary path to store `DynamicVersion`'s temporary files + + `OUTPUT_FOLDER` [Default: `${CMAKE_CURRENT_BINARY_DIR}`] + Path where to store generated files + + ## Targets + `${PROJECT_PREFIX}Version` + Target that recalculates the dynamic version each time. See [](#Output-files) for using dependencies that only + change when the actual commit/describe/version change. + + `${PROJECT_PREFIX}GitHash` + Target that recalculates the git hash each time. + + ## Output files + :::{note} + These files are updated only when the contents change. You can use them as dependencies for files generated from + . See for more + info on how to add file-level dependency + ::: + + `${OUTPUT_FOLDER}/.DynamicVersion.json` + All computed data of `DynamicVersion` + + `${OUTPUT_FOLDER}/.version` + Computed version + + `${OUTPUT_FOLDER}/.git_describe` + Computed git describe + + `${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) + + ]===] + + list(APPEND CMAKE_MESSAGE_CONTEXT dynamic_version) + set(ARGS_Options ALLOW_FAILS - ) - list(APPEND ARGS_OneValue + ) + set(ARGS_OneValue PROJECT_PREFIX OUTPUT_VERSION OUTPUT_DESCRIBE @@ -54,11 +142,13 @@ function(dynamic_version) FALLBACK_HASH TMP_FOLDER OUTPUT_FOLDER - ) + ) + set(ARGS_MultiValue + ) - cmake_parse_arguments(ARGS "${ARGS_Options}" "${ARGS_OneValue}" "${ARGS_MultiValue}" ${ARGN}) + cmake_parse_arguments(PARSE_ARGV 0 ARGS "${ARGS_Options}" "${ARGS_OneValue}" "${ARGS_MultiValue}") - set(DynamicVersion_ARGS "") + set(DynamicVersion_ARGS) # Set default values if (NOT DEFINED ARGS_OUTPUT_VERSION) @@ -88,11 +178,13 @@ function(dynamic_version) endif () if (NOT ARGS_PROJECT_PREFIX) message(AUTHOR_WARNING - "DynamicVersion: No PROJECT_PREFIX was given. Please provide one to avoid target name clashes") + "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") + "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) @@ -103,14 +195,15 @@ function(dynamic_version) 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") + "OUTPUT_FOLDER and TMP_FOLDER cannot 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}) @@ -134,7 +227,7 @@ function(dynamic_version) COMMAND_ERROR_IS_FATAL ANY) # Copy all configured files - foreach (file IN ITEMS .DynamicVersion.json .version .git_describe .git_commit) + 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}) endif () @@ -165,16 +258,16 @@ function(dynamic_version) -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 @@ -182,7 +275,8 @@ function(dynamic_version) PROPERTY CMAKE_CONFIGURE_DEPENDS ${ARGS_OUTPUT_FOLDER}/.version) message(VERBOSE - "DynamicVersion: Calculated version = ${${ARGS_OUTPUT_VERSION}}") + "Calculated version = ${${ARGS_OUTPUT_VERSION}}" + ) if (CMAKE_VERSION VERSION_LESS 3.25) # TODO: Remove when cmake 3.25 is commonly distributed @@ -196,36 +290,54 @@ function(dynamic_version) ${ARGS_OUTPUT_VERSION} ${ARGS_OUTPUT_COMMIT} ${ARGS_OUTPUT_DISTANCE} - ) + ) endfunction() + +#[==============================================================================================[ +# Auxiliary interface # +]==============================================================================================] + 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 + #[===[.md: + # get_dynamic_version + + Internal function that is called to calculate the dynamic version. This function is called by the + `${PROJECT_PREFIX}DynamicVersion` targets generated by {command}`dynamic_version`. + + In a nutshell, the `DynamicVersion.cmake` is executed with the variable `DynamicVersion_RUN` set to true. + + ## Synopsis + ```cmake + get_dynamic_version(PROJECT_SOURCE GIT_ARCHIVAL_FILE + TMP_FOLDER + [FALLBACK_VERSION ] [FALLBACK_HASH ] + ) + ``` + + ## Options + See {command}`dynamic_version` for details + + ## See also + - [pypa/setuptools_scm](https://github.com/pypa/setuptools_scm) + + ]===] + + list(APPEND CMAKE_MESSAGE_CONTEXT get_dynamic_version) + set(ARGS_Options + ALLOW_FAILS + ) + set(ARGS_OneValue PROJECT_SOURCE GIT_ARCHIVAL_FILE FALLBACK_VERSION FALLBACK_HASH TMP_FOLDER - ) - list(APPEND ARGS_Options - ALLOW_FAILS - ) + ) + set(ARGS_MultiValue + ) - cmake_parse_arguments(ARGS "${ARGS_Options}" "${ARGS_OneValue}" "${ARGS_MultiValue}" ${ARGN}) + cmake_parse_arguments(PARSE_ARGV 0 ARGS "${ARGS_Options}" "${ARGS_OneValue}" "${ARGS_MultiValue}") 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 @@ -262,8 +374,9 @@ function(get_dynamic_version) 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}") + "Missing file .git_archival.txt\n" + " .git_archival.txt: ${ARGS_GIT_ARCHIVAL_FILE}" + ) return() endif () @@ -273,8 +386,9 @@ function(get_dynamic_version) 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}") + "Missing string \"describe-name\" in .git_archival.txt\n" + " .git_archival.txt: ${ARGS_GIT_ARCHIVAL_FILE}" + ) return() endif () @@ -294,7 +408,9 @@ function(get_dynamic_version) 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") + message(DEBUG + "Found appropriate tag in .git_archival.txt file" + ) else () # If not it has to be computed from the git archive find_package(Git REQUIRED) @@ -305,8 +421,9 @@ function(get_dynamic_version) 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}") + "Project source is neither a git repository nor a git archive:\n" + " Source: ${ARGS_PROJECT_SOURCE}" + ) return() endif () # Get most recent commit hash @@ -324,8 +441,9 @@ function(get_dynamic_version) # 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}") + "Version tag is ill-formatted\n" + " Describe-name: ${describe-name}" + ) return() endif () string(JSON data SET @@ -334,6 +452,9 @@ function(get_dynamic_version) 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.]* WORKING_DIRECTORY ${ARGS_PROJECT_SOURCE} @@ -343,33 +464,46 @@ function(get_dynamic_version) # 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}") + "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") + message(DEBUG + "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}") + "Computed data:\n" + " data = ${data}" + ) file(WRITE ${ARGS_TMP_FOLDER}/.DynamicVersion.json ${data}) endfunction() + +#[==============================================================================================[ +# Private interface # +]==============================================================================================] + +# No private interface + + +#[==============================================================================================[ +# Misc # +]==============================================================================================] + # 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") + "DynamicVersion_ARGS not defined" + ) endif () get_dynamic_version(${DynamicVersion_ARGS}) endif () - diff --git a/src/bin/profile/CMakeLists.txt b/src/bin/profile/CMakeLists.txt index af20c491b..6f7117d9b 100644 --- a/src/bin/profile/CMakeLists.txt +++ b/src/bin/profile/CMakeLists.txt @@ -35,7 +35,7 @@ set_target_properties( add_test( NAME libint2/compiler/coretest/build - COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target libint-libcompiler-test + COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR} --target libint-libcompiler-test ) set_tests_properties( libint2/compiler/coretest/build diff --git a/src/lib/libint/CMakeLists.txt b/src/lib/libint/CMakeLists.txt index ada10dbf9..c6f4e6c1d 100644 --- a/src/lib/libint/CMakeLists.txt +++ b/src/lib/libint/CMakeLists.txt @@ -8,7 +8,7 @@ file(MAKE_DIRECTORY "${EXPORT_STAGE_DIR}/src") add_custom_command( OUTPUT "${EXPORT_STAGE_DIR}/src/libint2_params.h" - COMMAND build_libint + COMMAND $ WORKING_DIRECTORY "${EXPORT_STAGE_DIR}/src" DEPENDS build_libint @@ -59,6 +59,7 @@ add_custom_target(libint-library-export DEPENDS "${EXPORT_STAGE_DIR}.tgz") include(ExternalProject) list(APPEND library_CMAKE_ARGS + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DLIBINT2_ALIGN_SIZE=${LIBINT_ALIGN_SIZE} -DLIBINT2_REALTYPE=${LIBINT2_REALTYPE} -DLIBINT2_ENABLE_MPFR=${LIBINT2_ENABLE_MPFR} diff --git a/src/lib/libint/CMakeLists.txt.export b/src/lib/libint/CMakeLists.txt.export index 57e5a00c0..72e043505 100644 --- a/src/lib/libint/CMakeLists.txt.export +++ b/src/lib/libint/CMakeLists.txt.export @@ -34,6 +34,7 @@ include(CheckFunctionExists) # <<< General >>> +option_with_default(CMAKE_BUILD_TYPE "Build type" Release) 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 @@ -72,6 +73,10 @@ set(LIBINT2_SHELL_SET ${LIBINT2_SHELL_SET}) message(STATUS "Setting option LIBINT2_SHELL_SET: ${LIBINT2_SHELL_SET} (read-only from generation-time)") +######################## Process & Validate Options ########################### +include(autocmake_safeguards) + + ################################## Dependencies ################################# # See notes at https://github.com/evaleev/libint/blob/master/INSTALL.md#prerequisites diff --git a/src/lib/libint/populate.cmake b/src/lib/libint/populate.cmake index 0f478af3b..b6fb5d055 100644 --- a/src/lib/libint/populate.cmake +++ b/src/lib/libint/populate.cmake @@ -2,6 +2,7 @@ set(LIBRARY_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src/lib/libint) file( INSTALL + "${PROJECT_SOURCE_DIR}/cmake/modules/autocmake_safeguards.cmake" "${PROJECT_SOURCE_DIR}/cmake/modules/int_orderings.cmake" "${PROJECT_SOURCE_DIR}/cmake/modules/options.cmake" "${PROJECT_BINARY_DIR}/cmake/modules/int_computed.cmake"