From 29a3456b84267370fe0485369d0a85ed2c0df133 Mon Sep 17 00:00:00 2001 From: meriadeg perrinel Date: Tue, 28 Mar 2023 16:54:21 +0200 Subject: [PATCH 1/3] Added ROCBLAS and ROCSPARSE Dependendies for Kernels package --- TPLsList.cmake | 2 + cmake/TPLs/FindTPLROCBLAS.cmake | 63 +++++++++++++++++++ cmake/TPLs/FindTPLROCSPARSE.cmake | 63 +++++++++++++++++++ .../kokkos-kernels/cmake/Dependencies.cmake | 2 +- 4 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 cmake/TPLs/FindTPLROCBLAS.cmake create mode 100644 cmake/TPLs/FindTPLROCSPARSE.cmake diff --git a/TPLsList.cmake b/TPLsList.cmake index 33ee07e307a1..6b6e6e9187d0 100644 --- a/TPLsList.cmake +++ b/TPLsList.cmake @@ -61,6 +61,8 @@ TRIBITS_REPOSITORY_DEFINE_TPLS( CUBLAS "cmake/TPLs/" PT CUSOLVER "cmake/TPLs/" PT CUSPARSE "cmake/TPLs/" PT + ROCBLAS "cmake/TPLs/" PT + ROCSPARSE "cmake/TPLs/" PT Thrust "cmake/TPLs/" ST Cusp "cmake/TPLs/" ST TBB "cmake/TPLs/" EX diff --git a/cmake/TPLs/FindTPLROCBLAS.cmake b/cmake/TPLs/FindTPLROCBLAS.cmake new file mode 100644 index 000000000000..718165036a4e --- /dev/null +++ b/cmake/TPLs/FindTPLROCBLAS.cmake @@ -0,0 +1,63 @@ +# @HEADER +# ************************************************************************ +# +# Trilinos: An Object-Oriented Solver Framework +# Copyright (2001) Sandia Corporation +# +# +# Copyright (2001) Sandia Corporation. Under the terms of Contract +# DE-AC04-94AL85000, there is a non-exclusive license for use of this +# work by or on behalf of the U.S. Government. Export of this program +# may require a license from the United States Government. +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Corporation nor the names of the +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# NOTICE: The United States Government is granted for itself and others +# acting on its behalf a paid-up, nonexclusive, irrevocable worldwide +# license in this data to reproduce, prepare derivative works, and +# perform publicly and display publicly. Beginning five (5) years from +# July 25, 2001, the United States Government is granted for itself and +# others acting on its behalf a paid-up, nonexclusive, irrevocable +# worldwide license in this data to reproduce, prepare derivative works, +# distribute copies to the public, perform publicly and display +# publicly, and to permit others to do so. +# +# NEITHER THE UNITED STATES GOVERNMENT, NOR THE UNITED STATES DEPARTMENT +# OF ENERGY, NOR SANDIA CORPORATION, NOR ANY OF THEIR EMPLOYEES, MAKES +# ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL LIABILITY OR +# RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR USEFULNESS OF ANY +# INFORMATION, APPARATUS, PRODUCT, OR PROCESS DISCLOSED, OR REPRESENTS +# THAT ITS USE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS. +# +# ************************************************************************ +# @HEADER + +find_package(ROCBLAS) + +if(ROCBLAS_FOUND) + tribits_extpkg_create_imported_all_libs_target_and_config_file( ROCBLAS + INNER_FIND_PACKAGE_NAME ROCBLAS + IMPORTED_TARGETS_FOR_ALL_LIBS roc::rocblas ) +endif() + diff --git a/cmake/TPLs/FindTPLROCSPARSE.cmake b/cmake/TPLs/FindTPLROCSPARSE.cmake new file mode 100644 index 000000000000..d8a189dfd26d --- /dev/null +++ b/cmake/TPLs/FindTPLROCSPARSE.cmake @@ -0,0 +1,63 @@ +# @HEADER +# ************************************************************************ +# +# Trilinos: An Object-Oriented Solver Framework +# Copyright (2001) Sandia Corporation +# +# +# Copyright (2001) Sandia Corporation. Under the terms of Contract +# DE-AC04-94AL85000, there is a non-exclusive license for use of this +# work by or on behalf of the U.S. Government. Export of this program +# may require a license from the United States Government. +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Corporation nor the names of the +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# NOTICE: The United States Government is granted for itself and others +# acting on its behalf a paid-up, nonexclusive, irrevocable worldwide +# license in this data to reproduce, prepare derivative works, and +# perform publicly and display publicly. Beginning five (5) years from +# July 25, 2001, the United States Government is granted for itself and +# others acting on its behalf a paid-up, nonexclusive, irrevocable +# worldwide license in this data to reproduce, prepare derivative works, +# distribute copies to the public, perform publicly and display +# publicly, and to permit others to do so. +# +# NEITHER THE UNITED STATES GOVERNMENT, NOR THE UNITED STATES DEPARTMENT +# OF ENERGY, NOR SANDIA CORPORATION, NOR ANY OF THEIR EMPLOYEES, MAKES +# ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL LIABILITY OR +# RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR USEFULNESS OF ANY +# INFORMATION, APPARATUS, PRODUCT, OR PROCESS DISCLOSED, OR REPRESENTS +# THAT ITS USE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS. +# +# ************************************************************************ +# @HEADER + +find_package(ROCSPARSE) + +if(ROCSPARSE_FOUND) + tribits_extpkg_create_imported_all_libs_target_and_config_file( ROCSPARSE + INNER_FIND_PACKAGE_NAME ROCSPARSE + IMPORTED_TARGETS_FOR_ALL_LIBS roc::rocsparse ) +endif() + diff --git a/packages/kokkos-kernels/cmake/Dependencies.cmake b/packages/kokkos-kernels/cmake/Dependencies.cmake index 4ce5a98dc09e..d3b393dddef1 100644 --- a/packages/kokkos-kernels/cmake/Dependencies.cmake +++ b/packages/kokkos-kernels/cmake/Dependencies.cmake @@ -1,6 +1,6 @@ TRIBITS_PACKAGE_DEFINE_DEPENDENCIES( LIB_REQUIRED_PACKAGES KokkosCore KokkosContainers KokkosAlgorithms - LIB_OPTIONAL_TPLS quadmath MKL BLAS LAPACK CUSPARSE METIS SuperLU Cholmod CUBLAS + LIB_OPTIONAL_TPLS quadmath MKL BLAS LAPACK CUSPARSE METIS SuperLU Cholmod CUBLAS ROCBLAS ROCSPARSE TEST_OPTIONAL_TPLS yaml-cpp ) # NOTE: If you update names in LIB_OPTIONAL_TPLS above, make sure to map those names in From d34ca5b2139389c0719093bfdd5d0041091e132e Mon Sep 17 00:00:00 2001 From: "Roscoe A. Bartlett" Date: Wed, 29 Mar 2023 11:31:55 -0600 Subject: [PATCH 2/3] Automatic snapshot commit from tribits at 014a1538 Origin repo remote tracking branch: 'github/master' Origin repo remote repo URL: 'github = git@github.com:TriBITSPub/TriBITS.git' Git describe: Vera4.0-RC1-start-1488-gd9a337d8 At commit: commit 014a1538939b783602d2af6033b2175edfb51a96 Author: Roscoe A. Bartlett Date: Wed Mar 29 10:41:41 2023 -0600 Summary: Remove unused legacy RELATIVE_PATH code (#63, #560) --- cmake/tribits/CHANGELOG.md | 55 ++ .../ci_support/TribitsDumpDepsXmlScript.cmake | 2 +- .../TribitsWriteXmlDependenciesFiles.cmake | 1 - .../core/config_tests/fmangle/CMakeLists.txt | 2 +- .../CMakeLists.txt | 5 +- .../package_arch/TribitsAddAdvancedTest.cmake | 2 +- .../TribitsAddOptionAndDefine.cmake | 77 +- .../TribitsAdjustPackageEnables.cmake | 266 +++++- .../core/package_arch/TribitsConstants.cmake | 8 +- ...ImportedTargetsFindTplModuleHelpers.cmake} | 97 +-- ...ribitsExternalPackageWriteConfigFile.cmake | 261 ++++-- .../TribitsGetPackageEnableStatus.cmake | 23 +- ....cmake => TribitsGetPackageSublists.cmake} | 119 ++- .../package_arch/TribitsGlobalMacros.cmake | 62 +- ...ibitsInternalPackageWriteConfigFile.cmake} | 659 +++++---------- .../package_arch/TribitsPackageMacros.cmake | 50 +- .../TribitsPrintEnabledPackagesLists.cmake | 180 ++-- .../TribitsProcessEnabledTpl.cmake | 168 ---- .../TribitsProcessEnabledTpls.cmake | 286 +++++++ .../TribitsProcessPackagesAndDirsLists.cmake | 2 + .../TribitsProcessTplsLists.cmake | 106 +-- .../package_arch/TribitsProjectImpl.cmake | 4 - .../TribitsProjectWriteConfigFile.cmake | 228 ++++++ .../TribitsReadDepsFilesCreateDepsGraph.cmake | 6 +- ...itsSystemDataStructuresMacrosFunctions.rst | 89 +- ...ribitsTplFindIncludeDirsAndLibraries.cmake | 2 - ...TribitsWritePackageConfigFileHelpers.cmake | 65 ++ .../tribits_get_version_date.cmake | 2 +- cmake/tribits/core/std_tpls/FindTPLMPI.cmake | 6 +- .../ctest_driver/TribitsCTestDriverCore.cmake | 13 +- .../TribitsCTestDriverCoreHelpers.cmake | 4 +- .../TribitsGetCTestTestXmlDir.cmake | 2 +- .../tribits_ctest_update_commands.cmake | 2 +- ...ribits_ctest_update_commands_wrapper.cmake | 2 +- ...dd-CTEST_RESOURCE_SPEC_FILE-variable.patch | 377 --------- .../tribits/devtools_install/install-cmake.py | 8 +- .../build_ref/TribitsBuildReferenceBody.rst | 106 ++- .../doc/build_ref/create-project-build-ref.py | 4 +- ...TribitsCMakeLanguageOverviewAndGotchas.rst | 238 ++++++ .../guides/TribitsCoreDetailedReference.rst | 14 + .../tribits/doc/guides/TribitsGuidesBody.rst | 771 +++++++++--------- .../doc/guides/TribitsGuidesReferences.rst | 2 +- .../TribitsMacroFunctionDocTemplate.rst | 7 +- .../TribitsSystemMacroFunctionDocTemplate.rst | 6 +- .../TribitsMaintainersGuide.rst | 2 + .../guides/users_guide/TribitsUsersGuide.rst | 2 + .../src/TribitsTutorial_ConvertAProject.rst | 4 +- .../src/TribitsTutorial_HelloWorld.rst | 2 +- .../examples/MockTrilinos/CMakeLists.txt | 3 +- .../RawAndTribitsHelloWorld/CMakeLists.txt | 2 +- .../ReducedMockTrilinos/CMakeLists.txt | 2 +- .../examples/TribitsExampleApp/CMakeLists.txt | 2 +- .../TribitsExampleApp2/CMakeLists.txt | 2 +- .../TribitsExampleMetaProject/CMakeLists.txt | 2 +- .../TribitsExampleProject/CMakeLists.txt | 2 +- .../packages/simple_cxx/CMakeLists.txt | 1 + .../with_subpackages/b/CMakeLists.txt | 1 + .../packages/wrap_external/CMakeLists.txt | 60 +- .../TribitsExampleProject2/CMakeLists.txt | 2 +- .../CMakeLists.txt | 2 +- .../examples/TribitsHelloWorld/CMakeLists.txt | 2 +- .../TribitsOldSimpleExampleApp/CMakeLists.txt | 2 +- .../TribitsSimpleExampleApp/CMakeLists.txt | 2 +- .../examples/tpls/SimpleTpl/CMakeLists.txt | 2 +- .../tribits/examples/tpls/Tpl1/CMakeLists.txt | 2 +- .../tribits/examples/tpls/Tpl2/CMakeLists.txt | 2 +- .../tribits/examples/tpls/Tpl3/CMakeLists.txt | 2 +- .../tribits/examples/tpls/Tpl4/CMakeLists.txt | 2 +- 68 files changed, 2629 insertions(+), 1867 deletions(-) rename cmake/tribits/core/package_arch/{TribitsExternalPackageFindTplHelpers.cmake => TribitsExternalPackageWithImportedTargetsFindTplModuleHelpers.cmake} (57%) rename cmake/tribits/core/package_arch/{TribitsGetEnabledSublists.cmake => TribitsGetPackageSublists.cmake} (56%) rename cmake/tribits/core/package_arch/{TribitsWriteClientExportFiles.cmake => TribitsInternalPackageWriteConfigFile.cmake} (67%) delete mode 100644 cmake/tribits/core/package_arch/TribitsProcessEnabledTpl.cmake create mode 100644 cmake/tribits/core/package_arch/TribitsProcessEnabledTpls.cmake create mode 100644 cmake/tribits/core/package_arch/TribitsProjectWriteConfigFile.cmake create mode 100644 cmake/tribits/core/package_arch/TribitsWritePackageConfigFileHelpers.cmake delete mode 100644 cmake/tribits/devtools_install/0001-CTest-Add-CTEST_RESOURCE_SPEC_FILE-variable.patch create mode 100644 cmake/tribits/doc/guides/TribitsCMakeLanguageOverviewAndGotchas.rst diff --git a/cmake/tribits/CHANGELOG.md b/cmake/tribits/CHANGELOG.md index a03ba918a475..ad09ea89dcb7 100644 --- a/cmake/tribits/CHANGELOG.md +++ b/cmake/tribits/CHANGELOG.md @@ -2,6 +2,61 @@ ChangeLog for TriBITS ---------------------------------------- +## 2023-02-24: + +* **Changed:** Upgraded minimum required CMake version from 3.17 to 3.23. + Existing TriBITS projects that have already upgraded to require CMake 3.23+ + should not notice any major changes due to this change. + +## 2023-02-21: + +* **Added:** Added support for pre-installed internal packages treated as + external packages. Now, any set of internally defined TriBITS packages for + a TriBITS project can be pre-built and pre-installed and the remaining + packages in the TriBITS project can be configured to point to those by + setting `-D TPL_ENABLE_=ON`. This allows great flexibility in how + a TriBITS project's packages can be and built, installed, and deployed. + This technically implements "Use Case 3: Configure/build pointing to a + subset of already installed TriBITS packages in same repo" in [TriBITS + #63](https://github.com/TriBITSPub/TriBITS/issues/63). See the section + "Building against pre-installed packages" in the updated build reference + documentation for details. + +* **Fixed:** Setting `-D_ENABLE_=ON` for an external + package/TPL `` will not correctly enable and process the TPL. + +## 2022-12-07: + +* **Changed:** Setting `-D_ENABLE_=ON` now triggers the + enable an external package/TPL `` similar to the way that + `-DTPL_ENABLE_` has always done. This is technically a change in + backward compatibility because setting `_ENABLE_=ON` for + an external package/TPL used to be ignored. This change was done as part of + a general refactoring to unify the handling of internal and external + packages and is a side effect of that refactoring (see [TriBITS + #63](https://github.com/TriBITSPub/TriBITS/issues/63)). (Initially, setting + `-D_ENABLE_=ON` resulted in a failed configure because the + refactoring was not complete for the handling of external packages/TPL. But + this was fixed in a latter update.) + +## 2023-10-25: + +* **Added:** New option `_SKIP_INSTALL_PROJECT_CMAKE_CONFIG_FILES` + skips the install of the project-level `Config.cmake` file. The + default value is ``FALSE`` so as to maintain backward compatibility. (The + project can change the default.) + +* **Changed:** External packages/TPLs are now processed at the base project + scope level. This allows simple `set()` statements in package module files + or config files included by `find_package()` to have project-level scope for + the entire TriBITS project. This is more similar to how a raw CMake project + would usually behave that calls `find_package()` in the base + `CMakeLists.txt` file. Before, calls to `find_package()` were wrapped in a + CMake `function()` called from the base project directory scope. So while + IMPORTED targets created from a `find_package()` command where visible at + the base directory project-level scope, local variables were not. With this + change, now they are. + ## 2023-01-10: * **Added:** Added back support for deprecated variable diff --git a/cmake/tribits/ci_support/TribitsDumpDepsXmlScript.cmake b/cmake/tribits/ci_support/TribitsDumpDepsXmlScript.cmake index 5c926e9023f6..f55d03364ca4 100644 --- a/cmake/tribits/ci_support/TribitsDumpDepsXmlScript.cmake +++ b/cmake/tribits/ci_support/TribitsDumpDepsXmlScript.cmake @@ -50,7 +50,7 @@ # -P /ci_support/TribitsDumpDepsXmlScript.cmake # -cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) # A) Echo input options (must be specified with -D arguments to CMake command) diff --git a/cmake/tribits/ci_support/TribitsWriteXmlDependenciesFiles.cmake b/cmake/tribits/ci_support/TribitsWriteXmlDependenciesFiles.cmake index 1091008e3c01..2360acf1628e 100644 --- a/cmake/tribits/ci_support/TribitsWriteXmlDependenciesFiles.cmake +++ b/cmake/tribits/ci_support/TribitsWriteXmlDependenciesFiles.cmake @@ -178,7 +178,6 @@ function(tribits_write_deps_to_xml_string packageName libOrTest requiredOrOpti set(listType ${libOrTest}_${requiredOrOptional}_DEP_${packagesOrTpls}) message("") - print_var(listType) tribits_get_legacy_package_deps_sublist(${packageName} ${libOrTest} ${requiredOrOptional} ${packagesOrTpls} legacyPackageDepsList) diff --git a/cmake/tribits/core/config_tests/fmangle/CMakeLists.txt b/cmake/tribits/core/config_tests/fmangle/CMakeLists.txt index 0e24dacff5d5..2112fa58a44e 100644 --- a/cmake/tribits/core/config_tests/fmangle/CMakeLists.txt +++ b/cmake/tribits/core/config_tests/fmangle/CMakeLists.txt @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -cmake_minimum_required(VERSION 3.17) +cmake_minimum_required(VERSION 3.23) project(fmangle C Fortran) add_definitions(${COMMON_DEFS}) set(CMAKE_VERBOSE_MAKEFILE ON) diff --git a/cmake/tribits/core/installation/add_project_install_commands/CMakeLists.txt b/cmake/tribits/core/installation/add_project_install_commands/CMakeLists.txt index 14054ad190fe..67c74c964b0d 100644 --- a/cmake/tribits/core/installation/add_project_install_commands/CMakeLists.txt +++ b/cmake/tribits/core/installation/add_project_install_commands/CMakeLists.txt @@ -2,10 +2,11 @@ set(tribits_install_src "${${PROJECT_NAME}_TRIBITS_DIR}/${TRIBITS_CMAKE_INSTALLATION_FILES_DIR}") if ( ${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES - AND NOT ${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING + AND (NOT ${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING) + AND (NOT ${PROJECT_NAME}_SKIP_INSTALL_PROJECT_CMAKE_CONFIG_FILES) ) - include(TribitsWriteClientExportFiles) + include(TribitsProjectWriteConfigFile) tribits_write_project_client_export_files() diff --git a/cmake/tribits/core/package_arch/TribitsAddAdvancedTest.cmake b/cmake/tribits/core/package_arch/TribitsAddAdvancedTest.cmake index 0faae73d3a13..4c3ad13b8a3e 100644 --- a/cmake/tribits/core/package_arch/TribitsAddAdvancedTest.cmake +++ b/cmake/tribits/core/package_arch/TribitsAddAdvancedTest.cmake @@ -858,7 +858,7 @@ include(PrintVar) # ``${PROJECT_NAME}_TRIBITS_DIR`` (pointing to the TriBITS location). For example, # a valid project can be a simple as:: # -# cmake_minimum_required(VERSION 3.17.0) +# cmake_minimum_required(VERSION 3.23.0) # set(PROJECT_NAME TAATDriver) # project(${PROJECT_NAME} NONE) # set(${PROJECT_NAME}_TRACE_ADD_TEST TRUE) diff --git a/cmake/tribits/core/package_arch/TribitsAddOptionAndDefine.cmake b/cmake/tribits/core/package_arch/TribitsAddOptionAndDefine.cmake index 6f6e2945d794..f210f2eaafd6 100644 --- a/cmake/tribits/core/package_arch/TribitsAddOptionAndDefine.cmake +++ b/cmake/tribits/core/package_arch/TribitsAddOptionAndDefine.cmake @@ -41,29 +41,34 @@ include(TribitsPkgExportCacheVars) include(GlobalSet) -# @MACRO: tribits_add_option_and_define() +# @FUNCTION: tribits_add_option_and_define() # # Add an option and an optional macro define variable in one shot. # # Usage:: # # tribits_add_option_and_define( -# "" ) +# "" [NONCACHE]) # # This macro sets the user cache ``BOOL`` variable ```` and if # it is true, then sets the global (internal cache) macro define variable -# ```` to ``ON``, and otherwise sets it to ``OFF``. This is -# designed to make it easy to add a user-enabled option to a configured header -# file and have the define set in one shot. This would require that the -# package's configure file (see `tribits_configure_file()`_) have the line:: +# ```` to ``ON``, and otherwise sets it to ``OFF``. If +# ``NONCACHE`` is passed in, then ```` is set as a non-cache +# local varaible instead of a cache variable. +# +# This is designed to make it easy to add a user-enabled option to a +# configured header file and have the define set in one shot. This would +# require that the package's configure file (see `tribits_configure_file()`_) +# have the line:: # # #cmakedefine # # NOTE: This also calls `tribits_pkg_export_cache_var()`_ to export the -# variables ```` and ````. This also -# requires that local variables with the same names of these cache variables -# not be assigned with a different value from these cache variables. If they -# are, then an error will occur later when these variables are read. +# variables ```` and ```` (when ``NONCACHE`` +# is **not** passed). This also requires that local variables with the same +# names of these cache variables not be assigned with a different value from +# these cache variables. If they are, then an error will occur later when +# these variables are read. # # NOTE: The define var name ```` can be empty "" in which # case all logic related to ```` is skipped. (But in this @@ -71,25 +76,47 @@ include(GlobalSet) # # set( CACHE BOOL "") # -macro(tribits_add_option_and_define USER_OPTION_NAME MACRO_DEFINE_NAME - DOCSTRING DEFAULT_VALUE +function(tribits_add_option_and_define USER_OPTION_NAME MACRO_DEFINE_NAME + DOCSTRING DEFAULT_VALUE ) - #message("TRIBITS_ADD_OPTION_AND_DEFINE: '${USER_OPTION_NAME}' '${MACRO_DEFINE_NAME}' '${DEFAULT_VALUE}'") + # Assert inputs + set(set_MACRO_DEFINE_NAME_noncache OFF) + if ("${ARGN}" STREQUAL "NONCACHE") + set(set_MACRO_DEFINE_NAME_noncache ON) + elseif (NOT "${ARGN}" STREQUAL "") + message(SEND_ERROR "Error, optional argument" + " '${ARGN}' can only be 'NONCACHE' or empty!") + endif() + # Assert these are not already defined local vars + if (DEFINED ${USER_OPTION_NAME}) + if (NOT DEFINED CACHE{${USER_OPTION_NAME}}) + message(SEND_ERROR "ERROR: The option" + " ${USER_OPTION_NAME}='${${USER_OPTION_NAME}}'" + " is already defined as a non-cache variable!") + endif() + endif() + if (DEFINED ${MACRO_DEFINE_NAME}) + if (NOT DEFINED CACHE{${MACRO_DEFINE_NAME}}) + message(SEND_ERROR "ERROR: The macro define name" + " ${MACRO_DEFINE_NAME}='${${MACRO_DEFINE_NAME}}'" + " is already defined as a non-cache variable!") + endif() + endif() + # Set ${USER_OPTION_NAME} as exported cache var set( ${USER_OPTION_NAME} "${DEFAULT_VALUE}" CACHE BOOL "${DOCSTRING}" ) + tribits_pkg_export_cache_var(${USER_OPTION_NAME}) + # Set ${MACRO_DEFINE_NAME} as local or exported cache var if(NOT "${MACRO_DEFINE_NAME}" STREQUAL "") if(${USER_OPTION_NAME}) - global_set(${MACRO_DEFINE_NAME} ON) + set(macroDefineValue ON) else() - global_set(${MACRO_DEFINE_NAME} OFF) + set(macroDefineValue OFF) + endif() + if (set_MACRO_DEFINE_NAME_noncache) + set(${MACRO_DEFINE_NAME} ${macroDefineValue} PARENT_SCOPE) + else() + global_set(${MACRO_DEFINE_NAME} ${macroDefineValue}) + tribits_pkg_export_cache_var(${MACRO_DEFINE_NAME}) endif() endif() - tribits_pkg_export_cache_var(${USER_OPTION_NAME}) - if(NOT "${MACRO_DEFINE_NAME}" STREQUAL "") - tribits_pkg_export_cache_var(${MACRO_DEFINE_NAME}) - endif() -endmacro() - -# 2008/10/05: rabartl: ToDo: Add an option to automatically add the macro -# define to any XXX_config.h file that gets configured by -# tribits_configure_file(...). This will help to eliminate -# duplication. +endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsAdjustPackageEnables.cmake b/cmake/tribits/core/package_arch/TribitsAdjustPackageEnables.cmake index 53bbb1f2b5d5..cc6da7aba6df 100644 --- a/cmake/tribits/core/package_arch/TribitsAdjustPackageEnables.cmake +++ b/cmake/tribits/core/package_arch/TribitsAdjustPackageEnables.cmake @@ -87,6 +87,7 @@ macro(tribits_adjust_package_enables) tribits_sweep_backward_enable_upstream_packages() tribits_set_cache_vars_for_current_enabled_packages() tribits_do_final_parent_packages_enables_for_subpackage_enables() + tribits_adjust_internal_external_packages() tribits_setup_enabled_lists_and_pkg_idxs() tribits_setup_direct_packages_dependencies_lists_and_lib_required_enable_vars() tribits_print_direct_packages_dependencies_lists() @@ -224,7 +225,7 @@ endmacro() # NOTE: Above, we are sweeping over *all* of the not-disabled packages listed # in ${PROJECT_NAME}_DEFINED_INTERNAL_PACKAGES, including those package that # might have _PACKAGE_BUILD_STATUS=EXTERNAL. That makes sense -# because these are TriBITS (or TriBITS compatible) packages so we should +# because these are TriBITS (or TriBITS-compliant) packages so we should # assume that all of their downstream packages, whether internal or external, # should be enabled as well. If we find this is not the desirable behavior, # then we can change this later. @@ -276,8 +277,7 @@ endmacro() # @MACRO: tribits_sweep_backward_enable_upstream_packages() # -# Sweep backwards and enable required and (optionally) optional upstream -# packages. +# Sweep backwards and enable required (and optional) upstream packages. # # This sets the final value for: # @@ -351,6 +351,30 @@ macro(tribits_do_final_parent_packages_enables_for_subpackage_enables) endmacro() +# @MACRO: tribits_adjust_internal_external_packages() +# +# Macro to adjust the set of internal and external packages by changing +# `_PACKAGE_BUILD_STATUS`. +# +# This macro sweeps backwards over the dependency graph setting. +# +# NOTE: This is called **after** all of the logic that determines what +# packages are enabled or disabled. This is because we don't want to change +# the enable/disable logic when one or more initially internal packages are +# made external. We are going to just assume that if an initially internal +# package that is declared external should be disabled, then the user will +# need to make that decision explicitly. +# +macro(tribits_adjust_internal_external_packages) + tribits_create_reverse_list(${PROJECT_NAME}_DEFINED_PACKAGES + ${PROJECT_NAME}_REVERSE_DEFINED_PACKAGES) + message("\nAdjust the set of internal and external packages:\n") + foreach(packageName IN LISTS ${PROJECT_NAME}_REVERSE_DEFINED_PACKAGES) + tribits_set_package_and_related_upstream_packages_to_external(${packageName}) + endforeach() +endmacro() + + # Macro that sets up the basic lists of enabled packages and packages. # macro(tribits_setup_enabled_lists_and_pkg_idxs) @@ -663,7 +687,9 @@ endmacro() # macro(tribits_enable_upstream_packages packageName) - if (${PROJECT_NAME}_ENABLE_${packageName}) + tribits_get_package_enable_status(${packageName} packageEnable packageEnableVar) + + if (packageEnable) foreach(depPkg IN LISTS ${packageName}_LIB_DEFINED_DEPENDENCIES) tribits_private_enable_dep_package(${packageName} ${depPkg} LIB) @@ -769,13 +795,15 @@ endmacro() macro(tribits_enable_parent_package_for_subpackage_enables toplevelPackageName) foreach(tap2_subPkgName IN LISTS ${toplevelPackageName}_SUBPACKAGES) set(subpkgFullName ${toplevelPackageName}${tap2_subPkgName}) - if (${PROJECT_NAME}_ENABLE_${subpkgFullName} - AND (NOT ${PROJECT_NAME}_ENABLE_${toplevelPackageName}) - ) + tribits_get_package_enable_status(${toplevelPackageName} + toplevelPackageEnable toplevelPackageEnableVarName) + tribits_get_package_enable_status(${subpkgFullName} + subpkgEnable subpkgEnableVarName) + if (subpkgEnable AND (NOT toplevelPackageEnable)) message("-- " - "Setting ${PROJECT_NAME}_ENABLE_${toplevelPackageName}=ON" - " because ${PROJECT_NAME}_ENABLE_${subpkgFullName}=ON") - set(${PROJECT_NAME}_ENABLE_${toplevelPackageName} ON) + "Setting ${toplevelPackageEnableVarName}=ON because" + " ${subpkgEnableVarName}=${subpkgEnable}") + set(${toplevelPackageEnableVarName} ON) tribits_set_parent_package_subpackage_enable_for_enabled_subpackages( ${toplevelPackageName}) tribits_set_parent_package_test_example_enable_for_enabled_subpackages( @@ -794,6 +822,51 @@ macro(tribits_enable_parent_package_for_subpackage_enables toplevelPackageName) endmacro() +# Macro that sets $``{packageName}_PACKAGE_BUILD_STATUS=EXTERNAL and direct +# upstream dependent packages ``${depPkg}_PACKAGE_BUILD_STATUS=EXTERNAL`` if +# required. +# +# * Set an INTERNAL package as EXTERNAL if ``TPL_ENABLE_${packageName}`` is +# ``TRUE`` +# +# * Set a top-level package to EXTERNAL if any of its subpackages are EXTERNAL +# (or ``TPL_ENABLE_${subpkgFullName}`` is TRUE). +# +# This macro must be called in a backward/reverse sweep over the dependency +# graph to work correctly. It sets upstream packages as EXTERNAL if the given +# downstream package ```` is EXTERNAL. There is also special +# logic for handling a package that has subpackages. That is, if any +# subpackage of ```` is determined is EXTERNAL, then the parent +# package is set to EXTERNAL and all of the other subpackages in parent +# package ```` are set as EXTERNAL as well. (We don't allow a +# subset of subpackages in a parent package to be EXTERNAL and the other +# subpackages to be INTERNAL. That would be way too complicated to implement +# and be way too confusing for implementors and users.) +# +macro(tribits_set_package_and_related_upstream_packages_to_external packageName) + + tribits_set_parent_package_external_if_subpackage_external(${packageName} + subpackageTriggeredParentPackageExternal) + + tribits_set_package_to_external_if_requested_by_user(${packageName}) + + tribits_set_upstream_dep_packages_as_external(${packageName} + ${subpackageTriggeredParentPackageExternal}) + + tribits_set_package_as_processed_by_downstream_tribits_external_package(${packageName}) + +endmacro() +# NOTE: In the above macro, if ${packageName} is made EXTERNAL because it one +# of its subpackages is considered EXTERNAL, then the loop over all of the +# package's upstream dependencies listed in +# ${packageName}_LIB_DEFINED_DEPENDENCIES results in all of the other +# subpackages in that package to also be treated as external. (I.e., there is +# no need for a special loop over subpackages for the parent package. And the +# only direct dependencies for a parent package should be its subpackages. If +# that is not the case, then, technically, this would be setting more packages +# as EXTERNAL than need to be.) + + # Macro that sets up the flat list of direct package dependencies and enabled # package dependencies and sets ${packageName}_ENABLE_${depPkg} for LIB # dependencies @@ -1049,9 +1122,11 @@ macro(tribits_private_enable_dep_package packageName depPkgName libOrTest) tribits_get_package_enable_status(${depPkgName} depPkgEnable depPkgEnableVar) if (depPkgEnable) #message("The package is already enabled so there is nothing to enable!") - elseif (${depPkgEnableVar} STREQUAL "") + elseif ("${depPkgEnable}" STREQUAL "") set(tpedp_enableDepPkg "") - if (${packageName}_${libOrTest}_DEP_REQUIRED_${depPkgName}) + if (${packageName}_${libOrTest}_DEP_REQUIRED_${depPkgName} + AND (NOT "${${packageName}_SOURCE_DIR}" STREQUAL "") + ) message("-- " "Setting ${depPkgEnableVar}=ON" " because ${packageName} has a required dependence on ${depPkgName}") set(tpedp_enableDepPkg ON) @@ -1164,6 +1239,125 @@ macro(tribits_private_add_optional_package_enable packageName optionalDepPkgNa endmacro() +# Set the parent package as EXTERNAL if any of its subpackages are being +# treated as EXTERNAL and return bool if that is the case. +# +# On output, ``_PACKAGE_BUILD_STATUS`` will have been set +# to ``EXTERNAL`` if the returned var +# ``subpackageTriggeredParentPackageExternalOut`` is ``TRUE``. +# +macro(tribits_set_parent_package_external_if_subpackage_external parentPackageName + subpackageTriggeredParentPackageExternalOut + ) + + set(subpackageTriggeredParentPackageExternal FALSE) + + if (NOT ${parentPackageName}_PACKAGE_BUILD_STATUS STREQUAL "EXTERNAL") + foreach (tap2_subPkgName IN LISTS ${parentPackageName}_SUBPACKAGES) + set(subpkgFullName ${parentPackageName}${tap2_subPkgName}) + tribits_package_is_external(${subpkgFullName} subpkgIsExternal) + if (subpkgIsExternal) + set(becauseMsgStr "subpackage ${subpkgFullName} being treated as EXTERNAL") + if (TPL_ENABLE_${subpkgFullName}) + string(APPEND becauseMsgStr + " (TPL_ENABLE_${subpkgFullName}=${TPL_ENABLE_${subpkgFullName}})") + endif() + tribits_set_internal_package_to_external(${parentPackageName} "${becauseMsgStr}") + set(subpackageTriggeredParentPackageExternal TRUE) + break() + endif() + endforeach() + endif() + + set(${subpackageTriggeredParentPackageExternalOut} + ${subpackageTriggeredParentPackageExternal}) + +endmacro() + + +# Macro that sets ``_PACKAGE_BUILD_STATUS`` to ``EXTERNAL`` if +# requested by the user (e.g. by setting ``TPL_ENABLE_``). +# +macro(tribits_set_package_to_external_if_requested_by_user packageName) + if (NOT ${packageName}_PACKAGE_BUILD_STATUS STREQUAL "EXTERNAL") + if (TPL_ENABLE_${packageName}) + tribits_set_internal_package_to_external(${packageName} + "TPL_ENABLE_${packageName}=${TPL_ENABLE_${packageName}}") + endif() + endif() +endmacro() + + +# Macro that sets all of the direct upstream dependent packages as EXTERNAL if +# they should be. +# +# NOTE: We only bother setting upstream dependencies as EXTERNAL if the +# package ```` is enabled or if it is a parent package (enabled +# or not) where at least one of its subpackages is enabled and is being +# treated as EXTERNAL. (In the latter case, any subpackages that are not +# enabled will still be set as EXTERNAL.) +# +macro(tribits_set_upstream_dep_packages_as_external packageName + subpackageTriggeredParentPackageExternal + ) + + tribits_get_package_enable_status(${packageName} packageEnable "") + + if (${packageName}_PACKAGE_BUILD_STATUS STREQUAL "EXTERNAL") + foreach(depPkg IN LISTS ${packageName}_LIB_DEFINED_DEPENDENCIES) + if ((NOT ${depPkg}_PACKAGE_BUILD_STATUS STREQUAL "EXTERNAL") AND + (subpackageTriggeredParentPackageExternal OR packageEnable) + ) + tribits_set_internal_package_to_external(${depPkg} + "downstream package ${packageName} being treated as EXTERNAL") + endif() + endforeach() + endif() + +endmacro() + + +# Mark a package as being processed by a downstream TriBITS-compliant external +# package +# +macro(tribits_set_package_as_processed_by_downstream_tribits_external_package packageName) + + set_default(${packageName}_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE FALSE) + + tribits_get_package_enable_status(${packageName} packageEnable "") + + if (${packageName}_PACKAGE_BUILD_STATUS STREQUAL "EXTERNAL") + + foreach(fwdDepPkg IN LISTS ${packageName}_FORWARD_LIB_DEFINED_DEPENDENCIES) + + if((${fwdDepPkg}_IS_TRIBITS_COMPLIANT + OR ${fwdDepPkg}_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE) + AND (${fwdDepPkg}_PACKAGE_BUILD_STATUS STREQUAL "EXTERNAL") + ) + tribits_get_package_enable_status(${fwdDepPkg} fwdDepPkgEnable "") + if (${fwdDepPkg}_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE) + set(directOrIndirectStr "indirectly") + set(downstreamPkgStr "") + else() + set(directOrIndirectStr "directly") + set(downstreamPkgStr " ${fwdDepPkg}") + endif() + if (packageEnable AND (NOT ${packageName}_IS_TRIBITS_COMPLIANT)) + message("-- " + "NOTE: ${packageName} is ${directOrIndirectStr} downstream from a" + " TriBITS-compliant external package${downstreamPkgStr}") + endif() + set(${packageName}_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE TRUE) + break() + endif() + + endforeach() + + endif() + +endmacro() + + # Macro that sets ``_ENABLE_=ON`` if not already # enabled for all enabled subpackages of a parent package. # @@ -1204,4 +1398,52 @@ macro(tribits_set_parent_package_test_example_enable_for_enabled_subpackages endmacro() +# Macro that sets an internal package to EXTERNAL and print so and why (if the +# package is actually enabled) +# +# Usage:: +# +# tribits_set_internal_package_to_external( "" +# "" ...) +# +# This always sets ``_PACKAGE_BUILD_STATUS=EXTERNAL`` but only +# prints the message if ```` is enabled. +# +macro(tribits_set_internal_package_to_external depPkgName) + if (NOT ${depPkgName}_INTERNAL_PACKAGE_ALREADY_SET_EXTERNAL) + tribits_get_package_enable_status(${depPkgName} depPkgEnable "") + if (depPkgEnable) + message("-- " + "Treating internal package ${depPkgName} as EXTERNAL because" + " " ${ARGN}) + endif() + set(${depPkgName}_PACKAGE_BUILD_STATUS EXTERNAL) + set(${depPkgName}_FINDMOD TRIBITS_PKG) + set(${depPkgName}_INTERNAL_PACKAGE_ALREADY_SET_EXTERNAL TRUE) + endif() +endmacro() + + +macro(tribits_set_as_processed_by_downstream_tribits_external_package packageName + depPkgName + ) + +endmacro() + + +# Function to return if is to be treated as an EXTERNAL package +# in processing of the package +# +function(tribits_package_is_external packageName packageIsExternalOut) + if (TPL_ENABLE_${packageName}) + set(packageIsExternal TRUE) + elseif (${packageName}_PACKAGE_BUILD_STATUS STREQUAL "EXTERNAL") + set(packageIsExternal TRUE) + else() + set(packageIsExternal FALSE) + endif() + set(${packageIsExternalOut} ${packageIsExternal} PARENT_SCOPE) +endfunction() + + # LocalWords: tribits TriBITS foreach endmacro endfunction diff --git a/cmake/tribits/core/package_arch/TribitsConstants.cmake b/cmake/tribits/core/package_arch/TribitsConstants.cmake index efda842730a2..b26d497c55ba 100644 --- a/cmake/tribits/core/package_arch/TribitsConstants.cmake +++ b/cmake/tribits/core/package_arch/TribitsConstants.cmake @@ -39,7 +39,7 @@ # Define the TriBITS minimum required CMake version -set(TRIBITS_CMAKE_MINIMUM_REQUIRED 3.17.0) +set(TRIBITS_CMAKE_MINIMUM_REQUIRED 3.23.0) macro(tribits_asesrt_minimum_cmake_version) @@ -50,12 +50,6 @@ macro(tribits_asesrt_minimum_cmake_version) endmacro() -# Misc constants - -set(${PROJECT_NAME}_CTEST_USE_NEW_AAO_FEATURES TRUE) -# NOTE: This is left to maintain backward compatibility after upgrade to CMake -# 3.17 but this option is now hard-coded to TRUE in the implementation. - # File names for TriBITS system set(${PROJECT_NAME}_PACKAGES_FILE_NAME PackagesList.cmake) diff --git a/cmake/tribits/core/package_arch/TribitsExternalPackageFindTplHelpers.cmake b/cmake/tribits/core/package_arch/TribitsExternalPackageWithImportedTargetsFindTplModuleHelpers.cmake similarity index 57% rename from cmake/tribits/core/package_arch/TribitsExternalPackageFindTplHelpers.cmake rename to cmake/tribits/core/package_arch/TribitsExternalPackageWithImportedTargetsFindTplModuleHelpers.cmake index 1873267bd047..d6f3fd7ae44d 100644 --- a/cmake/tribits/core/package_arch/TribitsExternalPackageFindTplHelpers.cmake +++ b/cmake/tribits/core/package_arch/TribitsExternalPackageWithImportedTargetsFindTplModuleHelpers.cmake @@ -38,12 +38,32 @@ # @HEADER -# @FUNCTION: tribits_extpkg_create_imported_all_libs_target_and_config_file() +################################################################################ +# +# Module TribitsExternalPackageWithImportedTargetsFindTplModuleHelpers.cmake # -# Call from a ``FindTPL.cmake`` module that calls inner -# ``find_package()`` for external package that uses modern CMake +# Contains functions for implementing FindTPL.cmake files for +# external packages using find_package() that producing modern # IMPORTED targets. # +# NOTE: The acronym 'extpkgwit' stands for "External Package With Imported +# Targets". +# +################################################################################ + + +include(TribitsExternalPackageWriteConfigFile) + + + +# @FUNCTION: tribits_extpkg_create_imported_all_libs_target_and_config_file() +# +# Called from a `FindTPL.cmake`_ module which first calls +# ``find_package()``and the calls this function to get and +# external package that uses modern CMake IMPORTED targets. This function +# creates the ``::all_libs`` target and creates a TriBITS-compliant +# external package wrapper file `Config.cmake`. +# # Usage:: # # tribits_extpkg_create_imported_all_libs_target_and_config_file( @@ -51,18 +71,21 @@ # INNER_FIND_PACKAGE_NAME # IMPORTED_TARGETS_FOR_ALL_LIBS ... ) # -# This function is called in a TriBITS ``FindTPL.cmake`` wrapper -# module after it calls ``find_package()`` and then creates the -# IMPORTED target ``::all_libs`` from the list of IMPORTED targets -# `` ...`` which are defined from the call -# ``find_package()``. This function also takes care of -# generating the correct ``Config.cmake`` file under the directory:: +# This function is called from a TriBITS ``FindTPL.cmake`` wrapper +# module after it calls ``find_package()`` and then this function +# creates the IMPORTED target ``::all_libs`` from the list of +# IMPORTED targets `` ...`` which are +# defined from the call ``find_package()``. This function also +# takes care of generating the correct ``Config.cmake`` file under +# the directory:: # # ${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR} # -# The generated ``Config.cmake`` file calls -# ``find_dependency()`` (with no other argument) and then, again, -# defines the correct imported library dependency. +# The generated ``Config.cmake`` file pulls in the upstream +# TriBITS-compliant ``Config.cmake` files, calls +# ``find_dependency()`` (with no other arguments), defines the +# `::all_libs`` target, and then sets up the correct dependencies +# between these targets. # # For more details, see `Creating FindTPL.cmake using find_package() # with IMPORTED targets`_. @@ -87,56 +110,10 @@ function(tribits_extpkg_create_imported_all_libs_target_and_config_file target_link_libraries(${tplName}::all_libs INTERFACE ${importedTarget}) endforeach() - # Create Config.cmake file - tribits_extpkg_create_package_config_file_with_imported_targets( + # Create the TriBITS-compliant Config.cmake wrapper file + tribits_extpkgwit_create_package_config_file( ${tplName} INNER_FIND_PACKAGE_NAME ${PARSE_INNER_FIND_PACKAGE_NAME} IMPORTED_TARGETS_FOR_ALL_LIBS ${PARSE_IMPORTED_TARGETS_FOR_ALL_LIBS} ) endfunction() - - -function(tribits_extpkg_create_package_config_file_with_imported_targets - tplName - ) - - # Parse arguments - cmake_parse_arguments( - PARSE_ARGV 1 - PARSE "" "" # prefix, options, one_value_keywords - "INNER_FIND_PACKAGE_NAME;IMPORTED_TARGETS_FOR_ALL_LIBS" #multi_value_keywords - ) - tribits_check_for_unparsed_arguments(PARSE) - tribits_assert_parse_arg_one_value(PARSE INNER_FIND_PACKAGE_NAME) - tribits_assert_parse_arg_one_or_more_values(PARSE IMPORTED_TARGETS_FOR_ALL_LIBS) - set(externalPkg ${PARSE_INNER_FIND_PACKAGE_NAME}) - - # Create Config.cmake file - set(configFileStr "") - string(APPEND configFileStr - "include(CMakeFindDependencyMacro)\n" ) - if (${externalPkg}_DIR) - string(APPEND configFileStr - "set(${externalPkg}_DIR \"${${externalPkg}_DIR}\")\n" ) - endif() - string(APPEND configFileStr - "find_dependency(${externalPkg})\n" - "add_library(${tplName}::all_libs INTERFACE IMPORTED GLOBAL)\n" - ) - foreach (importedTarget IN LISTS PARSE_IMPORTED_TARGETS_FOR_ALL_LIBS) - string(APPEND configFileStr - "target_link_libraries(${tplName}::all_libs INTERFACE ${importedTarget})\n") - endforeach() - set(buildDirExternalPkgsDir - "${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR}") - set(tplConfigFile - "${buildDirExternalPkgsDir}/${tplName}/${tplName}Config.cmake") - file(WRITE "${tplConfigFile}" "${configFileStr}") - -endfunction() -# -# NOTE: Above, ${externalPkg}_DIR is only set when -# find_package(${externalPkg}) finds a package configure file -# ${externalPkg}Config.cmake and **not** when it uses a -# Find${externalPkg}.cmake module. Therefore, there is no reason to set -# ${externalPkg}_DIR in this file if it will not be used. diff --git a/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake b/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake index fd4adb86a9f8..85f37f3df356 100644 --- a/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake +++ b/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake @@ -42,14 +42,22 @@ include_guard() include(TribitsGeneralMacros) include(TribitsPackageDependencies) +include(TribitsWritePackageConfigFileHelpers) include(MessageWrapper) +################################################################################ +# +# User-level functions +# +################################################################################ + + # @FUNCTION: tribits_extpkg_write_config_file() # -# Write out a ``Config.cmake`` file given the list of include -# directories and libraries for an external package/TPL. +# Write out a ``Config.cmake`` file for a TriBITS TPL given the list +# of include directories and libraries for an external package/TPL. # # Usage:: # @@ -67,6 +75,9 @@ include(MessageWrapper) # and writes that text to the file ```` so see that function # for more details. # +# NOTE: This is used for a classic TriBITS TPL that does **not** use +# ``find_package()`` with modern IMPORTED targets. +# function(tribits_extpkg_write_config_file tplName tplConfigFile) tribits_extpkg_write_config_file_str(${tplName} tplConfigFileStr) file(WRITE "${tplConfigFile}" "${tplConfigFileStr}") @@ -164,6 +175,108 @@ function(tribits_extpkg_install_config_version_file tplName endfunction() +################################################################################ +# +# TriBITS Implementation functions +# +################################################################################ + + +# @FUNCTION: tribits_extpkgwit_create_package_config_file() +# +# Create the ``Config.cmake`` file for a TriBITS external package/TPL +# that is defined by a set of IMPORTED targets by call to +# ``find_package()`` +# +# Usage:: +# +# tribits_extpkgwit_create_package_config_file( +# INNER_FIND_PACKAGE_NAME +# IMPORTED_TARGETS_FOR_ALL_LIBS ... ) +# +function(tribits_extpkgwit_create_package_config_file tplName) + # Parse arguments + cmake_parse_arguments( + PARSE_ARGV 1 + PARSE "" "" # prefix, options, one_value_keywords + "INNER_FIND_PACKAGE_NAME;IMPORTED_TARGETS_FOR_ALL_LIBS" #multi_value_keywords + ) + tribits_check_for_unparsed_arguments(PARSE) + tribits_assert_parse_arg_one_value(PARSE INNER_FIND_PACKAGE_NAME) + tribits_assert_parse_arg_one_or_more_values(PARSE IMPORTED_TARGETS_FOR_ALL_LIBS) + set(externalPkg ${PARSE_INNER_FIND_PACKAGE_NAME}) + + # Create header for Config.cmake file + set(configFileStr "") + tribits_extpkgwit_append_package_config_file_header_str( + ${tplName} ${externalPkg} configFileStr) + + # Get ${externalPkg} from where you found it before (see note below) + tribits_extpkgwit_append_find_dependency_external_package_str( + ${tplName} ${externalPkg} configFileStr) + + # Pull in upstream Config.cmake files + tribits_extpkg_append_find_upstream_dependencies_str(${tplName} configFileStr) + + # Add the ${tplName}::all_libs target and link to this ${externalPkg} + # package's native IMPORTED targets + tribits_extpkg_append_create_all_libs_target_str( ${tplName} + LIB_TARGETS_LIST ${PARSE_IMPORTED_TARGETS_FOR_ALL_LIBS} + CONFIG_FILE_STR_INOUT configFileStr ) + + # Also link against upstream package's `::all_libs` targets + tribits_extpkg_append_target_link_libraries_to_upstream_all_libs_targets_str(${tplName} + ${tplName}::all_libs configFileStr) + + tribits_extpkg_append_tribits_compliant_package_config_vars_str(${tplName} + configFileStr) + + tribits_extpkg_write_package_config_file_from_str(${tplName} "${configFileStr}") +endfunction() + + +function(tribits_extpkgwit_append_find_dependency_external_package_str + tplName externalPkg configFileStrVarInOut + ) + set(configFileStr "${${configFileStrVarInOut}}") + if (${externalPkg}_DIR) + string(APPEND configFileStr + "set(${externalPkg}_DIR \"${${externalPkg}_DIR}\")\n" ) + endif() + string(APPEND configFileStr + "find_dependency(${externalPkg})\n\n") + set(${configFileStrVarInOut} "${configFileStr}" PARENT_SCOPE) +endfunction() +# +# NOTE: Above, ${externalPkg}_DIR is only set when +# find_package(${externalPkg}) finds a package configure file +# ${externalPkg}Config.cmake and **not** when it uses a +# Find${externalPkg}.cmake module. Therefore, there is no reason to set +# ${externalPkg}_DIR in this file if it will not be used. + + +function(tribits_extpkgwit_append_package_config_file_header_str + tplName externalPkg configFileStrVarInOut + ) + set(configFileStr "${${configFileStrVarInOut}}") + string(APPEND configFileStr + "# TriBITS-compliant Package config file for external package/TPL '${tplName}'\n" + "# based on non TriBITS-compliant external package '${externalPkg}' that uses\n" + "# modern IMPORTED targets\n" + "#\n" + "# Generated by CMake, do not edit!\n" + "\n" + "# Guard against multiple inclusion\n" + "if (TARGET ${tplName}::all_libs)\n" + " return()\n" + "endif()\n" + "\n" + "include(CMakeFindDependencyMacro)\n\n" + ) + set(${configFileStrVarInOut} "${configFileStr}" PARENT_SCOPE) +endfunction() + + # @FUNCTION: tribits_extpkg_write_config_file_str() # # Create the text string for a ``Config.cmake`` file given the list @@ -242,7 +355,7 @@ endfunction() # regarded as an error. # # For more details on the handling of individual ``TPL__LIBRARIES`` -# arguments, see `tribits_tpl_libraries_entry_type()`_. +# arguments, see `tribits_extpkg_tpl_libraries_entry_type()`_. # # The list of directories given in ``TPL__INCLUDE_DIRS`` is added to # the ``::all_libs`` target using ``target_include_directories()``. @@ -281,8 +394,8 @@ function(tribits_extpkg_write_config_file_str tplName tplConfigFileStrOut) "\n" ) - # B) Call find_dependency() for all direct dependent upstream TPLs - tribits_extpkg_add_find_upstream_dependencies_str(${tplName} + # B) Pull in upstream packages + tribits_extpkg_append_find_upstream_dependencies_str(${tplName} configFileStr) # C) Create IMPORTED library targets from TPL_${tplName}_LIBRARIES @@ -294,94 +407,70 @@ function(tribits_extpkg_write_config_file_str tplName tplConfigFileStrOut) ) # D) Create the ::all_libs target - tribits_extpkg_create_all_libs_target( + tribits_extpkg_append_create_all_libs_target_str( ${tplName} LIB_TARGETS_LIST ${libTargets} LIB_LINK_FLAGS_LIST ${libLinkFlags} CONFIG_FILE_STR_INOUT configFileStr ) - # E) Set the output + # E) Add standard TriBITS-compliant external package vars + tribits_extpkg_append_tribits_compliant_package_config_vars_str(${tplName} configFileStr) + + # F) Set the output set(${tplConfigFileStrOut} "${configFileStr}" PARENT_SCOPE) endfunction() -# @FUNCTION: tribits_extpkg_add_find_upstream_dependencies_str() +# @FUNCTION: tribits_extpkg_append_find_upstream_dependencies_str() # -# Add code to call find_dependency() for all upstream external packages/TPLs -# listed in ``_LIB_ENABLED_DEPENDENCIES``. +# Add includes for all upstream external packages/TPLs listed in +# ``_LIB_ENABLED_DEPENDENCIES``. # # Usage:: # -# tribits_extpkg_add_find_upstream_dependencies_str(tplName +# tribits_extpkg_append_find_upstream_dependencies_str(tplName # configFileFragStrInOut) # -# NOTE: This also requires that ``_DIR`` be set for each +# NOTE: This also requires that +# ``_TRIBITS_COMPLIANT_PACKAGE_CONFIG_FILE`` be set for each # external package/TPL listed in ``_LIB_ENABLED_DEPENDENCIES``. # -function(tribits_extpkg_add_find_upstream_dependencies_str +function(tribits_extpkg_append_find_upstream_dependencies_str tplName configFileFragStrInOut ) if (NOT "${${tplName}_LIB_ENABLED_DEPENDENCIES}" STREQUAL "") set(configFileFragStr "${${configFileFragStrInOut}}") - string(APPEND configFileFragStr - "include(CMakeFindDependencyMacro)\n" - "\n" - "# Don't allow find_dependency() to search anything other than _DIR\n" - "set(${tplName}_SearchNoOtherPathsArgs\n" - " NO_DEFAULT_PATH\n" - " NO_PACKAGE_ROOT_PATH NO_CMAKE_PATH\n" - " NO_CMAKE_ENVIRONMENT_PATH\n" - " NO_SYSTEM_ENVIRONMENT_PATH\n" - " NO_CMAKE_PACKAGE_REGISTRY\n" - " NO_CMAKE_SYSTEM_PATH\n" - " NO_CMAKE_SYSTEM_PACKAGE_REGISTRY\n" - " CMAKE_FIND_ROOT_PATH_BOTH\n" - " ONLY_CMAKE_FIND_ROOT_PATH\n" - " NO_CMAKE_FIND_ROOT_PATH\n" - " )\n" - "\n" - ) foreach (upstreamTplDepEntry IN LISTS ${tplName}_LIB_ENABLED_DEPENDENCIES) tribits_extpkg_get_dep_name_and_vis( "${upstreamTplDepEntry}" upstreamTplDepName upstreamTplDepVis) - if ("${${upstreamTplDepName}_DIR}" STREQUAL "") - message(FATAL_ERROR "ERROR: ${upstreamTplDepName}_DIR is empty!") + if (NOT "${${upstreamTplDepName}_TRIBITS_COMPLIANT_PACKAGE_CONFIG_FILE_DIR}" + STREQUAL "" + ) + set(upstreamTplPackageConfigFileDir + "${${upstreamTplDepName}_TRIBITS_COMPLIANT_PACKAGE_CONFIG_FILE_DIR}") + else() + set(upstreamTplPackageConfigFileDir + "\${CMAKE_CURRENT_LIST_DIR}/../${upstreamTplDepName}") endif() string(APPEND configFileFragStr "if (NOT TARGET ${upstreamTplDepName}::all_libs)\n" - " set(${upstreamTplDepName}_DIR \"\${CMAKE_CURRENT_LIST_DIR}/../${upstreamTplDepName}\")\n" - " find_dependency(${upstreamTplDepName} REQUIRED CONFIG \${${tplName}_SearchNoOtherPathsArgs})\n" - " unset(${upstreamTplDepName}_DIR)\n" + " include(\"${upstreamTplPackageConfigFileDir}/${upstreamTplDepName}Config.cmake\")\n" "endif()\n" "\n" ) endforeach() - string(APPEND configFileFragStr - "unset(${tplName}_SearchNoOtherPathsArgs)\n" - "\n" - ) set(${configFileFragStrInOut} "${configFileFragStr}" PARENT_SCOPE) endif() endfunction() # -# NOTE: Above, to be the most flexible, we have to set -# `_DIR` and then call `find_dependency()` instead of just -# including the file: -# -# include("${_DIR}/Config.cmake") -# -# This is to allow finding and depending on external packages/TPLs that may -# have different names than Config.cmake. The CMake -# command find_package() only returns _DIR, not the full -# path to the config file or even the config file name. It is a little bit -# dangerous to use find_dependency() in case the config fire is not found in -# the directory `_DIR` but I am not sure how else to do -# this. -# -# ToDo: It would be great to make the above find_dependency() call **only ** -# search the directory _DIR and no others. That would make +# NOTE: Above, we include the upstream ${upstreamTplDepName}Config.cmake file +# from either beside the current location (in the build tree or the install +# tree) or we use the location set in +# ${upstreamTplDepName}_TRIBITS_COMPLIANT_PACKAGE_CONFIG_FILE_DIR which would +# have been set by the ${upstreamTplDepName}Config.cmake file itself from an +# upstream install as pulled in from a TriBITS-compliant external package. # @FUNCTION: tribits_extpkg_process_libraries_list() @@ -435,7 +524,7 @@ function(tribits_extpkg_process_libraries_list tplName) set(configFileStr "") set(libTargets "") - set(lastLibProcessed "") + set(previousLibProcessed "") # Iterate through libs in reverse order setting dependencies on the libs # that came before them so CMake will put in right order on the link line. @@ -446,8 +535,7 @@ function(tribits_extpkg_process_libraries_list tplName) list(REVERSE reverseLibraries) foreach (libentry IN LISTS reverseLibraries) - #print_var(libentry) - tribits_tpl_libraries_entry_type(${libentry} libEntryType) + tribits_extpkg_tpl_libraries_entry_type(${libentry} libEntryType) if (libEntryType STREQUAL "UNSUPPORTED_LIB_ENTRY") message_wrapper(SEND_ERROR "ERROR: Can't handle argument '${libentry}' in list TPL_${tplName}_LIBRARIES") @@ -458,7 +546,7 @@ function(tribits_extpkg_process_libraries_list tplName) list(APPEND libLinkFlagsList "${libentry}") else() tribits_extpkg_process_libraries_list_library_entry( - ${tplName} "${libentry}" ${libEntryType} libTargets lastLibProcessed + ${tplName} "${libentry}" ${libEntryType} libTargets previousLibProcessed configFileStr ) endif() endforeach() @@ -474,13 +562,13 @@ function(tribits_extpkg_process_libraries_list tplName) endfunction() -# @FUNCTION: tribits_tpl_libraries_entry_type() +# @FUNCTION: tribits_extpkg_tpl_libraries_entry_type() # # Returns the type of the library entry in the list TPL__LIBRARIES # # Usage:: # -# tribits_tpl_libraries_entry_type( ) +# tribits_extpkg_tpl_libraries_entry_type( ) # # Arguments: # @@ -505,7 +593,7 @@ endfunction() # # * ``UNSUPPORTED_LIB_ENTRY``: An unsupported lib option # -function(tribits_tpl_libraries_entry_type libentry libEntryTypeOut) +function(tribits_extpkg_tpl_libraries_entry_type libentry libEntryTypeOut) string(SUBSTRING "${libentry}" 0 1 firstCharLibEntry) string(SUBSTRING "${libentry}" 0 2 firstTwoCharsLibEntry) if (firstTwoCharsLibEntry STREQUAL "-l") @@ -536,11 +624,11 @@ endfunction() # function(tribits_extpkg_process_libraries_list_library_entry tplName libentry libEntryType - libTargetsInOut lastLibProcessedInOut configFileStrInOut + libTargetsInOut previousLibProcessedInOut configFileStrInOut ) # Set local vars for inout vars set(libTargets ${${libTargetsInOut}}) - set(lastLibProcessed ${${lastLibProcessedInOut}}) + set(previousLibProcessed ${${previousLibProcessedInOut}}) set(configFileStr ${${configFileStrInOut}}) # Get libname tribits_extpkg_get_libname_and_path_from_libentry( @@ -550,24 +638,27 @@ function(tribits_extpkg_process_libraries_list_library_entry if (NOT (prefixed_libname IN_LIST libTargets)) tribits_extpkg_append_add_library_str (${libname} ${prefixed_libname} ${libEntryType} "${libpath}" configFileStr) - if (lastLibProcessed) + if (previousLibProcessed) + # This is not the first lib so we only need to link to the previous lib string(APPEND configFileStr "target_link_libraries(${prefixed_libname}\n" - " INTERFACE tribits::${tplName}::${lastLibProcessed})\n" + " INTERFACE tribits::${tplName}::${previousLibProcessed})\n" ) else() - tribits_extpkg_append_upstream_target_link_libraries_str( ${tplName} + # Only on the first lib do we add dependencies on all of the + # `::all_libs` targets + tribits_extpkg_append_target_link_libraries_to_upstream_all_libs_targets_str( ${tplName} ${prefixed_libname} configFileStr ) endif() string(APPEND configFileStr "\n") # Update for next loop - set(lastLibProcessed ${libname}) + set(previousLibProcessed ${libname}) list(APPEND libTargets ${prefixed_libname}) endif() # Set output vars set(${libTargetsInOut} ${libTargets} PARENT_SCOPE) - set(${lastLibProcessedInOut} ${lastLibProcessed} PARENT_SCOPE) + set(${previousLibProcessedInOut} ${previousLibProcessed} PARENT_SCOPE) set(${configFileStrInOut} ${configFileStr} PARENT_SCOPE) endfunction() # NOTE: Above, we only need to link the first library @@ -641,7 +732,7 @@ function(tribits_extpkg_get_libname_from_full_lib_path full_lib_path set(libname "") string(LENGTH "${full_libname}" full_libname_len) if (full_libname_len LESS 0) - tribits_print_invalid_lib_name(${tplName} "${full_lib_path}") + tribits_extpkg_print_invalid_lib_name(${tplName} "${full_lib_path}") endif() if (WIN32) # Native windows compilers does not prepend library names with 'lib' @@ -657,14 +748,14 @@ function(tribits_extpkg_get_libname_from_full_lib_path full_lib_path if (last_ext STREQUAL ".framework") set(libname "${full_libname}") else() - tribits_print_invalid_lib_name(${tplName} "${full_lib_path}") + tribits_extpkg_print_invalid_lib_name(${tplName} "${full_lib_path}") endif() endif() else() # I.e. Linux # Every other system (i.e. Linux) prepends the library name with 'lib' so # assert for that if (NOT beginsWithLib) - tribits_print_invalid_lib_name(${tplName} "${full_lib_path}") + tribits_extpkg_print_invalid_lib_name(${tplName} "${full_lib_path}") else() string(SUBSTRING "${full_libname}" 3 -1 libname) endif() @@ -693,7 +784,7 @@ function(tribits_extpkg_get_libname_from_lib_name_link_option # Assert begging part '-l' string(SUBSTRING "${lib_name_link_option}" 0 2 firstTwoCharsLibEntry) if ( ) - tribits_print_invalid_lib_link_option(${tplName} "${lib_name_link_option}") + tribits_extpkg_print_invalid_lib_link_option(${tplName} "${lib_name_link_option}") endif() # Get from -l string(SUBSTRING "${lib_name_link_option}" 2 -1 libname) @@ -702,19 +793,26 @@ function(tribits_extpkg_get_libname_from_lib_name_link_option endfunction() -function(tribits_print_invalid_lib_name tplName full_libname) +function(tribits_extpkg_print_invalid_lib_name tplName full_libname) message_wrapper(SEND_ERROR "ERROR: TPL_${tplName}_LIBRARIES entry '${full_libname}' not a valid lib file name!") endfunction() -function(tribits_print_invalid_lib_link_option tplName liblinkoption) +function(tribits_extpkg_print_invalid_lib_link_option tplName liblinkoption) message(SEND_ERROR "ERROR: TPL_${tplName}_LIBRARIES entry '${liblinkoption}' not a valid lib name link option!") endfunction() -function(tribits_extpkg_append_upstream_target_link_libraries_str +# @FUNCTION: tribits_extpkg_append_target_link_libraries_to_upstream_all_libs_targets_str() +# +# Append text calling `target_link_libraries( ... )` against +# the `::all_libs` targets for all of the direct enabled upstream +# dependencies listed in '_LIB_ENABLED_DEPENDENCIES` (taking into +# account `PUBLIC` and `PRIVATE` dependencies). +# +function(tribits_extpkg_append_target_link_libraries_to_upstream_all_libs_targets_str tplName prefix_libname configFileStrInOut ) set(configFileStr "${${configFileStrInOut}}") @@ -750,14 +848,14 @@ endfunction() # libraries being listed on link lines for downstsream library and exec links. -# @FUNCTION: tribits_extpkg_create_all_libs_target() +# @FUNCTION: tribits_extpkg_append_create_all_libs_target_str() # # Creates the ``::all_libs`` target command text using input info and # from ``TPL__INCLUDE_DIRS``. # # Usage:: # -# tribits_extpkg_create_all_libs_target( +# tribits_extpkg_append_create_all_libs_target_str( # # LIB_TARGETS_LIST # LIB_LINK_FLAGS_LIST @@ -777,7 +875,7 @@ endfunction() # ````: [out] A string variable that will be # appended with the ``::all_libs`` target statements. # -function(tribits_extpkg_create_all_libs_target tplName) +function(tribits_extpkg_append_create_all_libs_target_str tplName) # Parse commandline arguments @@ -791,7 +889,7 @@ function(tribits_extpkg_create_all_libs_target tplName) tribits_check_for_unparsed_arguments() # Set short-hand local vars - set(libTarget "${PARSE_LIB_TARGETS_LIST}") + set(libTargets "${PARSE_LIB_TARGETS_LIST}") set(libLinkFlags "${PARSE_LIB_LINK_FLAGS_LIST}") # Capture the initial input string in case the name of the var @@ -845,4 +943,3 @@ function(tribits_extpkg_create_all_libs_target tplName) PARENT_SCOPE) endfunction() - diff --git a/cmake/tribits/core/package_arch/TribitsGetPackageEnableStatus.cmake b/cmake/tribits/core/package_arch/TribitsGetPackageEnableStatus.cmake index 3fac736a78cc..3d7c425d7117 100644 --- a/cmake/tribits/core/package_arch/TribitsGetPackageEnableStatus.cmake +++ b/cmake/tribits/core/package_arch/TribitsGetPackageEnableStatus.cmake @@ -69,24 +69,19 @@ function(tribits_get_package_enable_status packageName packageEnableOut tribits_assert_package_enable_status(${packageName}) # Determine which variable, if any, to extract enable status from set(packageEnableVarName "") - if (${packageName}_PACKAGE_BUILD_STATUS STREQUAL "INTERNAL") + if (NOT "${${PROJECT_NAME}_ENABLE_${packageName}}" STREQUAL "") + set(packageEnableVarName ${PROJECT_NAME}_ENABLE_${packageName}) + elseif (NOT "${TPL_ENABLE_${packageName}}" STREQUAL "") + set(packageEnableVarName TPL_ENABLE_${packageName}) + elseif (${packageName}_PACKAGE_BUILD_STATUS STREQUAL "INTERNAL") set(packageEnableVarName ${PROJECT_NAME}_ENABLE_${packageName}) elseif (${packageName}_PACKAGE_BUILD_STATUS STREQUAL "EXTERNAL") - if (NOT "${TPL_ENABLE_${packageName}}" STREQUAL "") - set(packageEnableVarName TPL_ENABLE_${packageName}) - elseif (NOT "${${PROJECT_NAME}_ENABLE_${packageName}}" STREQUAL "") - set(packageEnableVarName ${PROJECT_NAME}_ENABLE_${packageName}) - else() - # If neither is set, select the default var TPL name - set(packageEnableVarName TPL_ENABLE_${packageName}) - endif() - endif() - if (packageEnableVarName) - set(packageEnable ${${packageEnableVarName}}) + set(packageEnableVarName TPL_ENABLE_${packageName}) else() - set(packageEnable "") + message(FATAL_ERROR "Could not determine status of package ${packageName}") endif() - # Set output args + # Extract the enable status, set output args + set(packageEnable ${${packageEnableVarName}}) if (packageEnableOut) set(${packageEnableOut} ${packageEnable} PARENT_SCOPE) endif() diff --git a/cmake/tribits/core/package_arch/TribitsGetEnabledSublists.cmake b/cmake/tribits/core/package_arch/TribitsGetPackageSublists.cmake similarity index 56% rename from cmake/tribits/core/package_arch/TribitsGetEnabledSublists.cmake rename to cmake/tribits/core/package_arch/TribitsGetPackageSublists.cmake index 0444ba3dde25..ddc392e531d9 100644 --- a/cmake/tribits/core/package_arch/TribitsGetEnabledSublists.cmake +++ b/cmake/tribits/core/package_arch/TribitsGetPackageSublists.cmake @@ -40,6 +40,55 @@ include(TribitsGetPackageEnableStatus) +# @FUNCTION: tribits_filter_package_list_from_var() +# +# Filter a list of packages based on several criteria including +# internal/external, enable status (with empty or non-empty) +# +# Usage:: +# +# tribits_filter_package_list_from_var( +# +# ) +# +# Where: +# +# * ````: Name of input list var of packages +# * ````: ``INTERNAL``, ``EXTERNAL`` or "" (i.e. both +# INTERNAL and EXTERNAL packages) (matches +# ``_PACKAGE_BUILD_STATUS``) +# * ````: ``ON`` for elements that match ``TRUE`` , ``OFF`` +# for elements that match ``FALSE`` +# * ````: Enable status is ``NONEMPTY`` (i.e. must have a +# value) or ``INCLUDE_EMPTY`` (matches those with a value and with empty +# ""). +# * ````: The name of the var that will store the filtered +# sublist of packages. +# +function(tribits_filter_package_list_from_var packageListVarName + internalOrExternal enabledFlag enableEmptyStatus packageSublistOut + ) + tribits_assert_include_empty_param(${enableEmptyStatus}) + tribits_get_sublist_internal_external(${packageListVarName} "${internalOrExternal}" + packageListTmp "") + if (enabledFlag AND (enableEmptyStatus STREQUAL "NONEMPTY")) + tribits_get_sublist_enabled(packageListTmp + packageSublist "") + elseif (enabledFlag AND (enableEmptyStatus STREQUAL "INCLUDE_EMPTY")) + tribits_get_sublist_nondisabled(${packageListTmp} packageSublist "") + elseif (NOT enabledFlag AND (enableEmptyStatus STREQUAL "NONEMPTY")) + tribits_get_sublist_disabled(packageListTmp + packageSublist "") + elseif (NOT enabledFlag AND (enableEmptyStatus STREQUAL "INCLUDE_EMPTY")) + tribits_get_sublist_nonenabled(packageListTmp + packageSublist "") + else() + message(FATAL_ERROR "Should never get here!") + endif() + set(${packageSublistOut} ${packageSublist} PARENT_SCOPE) +endfunction() + + # @FUNCTION: tribits_get_sublist_enabled() # # Get sub-list of enabled packages @@ -47,13 +96,13 @@ include(TribitsGetPackageEnableStatus) # Usage:: # # tribits_get_sublist_enabled( -# ) +# [] ) # # On output, ```` contains the sublist of entries in # ```` which evaluate to ``TRUE`` in an ``if ()`` statement. # function(tribits_get_sublist_enabled enableListName - enabledSublistNameOut numEnabledVarOut + enabledSublistNameOut numEnabledVarOut ) set(enabledSublist) foreach(pkgName IN LISTS ${enableListName}) @@ -77,7 +126,7 @@ endfunction() # Usage:: # # tribits_get_sublist_nondisabled( -# ) +# [] ) # # On output, ```` contains the sublist of entries from # ```` for which evaluate to ``TRUE`` or empty ``""`` in an @@ -108,7 +157,7 @@ endfunction() # Usage:: # # tribits_get_sublist_disabled( -# ) +# [] ) # # On output, ```` contains the sublist of entries # ```` which evaluate to ``FALSE`` and is not empty ``""`` in @@ -139,7 +188,7 @@ endfunction() # Usage:: # # tribits_get_sublist_nonenabled( -# ) +# [] ) # # On output, ```` contains the subset of entries in # ```` that evaluate to ``FALSE`` (which can also be empty @@ -161,3 +210,63 @@ function(tribits_get_sublist_nonenabled enableListName set(${numNonenabledVarOut} ${numNonenabled} PARENT_SCOPE) endif() endfunction() + + +# @FUNCTION: tribits_get_sublist_internal_external() +# +# Get sub-list of packages that are INTERNAL, EXTERNAL, or either. +# +# Usage:: +# +# tribits_get_sublist_internal_external( +# [] ) +# +# where: +# +# * `` is either `INTERNAL`, `EXTERNAL` or empty "". +# +# On output, ```` contains the sublist of entries in +# ```` which are either `INTERNAL` or `EXTERNAL` or both +# (if `` is "") based on `_PACKAGE_BUILD_STATUS` +# for each element package name. +# +function(tribits_get_sublist_internal_external inputPackageListName internalOrExternal + sublistNameOut sizeSublistOut + ) + tribits_assert_internal_or_external_arg("${internalOrExternal}") + if (NOT internalOrExternal STREQUAL "") + set(sublist "") + foreach(pkgName IN LISTS ${inputPackageListName}) + if (${pkgName}_PACKAGE_BUILD_STATUS STREQUAL internalOrExternal) + list(APPEND sublist ${pkgName}) + endif() + endforeach() + else() + set(sublist ${${inputPackageListName}}) + endif() + set(${sublistNameOut} ${sublist} PARENT_SCOPE) + if (numEnabledVarOut) + list(LENGTH sublist sizeSublist) + set(${sizeSublistOut} ${sizeSublist} PARENT_SCOPE) + endif() +endfunction() + + +function(tribits_assert_internal_or_external_arg internalOrExternal) + set(allowedValuesList "INTERNAL" "EXTERNAL" "") + if (NOT internalOrExternal IN_LIST allowedValuesList) + message(FATAL_ERROR "ERROR, the argument internalOrExternal=" + "'${internalOrExternal}' is not in the list of allowed values" + ${allowedValuesList} ) + endif() +endfunction() + + +function(tribits_assert_include_empty_param enableEmptyStatus) + if ((NOT enableEmptyStatus STREQUAL "NONEMPTY") AND + (NOT enableEmptyStatus STREQUAL "INCLUDE_EMPTY") + ) + message(FATAL_ERROR "Error, argument enableEmptyStatus='${enableEmptyStatus}'" + " is invalid! Use 'NONEMPTY' or 'INCLUDE_EMPTY'.") + endif() +endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake b/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake index 63e0930da23a..3ebfa7d9b75e 100644 --- a/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake @@ -44,7 +44,7 @@ include(TribitsTestCategories) include(TribitsGeneralMacros) include(TribitsAddTestHelpers) include(TribitsVerbosePrintVar) -include(TribitsProcessEnabledTpl) +include(TribitsProcessEnabledTpls) include(TribitsInstallHeaders) include(TribitsGetVersionDate) include(TribitsReportInvalidTribitsUsage) @@ -597,13 +597,21 @@ macro(tribits_define_global_options_and_define_extra_repos) if ("${${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES_DEFAULT}" STREQUAL "") set(${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES_DEFAULT OFF) endif() - advanced_set(${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES ${${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES_DEFAULT} CACHE BOOL "Determines if ${PROJECT_NAME}Config.cmake and Config.cmake files are created or not." ) + if ("${${PROJECT_NAME}_SKIP_INSTALL_PROJECT_CMAKE_CONFIG_FILES_DEFAULT}" STREQUAL "") + set(${PROJECT_NAME}_SKIP_INSTALL_PROJECT_CMAKE_CONFIG_FILES_DEFAULT OFF) + endif() + advanced_set(${PROJECT_NAME}_SKIP_INSTALL_PROJECT_CMAKE_CONFIG_FILES + ${${PROJECT_NAME}_SKIP_INSTALL_PROJECT_CMAKE_CONFIG_FILES_DEFAULT} + CACHE BOOL + "Skip installing the file ${PROJECT_NAME}Config.cmake." + ) + if (NOT ${PROJECT_NAME}_GENERATE_EXPORT_FILE_DEPENDENCIES_DEFAULT) # We need to generate the dependency logic for export dependency files if # asked. @@ -1453,52 +1461,27 @@ macro(tribits_handle_project_extra_link_flags_as_a_tpl) set(${lastLibTplName}_FINDMOD "${${PROJECT_NAME}_TRIBITS_DIR}/common_tpls/FindTPLProjectLastLib.cmake") - # Tack on ${PROJECT_NAME}TribitsLastLib as a dependency to all enabled - # external packages/TPLs - foreach(TPL_NAME ${${PROJECT_NAME}_DEFINED_TPLS}) - list(APPEND ${TPL_NAME}_LIB_DEFINED_DEPENDENCIES ${lastLibTplName}) - if (TPL_ENABLE_${TPL_NAME}) - list(APPEND ${TPL_NAME}_LIB_ENABLED_DEPENDENCIES ${lastLibTplName}) + # Tack on ${PROJECT_NAME}TribitsLastLib as a dependency to all packages + foreach(packageName ${${PROJECT_NAME}_DEFINED_PACKAGES}) + tribits_get_package_enable_status(${packageName} packageEnable "") + list(APPEND ${packageName}_LIB_DEFINED_DEPENDENCIES ${lastLibTplName}) + if (packageEnable) + list(APPEND ${packageName}_LIB_ENABLED_DEPENDENCIES ${lastLibTplName}) endif() endforeach() - # Prepend ${PROJECT_NAME}TribitsLastLib to the list of external packages/TPLs + # Prepend ${PROJECT_NAME}TribitsLastLib to the list of packages list(PREPEND ${PROJECT_NAME}_DEFINED_TPLS ${lastLibTplName}) + list(PREPEND ${PROJECT_NAME}_DEFINED_TOPLEVEL_PACKAGES ${lastLibTplName}) + list(PREPEND ${PROJECT_NAME}_DEFINED_PACKAGES ${lastLibTplName}) set(TPL_ENABLE_${lastLibTplName} ON) set(${lastLibTplName}_PACKAGE_BUILD_STATUS EXTERNAL) - # Tack on ${PROJECT_NAME}TribitsLastLib as a dependency to all enabled - # internal packages - foreach(PACKAGE_NAME ${${PROJECT_NAME}_DEFINED_INTERNAL_TOPLEVEL_PACKAGES}) - list(APPEND ${PACKAGE_NAME}_LIB_DEFINED_DEPENDENCIES ${lastLibTplName}) - if (${PROJECT_NAME}_ENABLE_${PACKAGE_NAME}) - list(APPEND ${PACKAGE_NAME}_LIB_ENABLED_DEPENDENCIES ${lastLibTplName}) - endif() - endforeach() - endif() endmacro() -# Gather information from enabled TPLs -# -macro(tribits_process_enabled_tpls) - - tribits_config_code_start_timer(CONFIGURE_TPLS_TIME_START_SECONDS) - - foreach(TPL_NAME ${${PROJECT_NAME}_DEFINED_TPLS}) - if (TPL_ENABLE_${TPL_NAME}) - tribits_process_enabled_tpl(${TPL_NAME}) - endif() - endforeach() - - tribits_config_code_stop_timer(CONFIGURE_TPLS_TIME_START_SECONDS - "\nTotal time to configure enabled external packages/TPLs") - -endmacro() - - # # Macros for setting up the standard environment # @@ -2102,7 +2085,10 @@ macro(tribits_configure_enabled_packages) # other even downstream packages (which is pretty messed up really). # - foreach(TRIBITS_PACKAGE ${${PROJECT_NAME}_DEFINED_INTERNAL_TOPLEVEL_PACKAGES}) + tribits_filter_package_list_from_var(${PROJECT_NAME}_DEFINED_TOPLEVEL_PACKAGES + INTERNAL ON NONEMPTY ${PROJECT_NAME}_enabledInternalTopLevelPackages) + + foreach(TRIBITS_PACKAGE IN LISTS ${PROJECT_NAME}_enabledInternalTopLevelPackages) # Get all the package sources independent of whether they are enabled or not. # There are some messed up packages that grab parts out of unrelated @@ -2153,7 +2139,7 @@ macro(tribits_configure_enabled_packages) # Tell packages that are also repos they are being processed as a package. set(TRIBITS_PROCESSING_PACKAGE TRUE) - foreach(TRIBITS_PACKAGE ${${PROJECT_NAME}_DEFINED_INTERNAL_TOPLEVEL_PACKAGES}) + foreach(TRIBITS_PACKAGE IN LISTS ${PROJECT_NAME}_enabledInternalTopLevelPackages) tribits_determine_if_process_package(${TRIBITS_PACKAGE} PROCESS_PACKAGE PACKAGE_ENABLE_STR) diff --git a/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake b/cmake/tribits/core/package_arch/TribitsInternalPackageWriteConfigFile.cmake similarity index 67% rename from cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake rename to cmake/tribits/core/package_arch/TribitsInternalPackageWriteConfigFile.cmake index 7ef8f2666bd4..914825ffad41 100644 --- a/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake +++ b/cmake/tribits/core/package_arch/TribitsInternalPackageWriteConfigFile.cmake @@ -37,177 +37,115 @@ # ************************************************************************ # @HEADER + +################################################################################ +# +# Module TribitsInternalPackageWriteConfigFile.cmake +# +# This module contains code for generating Config.cmake files for +# internal TriBITS packages. +# +################################################################################ + + include(TribitsGeneralMacros) include(TribitsPkgExportCacheVars) +include(TribitsWritePackageConfigFileHelpers) -### -### WARNING: See "NOTES TO DEVELOPERS" at the bottom of the file -### TribitsPackageMacros.cmake! -### -# This function will take a list and turn it into a space separated string -# adding the prefix to the front of every entry. +# Generate the ${PACKAGE_NAME}Config.cmake file for package PACKAGE_NAME. # -function(tribits_list_to_string LIST PREFIX OUTPUT_STRING) - set(LIST_STRING "") +# ToDo: Finish documentation! +# +function(tribits_write_package_client_export_files PACKAGE_NAME) - foreach(ITEM ${LIST}) - set(LIST_STRING "${LIST_STRING} ${PREFIX}${ITEM}") - endforeach() + if(${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("\nTRIBITS_WRITE_PACKAGE_CLIENT_EXPORT_FILES: ${PACKAGE_NAME}") + endif() - set(${OUTPUT_STRING} ${LIST_STRING} PARENT_SCOPE) -endfunction() + set(buildDirCMakePkgsDir + "${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_CMAKE_PKGS_DIR}") -# This function will take a list of libraries and turn it into a space -# separated string. In this case though the prefix is not always added -# to the front of each entry as libraries can be specified either as a -# name of a library to find or the absolute path to the library file -# with any decorations the system uses. When an absolute path is given -# the entry is used verbatim. -# -function(tribits_library_list_to_string LIST PREFIX OUTPUT_STRING) - set(LIST_STRING "") + set(EXPORT_FILES_ARGS PACKAGE_NAME ${PACKAGE_NAME}) - foreach(ITEM ${LIST}) - string(SUBSTRING ${ITEM} 0 1 OPTION_FLAG) - if(EXISTS ${ITEM} OR OPTION_FLAG STREQUAL "-") - set(LIST_STRING "${LIST_STRING} ${ITEM}") - else() - set(LIST_STRING "${LIST_STRING} ${PREFIX}${ITEM}") + if (${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES) + if(${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("For package ${PACKAGE_NAME} creating ${PACKAGE_NAME}Config.cmake") endif() - endforeach() + set(PACKAGE_CONFIG_FOR_BUILD_BASE_DIR + "${buildDirCMakePkgsDir}/${PACKAGE_NAME}" ) + set(PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR + "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles" ) + append_set(EXPORT_FILES_ARGS + PACKAGE_CONFIG_FOR_BUILD_BASE_DIR "${PACKAGE_CONFIG_FOR_BUILD_BASE_DIR}" + PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR "${PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR}" + ) + endif() + + tribits_write_flexible_package_client_export_files(${EXPORT_FILES_ARGS}) + + tribits_write_package_client_export_files_install_targets(${EXPORT_FILES_ARGS}) - set(${OUTPUT_STRING} ${LIST_STRING} PARENT_SCOPE) endfunction() -# @FUNCTION: tribits_write_flexible_package_client_export_files() +# @FUNCTION: tribits_write_package_client_export_files_install_targets() # -# Utility function for writing ``${PACKAGE_NAME}Config.cmake`` files for -# package ``${PACKAGE_NAME}`` with some greater flexibility than what is -# provided by the function ``tribits_write_package_client_export_files()`` and -# to allow unit testing the generation of these files.. +# Create the ``ConfigTargets.cmake`` file and install rules and the +# install() target for the previously generated +# ``Config_install.cmake`` files generated by the +# `tribits_write_flexible_package_client_export_files()`_ function. # # Usage:: # -# tribits_write_flexible_package_client_export_files( +# tribits_write_package_client_export_files_install_targets( # PACKAGE_NAME -# [EXPORT_FILE_VAR_PREFIX ] -# [PACKAGE_CONFIG_FOR_BUILD_BASE_DIR ] -# [PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR ] +# PACKAGE_CONFIG_FOR_BUILD_BASE_DIR +# PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR # ) # -# The arguments are: -# -# ``PACKAGE_NAME `` -# -# Gives the name of the TriBITS package for which the export files should -# be created. -# -# ``EXPORT_FILE_VAR_PREFIX `` -# -# If specified, then all of the variables in the generated export files -# will be prefixed with ``_`` instead of -# ``_``. -# -# ``PACKAGE_CONFIG_FOR_BUILD_BASE_DIR `` -# -# If specified, then the package's ``Config.cmake`` file and -# supporting files will be written under the directory -# ``/`` (and any subdirs that does exist -# will be created). The generated file ``Config.cmake`` is -# for usage of the package in the build tree (not the install tree) and -# points to include directories and libraries in the build tree. -# -# ``PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR `` -# -# If specified, then the package's ``Config_install.cmake`` -# file and supporting files will be written under the directory -# ``/`` (and any subdirs that does exist -# will be created). The file ``${PACKAGE_NAME}Config_install.cmake`` is -# meant to be installed renamed as ``Config.cmake`` in the -# install tree and it points to installed include directories and -# libraries. -# -# NOTE: This function does *not* contain any ``install()`` command itself -# because CMake will not allow those to even be present in scripting mode that -# is used for unit testing this function. Instead, the commands to install -# the files are added by the function -# ``tribits_write_package_client_export_files_install_targets()``. +# The install() commands must be in a different subroutine or CMake will not +# allow you to call the routine, even if you if() it out! # -function(tribits_write_flexible_package_client_export_files) - - if (TRIBITS_WRITE_FLEXIBLE_PACKAGE_CLIENT_EXPORT_FILES_DEBUG_DUMP) - message("\ntribits_write_flexible_package_client_export_files(${ARGN})") - endif() - - # - # A) Process the command-line arguments - # +function(tribits_write_package_client_export_files_install_targets) cmake_parse_arguments( #prefix PARSE #options - "WRITE_INSTALL_CMAKE_CONFIG_FILE" + "" #one_value_keywords - "PACKAGE_NAME;EXPORT_FILE_VAR_PREFIX;PACKAGE_CONFIG_FOR_BUILD_BASE_DIR;PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR" + "PACKAGE_NAME;PACKAGE_CONFIG_FOR_BUILD_BASE_DIR;PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR" #multi_value_keywords "" ${ARGN} ) - tribits_check_for_unparsed_arguments() - - if (NOT ${PROJECT_NAME}_GENERATE_EXPORT_FILE_DEPENDENCIES) - message(SEND_ERROR "Error: Can't generate export dependency files because" - " ${PROJECT_NAME}_GENERATE_EXPORT_FILE_DEPENDENCIES is not ON!") - return() - endif() - set(PACKAGE_NAME ${PARSE_PACKAGE_NAME}) - if (TRIBITS_WRITE_FLEXIBLE_PACKAGE_CLIENT_EXPORT_FILES_DEBUG_DUMP) - print_var(PACKAGE_NAME) - endif() - set(EXPORT_FILE_VAR_PREFIX ${PACKAGE_NAME}) - if (PARSE_EXPORT_FILE_VAR_PREFIX) - set(EXPORT_FILE_VAR_PREFIX ${PARSE_EXPORT_FILE_VAR_PREFIX}) - endif() - if (TRIBITS_WRITE_FLEXIBLE_PACKAGE_CLIENT_EXPORT_FILES_DEBUG_DUMP) - print_var(EXPORT_FILE_VAR_PREFIX) + if (PARSE_PACKAGE_CONFIG_FOR_BUILD_BASE_DIR) + tribits_get_package_config_build_dir_targets_file(${PACKAGE_NAME} + "${PARSE_PACKAGE_CONFIG_FOR_BUILD_BASE_DIR}" packageConfigBuildDirTargetsFile ) + export( + EXPORT ${PACKAGE_NAME} + NAMESPACE ${PACKAGE_NAME}:: + FILE "${packageConfigBuildDirTargetsFile}" ) endif() - # Generate a note discouraging editing of the Config.cmake file - set(DISCOURAGE_EDITING "Do not edit: This file was generated automatically by CMake.") - - # - # B) Deal with the library rpath issues with shared libs - # - - # Write the specification of the rpath if necessary. This is only needed if - # we're building shared libraries. - - if(BUILD_SHARED_LIBS) - string(REPLACE ";" ":" SHARED_LIB_RPATH_COMMAND "${FULL_LIBRARY_DIRS_SET}") - set(SHARED_LIB_RPATH_COMMAND - ${CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG}${SHARED_LIB_RPATH_COMMAND}) + if (PARSE_PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR) + install( + FILES + "${PARSE_PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR}/${PACKAGE_NAME}Config_install.cmake" + DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}/cmake/${PACKAGE_NAME}" + RENAME ${PACKAGE_NAME}Config.cmake + ) + install( + EXPORT ${PACKAGE_NAME} + NAMESPACE ${PACKAGE_NAME}:: + DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}/cmake/${PACKAGE_NAME}" + FILE "${PACKAGE_NAME}Targets.cmake" ) endif() - # - # C) Create the contents of the Config.cmake file for the build tree - # - - tribits_generate_package_config_file_for_build_tree(${PACKAGE_NAME} - EXPORT_FILE_VAR_PREFIX ${EXPORT_FILE_VAR_PREFIX}) - - # - # D) Create Config_install.cmake file for the install tree - # - - tribits_generate_package_config_file_for_install_tree(${PACKAGE_NAME} - EXPORT_FILE_VAR_PREFIX ${EXPORT_FILE_VAR_PREFIX}) - endfunction() @@ -260,7 +198,7 @@ function(tribits_generate_package_config_file_for_build_tree packageName) # below) set(PACKAGE_CONFIG_CODE "") - tribits_append_dependent_package_config_file_includes_and_enables(${packageName} + tribits_append_dependent_package_config_file_includes_and_enables_str(${packageName} EXPORT_FILE_VAR_PREFIX ${EXPORT_FILE_VAR_PREFIX} EXT_PKG_CONFIG_FILE_BASE_DIR "${buildDirExtPkgsDir}" PKG_CONFIG_FILE_BASE_DIR "${buildDirCMakePkgsDir}" @@ -280,9 +218,12 @@ function(tribits_generate_package_config_file_for_build_tree packageName) "${PACKAGE_CONFIG_FOR_BUILD_BASE_DIR}" packageConfigBuildDirTargetsFile ) string(APPEND PACKAGE_CONFIG_CODE "\n# Import ${packageName} targets\n" - "include(\"${packageConfigBuildDirTargetsFile}\")") + "include(\"${packageConfigBuildDirTargetsFile}\")\n") endif() + tribits_extpkg_append_tribits_compliant_package_config_vars_str(${packageName} + PACKAGE_CONFIG_CODE) + tribits_set_compiler_vars_for_config_file(BUILD_DIR) if ("${CMAKE_CXX_FLAGS}" STREQUAL "") @@ -348,30 +289,10 @@ function(tribits_generate_package_config_file_for_install_tree packageName) set(EXPORT_FILE_VAR_PREFIX ${packageName}) endif() - # Set the include and library directories relative to the location - # at which the ${PROJECT_NAME}Config.cmake file is going to be - # installed. Note the variable reference below is escaped so it - # won't be replaced until a client project attempts to locate - # directories using the installed config file. This is to deal with - # installers that allow relocation of the install tree at *install* - # time. - # The export files are typically installed in - # //cmake//. - # The relative path to the installation dir is hence k*(../) + ../../, where - # k is the number of components in . Extract those here. - # This doesn't work if ${${PROJECT_NAME}_INSTALL_LIB_DIR} contains "./" or - # "../" components, but really, it never did. All of this should actually be - # handled by CMake's configure_package_config_file(). - string(REPLACE "/" ";" PATH_LIST ${${PROJECT_NAME}_INSTALL_LIB_DIR}) - set(RELATIVE_PATH "../..") - foreach(PATH ${PATH_LIST}) - set(RELATIVE_PATH "${RELATIVE_PATH}/..") - endforeach() - # Custom code in configuration file. set(PACKAGE_CONFIG_CODE "") - tribits_append_dependent_package_config_file_includes_and_enables(${packageName} + tribits_append_dependent_package_config_file_includes_and_enables_str(${packageName} EXPORT_FILE_VAR_PREFIX ${EXPORT_FILE_VAR_PREFIX} EXT_PKG_CONFIG_FILE_BASE_DIR "\${CMAKE_CURRENT_LIST_DIR}/../../${${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR}" @@ -381,7 +302,10 @@ function(tribits_generate_package_config_file_for_install_tree packageName) # Import install targets string(APPEND PACKAGE_CONFIG_CODE "\n# Import ${packageName} targets\n" - "include(\"\${CMAKE_CURRENT_LIST_DIR}/${packageName}Targets.cmake\")") + "include(\"\${CMAKE_CURRENT_LIST_DIR}/${packageName}Targets.cmake\")\n") + + tribits_extpkg_append_tribits_compliant_package_config_vars_str(${packageName} + PACKAGE_CONFIG_CODE) # Write the specification of the rpath if necessary. This is only needed if # we're building shared libraries. @@ -407,7 +331,137 @@ function(tribits_generate_package_config_file_for_install_tree packageName) endfunction() -# @FUNCTION: tribits_append_dependent_package_config_file_includes_and_enables() +# @FUNCTION: tribits_write_flexible_package_client_export_files() +# +# Utility function for writing ``${PACKAGE_NAME}Config.cmake`` files for +# package ``${PACKAGE_NAME}`` with some greater flexibility than what is +# provided by the function ``tribits_write_package_client_export_files()`` and +# to allow unit testing the generation of these files.. +# +# Usage:: +# +# tribits_write_flexible_package_client_export_files( +# PACKAGE_NAME +# [EXPORT_FILE_VAR_PREFIX ] +# [PACKAGE_CONFIG_FOR_BUILD_BASE_DIR ] +# [PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR ] +# ) +# +# The arguments are: +# +# ``PACKAGE_NAME `` +# +# Gives the name of the TriBITS package for which the export files should +# be created. +# +# ``EXPORT_FILE_VAR_PREFIX `` +# +# If specified, then all of the variables in the generated export files +# will be prefixed with ``_`` instead of +# ``_``. +# +# ``PACKAGE_CONFIG_FOR_BUILD_BASE_DIR `` +# +# If specified, then the package's ``Config.cmake`` file and +# supporting files will be written under the directory +# ``/`` (and any subdirs that does exist +# will be created). The generated file ``Config.cmake`` is +# for usage of the package in the build tree (not the install tree) and +# points to include directories and libraries in the build tree. +# +# ``PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR `` +# +# If specified, then the package's ``Config_install.cmake`` +# file and supporting files will be written under the directory +# ``/`` (and any subdirs that does exist +# will be created). The file ``${PACKAGE_NAME}Config_install.cmake`` is +# meant to be installed renamed as ``Config.cmake`` in the +# install tree and it points to installed include directories and +# libraries. +# +# NOTE: This function does *not* contain any ``install()`` command itself +# because CMake will not allow those to even be present in scripting mode that +# is used for unit testing this function. Instead, the commands to install +# the files are added by the function +# ``tribits_write_package_client_export_files_install_targets()``. +# +function(tribits_write_flexible_package_client_export_files) + + if (TRIBITS_WRITE_FLEXIBLE_PACKAGE_CLIENT_EXPORT_FILES_DEBUG_DUMP) + message("\ntribits_write_flexible_package_client_export_files(${ARGN})") + endif() + + # + # A) Process the command-line arguments + # + + cmake_parse_arguments( + #prefix + PARSE + #options + "WRITE_INSTALL_CMAKE_CONFIG_FILE" + #one_value_keywords + "PACKAGE_NAME;EXPORT_FILE_VAR_PREFIX;PACKAGE_CONFIG_FOR_BUILD_BASE_DIR;PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR" + #multi_value_keywords + "" + ${ARGN} + ) + + tribits_check_for_unparsed_arguments() + + if (NOT ${PROJECT_NAME}_GENERATE_EXPORT_FILE_DEPENDENCIES) + message(SEND_ERROR "Error: Can't generate export dependency files because" + " ${PROJECT_NAME}_GENERATE_EXPORT_FILE_DEPENDENCIES is not ON!") + return() + endif() + + set(PACKAGE_NAME ${PARSE_PACKAGE_NAME}) + if (TRIBITS_WRITE_FLEXIBLE_PACKAGE_CLIENT_EXPORT_FILES_DEBUG_DUMP) + print_var(PACKAGE_NAME) + endif() + + set(EXPORT_FILE_VAR_PREFIX ${PACKAGE_NAME}) + if (PARSE_EXPORT_FILE_VAR_PREFIX) + set(EXPORT_FILE_VAR_PREFIX ${PARSE_EXPORT_FILE_VAR_PREFIX}) + endif() + if (TRIBITS_WRITE_FLEXIBLE_PACKAGE_CLIENT_EXPORT_FILES_DEBUG_DUMP) + print_var(EXPORT_FILE_VAR_PREFIX) + endif() + + # Generate a note discouraging editing of the Config.cmake file + set(DISCOURAGE_EDITING "Do not edit: This file was generated automatically by CMake.") + + # + # B) Deal with the library rpath issues with shared libs + # + + # Write the specification of the rpath if necessary. This is only needed if + # we're building shared libraries. + + if(BUILD_SHARED_LIBS) + string(REPLACE ";" ":" SHARED_LIB_RPATH_COMMAND "${FULL_LIBRARY_DIRS_SET}") + set(SHARED_LIB_RPATH_COMMAND + ${CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG}${SHARED_LIB_RPATH_COMMAND}) + endif() + + # + # C) Create the contents of the Config.cmake file for the build tree + # + + tribits_generate_package_config_file_for_build_tree(${PACKAGE_NAME} + EXPORT_FILE_VAR_PREFIX ${EXPORT_FILE_VAR_PREFIX}) + + # + # D) Create Config_install.cmake file for the install tree + # + + tribits_generate_package_config_file_for_install_tree(${PACKAGE_NAME} + EXPORT_FILE_VAR_PREFIX ${EXPORT_FILE_VAR_PREFIX}) + +endfunction() + + +# @FUNCTION: tribits_append_dependent_package_config_file_includes_and_enables_str() # # Append the includes for upstream external packages (TPLs) and internal # packages as well as the enables/disables for upstream dependencies to an @@ -415,7 +469,7 @@ endfunction() # # Usage:: # -# tribits_append_dependent_package_config_file_includes_and_enables( +# tribits_append_dependent_package_config_file_includes_and_enables_str( # # EXPORT_FILE_VAR_PREFIX # EXT_PKG_CONFIG_FILE_BASE_DIR @@ -423,10 +477,10 @@ endfunction() # CONFIG_FILE_STR_INOUT # ) # -function(tribits_append_dependent_package_config_file_includes_and_enables packageName) +function(tribits_append_dependent_package_config_file_includes_and_enables_str packageName) if (TRIBITS_WRITE_FLEXIBLE_PACKAGE_CLIENT_EXPORT_FILES_DEBUG_DUMP) - message("tribits_append_dependent_package_config_file_includes_and_enables(${ARGV})") + message("tribits_append_dependent_package_config_file_includes_and_enables_str(${ARGV})") endif() # Parse input @@ -474,11 +528,17 @@ function(tribits_append_dependent_package_config_file_includes_and_enables packa foreach(depPkg IN LISTS ${packageName}_LIB_ENABLED_DEPENDENCIES) set(packageConfigBaseDir "") # Initially, no add include() if (${depPkg}_PACKAGE_BUILD_STATUS STREQUAL "INTERNAL") - set(packageConfigBaseDir "${pkgConfigFileBaseDir}/${depPkg}") + set(packageConfigBaseDir "\${CMAKE_CURRENT_LIST_DIR}/../${depPkg}") elseif (${depPkg}_PACKAGE_BUILD_STATUS STREQUAL "EXTERNAL") - set(packageConfigBaseDir "${extPkgConfigFileBaseDir}/${depPkg}") + if (NOT "${${depPkg}_TRIBITS_COMPLIANT_PACKAGE_CONFIG_FILE_DIR}" STREQUAL "") + set(packageConfigBaseDir "${${depPkg}_TRIBITS_COMPLIANT_PACKAGE_CONFIG_FILE_DIR}") + else() + set(packageConfigBaseDir + "\${CMAKE_CURRENT_LIST_DIR}/../../${${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR}/${depPkg}") + endif() else() - message(FATAL_ERROR "ERROR: ${depPkg}_PACKAGE_BUILD_STATUS='${${depPkg}_PACKAGE_BUILD_STATUS}' invalid!") + message(FATAL_ERROR "ERROR:" + " ${depPkg}_PACKAGE_BUILD_STATUS='${${depPkg}_PACKAGE_BUILD_STATUS}' invalid!") endif() if (packageConfigBaseDir) string(APPEND configFileStr @@ -495,66 +555,6 @@ function(tribits_append_dependent_package_config_file_includes_and_enables packa endfunction() -# @FUNCTION: tribits_write_package_client_export_files_install_targets() -# -# Create the ``ConfigTargets.cmake`` file and install rules and the -# install() target for the previously generated -# ``Config_install.cmake`` files generated by the -# `tribits_write_flexible_package_client_export_files()`_ function. -# -# Usage:: -# -# tribits_write_package_client_export_files_install_targets( -# PACKAGE_NAME -# PACKAGE_CONFIG_FOR_BUILD_BASE_DIR -# PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR -# ) -# -# The install() commands must be in a different subroutine or CMake will not -# allow you to call the routine, even if you if() it out! -# -function(tribits_write_package_client_export_files_install_targets) - - cmake_parse_arguments( - #prefix - PARSE - #options - "" - #one_value_keywords - "PACKAGE_NAME;PACKAGE_CONFIG_FOR_BUILD_BASE_DIR;PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR" - #multi_value_keywords - "" - ${ARGN} - ) - - set(PACKAGE_NAME ${PARSE_PACKAGE_NAME}) - - if (PARSE_PACKAGE_CONFIG_FOR_BUILD_BASE_DIR) - tribits_get_package_config_build_dir_targets_file(${PACKAGE_NAME} - "${PARSE_PACKAGE_CONFIG_FOR_BUILD_BASE_DIR}" packageConfigBuildDirTargetsFile ) - export( - EXPORT ${PACKAGE_NAME} - NAMESPACE ${PACKAGE_NAME}:: - FILE "${packageConfigBuildDirTargetsFile}" ) - endif() - - if (PARSE_PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR) - install( - FILES - "${PARSE_PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR}/${PACKAGE_NAME}Config_install.cmake" - DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}/cmake/${PACKAGE_NAME}" - RENAME ${PACKAGE_NAME}Config.cmake - ) - install( - EXPORT ${PACKAGE_NAME} - NAMESPACE ${PACKAGE_NAME}:: - DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}/cmake/${PACKAGE_NAME}" - FILE "${PACKAGE_NAME}Targets.cmake" ) - endif() - -endfunction() - - # Function to return the full path the targets file for the # Config.cmake file in the build tree. # @@ -567,219 +567,6 @@ function(tribits_get_package_config_build_dir_targets_file PACKAGE_NAME endfunction() -# Generate the ${PACKAGE_NAME}Config.cmake file for package PACKAGE_NAME. -# -# ToDo: Finish documentation! -# -function(tribits_write_package_client_export_files PACKAGE_NAME) - - if(${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("\nTRIBITS_WRITE_PACKAGE_CLIENT_EXPORT_FILES: ${PACKAGE_NAME}") - endif() - - set(buildDirCMakePkgsDir - "${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_CMAKE_PKGS_DIR}") - - set(EXPORT_FILES_ARGS PACKAGE_NAME ${PACKAGE_NAME}) - - if (${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES) - if(${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("For package ${PACKAGE_NAME} creating ${PACKAGE_NAME}Config.cmake") - endif() - set(PACKAGE_CONFIG_FOR_BUILD_BASE_DIR - "${buildDirCMakePkgsDir}/${PACKAGE_NAME}" ) - set(PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR - "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles" ) - append_set(EXPORT_FILES_ARGS - PACKAGE_CONFIG_FOR_BUILD_BASE_DIR "${PACKAGE_CONFIG_FOR_BUILD_BASE_DIR}" - PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR "${PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR}" - ) - endif() - - tribits_write_flexible_package_client_export_files(${EXPORT_FILES_ARGS}) - - tribits_write_package_client_export_files_install_targets(${EXPORT_FILES_ARGS}) - -endfunction() - - -# Write the outer TriBITS Config.cmake file -# -# If ${PROJECT_NAME}_VERSION is not set or is '' on input, then it will be set -# to 0.0.0 in order to create the ${PROJECT_NAME}ConfigVersion.cmake file. -# -# ToDo: Finish documentation! -# -function(tribits_write_project_client_export_files) - - set(EXPORT_FILE_VAR_PREFIX ${PROJECT_NAME}) - - # Reversing the package list so that libraries will be produced in order of - # most dependent to least dependent. - set(PACKAGE_LIST ${${PROJECT_NAME}_DEFINED_INTERNAL_PACKAGES}) - if (PACKAGE_LIST) - list(REVERSE PACKAGE_LIST) - endif() - - # Loop over all packages to determine which were enabled. Then build a list - # of all their libraries/includes in the proper order for linking - set(FULL_PACKAGE_SET "") - set(FULL_LIBRARY_SET "") - foreach(TRIBITS_PACKAGE ${PACKAGE_LIST}) - if(${PROJECT_NAME}_ENABLE_${TRIBITS_PACKAGE}) - list(APPEND FULL_PACKAGE_SET ${TRIBITS_PACKAGE}) - list(APPEND FULL_LIBRARY_SET ${${TRIBITS_PACKAGE}_LIBRARIES}) - endif() - endforeach() - - set(${PROJECT_NAME}_CONFIG_LIBRARIES ${FULL_LIBRARY_SET}) - - # Reversing the tpl list so that the list of tpls will be produced in - # order of most dependent to least dependent. - if (${PROJECT_NAME}_DEFINED_TPLS) - set(TPL_LIST ${${PROJECT_NAME}_DEFINED_TPLS}) - list(REVERSE TPL_LIST) - endif() - - # Loop over all TPLs to determine which were enabled. Then build a list - # of all their libraries/includes in the proper order for linking - set(FULL_TPL_SET "") - set(FULL_TPL_LIBRARY_SET "") - foreach(TPL ${TPL_LIST}) - if(TPL_ENABLE_${TPL}) - list(APPEND FULL_TPL_SET ${TPL}) - list(APPEND FULL_TPL_LIBRARY_SET ${TPL_${TPL}_LIBRARIES}) - endif() - endforeach() - - set(${PROJECT_NAME}_CONFIG_TPL_LIBRARIES ${FULL_TPL_LIBRARY_SET}) - - # - # Configure two files for finding ${PROJECT_NAME}. One for the build tree - # and one for installing - # - - # Generate a note discouraging editing of the Config.cmake file - set(DISCOURAGE_EDITING "Do not edit: This file was generated automatically by CMake.") - - # Write the specification of the rpath if necessary. This is only needed if - # we're building shared libraries. - if(BUILD_SHARED_LIBS) - string(REPLACE ";" ":" SHARED_LIB_RPATH_COMMAND - "${${PROJECT_NAME}_CONFIG_LIBRARY_DIRS}") - set(SHARED_LIB_RPATH_COMMAND ${CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG}${SHARED_LIB_RPATH_COMMAND}) - endif() - - # Custom code in configuration file. - set(PROJECT_CONFIG_CODE "") - - # Appending the logic to include each package's config file. - set(LOAD_CODE "# Load configurations from enabled packages") - foreach(TRIBITS_PACKAGE ${FULL_PACKAGE_SET}) - set(LOAD_CODE "${LOAD_CODE} -include(\"${${TRIBITS_PACKAGE}_BINARY_DIR}/${TRIBITS_PACKAGE}Config.cmake\")") - endforeach() - set(PROJECT_CONFIG_CODE "${PROJECT_CONFIG_CODE}\n${LOAD_CODE}") - - tribits_set_compiler_vars_for_config_file(INSTALL_DIR) - - if (${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES) - # In TribitsProjectConfigTemplate.cmake.in, we would like to preserve - # ${}-variables after the conversion to TribitsProjectConfigTemplate.cmake. - # To this end, one typically uses the @-syntax for variables. That doesn't - # support nested variables, however. Use ${PDOLLAR} as a workaround, cf. - # . - set(PDOLLAR "$") - set(tribitsInstallationDir - "${${PROJECT_NAME}_TRIBITS_DIR}/${TRIBITS_CMAKE_INSTALLATION_FILES_DIR}") - set(TRIBITS_PROJECT_INSTALL_INCLUDE_DIR "") - configure_file( - "${tribitsInstallationDir}/TribitsProjectConfigTemplate.cmake.in" - "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" ) - endif() - - ###### - # Create a configure file for the install tree and set the install target for it. This - # file isn't generally useful inside the build tree. It will be placed in the base - # install directory for ${PROJECT_NAME} when installed. - ###### - - # Set the include and library directories relative to the location - # at which the ${PROJECT_NAME}Config.cmake file is going to be - # installed. Note the variable reference below is escaped so it - # won't be replaced until a client project attempts to locate - # directories using the installed config file. This is to deal with - # installers that allow relocation of the install tree at *install* - # time. - # The export files are typically installed in - # //cmake//. - # The relative path to the installation dir is hence k*(../) + ../../, where - # k is the number of components in . Extract those here. - # This doesn't work if ${${PROJECT_NAME}_INSTALL_LIB_DIR} contains "./" or - # "../" components, but really, it never did. All of this should actually be - # handled by CMake's configure_package_config_file(). - string(REPLACE "/" ";" PATH_LIST ${${PROJECT_NAME}_INSTALL_LIB_DIR}) - set(RELATIVE_PATH "../..") - foreach(PATH ${PATH_LIST}) - set(RELATIVE_PATH "${RELATIVE_PATH}/..") - endforeach() - - # Write the specification of the rpath if necessary. This is only needed if - # we're building shared libraries. - if(BUILD_SHARED_LIBS) - set(SHARED_LIB_RPATH_COMMAND - "${CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG}${CMAKE_INSTALL_PREFIX}/${${PROJECT_NAME}_INSTALL_LIB_DIR}" - ) - endif() - - if (${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES) - - tribits_set_compiler_vars_for_config_file(INSTALL_DIR) - - # Custom code in configuration file. - set(PROJECT_CONFIG_CODE "") - - set(PDOLLAR "$") # Hack used in configure file below - - if (IS_ABSOLUTE "${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}") - set(TRIBITS_PROJECT_INSTALL_INCLUDE_DIR "${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}") - else() - set(TRIBITS_PROJECT_INSTALL_INCLUDE_DIR - "${CMAKE_INSTALL_PREFIX}/${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}") - endif() - - configure_file( - "${${PROJECT_NAME}_TRIBITS_DIR}/${TRIBITS_CMAKE_INSTALLATION_FILES_DIR}/TribitsProjectConfigTemplate.cmake.in" - "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config_install.cmake" - ) - - install( - FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config_install.cmake" - DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}/cmake/${PROJECT_NAME}" - RENAME ${PROJECT_NAME}Config.cmake - ) - endif() - - # - # Configure the version file for ${PROJECT_NAME} - # - include(CMakePackageConfigHelpers) - if ("${${PROJECT_NAME}_VERSION}" STREQUAL "") - set(${PROJECT_NAME}_VERSION 0.0.0) - endif() - write_basic_package_version_file( - ${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake - VERSION ${${PROJECT_NAME}_VERSION} - COMPATIBILITY SameMajorVersion - ) - install( - FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" - DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}/cmake/${PROJECT_NAME}" - ) - -endfunction() - - macro(tribits_set_compiler_var_for_config_file LANG FOR_DIR) if (NOT "${CMAKE_${LANG}_COMPILER_FOR_CONFIG_FILE_${FOR_DIR}}" STREQUAL "") set(CMAKE_${LANG}_COMPILER_FOR_CONFIG_FILE diff --git a/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake b/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake index a0c53f5129fe..0a091c4d2d74 100644 --- a/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake @@ -38,7 +38,7 @@ # @HEADER include(TribitsPackageSetupCompilerFlags) -include(TribitsWriteClientExportFiles) +include(TribitsInternalPackageWriteConfigFile) include(TribitsGeneralMacros) include(TribitsLibIsTestOnly) @@ -407,6 +407,54 @@ macro(tribits_package_assert_call_context) endmacro() +# @MACRO: tribits_disable_optional_dependency() +# +# Macro called to disable an optional dependency in the current package for an +# optional (internal or external) upstream package. +# +# Usage:: +# +# tribits_disable_optional_dependency( "") +# +# This macro can be called from a top-level package's +# ``/CMakeLists.txt`` file to disable an optional dependency that +# may have been enabled by the user or through automated enable/disable logic. +# +# This is most useful in cases where multiple criteria must be considered +# before support for some upstream dependency can really be supported. In +# that case, the dependency can be disabled in the current package and +# telegraphed to all downstream packages. See `How to tweak downstream +# TriBITS "ENABLE" variables during package configuration`_ for more details. +# +macro(tribits_disable_optional_dependency upstreamPackageName reasonStr) + # Assert called in the correct context + if (NOT "${${PACKAGE_NAME}_PARENT_PACKAGE}" STREQUAL "") + message(FATAL_ERROR "ERROR: Calling tribits_disable_optional_dependency() from" + " a subpackage it not allowed. It must be called from the parent package's" + " ${${PACKAGE_NAME}_PARENT_PACKAGE} CMakeLists.txt file") + endif() + if (NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${${PACKAGE_NAME}_SOURCE_DIR}") + message(FATAL_ERROR "ERROR: Calling tribits_disable_optional_dependency() from" + " a subdirectory CMakeLists.txt file under '${CMAKE_CURRENT_SOURCE_DIR}' is not allowed." + " Instead, please call this from the package's base CMakeLists.txt file" + " '${${PACKAGE_NAME}_SOURCE_DIR}/CMakeLists.txt'" ) + endif() + # Get the variable names that are going to be set assert they exist already + set(packageEnableVarName ${PACKAGE_NAME}_ENABLE_${upstreamPackageName}) + assert_defined(${packageEnableVarName}) + string(TOUPPER ${upstreamPackageName} upstreamPackageName_UC) + set(havePackageUpstreamPackageMacroVarName + HAVE_${PACKAGE_NAME_UC}_${upstreamPackageName_UC}) + assert_defined(${havePackageUpstreamPackageMacroVarName}) + # Set the variables to OFF in local and project-level scopes + if (NOT "${reasonStr}" STREQUAL "") + message("-- ${reasonStr}") + endif() + dual_scope_set(${packageEnableVarName} OFF) + dual_scope_set(${havePackageUpstreamPackageMacroVarName} OFF) +endmacro() + + # @MACRO: tribits_add_test_directories() # # Macro called to add a set of test directories for an package. diff --git a/cmake/tribits/core/package_arch/TribitsPrintEnabledPackagesLists.cmake b/cmake/tribits/core/package_arch/TribitsPrintEnabledPackagesLists.cmake index b49d96372bfc..eb42f8be3578 100644 --- a/cmake/tribits/core/package_arch/TribitsPrintEnabledPackagesLists.cmake +++ b/cmake/tribits/core/package_arch/TribitsPrintEnabledPackagesLists.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -include(TribitsGetEnabledSublists) +include(TribitsGetPackageSublists) # @FUNCTION: tribits_print_enables_before_adjust_package_enables() @@ -50,18 +50,24 @@ include(TribitsGetEnabledSublists) # tribits_print_enables_before_adjust_package_enables() # function(tribits_print_enables_before_adjust_package_enables) - tribits_print_internal_toplevel_package_list_enable_status( - "\nExplicitly enabled top-level packages on input (by user)" ON FALSE) - tribits_print_internal_package_list_enable_status( - "\nExplicitly enabled packages on input (by user)" ON FALSE) - tribits_print_internal_toplevel_package_list_enable_status( - "\nExplicitly disabled top-level packages on input (by user or by default)" OFF FALSE) - tribits_print_internal_package_list_enable_status( - "\nExplicitly disabled packages on input (by user or by default)" OFF FALSE) - tribits_print_tpl_list_enable_status( - "\nExplicitly enabled external packages/TPLs on input (by user)" ON FALSE) - tribits_print_tpl_list_enable_status( - "\nExplicitly disabled external packages/TPLs on input (by user or by default)" OFF FALSE) + tribits_print_toplevel_package_list_enable_status( + "\nExplicitly enabled top-level packages on input (by user)" + INTERNAL ON NONEMPTY) + tribits_print_package_list_enable_status( + "\nExplicitly enabled packages on input (by user)" INTERNAL ON NONEMPTY) + tribits_print_toplevel_package_list_enable_status( + "\nExplicitly disabled top-level packages on input (by user or by default)" + INTERNAL OFF NONEMPTY) + tribits_print_package_list_enable_status( + "\nExplicitly disabled packages on input (by user or by default)" + INTERNAL OFF NONEMPTY) + tribits_print_package_list_enable_status( + "\nExplicitly enabled external packages/TPLs on input (by user)" EXTERNAL ON NONEMPTY) + tribits_print_package_list_enable_status( + "\nExplicitly disabled external packages/TPLs on input (by user or by default)" + EXTERNAL OFF NONEMPTY) + tribits_print_package_build_status("\nInitial package build status:\n" + "-- Initial: " PRINT_ALL) endfunction() @@ -75,111 +81,97 @@ endfunction() # tribits_print_enables_after_adjust_package_enables() # function(tribits_print_enables_after_adjust_package_enables) - tribits_print_prefix_string_and_list( - "\nFinal set of enabled top-level packages" - "${${PROJECT_NAME}_ENABLED_INTERNAL_TOPLEVEL_PACKAGES}") - tribits_print_prefix_string_and_list( - "\nFinal set of enabled packages" - "${${PROJECT_NAME}_ENABLED_INTERNAL_PACKAGES}") - tribits_print_internal_toplevel_package_list_enable_status( - "\nFinal set of non-enabled top-level packages" OFF TRUE) - tribits_print_internal_package_list_enable_status( - "\nFinal set of non-enabled packages" OFF TRUE) - tribits_print_tpl_list_enable_status( - "\nFinal set of enabled external packages/TPLs" ON FALSE) - tribits_print_tpl_list_enable_status( - "\nFinal set of non-enabled external packages/TPLs" OFF TRUE) + tribits_print_toplevel_package_list_enable_status( + "\nFinal set of enabled top-level packages" INTERNAL ON NONEMPTY) + tribits_print_package_list_enable_status( + "\nFinal set of enabled packages" INTERNAL ON NONEMPTY) + tribits_print_toplevel_package_list_enable_status( + "\nFinal set of non-enabled top-level packages" INTERNAL OFF INCLUDE_EMPTY) + tribits_print_package_list_enable_status( + "\nFinal set of non-enabled packages" INTERNAL OFF INCLUDE_EMPTY) + tribits_print_toplevel_package_list_enable_status( + "\nFinal set of enabled top-level external packages/TPLs" EXTERNAL ON NONEMPTY) + tribits_print_package_list_enable_status( + "\nFinal set of enabled external packages/TPLs" EXTERNAL ON NONEMPTY) + tribits_print_toplevel_package_list_enable_status( + "\nFinal set of non-enabled top-level external packages/TPLs" EXTERNAL OFF INCLUDE_EMPTY) + tribits_print_package_list_enable_status( + "\nFinal set of non-enabled external packages/TPLs" EXTERNAL OFF INCLUDE_EMPTY) + tribits_print_package_build_status("\nFinal package build status (enabled only):\n" + "-- Final: " PRINT_ONLY_ENABLED) endfunction() -# Function that prints the current set of enabled internal top-level packages +# Function that prints the current set of enabled internal or external +# top-level packages # -function(tribits_print_internal_toplevel_package_list_enable_status - DOCSTRING ENABLED_FLAG INCLUDE_EMPTY +function(tribits_print_toplevel_package_list_enable_status + docString internalOrExternal enabledFlag enableEmptyStatus ) tribits_print_packages_list_enable_status_from_var( - ${PROJECT_NAME}_DEFINED_INTERNAL_TOPLEVEL_PACKAGES - "${DOCSTRING}" ${ENABLED_FLAG} ${INCLUDE_EMPTY} ) + ${PROJECT_NAME}_DEFINED_TOPLEVEL_PACKAGES + "${docString}" "${internalOrExternal}" ${enabledFlag} ${enableEmptyStatus} ) endfunction() # Prints the current set of enabled/disabled internal packages # -function(tribits_print_internal_package_list_enable_status - DOCSTRING ENABLED_FLAG INCLUDE_EMPTY +function(tribits_print_package_list_enable_status + docString internalOrExternal enabledFlag enableEmptyStatus ) - if (ENABLED_FLAG AND NOT INCLUDE_EMPTY) - tribits_get_sublist_enabled( - ${PROJECT_NAME}_DEFINED_INTERNAL_PACKAGES - internalPackagesEnableStatusList "") - elseif (ENABLED_FLAG AND INCLUDE_EMPTY) - tribits_get_sublist_nondisabled( - ${PROJECT_NAME}_DEFINED_INTERNAL_PACKAGES ${PROJECT_NAME} - internalPackagesEnableStatusList "") - elseif (NOT ENABLED_FLAG AND NOT INCLUDE_EMPTY) - tribits_get_sublist_disabled( - ${PROJECT_NAME}_DEFINED_INTERNAL_PACKAGES - internalPackagesEnableStatusList "") - else() # NOT ENABLED_FLAG AND INCLUDE_EMPTY - tribits_get_sublist_nonenabled( - ${PROJECT_NAME}_DEFINED_INTERNAL_PACKAGES - internalPackagesEnableStatusList "") - endif() - tribits_print_prefix_string_and_list("${DOCSTRING}" - "${internalPackagesEnableStatusList}") -endfunction() - - -# Print the current set of enabled/disabled TPLs -# -function(tribits_print_tpl_list_enable_status DOCSTRING ENABLED_FLAG INCLUDE_EMPTY) - if (ENABLED_FLAG AND NOT INCLUDE_EMPTY) - tribits_get_sublist_enabled( ${PROJECT_NAME}_DEFINED_TPLS - tplsEnableStatusList "") - elseif (ENABLED_FLAG AND INCLUDE_EMPTY) - tribits_get_sublist_nondisabled( ${PROJECT_NAME}_DEFINED_TPLS - tplsEnableStatusList "") - elseif (NOT ENABLED_FLAG AND NOT INCLUDE_EMPTY) - tribits_get_sublist_disabled( ${PROJECT_NAME}_DEFINED_TPLS - tplsEnableStatusList "") - else() # NOT ENABLED_FLAG AND INCLUDE_EMPTY - tribits_get_sublist_nonenabled( ${PROJECT_NAME}_DEFINED_TPLS - tplsEnableStatusList "") - endif() - tribits_print_prefix_string_and_list("${DOCSTRING}" "${tplsEnableStatusList}") + tribits_print_packages_list_enable_status_from_var( + ${PROJECT_NAME}_DEFINED_PACKAGES + "${docString}" "${internalOrExternal}" ${enabledFlag} ${enableEmptyStatus} ) endfunction() # Print the current set of enabled/disabled packages given input list of # packages # -function(tribits_print_packages_list_enable_status_from_var PACKAGES_LIST_VAR - DOCSTRING ENABLED_FLAG INCLUDE_EMPTY +function(tribits_print_packages_list_enable_status_from_var packageListVarName + docString internalOrExternal enabledFlag enableEmptyStatus ) - if (ENABLED_FLAG AND NOT INCLUDE_EMPTY) - tribits_get_sublist_enabled(${PACKAGES_LIST_VAR} - enableStatusList "") - elseif (ENABLED_FLAG AND INCLUDE_EMPTY) - tribits_get_sublist_nondisabled(${PACKAGES_LIST_VAR} enableStatusList "") - elseif (NOT ENABLED_FLAG AND NOT INCLUDE_EMPTY) - tribits_get_sublist_disabled(${PACKAGES_LIST_VAR} - enableStatusList "") - else() # NOT ENABLED_FLAG AND INCLUDE_EMPTY - tribits_get_sublist_nonenabled(${PACKAGES_LIST_VAR} - enableStatusList "") - endif() - tribits_print_prefix_string_and_list("${DOCSTRING}" "${enableStatusList}") + tribits_filter_package_list_from_var(${packageListVarName} + "${internalOrExternal}" "${enabledFlag}" ${enableEmptyStatus} packageSublist) + tribits_print_prefix_string_and_list("${docString}" packageSublist) endfunction() # Print out a list with white-space separators with an initial doc string # -function(tribits_print_prefix_string_and_list DOCSTRING LIST_TO_PRINT) - string(REPLACE ";" " " LIST_TO_PRINT_STR "${LIST_TO_PRINT}") - list(LENGTH LIST_TO_PRINT NUM_ELEMENTS) - if (NUM_ELEMENTS GREATER "0") - message("${DOCSTRING}: ${LIST_TO_PRINT_STR} ${NUM_ELEMENTS}") +function(tribits_print_prefix_string_and_list docString listNameToPrint) + string(REPLACE ";" " " listToPrintStr "${${listNameToPrint}}") + list(LENGTH ${listNameToPrint} numElements) + if (numElements GREATER "0") + message("${docString}: ${listToPrintStr} ${numElements}") + else() + message("${docString}: ${numElements}") + endif() +endfunction() + + +# Print out the `_PACKAGE_BUILD_STATUS` vars +# +function(tribits_print_package_build_status summaryHeaderStr prefixStr + printEnabledOpt + ) + if (printEnabledOpt STREQUAL "PRINT_ALL") + set(printAll ON) + elseif (printEnabledOpt STREQUAL "PRINT_ONLY_ENABLED") + set(printAll OFF) else() - message("${DOCSTRING}: ${NUM_ELEMENTS}") + message(FATAL_ERROR + "Error, invalid value for printEnabledOpt='${printEnabledOpt}'") + endif() + + if (${PROJECT_NAME}_DUMP_PACKAGE_BUILD_STATUS) + message("${summaryHeaderStr}") + foreach(packageName IN LISTS ${PROJECT_NAME}_DEFINED_PACKAGES) + tribits_get_package_enable_status(${packageName} packageEnable "") + if (printAll OR packageEnable) + message("${prefixStr}${packageName}_PACKAGE_BUILD_STATUS=" + "${${packageName}_PACKAGE_BUILD_STATUS}") + endif() + endforeach() endif() endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsProcessEnabledTpl.cmake b/cmake/tribits/core/package_arch/TribitsProcessEnabledTpl.cmake deleted file mode 100644 index f6925f2081ff..000000000000 --- a/cmake/tribits/core/package_arch/TribitsProcessEnabledTpl.cmake +++ /dev/null @@ -1,168 +0,0 @@ -# @HEADER -# ************************************************************************ -# -# TriBITS: Tribal Build, Integrate, and Test System -# Copyright 2013 Sandia Corporation -# -# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, -# the U.S. Government retains certain rights in this software. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 3. Neither the name of the Corporation nor the names of the -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY -# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE -# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# ************************************************************************ -# @HEADER - - -# Standard TriBITS Includes -include(TribitsExternalPackageFindTplHelpers) -include(TribitsExternalPackageWriteConfigFile) -include(TribitsTplFindIncludeDirsAndLibraries) -include(TribitsGeneralMacros) - -# Standard TriBITS utilities includes -include(AppendStringVar) -include(TribitsStandardizePaths) - - -# @FUNCTION: tribits_process_enabled_tpl() -# -# Process an enabled TPL's FindTPL${TPL_NAME}.cmake module. -# -function(tribits_process_enabled_tpl TPL_NAME) - - # Setup the processing string - set(PROCESSING_MSG_STRING "Processing enabled external package/TPL: ${TPL_NAME} (") - if (${TPL_NAME}_ENABLING_PKG) - string(APPEND PROCESSING_MSG_STRING - "enabled by ${${TPL_NAME}_ENABLING_PKG}," ) - else() - string(APPEND PROCESSING_MSG_STRING - "enabled explicitly," ) - endif() - string(APPEND PROCESSING_MSG_STRING - " disable with -DTPL_ENABLE_${TPL_NAME}=OFF)" ) - - # Print the processing header - message("${PROCESSING_MSG_STRING}") - - if (NOT ${PROJECT_NAME}_TRACE_DEPENDENCY_HANDLING_ONLY) - - # Locate the FindTPL${TPL_NAME}.cmake module - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - print_var(${TPL_NAME}_FINDMOD) - endif() - if (${TPL_NAME}_FINDMOD STREQUAL "TRIBITS_PKG") - set(TPL_${TPL_NAME}_PARTS_ALREADY_SET FALSE) # ToDo: Take out? - if (NOT TPL_${TPL_NAME}_PARTS_ALREADY_SET) - find_package(${TPL_NAME} CONFIG REQUIRED) - global_set(TPL_${TPL_NAME}_LIBRARIES - "${${TPL_NAME}_LIBRARIES}" "${${TPL_NAME}_TPL_LIBRARIES}") - global_set(TPL_${TPL_NAME}_PARTS_ALREADY_SET TRUE) - endif() - return() - elseif (IS_ABSOLUTE ${${TPL_NAME}_FINDMOD}) - #message("${${TPL_NAME}_FINDMOD} is absolute!") - set(CURRENT_TPL_PATH "${${TPL_NAME}_FINDMOD}") - else() - #message("${${TPL_NAME}_FINDMOD} is *NOT* absolute!") - set(CURRENT_TPL_PATH "${PROJECT_SOURCE_DIR}/${${TPL_NAME}_FINDMOD}") - endif() - #print_var(CURRENT_TPL_PATH) - - # Process the FindTPL${TPL_NAME}.cmake module - tribits_trace_file_processing(TPL INCLUDE "${CURRENT_TPL_PATH}") - set(TRIBITS_FINDING_RAW_${TPL_NAME}_PACKAGE_FIRST TRUE) - include("${CURRENT_TPL_PATH}") - unset(TRIBITS_FINDING_RAW_${TPL_NAME}_PACKAGE_FIRST) - # NOTE: Above, setting TRIBITS_FINDING_RAW_${TPL_NAME}_PACKAGE_FIRST=TRUE - # triggers special logic in the TriBITS-created - # ${TPL_NAME}ConfigVersion.cmake file to set - # PACKAGE_VERSION_COMPATIBLE=FALSE and result in find_package(${TPL_NAME}) - # that may be called inside of ${TPL_NAME}_FINDMOD to not find a - # TriBITS-generated ${TPL_NAME}Config.cmake file. This allows - # find_package(${TPL_NAME}) to usae a proper non-TriBITS - # Find${TPL_NAME}.cmake module or find a non-TriBITS - # ${TPL_NAME}Config.cmake module. - - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - print_var(TPL_${TPL_NAME}_NOT_FOUND) - endif() - - # Address failed find of the TPL - if (TPL_${TPL_NAME}_NOT_FOUND AND NOT TPL_TENTATIVE_ENABLE_${TPL_NAME}) - message( - "-- NOTE: The find module file for this failed TPL '${TPL_NAME}' is:\n" - " ${CURRENT_TPL_PATH}\n" - " which is pointed to in the file:\n" - " ${${TPL_NAME}_TPLS_LIST_FILE}\n" - ) - if (${TPL_NAME}_ENABLING_PKG) - message( - "TIP: One way to get past the configure failure for the\n" - "TPL '${TPL_NAME}' is to simply disable it with:\n" - " -DTPL_ENABLE_${TPL_NAME}=OFF\n" - "which will disable it and will recursively disable all of the\n" - "downstream packages that have required dependencies on it, including\n" - "the package '${${TPL_NAME}_ENABLING_PKG}' which triggered its enable.\n" - "When you reconfigure, just grep the cmake stdout for '${TPL_NAME}'\n" - "and then follow the disables that occur as a result to see what impact\n" - "this TPL disable has on the configuration of ${PROJECT_NAME}.\n" - ) - else() - message( - "TIP: Even though the TPL '${TPL_NAME}' was explicitly enabled in input,\n" - "it can be disabled with:\n" - " -DTPL_ENABLE_${TPL_NAME}=OFF\n" - "which will disable it and will recursively disable all of the\n" - "downstream packages that have required dependencies on it.\n" - "When you reconfigure, just grep the cmake stdout for '${TPL_NAME}'\n" - "and then follow the disables that occur as a result to see what impact\n" - "this TPL disable has on the configuration of ${PROJECT_NAME}.\n" - ) - endif() - message(FATAL_ERROR - "ERROR: TPL_${TPL_NAME}_NOT_FOUND=${TPL_${TPL_NAME}_NOT_FOUND}, aborting!") - endif() - - # Generate the ConfigVersion.cmake file if it has not been - # created yet and add install targets for Config[Version].cmake - set(buildDirExternalPkgsDir - "${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR}") - set(tplConfigFile - "${buildDirExternalPkgsDir}/${TPL_NAME}/${TPL_NAME}Config.cmake") - set(tplConfigVersionFile - "${buildDirExternalPkgsDir}/${TPL_NAME}/${TPL_NAME}ConfigVersion.cmake") - tribits_extpkg_write_config_version_file(${TPL_NAME} - "${tplConfigVersionFile}") - tribits_extpkg_install_config_file(${TPL_NAME} "${tplConfigFile}") - tribits_extpkg_install_config_version_file(${TPL_NAME} - "${tplConfigVersionFile}") - - endif() - -endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsProcessEnabledTpls.cmake b/cmake/tribits/core/package_arch/TribitsProcessEnabledTpls.cmake new file mode 100644 index 000000000000..b161a9edef11 --- /dev/null +++ b/cmake/tribits/core/package_arch/TribitsProcessEnabledTpls.cmake @@ -0,0 +1,286 @@ +# @HEADER +# ************************************************************************ +# +# TriBITS: Tribal Build, Integrate, and Test System +# Copyright 2013 Sandia Corporation +# +# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +# the U.S. Government retains certain rights in this software. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Corporation nor the names of the +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# ************************************************************************ +# @HEADER + + +# Standard TriBITS Includes +include(TribitsExternalPackageWithImportedTargetsFindTplModuleHelpers) +include(TribitsExternalPackageWriteConfigFile) +include(TribitsTplFindIncludeDirsAndLibraries) +include(TribitsGeneralMacros) + +# Standard TriBITS utilities includes +include(AppendStringVar) +include(TribitsStandardizePaths) + + +# Gather information from enabled TPLs +# +macro(tribits_process_enabled_tpls) + + tribits_config_code_start_timer(CONFIGURE_TPLS_TIME_START_SECONDS) + + tribits_filter_package_list_from_var(${PROJECT_NAME}_DEFINED_TOPLEVEL_PACKAGES + EXTERNAL ON NONEMPTY ${PROJECT_NAME}_enabledExternalTopLevelPackages) + + tribits_project_has_tribits_compliant_external_packages( + ${PROJECT_NAME}_enabledExternalTopLevelPackages + projectHasTribitsCompliantExternalPackages ) + + if (projectHasTribitsCompliantExternalPackages) + message("") + message("Getting information for all enabled TriBITS-compliant" + " or upstream external packages/TPLs ...") + message("") + + foreach(TPL_NAME IN LISTS ${PROJECT_NAME}_enabledExternalTopLevelPackages) + if (${TPL_NAME}_IS_TRIBITS_COMPLIANT + OR ${TPL_NAME}_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE + ) + tribits_process_enabled_tribits_compliant_or_upstream_tpl(${TPL_NAME}) + endif() + endforeach() + + set(remainingTplsTextStr " remaining") + + else() + + set(remainingTplsTextStr "") + + endif() + + message("") + message("Getting information for all${remainingTplsTextStr} enabled external packages/TPLs ...") + message("") + + foreach(TPL_NAME IN LISTS ${PROJECT_NAME}_enabledExternalTopLevelPackages) + if ((NOT ${TPL_NAME}_IS_TRIBITS_COMPLIANT) + AND (NOT ${TPL_NAME}_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE) + ) + tribits_process_enabled_standard_tpl(${TPL_NAME}) + endif() + endforeach() + + tribits_config_code_stop_timer(CONFIGURE_TPLS_TIME_START_SECONDS + "\nTotal time to configure enabled external packages/TPLs") + +endmacro() + + +macro(tribits_process_enabled_tribits_compliant_or_upstream_tpl TPL_NAME) + + tribits_get_enabled_tpl_processing_string(${TPL_NAME} tplProcessingString) + message("${tplProcessingString}") + + if (NOT ${PROJECT_NAME}_TRACE_DEPENDENCY_HANDLING_ONLY) + if (NOT ${TPL_NAME}_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE) + tribits_process_enabled_tribits_compliant_tpl(${TPL_NAME}) + else() + message("-- " + "The external package/TPL ${TPL_NAME} will be read in by a downstream" + " TriBITS-compliant external package") + endif() + endif() + +endmacro() + + +# @MACRO: tribits_process_enabled_standard_tpl() +# +# Process an enabled TPL's FindTPL${TPL_NAME}.cmake module. +# +macro(tribits_process_enabled_standard_tpl TPL_NAME) + + tribits_get_enabled_tpl_processing_string(${TPL_NAME} tplProcessingString) + message("${tplProcessingString}") + + if (NOT ${PROJECT_NAME}_TRACE_DEPENDENCY_HANDLING_ONLY) + + # Locate the FindTPL${TPL_NAME}.cmake module + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + print_var(${TPL_NAME}_FINDMOD) + endif() + + tribits_process_enabled_tribits_find_tpl_mod_file(${TPL_NAME}) + tribits_address_failed_tpl_find(${TPL_NAME}) + tribits_generate_tpl_version_file_and_add_package_config_install_targets( + ${TPL_NAME}) + + endif() + +endmacro() + + +# Get external package/TPL processing string +# +function(tribits_get_enabled_tpl_processing_string TPL_NAME tplProcessingStringOut) + set(tplProcessingString "Processing enabled external package/TPL: ${TPL_NAME} (") + if (${TPL_NAME}_ENABLING_PKG) + string(APPEND tplProcessingString "enabled by ${${TPL_NAME}_ENABLING_PKG}," ) + else() + string(APPEND tplProcessingString "enabled explicitly," ) + endif() + string(APPEND tplProcessingString " disable with -DTPL_ENABLE_${TPL_NAME}=OFF)" ) + set(${tplProcessingStringOut} "${tplProcessingString}" PARENT_SCOPE) +endfunction() + + +# Process an enabled TPL defined using a TriBITS-compliant external +# packages Config.cmake file +# +macro(tribits_process_enabled_tribits_compliant_tpl TPL_NAME) + message("-- " + "Calling find_package(${TPL_NAME}) for TriBITS-compliant external package") + find_package(${TPL_NAME} CONFIG REQUIRED) +endmacro() + + +# Process an enabled TPL defined using a FindTPL.cmake module +# +macro(tribits_process_enabled_tribits_find_tpl_mod_file TPL_NAME) + + if (IS_ABSOLUTE ${${TPL_NAME}_FINDMOD}) + #message("${${TPL_NAME}_FINDMOD} is absolute!") + set(CURRENT_TPL_PATH "${${TPL_NAME}_FINDMOD}") + else() + #message("${${TPL_NAME}_FINDMOD} is *NOT* absolute!") + set(CURRENT_TPL_PATH "${PROJECT_SOURCE_DIR}/${${TPL_NAME}_FINDMOD}") + endif() + #print_var(CURRENT_TPL_PATH) + + # Process the FindTPL${TPL_NAME}.cmake module + tribits_trace_file_processing(TPL INCLUDE "${CURRENT_TPL_PATH}") + set(TRIBITS_FINDING_RAW_${TPL_NAME}_PACKAGE_FIRST TRUE) + include("${CURRENT_TPL_PATH}") + unset(TRIBITS_FINDING_RAW_${TPL_NAME}_PACKAGE_FIRST) + # NOTE: Above, setting TRIBITS_FINDING_RAW_${TPL_NAME}_PACKAGE_FIRST=TRUE + # triggers special logic in the TriBITS-created + # ${TPL_NAME}ConfigVersion.cmake file to set + # PACKAGE_VERSION_COMPATIBLE=FALSE and result in find_package(${TPL_NAME}) + # that may be called inside of ${TPL_NAME}_FINDMOD to not find a + # TriBITS-generated ${TPL_NAME}Config.cmake file. This allows + # find_package(${TPL_NAME}) to usae a proper non-TriBITS + # Find${TPL_NAME}.cmake module or find a non-TriBITS + # ${TPL_NAME}Config.cmake module. + + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + print_var(TPL_${TPL_NAME}_NOT_FOUND) + endif() + +endmacro() + + +function(tribits_address_failed_tpl_find TPL_NAME) + # Address failed find of the TPL + if (TPL_${TPL_NAME}_NOT_FOUND AND NOT TPL_TENTATIVE_ENABLE_${TPL_NAME}) + message( + "-- NOTE: The find module file for this failed TPL '${TPL_NAME}' is:\n" + " ${CURRENT_TPL_PATH}\n" + " which is pointed to in the file:\n" + " ${${TPL_NAME}_TPLS_LIST_FILE}\n" + ) + if (${TPL_NAME}_ENABLING_PKG) + message( + "TIP: One way to get past the configure failure for the\n" + "TPL '${TPL_NAME}' is to simply disable it with:\n" + " -DTPL_ENABLE_${TPL_NAME}=OFF\n" + "which will disable it and will recursively disable all of the\n" + "downstream packages that have required dependencies on it, including\n" + "the package '${${TPL_NAME}_ENABLING_PKG}' which triggered its enable.\n" + "When you reconfigure, just grep the cmake stdout for '${TPL_NAME}'\n" + "and then follow the disables that occur as a result to see what impact\n" + "this TPL disable has on the configuration of ${PROJECT_NAME}.\n" + ) + else() + message( + "TIP: Even though the TPL '${TPL_NAME}' was explicitly enabled in input,\n" + "it can be disabled with:\n" + " -DTPL_ENABLE_${TPL_NAME}=OFF\n" + "which will disable it and will recursively disable all of the\n" + "downstream packages that have required dependencies on it.\n" + "When you reconfigure, just grep the cmake stdout for '${TPL_NAME}'\n" + "and then follow the disables that occur as a result to see what impact\n" + "this TPL disable has on the configuration of ${PROJECT_NAME}.\n" + ) + endif() + message(FATAL_ERROR + "ERROR: TPL_${TPL_NAME}_NOT_FOUND=${TPL_${TPL_NAME}_NOT_FOUND}, aborting!") + endif() +endfunction() + + +# Generate the ConfigVersion.cmake file for a TriBITS TPL and install +# the already generated Config.cmake file +# +function(tribits_generate_tpl_version_file_and_add_package_config_install_targets + TPL_NAME + ) + set(buildDirExternalPkgsDir + "${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR}") + set(tplConfigFile + "${buildDirExternalPkgsDir}/${TPL_NAME}/${TPL_NAME}Config.cmake") + set(tplConfigVersionFile + "${buildDirExternalPkgsDir}/${TPL_NAME}/${TPL_NAME}ConfigVersion.cmake") + tribits_extpkg_write_config_version_file(${TPL_NAME} + "${tplConfigVersionFile}") + tribits_extpkg_install_config_file(${TPL_NAME} "${tplConfigFile}") + tribits_extpkg_install_config_version_file(${TPL_NAME} + "${tplConfigVersionFile}") +endfunction() + + +function(tribits_project_has_tribits_compliant_external_packages + enabledExternalTopLevelPackagesListName + projectHasTribitsCompliantExternalPackagesOut + ) + + set(projectHasTribitsCompliantExternalPackages FALSE) + + foreach(TPL_NAME IN LISTS ${enabledExternalTopLevelPackagesListName}) + if (${TPL_NAME}_IS_TRIBITS_COMPLIANT + OR ${TPL_NAME}_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE + ) + set(projectHasTribitsCompliantExternalPackages TRUE) + break() + endif() + endforeach() + + set(${projectHasTribitsCompliantExternalPackagesOut} + ${projectHasTribitsCompliantExternalPackages} PARENT_SCOPE) + +endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsProcessPackagesAndDirsLists.cmake b/cmake/tribits/core/package_arch/TribitsProcessPackagesAndDirsLists.cmake index d045fdedfaaa..447f98265c1b 100644 --- a/cmake/tribits/core/package_arch/TribitsProcessPackagesAndDirsLists.cmake +++ b/cmake/tribits/core/package_arch/TribitsProcessPackagesAndDirsLists.cmake @@ -572,6 +572,7 @@ macro(tribits_process_packages_and_dirs_lists REPOSITORY_NAME REPOSITORY_DIR) set(${TRIBITS_PACKAGE}_PARENT_REPOSITORY ${REPOSITORY_NAME}) tribits_insert_standard_package_options(${TRIBITS_PACKAGE} ${PACKAGE_TESTGROUP}) set(${TRIBITS_PACKAGE}_PACKAGE_BUILD_STATUS INTERNAL) + set(${TRIBITS_PACKAGE}_IS_TRIBITS_COMPLIANT TRUE) else() if (${PROJECT_NAME}_VERBOSE_CONFIGURE) message( @@ -593,6 +594,7 @@ macro(tribits_process_packages_and_dirs_lists REPOSITORY_NAME REPOSITORY_DIR) print_var(${TRIBITS_PACKAGE}_PARENT_PACKAGE) print_var(${TRIBITS_PACKAGE}_PARENT_REPOSITORY) print_var(${TRIBITS_PACKAGE}_PACKAGE_BUILD_STATUS) + print_var(${TRIBITS_PACKAGE}_IS_TRIBITS_COMPLIANT) endif() if (TRIBITS_PROCESS_PACKAGES_AND_DIRS_LISTS_VERBOSE) diff --git a/cmake/tribits/core/package_arch/TribitsProcessTplsLists.cmake b/cmake/tribits/core/package_arch/TribitsProcessTplsLists.cmake index 611dcf3f73b2..f5e5a6e55d63 100644 --- a/cmake/tribits/core/package_arch/TribitsProcessTplsLists.cmake +++ b/cmake/tribits/core/package_arch/TribitsProcessTplsLists.cmake @@ -47,10 +47,10 @@ include(Split) # @MACRO: tribits_repository_define_tpls() # -# Define the list of `TriBITS TPLs`_ (external packages) for a given `TriBITS -# Repository`_ which includes the TPL name, find module, and classification . -# This macro is typically called from inside of the repository's -# `/TPLsList.cmake`_ file. +# Define the list of `TriBITS External Packages/TPLs`_ for a given `TriBITS +# Repository`_ which includes the external package/TPL name, TriBITS TPL find +# module, and classification . This macro is typically called from inside of +# a TriBITS Repository's `/TPLsList.cmake`_ file. # # Usage:: # @@ -62,58 +62,53 @@ include(Split) # # This macro sets up a 2D array of ``NumTPLS`` by ``NumColumns`` listing out # the `TriBITS TPLs`_ for a `TriBITS Repository`_. Each row (with 3 entries) -# specifies a TPL which contains the columns (ordered 0-2): +# specifies a different TriBITS exernal package/TPL which contains the columns +# (ordered 0-2): # -# 0. **TPL** (````): The name of the TriBITS TPL ````. -# This name must be unique across all other TriBITS TPLs in this or any -# other TriBITS repo that might be combined into a single TriBITS project -# meta-build (see `Globally unique TriBITS TPL names`_). However, a TPL -# can be redefined from an upstream repo (see below). The name should be a -# valid identifier (e.g. matches the regex ``[a-zA-Z_][a-zA-Z0-9_]*``). -# TPL names typically use mixed case (e.g. ``SomeTpl`` and not -# ``SOMETPL``). +# 0. **TPL** (````): The name of the TriBITS external package/TPL +# ````. This name must be unique across all other TriBITS TPLs in +# this or any other TriBITS repo that might be combined into a single +# TriBITS project meta-build (see `Globally unique TriBITS TPL names`_). +# However, a TPL can be redefined from an upstream repo (see below). The +# name should be a valid identifier (e.g. matches the regex +# ``[a-zA-Z_][a-zA-Z0-9_]*``). TPL names typically use mixed case +# (e.g. ``SomeTpl``, not ``SOMETPL``). # -# 1. **FINDMOD** (````): The relative or absolute path for the -# find module, usually with the name `FindTPL.cmake`_. If it is a -# relative path, it is considered relative to the repository base directory -# ````. If just the base path for the find module is given, -# ending with ``"/"`` (e.g. ``"cmake/tpls/"``), then the find module will -# be assumed to be under that this directory with the standard name +# 1. **FINDMOD** (````): For a TriBITS external package/TPL that +# **is not** a `TriBITS-compliant external package`_, this is set to the +# relative or absolute path for the TriBITS TPL find module, usually with +# the name `FindTPL.cmake`_. If it is a relative path, it is +# considered relative to the repository base directory ````. If +# just the base path for the find module is given, ending with ``"/"`` +# (e.g. ``"cmake/tpls/"``), then the find module will be assumed to be +# under that this directory with the standard name # ``FindTPL.cmake``. (See `Creating the FindTPL.cmake -# file`_.) +# file`_.) However, if the external package **is** a `TriBITS-compliant +# external package`_, provide the value ``TRIBITS_PKG`` instead and no +# ``FindTPL.cmake`` file is needed. If a +# ``FindTPLDependencies.cmake`` file is needed in this case, then +# provide the path to that file (relative or absolute, directory or file +# path) using ``TRIBITS_PKG:``. This field is used to +# set the variables `_FINDMOD`_ and +# `_DEPENDENCIES_FILE`_. # -# 2. **CLASSIFICATION** (````): Gives the `Package Test -# Group`_ `PT`_, `ST`_, or `EX`_ and the maturity level ``EP``, ``RS``, -# ``PG``, ``PM``, ``GRS``, ``GPG``, ``GPM``, ``UM``. These are separated -# by a coma with no space in between such as ``"RS,PT"`` for a "Research -# Stable", "Primary Tested" package. No spaces are allowed so that CMake -# treats this a one field in the array. The maturity level can be left off -# in which case it is assumed to be ``UM`` for "Unspecified Maturity". +# 2. **CLASSIFICATION** (````): Gives the `Package Test Group`_ +# `PT`_, `ST`_, or `EX`_ and the maturity level ``EP``, ``RS``, ``PG``, +# ``PM``, ``GRS``, ``GPG``, ``GPM``, ``UM``. These are separated by a coma +# with no space in between such as ``"RS,PT"`` for a "Research Stable", +# "Primary Tested" package. No spaces are allowed so that CMake treats +# this a one field in the array. The maturity level can be left off in +# which case it is assumed to be ``UM`` for "Unspecified Maturity". This +# field is used to set the variable `_TESTGROUP`_ and +# ``_MATURITY_LEVEL``. # -# A TPL defined in a upstream repo can listed again in a downstream repo, -# which allows redefining the find module that is used to specify the TPL. -# This allows downstream repos to add additional requirements for a given TPL -# (i.e. add more libraries, headers, etc.). However, the downstream repo's -# find module file must find the TPL components that are fully compatible with -# the upstream's find module. -# -# This macro just sets the variable:: -# -# ${REPOSITORY_NAME}_TPLS_FINDMODS_CLASSIFICATIONS -# -# in the current scope. The advantages of using this macro instead of -# directly setting this variable are that the macro: -# -# * Asserts that the variable ``REPOSITORY_NAME`` is defined and set -# -# * Avoids having to hard-code the assumed repository name -# ``${REPOSITORY_NAME}``. This provides more flexibility for how other -# TriBITS projects choose to name a given TriBITS repo (i.e. the name of -# repo subdirs). -# -# * Avoids misspelling the name of the variable -# ``${REPOSITORY_NAME}_TPLS_FINDMODS_CLASSIFICATIONS``. If one misspells -# the name of a macro, it is an immediate error in CMake. +# A TPL defined in a upstream repo can be listed again in a downstream repo, +# which allows redefining the find module that is used to specify the external +# package/TPL. This allows downstream repos to add additional requirements +# for a given TPL (i.e. add more libraries, headers, etc.). However, the +# downstream repo's find module file must find the TPL components that are +# fully compatible with the upstream defined find module in terms of what it +# provides for packages in the upstream repos. # macro(tribits_repository_define_tpls) assert_defined(REPOSITORY_NAME) @@ -275,6 +270,14 @@ macro(tribits_process_tpls_lists REPOSITORY_NAME REPOSITORY_DIR) set(${TPL_NAME}_PACKAGE_BUILD_STATUS EXTERNAL) + # Set ${TPL_NAME}_IS_TRIBITS_COMPLIANT + + if (${TPL_NAME}_FINDMOD STREQUAL "TRIBITS_PKG") + set(${TPL_NAME}_IS_TRIBITS_COMPLIANT TRUE) + else() + set(${TPL_NAME}_IS_TRIBITS_COMPLIANT FALSE) + endif() + # Print variables/properties for the TPL if (${PROJECT_NAME}_VERBOSE_CONFIGURE OR TRIBITS_PROCESS_TPLS_LISTS_VERBOSE) @@ -283,6 +286,7 @@ macro(tribits_process_tpls_lists REPOSITORY_NAME REPOSITORY_DIR) print_var(${TPL_NAME}_DEPENDENCIES_FILE) print_var(${TPL_NAME}_TPLS_LIST_FILE) print_var(${TPL_NAME}_PACKAGE_BUILD_STATUS) + print_var(${TPL_NAME}_IS_TRIBITS_COMPLIANT) endif() # Set cache var TPL_ENABLE_${TPL_NAME} with default "" diff --git a/cmake/tribits/core/package_arch/TribitsProjectImpl.cmake b/cmake/tribits/core/package_arch/TribitsProjectImpl.cmake index 892cecc6b6a3..f27caa3e6687 100644 --- a/cmake/tribits/core/package_arch/TribitsProjectImpl.cmake +++ b/cmake/tribits/core/package_arch/TribitsProjectImpl.cmake @@ -190,10 +190,6 @@ macro(tribits_project_impl) # G) Go get the information for all enabled TPLS # - message("") - message("Getting information for all enabled external packages/TPLs ...") - message("") - tribits_process_enabled_tpls() # diff --git a/cmake/tribits/core/package_arch/TribitsProjectWriteConfigFile.cmake b/cmake/tribits/core/package_arch/TribitsProjectWriteConfigFile.cmake new file mode 100644 index 000000000000..5f4fa70899e4 --- /dev/null +++ b/cmake/tribits/core/package_arch/TribitsProjectWriteConfigFile.cmake @@ -0,0 +1,228 @@ +# @HEADER +# ************************************************************************ +# +# TriBITS: Tribal Build, Integrate, and Test System +# Copyright 2013 Sandia Corporation +# +# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +# the U.S. Government retains certain rights in this software. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Corporation nor the names of the +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# ************************************************************************ +# @HEADER + + +################################################################################ +# +# Module TribitsInternalPackageWriteConfigFile.cmake +# +# This module contains code for generating Config.cmake files for +# TriBITS projects. +# +################################################################################ + + +include(TribitsInternalPackageWriteConfigFile) + + +# Write the outer TriBITS Config.cmake file +# +# If ${PROJECT_NAME}_VERSION is not set or is '' on input, then it will be set +# to 0.0.0 in order to create the ${PROJECT_NAME}ConfigVersion.cmake file. +# +# ToDo: Finish documentation! +# +function(tribits_write_project_client_export_files) + + set(EXPORT_FILE_VAR_PREFIX ${PROJECT_NAME}) + + # Reversing the package list so that libraries will be produced in order of + # most dependent to least dependent. + set(PACKAGE_LIST ${${PROJECT_NAME}_DEFINED_INTERNAL_PACKAGES}) + if (PACKAGE_LIST) + list(REVERSE PACKAGE_LIST) + endif() + + # Loop over all packages to determine which were enabled. Then build a list + # of all their libraries/includes in the proper order for linking + set(FULL_PACKAGE_SET "") + set(FULL_LIBRARY_SET "") + foreach(TRIBITS_PACKAGE ${PACKAGE_LIST}) + if(${PROJECT_NAME}_ENABLE_${TRIBITS_PACKAGE}) + list(APPEND FULL_PACKAGE_SET ${TRIBITS_PACKAGE}) + list(APPEND FULL_LIBRARY_SET ${${TRIBITS_PACKAGE}_LIBRARIES}) + endif() + endforeach() + + set(${PROJECT_NAME}_CONFIG_LIBRARIES ${FULL_LIBRARY_SET}) + + # Reversing the tpl list so that the list of tpls will be produced in + # order of most dependent to least dependent. + if (${PROJECT_NAME}_DEFINED_TPLS) + set(TPL_LIST ${${PROJECT_NAME}_DEFINED_TPLS}) + list(REVERSE TPL_LIST) + endif() + + # Loop over all TPLs to determine which were enabled. Then build a list + # of all their libraries/includes in the proper order for linking + set(FULL_TPL_SET "") + set(FULL_TPL_LIBRARY_SET "") + foreach(TPL ${TPL_LIST}) + if(TPL_ENABLE_${TPL}) + list(APPEND FULL_TPL_SET ${TPL}) + list(APPEND FULL_TPL_LIBRARY_SET ${TPL_${TPL}_LIBRARIES}) + endif() + endforeach() + + set(${PROJECT_NAME}_CONFIG_TPL_LIBRARIES ${FULL_TPL_LIBRARY_SET}) + + # + # Configure two files for finding ${PROJECT_NAME}. One for the build tree + # and one for installing + # + + # Generate a note discouraging editing of the Config.cmake file + set(DISCOURAGE_EDITING "Do not edit: This file was generated automatically by CMake.") + + # Write the specification of the rpath if necessary. This is only needed if + # we're building shared libraries. + if(BUILD_SHARED_LIBS) + string(REPLACE ";" ":" SHARED_LIB_RPATH_COMMAND + "${${PROJECT_NAME}_CONFIG_LIBRARY_DIRS}") + set(SHARED_LIB_RPATH_COMMAND ${CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG}${SHARED_LIB_RPATH_COMMAND}) + endif() + + # Custom code in configuration file. + set(PROJECT_CONFIG_CODE "") + + # Appending the logic to include each package's config file. + set(LOAD_CODE "# Load configurations from enabled packages") + foreach(TRIBITS_PACKAGE ${FULL_PACKAGE_SET}) + set(LOAD_CODE "${LOAD_CODE} +include(\"${${TRIBITS_PACKAGE}_BINARY_DIR}/${TRIBITS_PACKAGE}Config.cmake\")") + endforeach() + set(PROJECT_CONFIG_CODE "${PROJECT_CONFIG_CODE}\n${LOAD_CODE}") + + tribits_set_compiler_vars_for_config_file(INSTALL_DIR) + + if (${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES) + # In TribitsProjectConfigTemplate.cmake.in, we would like to preserve + # ${}-variables after the conversion to TribitsProjectConfigTemplate.cmake. + # To this end, one typically uses the @-syntax for variables. That doesn't + # support nested variables, however. Use ${PDOLLAR} as a workaround, cf. + # . + set(PDOLLAR "$") + set(tribitsInstallationDir + "${${PROJECT_NAME}_TRIBITS_DIR}/${TRIBITS_CMAKE_INSTALLATION_FILES_DIR}") + set(TRIBITS_PROJECT_INSTALL_INCLUDE_DIR "") + configure_file( + "${tribitsInstallationDir}/TribitsProjectConfigTemplate.cmake.in" + "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" ) + endif() + + ###### + # Create a configure file for the install tree and set the install target for it. This + # file isn't generally useful inside the build tree. It will be placed in the base + # install directory for ${PROJECT_NAME} when installed. + ###### + + # Set the include and library directories relative to the location + # at which the ${PROJECT_NAME}Config.cmake file is going to be + # installed. Note the variable reference below is escaped so it + # won't be replaced until a client project attempts to locate + # directories using the installed config file. This is to deal with + # installers that allow relocation of the install tree at *install* + # time. + # The export files are typically installed in + # //cmake//. + # The relative path to the installation dir is hence k*(../) + ../../, where + # k is the number of components in . Extract those here. + # This doesn't work if ${${PROJECT_NAME}_INSTALL_LIB_DIR} contains "./" or + # "../" components, but really, it never did. All of this should actually be + # handled by CMake's configure_package_config_file(). + string(REPLACE "/" ";" PATH_LIST ${${PROJECT_NAME}_INSTALL_LIB_DIR}) + set(RELATIVE_PATH "../..") + foreach(PATH ${PATH_LIST}) + set(RELATIVE_PATH "${RELATIVE_PATH}/..") + endforeach() + + # Write the specification of the rpath if necessary. This is only needed if + # we're building shared libraries. + if(BUILD_SHARED_LIBS) + set(SHARED_LIB_RPATH_COMMAND + "${CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG}${CMAKE_INSTALL_PREFIX}/${${PROJECT_NAME}_INSTALL_LIB_DIR}" + ) + endif() + + if (${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES) + + tribits_set_compiler_vars_for_config_file(INSTALL_DIR) + + # Custom code in configuration file. + set(PROJECT_CONFIG_CODE "") + + set(PDOLLAR "$") # Hack used in configure file below + + if (IS_ABSOLUTE "${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}") + set(TRIBITS_PROJECT_INSTALL_INCLUDE_DIR "${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}") + else() + set(TRIBITS_PROJECT_INSTALL_INCLUDE_DIR + "${CMAKE_INSTALL_PREFIX}/${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}") + endif() + + configure_file( + "${${PROJECT_NAME}_TRIBITS_DIR}/${TRIBITS_CMAKE_INSTALLATION_FILES_DIR}/TribitsProjectConfigTemplate.cmake.in" + "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config_install.cmake" + ) + + install( + FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config_install.cmake" + DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}/cmake/${PROJECT_NAME}" + RENAME ${PROJECT_NAME}Config.cmake + ) + endif() + + # + # Configure the version file for ${PROJECT_NAME} + # + include(CMakePackageConfigHelpers) + if ("${${PROJECT_NAME}_VERSION}" STREQUAL "") + set(${PROJECT_NAME}_VERSION 0.0.0) + endif() + write_basic_package_version_file( + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake + VERSION ${${PROJECT_NAME}_VERSION} + COMPATIBILITY SameMajorVersion + ) + install( + FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" + DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}/cmake/${PROJECT_NAME}" + ) + +endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsReadDepsFilesCreateDepsGraph.cmake b/cmake/tribits/core/package_arch/TribitsReadDepsFilesCreateDepsGraph.cmake index bd5f09e61d37..c8c22505b3c5 100644 --- a/cmake/tribits/core/package_arch/TribitsReadDepsFilesCreateDepsGraph.cmake +++ b/cmake/tribits/core/package_arch/TribitsReadDepsFilesCreateDepsGraph.cmake @@ -554,10 +554,10 @@ endfunction() # Implementation macro for tribits_set_dep_packages() to deal with a package # that is not defined by TriBITS. # -# ToDo #63: This may need to be modified when dealing with TriBITS-compatible +# ToDo #63: This may need to be modified when dealing with TriBITS-compliant # packages already installed out on the system. We may need a mode where we # don't assert packages that are not defined but instead just assume they are -# TriBITS-compatible packages already installed. +# TriBITS-compliant packages already installed. # macro(tribits_set_dep_packages__handle_undefined_pkg packageName depPkg requiredOrOptional pkgsOrTpls packageEnableVar @@ -960,6 +960,8 @@ macro(tribits_read_subpackage_deps_file_add_to_graph PACKAGE_NAME tribits_process_package_dependencies_lists(${SUBPACKAGE_FULLNAME}) + set(${SUBPACKAGE_FULLNAME}_IS_TRIBITS_COMPLIANT TRUE) + set(${SUBPACKAGE_FULLNAME}_REGRESSION_EMAIL_LIST ${${PACKAGE_NAME}_REGRESSION_EMAIL_LIST}) diff --git a/cmake/tribits/core/package_arch/TribitsSystemDataStructuresMacrosFunctions.rst b/cmake/tribits/core/package_arch/TribitsSystemDataStructuresMacrosFunctions.rst index f4661403fabd..861ccc835ec6 100644 --- a/cmake/tribits/core/package_arch/TribitsSystemDataStructuresMacrosFunctions.rst +++ b/cmake/tribits/core/package_arch/TribitsSystemDataStructuresMacrosFunctions.rst @@ -428,7 +428,7 @@ Logic`_. Determining if a package is internal or external ++++++++++++++++++++++++++++++++++++++++++++++++ -As mentioned above, some subset of packages listed in +As mentioned above, some subset of initially internal packages listed in `${PROJECT_NAME}_DEFINED_INTERNAL_TOPLEVEL_PACKAGES`_ (which all have ``${PACKAGE_NAME}_SOURCE_DIR != ""``) may be chosen to be external packages. Packages that could be built internally may be chosen to be treated as @@ -437,10 +437,6 @@ external packages (and therefore located on the system using -D TPL_ENABLE_=ON -or:: - - -D _ROOT= - .. _${PACKAGE_NAME}_PACKAGE_BUILD_STATUS: .. _${TPL_NAME}_PACKAGE_BUILD_STATUS: @@ -449,10 +445,91 @@ external package is provided by the variable:: ${PACKAGE_NAME}_PACKAGE_BUILD_STATUS=[INTERNAL|EXTERNAL] +(NOT: The value of ``${PACKAGE_NAME}_PACKAGE_BUILD_STATUS`` is only changed +after all of the enable/disable dependency logic is complete.) + As a result, every other package upstream from any of these ```` packages must therefore also be treated as external packages automatically and will have -``${PACKAGE_NAME}_PACKAGE_BUILD_STATUS=EXTERNAL`` set accordingly. +``${PACKAGE_NAME}_PACKAGE_BUILD_STATUS=EXTERNAL`` set accordingly. Also, if +any subpackage is determined to be EXTERNAL, then the parent package of that +subpackage and every other peer subpackage will also be set to EXTERNAL. + + +Processing of external packages/TPLs and TriBITS-compliant external packages ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +The processing of external packages/TPLs is influenced by whether the external +package is a regular TriBITS TPL or is a TriBITS-compliant external +package. Here, a **TriBITS-Compliant External Package** has a +``Config.cmake`` file that satisfies the following properties: + +* Has the target ``::all_libs``. +* Calls ``find_dependency()`` for all upstream packages it depends on. +* Every upstream dependent package ```` has the target + ``::all_libs``. + +That means that when calling ``find_package()`` for a TriBITS-compliant +external package, there is no need to worry about finding any of its upstream +dependent external packages. That means that any external packages/TPLs +defined a TriBITS project which is upstream from a TriBITS-compliant +external package will be uniquely defined by calling ``find_package()`` on the +most downstream TriBITS-compliant external package that depends on it. +Therefore, defining the external packages and their targets in this set of +external packages just involves calling ``find_package()`` on the terminal +TriBITS-compliant external packages (i.e. TriBITS-compliant +external packages that don't have any downstream dependencies that are +external packages). Then the remaining subset of external packages/TPLs that +don't have a downstream TriBITS-compliant external package dependency +will be defined as usual. (ToDo: Put in a more detailed examples explaining +how this works.) + +The variables that are set internally to define these different subsets of +external packages/TPLs are: + +* ``_IS_TRIBITS_COMPLIANT``: Set the ``TRUE`` if the package + ```` provides the ``::all_libs`` target for itself and all + of its upstream dependent (internal or external) packages (whether this + package is treated as an internal or external package). + +* ``_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE``: Set to + ``TRUE`` if the external package/TPL will be processed by downstream TriBITS + complient package. In this case, we just print that we are skipping the + find operation and explain why. + +An external package with ``_IS_TRIBITS_COMPLIANT=TRUE`` **AND** +``_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE=FALSE`` is the +one for which ``find_package( CONFIG REQUIRED)`` will be called and +does not have any downstream packages that are being treated as external +packages. + +The variable ``_IS_TRIBITS_COMPLIANT`` is set right when the +packages are initially defined by reading in the various input files. That +is, all initially internal packages that are listed in a +`/PackagesList.cmake`_ file will have +``_IS_TRIBITS_COMPLIANT=TRUE`` set. While all external +packages/TPLs listed in a `/TPLsList.cmake`_ file will have +``_IS_TRIBITS_COMPLIANT=FALSE`` set (except for those tagged +with ``TRIBITS_PKG`` which will have +``_IS_TRIBITS_COMPLIANT=FALSE`` set). + +NOTE: When a TriBITS TPL (i.e. ``_IS_TRIBITS_COMPLIANT=FALSE``) +is being processed, we can't assume where its +``Config.cmake`` file exists so we must find upstream +dependencies using ``set(_DIR ...)`` and +``find_dependency( CONFIG REQUIRED)``. + +So the first loop over external packages/TPLs will be those external +packages/TPLs that have ``_IS_TRIBITS_COMPLIANT=TRUE`` **OR** +``_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE=TRUE``. And we +only call ``find_package()`` for those TriBITS-compliant external +packages that have ``_IS_TRIBITS_COMPLIANT=TRUE`` **AND** +``_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE=FALSE``. + +The second loop are those external packages/TPLs that don't have a downstream +TriBITS-compliant external package which are all of those external +packages for which ``_IS_TRIBITS_COMPLIANT=FALSE`` **AND** +``_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE=FALSE``. Other package-related variables diff --git a/cmake/tribits/core/package_arch/TribitsTplFindIncludeDirsAndLibraries.cmake b/cmake/tribits/core/package_arch/TribitsTplFindIncludeDirsAndLibraries.cmake index ad2621289daf..490d204ec71e 100644 --- a/cmake/tribits/core/package_arch/TribitsTplFindIncludeDirsAndLibraries.cmake +++ b/cmake/tribits/core/package_arch/TribitsTplFindIncludeDirsAndLibraries.cmake @@ -724,8 +724,6 @@ function(tribits_tpl_find_include_dirs_and_libraries TPL_NAME) tribits_extpkg_write_config_file(${TPL_NAME} "${tplConfigFile}") if (NOT ${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING) include("${tplConfigFile}") - set(${TPL_NAME}_DIR "${tplConfigFileBaseDir}" CACHE INTERNAL - "TriBITS-generated ${TPL_NAME}Config.cmake file used from this dir") endif() # NOTE: The file ConfigVersion.cmake will get created elsewhere as # will the install targets for the files Config and diff --git a/cmake/tribits/core/package_arch/TribitsWritePackageConfigFileHelpers.cmake b/cmake/tribits/core/package_arch/TribitsWritePackageConfigFileHelpers.cmake new file mode 100644 index 000000000000..310e58876153 --- /dev/null +++ b/cmake/tribits/core/package_arch/TribitsWritePackageConfigFileHelpers.cmake @@ -0,0 +1,65 @@ +# @HEADER +# ************************************************************************ +# +# TriBITS: Tribal Build, Integrate, and Test System +# Copyright 2013 Sandia Corporation +# +# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +# the U.S. Government retains certain rights in this software. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Corporation nor the names of the +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# ************************************************************************ +# @HEADER + + +# @FUNCTION: tribits_extpkg_append_tribits_compliant_package_config_vars_str() +# +# Append the standard TriBITS-compliant external package variables +# +function(tribits_extpkg_append_tribits_compliant_package_config_vars_str packageName + packageConfigCodeStrVarInOut + ) + set(packageConfigCodeStr "${${packageConfigCodeStrVarInOut}}") + string(APPEND packageConfigCodeStr + "\n# Standard TriBITS-compliant external package variables\n" + "set(${packageName}_IS_TRIBITS_COMPLIANT TRUE)\n" + "set(${packageName}_TRIBITS_COMPLIANT_PACKAGE_CONFIG_FILE \"\${CMAKE_CURRENT_LIST_FILE}\")\n" + "set(${packageName}_TRIBITS_COMPLIANT_PACKAGE_CONFIG_FILE_DIR \"\${CMAKE_CURRENT_LIST_DIR}\")\n" + ) + set(${packageConfigCodeStrVarInOut} "${packageConfigCodeStr}" PARENT_SCOPE) +endfunction() + + +function(tribits_extpkg_write_package_config_file_from_str tplName configFileStr) + set(buildDirExternalPkgsDir + "${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR}") + set(tplConfigFile + "${buildDirExternalPkgsDir}/${tplName}/${tplName}Config.cmake") + file(WRITE "${tplConfigFile}" "${configFileStr}") +endfunction() \ No newline at end of file diff --git a/cmake/tribits/core/package_arch/tribits_get_version_date.cmake b/cmake/tribits/core/package_arch/tribits_get_version_date.cmake index e40365f0774f..3b941efc4dc9 100644 --- a/cmake/tribits/core/package_arch/tribits_get_version_date.cmake +++ b/cmake/tribits/core/package_arch/tribits_get_version_date.cmake @@ -11,7 +11,7 @@ # -P tribits_get_version_date.cmake # -cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) # A) Validate input diff --git a/cmake/tribits/core/std_tpls/FindTPLMPI.cmake b/cmake/tribits/core/std_tpls/FindTPLMPI.cmake index f4917fd6a050..dd555efd7522 100644 --- a/cmake/tribits/core/std_tpls/FindTPLMPI.cmake +++ b/cmake/tribits/core/std_tpls/FindTPLMPI.cmake @@ -39,9 +39,9 @@ # Either the MPI compiler wrappers take care of these or the user has to set # the explicitly using basic compile flags and ${PROJECT_NAME}_EXTRA_LINK_FLAGS. -global_set(TPL_MPI_INCLUDE_DIRS) -global_set(TPL_MPI_LIBRARIES) -global_set(TPL_MPI_LIBRARY_DIRS) +global_set(TPL_MPI_INCLUDE_DIRS "") +global_set(TPL_MPI_LIBRARIES "") +global_set(TPL_MPI_LIBRARY_DIRS "") if(WIN32 AND TPL_ENABLE_MPI) find_package(MPI) diff --git a/cmake/tribits/ctest_driver/TribitsCTestDriverCore.cmake b/cmake/tribits/ctest_driver/TribitsCTestDriverCore.cmake index 500dd0bf9b0a..563f5de65cb2 100644 --- a/cmake/tribits/ctest_driver/TribitsCTestDriverCore.cmake +++ b/cmake/tribits/ctest_driver/TribitsCTestDriverCore.cmake @@ -50,7 +50,7 @@ message("*******************************") message("") -cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) set(THIS_CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_DIR}") @@ -1290,9 +1290,9 @@ include(TribitsCTestDriverCoreHelpers) # packages and therefore is more robust. But the package-by-package mode is # more expensive in several respects for many projects. # -# For versions of CMake 3.17.0 and above and newer versions of CDash, the -# CDash server for the all-at-once mode will break down build and test results -# on a package-by-package basis on CDash together. +# For newer versions of CDash 3.1+, for the all-at-once mode, the CDash server +# will break down build and test results on a package-by-package basis on +# CDash together. # # .. _Multiple ctest -S invocations (tribits_ctest_driver()): # @@ -2274,8 +2274,9 @@ function(tribits_ctest_driver) select_final_set_of_packages_to_directly_test() # Above sets ${PROJECT_NAME}_PACKAGES_TO_DIRECTLY_TEST - tribits_print_packages_list_enable_status_from_var( ${PROJECT_NAME}_PACKAGES_TO_DIRECTLY_TEST - "\nFinal set of packages to be explicitly processed by CTest/CDash" ON FALSE) + tribits_print_packages_list_enable_status_from_var( + ${PROJECT_NAME}_PACKAGES_TO_DIRECTLY_TEST + "\nFinal set of packages to be explicitly processed by CTest/CDash" "" ON NONEMPTY) message( "\n***" diff --git a/cmake/tribits/ctest_driver/TribitsCTestDriverCoreHelpers.cmake b/cmake/tribits/ctest_driver/TribitsCTestDriverCoreHelpers.cmake index 837ddf05e5f8..08c621ed422c 100644 --- a/cmake/tribits/ctest_driver/TribitsCTestDriverCoreHelpers.cmake +++ b/cmake/tribits/ctest_driver/TribitsCTestDriverCoreHelpers.cmake @@ -513,9 +513,9 @@ macro(enable_only_modified_packages) message("\nDirectly modified or failing non-disabled packages that need" " to be tested: ALL_PACKAGES") else() - tribits_print_internal_package_list_enable_status( + tribits_print_package_list_enable_status( "\nDirectly modified or failing non-disabled packages that need to be tested" - ON FALSE ) + INTERNAL ON NONEMPTY ) endif() endmacro() diff --git a/cmake/tribits/ctest_driver/TribitsGetCTestTestXmlDir.cmake b/cmake/tribits/ctest_driver/TribitsGetCTestTestXmlDir.cmake index 71d54e1df099..1aa1aaf33961 100644 --- a/cmake/tribits/ctest_driver/TribitsGetCTestTestXmlDir.cmake +++ b/cmake/tribits/ctest_driver/TribitsGetCTestTestXmlDir.cmake @@ -14,7 +14,7 @@ # then prints the directory /Testing/ to STDOUT. # -cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) if ("${PROJECT_NAME}" STREQUAL "") message(FATAL_ERROR "Error, PROJECT_NAME must be set!") diff --git a/cmake/tribits/ctest_driver/tribits_ctest_update_commands.cmake b/cmake/tribits/ctest_driver/tribits_ctest_update_commands.cmake index 81c22cc41730..4caf72774e58 100644 --- a/cmake/tribits/ctest_driver/tribits_ctest_update_commands.cmake +++ b/cmake/tribits/ctest_driver/tribits_ctest_update_commands.cmake @@ -18,7 +18,7 @@ # 3.12) crash in that case. # -cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) message("\ncmake -P tribits_ctest_update_commands.cmake:") message("-- GIT_EXE=${GIT_EXE}") diff --git a/cmake/tribits/ctest_driver/tribits_ctest_update_commands_wrapper.cmake b/cmake/tribits/ctest_driver/tribits_ctest_update_commands_wrapper.cmake index 9c18b0d1273b..2c3fcf206c64 100644 --- a/cmake/tribits/ctest_driver/tribits_ctest_update_commands_wrapper.cmake +++ b/cmake/tribits/ctest_driver/tribits_ctest_update_commands_wrapper.cmake @@ -7,7 +7,7 @@ # the output (and does not send it to CDash). # -cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) message("\ncmake -P tribits_ctest_update_commands_wrapper.cmake:") message("-- OUTPUT_FILE=${OUTPUT_FILE}\n") diff --git a/cmake/tribits/devtools_install/0001-CTest-Add-CTEST_RESOURCE_SPEC_FILE-variable.patch b/cmake/tribits/devtools_install/0001-CTest-Add-CTEST_RESOURCE_SPEC_FILE-variable.patch deleted file mode 100644 index ad9103dff286..000000000000 --- a/cmake/tribits/devtools_install/0001-CTest-Add-CTEST_RESOURCE_SPEC_FILE-variable.patch +++ /dev/null @@ -1,377 +0,0 @@ -From 230de4e06240f48715685ea184386d7314137d59 Mon Sep 17 00:00:00 2001 -From: Kyle Edwards -Date: Thu, 2 Apr 2020 16:16:15 -0400 -Subject: [PATCH] CTest: Add CTEST_RESOURCE_SPEC_FILE variable - ---- - Help/manual/cmake-variables.7.rst | 1 + - Help/manual/ctest.1.rst | 8 +++-- - Help/variable/CTEST_RESOURCE_SPEC_FILE.rst | 5 +++ - Source/CTest/cmCTestTestCommand.cxx | 7 ++++ - Source/CTest/cmCTestTestHandler.cxx | 37 +++++++++++++--------- - Source/CTest/cmCTestTestHandler.h | 2 +- - Source/cmLocalGenerator.cxx | 7 ++++ - .../CTestResourceAllocation/RunCMakeTest.cmake | 28 +++++++++------- - .../checkfree1-ctest-s-res-cache-check.cmake | 1 + - .../checkfree1-ctest-s-res-variable-check.cmake | 1 + - .../notenough1-ctest-s-res-cache-check.cmake | 3 ++ - .../notenough1-ctest-s-res-cache-result.txt | 1 + - .../notenough1-ctest-s-res-cache-stderr.txt | 14 ++++++++ - .../notenough1-ctest-s-res-variable-check.cmake | 3 ++ - .../notenough1-ctest-s-res-variable-result.txt | 1 + - .../notenough1-ctest-s-res-variable-stderr.txt | 14 ++++++++ - .../RunCMake/CTestResourceAllocation/test.cmake.in | 14 +++++--- - 17 files changed, 113 insertions(+), 34 deletions(-) - create mode 100644 Help/variable/CTEST_RESOURCE_SPEC_FILE.rst - create mode 100644 Tests/RunCMake/CTestResourceAllocation/checkfree1-ctest-s-res-cache-check.cmake - create mode 100644 Tests/RunCMake/CTestResourceAllocation/checkfree1-ctest-s-res-variable-check.cmake - create mode 100644 Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-cache-check.cmake - create mode 100644 Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-cache-result.txt - create mode 100644 Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-cache-stderr.txt - create mode 100644 Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-variable-check.cmake - create mode 100644 Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-variable-result.txt - create mode 100644 Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-variable-stderr.txt - -diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst -index fc27739..312346d 100644 ---- a/Help/manual/cmake-variables.7.rst -+++ b/Help/manual/cmake-variables.7.rst -@@ -621,6 +621,7 @@ Variables for CTest - /variable/CTEST_P4_COMMAND - /variable/CTEST_P4_OPTIONS - /variable/CTEST_P4_UPDATE_OPTIONS -+ /variable/CTEST_RESOURCE_SPEC_FILE - /variable/CTEST_RUN_CURRENT_SCRIPT - /variable/CTEST_SCP_COMMAND - /variable/CTEST_SITE -diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst -index 6503f0e..f2033b7 100644 ---- a/Help/manual/ctest.1.rst -+++ b/Help/manual/ctest.1.rst -@@ -994,8 +994,12 @@ Configuration settings include: - - ``ResourceSpecFile`` - Specify a -- :ref:`resource specification file `. See -- :ref:`ctest-resource-allocation` for more information. -+ :ref:`resource specification file `. -+ -+ * `CTest Script`_ variable: :variable:`CTEST_RESOURCE_SPEC_FILE` -+ * :module:`CTest` module variable: ``CTEST_RESOURCE_SPEC_FILE`` -+ -+ See :ref:`ctest-resource-allocation` for more information. - - ``LabelsForSubprojects`` - Specify a semicolon-separated list of labels that will be treated as -diff --git a/Help/variable/CTEST_RESOURCE_SPEC_FILE.rst b/Help/variable/CTEST_RESOURCE_SPEC_FILE.rst -new file mode 100644 -index 0000000..59f365f ---- /dev/null -+++ b/Help/variable/CTEST_RESOURCE_SPEC_FILE.rst -@@ -0,0 +1,5 @@ -+CTEST_RESOURCE_SPEC_FILE -+------------------------ -+ -+Specify the CTest ``ResourceSpecFile`` setting in a :manual:`ctest(1)` -+dashboard client script. -diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx -index 0f9b695..c5f683d 100644 ---- a/Source/CTest/cmCTestTestCommand.cxx -+++ b/Source/CTest/cmCTestTestCommand.cxx -@@ -52,6 +52,13 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() - } - } - this->CTest->SetTimeOut(timeout); -+ -+ const char* resourceSpecFile = -+ this->Makefile->GetDefinition("CTEST_RESOURCE_SPEC_FILE"); -+ if (this->ResourceSpecFile.empty() && resourceSpecFile) { -+ this->ResourceSpecFile = resourceSpecFile; -+ } -+ - cmCTestGenericHandler* handler = this->InitializeActualHandler(); - if (!this->Start.empty() || !this->End.empty() || !this->Stride.empty()) { - handler->SetOption( -diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx -index 4f324ea..25d6710 100644 ---- a/Source/CTest/cmCTestTestHandler.cxx -+++ b/Source/CTest/cmCTestTestHandler.cxx -@@ -406,7 +406,9 @@ int cmCTestTestHandler::ProcessHandler() - // start the real time clock - auto clock_start = std::chrono::steady_clock::now(); - -- this->ProcessDirectory(passed, failed); -+ if (!this->ProcessDirectory(passed, failed)) { -+ return -1; -+ } - - auto clock_finish = std::chrono::steady_clock::now(); - -@@ -543,22 +545,11 @@ bool cmCTestTestHandler::ProcessOptions() - if (val) { - this->ExcludeFixtureCleanupRegExp = val; - } -- this->SetRerunFailed(cmIsOn(this->GetOption("RerunFailed"))); -- - val = this->GetOption("ResourceSpecFile"); - if (val) { -- this->UseResourceSpec = true; - this->ResourceSpecFile = val; -- auto result = this->ResourceSpec.ReadFromJSONFile(val); -- if (result != cmCTestResourceSpec::ReadFileResult::READ_OK) { -- cmCTestLog(this->CTest, ERROR_MESSAGE, -- "Could not read/parse resource spec file " -- << val << ": " -- << cmCTestResourceSpec::ResultToString(result) -- << std::endl); -- return false; -- } - } -+ this->SetRerunFailed(cmIsOn(this->GetOption("RerunFailed"))); - - return true; - } -@@ -1259,7 +1250,7 @@ bool cmCTestTestHandler::GetValue(const char* tag, std::string& value, - return ret; - } - --void cmCTestTestHandler::ProcessDirectory(std::vector& passed, -+bool cmCTestTestHandler::ProcessDirectory(std::vector& passed, - std::vector& failed) - { - this->ComputeTestList(); -@@ -1283,7 +1274,17 @@ void cmCTestTestHandler::ProcessDirectory(std::vector& passed, - } else { - parallel->SetTestLoad(this->CTest->GetTestLoad()); - } -- if (this->UseResourceSpec) { -+ if (!this->ResourceSpecFile.empty()) { -+ this->UseResourceSpec = true; -+ auto result = this->ResourceSpec.ReadFromJSONFile(this->ResourceSpecFile); -+ if (result != cmCTestResourceSpec::ReadFileResult::READ_OK) { -+ cmCTestLog(this->CTest, ERROR_MESSAGE, -+ "Could not read/parse resource spec file " -+ << this->ResourceSpecFile << ": " -+ << cmCTestResourceSpec::ResultToString(result) -+ << std::endl); -+ return false; -+ } - parallel->InitResourceAllocator(this->ResourceSpec); - } - -@@ -1344,6 +1345,8 @@ void cmCTestTestHandler::ProcessDirectory(std::vector& passed, - this->ElapsedTestingTime = - std::chrono::steady_clock::now() - elapsed_time_start; - *this->LogFile << "End testing: " << this->CTest->CurrentTime() << std::endl; -+ -+ return true; - } - - void cmCTestTestHandler::GenerateTestCommand( -@@ -1742,6 +1745,10 @@ void cmCTestTestHandler::GetListOfTests() - if (cmSystemTools::GetErrorOccuredFlag()) { - return; - } -+ const char* specFile = mf.GetDefinition("CTEST_RESOURCE_SPEC_FILE"); -+ if (this->ResourceSpecFile.empty() && specFile) { -+ this->ResourceSpecFile = specFile; -+ } - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, - "Done constructing a list of tests" << std::endl, - this->Quiet); -diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h -index b1c8755..bb41c79 100644 ---- a/Source/CTest/cmCTestTestHandler.h -+++ b/Source/CTest/cmCTestTestHandler.h -@@ -278,7 +278,7 @@ private: - /** - * Run the tests for a directory and any subdirectories - */ -- void ProcessDirectory(std::vector& passed, -+ bool ProcessDirectory(std::vector& passed, - std::vector& failed); - - /** -diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx -index cf6802d..5e78911 100644 ---- a/Source/cmLocalGenerator.cxx -+++ b/Source/cmLocalGenerator.cxx -@@ -299,6 +299,13 @@ void cmLocalGenerator::GenerateTestFiles() - << "# testing this directory and lists subdirectories to " - << "be tested as well." << std::endl; - -+ std::string resourceSpecFile = -+ this->Makefile->GetSafeDefinition("CTEST_RESOURCE_SPEC_FILE"); -+ if (!resourceSpecFile.empty()) { -+ fout << "set(CTEST_RESOURCE_SPEC_FILE \"" << resourceSpecFile << "\")" -+ << std::endl; -+ } -+ - const char* testIncludeFile = - this->Makefile->GetProperty("TEST_INCLUDE_FILE"); - if (testIncludeFile) { -diff --git a/Tests/RunCMake/CTestResourceAllocation/RunCMakeTest.cmake b/Tests/RunCMake/CTestResourceAllocation/RunCMakeTest.cmake -index 8584786..777f192 100644 ---- a/Tests/RunCMake/CTestResourceAllocation/RunCMakeTest.cmake -+++ b/Tests/RunCMake/CTestResourceAllocation/RunCMakeTest.cmake -@@ -140,9 +140,13 @@ run_ctresalloc_verify(ctresalloc-verify-noend "test1") - # Now test the resource allocation feature of CTest - ############################################################################### - --function(run_ctest_resource name parallel random) -- run_ctest("${name}-ctest-s-res" "-DCTEST_RESOURCE_ALLOC_ENABLED=1" "-DCTRESALLOC_COMMAND=${CTRESALLOC_COMMAND}" "-DCTEST_PARALLEL=${parallel}" "-DCTEST_RANDOM=${random}") -- run_ctest("${name}-ctest-s-nores" "-DCTEST_RESOURCE_ALLOC_ENABLED=0" "-DCTRESALLOC_COMMAND=${CTRESALLOC_COMMAND}" "-DCTEST_PARALLEL=${parallel}" "-DCTEST_RANDOM=${random}") -+function(run_ctest_resource name parallel random extra) -+ run_ctest("${name}-ctest-s-res" "-DCTEST_RESOURCE_ALLOC_ENABLED=1" "-DCTEST_RESOURCE_SPEC_SOURCE=ARG" "-DCTRESALLOC_COMMAND=${CTRESALLOC_COMMAND}" "-DCTEST_PARALLEL=${parallel}" "-DCTEST_RANDOM=${random}") -+ run_ctest("${name}-ctest-s-nores" "-DCTEST_RESOURCE_ALLOC_ENABLED=0" "-DCTEST_RESOURCE_SPEC_SOURCE=NONE" "-DCTRESALLOC_COMMAND=${CTRESALLOC_COMMAND}" "-DCTEST_PARALLEL=${parallel}" "-DCTEST_RANDOM=${random}") -+ if(extra) -+ run_ctest("${name}-ctest-s-res-variable" "-DCTEST_RESOURCE_ALLOC_ENABLED=1" "-DCTEST_RESOURCE_SPEC_SOURCE=VARIABLE" "-DCTRESALLOC_COMMAND=${CTRESALLOC_COMMAND}" "-DCTEST_PARALLEL=${parallel}" "-DCTEST_RANDOM=${random}") -+ run_ctest("${name}-ctest-s-res-cache" "-DCTEST_RESOURCE_ALLOC_ENABLED=1" "-DCTEST_RESOURCE_SPEC_SOURCE=CACHE" "-DCTRESALLOC_COMMAND=${CTRESALLOC_COMMAND}" "-DCTEST_PARALLEL=${parallel}" "-DCTEST_RANDOM=${random}") -+ endif() - endfunction() - - function(verify_ctest_resources) -@@ -155,15 +159,15 @@ function(verify_ctest_resources) - endif() - endfunction() - --run_ctest_resource(lotsoftests 10 1) --run_ctest_resource(checkfree1 2 0) --run_ctest_resource(checkfree2 1 0) --run_ctest_resource(notenough1 1 0) --run_ctest_resource(notenough2 1 0) --run_ctest_resource(notenough3 1 0) --run_ctest_resource(combine 1 0) --run_ctest_resource(ensure_parallel 2 0) -+run_ctest_resource(lotsoftests 10 1 0) -+run_ctest_resource(checkfree1 2 0 1) -+run_ctest_resource(checkfree2 1 0 0) -+run_ctest_resource(notenough1 1 0 1) -+run_ctest_resource(notenough2 1 0 0) -+run_ctest_resource(notenough3 1 0 0) -+run_ctest_resource(combine 1 0 0) -+run_ctest_resource(ensure_parallel 2 0 0) - - set(ENV{CTEST_RESOURCE_GROUP_COUNT} 2) --run_ctest_resource(process_count 1 0) -+run_ctest_resource(process_count 1 0 0) - unset(ENV{CTEST_RESOURCE_GROUP_COUNT}) -diff --git a/Tests/RunCMake/CTestResourceAllocation/checkfree1-ctest-s-res-cache-check.cmake b/Tests/RunCMake/CTestResourceAllocation/checkfree1-ctest-s-res-cache-check.cmake -new file mode 100644 -index 0000000..ceda72e ---- /dev/null -+++ b/Tests/RunCMake/CTestResourceAllocation/checkfree1-ctest-s-res-cache-check.cmake -@@ -0,0 +1 @@ -+verify_ctest_resources() -diff --git a/Tests/RunCMake/CTestResourceAllocation/checkfree1-ctest-s-res-variable-check.cmake b/Tests/RunCMake/CTestResourceAllocation/checkfree1-ctest-s-res-variable-check.cmake -new file mode 100644 -index 0000000..ceda72e ---- /dev/null -+++ b/Tests/RunCMake/CTestResourceAllocation/checkfree1-ctest-s-res-variable-check.cmake -@@ -0,0 +1 @@ -+verify_ctest_resources() -diff --git a/Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-cache-check.cmake b/Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-cache-check.cmake -new file mode 100644 -index 0000000..321e9a2 ---- /dev/null -+++ b/Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-cache-check.cmake -@@ -0,0 +1,3 @@ -+if(EXISTS "${RunCMake_TEST_BINARY_DIR}/ctresalloc.log") -+ set(RunCMake_TEST_FAILED "ctresalloc.log should not exist") -+endif() -diff --git a/Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-cache-result.txt b/Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-cache-result.txt -new file mode 100644 -index 0000000..b57e2de ---- /dev/null -+++ b/Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-cache-result.txt -@@ -0,0 +1 @@ -+(-1|255) -diff --git a/Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-cache-stderr.txt b/Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-cache-stderr.txt -new file mode 100644 -index 0000000..521a34b ---- /dev/null -+++ b/Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-cache-stderr.txt -@@ -0,0 +1,14 @@ -+^Insufficient resources for test Test1: -+ -+ Test requested resources of type 'fluxcapacitors' in the following amounts: -+ 200 slots -+ but only the following units were available: -+ 'outatime': 121 slots -+ -+Resource spec file: -+ -+ [^ -+]*/Tests/RunCMake/CTestResourceAllocation/resspec.json -+CMake Error at [^ -+]*/Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-cache/test\.cmake:[0-9]+ \(message\): -+ Tests did not pass$ -diff --git a/Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-variable-check.cmake b/Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-variable-check.cmake -new file mode 100644 -index 0000000..321e9a2 ---- /dev/null -+++ b/Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-variable-check.cmake -@@ -0,0 +1,3 @@ -+if(EXISTS "${RunCMake_TEST_BINARY_DIR}/ctresalloc.log") -+ set(RunCMake_TEST_FAILED "ctresalloc.log should not exist") -+endif() -diff --git a/Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-variable-result.txt b/Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-variable-result.txt -new file mode 100644 -index 0000000..b57e2de ---- /dev/null -+++ b/Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-variable-result.txt -@@ -0,0 +1 @@ -+(-1|255) -diff --git a/Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-variable-stderr.txt b/Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-variable-stderr.txt -new file mode 100644 -index 0000000..dcf13e0 ---- /dev/null -+++ b/Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-variable-stderr.txt -@@ -0,0 +1,14 @@ -+^Insufficient resources for test Test1: -+ -+ Test requested resources of type 'fluxcapacitors' in the following amounts: -+ 200 slots -+ but only the following units were available: -+ 'outatime': 121 slots -+ -+Resource spec file: -+ -+ [^ -+]*/Tests/RunCMake/CTestResourceAllocation/resspec.json -+CMake Error at [^ -+]*/Tests/RunCMake/CTestResourceAllocation/notenough1-ctest-s-res-variable/test\.cmake:[0-9]+ \(message\): -+ Tests did not pass$ -diff --git a/Tests/RunCMake/CTestResourceAllocation/test.cmake.in b/Tests/RunCMake/CTestResourceAllocation/test.cmake.in -index 4b426f1..54eb4e9 100644 ---- a/Tests/RunCMake/CTestResourceAllocation/test.cmake.in -+++ b/Tests/RunCMake/CTestResourceAllocation/test.cmake.in -@@ -8,15 +8,21 @@ set(CTEST_CMAKE_GENERATOR_TOOLSET "@RunCMake_GENERATOR_TOOLSET@") - set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") - set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC") - --ctest_start(Experimental QUIET) --ctest_configure(OPTIONS -+set(config_options - "-DCTEST_RESOURCE_ALLOC_ENABLED=${CTEST_RESOURCE_ALLOC_ENABLED};-DCTRESALLOC_COMMAND=${CTRESALLOC_COMMAND}" - ) --ctest_build() - --if(CTEST_RESOURCE_ALLOC_ENABLED) -+if(CTEST_RESOURCE_SPEC_SOURCE STREQUAL "ARG") - set(resspec RESOURCE_SPEC_FILE "@RunCMake_SOURCE_DIR@/resspec.json") -+elseif(CTEST_RESOURCE_SPEC_SOURCE STREQUAL "VARIABLE") -+ set(CTEST_RESOURCE_SPEC_FILE "@RunCMake_SOURCE_DIR@/resspec.json") -+elseif(CTEST_RESOURCE_SPEC_SOURCE STREQUAL "CACHE") -+ list(APPEND config_options "-DCTEST_RESOURCE_SPEC_FILE=@RunCMake_SOURCE_DIR@/resspec.json") - endif() -+ -+ctest_start(Experimental QUIET) -+ctest_configure(OPTIONS "${config_options}") -+ctest_build() - ctest_test(${resspec} RETURN_VALUE retval PARALLEL_LEVEL ${CTEST_PARALLEL} SCHEDULE_RANDOM ${CTEST_RANDOM}) - if(retval) - message(FATAL_ERROR "Tests did not pass") --- -2.7.4 - diff --git a/cmake/tribits/devtools_install/install-cmake.py b/cmake/tribits/devtools_install/install-cmake.py index 5b5b48ea76bf..795d2b29e673 100755 --- a/cmake/tribits/devtools_install/install-cmake.py +++ b/cmake/tribits/devtools_install/install-cmake.py @@ -45,7 +45,7 @@ # cmakeBaseName = "cmake" -cmakeDefaultVersion = "3.17.4" +cmakeDefaultVersion = "3.23.4" # @@ -106,9 +106,6 @@ def getExtraHelpStr(self, version): when doing the configure. Therefore, this builds and installs an optimized version of CMake by default. -If CMake 3.17 is selected, a patch is applied which adds the CTEST_RESOURCE_SPEC_FILE -variable. (For versions 3.18+ this is not needed.) - NOTE: To install CMake from the tip of a branch such as 'master', one must override the 'download' command and eliminate the 'untar' command. One must stick with the directory structure that is assumed by the underlying code @@ -183,9 +180,6 @@ def doUntar(self): createDir(self.cmakeSrcDir, verbose=True) echoRunSysCmnd("tar -xzf "+self.cmakeTarball \ +" -C "+self.cmakeSrcDir+" --strip-components 1") - if self.inOptions.version.startswith("3.17"): - echoRunSysCmnd("patch -d "+self.cmakeSrcDir+" -p1 -i " \ - +os.path.join(devtools_install_dir, "0001-CTest-Add-CTEST_RESOURCE_SPEC_FILE-variable.patch")) def doConfigure(self): createDir(self.cmakeBuildBaseDir, True, True) diff --git a/cmake/tribits/doc/build_ref/TribitsBuildReferenceBody.rst b/cmake/tribits/doc/build_ref/TribitsBuildReferenceBody.rst index 07f0570a2b6f..a9ab5f74120c 100644 --- a/cmake/tribits/doc/build_ref/TribitsBuildReferenceBody.rst +++ b/cmake/tribits/doc/build_ref/TribitsBuildReferenceBody.rst @@ -75,19 +75,12 @@ back-end build system. It also provides some other nice features like ``ninja -n -d explain`` to show why the build system decides to (re)build the targets that it decides to build. -The Kitware fork of Ninja at: - - https://github.com/Kitware/ninja/releases - -provides releases of Ninja that allows CMake 3.7.0+ to build Fortran code with -Ninja. For example, the Kitware Ninja release ``1.7.2.git.kitware.dyndep-1`` -works with Fortran. As of Ninja 1.10+, Fortran support is part of the -official Google-maintained version of Ninja as can be obtained from: +As of Ninja 1.10+, Fortran support is part of the official GitHub version of +Ninja as can be obtained from: https://github.com/ninja-build/ninja/releases -and as of CMake 3.17+, cmake will recognize native Fortran support for Ninja -1.10+ (see `CMake Ninja Fortran Support`_). +(see `CMake Ninja Fortran Support`_). Ninja is easy to install from source on almost any machine. On Unix/Linux systems it is as simple as ``configure --prefix=``, ``make`` and ``make @@ -1965,6 +1958,81 @@ and module files. Therefore, don't enable this if Fortran code in your project is pulling in module files from TPLs. +Building against pre-installed packages +--------------------------------------- + +The project can build against any pre-installed packages defined in +the project and ignore the internally defined packages. To trigger the enable +of a pre-installed internal package treated as an external package, configure +with:: + + -D TPL_ENABLE_=ON + +That will cause the CMake project to pull in the pre-installed +package ```` as an external package using +``find_package()`` instead of configuring and building the +internally defined ```` package. + +Configuring and building against a pre-installed package treated as an +external packages has several consequences: + +* Any internal packages that are upstream from ```` from an + enabled set of dependencies will also be treated as external packages (and + therefore must be pre-installed as well). + +* The TriBITS package ``Dependencies.cmake`` files for the + ```` package and all of its upstream packages must still + exist and will still be read in by the CMake project and the same + enable/disable logic will be performed as if the packages were being treated + internal. (However, the base ``CMakeLists.txt`` and all of other files for + these internally defined packages being treated as external packages can be + missing and will be ignored.) + +* The same set of enabled and disabled upstream dependencies must be specified + to the CMake project that was used to pre-build and pre-install + these internally defined packages being treated as external packages. + (Otherwise, a configure error will result from the mismatch.) + +* The definition of any TriBITS external packages/TPLs that are enabled + upstream dependencies from any of these internally defined packages being + treated as external packages will be defined by the calls to + ``find_package()`` and will **not** be found again. + +The logic for treating internally defined packages as external packages will +be printed in the CMake configure output in the section ``Adjust the set of +internal and external packages`` with output like:: + + Adjust the set of internal and external packages ... + + -- Treating internal package as EXTERNAL because TPL_ENABLE_=ON + -- Treating internal package as EXTERNAL because downstream package being treated as EXTERNAL + -- NOTE: is indirectly downstream from a TriBITS-compliant external package + -- NOTE: is indirectly downstream from a TriBITS-compliant external package + +All of these internally defined being treated as external (and all of their +upstream dependencies) are processed in a loop over these just these +TriBITS-compliant external packages and ``find_package()`` is only called on +the terminal TriBITS-compliant external packages. This is shown in the CMake +output in the section ``Getting information for all enabled TriBITS-compliant +or upstream external packages/TPLs`` and looks like:: + + Getting information for all enabled TriBITS-compliant or upstream external packages/TPLs ... + + Processing enabled external package/TPL: (...) + -- The external package/TPL will be read in by a downstream TriBITS-compliant external package + Processing enabled external package/TPL: (...) + -- The external package/TPL will be read in by a downstream TriBITS-compliant external package + Processing enabled external package/TPL: (...) + -- The external package/TPL will be read in by a downstream TriBITS-compliant external package + Processing enabled external package/TPL: (...) + -- Calling find_package( for TriBITS-compliant external package + +In the above example ````, ```` and ```` are all direct or +indirect dependencies of ```` and therefore calling just +``find_package()`` fully defines those TriBITS-compliant external +packages as well. + + xSDK Configuration Options -------------------------- @@ -2558,11 +2626,6 @@ NOTES: for the ``CTEST_RESOURCE_SPEC_FILE`` cache variable was not added until CMake 3.18.) -* CMake versions 3.18+ can be used to get built-in CMake/CTest support for the - ``CTEST_RESOURCE_SPEC_FILE`` cache variable. This avoids needing to - explicitly pass the ctest resource file to ``ctest`` at runtime for - CMake/CTest versions 3.17.z. - * **WARNING:** This currently only works for a single node, not multiple nodes. (CTest needs to be extended to work correctly for multiple nodes where each node has multiple GPUs. Alternatively, TriBITS could be extended @@ -2816,6 +2879,12 @@ of packages the files are requested for with:: -D _GENERATE_EXPORT_FILES_FOR_ONLY_LISTED_PACKAGES=";" +To only install the package ``Config.cmake`` files and **not** the +project-level ``Config.cmake`` file, configure with:: + + -D _ENABLE_INSTALL_CMAKE_CONFIG_FILES=ON \ + -D _SKIP_INSTALL_PROJECT_CMAKE_CONFIG_FILES=ON \ + NOTES: * Only enabled packages will have their export files generated. @@ -2823,6 +2892,13 @@ NOTES: * One would only want to limit the export files generated for very large projects where the cost my be high for doing so. +* One would want to skip the installation of the project-level + ``Config.cmake`` file in cases where the TriBITS project's packages + may be built in smaller subsets of packages in different individual CMake + project builds where there is no clear completion to the installation of the + packages for a given TriBITS project containing a larger collection of + packages. + Generating a project repo version file -------------------------------------- diff --git a/cmake/tribits/doc/build_ref/create-project-build-ref.py b/cmake/tribits/doc/build_ref/create-project-build-ref.py index b84198824a7f..ce0ee6a92800 100755 --- a/cmake/tribits/doc/build_ref/create-project-build-ref.py +++ b/cmake/tribits/doc/build_ref/create-project-build-ref.py @@ -95,8 +95,8 @@ clp.add_option( "--min-cmake-version", dest="minCMakeVersion", type="string", help="Minimum version of CMake needed for given project" \ - " [Default '3.17.0']", - default="3.17.0" ) + " [Default '3.23.0']", + default="3.23.0" ) GenerateDocUtilsOutput.addCmndLineOptions(clp) diff --git a/cmake/tribits/doc/guides/TribitsCMakeLanguageOverviewAndGotchas.rst b/cmake/tribits/doc/guides/TribitsCMakeLanguageOverviewAndGotchas.rst new file mode 100644 index 000000000000..885229038290 --- /dev/null +++ b/cmake/tribits/doc/guides/TribitsCMakeLanguageOverviewAndGotchas.rst @@ -0,0 +1,238 @@ +CMake Language Overview and Gotchas +----------------------------------- + +TriBITS removes a lot of the boiler plate code needed to write a CMake +project. As a result, many people can come into a project that uses TriBITS +and quickly start to contribute by adding new source files, adding new +libraries, adding new tests, and even adding new TriBITS packages and external +packages/TPLs; all without really having learned anything about CMake. Often +one can use existing example CMake code as a guide and be successful using +basic functionality. As long as nothing out of the ordinary happens, many +people can get along just fine in this mode for a time. + +However, we have observed that most mistakes and problems that people run into when +using TriBITS are due to lack of basic knowledge of the CMake language. One can find +basic tutorials and references on the CMake language in various locations online for free. +One can also purchase the `official CMake reference book`_. Also, documentation +for any built-in CMake command is available locally by running:: + + $ cmake --help-command + +Because tutorials and detailed documentation for the CMake language already +exists, this document does not attempt to provide a first reference to CMake +(which is a large topic in itself). However, what we try to provide below is +a short overview of the more quirky or surprising aspects of the CMake +language that a programmer experienced in another language might get tripped +up or surprised by. Some of the more unique features of the language are +described in order to help avoid some of these common mistakes and provide +greater understanding of how TriBITS works. + +.. _Official CMake reference book: http://www.cmake.org/cmake/help/book.html + +The CMake language is used to write CMake projects with TriBITS. In fact the +core TriBITS functionality itself is implemented in the CMake language (see +`TriBITS System Project Dependencies`_). CMake is a fairly simple programming +language with relatively simple rules (for the most part). However, compared +to other programming languages, there are a few peculiar aspects to the CMake +language that can make working with it difficult if you don't understand these +rules. For example there are unexpected variable scoping rules and how arguments +are passed to macros and functions can be tricky. Also, CMake has some interesting +gotchas. In order to effectively use TriBITS (or just raw CMake) to construct +and maintain a project's CMake files, one must know the basic rules of CMake +and be aware of these gotchas. + +The first thing to understand about the CMake language is that nearly every +line of CMake code is just a command taking a string (or an array of strings) +and functions that operate on strings. An array argument is just a single +string literal with elements separated by semi-colons ``";;..."``. +CMake is a bit odd in how it deals with these arrays, which are just +represented as a string with elements separated with semi-colons ``';'``. For +example, all of the following are equivalent and pass in a CMake array with 3 +elements [``A``], [``B``], and [``C``]:: + + some_func(A B C) + some_func("A" "B" "C") + some_func("A;B;C") + +However, the above is *not* the same as:: + + some_func("A B C") + +which just passes in a single element with value [``A B C``]. Raw quotes in +CMake basically escape the interpretation of space characters as array element +boundaries. Quotes around arguments with no spaces does nothing (as seen +above, except for the interpretation as variable names in an ``if()`` +statement). In order to get a quote char [``"``] into string, you must escape +it as:: + + some_func(\"A\") + +which passes an array with the single argument [``\"A\"``]. + +Variables are set using the built-in CMake ``set()`` command that just takes +string arguments like:: + + set(SOME_VARIABLE "some_value") + +In CMake, the above is identical, in every way, to:: + + set(SOME_VARIABLE some_value) + set("SOME_VARIABLE";"some_value") + set("SOME_VARIABLE;some_value") + +The function ``set()`` simply interprets the first argument to as the name of +a variable to set in the local scope. Many other built-in and user-defined +CMake functions work the same way. That is, some of the string arguments are +interpreted as the names of variables. There is no special language feature +that interprets them as variables (except in an ``if()`` statement). + +However, CMake appears to parse arguments differently for built-in CMake +control structure functions like ``foreach()`` and ``if()`` and does not just +interpret them as a string array. For example:: + + foreach (SOME_VAR "a;b;c") + message("SOME_VAR='${SOME_VAR}'") + endforeach() + +prints ```SOME_VAR='a;b;c'`` instead of printing ``SOME_VAR='a'`` followed by +``SOME_VAR='b'``, etc., as you would otherwise expect. Therefore, this simple +rule for the handling of function arguments as string arrays does not hold for +CMake logic control commands. Just follow the CMake documentation for these +control structures (i.e. see ``cmake --help-command if`` and ``cmake +--help-command foreach``). + +CMake offers a rich assortment of built-in commands for doing all sorts of +things. Two of these are the built-in ``macro()`` and the ``function()`` +commands which allow you to create user-defined macros and functions. TriBITS +is actually built on CMake functions and macros. All of the built-in and +user-defined macros, and some functions take an array of string arguments. +Some functions take in positional arguments. In fact, most functions take a +combination of positional and keyword arguments. + +Variable names are translated into their stored values using +``${SOME_VARIABLE}``. The value that is extracted depends on if the variable +is set in the local or global (cache) scope. The local scopes for CMake start +in the base project directory in its base ``CMakeLists.txt`` file. Any +variables that are created by macros in that base local scope are seen across +an entire project but are *not* persistent across multiple successive +``cmake`` configure invocations where the cache file ``CMakeCache.txt`` is not +deleted in between. + +The handling of variables is one area where CMake is radically different from +most other languages. First, a variable that is not defined simply returns +nothing. What is surprising to most people about this is that it does not +even return an empty string that would register as an array element! For +example, the following set statement:: + + set(SOME_VAR a ${SOME_UNDEFINED_VAR} c) + +(where ``SOME_UNDEFINED_VAR`` is an undefined variable) produces +``SOME_VAR='a;c'`` and *not* ``'a;;c'``! The same thing occurs when an empty +variable is de-references such as with:: + + set(EMPTY_VAR "") + set(SOME_VAR a ${EMPTY_VAR} c) + +which produces ``SOME_VAR='a;c'`` and *not* ``'a;;c'``. In order to always +produce an element in the array even if the variable is empty, one must quote +the argument as with:: + + set(EMPTY_VAR "") + set(SOME_VAR a "${EMPTY_VAR}" c) + +which produces ``SOME_VAR='a;;c'``, or three elements as one might assume. + +This is a common error that people make when they call CMake functions +(built-in or TriBITS-defined) involving variables that might be undefined or +empty. For example, for the macro:: + + macro(some_macro A_ARG B_ARG C_ARG) + ... + endmacro() + +if someone tries to call it with (misspelled variable?):: + + some_macro(a ${SOME_OHTER_VAR} c) + +and if ``SOME_OHTER_VAR=""`` or if it is undefined, then CMake will error out +with the error message saying that the macro ``some_macro()`` takes 3 +arguments but only 2 were provided. If a variable might be empty but that is +still a valid argument to the command, then it must be quoted as:: + + some_macro(a "${SOME_OHTER_VAR}" c) + +Related to this problem is that if you misspell the name of a variable in a +CMake ``if()`` statement like:: + + if (SOME_VARBLE) + ... + endif() + +then it will always be false and the code inside the if statement will never +be executed! To avoid this problem, use the utility function +`assert_defined()`_ as:: + + assert_defined(SOME_VARBLE) + if (SOME_VARBLE) + ... + endif() + +In this case, the misspelled variable would be caught. + +While on the subject of ``if()`` statements, CMake has a strange convention. +When you say:: + + if (SOME_VAR) + do_something() + endif() + +then ``SOME_VAR`` is interpreted as a variable and will be considered true and +``do_something()`` will be called if ``${SOME_VAR}`` does *not* evaluate to +``0``, ``OFF``, ``NO``, ``FALSE``, ``N``, ``IGNORE``, ``""``, or ends in the +suffix ``-NOTFOUND``. How about that for a true/false rule! To be safe, use +``ON/OFF`` and ``TRUE/FALSE`` pairs for setting variables. Look up native +CMake documentation on ``if()`` for all the interesting details and all the +magical things it can do. + +**WARNING:** If you mistype ``"ON"`` as ``"NO"``, it evaluates to +``FALSE``/``OFF``! (That is a fun defect to track down!) + +CMake language behavior with respect to case sensitivity is also strange: + +* Calls of built-in and user-defined macros and functions is *case + insensitive*! That is ``set(...)``, ``set(...)``, ``set()``, and all other + combinations of upper and lower case characters for 'S', 'E', 'T' all call + the built-in ``set()`` function. The convention in TriBITS is to use + ``lower_case_with_underscores()`` for functions and macros. + +* However, the names of CMake (local or cache/global) variables are *case + sensitive*! That is, ``SOME_VAR`` and ``some_var`` are *different* + variables. Built-in CMake variables tend use all caps with underscores + (e.g. ``CMAKE_CURRENT_SOURCE_DIR``) but other built-in CMake variables tend + to use mixed case with underscores (e.g. ``CMAKE_Fortran_FLAGS``). TriBITS + tends to use a similar naming convention where project-level and cache + variables have mostly upper-case letters except for parts that are proper + nouns like the project, package or external package/TPL name + (e.g. ``TribitsExProj_TRIBITS_DIR``, ``TriBITS_SOURCE_DIR``, + ``Boost_INCLUDE_DIRS``). Local variables and function/macro parameters can + use camelCase or lower_case_with_underscores. + +I don't know of any other programming language that uses different case +sensitivity rules for variables and functions. However, because we must parse +macro and function arguments when writing user-defined macros and functions, +it is a good thing that CMake variables are case sensitive. Case insensitivity +would make it much harder and more expensive to parse argument lists that take +keyword-based arguments. + +Other mistakes that people make result from not understanding how CMake scopes +variables and other entities. CMake defines a global scope (i.e. "cache" +variables) and several nested local scopes that are created by +``add_subdirectory()`` and entering functions. See `dual_scope_set()`_ for a +short discussion of these scoping rules. And it is not just variables that +can have local and global scoping rules. Other entities, like defines set +with the built-in command ``add_definitions()`` only apply to the local scope +and child scopes. That means that if you call ``add_definitions()`` to set a +define that affects the meaning of a header-file in C or C++, for example, +that definition will *not* carry over to a peer subdirectory and those +definitions will not be set (see warning in `Miscellaneous Notes +(tribits_add_library())`_). diff --git a/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst b/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst index 2cc0fb95e97d..50a90c79aca5 100644 --- a/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst +++ b/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst @@ -89,6 +89,7 @@ a given TriBITS project are: * `${PROJECT_NAME}_REQUIRES_PYTHON`_ * `${PROJECT_NAME}_SET_INSTALL_RPATH`_ * `${PROJECT_NAME}_SHOW_TEST_START_END_DATE_TIME`_ +* `${PROJECT_NAME}_SKIP_INSTALL_PROJECT_CMAKE_CONFIG_FILES`_ * `${PROJECT_NAME}_TEST_CATEGORIES`_ * `${PROJECT_NAME}_TPL_SYSTEM_INCLUDE_DIRS`_ * `${PROJECT_NAME}_TRACE_ADD_TEST`_ @@ -671,6 +672,19 @@ These options are described below. date/time for regular tests added with `tribits_add_test()`_ (which uses a raw command with ``add_test()``). +.. _${PROJECT_NAME}_SKIP_INSTALL_PROJECT_CMAKE_CONFIG_FILES: + +**${PROJECT_NAME}_SKIP_INSTALL_PROJECT_CMAKE_CONFIG_FILES** + + To change the default value of the + ``${PROJECT_NAME}_SKIP_INSTALL_PROJECT_CMAKE_CONFIG_FILES`` to ``TRUE``, for + example, for a TriBITS project, set:: + + set(${PROJECT_NAME}_SKIP_INSTALL_PROJECT_CMAKE_CONFIG_FILES_DEFAULT TRUE) + + in the project's `/CMakeLists.txt`_ or + `/ProjectName.cmake`_ files. + .. _${PROJECT_NAME}_SKIP_EXTRAREPOS_FILE: **${PROJECT_NAME}_SKIP_EXTRAREPOS_FILE** diff --git a/cmake/tribits/doc/guides/TribitsGuidesBody.rst b/cmake/tribits/doc/guides/TribitsGuidesBody.rst index 3b790406c7bc..0cbcf2c5a98a 100644 --- a/cmake/tribits/doc/guides/TribitsGuidesBody.rst +++ b/cmake/tribits/doc/guides/TribitsGuidesBody.rst @@ -110,259 +110,21 @@ may not be necessary and the `TriBITS Overview`_ or the above roles and discussion help the reader select the right document to start with. +NOTE: Before getting started with TriBITS, if a reader is unfamiliar with +CMake, please review the `CMake Language Overview and Gotchas`_. Once those +CMake basics and common gotchas have been reviewed, we now get into the meat +of TriBITS starting with software engineering principles that lie at the +foundation of TriBITS. That is followed by with and overall of the structure +of a TriBITS project. -CMake Language Overview and Gotchas ------------------------------------ - -TriBITS removes a lot of the boiler plate code needed to write a CMake -project. As a result, many people can come into a project that uses TriBITS -and quickly start to contribute by adding new source files, adding new -libraries, adding new tests, and even adding new TriBITS packages and external -packages/TPLs; all without really having learned anything about CMake. Often -one can use existing example CMake code as a guide and be successful using -basic functionality. As long as nothing out of the ordinary happens, many -people can get along just fine in this mode for a time. - -However, we have observed that most mistakes and problems that people run into when -using TriBITS are due to lack of basic knowledge of the CMake language. One can find -basic tutorials and references on the CMake language in various locations online for free. -One can also purchase the `official CMake reference book`_. Also, documentation -for any built-in CMake command is available locally by running:: - - $ cmake --help-command - -Because tutorials and detailed documentation for the CMake language already -exists, this document does not attempt to provide a first reference to CMake -(which is a large topic in itself). However, what we try to provide below is -a short overview of the more quirky or surprising aspects of the CMake -language that a programmer experienced in another language might get tripped -up or surprised by. Some of the more unique features of the language are -described in order to help avoid some of these common mistakes and provide -greater understanding of how TriBITS works. - -.. _Official CMake reference book: http://www.cmake.org/cmake/help/book.html - -The CMake language is used to write CMake projects with TriBITS. In fact the -core TriBITS functionality itself is implemented in the CMake language (see -`TriBITS System Project Dependencies`_). CMake is a fairly simple programming -language with relatively simple rules (for the most part). However, compared -to other programming languages, there are a few peculiar aspects to the CMake -language that can make working with it difficult if you don't understand these -rules. For example there are unexpected variable scoping rules and how arguments -are passed to macros and functions can be tricky. Also, CMake has some interesting -gotchas. In order to effectively use TriBITS (or just raw CMake) to construct -and maintain a project's CMake files, one must know the basic rules of CMake -and be aware of these gotchas. - -The first thing to understand about the CMake language is that nearly every -line of CMake code is just a command taking a string (or an array of strings) -and functions that operate on strings. An array argument is just a single -string literal with elements separated by semi-colons ``";;..."``. -CMake is a bit odd in how it deals with these arrays, which are just -represented as a string with elements separated with semi-colons ``';'``. For -example, all of the following are equivalent and pass in a CMake array with 3 -elements [``A``], [``B``], and [``C``]:: - - some_func(A B C) - some_func("A" "B" "C") - some_func("A;B;C") - -However, the above is *not* the same as:: - - some_func("A B C") - -which just passes in a single element with value [``A B C``]. Raw quotes in -CMake basically escape the interpretation of space characters as array element -boundaries. Quotes around arguments with no spaces does nothing (as seen -above, except for the interpretation as variable names in an ``if()`` -statement). In order to get a quote char [``"``] into string, you must escape -it as:: - - some_func(\"A\") - -which passes an array with the single argument [``\"A\"``]. - -Variables are set using the built-in CMake ``set()`` command that just takes -string arguments like:: - - set(SOME_VARIABLE "some_value") - -In CMake, the above is identical, in every way, to:: - - set(SOME_VARIABLE some_value) - set("SOME_VARIABLE";"some_value") - set("SOME_VARIABLE;some_value") - -The function ``set()`` simply interprets the first argument to as the name of -a variable to set in the local scope. Many other built-in and user-defined -CMake functions work the same way. That is, some of the string arguments are -interpreted as the names of variables. There is no special language feature -that interprets them as variables (except in an ``if()`` statement). - -However, CMake appears to parse arguments differently for built-in CMake -control structure functions like ``foreach()`` and ``if()`` and does not just -interpret them as a string array. For example:: - - foreach (SOME_VAR "a;b;c") - message("SOME_VAR='${SOME_VAR}'") - endforeach() - -prints ```SOME_VAR='a;b;c'`` instead of printing ``SOME_VAR='a'`` followed by -``SOME_VAR='b'``, etc., as you would otherwise expect. Therefore, this simple -rule for the handling of function arguments as string arrays does not hold for -CMake logic control commands. Just follow the CMake documentation for these -control structures (i.e. see ``cmake --help-command if`` and ``cmake ---help-command foreach``). - -CMake offers a rich assortment of built-in commands for doing all sorts of -things. Two of these are the built-in ``macro()`` and the ``function()`` -commands which allow you to create user-defined macros and functions. TriBITS -is actually built on CMake functions and macros. All of the built-in and -user-defined macros, and some functions take an array of string arguments. -Some functions take in positional arguments. In fact, most functions take a -combination of positional and keyword arguments. - -Variable names are translated into their stored values using -``${SOME_VARIABLE}``. The value that is extracted depends on if the variable -is set in the local or global (cache) scope. The local scopes for CMake start -in the base project directory in its base ``CMakeLists.txt`` file. Any -variables that are created by macros in that base local scope are seen across -an entire project but are *not* persistent across multiple successive -``cmake`` configure invocations where the cache file ``CMakeCache.txt`` is not -deleted in between. - -The handling of variables is one area where CMake is radically different from -most other languages. First, a variable that is not defined simply returns -nothing. What is surprising to most people about this is that it does not -even return an empty string that would register as an array element! For -example, the following set statement:: - - set(SOME_VAR a ${SOME_UNDEFINED_VAR} c) - -(where ``SOME_UNDEFINED_VAR`` is an undefined variable) produces -``SOME_VAR='a;c'`` and *not* ``'a;;c'``! The same thing occurs when an empty -variable is de-references such as with:: - - set(EMPTY_VAR "") - set(SOME_VAR a ${EMPTY_VAR} c) - -which produces ``SOME_VAR='a;c'`` and *not* ``'a;;c'``. In order to always -produce an element in the array even if the variable is empty, one must quote -the argument as with:: - - set(EMPTY_VAR "") - set(SOME_VAR a "${EMPTY_VAR}" c) - -which produces ``SOME_VAR='a;;c'``, or three elements as one might assume. - -This is a common error that people make when they call CMake functions -(built-in or TriBITS-defined) involving variables that might be undefined or -empty. For example, for the macro:: - - macro(some_macro A_ARG B_ARG C_ARG) - ... - endmacro() - -if someone tries to call it with (misspelled variable?):: - - some_macro(a ${SOME_OHTER_VAR} c) - -and if ``SOME_OHTER_VAR=""`` or if it is undefined, then CMake will error out -with the error message saying that the macro ``some_macro()`` takes 3 -arguments but only 2 were provided. If a variable might be empty but that is -still a valid argument to the command, then it must be quoted as:: - - some_macro(a "${SOME_OHTER_VAR}" c) - -Related to this problem is that if you misspell the name of a variable in a -CMake ``if()`` statement like:: - - if (SOME_VARBLE) - ... - endif() - -then it will always be false and the code inside the if statement will never -be executed! To avoid this problem, use the utility function -`assert_defined()`_ as:: - - assert_defined(SOME_VARBLE) - if (SOME_VARBLE) - ... - endif() - -In this case, the misspelled variable would be caught. - -While on the subject of ``if()`` statements, CMake has a strange convention. -When you say:: - - if (SOME_VAR) - do_something() - endif() - -then ``SOME_VAR`` is interpreted as a variable and will be considered true and -``do_something()`` will be called if ``${SOME_VAR}`` does *not* evaluate to -``0``, ``OFF``, ``NO``, ``FALSE``, ``N``, ``IGNORE``, ``""``, or ends in the -suffix ``-NOTFOUND``. How about that for a true/false rule! To be safe, use -``ON/OFF`` and ``TRUE/FALSE`` pairs for setting variables. Look up native -CMake documentation on ``if()`` for all the interesting details and all the -magical things it can do. - -**WARNING:** If you mistype ``"ON"`` as ``"NO"``, it evaluates to -``FALSE``/``OFF``! (That is a fun defect to track down!) - -CMake language behavior with respect to case sensitivity is also strange: - -* Calls of built-in and user-defined macros and functions is *case - insensitive*! That is ``set(...)``, ``set(...)``, ``set()``, and all other - combinations of upper and lower case characters for 'S', 'E', 'T' all call - the built-in ``set()`` function. The convention in TriBITS is to use - ``lower_case_with_underscores()`` for functions and macros. - -* However, the names of CMake (local or cache/global) variables are *case - sensitive*! That is, ``SOME_VAR`` and ``some_var`` are *different* - variables. Built-in CMake variables tend use all caps with underscores - (e.g. ``CMAKE_CURRENT_SOURCE_DIR``) but other built-in CMake variables tend - to use mixed case with underscores (e.g. ``CMAKE_Fortran_FLAGS``). TriBITS - tends to use a similar naming convention where project-level and cache - variables have mostly upper-case letters except for parts that are proper - nouns like the project, package or external package/TPL name - (e.g. ``TribitsExProj_TRIBITS_DIR``, ``TriBITS_SOURCE_DIR``, - ``Boost_INCLUDE_DIRS``). Local variables and function/macro parameters can - use camelCase or lower_case_with_underscores. - -I don't know of any other programming language that uses different case -sensitivity rules for variables and functions. However, because we must parse -macro and function arguments when writing user-defined macros and functions, -it is a good thing that CMake variables are case sensitive. Case insensitivity -would make it much harder and more expensive to parse argument lists that take -keyword-based arguments. - -Other mistakes that people make result from not understanding how CMake scopes -variables and other entities. CMake defines a global scope (i.e. "cache" -variables) and several nested local scopes that are created by -``add_subdirectory()`` and entering functions. See `dual_scope_set()`_ for a -short discussion of these scoping rules. And it is not just variables that -can have local and global scoping rules. Other entities, like defines set -with the built-in command ``add_definitions()`` only apply to the local scope -and child scopes. That means that if you call ``add_definitions()`` to set a -define that affects the meaning of a header-file in C or C++, for example, -that definition will *not* carry over to a peer subdirectory and those -definitions will not be set (see warning in `Miscellaneous Notes -(tribits_add_library())`_). - -Now that some CMake basics and common gotchas have been reviewed, we now get -into the meat of TriBITS starting with the overall structure of a TriBITS -project in the next section. Software Engineering Packaging Principles ----------------------------------------- -The term "software engineering" package is adopted in TriBITS nomenclature in -order to highlight and the role of defining and managing "Packages" according -to standard software engineering packaging principles. In his book [`Agile -Software Development, 2003`_], Robert Martin defines several object-oriented -(OO) software engineering principles related to packaging software which are -listed below: +The design of TriBITS takes into account standard software engineering +packaging principles. In his book [`Agile Software Development, 2003`_], +Robert Martin defines several software engineering principles related to +packaging software which are listed below: * *Package Cohesion OO Principles*: @@ -398,6 +160,7 @@ further. However, interested readers are strongly encouraged to read [`Agile Software Development, 2003`_] as one of the better software engineering books out there (see https://bartlettroscoe.github.io/reading-list/#most_recommended_se_books). + TriBITS Project Structure ========================= @@ -472,7 +235,7 @@ units are: Packages`_. A modern TriBITS external package/TPL (Third Party Library) is typically just a small file ``FindTPL.cmake`` that calls ``find_package()`` and defines the ``::all_libs`` - target. More generally, an external package/TPL can be specificed as a list + target. More generally, an external package/TPL can be specified as a list list of libraries and/or include directories for header files. Examples of basic external packages/TPLs include ``BLAS``, ``LAPACK``, and ``Boost``. @@ -714,7 +477,7 @@ the variable ``TRIBITS_CMAKE_MINIMUM_REQUIRED`` (the current minimum version of CMake required by TriBITS is given at in `Getting set up to use CMake`_) . For example, the ``VERA/CMakeLists.txt`` file lists as its first line:: - set(VERA_TRIBITS_CMAKE_MINIMUM_REQUIRED 3.17.0) + set(VERA_TRIBITS_CMAKE_MINIMUM_REQUIRED 3.23.0) cmake_minimum_required(VERSION ${VERA_TRIBITS_CMAKE_MINIMUM_REQUIRED} FATAL_ERROR) @@ -1798,6 +1561,17 @@ defined: what contexts the package is enabled or not for testing-related purposes (see `Nested Layers of TriBITS Project Testing`_) + .. _${PACKAGE_NAME}_SUBPACKAGES: + + ``${PACKAGE_NAME}_SUBPACKAGES`` + + Defines the list of subpackage names for a top-level parent package. This + gives the unique subpackage name without the parent package prefix. For + example, the `ReducedMockTrilinos`_ package ``Thyra`` has the subpackages + ``CoreLibs``, ``GoodStuff``, etc. (which forms the full package names + ``ThyraCoreLibs``, ``ThyraGoodStuff``, etc.). If a top-level package is + not broken down into subpackages, then this list is empty. + .. _TriBITS Package Cache Variables: In addition, the following user-settable **TriBITS Package Cache Variables** @@ -1809,7 +1583,7 @@ are defined before a Package's ``CMakeLists.txt`` file is processed: Set to ``ON`` if the package is enabled and is to be processed or will be set to ``ON`` or ``OFF`` automatically during enable/disable logic. For a - parent package that is not directly enabled but were one of its + parent package that is not directly enabled but where one of its subpackages is enabled, this will get set to ``ON`` (but that is not the same as the parent package being directly enabled and therefore does not imply that all of the required subpackages will be enabled, only that the @@ -1841,6 +1615,10 @@ are defined before a Package's ``CMakeLists.txt`` file is processed: `${PACKAGE_NAME}_LIB_DEFINED_DEPENDENCIES`_ or `${PACKAGE_NAME}_TEST_DEFINED_DEPENDENCIES`_. + **NOTE:** The value of this variable also determines the value of the + macro define variable name + `HAVE__`_. + .. _${PACKAGE_NAME}_ENABLE_TESTS: ``${PACKAGE_NAME}_ENABLE_TESTS`` @@ -1889,6 +1667,13 @@ are defined in the top-level project scope before a Package's #cmakedefine HAVE_EPETRAEXT_TRIUTILS + NOTE: TriBITS automatically sets this variable depending on the value of + `${PACKAGE_NAME}_ENABLE_${OPTIONAL_DEP_PACKAGE_NAME}`_ during the step + "Adjust package and TPLs enables and disables" in `Full Processing of + TriBITS Project Files`_. And tweaking this variable after that must be + done carefully as described in `How to tweak downstream TriBITS "ENABLE" + variables during package configuration`_. + Currently, a Package can refer to its containing Repository and refer to its source and binary directories. This is so that it can refer to repository-level resources (e.g. like the ``Trilinos_version.h`` file for @@ -2144,10 +1929,11 @@ A *TriBITS External Package/TPL*: interface to one or more downstream TriBITS Packages. * Has a globally unique name ```` (see `Globally unique TriBITS TPL names`_) that is declared in a `/TPLsList.cmake`_ file. -* Has as `FindTPL.cmake`_ module that finds the pieces of an external - package/TPL and provides them to downstream packages through a required - INTERFACE target ``::all_libs`` (which gives the libraries, include - directories, and other usage requirements). +* Has as `FindTPL.cmake`_ module (for non-`TriBITS-Compliant External + Packages`_) that finds the pieces of an external package/TPL and provides + them to downstream packages through a required INTERFACE target + ``::all_libs`` (which gives the libraries, include directories, and + other usage requirements, see `TriBITS-Compliant External Package`_). * Is listed as an explicit optional or required dependency in one or more downstream TriBITS packages' `/cmake/Dependencies.cmake`_ files. * Can be enabled automatically or can trigger the disable of dependent @@ -2166,6 +1952,14 @@ if an external package/TPL is explicitly disabled, all of the downstream packages that depend on it will be automatically disabled as well (see `Package disable triggers auto-disables of downstream dependencies`_). +NOTE: The TriBITS TPL system implements a mechanism to turn external +dependencies into both `TriBITS-compliant packages`_ for consumption by +downstream TriBITS internal packages and also writes ``Config.cmake`` +files that are `TriBITS-compliant external packages`_ for consumption by +downstream ``Config.cmake`` files (which are `TriBITS-compliant +external packages`_) generated by `TriBITS-compliant internal packages`_. + + .. _Globally unique TriBITS TPL names: **WARNING:** One must be very careful to pick **Globally unique TriBITS @@ -2202,12 +1996,13 @@ below: .. _FindTPL.cmake: .. _/FindTPL.cmake: -**/FindTPL.cmake**: [Required] Defines how an external -package/TPL is found and provided for usage by a downstream TriBITS package by -providing the ``::all_libs`` target and a package config file -``Config.cmake`` that also defines the target -``::all_libs``. (The requirements for a ``FindTPL.cmake`` -file are given in `Requirements for FindTPL.cmake modules`_). +**/FindTPL.cmake**: [Required] *TriBITS TPL find module* +that defines how a TriBITS external package/TPL is found and provided for +usage by a downstream TriBITS package. This module must provide the +``::all_libs`` target and must create a `TriBITS-compliant external +package`_ wrapper package config file ``Config.cmake``. (See the +requirements for a ``FindTPL.cmake`` file in `Requirements for +FindTPL.cmake modules`_). The form of a simple ``FindTPL.cmake`` file that uses an internal call to ``find_package()`` which provides modern IMPORTED CMake @@ -2223,7 +2018,8 @@ In this case, the purpose for the ``FindTPL.cmake`` file (as apposed to a direct call to ``find_package()``) is to ensure the definition of the complete target ``::all_libs`` which contains all usage requirements for the external package/TPL (i.e. all of the libraries, -include directories, etc.). +include directories, etc.) and this also generates the wrapper package config +file ``Config.cmake``. The form of a simple ``FindTPL.cmake`` file that just provides a list of required header files and libraries that does **not** use an internal call @@ -2287,16 +2083,20 @@ defined TPL ``TPL_NAME`` is assigned the following global non-cache variables: ``${TPL_NAME}_FINDMOD`` - Relative path (w.r.t. ````) or absolute path for the external - package/TPL's find module (typically named `FindTPL.cmake`_): - This is set using the ``FINDMOD`` field in the call to - `tribits_repository_define_tpls()`_. The final value of the variable is - defined by the *last* `/TPLsList.cmake`_ file that is processed - that declares the TPL ``TPL_NAME``. For example, if - ``Repo1/TPLsList.cmake`` and ``Repo2/TPLsList.cmake`` both list the TPL - ``SomeTpl``, then if ``Repo2`` is processed after ``Repo1``, then - ``SomeTpl_FINDMOD`` is determined by ``Repo2/TPLsList.cmake`` and the find - module listed in ``Repo1/TPLsList.cmake`` is ignored. + For a **non-** `TriBITS-compliant external package`_, this is the relative + path (w.r.t. ````) or absolute path for the *TriBITS TPL find + module* (typically named `FindTPL.cmake`_). This is set using the + ``FINDMOD`` field in the call to `tribits_repository_define_tpls()`_. The + final value of the variable is defined by the **last** + `/TPLsList.cmake`_ file that is processed that declares the TPL + ``TPL_NAME``. For example, if ``Repo1/TPLsList.cmake`` and + ``Repo2/TPLsList.cmake`` both list the TPL ``SomeTpl``, then if ``Repo2`` + is processed after ``Repo1``, then ``SomeTpl_FINDMOD`` is determined by + ``Repo2/TPLsList.cmake`` and the find module listed in + ``Repo1/TPLsList.cmake`` is ignored. NOTE: for a `TriBITS-compliant + external package`_, the special value ``TRIBITS_PKG`` is also recognized. + (Any pre-installed TriBITS package is a `TriBITS-compliant external + package`_.) .. __DEPENDENCIES_FILE: .. _${TPL_NAME}_DEPENDENCIES_FILE: @@ -2306,10 +2106,15 @@ defined TPL ``TPL_NAME`` is assigned the following global non-cache variables: Relative path (w.r.t. ````) or absolute path for the external package/TPL's dependencies file (typically named `FindTPLDependencies.cmake`_). This is always beside the find - module `${TPL_NAME}_FINDMOD`_ (and in fact - ``${TPL_NAME}_DEPENDENCIES_FILE`` is constructed from - ``${TPL_NAME}_FINDMOD``). - + module `${TPL_NAME}_FINDMOD`_. (In fact, for a **non-** + `TriBITS-compliant external package`_, ``${TPL_NAME}_DEPENDENCIES_FILE`` + is constructed from ``${TPL_NAME}_FINDMOD``). NOTE: A `TriBITS-compliant + external package`_ with dependencies will also have this file set and the + path will be specified independent of the path to the non-existent + ``FindTPL.cmake`` file (see the ``FINDMOD`` field in the call to + `tribits_repository_define_tpls()`_). + + .. __TESTGROUP: .. _${TPL_NAME}_TESTGROUP: ``${TPL_NAME}_TESTGROUP`` @@ -2764,6 +2569,158 @@ without having to define its own ``QT`` TPL in its repository's .. ToDo: Describe considerations on where to set variables ... +.. _TriBITS-Compliant Package: + +TriBITS-Compliant Packages +========================== + +At the CMake build-system level, there are just a few key requirements that a +TriBITS package has for its upstream dependent packages when it is being +configured to be built. These requirements apply whether the upstream package +is defined internally in the current CMake project or provided externally and +pulled in through ``find_package()``. + +The common requirements for both internal and external **TriBITS-compliant +packages** as imposed by downstream TriBITS internal packages are: + +* Provides the (INTERFACE) target ``::all_libs`` which provides all + usage requirements for the libraries of ```` through the target + properties: + + * ``INTERFACE_LINK_LIBRARIES``: The library files needed link against (or + upstream library targets including ``::all_libs`` for all + its upstream packages) + + * ``INTERFACE_INCLUDE_DIRECTORIES``: Include directories to all public header files + + * ``INTERFACE_COMPILE_OPTIONS``: Required compiler options + + * ``INTERFACE_COMPILE_DEFINITIONS``: Required compiler/macro definitions + + * ``INTERFACE_LINK_OPTIONS``: Required compiler/macro definitions + + * Any other ``INTERFACE_XXX`` or ``IMPORTED_XXX`` target property needed to + correctly use the libraries for package ````. + +* Provides namespaced variables ``_ENABLE_`` set to + ``TRUE`` or ``FALSE`` for all of the upstream required and optional + dependencies for the package ````. + +* [Optional] Provides namespaced variables of the form + ``_`` for any other information about the configuration + of package ```` that may need to be known by a downstream TriBITS + package. + +* [Optional] Provides any (namespaced by ``_`` or ``_``) + CMake macros or functions that downstream CMake packages may need to use the + upstream package ````. + +* All of the upstream dependencies (listed in the ``INTERFACE_LINK_LIBRARIES`` + property recursively) are also `TriBITS-compliant packages`_ + +The TriBITS system will also set the variable: + +* ``_IS_TRIBITS_COMPLIANT``: Set to ``TRUE`` + +for all packages that are determined to be TriBITS-compliant packages. + +The above are all that is needed by downstream TriBITS packages to build and +link against their upstream dependencies. + +If a TriBITS package provides any CTest tests/examples, then it must also +satsify the following requirements: + +* Test names must be prefixed with the package name ``_``. + +* Tests should only be added if the variable ``_ENABLE_TESTS`` is + true. + +* Examples (that run as CTest tests) should only be added if the variable + ``_ENABLE_EXAMPLES`` is true. + +* The test ``PROCESSORS`` and other test properties must be set in a way + consistent with `tribits_add_test()`_ so as to run in parallel with other + tests and not overwhelm the computing resources on the machine. + +Additional requirements are placed on TriBITS-compliant packages depending on +if they are defined as internal CMake packages (i.e. `TriBITS-compliant +internal packages`_) or are pulled in as external pre-built/pre-installed +packages (i.e. `TriBITS-compliant external packages`_). + + +.. _TriBITS-Compliant Internal Packages: + +TriBITS-Compliant Internal Packages +----------------------------------- + +For TriBITS packages that are defined, built, and installed from a TriBITS +CMake project, there are an additional set of requirements for them to +behavior correctly with respect to other TriBITS packages. + +The requirements for **TriBITS-compliant internal packages** are: + +* All of the requirements for a `TriBITS-Compliant Package`_. + +* At the end of configuration and generation, writes out a `TriBITS-Compliant + External Package`_ file ``Config.cmake`` and supporting files under + the build directory ``/cmake_packages//`` allowing the + built (but not installed) package to be used by downstream CMake + packages/projects. + +* Provides an install target to create a `TriBITS-Compliant External Package`_ + file ``Config.cmake`` and supporting files under the install + directory ``/lib/cmake//`` allowing the installed + package to be used by downstream CMake packages/projects. + +* All of the upstream dependencies (recursively) are also `TriBITS-compliant + packages`_ + +TriBITS internal packages that are defined using the TriBITS framework using +the TriBITS-provided macros and functions such as `tribits_add_library()`_ are +automatically `TriBITS-compliant internal packages`_ and when they are +installed they automatically provide `TriBITS-compliant external packages`_. +But it is possible for a CMake package to write its own raw CMake code to +satisfy these basic requirements for both internal and external packages. + + +.. _TriBITS-Compliant External Package: + +TriBITS-Compliant External Packages +----------------------------------- + +For packages that are installed on the system and not built in the current +CMake project, a streamlined type of `TriBITS External Package/TPL`_ is a +*TriBITS-compliant external package*. These special types of external +package's don't need to provide a `FindTPL.cmake`_ find module. +Instead, they are fully defined by calling ``find_package()`` to +locate and load their ``Config.cmake`` package config file. + +The requirements for **TriBITS-compliant external packages** are: + +* All of the requirements for a `TriBITS-Compliant Package`_. + +* Defined by an installed ``Config.cmake`` file that provides + IMPORTED targets and ``set()`` statements for all of the needed variables. + +* Provides CMake variables: + + * ``_CONFIG`` or + ``_TRIBITS_COMPLIANT_PACKAGE_CONFIG_FILE``: Points to the file + ``Config.cmake`` (i.e. ``${CMAKE_CURRENT_LIST_FILE}``) + + * ``_DIR`` or + ``_TRIBITS_COMPLIANT_PACKAGE_CONFIG_FILE_DIR`` Points to the base + directory for ``Config.cmake`` + (i.e. ``${CMAKE_CURRENT_LIST_DIR}``) + +* All of the upstream dependencies (recursively) are also provided as + `TriBITS-compliant external packages`_ with + ``Config.cmake`` files (see above) and all of the targets + and variables for a TriBITS-compliant external package are defined when the + ``Config.cmake`` file is included (or pulled in with + ``find_package()`` or ``find_dependency()``). + + Example TriBITS Projects ========================= @@ -3348,6 +3305,7 @@ dependency`_ for more discussion and examples. Before getting into specific `Example Enable/Disable Use Cases`_, some of the `TriBITS Dependency Handling Behaviors`_ are first defined below. + TriBITS Dependency Handling Behaviors ------------------------------------- @@ -3768,15 +3726,20 @@ In more detail, these rules/behaviors are: 22) **TriBITS auto-enables/disables done using non-cache local variables**: TriBITS setting (or overrides) of enable/disable cache variables are done by setting local non-cache variables at the top project-level scope - (i.e. the ``/CMakeLists.txt`` file scope). This is done so - they don't get set in the cache and so that the same dependency + (i.e. the ``/CMakeLists.txt`` file scope) and does **not** + touch the value of the cache variables that may be set by the user on + input or the cache variables with documentation set by TriBITS. This is + done so they don't get set in the cache and so that the same dependency enable/disable logic is redone, from scratch, with each re-configure. This results in the same enable/disable logic output as for the initial configure. This is to avoid confusion by the user about why some packages - and TPLs are enabled and some are not on subsequent reconfigures. - However, this implementation choice must be understood when one wants to - go about tweaking these TriBITS enable/disable variables as described in - `How to check for and tweak TriBITS "ENABLE" cache variables`_ and `How to + and TPLs are enabled and some are not on subsequent reconfigures. This is + also desirable behavior as it preserves the user's input values for these + variables to document what was set by the user. However, this + implementation choice (and the tricky relationship between cache and + non-cache CMake variables) must be clearly understood when one wants to go + about tweaking these TriBITS enable/disable variables as described in `How + to check for and tweak TriBITS "ENABLE" cache variables`_ and `How to tweak downstream TriBITS "ENABLE" variables during package configuration`_. @@ -4674,7 +4637,7 @@ Test Test Category ``BASIC`` (`Test Test Category BASIC`_) Typically a TriBITS project will define a "standard development environment" which is comprised of a standard compiler (e.g. GCC 8.3.0), external package/TPL versions (e.g. OpenMPI 4.0.5, Boost 4.9, etc.), and other tools -(e.g. cmake 3.17.0, git 2.10.1, etc.). This standard development environment +(e.g. cmake 3.23.0, git 2.10.1, etc.). This standard development environment is expected to be used to test changes to the project's code before any push. By using a standard development environment, if the code builds and all the tests pass for the "default" pre-push builds for one developer, then that @@ -5578,15 +5541,20 @@ To add a new TriBITS TPL, do the following: 3) **Create the FindTPL.cmake file** (or some other name, see `_FINDMOD`_) under ``/``. (See `Creating the - FindTPL.cmake file`_.) + FindTPL.cmake file`_.) However, if the external package/TPL is a + `TriBITS-compliant external package`_ this file is not needed and is + ignored. 4) **[Optional] Create the FindTPLDependencies.cmake file** in the same directory as the ``FindTPL.cmake`` file, ``/``. - (See `FindTPLDependencies.cmake`_.) + (See `FindTPLDependencies.cmake`_.) NOTE: This file is need for a + `TriBITS-compliant external package`_ if it has upstream dependent external + packages/TPLs (where the file ``FindTPL.cmake`` is not needed). -5) **Add a row to the /TPLsList.cmake file** for the new TPL after - any TPLs that this new TPL may depend on. (See - `/TPLsList.cmake`_.) +5) **Add a row to the /TPLsList.cmake file** for the new external + package/TPL after any upstream TPLs that this new TPL may depend on. NOTE: + For a `TriBITS-compliant external package`_, the special value + ``TRIBITS_PKG`` is used for the TPL (See `/TPLsList.cmake`_.) 6) **Configure the TriBITS project enabling the new TPL with TPL_ENABLE_=ON** and see that the TPL is found correctly at @@ -5657,16 +5625,16 @@ usage requirements (such as the target properties ``INTERFACE_INCLUDE_DIRECTORIES`` and ``INTERFACE_LINK_LIBRARIES``) and use ``find_dependency()`` to get all of their required external upstream package dependencies, many do not. Also, many of these don't provide a complete -``::all_libs`` target which is required for a TriBITS-compatible +``::all_libs`` target which is required for a TriBITS-compliant external package/TPL. In this case, the ``FindTPL.cmake`` file provides a thin "glue" layer to adapt the information and objects provided by the ``find_package( ...)`` call into a complete ``::all_libs`` target and a wrapper ``Config.cmake`` file -for consumption by downstream TriBITS-compatible packages. +for consumption by downstream TriBITS-compliant packages. -The following subsections will describe how to create these TriBITS-compatible +The following subsections will describe how to create these TriBITS-compliant ``FindTPL.cmake`` modules for all of the various cases using an internal call to ``find_package( ...)``: @@ -5681,10 +5649,9 @@ For cases where ``find_package()`` provides complete and proper modern (namespaced) IMPORTED targets (but is missing the ``::all_libs`` target or the name ```` and ```` name are different), these ``FindTPL.cmake`` modules can call the -function -`tribits_extpkg_create_imported_all_libs_target_and_config_file()`_ -after calling ``find_package()`` to create a very thin wrapper -``FindTPL.cmake`` module. In these cases, such a +function `tribits_extpkg_create_imported_all_libs_target_and_config_file()`_ +after calling ``find_package()`` to create a very thin find +module file ``FindTPL.cmake``. In these cases, such a ``FindTPL.cmake`` module file is nothing more than:: find_package( REQUIRED) @@ -5694,27 +5661,30 @@ after calling ``find_package()`` to create a very thin wrapper IMPORTED_TARGETS_FOR_ALL_LIBS ... ) The function -`tribits_extpkg_create_imported_all_libs_target_and_config_file()`_ -creates the target ``::all_libs`` and the wrapper file +`tribits_extpkg_create_imported_all_libs_target_and_config_file()`_ creates +the target ``::all_libs`` and the wrapper file ``Config.cmake`` which is installed by TriBITS. The only unique information required to create this glue module is the name of the external package ```` and the exact full names of the IMPORTED targets `` ...`` provided by the -``find_package( ...)`` call. +``find_package( ...)`` call. The TriBITS function +``tribits_extpkg_create_imported_all_libs_target_and_config_file()`` takes +care of all of the rest of the details. Such simple ``FindTPL.cmake`` modules do not follow the legacy TriBITS TPL convention of allowing users to specify a TPL by setting the cache variables ``_INCLUDE_DIRS``, ``_LIBRARY_DIRS``, and ``_LIBRARY_NAMES`` or by setting ``TPL__INCLUDE_DIRS`` and ``_LIBRARIES``. But as the ecosystem of CMake software transitions -to modern CMake and uniform usage of complete ``Config.cmake`` files, -that is the reasonable thing to do. +to modern CMake along with the proper usage of complete +``Config.cmake`` files, this is the reasonable thing to do. However, to maintain backwards compatibility with the legacy TriBITS TPL system (such as when upgrading a existing ``FindTPL.cmake`` file), a ``FindTPL.cmake`` file can be extended to use the -`tribits_tpl_allow_pre_find_package()`_ in combination with the function -`tribits_tpl_find_include_dirs_and_libraries()`_ function as follows:: +`tribits_tpl_allow_pre_find_package()`_ in combination with the functions +``tribits_extpkg_create_imported_all_libs_target_and_config_file()`` and +`tribits_tpl_find_include_dirs_and_libraries()`_ as follows:: set(REQUIRED_HEADERS ...) set(REQUIRED_LIBS_NAMES ...) @@ -5931,21 +5901,31 @@ header files and libraries that must be found. A simple Requirements for FindTPL.cmake modules +++++++++++++++++++++++++++++++++++++++++++++++ -It is possible to create a ``FindTPL.cmake`` module without using any -TriBITS functions. The only firm requirements for a -``FindTPL.cmake`` file after it is included are: +It is possible to create a ``FindTPL.cmake`` find module without +using any TriBITS functions. The only firm requirements for a +``FindTPL.cmake`` file are: * The target ``::all_libs`` must be created and it must contain all of the needed libraries, include directories, and other usage requirements - (including for all upstream external packages/TPLs). + (including for all upstream external packages/TPLs) to implement a + `TriBITS-compliant package`_ to be consumed by downstream TriBITS packages. * The file ``/external_packages//Config.cmake`` - must be created in the build directory and when including the file - ``Config.cmake`` it must define the equivalent target - ``::all_libs`` (and must call ``find_dependency()`` correctly on - all upstream external packages/TPLs). - -Some of issues to consider in this case are described in the section `Tricky + must be created in the build directory, and when included, it must define + the equivalent IMPORTED target ``::all_libs``, pull all of the + ``Config.cmake`` files for upstream external packages/TPLs, and + define the needed variables to provide a `TriBITS-compliant external + package`_. + +TriBITS will set the remaining variables to provide a complete +`TriBITS-Compliant Package`_ for the current CMake project and will add the +install target to install the file +``/external_packages//Config.cmake`` to create a +`TriBITS-compliant external package`_. TriBITS will also automatically create +an appropriate package version file ``ConfigVersion.cmake``. + +Some of issues to consider in this case (and the role of the +``ConfigVersion.cmake`` file) are described in the section `Tricky considerations for TriBITS-generated Config.cmake files`_. @@ -6332,7 +6312,7 @@ enabling/disabling various entities that allow for a default "undefined" empty * ``${PROJECT_NAME}_ENABLE_`` (Packages) * ``TPL_ENABLE_`` (External Packages/TPLs) -* ``_ENABLE_`` (Optional support for a +* ``_ENABLE_`` (Support for a package ```` in a downstream package ````) * ``_ENABLE_TESTS`` (Package tests) @@ -6358,7 +6338,8 @@ following: default defined or not. 2) To tweak the enable/disable of one or more of these variables after user - input but before auto-enable/disable logic: + input but **before** the step "Adjust package and TPLs enables and + disables" in `Full Processing of TriBITS Project Files`_: a) To tweak the enables/disables for a TriBITS Repository (i.e. affecting all TriBITS projects) add enable/disable code to the file @@ -6390,10 +6371,12 @@ possible values of ``ON``, ``OFF`` and empty ``""`` (see the macro ``_ENABLE_`` variable is defined (e.g. ``if (DEFINED _ENABLE_) ... endif()``) does not mean that it has been set to ``ON`` or ``OFF`` yet (or any non-empty values that evaluates to true or false -in CMake). To see if an ``ENABLE`` variable is one of these variables, look -in the CMakeCache.txt file for the type. If the type is ``STRING``, then it -is most likely this type of variable with a default value of empty ``""``. -However, if the cache type is ``BOOL`` then it is likely a standard bool +in CMake). To see if an ``ENABLE`` variable is one of these types, look in +the ``CMakeCache.txt``. If the type of the variable ``_ENABLE_`` is +``STRING`` and you see another variable set with the name +``_ENABLE__-STRINGS``, then it is most likely this special type of +``ENABLE`` variable with a typical default value of empty ``""``. However, if +the cache variable is of type ``BOOL``, then it is likely a standard bool variable that is not allowed to have a value of empty ``""``. Second, note that the value of empty ``""`` evaluates to ``FALSE`` in CMake @@ -6401,11 +6384,11 @@ Second, note that the value of empty ``""`` evaluates to ``FALSE`` in CMake variables evaluates to true, then just use ``if (_ENABLE_) ... endif()``. -Third, note that TriBITS will not define these cache variables until TriBITS -processes the ``Dependencies.cmake`` files on the first configure (see `Full -TriBITS Project Configuration`_). On future reconfigures, these variables are -all defined (but most will have a default value of empty ``""`` stored in the -cache). +Third, note that TriBITS will not define cache variables for these ``ENABLE`` +variables until TriBITS processes the ``Dependencies.cmake`` files on the +first configure (see `Full TriBITS Project Configuration`_). On future +reconfigures, these variables are all defined (but most will have a default +value of empty ``""`` stored in the cache). The reason the files ``RepositoryDependenciesSetup.cmake`` and ``ProjectDependenciesSetup.cmake`` are the best places to put in these tweaks @@ -6418,6 +6401,11 @@ Logic`_). Also, these files get processed in `Reduced Package Dependency Processing`_ as well so they get processed in all contexts where enable/disable logic is applied. +However, if one wants to tweak these variables once packages are starting to +be processed (in step "For each ```` in all enabled top-level +packages" in `Full TriBITS Project Configuration`_), there are fewer +situations where that can be done correctly as described in the next section. + How to tweak downstream TriBITS "ENABLE" variables during package configuration ------------------------------------------------------------------------------- @@ -6426,44 +6414,64 @@ There are cases where one may need to enable or disable some feature that TriBITS may have enabled by default (such as in "Adjust package and TPLs enables and disables" in `Full Processing of TriBITS Project Files`_) and that decision can only be made while processing a package's -`/CMakeLists.txt`_ file. (And therefore the logic for this disable -cannot be performed in the ``ProjectDependenciesSetup.cmake`` or -``RepositoryDependenciesSetup.cmake`` files as described in `How to check for -and tweak TriBITS "ENABLE" cache variables`_ which are processed before the -enabled packages are configured.) Also, there are cases where it is necessary -to make this change visible to downstream packages such as when -```` support of some feature depends on -```` support for that same feature. Examples include -optional support of an upstream package in a downstream package -``_ENABLE_`` or for support for an -optional TPL in a downstream package ``_ENABLE_``. -But other examples may include variables that are not optional TriBITS package -and TPL enables (such as support for a given data-type that may impact -multiple packages). +`/CMakeLists.txt`_ file and not before. (And therefore the logic +for this disable cannot be performed in the ``ProjectDependenciesSetup.cmake`` +or ``RepositoryDependenciesSetup.cmake`` files as described in `How to check +for and tweak TriBITS "ENABLE" cache variables`_.) Also, there are cases +where it is necessary to make this change visible to downstream packages. The +main example is when optional support of an upstream package in a downstream +package ``_ENABLE_`` must be changed in +the package's `/CMakeLists.txt`_ file. But there are other +examples such as support for a given data-type that may impact multiple +downstream packages. When the internal configuration of a package (i.e. while processing its ``/CMakeLists.txt`` file) determines that an optional feature -``_ENABLE_`` must be enabled or disabled with and will change the -value previously set (e.g. during the "Adjust package and TPLs enables and -disables" stage), one cannot use a simple ``set()`` statement. Changing the -value of an ``_ENABLE_`` variable inside a package's -``/CMakeLists.txt`` file using a raw ``set(_ENABLE_ +``_ENABLE_`` must change the value previously set (e.g. that was +set automatically by TriBITS during the "Adjust package and TPLs enables and +disables" stage in `Full Processing of TriBITS Project Files`_), one cannot +use a simple ``set()`` statement. Changing the value of a +``_ENABLE_`` variable inside a package's +``/CMakeLists.txt`` file using a raw ``set(_ENABLE_ )`` statement only changes the variable's value inside the package's scope, but all other packages will see the old value of -``_ENABLE_``. To correctly change the value of one of these +``_ENABLE_``. To correctly change the value of one of these variables, instead use `dual_scope_set()`_ from the top-level -``/CMakeLists.txt`` file. This sets the value in both the -base-level (global) project scope and in the local scope of -``/CMakeLists.txt``. (But this does **not** change the value of a -cache variable ``_ENABLE_`` that may have been set by the user or -some other means; see `TriBITS auto-enables/disables done using non-cache -local variables`_.) Any downstream package (configured after processing -``/CMakeLists.txt``) will see the new value ``_ENABLE_ -STREQUAL ``. It is also strongly recommended that a message or warning -be printed to CMake STDOUT using ``message(["NOTE: "|WARNING] "")`` -when globally changing an ENABLE variable. The user may have set it -explicitly, and they should know exactly why and where their choice is being -overridden. +``/CMakeLists.txt`` file. To perform this disable more robustly +than calling ``dual_scope_set()`` directly, use the provided macro +`tribits_disable_optional_dependency()`_. For example, to disable optional +support for ```` in ```` in +```` package's ``/CMakeLists.txt`` file based +on some criteria, add the CMake code:: + + if () + tribits_disable_optional_dependency( + "NOTE: ${PACKAGE_NAME}_ENABLE_ being set to OFF because of " ) + endif() + +Calling ``dual_scope_set()`` in the package's top-level +``/CMakeLists.txt`` file sets the value in both the local scope of +``/CMakeLists.txt`` (and therefore propagated to all other +``CMakeLists.txt`` files in that package) and in base-level (global) project +scope. (But this does **not** change the value of a cache variable +``_ENABLE_`` that may have been set by the user or some other +means which is the desired behavior; see `TriBITS auto-enables/disables done +using non-cache local variables`_.) In this way, any downstream package +(configured after processing ``/CMakeLists.txt``) will see the new +value for ``_ENABLE_``. + +It is also strongly recommended that a message be printed to CMake STDOUT +using ``message("-- " "NOTE: ")`` when changing the value of one of +these ``_ENABLE_`` variables. The user may have set it +explicitly or TriBITS may have printed automatic logic for setting it by +default, and user needs to know why and where the value is being overridden. + +**NOTE:** However, it is **not** allowed to try to change the value of a +global enable of a upstream or downstream package by trying to change the +value of ``_ENABLE_`` or ``TPL_ENABLE_`` in a +``/CMakeLists.txt`` file. Changing the value of these variables +after the "Adjust package and TPLs enables and disables" stage in `Full +Processing of TriBITS Project Files`_ will result in undefined behavior. How to set up multi-repository support @@ -6935,38 +6943,41 @@ Tricky considerations for TriBITS-generated Config.cmake files ----------------------------------------------------------------------- An issue that comes up with external packages/TPLs like HDF5 that needs to be -discussed here is the fact that ``FindTPL.cmake`` files create (See -`How to add a new TriBITS TPL`_) and TriBITS installs files of the name -``Config.cmake`` and that could potentially be found by calls to -``find_package()`` (when `` == `` like with -HDF5). These TriBITS-generated ``Config.cmake`` files are primarily -meant to provide the ``::all_libs`` targets for downstream -TriBITS-compatible ``Config.cmake`` files. These TriBITS-generated -``Config.cmake`` files will usually not behave the same way that a -more general ``Find.config`` modules or native -``Config.cmake`` configure files would behave as expected when found -by ``find_package()`` commands called in some arbitrary downstream -raw CMake project. Therefore, to avoid having an installed TriBITS-generated -``HDF5Config.cmake`` file, for example, being found by the inner call to -``find_package(HDF5 ...)`` in the file ``FindTPLHDF5.cmake`` (which would be -disastrous), TriBITS employs two safeguards. First, TriBITS-generated -``Config.cmake`` files are placed into the build directory under:: +discussed here is the fact that ``FindTPL.cmake`` module files create +(See `How to add a new TriBITS TPL`_) and TriBITS installs package config +files of the name ``Config.cmake``. These TriBITS-generated package +config files ``Config.cmake`` could potentially be found by calls to +``find_package()`` (i.e. when `` == `` like +with HDF5). These TriBITS-generated ``Config.cmake`` files are +primarily meant to provide a `TriBITS-compliant external package`_ for +downstream TriBITS-compliant ``Config.cmake`` files. These +TriBITS-generated ``Config.cmake`` files will usually not behave the +same way existing ``Find.config`` find modules or native +``Config.cmake`` package config files would behave as expected by +downstream projects when found by ``find_package()`` commands called +in some arbitrary downstream raw CMake project. Therefore, to avoid having an +installed TriBITS-generated ``HDF5Config.cmake`` file, for example, being +found by the inner call to ``find_package(HDF5 ...)`` in the file +``FindTPLHDF5.cmake`` (which could be disastrous), TriBITS employs two +safeguards. + +First, TriBITS-generated ``Config.cmake`` package config files are +placed into the build directory under:: /external_packages//Config.cmake -and installed into the directory under:: +and installed into the installation directory under:: /lib/external_packages//Config.cmake so they will not be found by ``find_package()`` by default when ``/cmake_packages`` and/or ````, respectively, are added -to ``CMAKE_PREFIX_PATH``. Also, even if -``/lib/external_packages`` or ``/external_packages`` do -get added to the search path somehow (e.g. by appending those to -``CMAKE_INSTALL_PREFIX``), the TriBITS framework will set the variable -``TRIBITS_FINDING_RAW__PACKAGE_FIRST=TRUE`` before including -``FindTPL.cmake`` and there is special logic in the TriBITS-generated -``ConfigVersion.cmake`` file that will set +to ``CMAKE_PREFIX_PATH``. + +Second, even if the directories ``/lib/external_packages`` or +``/external_packages`` do get added to the search path somehow +(e.g. by appending those to ``CMAKE_INSTALL_PREFIX``), the companion +TriBITS-generated ``ConfigVersion.cmake`` files will set ``PACKAGE_VERSION_COMPATIBLE=OFF`` and result in ``find_package()`` not selecting the TriBITS-generated ``Config.cmake`` file. (It turns out that CMake's ``find_package()`` command always includes the file @@ -6998,7 +7009,7 @@ will be used). Also, there are cases were one cannot easily control the default file or directory creation permissions using ``umask``. And there are cases where one would like to recursively install a set of directories and files where some of these files may be scripts that need to have the execute -permission set on them for them to work. The only to flexiable accomplish +permission set on them for them to work. The only to flexible accomplish that with CMake (if one does not know the exist list of those files or extensions of those files) is to pass in the ``SOURCE_PERMISSIONS`` option to the ``install(DIRECTORY ...)`` command. An example of this is shown in: diff --git a/cmake/tribits/doc/guides/TribitsGuidesReferences.rst b/cmake/tribits/doc/guides/TribitsGuidesReferences.rst index 52bce47e6e5d..9ca7cc5c5eee 100644 --- a/cmake/tribits/doc/guides/TribitsGuidesReferences.rst +++ b/cmake/tribits/doc/guides/TribitsGuidesReferences.rst @@ -116,7 +116,7 @@ Scott, Craig. *Professional CMake: A Practical Guide (5th Edition).* ISBN 978-1 .. Common references to raw CMake commands: -.. _configure_file(): https://cmake.org/cmake/help/v3.17/command/configure_file.html +.. _configure_file(): https://cmake.org/cmake/help/v3.23/command/configure_file.html .. Other references diff --git a/cmake/tribits/doc/guides/TribitsMacroFunctionDocTemplate.rst b/cmake/tribits/doc/guides/TribitsMacroFunctionDocTemplate.rst index c0916454df5b..15e079ea7067 100644 --- a/cmake/tribits/doc/guides/TribitsMacroFunctionDocTemplate.rst +++ b/cmake/tribits/doc/guides/TribitsMacroFunctionDocTemplate.rst @@ -9,7 +9,7 @@ @FUNCTION: tribits_add_executable() + @FUNCTION: tribits_add_executable_and_test() + @FUNCTION: tribits_add_library() + -@MACRO: tribits_add_option_and_define() + +@FUNCTION: tribits_add_option_and_define() + @MACRO: tribits_add_show_deprecated_warnings_option() + @FUNCTION: tribits_add_test() + @MACRO: tribits_add_test_directories() + @@ -19,11 +19,13 @@ @FUNCTION: tribits_copy_files_to_binary_dir() + @FUNCTION: tribits_ctest_driver() + @FUNCTION: tribits_determine_if_current_package_needs_rebuilt() + +@MACRO: tribits_disable_optional_dependency() + @MACRO: tribits_disable_package_on_platforms() + @MACRO: tribits_exclude_files() + @MACRO: tribits_extpkg_define_dependencies() + @FUNCTION: tribits_extpkg_get_dep_name_and_vis() + @FUNCTION: tribits_extpkg_create_imported_all_libs_target_and_config_file() + +@FUNCTION: tribits_extpkg_tpl_libraries_entry_type() + @FUNCTION: tribits_extpkg_write_config_file() + @FUNCTION: tribits_extpkg_write_config_file_str() + @FUNCTION: tribits_find_most_recent_binary_file_timestamp() + @@ -38,7 +40,7 @@ @MACRO: tribits_package_define_dependencies() + @MACRO: tribits_package_postprocess() + @MACRO: tribits_process_subpackages() + -@FUNCTION: tribits_process_enabled_tpl() + +@MACRO: tribits_process_enabled_standard_tpl() + @MACRO: tribits_project() + @MACRO: tribits_project_define_extra_repositories() + @MACRO: tribits_project_enable_all() + @@ -50,7 +52,6 @@ @MACRO: tribits_subpackage_postprocess() + @FUNCTION: tribits_tpl_allow_pre_find_package() + @FUNCTION: tribits_tpl_find_include_dirs_and_libraries() + -@FUNCTION: tribits_tpl_libraries_entry_type() + @FUNCTION: tribits_tpl_tentatively_enable() + @FUNCTION: tribits_write_flexible_package_client_export_files() + @FUNCTION: tribits_verbose_print_var() + diff --git a/cmake/tribits/doc/guides/TribitsSystemMacroFunctionDocTemplate.rst b/cmake/tribits/doc/guides/TribitsSystemMacroFunctionDocTemplate.rst index a8c9f53d216a..6a71292c45a5 100644 --- a/cmake/tribits/doc/guides/TribitsSystemMacroFunctionDocTemplate.rst +++ b/cmake/tribits/doc/guides/TribitsSystemMacroFunctionDocTemplate.rst @@ -16,15 +16,17 @@ understand the internals of TriBITS. @MACRO: tribits_append_forward_dep_packages() + @MACRO: tribits_assert_read_dependency_vars() + @FUNCTION: tribits_dump_package_dependencies_info() + -@FUNCTION: tribits_extpkg_add_find_upstream_dependencies_str() + -@FUNCTION: tribits_extpkg_create_all_libs_target() + +@FUNCTION: tribits_extpkg_append_create_all_libs_target_str() + +@FUNCTION: tribits_extpkg_append_find_upstream_dependencies_str() + @FUNCTION: tribits_extpkg_install_config_file() + @FUNCTION: tribits_extpkg_install_config_version_file() + @FUNCTION: tribits_extpkg_process_libraries_list() + @MACRO: tribits_extpkg_setup_enabled_dependencies() + @FUNCTION: tribits_extpkg_write_config_version_file() + +@FUNCTION: tribits_filter_package_list_from_var() + @FUNCTION: tribits_get_sublist_disabled() + @FUNCTION: tribits_get_sublist_enabled() + +@FUNCTION: tribits_get_sublist_internal_external() + @FUNCTION: tribits_get_sublist_nondisabled() + @FUNCTION: tribits_get_sublist_nonenabled() + @FUNCTION: tribits_print_initial_dependency_info() + diff --git a/cmake/tribits/doc/guides/maintainers_guide/TribitsMaintainersGuide.rst b/cmake/tribits/doc/guides/maintainers_guide/TribitsMaintainersGuide.rst index c9c0b1b7ccaf..f9d973495bf7 100644 --- a/cmake/tribits/doc/guides/maintainers_guide/TribitsMaintainersGuide.rst +++ b/cmake/tribits/doc/guides/maintainers_guide/TribitsMaintainersGuide.rst @@ -71,6 +71,8 @@ Developers`_ and `TriBITS System Architects`_. Appendix ======== +.. include:: ../TribitsCMakeLanguageOverviewAndGotchas.rst + .. include:: ../TribitsHistory.rst .. include:: ../TribitsPackageNotCMakePackage.rst diff --git a/cmake/tribits/doc/guides/users_guide/TribitsUsersGuide.rst b/cmake/tribits/doc/guides/users_guide/TribitsUsersGuide.rst index be4cee320ff3..720a71c750e7 100644 --- a/cmake/tribits/doc/guides/users_guide/TribitsUsersGuide.rst +++ b/cmake/tribits/doc/guides/users_guide/TribitsUsersGuide.rst @@ -90,6 +90,8 @@ in the `Appendix`_. Appendix ======== +.. include:: ../TribitsCMakeLanguageOverviewAndGotchas.rst + .. include:: ../TribitsHistory.rst .. include:: ../TribitsPackageNotCMakePackage.rst diff --git a/cmake/tribits/doc/tutorial/src/TribitsTutorial_ConvertAProject.rst b/cmake/tribits/doc/tutorial/src/TribitsTutorial_ConvertAProject.rst index 4533d89887d3..d3b202ac97d9 100644 --- a/cmake/tribits/doc/tutorial/src/TribitsTutorial_ConvertAProject.rst +++ b/cmake/tribits/doc/tutorial/src/TribitsTutorial_ConvertAProject.rst @@ -392,7 +392,7 @@ in this project level CMakeLists file: 1. cmake_minimum_version() - set the minimum version of cmake required for this project o build. If you try and run with a lower version then there will be an error. You cannot specify a version lower than - 3.17.0 + 3.23.0 #. Include ProjectNmae.cmake and call project() with argument PROJECT_NAME #. specify the directory to tribits and include TriBITS.cmake #. specify which packages are turned on/off by default @@ -401,7 +401,7 @@ in this project level CMakeLists file: Here is an examlpe of a project CMakeLists:: # Deefine your minimum CMake version - cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR) + cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) # Define your project name and set up major project options include("${CMAKE_CURRENT_SOURCE_DIR}/ProjectName.cmake") diff --git a/cmake/tribits/doc/tutorial/src/TribitsTutorial_HelloWorld.rst b/cmake/tribits/doc/tutorial/src/TribitsTutorial_HelloWorld.rst index 885c3b4faa56..3284283dd8c3 100644 --- a/cmake/tribits/doc/tutorial/src/TribitsTutorial_HelloWorld.rst +++ b/cmake/tribits/doc/tutorial/src/TribitsTutorial_HelloWorld.rst @@ -163,7 +163,7 @@ single line:: have the following contents:: # To be safe, define your minimum CMake version - cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR) + cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) # Make CMake set WIN32 with CYGWIN for older CMake versions set(CMAKE_LEGACY_CYGWIN_WIN32 1 CACHE BOOL "" FORCE) diff --git a/cmake/tribits/examples/MockTrilinos/CMakeLists.txt b/cmake/tribits/examples/MockTrilinos/CMakeLists.txt index c089891caedc..7fb43de86344 100644 --- a/cmake/tribits/examples/MockTrilinos/CMakeLists.txt +++ b/cmake/tribits/examples/MockTrilinos/CMakeLists.txt @@ -37,9 +37,10 @@ # ************************************************************************ # @HEADER -cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) include(${CMAKE_SOURCE_DIR}/ProjectName.cmake) project(${PROJECT_NAME} NONE) set(${PROJECT_NAME}_TRIBITS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../.." CACHE PATH "") +set(${PROJECT_NAME}_TRACE_DEPENDENCY_HANDLING_ONLY ON CACHE BOOL "") include("${${PROJECT_NAME}_TRIBITS_DIR}/TriBITS.cmake") tribits_project() diff --git a/cmake/tribits/examples/RawAndTribitsHelloWorld/CMakeLists.txt b/cmake/tribits/examples/RawAndTribitsHelloWorld/CMakeLists.txt index 0dd4c802b3fe..bfb9ca470608 100644 --- a/cmake/tribits/examples/RawAndTribitsHelloWorld/CMakeLists.txt +++ b/cmake/tribits/examples/RawAndTribitsHelloWorld/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) include(${CMAKE_CURRENT_SOURCE_DIR}/ProjectName.cmake) # Called at the top of every CMakeLists.txt file diff --git a/cmake/tribits/examples/ReducedMockTrilinos/CMakeLists.txt b/cmake/tribits/examples/ReducedMockTrilinos/CMakeLists.txt index ee377d58b35c..14281e147f19 100644 --- a/cmake/tribits/examples/ReducedMockTrilinos/CMakeLists.txt +++ b/cmake/tribits/examples/ReducedMockTrilinos/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) include(${CMAKE_CURRENT_SOURCE_DIR}/ProjectName.cmake) project(${PROJECT_NAME} NONE) set(${PROJECT_NAME}_TRIBITS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../.." CACHE PATH "") diff --git a/cmake/tribits/examples/TribitsExampleApp/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleApp/CMakeLists.txt index 562a38ffd4ab..57839bd71f08 100644 --- a/cmake/tribits/examples/TribitsExampleApp/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleApp/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.17.1) +cmake_minimum_required(VERSION 3.23.1) project(TribitsExApp DESCRIPTION diff --git a/cmake/tribits/examples/TribitsExampleApp2/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleApp2/CMakeLists.txt index 306b0d61b6ed..3ffbae9f46ec 100644 --- a/cmake/tribits/examples/TribitsExampleApp2/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleApp2/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.17.1) +cmake_minimum_required(VERSION 3.23.1) project(TribitsExApp2 DESCRIPTION diff --git a/cmake/tribits/examples/TribitsExampleMetaProject/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleMetaProject/CMakeLists.txt index 00ff4f3308fe..9488edf431f2 100644 --- a/cmake/tribits/examples/TribitsExampleMetaProject/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleMetaProject/CMakeLists.txt @@ -6,7 +6,7 @@ # To be safe, define your minimum CMake version. This may be newer than the # min required by TriBITS. -cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) # Make CMake set WIN32 with CYGWIN for older CMake versions. CMake requires # this to be in the top-level CMakeLists.txt file and not an include file :-( diff --git a/cmake/tribits/examples/TribitsExampleProject/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject/CMakeLists.txt index f413d381b010..819dfd331cbd 100644 --- a/cmake/tribits/examples/TribitsExampleProject/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleProject/CMakeLists.txt @@ -6,7 +6,7 @@ # To be safe, define your minimum CMake version. This may be newer than the # min required by TriBITS. -cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) # Make CMake set WIN32 with CYGWIN for older CMake versions. CMake requires # this to be in the top-level CMakeLists.txt file and not an include file :-( diff --git a/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/CMakeLists.txt index 4eb715a09576..295e359fa8e1 100644 --- a/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/CMakeLists.txt @@ -32,6 +32,7 @@ endif() global_set(EXPECTED_SIMPLECXX_AND_DEPS "SimpleCxx ${simpletplText}headeronlytpl") +tribits_pkg_export_cache_var(EXPECTED_SIMPLECXX_AND_DEPS) # # E) Do standard post processing diff --git a/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/b/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/b/CMakeLists.txt index 200d869b1f43..717246f3c6fa 100644 --- a/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/b/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/b/CMakeLists.txt @@ -22,6 +22,7 @@ endif() global_set(EXPECTED_B_DEPS "${EXPECTED_A_AND_DEPS_STR}${EXPECTED_INSERTEDPKG_AND_DEPS_STR}${EXPECTED_SIMPLECXX_AND_DEPS}") +tribits_pkg_export_cache_var(EXPECTED_B_DEPS) tribits_add_test_directories(tests) diff --git a/cmake/tribits/examples/TribitsExampleProject/packages/wrap_external/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject/packages/wrap_external/CMakeLists.txt index 0efcd994f721..a9f8b0a37331 100644 --- a/cmake/tribits/examples/TribitsExampleProject/packages/wrap_external/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleProject/packages/wrap_external/CMakeLists.txt @@ -7,21 +7,6 @@ # provides libraries that need to be cast as TriBITS CMake libraries. To # make this even more interesting, the external software has dependencies on # upstream TriBITS packages. -# -# An overview of the basic tasks required are: -# -# a) Enumerate the upstream packages and TPLs needed (this is done in the -# cmake/Dependencies.cmake file). -# -# b) Generate an export makefile for the upstream packages and TPLs -# -# c) Call the configure script for the external package passing the compilers, -# compiler flags, and a pointer to the export makefile (which is just used to -# lift the include dirs and libs). -# -# d) Define library targets for the external project and define a build rule -# for generating those libraries given the list of header and source files in -# the external project. tribits_package(WrapExternal) @@ -66,41 +51,51 @@ endif() string(TOUPPER "${CMAKE_BUILD_TYPE}" upperBuildType) -set(includeDirsList - -I ${WithSubpackagesA_SOURCE_DIR} - -I ${SimpleCxx_SOURCE_DIR}/src - -I ${SimpleCxx_BINARY_DIR}/src - ) +get_target_property(simpleCxx_IncludeDirs + SimpleCxx::simplecxx INTERFACE_INCLUDE_DIRECTORIES) + +get_target_property(withSubpackagesA_IncludeDirs + WithSubpackagesA::pws_a INTERFACE_INCLUDE_DIRECTORIES) + +set(includeDirsList ${withSubpackagesA_IncludeDirs} ${simpleCxx_IncludeDirs}) + if (${PACKAGE_NAME}_ENABLE_MixedLang) - list(PREPEND includeDirsList - -I ${MixedLang_SOURCE_DIR}/src - -I ${MixedLang_BINARY_DIR}/src - ) + get_target_property(mixedLang_IncludeDirs + MixedLang::mixedlang INTERFACE_INCLUDE_DIRECTORIES) + list(PREPEND includeDirsList ${mixedLang_IncludeDirs}) endif() -list(JOIN includeDirsList " " includeDirs) -# NOTE: TriBITS export Makefile support used to handle the above stuff -# automatically but that is what you give up when moving to modern CMake. +list(JOIN includeDirsList " -I" includeDirsCompileOptions) +set(includeDirsCompileOptions "-I${includeDirsCompileOptions}") # -# C) Do configuration of the external project +# C) Do configuration of the external project as a build target # set(EXTERNAL_FUNC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_func) set(EXTERNAL_FUNC_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/external_func) set(EXTERNAL_FUNC_LIB_FILE ${EXTERNAL_FUNC_BINARY_DIR}/libexternal_func.a) +set(EXTERNAL_FUNC_MAKEFILE ${EXTERNAL_FUNC_BINARY_DIR}/Makefile) file(MAKE_DIRECTORY ${EXTERNAL_FUNC_BINARY_DIR}) -execute_process( +add_custom_command( + OUTPUT ${EXTERNAL_FUNC_MAKEFILE} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt + ${EXTERNAL_FUNC_SOURCE_DIR}/configure.py COMMAND ${PYTHON_EXECUTABLE} ${EXTERNAL_FUNC_SOURCE_DIR}/configure.py "--cxx=${CMAKE_CXX_COMPILER}" "--cxx-flags=${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${upperBuildType}}" "--ar=${CMAKE_AR}" - "--include-dirs=${includeDirs}" + "--include-dirs=${includeDirsCompileOptions}" "--src-dir=${EXTERNAL_FUNC_SOURCE_DIR}" "--build-dir=${EXTERNAL_FUNC_BINARY_DIR}" ) +# NOTE: Above, we have to run the configure.py script at build time after +# generation because ${includeDirsCompileOptions} contains generation +# expressions that are evaluated at generation time by the +# add_custom_command() call. + # # D) Define a custom build rule and target to create external_func library # @@ -109,6 +104,7 @@ add_custom_command( OUTPUT ${EXTERNAL_FUNC_LIB_FILE} DEPENDS ${EXTERNAL_FUNC_SOURCE_DIR}/external_func.hpp ${EXTERNAL_FUNC_SOURCE_DIR}/external_func.cpp + ${EXTERNAL_FUNC_MAKEFILE} COMMAND make ${CTEST_BUILD_FLAGS} WORKING_DIRECTORY ${EXTERNAL_FUNC_BINARY_DIR} ) @@ -137,13 +133,13 @@ add_dependencies(external_func build_external_func) # E.2) Make sure before we build the external library, we first build the # libraries. -add_dependencies(build_external_func pws_a) +add_dependencies(build_external_func WithSubpackagesA::pws_a) # NOTE: You have to put the lib dependencies on build target, not the imported # library target! # E.3) Update the TriBITS variables append_set(${PACKAGE_NAME}_LIB_TARGETS external_func) -global_set(${PACKAGE_NAME}_LIBRARIES external_func pws_a) +global_set(${PACKAGE_NAME}_LIBRARIES external_func WithSubpackagesA::pws_a) global_set(${PACKAGE_NAME}_HAS_NATIVE_LIBRARIES ON) tribits_include_directories(${EXTERNAL_FUNC_SOURCE_DIR}) # NOTE: Above, you have to add the upstream dependent libraries to the current diff --git a/cmake/tribits/examples/TribitsExampleProject2/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject2/CMakeLists.txt index 8e63bc40e843..7ba3163d9adf 100644 --- a/cmake/tribits/examples/TribitsExampleProject2/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleProject2/CMakeLists.txt @@ -4,7 +4,7 @@ # # ################################################################################ -cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) include("${CMAKE_CURRENT_SOURCE_DIR}/ProjectName.cmake") project(${PROJECT_NAME} LANGUAGES NONE) set(TRIBITS_HIDE_DEPRECATED_INCLUDE_DIRECTORIES_OVERRIDE TRUE) diff --git a/cmake/tribits/examples/TribitsExampleProjectAddons/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProjectAddons/CMakeLists.txt index b4dcaeb90b4f..d2bb6a2b8b68 100644 --- a/cmake/tribits/examples/TribitsExampleProjectAddons/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleProjectAddons/CMakeLists.txt @@ -6,7 +6,7 @@ # To be safe, define your minimum CMake version. This may be newer than the # min required by TriBITS. -cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) # Make CMake set WIN32 with CYGWIN for older CMake versions. CMake requires # this to be in the top-level CMakeLists.txt file and not an include file :-( diff --git a/cmake/tribits/examples/TribitsHelloWorld/CMakeLists.txt b/cmake/tribits/examples/TribitsHelloWorld/CMakeLists.txt index eeeb79cdff6e..8ffd690a3ef1 100644 --- a/cmake/tribits/examples/TribitsHelloWorld/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsHelloWorld/CMakeLists.txt @@ -1,5 +1,5 @@ # Example of a simple project that uses TriBITS -cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) include(${CMAKE_CURRENT_SOURCE_DIR}/ProjectName.cmake) project(${PROJECT_NAME} NONE) set(${PROJECT_NAME}_TRIBITS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../.. diff --git a/cmake/tribits/examples/TribitsOldSimpleExampleApp/CMakeLists.txt b/cmake/tribits/examples/TribitsOldSimpleExampleApp/CMakeLists.txt index b0d9d5d0699b..e46f7f1726db 100644 --- a/cmake/tribits/examples/TribitsOldSimpleExampleApp/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsOldSimpleExampleApp/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.17.1) +cmake_minimum_required(VERSION 3.23.1) project(TribitsOldSimpleExApp DESCRIPTION diff --git a/cmake/tribits/examples/TribitsSimpleExampleApp/CMakeLists.txt b/cmake/tribits/examples/TribitsSimpleExampleApp/CMakeLists.txt index 58725b4fc565..81c6245486aa 100644 --- a/cmake/tribits/examples/TribitsSimpleExampleApp/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsSimpleExampleApp/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.17.1) +cmake_minimum_required(VERSION 3.23.1) project(TribitsSimpleExApp DESCRIPTION diff --git a/cmake/tribits/examples/tpls/SimpleTpl/CMakeLists.txt b/cmake/tribits/examples/tpls/SimpleTpl/CMakeLists.txt index b2909c6b096c..22c1593c50e9 100644 --- a/cmake/tribits/examples/tpls/SimpleTpl/CMakeLists.txt +++ b/cmake/tribits/examples/tpls/SimpleTpl/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.17.0) +cmake_minimum_required(VERSION 3.23.0) project(SimpleTpl DESCRIPTION diff --git a/cmake/tribits/examples/tpls/Tpl1/CMakeLists.txt b/cmake/tribits/examples/tpls/Tpl1/CMakeLists.txt index 681cefc9ca31..36d44a63708d 100644 --- a/cmake/tribits/examples/tpls/Tpl1/CMakeLists.txt +++ b/cmake/tribits/examples/tpls/Tpl1/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.17.0) +cmake_minimum_required(VERSION 3.23.0) project(Tpl1 DESCRIPTION diff --git a/cmake/tribits/examples/tpls/Tpl2/CMakeLists.txt b/cmake/tribits/examples/tpls/Tpl2/CMakeLists.txt index 36f9a747f4f8..7b41223cbd69 100644 --- a/cmake/tribits/examples/tpls/Tpl2/CMakeLists.txt +++ b/cmake/tribits/examples/tpls/Tpl2/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.17.0) +cmake_minimum_required(VERSION 3.23.0) project(Tpl2 DESCRIPTION diff --git a/cmake/tribits/examples/tpls/Tpl3/CMakeLists.txt b/cmake/tribits/examples/tpls/Tpl3/CMakeLists.txt index a10cb463ceef..6ce21884930f 100644 --- a/cmake/tribits/examples/tpls/Tpl3/CMakeLists.txt +++ b/cmake/tribits/examples/tpls/Tpl3/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.17.0) +cmake_minimum_required(VERSION 3.23.0) project(Tpl3 DESCRIPTION diff --git a/cmake/tribits/examples/tpls/Tpl4/CMakeLists.txt b/cmake/tribits/examples/tpls/Tpl4/CMakeLists.txt index cbbe3f2acf6b..bd5886380231 100644 --- a/cmake/tribits/examples/tpls/Tpl4/CMakeLists.txt +++ b/cmake/tribits/examples/tpls/Tpl4/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.17.0) +cmake_minimum_required(VERSION 3.23.0) project(Tpl4 DESCRIPTION From 6b5afb308c122ea52c4b6b2c9580991efcd7131f Mon Sep 17 00:00:00 2001 From: meriadeg perrinel Date: Thu, 30 Mar 2023 14:10:15 +0200 Subject: [PATCH 3/3] changed rocblas and rocsparse order in TPLsList.cmake --- TPLsList.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TPLsList.cmake b/TPLsList.cmake index 6b6e6e9187d0..b95aff2dbfa0 100644 --- a/TPLsList.cmake +++ b/TPLsList.cmake @@ -61,10 +61,10 @@ TRIBITS_REPOSITORY_DEFINE_TPLS( CUBLAS "cmake/TPLs/" PT CUSOLVER "cmake/TPLs/" PT CUSPARSE "cmake/TPLs/" PT - ROCBLAS "cmake/TPLs/" PT - ROCSPARSE "cmake/TPLs/" PT Thrust "cmake/TPLs/" ST Cusp "cmake/TPLs/" ST + ROCBLAS "cmake/TPLs/" PT + ROCSPARSE "cmake/TPLs/" PT TBB "cmake/TPLs/" EX Pthread "cmake/TPLs/" PT HWLOC "cmake/TPLs/" ST