diff --git a/.gitignore b/.gitignore index 614cc8eabca6..19a2b3f0c2b2 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ doxygen_objdb_*.tmp # Trilinos extra repos /TriBITS/ +/TriBITS /preCopyrightTrilinos/ /DrekarBase/ /DrekarResearch/ diff --git a/RELEASE_NOTES b/RELEASE_NOTES index ad931b671a2d..572a29215f44 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -1,3 +1,97 @@ +############################################################################### +# # +# Trilinos Release 14.0 Release Notes # +# # +############################################################################### + +CMake + + - A switch to modern CMake targets in IMPORTED library targets in installed + `Config.cmake` files has been made that **breaks backward + compatibility** for some downstream CMake projects by changing how include + directories are handled: + + With the switch to modern CMake IMPORTED targets, now include directories + (along with critical compiler options and other modern CMake usage + requirements) are propagated through linking to the IMPORTED library + targets in downstream customer CMake projects. This makes the usage of + the variables `Trilinos_INCLUDE_DIRS` and `Trilinos_TPL_INCLUDE_DIRS` + unnecessary in downstream CMake projects. The variable + `Trilinos_INCLUDE_DIRS` is still set but the variable + `Trilinos_TPL_INCLUDE_DIRS` is empty in this change to modern CMake. To + get include directories for Trilinos packages and TPLs, one must link + against the Trilinos target `Trilinos::all_libs` or + `Trilinos::all_selected_libs` or by linking against the individual package + targets `::all_libs` and/or the TPL targets + `::all_libs`. To upgrade downstream CMake projects that are + showing missing include directories (i.e. header files can't be found on + the compile liens) just add `target_link_libraries()` calls with the + appropriate `::all_libs` targets for the desired package and/or + TPL. (See the section "Using the installed software in downstream CMake + projects" in the updated build reference guide.) However, backward + compatibility is maintained for most customers which are linking all of + their libraries against `${Trilinos_LIBRARIES}`. For these projects, no + changes will need to be made. + + However, this change to modern CMake targets will also cause downstream + CMake projects to pull in include directories as `SYSTEM` includes + (e.g. using `-isystem` instead of `-I`) from IMPORTED library targets. + This changes how these include directories are searched and could break + some fragile build environments that have the same header file names in + multiple include directories searched by the compiler. Also, this will + silence any regular compiler warnings from header files found under these + include directories. This constitutes a **break in backward + compatibility** that will break some customer CMake project builds that + use Trilinos on fragile environments where the search order of the include + directories is important. + + There are several different approaches for addressing this change from + `-I` to `-isystem` for the Trilinos include directories described below. + + **Approach-1:** Update to CMake 3.23 and set the Trilinos configure + variable: + + -D Trilinos_IMPORTED_NO_SYSTEM=ON + + This will change back the listing of Trilinos include directories in + downstream customer CMake projects from `-isystem` and `-I` and will + therefore restore about perfect backward compatibility. + + **Approach-2:** Set the cache variable + `CMAKE_NO_SYSTEM_FROM_IMPORTED=TRUE` in a downstream CMake project to set + which will restore the include directories for the IMPORTED library + targets for the TriBITS project as non-SYSTEM include directories + (i.e. `-I`) but it will also cause all include directories for all + IMPORTED library targets to be non-SYSTEM (i.e. `-I`) even if they were + being handled as SYSTEM include directories before. Therefore, that could + still break the downstream project as it might change what header files + are found for these other IMPORTED library targets and may expose many new + warnings (which may have been silenced by their include directories being + pulled in using `-isystem`). + + **Approach-3:** Clean up the list of include directories that is searched + by the compiler so that only the correct header files can be found + (regardless of the search order). + + **Approach-4:** Delete some header files in the set of searched include + directories so that only the correct header files can be found (regardless + of the search order). + + **Approach-5:** Use other approaches more specific to the given customer + project. For example, if multiple different versions of the googletest + (gtest) library header files can be found in the list of include + directories, then a customer project can build its own version of + googletest and put it's include directories first on the compile line and + list them with `-I` to ensure that only that version will be found, no + matter how many other versions of gtest are installed on the system. For + an example of how this was done for one customer CMake project, see + https://github.com/trilinos/Trilinos/issues/8001#issuecomment-1032827124. + + For more details on this change in the handling of include directories + with the switch to modern CMake, see + https://github.com/TriBITSPub/TriBITS/issues/443. + + ############################################################################### # # # Trilinos Release 12.12 Release Notes # diff --git a/TPLsList.cmake b/TPLsList.cmake index 776288a4866d..6844a0bfdbe8 100644 --- a/TPLsList.cmake +++ b/TPLsList.cmake @@ -71,8 +71,8 @@ TRIBITS_REPOSITORY_DEFINE_TPLS( ARPREC "packages/teuchos/cmake/tpls/" ST QD "packages/teuchos/cmake/tpls/" ST MPI "${${PROJECT_NAME}_TRIBITS_DIR}/core/std_tpls/" PT - BLAS "${${PROJECT_NAME}_TRIBITS_DIR}/common_tpls/" PT - LAPACK "${${PROJECT_NAME}_TRIBITS_DIR}/common_tpls/" PT + BLAS "cmake/TPLs/" PT + LAPACK "cmake/TPLs/" PT Boost "${${PROJECT_NAME}_TRIBITS_DIR}/common_tpls/" PT Scotch "cmake/TPLs/" ST OVIS "cmake/TPLs/" ST diff --git a/cmake/TPLs/FindTPLBLAS.cmake b/cmake/TPLs/FindTPLBLAS.cmake new file mode 100644 index 000000000000..dc04355fdd26 --- /dev/null +++ b/cmake/TPLs/FindTPLBLAS.cmake @@ -0,0 +1,80 @@ +# @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 + + +if (MSVC AND NOT + (BLAS_LIBRARY_DIRS OR + (NOT "${BLAS_LIBRARY_NAMES}" STREQUAL "blas blas_win32" AND + NOT "${BLAS_LIBRARY_NAMES}" STREQUAL "") OR + BLAS_INCLUDE_DIRS OR + BLAS_INCLUDE_NAMES OR + (NOT "${TPL_BLAS_LIBRARIES}" STREQUAL "blas" AND + NOT "${TPL_BLAS_LIBRARIES}" STREQUAL "") OR + TPL_BLAS_INCLUDE_DIRS) + ) + # Find the CLAPACK built by CMake on the machine for MSVC if found it will + # set the BLAS and LAPACK libraries. NOTE: This the FindCLAPACK module must + # be called every configure or this does not work! + # If the user has specified alternate name or location of their blas that + # will be used instead. + find_package(CLAPACK 3.2.1 NO_MODULE) + if (CLAPACK_FOUND) + advanced_set(TPL_BLAS_LIBRARIES blas + CACHE FILEPATH "Set from MSVC CLAPACK specialization") + endif() +endif() + +tribits_tpl_find_include_dirs_and_libraries( BLAS + REQUIRED_LIBS_NAMES "blas blas_win32") diff --git a/cmake/TPLs/FindTPLCUBLAS.cmake b/cmake/TPLs/FindTPLCUBLAS.cmake index 8ce61e78e661..84b2cae78edc 100644 --- a/cmake/TPLs/FindTPLCUBLAS.cmake +++ b/cmake/TPLs/FindTPLCUBLAS.cmake @@ -63,8 +63,9 @@ ELSE() IF(CUDA_cublas_LIBRARY STREQUAL "CUDA_cublas_LIBRARY-NOTFOUND") MESSAGE(FATAL_ERROR "\nCUBLAS: could not find cublas library.") ENDIF() - GLOBAL_SET(TPL_CUBLAS_LIBRARY_DIRS) - GLOBAL_SET(TPL_CUBLAS_INCLUDE_DIRS ${TPL_CUDA_INCLUDE_DIRS}) - GLOBAL_SET(TPL_CUBLAS_LIBRARIES ${CUDA_cublas_LIBRARY}) + SET(TPL_CUBLAS_LIBRARIES ${CUDA_cublas_LIBRARY}) ENDIF() +tribits_tpl_find_include_dirs_and_libraries(CUBLAS REQUIRED_LIBS_NAMES cublas) + +unset(TPL_CUBLAS_LIBRARIES) diff --git a/cmake/TPLs/FindTPLCUSOLVER.cmake b/cmake/TPLs/FindTPLCUSOLVER.cmake index 7725cc028cfc..6750944c8b24 100644 --- a/cmake/TPLs/FindTPLCUSOLVER.cmake +++ b/cmake/TPLs/FindTPLCUSOLVER.cmake @@ -63,8 +63,9 @@ ELSE() IF(CUDA_cusolver_LIBRARY STREQUAL "CUDA_cusolver_LIBRARY-NOTFOUND") MESSAGE(FATAL_ERROR "\nCUSOLVER: could not find cusolver library.") ENDIF() - GLOBAL_SET(TPL_CUSOLVER_LIBRARY_DIRS) - GLOBAL_SET(TPL_CUSOLVER_INCLUDE_DIRS ${TPL_CUDA_INCLUDE_DIRS}) - GLOBAL_SET(TPL_CUSOLVER_LIBRARIES ${CUDA_cusolver_LIBRARY}) + SET(TPL_CUSOLVER_LIBRARIES ${CUDA_cusolver_LIBRARY}) ENDIF() +tribits_tpl_find_include_dirs_and_libraries(CUSOLVER REQUIRED_LIBS_NAMES cusparse) + +unset(TPL_CUSOLVER_LIBRARIES) diff --git a/cmake/TPLs/FindTPLCUSPARSE.cmake b/cmake/TPLs/FindTPLCUSPARSE.cmake index aad1e2bad762..b6a3859d1ffa 100644 --- a/cmake/TPLs/FindTPLCUSPARSE.cmake +++ b/cmake/TPLs/FindTPLCUSPARSE.cmake @@ -68,8 +68,9 @@ ELSE() MESSAGE(FATAL_ERROR "\nCUSPARSE: could not find cuspasre library.") ENDIF() ENDIF(CMAKE_VERSION VERSION_LESS "2.8.8") - GLOBAL_SET(TPL_CUSPARSE_LIBRARY_DIRS) - GLOBAL_SET(TPL_CUSPARSE_INCLUDE_DIRS ${TPL_CUDA_INCLUDE_DIRS}) - GLOBAL_SET(TPL_CUSPARSE_LIBRARIES ${CUDA_cusparse_LIBRARY}) + SET(TPL_CUSPARSE_LIBRARIES ${CUDA_cusparse_LIBRARY}) ENDIF() +tribits_tpl_find_include_dirs_and_libraries(CUSPARSE REQUIRED_LIBS_NAMES cusparse) + +unset(TPL_CUSPARSE_LIBRARIES) diff --git a/cmake/TPLs/FindTPLCUSPARSEDependencies.cmake b/cmake/TPLs/FindTPLCUSPARSEDependencies.cmake new file mode 100644 index 000000000000..904d7ad4f545 --- /dev/null +++ b/cmake/TPLs/FindTPLCUSPARSEDependencies.cmake @@ -0,0 +1,2 @@ +tribits_extpkg_define_dependencies( CUSPARSE + DEPENDENCIES CUBLAS) diff --git a/cmake/TPLs/FindTPLLAPACK.cmake b/cmake/TPLs/FindTPLLAPACK.cmake new file mode 100644 index 000000000000..443924df0d7a --- /dev/null +++ b/cmake/TPLs/FindTPLLAPACK.cmake @@ -0,0 +1,74 @@ +# @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 + + +if (MSVC AND NOT + (LAPACK_LIBRARY_DIRS OR + (NOT "${LAPACK_LIBRARY_NAMES}" STREQUAL "lapack lapack_win32" AND + NOT "${LAPACK_LIBRARY_NAMES}" STREQUAL "") OR + LAPACK_INCLUDE_DIRS OR + LAPACK_INCLUDE_NAMES OR + (NOT "${TPL_LAPACK_LIBRARIES}" STREQUAL "lapack" AND + NOT "${TPL_LAPACK_LIBRARIES}" STREQUAL "") OR + TPL_LAPACK_INCLUDE_DIRS) + ) + if(CLAPACK_FOUND) + advanced_set(TPL_LAPACK_LIBRARIES lapack + CACHE FILEPATH "Set from MSVC CLAPACK specialization") + endif() +endif() + +tribits_tpl_find_include_dirs_and_libraries( LAPACK + REQUIRED_LIBS_NAMES "lapack lapack_win32") diff --git a/cmake/TPLs/FindTPLLAPACKDependencies.cmake b/cmake/TPLs/FindTPLLAPACKDependencies.cmake new file mode 100644 index 000000000000..0256dbbfd4dd --- /dev/null +++ b/cmake/TPLs/FindTPLLAPACKDependencies.cmake @@ -0,0 +1,2 @@ +tribits_extpkg_define_dependencies( LAPACK + DEPENDENCIES BLAS) diff --git a/cmake/TPLs/FindTPLParMETIS.cmake b/cmake/TPLs/FindTPLParMETIS.cmake index ac97987e1713..e53218627b98 100644 --- a/cmake/TPLs/FindTPLParMETIS.cmake +++ b/cmake/TPLs/FindTPLParMETIS.cmake @@ -82,9 +82,7 @@ FUNCTION(CHECK_PARMETIS_HAS_VERSION_4_0_3 VARNAME) " ) - SET(CMAKE_REQUIRED_INCLUDES ${TPL_ParMETIS_INCLUDE_DIRS}) - SET(CMAKE_REQUIRED_LIBRARIES ${TPL_ParMETIS_LIBRARIES}) - SET(CMAKE_REQUIRED_FLAGS ${CMAKE_EXE_LINKER_FLAGS}) + SET(CMAKE_REQUIRED_LIBRARIES ParMETIS::all_libs) CHECK_C_SOURCE_COMPILES("${SOURCE}" ${VARNAME}) ENDFUNCTION() diff --git a/cmake/TPLs/FindTPLParMETISDependencies.cmake b/cmake/TPLs/FindTPLParMETISDependencies.cmake new file mode 100644 index 000000000000..d999aca2b2ae --- /dev/null +++ b/cmake/TPLs/FindTPLParMETISDependencies.cmake @@ -0,0 +1,2 @@ +tribits_extpkg_define_dependencies( ParMETIS + DEPENDENCIES METIS) diff --git a/cmake/TPLs/FindTPLPthread.cmake b/cmake/TPLs/FindTPLPthread.cmake index fc401d754335..0c556c8aaa0b 100644 --- a/cmake/TPLs/FindTPLPthread.cmake +++ b/cmake/TPLs/FindTPLPthread.cmake @@ -54,29 +54,33 @@ # @HEADER -SET(USE_THREADS FALSE) +set(USE_THREADS FALSE) -IF(NOT TPL_Pthread_INCLUDE_DIRS AND NOT TPL_Pthread_LIBRARY_DIRS AND NOT TPL_Pthread_LIBRARIES) +if (NOT TPL_Pthread_INCLUDE_DIRS AND NOT TPL_Pthread_LIBRARY_DIRS + AND NOT TPL_Pthread_LIBRARIES + ) # Use CMake's Thread finder since it is a bit smarter in determining # whether pthreads is already built into the compiler and doesn't need # a library to link. - FIND_PACKAGE(Threads) + find_package(Threads) #If Threads found a copy of pthreads make sure it is one of the cases the tribits #tpl system cannot handle. - IF(Threads_FOUND AND CMAKE_USE_PTHREADS_INIT) - IF(CMAKE_THREAD_LIBS_INIT STREQUAL "" OR CMAKE_THREAD_LIBS_INIT STREQUAL "-pthread") - SET(USE_THREADS TRUE) - ENDIF() - ENDIF() -ENDIF() + if (Threads_FOUND AND CMAKE_USE_PTHREADS_INIT) + if(CMAKE_THREAD_LIBS_INIT STREQUAL "" OR CMAKE_THREAD_LIBS_INIT STREQUAL "-pthread") + set(USE_THREADS TRUE) + set(TPL_Pthread_INCLUDE_DIRS "") + set(TPL_Pthread_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}") + set(TPL_Pthread_LIBRARY_DIRS "") + endif() + endif() +endif() -IF(USE_THREADS) - SET(TPL_Pthread_INCLUDE_DIRS "") - SET(TPL_Pthread_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}") - SET(TPL_Pthread_LIBRARY_DIRS "") -ELSE() - TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES( Pthread +if (USE_THREADS AND CMAKE_THREAD_LIBS_INIT STREQUAL "") + # Produce dummy Pthread::all_libs target and PthreadConfig.cmake file + tribits_tpl_find_include_dirs_and_libraries(Pthread) +else() + tribits_tpl_find_include_dirs_and_libraries( Pthread REQUIRED_HEADERS pthread.h REQUIRED_LIBS_NAMES pthread - ) -ENDIF() + ) +endif() diff --git a/cmake/TPLs/FindTPLScotch.cmake b/cmake/TPLs/FindTPLScotch.cmake index f4de130a3c99..22c4c7c24860 100644 --- a/cmake/TPLs/FindTPLScotch.cmake +++ b/cmake/TPLs/FindTPLScotch.cmake @@ -94,9 +94,7 @@ FUNCTION(CHECK_SCOTCH_VERSION_6_0_3 VARNAME) } " ) - SET(CMAKE_REQUIRED_INCLUDES ${TPL_Scotch_INCLUDE_DIRS}) - SET(CMAKE_REQUIRED_LIBRARIES ${TPL_Scotch_LIBRARIES}) - SET(CMAKE_REQUIRED_FLAGS ${CMAKE_EXE_LINKER_FLAGS}) + SET(CMAKE_REQUIRED_LIBRARIES Scotch::all_libs) CHECK_C_SOURCE_COMPILES("${SOURCE}" ${VARNAME}) ENDFUNCTION() diff --git a/cmake/TPLs/FindTPLSuperLU.cmake b/cmake/TPLs/FindTPLSuperLU.cmake index 6ab392ccac8c..aaf9033feaeb 100644 --- a/cmake/TPLs/FindTPLSuperLU.cmake +++ b/cmake/TPLs/FindTPLSuperLU.cmake @@ -89,9 +89,7 @@ int main() " ) - SET(CMAKE_REQUIRED_INCLUDES ${TPL_SuperLU_INCLUDE_DIRS}) - SET(CMAKE_REQUIRED_LIBRARIES ${TPL_SuperLU_LIBRARIES} ${TPL_METIS_LIBRARIES} ${TPL_BLAS_LIBRARIES}) - SET(CMAKE_REQUIRED_FLAGS ${CMAKE_EXE_LINKER_FLAGS}) + SET(CMAKE_REQUIRED_LIBRARIES SuperLU::all_libs) CHECK_C_SOURCE_COMPILES("${SOURCE}" ${VARNAME}) ENDFUNCTION() diff --git a/cmake/TPLs/FindTPLSuperLUDependencies.cmake b/cmake/TPLs/FindTPLSuperLUDependencies.cmake new file mode 100644 index 000000000000..47a938258d0d --- /dev/null +++ b/cmake/TPLs/FindTPLSuperLUDependencies.cmake @@ -0,0 +1,2 @@ +tribits_extpkg_define_dependencies( SuperLU + DEPENDENCIES ParMETIS BLAS) diff --git a/cmake/TPLs/FindTPLSuperLUDist.cmake b/cmake/TPLs/FindTPLSuperLUDist.cmake index 233e173b3d0e..249f05879263 100644 --- a/cmake/TPLs/FindTPLSuperLUDist.cmake +++ b/cmake/TPLs/FindTPLSuperLUDist.cmake @@ -79,8 +79,7 @@ int main() " ) - SET(CMAKE_REQUIRED_INCLUDES ${TPL_SuperLUDist_INCLUDE_DIRS}) - SET(CMAKE_REQUIRED_LIBRARIES ${TPL_SuperLUDist_LIBRARIES} ${TPL_ParMETIS_LIBRARIES} ${TPL_METIS_LIBRARIES} ${TPL_BLAS_LIBRARIES}) + SET(CMAKE_REQUIRED_LIBRARIES SuperLUDist::all_libs) SET(CMAKE_REQUIRED_FLAGS ${CMAKE_EXE_LINKER_FLAGS}) CHECK_C_SOURCE_COMPILES("${SOURCE}" ${VARNAME}) ENDFUNCTION() @@ -101,8 +100,7 @@ int main() " ) - SET(CMAKE_REQUIRED_INCLUDES ${TPL_SuperLUDist_INCLUDE_DIRS}) - SET(CMAKE_REQUIRED_LIBRARIES ${TPL_SuperLUDist_LIBRARIES} ${TPL_ParMETIS_LIBRARIES} ${TPL_METIS_LIBRARIES} ${TPL_BLAS_LIBRARIES}) + SET(CMAKE_REQUIRED_LIBRARIES SuperLUDist::all_libs) SET(CMAKE_REQUIRED_FLAGS ${CMAKE_EXE_LINKER_FLAGS}) CHECK_C_SOURCE_COMPILES("${SOURCE}" ${VARNAME}) ENDFUNCTION() diff --git a/cmake/TPLs/FindTPLSuperLUDistDependencies.cmake b/cmake/TPLs/FindTPLSuperLUDistDependencies.cmake new file mode 100644 index 000000000000..d0419545d2cd --- /dev/null +++ b/cmake/TPLs/FindTPLSuperLUDistDependencies.cmake @@ -0,0 +1,2 @@ +tribits_extpkg_define_dependencies( SuperLUDist + DEPENDENCIES ParMETIS BLAS) diff --git a/cmake/std/atdm/cee-rhel7/environment.sh b/cmake/std/atdm/cee-rhel7/environment.sh index f1e5311a6f6b..b949cb70c00c 100755 --- a/cmake/std/atdm/cee-rhel7/environment.sh +++ b/cmake/std/atdm/cee-rhel7/environment.sh @@ -195,11 +195,6 @@ fi # to be safe. Also, we need to set OMP_* env vars here because the SPARC # modules change them! -# Use updated Ninja and CMake -module load sems-archive-env -module load sems-archive-cmake/3.19.1 -module load sems-archive-ninja_fortran/1.8.2 - export ATDM_CONFIG_USE_HWLOC=OFF export ATDM_CONFIG_BINUTILS_LIBS="/usr/lib64/libbfd.so;/usr/lib64/libiberty.a" diff --git a/cmake/tribits/CHANGELOG.md b/cmake/tribits/CHANGELOG.md new file mode 100644 index 000000000000..20ca6f378e41 --- /dev/null +++ b/cmake/tribits/CHANGELOG.md @@ -0,0 +1,445 @@ +---------------------------------------- +ChangeLog for TriBITS +---------------------------------------- + +## 2022-07-14: + +* **Added:** Added support for `FindTPLDependencies.cmake` with new + macro `tribits_extpkg_define_dependencies()` that sets + `_LIB_ALL_DEPENDENCIES`. Now `_LIB_ENABLED_DEPENDENCIES` + is automatically set from `_LIB_ALL_DEPENDENCIES` based on what + TPLs are actaully enabled. This avoids the problem described below from + directly setting `_LIB_ENABLED_DEPENDENCIES` without reguard to + what TPLs are actaully enabled. This maintains backward compatibility for + existing configure scripts where an upstream TPL may not be enabled in some + strange configure scripts (see + [TriBITSPub/TriBITS#494](https://github.com/TriBITSPub/TriBITS/issues/494)). + +## 2022-05-25: + +* **Changed:** Dependencies between external packages (TPLs) must now be + specified in order for correct linkage. No longer will listing the external + packages (TPLs) in the correct order in the `/TPLsList.cmake` file + and listing all upstream external packages (TPLs) in + `/cmake/Dependencies.cmake` be sufficient. For now, + dependencies between external packages (TPLs) can be set in the + `/TPLsList.cmake` file by setting the cache var + `_LIB_ENABLED_DEPENDENCIES` for each downstream external package + (TPL). (See + [`TribitsExampleProject2/TPLsList.cmake`](https://github.com/TriBITSPub/TriBITS/blob/master/tribits/examples/TribitsExampleProject2/TPLsList.cmake) + for an example.) Later, a more scalable approach for setting these vars + will be devised. However, this means it is no longer necessary for a + package to list all of its upstream external packages/TPLs, only its direct + dependencies. + +* **Changed:** All compliant external packages (TPLs) must now set the + imported target `::all_libs` in their `FindTPL.cmake` + files instead of the variables `TPL__INCLUDE` and + `TPL__LIBRARIES`. + +* **Changed:** The project-level variables `_INCLUDE_DIRS`, + `_TPL_INCLUDE_DIRS`, `_LIBRARY_DIRS` and + `_TPL_LIBRARY_DIRS` from the file `Config.cmake` and + package-level variables `_INCLUDE_DIRS`, + `_TPL_INCLUDE_DIRS`, `_LIBRARY_DIRS` and + `_TPL_LIBRARY_DIRS` from the installed files + `Config.cmake` are now set to empty. Downstream CMake projects + will need to link against the exported project-level target + `::all_libs` or `::all_selected_libs` or the package-level + targets `::all_libs` in order to get the list of include + directories that are propagated through those targets by CMake. + +* **Changed:** The function `tribits_add_library()` no longer sets the + directory property `INCLUDE_DIRECTORIES` and instead passes include + directory information between targets directly using the + `INTERFACE_INCLUDE_DIRECTORIES` target property. This may result in + situations where include directories were getting set through the directory + property `INCLUDE_DIRECTORIES` and getting picked up in the builds of + targets that lacked the proper library dependencies. Therefore, this is + technically a break in backward compatibility, but not for well-formed + TriBITS projects. + +* **Changed:** Variables `${PACKAGE_NAME}_ENABLE_` are now set to + `TRUE` for required upstream internal and external packages/TPLs `` + (in order to simplify internal TriBITS logic). However, a side-effect of + this change is that CMake code that was ifed out with an `if + (${PACKAGE_NAME}_ENABLE_)` statement (because that variable was not + defined and therefore defaults to `FLASE`) for a required upstream + dependency `` will now be enabled. (This mistake can happen when an + optional dependency `` is changed to a required dependency but the + `if()` statements based on `${PACKAGE_NAME}_ENABLE_` are not + removed. Well-formed TriBITS projects and packages should not experience + this problem or notice any change.) + +## 2022-05-16: + +* **Added:** The function `tribits_add_advanced_test(`) now correctly accepts + a list of regexes for `PASS_REGULAR_EXPRESSION` and + `FAIL_REGULAR_EXPRESSION` and behave the same as the raw CTest properties of + the same names. + +## 2022-03-10: + +* **Changed:** The `tribits_add_advanced_test()` command now correctly reports + unparsed/unrecognized arguments. This will break some sloppy usages. (One + TriBITS test had to be fixed.) + +* **Changed:** The `tribits_add_test()` and `tribits_add_advanced_test()` + behave differently with data passed in with explicit colon arguments. For + example, before `PASS_REGULAR_EXPRESSION ";"` could be used + to pass in a list of regular expressions but with the new handling of + function arguments, this now gets set as a single regex + `"\\;"` which is not the same. The fix (that also works + with older versions of TriBITS) is to pass in multiple regexes as separate + arguments as `PASS_REGULAR_EXPRESSION "" ""`. + +* **Added:** The `tribits_add_test()`, `tribits_add_advanced_test()`, and + `tribits_add_executable_and_test()` functions now allow handling semi-colons + ';' in the quoted arguments to CMND/EXEC `ARGS` and `ENVIRONMENT` variable + values by adding a `LIST_SEPARATOR ` argument (same as for + `ExternalProject_Add()`). + +* **Changed:** The `tribits_add_test()` and `tribits_add_advanced_test()` + functions switched over from using `cmake_parse_arguments(... ${ARGN})` to + using `cmake_parse_arguments(PARSE_ARGV ...)` and, therefore, now will no + longer ignore empty arguments. This will break backward compatibility for + cases where empty quoted arguments like `"${SomeVar}"` are passed in where + the variable `SomeVar` is empty. + +## 2022-03-02: + +* **Added:** The project-level cache variable `_IMPORTED_NO_SYSTEM` + was added to set the `IMPORTED_NO_SYSTEM` property (CMake versions 3.23+ + only) on the IMPORTED library targets in the installed + `Config.cmake` files (see updated TriBITS users guide and build + reference documentation for `_IMPORTED_NO_SYSTEM`). Setting this + to `ON` results in the include directories for this project's IMPORTED + library targets to be listed on the compile lines in downstream CMake + projects using `-I` instead of the default `-isystem` for IMPORTED library + targets. Setting this option to `ON` returns backward compatibility for the + move to modern CMake targets which involved setting the include directories + on the IMPORTED library targets using `target_include_directories()` + described below (which changed the include directories from being listed as + `-I` to `-isystem` by default).
**Workaround:** As a workaround for + CMake versions less than 3.23, downstream CMake projects can set + `CMAKE_NO_SYSTEM_FROM_IMPORTED=TRUE` in their CMake configure as described + below.
For more details, see + [TriBITSPub/TriBITS#443](https://github.com/TriBITSPub/TriBITS/issues/443). + +## 2021-11-18: + +* **Changed:** The default `_GENERATE_REPO_VERSION_FILE_DEFAULT` will + be overridden to `OFF` if the 'git' executable cannot be found at configure + time. See updated TriBITS Developer's Guide documentation. + +* **Changed:** The default value for `_ENABLE_Fortran` is set to + `OFF` on WIN32 systems. (Getting a Fortran compiler for native Windows is + not typically very easy.) + +## 2021-10-11 + +* **Changed:** The `Config.cmake` for each enabled package generated + in the build directory tree have been moved from + `/packages//` to + `/cmake_packages//`. (This makes it easy for + `find_package()` to find these files by simply adding the + directory `/cmake_packages` to `CMAKE_PREFIX_PATH` and then + `Config.cmake` for any enabled package will be found automatically + found by CMake.) + +* **Added/Changed:** Added the include directories for each library target + with `target_include_directories()`. This makes the usage of the variables + `_INCLUDE_DIRS`, `_TPL_INCLUDE_DIRS`, + `_INCLUDE_DIRS`, and `_TPL_INCLUDE_DIRS` unnecessary by + downstream CMake projects. (See the changes to the + `TribitsExampleApp/CmakeLists.txt` file that removed calls to + `include_directories()` involving these variables.) However, this change + will also cause downstream CMake projects to pull in include directories as + `SYSTEM` includes (e.g. using `-isystem` instead of `-I`) from IMPORTED + library targets. This changes how these include directories are searched + and could break some fragile build environments that have the same header + file names in multiple include directories searched by the compiler. + Changing to `-isystem` will also silence any regular compiler warnings from + headers found under these include directories.
***Workarounds:*** One + workaround for this is for the downstream CMake project to set the cache + variable `CMAKE_NO_SYSTEM_FROM_IMPORTED=TRUE` which will restore the include + directories for the IMPORTED library targets for the TriBITS project as + non-SYSTEM include directories (i.e. `-I`) but it will also cause all + include directories for all IMPORTED library targets to be non-SYSTEM + (i.e. `-I`) even if they were being handled as SYSTEM include directories + using `-isystem` before. Therefore, that could still break the downstream + project as it might change what header files are found for these other + IMPORTED library targets and may expose many new warnings (which may have + been silenced by their include directories being pulled in using + `-isystem`). The other workaround would be to clean up the list of include + directories or delete some header files in those include directories so that + only the correct header files can be found (regardless of the include + directory search order). For more details, see + [TriBITSPub/TriBITS#443](https://github.com/TriBITSPub/TriBITS/issues/443). + +## 2021-09-13 + +* **Removed:** Support for generation and installation of `Makefile.export.*` + files has been removed along with the cache variable + `_ENABLE_EXPORT_MAKEFILES`. This is to allow the refactoring of + TriBITS to use modern CMake targets that propagate all information and + removing complex dependency tracking information from TriBITS (see + TriBITSPub/TriBITS#63 and TriBITSPub/TriBITS#299). + +## 2021-06-17 + +* **Added:** Added tool `tribits/python_utils/lower_case_cmake.py` and driver + `tribits/refactoring/lower-case-cmake-tree.sh` that can make CMake command + calls lower-case and make macro and function definition names lower case. + This was applied to the entire TriBITS repository (and then minor + modifications to fix a few issues). This should not impact users of TriBITS + but it does change the case of commands in the TriBITS error messages. (See + TriBITSPub/TriBITS#274) + +## 2021-05-15 + +* **Changed/Fixed:** Changed so that all arguments passed to `ctest -S` + command in 'dashboard' target are passed if their value is non-empty instead + of `TRUE`. Also, `CTEST_BUILD_NAME`, `TRIBITS_2ND_CTEST_DROP_SITE` and + `TRIBITS_2ND_CTEST_DROP_LOCATION` can now be set and overridden in the CMake + configure and will get passed to the `ctest -S` command by the 'dashboard' + target. This now allows setting these latter vars to `OFF` or `FALSE` which + allows skipping a submit to a secondary CDash site if the underlying project + is set up to submit to a secondary CDash site by default (see + trilinos/Trilinos#9079). These changes technically break backward + compatibility because now setting some vars in the CMake configure will now + get passed on to `ctest -S` command in the 'dashboard' target and some vars + set in the env when calling 'make dashboard' will now be ignored if they + were set in the CMake cache. But many of these vars are only forwarded to + the ctest -S command in the env if they are set to non-empty in the + configure. So existing processes that set `CTEST_BUILD_NAME` in the env + when running `make dashboard` but not in the CMake configure will still + behave the same (which is why no existing TriBITS tests had to change). For + these reasons, the chance of these changes causing a problem for most users + should be very small and in fact it restores what most people would consider + to be logical and useful behavior. + +## 2021-03-12 + +* **Changed:** Upgrade minimum required CMake version from 3.10 to 3.17. Existing + TriBITS projects that have already upgraded to require CMake 3.17+ should not + notice any major changes due to this change. + +## 2020-11-12 + +* **Changed:** The default for `_ENABLE_EXPLICIT_INSTANTIATION` (ETI) + was changed from `OFF` to `ON`. This was turned on in practice for almost + all users of Trilinos so while this change technically breaks backward + compatibility of TriBITS, in practice, this will likely not impact any + important customers. (And new customers of Trilinos and related TriBITS + projects will enjoy the benefits of ETI by default. See + trilinos/Trilinos#8130.) + +## 2020-10-08 + +* **Changed:** Tests defined with `TRIBITS_ADD_TEST()` and + `TRIBITS_ADD_ADVANCED_TEST()` with `NUM_MPI_PROCS > 1` will now not be + added for non-MPI (`TPL_ENABLE_MPI=OFF`) configurations. Before, the test + would get added and basically ignore the value of `NUM_MPI_PROCS`. This + change together with the change to move to using `add_test(NAME + COMMAND )` mostly restores backward compatibility for projects + using TriBITS. For more details, see trilinos/Trilinos#8110. + +## 2020-09-28 + +* **Changed/Fixed:** Tests defined with `TRIBITS_ADD_TEST()` and + `TRIBITS_ADD_ADVANCED_TEST()` have been updated from using + `add_test( )` to using `add_test(NAME COMMAND + )`. This now causes CMake to error-out if there is more than one + test with the same name in the same directory. Before, CMake would allow + it (but the behavior in that case was undocumented and undefined). For + more details, see trilinos/Trilinos#8110. + +## 2020-06-16 + +* **Added/Deprecated:** The variables `_FORTRAN_COMPILER` and + `_FORTRAN_FLAGS` in the `Config.cmake` files (in the build + dir and the install dir) are deprecated. Please use the new variables + `_Fortran_COMPILER` and `_Fortran_FLAGS`. (Justification: + In raw CMake, the compiler is called 'Fortran', not 'FORTRAN'. Also, the + name 'Fortran' is already used in the `Config.cmake` file.) + +## 2020-04-16 + +* **Changed/Removed:** TriBITS Core: `CMAKE_CXX_STANDARD` is now always set to + at least `11` to enable C++11 support. The `${PROJECT_NAME}_ENABLE_CXX11` + option has been removed, but a variable of the same name is hard-coded to ON + for compatibility. + +* **Changed/Removed:** TriBITS Core: `CMAKE_CXX_FLAGS` will no longer contain + an explicit C++ standard option like `-std=c++11`. TriBITS clients' + dependents using CMake will still compile with support for C++11 language + constructs because libraries come with `INTERFACE_COMPILE_FEATURES` + including `cxx_std_11`. However, those using `Makefile.export.` + files will no longer get a `-std=c++11` flag. + +## 2018-10-10 + +* **Changed:** TriBITS Core: Changed minimum CMake version from 2.8.11 to + 3.10.0. + +## 2017-09-25 + +* **Added:** TriBITS CTest Driver: Added cache and env vars + `CTEST_SUBMIT_RETRY_COUNT` and `CTEST_SUBMIT_RETRY_DELAY` to allow the + number of `ctest_submit()` submit attempts to retry and how long to pause + between retries. Before, these were hard-coded to 25 and 120 respectively, + which means that something like a MySQL insertion error could consume as + much as 50 minutes before moving on! The new defaults are set at 5 retries + with a 3 sec delay (which appear to be the CTest defaults). + +## 2017-09-30 + +* **Added:** TriBITS Core: Added `TEST_ COPY_FILES_TO_TEST_DIR` block for + `TRIBITS_ADD_ADVANCED_TEST()`. This was added in such a way so to avoid + clashing with existing usages of the script (since the new arguments + `SOURCE_DIR` and `DEST_DIR` are only parsed if `COPY_FILES_TO_TEST_DIR` is + listed in the `TEST_ block`. + +## 2017-09-05 + +* **Changed:** TriBITS Core: Un-parsed and otherwise ignored arguments to many + TriBITS functions and macros are now flagged (see developers guide + documentation for `${PROJECT_NAME}_CHECK_FOR_UNPARSED_ARGUMENTS`). The + default value is `WARNING` which results in simply printing a warning but + allow configure to complete. This allows one to see the warnings but for + the project to continue to work as before. But this can be changed to + `SEND_ERROR` or `FATAL_ERROR` that will fail the configure. + +## 2017-06-24 + +* **Added:** TriBITS CTest Driver: Add new all-at-once mode for `ctest -S` + driver scripts using `TRIBITS_CTEST_DRIVER()` by setting the variable + `${PROJECT_NAME}_CTEST_DO_ALL_AT_ONCE=TRUE`. This works with older versions + of CMake/CTest and CDash but, by default, will just return a single glob of + results, not breaking-out results on a package-by-package basis. Therefore, + this is disabled by default and package-by-package mode is used by default. + But if `${PROJECT_NAME}_CTEST_USE_NEW_AAO_FEATURES=TRUE` is set, then + TriBITS will take advantage of new CMake, CTest, and CDash features + (currently on a branch) to display the results on CDash broken down + package-by-package. Once these changes are merged to the CMake/CTest and + CDash 'master' branches, then the default for + `${PROJECT_NAME}_CTEST_USE_NEW_AAO_FEATURES` will be set to `TRUE` + automatically when it detects an updated version of CMake/CTest is present. + In the future, at some point, the TriBITS default for + `${PROJECT_NAME}_CTEST_DO_ALL_AT_ONCE` will change from `FALSE` to `TRUE` + since that is a much more efficient way to drive automated testing. + +## 2017-05-25 + +* **Added/Deprecated:** TriBITS Core: The usage of `PARSE_ARGUMENTS()` has + been deprecated and replaced by `CMAKE_PARSE_ARGUMENTS()` everywhere in + TriBITS. Any call to `PARSE_ARGUMENTS()` will warn users and tell them to + use `CMAKE_PARSE_ARGUMENTS()` instead. + +## 2017-05-17 + +* **Changed:** TriBITS Core: TriBITS now unconditionally sets + `${PROJECT_NAME}_ENABLE_Fortran_DEFAULT` to `ON`. Projects will now need to + put in special logic to set to `OFF` or `ON` for certain platforms. + +## 2017-01-11 + +* **Changed/Fixed:** TriBITS Core: TriBITS now correctly sets the default + value for DART_TESTING_TIMEOUT to 1500 seconds and will scale it by + `_SCALE_TEST_TIMEOUT` even if `DART_TESTING_TIMEOUT` is not + explicitly set. + +## 2016-12-07 + +* **Removed:** TriBITS Core: The long deprecated variable + `${PROJECT_NAME}_ENABLE_SECONDARY_STABLE_CODE` has been removed. Upgrading + existing TriBITS projects just requires a simple string replacement of + `_ENABLE_SECONDARY_STABLE_CODE` with `_ENABLE_SECONDARY_TESTED_CODE` in all + files. Since Trilinos has turned on ST code by default and many other + TriBITS projects don't differentiate between PT and ST code, this change + should not even break those projects, even if they don't update. + +## 2016-11-02 + +* **Added/Changed/Removed:** TriBITS Python Utils: gitdist now accepts + `--dist-repos` and `--dist-not-repos` arguments and requires that the base + repo '.' be explicitly listed in the `.gitdist[.default]` files and in + `--dist-repos`. The arguments `--dist-extra-repos`, + `--dist-not-extra-repos` and `--dist-not-base-repo` are not longer + supported. See `gitdist --help` for more details. + +* **Changed:** TriBITS projects now install with full RPATH set by default + (see "Setting install RPATH" in build reference guide). + +## 2016-10-22 + +* **Changed:** TriBITS Core: `TRIBITS_ADD_TEST()` argument for + `FAIL_REGULAR_EXPRESSION` now works when circular RCP detection is enabled. + This is technically a break in backward compatibility since now that + argument will not be ignored and any tests that specified this may change + behavior. + +* **Changed:** TriBITS Core: `TRIBITS_ADD_ADVANCED_TEST()` block `TEST_` + argument `FAIL_REGULAR_EXPRESSION` now works. Before, it was just being + ignored. This is technically a break in backward compatibility since now + that argument will not be ignored and any tests that specified this may + change behavior. + +* **Added/Changed:** TriBITS Core: Added `TRIBITS_ADD_ADVANCED_TEST()` block + `TEST_` option `WILL_FAIL` that has the same behavior as the built-in + CTest option `WILL_FAIL`. Note that this technically can break backward + compatibility since `WILL_FAIL` may have been interpreted to be a value from + another argument and now will not. + +## 2016-01-22 + +* **Added/Deprecated:** TriBITS Core: Change test category `WEEKLY` to `HEAVY` + and depreciate `WEEKLY`. You can still use `WEEKLY` but it will result in a + lot of warnings. + +## 2015-12-03 + +* **Added:** TriBITS CI Support: `checkin-test.py`: Added support for tracking + branches for each repo independently and not assume 'origin' and not assume + that all of the repos are on the same branch or will be pulling and pushing + to the same remote branch. This will make it easier to use the + `checkin-test.py` script to set up various integration scenarios. See + TriBITSPub/TriBITS#15 for details. + +## 2015-04-14 + +* MAJOR: TriBITS Core: When configuring with + ${PROJECT_NAME}_ENABLE_CXX11=ON, if C++11 support cannot be verified, then + the configure will fail hard right away. Before, TriBITS would disable + C++11 support and continue. + +## 2014-11-22 + +* **Added:** TriBITS Core: Added `${PROJECT_NAME}_TRACE_ADD_TEST`: Now you can + print a single line to STDOUT if a test got added (and its important + properties) or not and if not then why the test did not get added. + +## 2014-09-22 + +* **Changed:** TriBITS Core: Changed minimum version of CMake from 2.7 to + 2.8.11. + +## 2014-09-21 + +* **Added:** TriBITS Dashboard Driver: Added support for the env var + `TRIBITS_TDD_USE_SYSTEM_CTEST` so that if equal to `1`, then the TriBITS + Dashboard Driver (TDD) system will use the CTest (and CMake) in the env will + be used instead of being downloaded using `download-cmake.py`. This not + only speeds up the automated builds, but it also ensures that the automated + testing uses exactly the install of CMake/CTest that is used by the + developers on the system. Also, it has been found that `download-cmake.py` + will download and install a 32bit version even on 64bit machines. + + diff --git a/cmake/tribits/ReleaseNotes.txt b/cmake/tribits/ReleaseNotes.txt deleted file mode 100644 index 021bed044532..000000000000 --- a/cmake/tribits/ReleaseNotes.txt +++ /dev/null @@ -1,288 +0,0 @@ ----------------------------------------- -Release Notes for TriBITS ----------------------------------------- - -2021/06/17: - -(*) MINOR: Added tool tribits/python_utils/lower_case_cmake.py and driver - tribits/refactoring/lower-case-cmake-tree.sh that can make CMake command - calls lower-case and make macro and function definition names lowe case. - This was applied to the entire TriBITS repository (and then minor - modifications for fix a few issues). This should not impact users of - TriBITS but it does change the case of commands in the TriBITS error - messages. (See TriBITSPub/TriBITS#274) - -2021/05/15: - -(*) MAJOR: Changed so that all arguments passed to ctest -S command in - 'dashboard' target are passed if their value is non-empty instead of TRUE. - Also, CTEST_BUILD_NAME, TRIBITS_2ND_CTEST_DROP_SITE and - TRIBITS_2ND_CTEST_DROP_LOCATION can now be set and overridden in the CMake - configure and will get passed to the ctest -S command by the 'dashboard' - target. This now allows setting these latter vars to 'OFF' or 'FALSE' - which allows skipping a submit to a secondary CDash site if the underlying - project is set up to submit to a secondary CDash site by default (see - trilinos/Trilinos#9079). These changes technically break backward - compatibility because now setting some vars in the CMake configure will - now get passed on to ctest -S command in the 'dashboard' target and some - vars set in the env when calling 'make dashboard' will now be ignored if - they were set in the CMake cache. But many of these vars are only - forwarded to the ctest -S command in the env if they are set to non-empty - in the configure. So existing processes that set CTEST_BUILD_NAME in the - env when running 'make dashboard' but not in the CMake configure will - still behave the same (which is why no existing TriBITS tests had to - change). For these reasons, the chance of these changes causing a problem - for most users should be very small and in fact it restores what most - people would consider to be logical and useful behavior. - -2021/03/12: - -(*) MAJOR: Upgrade minimum required CMake version from 3.10 to 3.17. Existing - TriBITS projects that have already upgraded to require CMake 3.17+ should not - notice any major changes due to this change. - -2020/11/12: - -(*) MAJOR: The default for `_ENABLE_EXPLICIT_INSTANTIATION` (ETI) was - changed from `OFF` to `ON`. This was turned on in practice for almost all - users of Trilinos so while this change technically breaks backward - compatibility of TriBITS, in practice, this will likely not impact any - important customers. (And new customers of Trilinos and related TriBITS - projects will enjoy the benefits of ETI by default. See - trilinos/Trilinos#8130.) - -2020/10/08: - -(*) MAJOR: Tests defined with `TRIBITS_ADD_TEST()` and - `TRIBITS_ADD_ADVANCED_TEST()` with `NUM_MPI_PROCS > 1` will now not be - added for non-MPI TPL_ENABLE_MPI=OFF configurations. Before, the test - would get added and basically ignore the value of `NUM_MPI_PROCS`. This - change together with the change to move to using `add_test(NAME - COMMAND )` mostly restores backward compatibility for projects - using TriBITS. For more details, see trilinos/Trilinos#8110. - -2020/09/28: - -(*) MAJOR: Tests defined with `TRIBITS_ADD_TEST()` and - `TRIBITS_ADD_ADVANCED_TEST()` have been updated from using - `add_test( )` to using `add_test(NAME COMMAND - )`. This now causes CMake to error out if there is more than one - test with the same name in the same directory. Before, CMake would allow - it (but the behavior in that case was undocumented and undefined). For - more details, see trilinos/Trilinos#8110. - -2020/06/16: - -(*) MINOR: The variables _FORTRAN_COMPILER and - _FORTRAN_FLAGS in the Config.cmake files (in the build - dir and the install dir) are deprecated. Please use the new variables - _Fortran_COMPILER and _Fortran_FLAGS. (Justification: - In raw CMake, the compiler is called 'Fortran', not 'FORTRAN'. Also, the - name 'Fortran' is already used in the Config.cmake file.) - -2020/04/16: - -(*) MAJOR: TriBITS Core: CMAKE_CXX_STANDARD is now always set to at least 11 - to enable C++11 support. The ${PROJECT_NAME}_ENABLE_CXX11 option has been - removed, but a variable of the same name is hard-coded to ON for - compatibility. - -(*) MAJOR: TriBITS Core: CMAKE_CXX_FLAGS will no longer contain an explicit - C++ standard option like '-std=c++11'. TriBITS clients' dependents - using CMake will still compile with support for C++11 language constructs - because libraries come with INTERFACE_COMPILE_FEATURES including cxx_std_11. - However, those using Makefile.export. files will no longer get - a '-std=c++11` flag from TriBITS. - -2018/10/10: - -(*) MAJOR: TriBITS Core: Changed minimum CMake version from 2.8.11 to 3.10.0. - -2017/09/25: - -(*) MINOR: TriBITS CTest Driver: Added cache and env vars - CTEST_SUBMIT_RETRY_COUNT and CTEST_SUBMIT_RETRY_DELAY to allow the number - of ctest_submit() submit attempts to retry and how how log to pause - between retries. Before, these were hard-coded to 25 and 120 - respectively, which means that something like a MySQL insertion error - could consume as much as 50 minutes before moving on! The new defaults are - set at 5 retries with a 3 sec delay (which appear to be the CTest - defaults). - -2017/09/30: - -(*) MINOR: TriBITS Core: Added TEST_ COPY_FILES_TO_TEST_DIR block for - TRIBITS_ADD_ADVANCED_TEST(). This was added in such a way so to avoid - clashing with existing usages of the script (since the new arguments - SOURCE_DIR and DEST_DIR are only parsed if COPY_FILES_TO_TEST_DIR is - listed in the TEST_ block. - -2017/09/05: - -(*) MINOR: TriBITS Core: Un-parsed and otherwise ignored arguments are now - flagged (see developers guide documentation for - ${PROJECT_NAME}_CHECK_FOR_UNPARSED_ARGUMENTS). The default value is - 'WARNING' which results in simply printing a warning but allow configure - to complete. This allows one to see the warnings but for the project to - continue to work as before. But this can be changed to 'SEND_ERROR' or - 'FATAL_ERROR' that will fail the configure. - -2017/06/24: - -(*) MINOR: TriBITS CTest Driver: Add new all-at-once more for CTest -S driver - scripts using TRIBITS_CTEST_DRIVER() by setting the variable - ${PROJECT_NAME}_CTEST_DO_ALL_AT_ONCE=TRUE. This works with older versions - of CMake/CTest and CDash but, by default, will just return a single glob - of results, not breaking results out package-by-package. Therefore, this - is disabled by default and package-by-package mode is used by default. - But if ${PROJECT_NAME}_CTEST_USE_NEW_AAO_FEATURES=TRUE is set, then - TriBITS will take advantage of new CMake, CTest, and CDash features - (currently on a branch) to display the results on CDash broken down - package-by-package. Once these changes are merged to the CMake/CTest and - CDash 'master' branches, then the default for - ${PROJECT_NAME}_CTEST_USE_NEW_AAO_FEATURES will be set to TRUE - automatically when it detects an updated version of CMake/CTest is - present. In the future, at some point, the TriBITS default for - ${PROJECT_NAME}_CTEST_DO_ALL_AT_ONCE will change from FALSE to TRUE since - that is a much more efficient way to drive automated testing. - -2017/05/25: - -(*) MINOR: TriBITS Core: PARSE_ARGUMENTS() has been deprecated and replaced by - CMAKE_PARSE_ARGUMENTS() everywhere in TriBITS. Any call to - PARSE_ARGUMENTS() will warn users and tell them to use - CMAKE_PARSE_ARGUMENTS() instead. - -2017/05/17: - -(*) MAJOR: TriBITS Core: TriBITS now unconditionally sets - ${PROJECT_NAME}_ENABLE_Fortran_DEFAULT to ON. Projects will now need to - put in special logic to set to OFF or ON for certain platforms. - -2017/01/11: - -(*) MINOR: TriBITS Core: TriBITS now correctly sets the default value for - DART_TESTING_TIMEOUT to 1500 seconds and will scale it by - _SCALE_TEST_TIMEOUT even if DART_TESTING_TIMEOUT is not - explicitly set. - -2016/12/07: - -(*) MAJOR: TriBITS Core: The long deprecated variable - ${PROJECT_NAME}_ENABLE_SECONDARY_STABLE_CODE has been removed. Upgrading - existing TriBITS projects just requires a simple string replacement of - _ENABLE_SECONDARY_STABLE_CODE with _ENABLE_SECONDARY_TESTED_CODE in all - files. Since Trilinos has turned on ST code by default and many other - TriBITS projects don't differentiate between PT and ST code, this change - should not even break those projects, even if they don't update. - -2016/11/02: - -(*) MAJOR: TriBITS Python Utils: gitdist now accepts --dist-repos and - --dist-not-repos arguments and requires that the base repo '.' be - explicitly listed in the .gitdist[.default] files and in --dist-repos. - The arguments --dist-extra-repos, --dist-not-extra-repos and - --dist-not-base-repo are not longer supported. See gitdist --help for - more details. - -(*) MINOR: TriBITS projects now install with full RPATH set by default (see - "Setting install RPATH" in build reference guide). - -2016/10/22: - -(*) MAJOR: TriBITS Core: TRIBITS_ADD_TEST() argument FAIL_REGULAR_EXPRESSION - now works when circular RCP detection is enabled. This is technically a - break in backward compatibility since now that argument will not be - ignored and any tests that specified this may change behavior. - -(*) MAJOR: TriBITS Core: TRIBITS_ADD_ADVANCED_TEST() TEST_ argument - FAIL_REGULAR_EXPRESSION now works. Before, it was just being ignored. - This is technically a break in backward compatibility since now that - argument will not be ignored and any tests that specified this may change - behavior. - -(*) MINOR: TriBITS Core: Added TRIBITS_ADD_ADVANCED_TEST() TEST_ option - WILL_FAIL that has the same behavior as the built-in CTest option - WILL_FAIL. - -2016/01/22: - -(*) MINOR: TriBITS Core: Change test category WEEKLY to HEAVY and depreciate - WEEKLY. You can still use WEEKLY but it will result in a lot of warnings. - -2015/12/03: - -(*) MINOR: TriBITS CI Support: checkin-test.py: Added support for tracking - branches for each repo independently and not assume 'origin' and not - assume that all of the repos are on the same branch or will be pulling and - pushing to the same remote branch. This will make it easier to use the - checkin-test.py script to set up various integration scenarios. See - TriBITS GitHub Issue #15 for details. - -2015/04/14: - -(*) MAJOR: TriBITS Core: When configuring with - ${PROJECT_NAME}_ENABLE_CXX11=ON, if C++11 support cannot be verified, then - the configure will fail hard right away. Before, TriBITS would disable - C++11 support and continue. - -2014/11/22: - -(*) MINOR: TriBITS Core: Added ${PROJECT_NAME}_TRACE_ADD_TEST: Now you can a - single line print if a test got added (and its important properties if it - did) or not and if not then why the test did not get added. - -2014/09/22: - -(*) MAJOR: TriBITS Core: Changed minimum version of CMake from 2.7 to 2.8.11. - -2014/09/21: - -(*) MINOR: TriBITS Dashboard Driver: Added support for the env var - TRIBITS_TDD_USE_SYSTEM_CTEST so that if equal to 1, then the TriBITS - Dashboard Driver (TDD) system will use the CTest (and CMake) in the env - will be used instead of being downloaded using download-cmake.py. This - not only speeds up the automated builds, but it also ensures that the - automated testing uses exactly the install of CMake/CTest that is used by - the developers on the system. Also, it has been found that - download-cmake.py will download and install a 32bit version even on 64bit - machines. - -Trilinos 11.7: --------------- - -(*) MINOR: TriBITS Core: Switched from the terms Primary Stable (PS) and - Secondary Stable (SS) code to Primary Tested (PT) and Secondary Tested - (ST) according to the plan in the TriBITS Life-cycle model. Using 'PS' and - 'SS' is still allowed but is deprecated. This also included deprecating - the variable _ENABLE_SECONDARY_STABLE_CODE and replacing it with - _ENABLE_SECONDARY_TEST_CODE. Again, backward compatibility is - preserved. Also, the checkin-test.py arg --ss-extra-builds is deprecated - and replaced with --st-extra-builds. - - -Trilinos 11.6: --------------- - -(*) MAJOR: TriBITS Core: Changed behavior of _ENABLE_=ON to - enable all subpackages for that package including in propagating forward - dependencies. See updated BuildQuickRef.* document. - - -Trilinos 11.3: --------------- - -(*) MINOR: TriBITS Core: Added ENVIRONMENT env1=val1 env2=val2 ... argument to - TRIBITS_ADD_TEST(), TRIBITS_ADD_ADVANCED_TEST(), and - TRIBITS_ADD_EXECUTABLE_AND_TEST(). - -(*) MINOR: TriBITS Core: Fixed the generation of headers for explicit - instantiation system for subpackages: Now subpackages that use the macro - TRIBITS_CREATE_CLIENT_TEMPLATE_HEADERS() to generate XXX.hpp header files - with or without explicit instantiation will key off of the parent package's - explicit instantiation setting. In addition, packages that use the macro - TRIBITS_CREATE_CLIENT_TEMPLATE_HEADERS() will also need to add a call to - TRIBITS_ADD_EXPLICIT_INSTANTIATION_OPTION() in their top-level - CMakeLists.txt file. - - diff --git a/cmake/tribits/TriBITS.cmake b/cmake/tribits/TriBITS.cmake index 1ef5536ea83e..cc85eca0fb50 100644 --- a/cmake/tribits/TriBITS.cmake +++ b/cmake/tribits/TriBITS.cmake @@ -1,4 +1,42 @@ +# @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 + # Top-level include file that pulls in TriBITS so it can be used by a project. # A Project's top-level CMakeLists.cmake file just does: # @@ -7,7 +45,6 @@ # and then they can call: # # tribits_project() -# if (${PROJECT_NAME}_TRIBITS_DIR) set(TRIBITS_BASE_DIR_LOCAL "${${PROJECT_NAME}_TRIBITS_DIR}") diff --git a/cmake/tribits/ci_support/TribitsDumpDepsXmlScript.cmake b/cmake/tribits/ci_support/TribitsDumpDepsXmlScript.cmake index 459f8665380e..771c2e6dcd31 100644 --- a/cmake/tribits/ci_support/TribitsDumpDepsXmlScript.cmake +++ b/cmake/tribits/ci_support/TribitsDumpDepsXmlScript.cmake @@ -50,6 +50,8 @@ # -P /ci_support/TribitsDumpDepsXmlScript.cmake # +cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR) + # A) Echo input options (must be specified with -D arguments to CMake command) # PROJECT_SOURCE_DIR @@ -106,7 +108,7 @@ set( CMAKE_MODULE_PATH include(TribitsConstants) tribits_asesrt_minimum_cmake_version() -include(TribitsCMakePolicies) +include(TribitsCMakePolicies NO_POLICY_SCOPE) include(TribitsGlobalMacros) include(TribitsPrintDependencyInfo) diff --git a/cmake/tribits/ci_support/TribitsGetExtraReposForCheckinTest.cmake b/cmake/tribits/ci_support/TribitsGetExtraReposForCheckinTest.cmake index 7ba66a93d313..d0afd980bdd9 100644 --- a/cmake/tribits/ci_support/TribitsGetExtraReposForCheckinTest.cmake +++ b/cmake/tribits/ci_support/TribitsGetExtraReposForCheckinTest.cmake @@ -86,7 +86,7 @@ set( CMAKE_MODULE_PATH "${${PROJECT_NAME}_TRIBITS_DIR}/core/utils" "${${PROJECT_NAME}_TRIBITS_DIR}/core/package_arch" ) -include(TribitsCMakePolicies) +include(TribitsCMakePolicies NO_POLICY_SCOPE) include(Split) include(AppendStringVar) include(SetDefaultAndFromEnv) # Used in ExtraRepositoriesList.cmake file? diff --git a/cmake/tribits/common_tpls/FindTPLBLAS.cmake b/cmake/tribits/common_tpls/FindTPLBLAS.cmake index dc04355fdd26..78ba327150e2 100644 --- a/cmake/tribits/common_tpls/FindTPLBLAS.cmake +++ b/cmake/tribits/common_tpls/FindTPLBLAS.cmake @@ -54,6 +54,31 @@ # @HEADER +set(REQUIRED_LIBS_NAMES "blas blas_win32") + +# +# Second, search for BLAS components (if allowed) using the standard +# find_package(BLAS ...). +# +tribits_tpl_allow_pre_find_package(BLAS BLAS_ALLOW_PREFIND) +if (BLAS_ALLOW_PREFIND) + + message("-- Using find_package(BLAS ...) ...") + + find_package(BLAS) + + if (BLAS_FOUND) + # Tell TriBITS that we found BLAS and there no need to look any further! + set(TPL_BLAS_INCLUDE_DIRS "" CACHE PATH + "BLAS include dirs") + set(TPL_BLAS_LIBRARIES ${BLAS_LIBRARIES} CACHE FILEPATH + "BLAS libraries") + set(TPL_BLAS_LIBRARY_DIRS "" CACHE PATH + "BLAS library dirs") + endif() + +endif() + if (MSVC AND NOT (BLAS_LIBRARY_DIRS OR (NOT "${BLAS_LIBRARY_NAMES}" STREQUAL "blas blas_win32" AND @@ -75,6 +100,12 @@ if (MSVC AND NOT CACHE FILEPATH "Set from MSVC CLAPACK specialization") endif() endif() - +# +# Third, call tribits_tpl_find_include_dirs_and_libraries() +# tribits_tpl_find_include_dirs_and_libraries( BLAS - REQUIRED_LIBS_NAMES "blas blas_win32") + REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} + ) +# NOTE: If find_package(BLAS ...) was called and successfully found BLAS, then +# tribits_tpl_find_include_dirs_and_libraries() will use the already-set +# variables TPL_BLAS_INCLUDE_DIRS and TPL_BLAS_LIBRARIES and then print them diff --git a/cmake/tribits/common_tpls/FindTPLLAPACK.cmake b/cmake/tribits/common_tpls/FindTPLLAPACK.cmake index 443924df0d7a..5e8d9724200b 100644 --- a/cmake/tribits/common_tpls/FindTPLLAPACK.cmake +++ b/cmake/tribits/common_tpls/FindTPLLAPACK.cmake @@ -53,6 +53,37 @@ # ************************************************************************ # @HEADER +# +# First, set up the variables for the (backward-compatible) TriBITS way of +# finding LAPACK. These are used in case find_package(LAPACK ...) is not called +# or does not find LAPACK. Also, these variables need to be non-null in order +# to trigger the right behavior in the function +# tribits_tpl_find_include_dirs_and_libraries(). +# +set(REQUIRED_LIBS_NAMES "lapack lapack_win32") + +# +# Second, search for LAPACK components (if allowed) using the standard +# find_package(LAPACK ...). +# +tribits_tpl_allow_pre_find_package(LAPACK LAPACK_ALLOW_PREFIND) +if (LAPACK_ALLOW_PREFIND) + + message("-- Using find_package(LAPACK ...) ...") + + find_package(LAPACK) + + if (LAPACK_FOUND) + # Tell TriBITS that we found LAPACK and there no need to look any further! + set(TPL_LAPACK_INCLUDE_DIRS "" CACHE PATH + "LAPACK include dirs") + set(TPL_LAPACK_LIBRARIES ${LAPACK_LIBRARIES} CACHE FILEPATH + "LAPACK libraries") + set(TPL_LAPACK_LIBRARY_DIRS "" CACHE PATH + "LAPACK library dirs") + endif() + +endif() if (MSVC AND NOT (LAPACK_LIBRARY_DIRS OR @@ -70,5 +101,13 @@ if (MSVC AND NOT endif() endif() +# +# Third, call tribits_tpl_find_include_dirs_and_libraries() +# tribits_tpl_find_include_dirs_and_libraries( LAPACK - REQUIRED_LIBS_NAMES "lapack lapack_win32") + REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} + ) +# NOTE: If find_package(LAPACK ...) was called and successfully found LAPACK, then +# tribits_tpl_find_include_dirs_and_libraries() will use the already-set +# variables TPL_LAPACK_INCLUDE_DIRS and TPL_LAPACK_LIBRARIES and then print them +# out (and set some other standard variables as well). This is the final diff --git a/cmake/tribits/common_tpls/FindTPLNetcdf.cmake b/cmake/tribits/common_tpls/FindTPLNetcdf.cmake index e4053ee3d0ec..9ffd66c06a63 100644 --- a/cmake/tribits/common_tpls/FindTPLNetcdf.cmake +++ b/cmake/tribits/common_tpls/FindTPLNetcdf.cmake @@ -66,7 +66,7 @@ if (Netcdf_ALLOW_PREFIND) "${CMAKE_CURRENT_LIST_DIR}/find_modules" "${CMAKE_CURRENT_LIST_DIR}/utils" ) - + find_package(NetCDF) if (NetCDF_FOUND) @@ -80,7 +80,7 @@ if (Netcdf_ALLOW_PREFIND) set(TPL_Netcdf_LIBRARY_DIRS ${_hdf5_LIBRARY_SEARCH_DIRS} CACHE PATH "${DOCSTR} library files") set(TPL_Netcdf_LIBRARIES ${NetCDF_LIBRARIES} CACHE PATH - "List of semi-colon seprated library names (not 'lib' or extension).") + "List of semi-colon separated library names (not 'lib' or extension).") set(TPL_Netcdf_INCLUDE_DIRS ${NetCDF_INCLUDE_DIRS} CACHE PATH "${DOCSTR} header files.") endif() @@ -116,7 +116,7 @@ tribits_tpl_find_include_dirs_and_libraries( Netcdf # If the `find_package(NetCDF)` is not run, then this may not be set # Need to determine how this is set in the library that is being used... -if ("${TPL_Netcdf_PARALLEL}" STREQUAL "") +if ("${TPL_Netcdf_PARALLEL}" STREQUAL "") assert_defined(TPL_Netcdf_INCLUDE_DIRS) find_path(meta_path NAMES "netcdf_meta.h" @@ -129,12 +129,12 @@ if ("${TPL_Netcdf_PARALLEL}" STREQUAL "") file(STRINGS "${meta_path}/netcdf_meta.h" netcdf_par_string REGEX "NC_HAS_PARALLEL ") string(REGEX MATCH "[01]" netcdf_par_val "${netcdf_par_string}") if (netcdf_par_val EQUAL 1) - set(TPL_Netcdf_PARALLEL True CACHE INTERNAL + set(TPL_Netcdf_PARALLEL True CACHE INTERNAL "True if netcdf compiled with parallel enabled") endif() endif() - if ("${TPL_Netcdf_PARALLEL}" STREQUAL "") - set(TPL_Netcdf_PARALLEL False CACHE INTERNAL + if ("${TPL_Netcdf_PARALLEL}" STREQUAL "") + set(TPL_Netcdf_PARALLEL False CACHE INTERNAL "True if netcdf compiled with parallel enabled") endif() endif() diff --git a/cmake/tribits/common_tpls/FindTPLProjectLastLib.cmake b/cmake/tribits/common_tpls/FindTPLProjectLastLib.cmake new file mode 100644 index 000000000000..97d052978c84 --- /dev/null +++ b/cmake/tribits/common_tpls/FindTPLProjectLastLib.cmake @@ -0,0 +1,9 @@ +# This is a hack to handle the ${PROJECT_NAME}_EXTRA_LINK_FLAGS options as a +# TPL that every downstream TPL and package will depend on. + +separate_arguments(TPL_${PROJECT_NAME}TribitsLastLib_LIBRARIES NATIVE_COMMAND + "${${PROJECT_NAME}_EXTRA_LINK_FLAGS}") + +tribits_tpl_find_include_dirs_and_libraries( ${PROJECT_NAME}TribitsLastLib + REQUIRED_LIBS_NAMES NEVER_USED + ) diff --git a/cmake/tribits/core/installation/TribitsPackageConfigTemplate.cmake.in b/cmake/tribits/core/installation/TribitsPackageConfigTemplate.cmake.in index 0ebe06a1651b..1b11675c7d76 100644 --- a/cmake/tribits/core/installation/TribitsPackageConfigTemplate.cmake.in +++ b/cmake/tribits/core/installation/TribitsPackageConfigTemplate.cmake.in @@ -4,7 +4,6 @@ # 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. # @@ -46,7 +45,7 @@ # ############################################################################## -${DEFINE_CMAKE_CURRENT_LIST_DIR_CODE_SNIPPET} +include_guard(GLOBAL) ## --------------------------------------------------------------------------- ## Compilers used by ${PROJECT_NAME}/${PACKAGE_NAME} build @@ -96,19 +95,19 @@ set(${EXPORT_FILE_VAR_PREFIX}_AR ${CMAKE_AR}) set(${EXPORT_FILE_VAR_PREFIX}_INSTALL_DIR "@CMAKE_INSTALL_PREFIX@") ## List of package include dirs -set(${EXPORT_FILE_VAR_PREFIX}_INCLUDE_DIRS "${FULL_INCLUDE_DIRS_SET}") +set(${EXPORT_FILE_VAR_PREFIX}_INCLUDE_DIRS "") ## List of package library paths -set(${EXPORT_FILE_VAR_PREFIX}_LIBRARY_DIRS "${FULL_LIBRARY_DIRS_SET}") +set(${EXPORT_FILE_VAR_PREFIX}_LIBRARY_DIRS "") ## List of package libraries set(${EXPORT_FILE_VAR_PREFIX}_LIBRARIES "${FULL_LIBRARY_SET}") ## Specification of directories for TPL headers -set(${EXPORT_FILE_VAR_PREFIX}_TPL_INCLUDE_DIRS "${${PACKAGE_NAME}_TPL_INCLUDE_DIRS}") +set(${EXPORT_FILE_VAR_PREFIX}_TPL_INCLUDE_DIRS "") ## Specification of directories for TPL libraries -set(${EXPORT_FILE_VAR_PREFIX}_TPL_LIBRARY_DIRS "${${PACKAGE_NAME}_TPL_LIBRARY_DIRS}") +set(${EXPORT_FILE_VAR_PREFIX}_TPL_LIBRARY_DIRS "") ## List of required TPLs set(${EXPORT_FILE_VAR_PREFIX}_TPL_LIBRARIES "${${PACKAGE_NAME}_TPL_LIBRARIES}") @@ -137,3 +136,29 @@ set(${EXPORT_FILE_VAR_PREFIX}_PACKAGE_LIST "${FULL_PACKAGE_SET}") set(${EXPORT_FILE_VAR_PREFIX}_TPL_LIST "${ORDERED_FULL_TPL_SET}") ${PACKAGE_CONFIG_CODE} + +## ---------------------------------------------------------------------------- +## Create deprecated non-namespaced library targets for backwards compatibility +## ---------------------------------------------------------------------------- + +set(${EXPORT_FILE_VAR_PREFIX}_EXPORTED_PACKAGE_LIBS_NAMES "${EXPORTED_PACKAGE_LIBS_NAMES}") + +foreach(libname IN LISTS ${EXPORT_FILE_VAR_PREFIX}_EXPORTED_PACKAGE_LIBS_NAMES) + if (NOT TARGET ${PDOLLAR}{libname}) + add_library(${PDOLLAR}{libname} INTERFACE IMPORTED) + target_link_libraries(${PDOLLAR}{libname} + INTERFACE ${PACKAGE_NAME}::${PDOLLAR}{libname}) + set(deprecationMessage + "WARNING: The non-namespaced target '${PDOLLAR}{libname}' is deprecated!" + " If always using newer versions of the project '${PROJECT_NAME}', then use the" + " new namespaced target '${PACKAGE_NAME}::${PDOLLAR}{libname}', or better yet," + " '${PACKAGE_NAME}::all_libs' to be less sensitive to changes in the definition" + " of targets in the package '${PACKAGE_NAME}'. Or, to maintain compatibility with" + " older or newer versions the project '${PROJECT_NAME}', instead link against the" + " libraries specified by the variable '${PACKAGE_NAME}_LIBRARIES'." + ) + string(REPLACE ";" "" deprecationMessage "${PDOLLAR}{deprecationMessage}") + set_target_properties(${PDOLLAR}{libname} + PROPERTIES DEPRECATION "${PDOLLAR}{deprecationMessage}" ) + endif() +endforeach() diff --git a/cmake/tribits/core/installation/TribitsPackageConfigTemplate.export.in b/cmake/tribits/core/installation/TribitsPackageConfigTemplate.export.in deleted file mode 100644 index c63e3b36d3ea..000000000000 --- a/cmake/tribits/core/installation/TribitsPackageConfigTemplate.export.in +++ /dev/null @@ -1,110 +0,0 @@ -############################################################################## -# -# Make variables for use by ${PROJECT_NAME}/${PACKAGE_NAME} clients. -# -# ${DISCOURAGE_EDITING} -# -############################################################################## - - -## --------------------------------------------------------------------------- -## Compilers used by ${PROJECT_NAME}/${PACKAGE_NAME} build -## --------------------------------------------------------------------------- - -${EXPORT_FILE_VAR_PREFIX}_CXX_COMPILER=${CMAKE_CXX_COMPILER} - -${EXPORT_FILE_VAR_PREFIX}_C_COMPILER=${CMAKE_C_COMPILER} - -${EXPORT_FILE_VAR_PREFIX}_FORTRAN_COMPILER=${CMAKE_Fortran_COMPILER} -${EXPORT_FILE_VAR_PREFIX}_Fortran_COMPILER=${CMAKE_Fortran_COMPILER} - - -## --------------------------------------------------------------------------- -## Compiler flags used by ${PROJECT_NAME}/${PACKAGE_NAME} build -## --------------------------------------------------------------------------- - -## Set compiler flags, including those determined by build type -${EXPORT_FILE_VAR_PREFIX}_CXX_FLAGS=${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}} -${EXPORT_FILE_VAR_PREFIX}_CXX_COMPILER_FLAGS=${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}} - -${EXPORT_FILE_VAR_PREFIX}_C_FLAGS=${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE}} -${EXPORT_FILE_VAR_PREFIX}_C_COMPILER_FLAGS=${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE}} - -${EXPORT_FILE_VAR_PREFIX}_FORTRAN_FLAGS=${CMAKE_FORTRAN_FLAGS} ${CMAKE_Fortran_FLAGS_${CMAKE_BUILD_TYPE}} -${EXPORT_FILE_VAR_PREFIX}_Fortran_COMPILER_FLAGS=${CMAKE_FORTRAN_FLAGS} ${CMAKE_Fortran_FLAGS_${CMAKE_BUILD_TYPE}} - -## Extra link flags (e.g., specification of fortran libraries) -${EXPORT_FILE_VAR_PREFIX}_EXTRA_LD_FLAGS=${${PROJECT_NAME}_EXTRA_LINK_FLAGS} - -## This is the command-line entry used for setting rpaths. In a build -## with static libraries it will be empty. -${EXPORT_FILE_VAR_PREFIX}_SHARED_LIB_RPATH_COMMAND=${SHARED_LIB_RPATH_COMMAND} -${EXPORT_FILE_VAR_PREFIX}_BUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} - -${EXPORT_FILE_VAR_PREFIX}_LINKER=${CMAKE_LINKER} -${EXPORT_FILE_VAR_PREFIX}_AR=${CMAKE_AR} - -## --------------------------------------------------------------------------- -## Set library specifications and paths -## --------------------------------------------------------------------------- - -## The project version number -${EXPORT_FILE_VAR_PREFIX}_VERSION=${${PROJECT_NAME}_VERSION} - -## List of package include dirs -${EXPORT_FILE_VAR_PREFIX}_INCLUDE_DIRS=${MAKEFILE_INCLUDE_DIRS} - -## List of package library paths -${EXPORT_FILE_VAR_PREFIX}_LIBRARY_DIRS=${MAKEFILE_LIBRARY_DIRS} - -## List of package libraries -${EXPORT_FILE_VAR_PREFIX}_LIBRARIES=${MAKEFILE_FULL_LIBRARY_SET} - -## Specification of directories for TPL headers -${EXPORT_FILE_VAR_PREFIX}_TPL_INCLUDE_DIRS=${MAKEFILE_${PACKAGE_NAME}_TPL_INCLUDE_DIRS} - -## Specification of directories for TPL libraries -${EXPORT_FILE_VAR_PREFIX}_TPL_LIBRARY_DIRS=${MAKEFILE_${PACKAGE_NAME}_TPL_LIBRARY_DIRS} - -## List of required TPLs -${EXPORT_FILE_VAR_PREFIX}_TPL_LIBRARIES=${MAKEFILE_${PACKAGE_NAME}_TPL_LIBRARIES} - -## --------------------------------------------------------------------------- -## MPI specific variables -## These variables are provided to make it easier to get the mpi libraries -## and includes on systems that do not use the mpi wrappers for compiling -## --------------------------------------------------------------------------- - -${EXPORT_FILE_VAR_PREFIX}_MPI_LIBRARIES=${MAKEFILE_TPL_MPI_LIBRARIES} -${EXPORT_FILE_VAR_PREFIX}_MPI_LIBRARY_DIRS=${MAKEFILE_TPL_MPI_LIBRARY_DIRS} -${EXPORT_FILE_VAR_PREFIX}_MPI_INCLUDE_DIRS=${MAKEFILE_TPL_MPI_INCLUDE_DIRS} -${EXPORT_FILE_VAR_PREFIX}_MPI_EXEC=${MPI_EXEC} -${EXPORT_FILE_VAR_PREFIX}_MPI_EXEC_MAX_NUMPROCS=${MPI_EXEC_MAX_NUMPROCS} -${EXPORT_FILE_VAR_PREFIX}_MPI_EXEC_NUMPROCS_FLAG=${MPI_EXEC_NUMPROCS_FLAG} - -## --------------------------------------------------------------------------- -## Set useful general variables -## --------------------------------------------------------------------------- - -## The packages enabled for this project -${EXPORT_FILE_VAR_PREFIX}_PACKAGE_LIST=${MAKEFILE_FULL_PACKAGE_SET} - -## The TPLs enabled for this project -${EXPORT_FILE_VAR_PREFIX}_TPL_LIST=${MAKEFILE_ORDERED_FULL_TPL_SET} - -## --------------------------------------------------------------------------- -## Deprecated variables -## These variables from the autotools version of Makefile.export. -## have been deprecated. To help avoid confusion with projects that haven't -## migrated to the new version of the variable names when the don't compile. -## This will put an obvious statement in the link line that these Trilinos -## Makefile variables are no longer used. Without this there would be a link -## error with no obvious reason as to why other than the lack of Trilinos libs -## which would be confusing since the link line in the Makefile would have -## stated to put them on the line. -## --------------------------------------------------------------------------- - -${EXPORT_FILE_VAR_PREFIX_UPPER}_LIBS="The Trilinos variable ${EXPORT_FILE_VAR_PREFIX_UPPER}_LIBS has been deprecated. Please see the documentation on the Makefile.export capability for instructions on how to transition to the new system." -${EXPORT_FILE_VAR_PREFIX_UPPER}_INCLUDES="The Trilinos variable ${EXPORT_FILE_VAR_PREFIX_UPPER}_INCLUDES has been deprecated. Please see the documentation on the Makefile.export capability for instructions on how to transition to the new system." - - diff --git a/cmake/tribits/core/installation/TribitsProjectConfigTemplate.cmake.in b/cmake/tribits/core/installation/TribitsProjectConfigTemplate.cmake.in index 55e5b6e6ca3a..5872986017f6 100644 --- a/cmake/tribits/core/installation/TribitsProjectConfigTemplate.cmake.in +++ b/cmake/tribits/core/installation/TribitsProjectConfigTemplate.cmake.in @@ -46,11 +46,6 @@ # ############################################################################## -# -# Ensure CMAKE_CURRENT_LIST_DIR is usable. -# -${DEFINE_CMAKE_CURRENT_LIST_DIR_CODE_SNIPPET} - ## --------------------------------------------------------------------------- ## Compilers used by ${PROJECT_NAME} build ## --------------------------------------------------------------------------- @@ -106,65 +101,46 @@ endif() # Initialize ${PROJECT_NAME}_FOUND with true, and set it to FALSE if any of # the required components wasn't found. set(${PROJECT_NAME}_FOUND TRUE) -foreach(comp ${PDOLLAR}{COMPONENTS_LIST}) - set( - INCLUDE_FILE +set(${PROJECT_NAME}_NOT_FOUND_MESSAGE "") +set(selectedComponentsFound "") +foreach (comp IN ITEMS ${PDOLLAR}{COMPONENTS_LIST}) + set(compPkgConfigFile ${PDOLLAR}{CMAKE_CURRENT_LIST_DIR}/../${PDOLLAR}{comp}/${PDOLLAR}{comp}Config.cmake ) - if (EXISTS ${PDOLLAR}{INCLUDE_FILE}) - # Set ${PROJECT_NAME}__FOUND. - set(${PROJECT_NAME}_${PDOLLAR}{comp}_FOUND TRUE) - # Include the package file. - include(${PDOLLAR}{INCLUDE_FILE}) - # Add variables to lists. - list(APPEND ${PROJECT_NAME}_INCLUDE_DIRS ${PDOLLAR}{${PDOLLAR}{comp}_INCLUDE_DIRS}) - list(APPEND ${PROJECT_NAME}_LIBRARY_DIRS ${PDOLLAR}{${PDOLLAR}{comp}_LIBRARY_DIRS}) - list(APPEND ${PROJECT_NAME}_LIBRARIES ${PDOLLAR}{${PDOLLAR}{comp}_LIBRARIES}) - list(APPEND ${PROJECT_NAME}_TPL_INCLUDE_DIRS ${PDOLLAR}{${PDOLLAR}{comp}_TPL_INCLUDE_DIRS}) - list(APPEND ${PROJECT_NAME}_TPL_LIBRARY_DIRS ${PDOLLAR}{${PDOLLAR}{comp}_TPL_LIBRARY_DIRS}) - list(APPEND ${PROJECT_NAME}_TPL_LIBRARIES ${PDOLLAR}{${PDOLLAR}{comp}_TPL_LIBRARIES}) - else() - # Set ${PROJECT_NAME}__FOUND to FALSE. - set(${PROJECT_NAME}_${PDOLLAR}{comp}_FOUND FALSE) - # Set ${PROJECT_NAME}_FOUND to FALSE if component is not optional. - if(${PROJECT_NAME}_FIND_REQUIRED_${PDOLLAR}{comp}) - set(${PROJECT_NAME}_FOUND FALSE) - endif() - endif() + if (EXISTS ${PDOLLAR}{compPkgConfigFile}) + # Set ${PROJECT_NAME}__FOUND. + set(${PROJECT_NAME}_${PDOLLAR}{comp}_FOUND TRUE) + # Include the package file. + include(${PDOLLAR}{compPkgConfigFile}) + # Add variables to lists. + list(APPEND ${PROJECT_NAME}_LIBRARIES ${PDOLLAR}{${PDOLLAR}{comp}_LIBRARIES}) + list(APPEND ${PROJECT_NAME}_TPL_LIBRARIES ${PDOLLAR}{${PDOLLAR}{comp}_TPL_LIBRARIES}) + list(APPEND selectedComponentsFound ${PDOLLAR}{comp}) + else() + set(${PROJECT_NAME}_${PDOLLAR}{comp}_FOUND FALSE) + if(${PROJECT_NAME}_FIND_REQUIRED_${PDOLLAR}{comp}) + string(APPEND ${PROJECT_NAME}_NOT_FOUND_MESSAGE + "ERROR: Could not find component '${PDOLLAR}{comp}'!\n") + set(${PROJECT_NAME}_FOUND FALSE) + endif() + endif() endforeach() -# Resolve absolute paths and remove duplicate paths -# for LIBRARY_DIRS and INCLUDE_DIRS -# This reduces stress on regular expressions later -set(short_dirs) -foreach(dir ${PDOLLAR}{${PROJECT_NAME}_INCLUDE_DIRS}) - get_filename_component(dir_abs ${PDOLLAR}{dir} ABSOLUTE) - list(APPEND short_dirs ${PDOLLAR}{dir_abs}) -endforeach() -list(REMOVE_DUPLICATES short_dirs) -set(${PROJECT_NAME}_INCLUDE_DIRS ${PDOLLAR}{short_dirs}) +# Deprecated (see #299)! +set(${PROJECT_NAME}_INCLUDE_DIRS "${TRIBITS_PROJECT_INSTALL_INCLUDE_DIR}") -set(short_dirs) -foreach(dir ${PDOLLAR}{${PROJECT_NAME}_LIBRARY_DIRS}) - get_filename_component(dir_abs ${PDOLLAR}{dir} ABSOLUTE) - list(APPEND short_dirs ${PDOLLAR}{dir_abs}) -endforeach() -list(REMOVE_DUPLICATES short_dirs) -set(${PROJECT_NAME}_LIBRARY_DIRS ${PDOLLAR}{short_dirs}) +# Deprecated (see #299)! +set(${PROJECT_NAME}_LIBRARY_DIRS "") # Remove duplicates in ${PROJECT_NAME}_LIBRARIES list(REVERSE ${PROJECT_NAME}_LIBRARIES) list(REMOVE_DUPLICATES ${PROJECT_NAME}_LIBRARIES) list(REVERSE ${PROJECT_NAME}_LIBRARIES) -# Remove duplicates in ${PROJECT_NAME}_TPL_INCLUDE_DIRS -if (${PROJECT_NAME}_TPL_INCLUDE_DIRS) - list(REMOVE_DUPLICATES ${PROJECT_NAME}_TPL_INCLUDE_DIRS) -endif() - -# NOTE: It is *NOT* safe to try to remove duplicate in -# ${PROJECT_NAME}_TPL_LIBRARIES because these can be specified as -L, -l, etc. -# Actually, we should think about that. +# Remove duplicates in ${PROJECT_NAME}_TPL_LIBRARIES +list(REVERSE ${PROJECT_NAME}_TPL_LIBRARIES) +list(REMOVE_DUPLICATES ${PROJECT_NAME}_TPL_LIBRARIES) +list(REVERSE ${PROJECT_NAME}_TPL_LIBRARIES) ## --------------------------------------------------------------------------- ## MPI specific variables @@ -198,5 +174,34 @@ set(${PROJECT_NAME}_Fortran_IMPLICIT_LINK_LIBRARIES "${CMAKE_Fortran_IMPLICIT_LI ## The packages enabled for this project set(${PROJECT_NAME}_PACKAGE_LIST "${FULL_PACKAGE_SET}") +## The selected packages for this project +set(${PROJECT_NAME}_SELECTED_PACKAGE_LIST "${PDOLLAR}{selectedComponentsFound}") + ## The TPLs enabled for this project set(${PROJECT_NAME}_TPL_LIST "${FULL_TPL_SET}") + +## --------------------------------------------------------------------------- +## Modern CMake (IMPORTED) targets +## --------------------------------------------------------------------------- + +# ${PROJECT_NAME}::all_libs (Does *not* depend on COMPONENTS) +if (NOT TARGET ${PROJECT_NAME}::all_libs) + set(${PROJECT_NAME}_ALL_PACKAGES_TARGETS) + foreach (pkg IN ITEMS ${FULL_PACKAGE_SET}) + list(APPEND ${PROJECT_NAME}_ALL_PACKAGES_TARGETS ${PDOLLAR}{pkg}::all_libs) + endforeach() + add_library(${PROJECT_NAME}::all_libs IMPORTED INTERFACE GLOBAL) + target_link_libraries(${PROJECT_NAME}::all_libs + INTERFACE ${PDOLLAR}{${PROJECT_NAME}_ALL_PACKAGES_TARGETS} ) +endif() + +# ${PROJECT_NAME}::all_selected_libs (Depend on COMPONENTS) +if (NOT TARGET ${PROJECT_NAME}::all_selected_libs) + set(${PROJECT_NAME}_ALL_SELECTED_PACKAGES_TARGETS) + foreach (pkg IN ITEMS ${PDOLLAR}{selectedComponentsFound}) + list(APPEND ${PROJECT_NAME}_ALL_SELECTED_PACKAGES_TARGETS ${PDOLLAR}{pkg}::all_libs) + endforeach() + add_library(${PROJECT_NAME}::all_selected_libs IMPORTED INTERFACE GLOBAL) + target_link_libraries(${PROJECT_NAME}::all_selected_libs + INTERFACE ${PDOLLAR}{${PROJECT_NAME}_ALL_SELECTED_PACKAGES_TARGETS} ) +endif() diff --git a/cmake/tribits/core/installation/TribitsProjectConfigTemplate.export.in b/cmake/tribits/core/installation/TribitsProjectConfigTemplate.export.in deleted file mode 100644 index 18b8ac7d3384..000000000000 --- a/cmake/tribits/core/installation/TribitsProjectConfigTemplate.export.in +++ /dev/null @@ -1,90 +0,0 @@ -############################################################################## -# -# Make variables for use by ${PROJECT_NAME} clients. -# -# ${DISCOURAGE_EDITING} -# -############################################################################## - - -## --------------------------------------------------------------------------- -## Compilers used by ${PROJECT_NAME} build -## --------------------------------------------------------------------------- - -${PROJECT_NAME}_CXX_COMPILER=${CMAKE_CXX_COMPILER} - -${PROJECT_NAME}_C_COMPILER=${CMAKE_C_COMPILER} - -${PROJECT_NAME}_Fortran_COMPILER=${CMAKE_Fortran_COMPILER} - - -## --------------------------------------------------------------------------- -## Compiler flags used by ${PROJECT_NAME} build -## --------------------------------------------------------------------------- - -${PROJECT_NAME}_CXX_COMPILER_FLAGS=${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}} - -${PROJECT_NAME}_C_COMPILER_FLAGS=${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE}} - -${PROJECT_NAME}_Fortran_COMPILER_FLAGS=${CMAKE_Fortran_FLAGS} ${CMAKE_Fortran_FLAGS_${CMAKE_BUILD_TYPE}} - -## Extra link flags (e.g., specification of fortran libraries) -${PROJECT_NAME}_EXTRA_LD_FLAGS=${${PROJECT_NAME}_EXTRA_LINK_FLAGS} - -## This is the command-line entry used for setting rpaths. In a build -## with static libraries it will be empty. -${PROJECT_NAME}_SHARED_LIB_RPATH_COMMAND=${SHARED_LIB_RPATH_COMMAND} -${PROJECT_NAME}_BUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} - -${PROJECT_NAME}_LINKER=${CMAKE_LINKER} -${PROJECT_NAME}_AR=${CMAKE_AR} - - -## --------------------------------------------------------------------------- -## Set library specifications and paths -## --------------------------------------------------------------------------- - -## The project version number -${PROJECT_NAME}_VERSION=${${PROJECT_NAME}_VERSION} - -## The project include file directories. -${PROJECT_NAME}_INCLUDE_DIRS=${MAKEFILE_${PROJECT_NAME}_CONFIG_INCLUDE_DIRS} - -## The project library directories. -${PROJECT_NAME}_LIBRARY_DIRS=${MAKEFILE_${PROJECT_NAME}_CONFIG_LIBRARY_DIRS} - -## The project libraries. -${PROJECT_NAME}_LIBRARIES=${MAKEFILE_${PROJECT_NAME}_CONFIG_LIBRARIES} - -## The project tpl include paths -${PROJECT_NAME}_TPL_INCLUDE_DIRS=${MAKEFILE_${PROJECT_NAME}_CONFIG_TPL_INCLUDE_DIRS} - -## The project tpl library paths -${PROJECT_NAME}_TPL_LIBRARY_DIRS=${MAKEFILE_${PROJECT_NAME}_CONFIG_TPL_LIBRARY_DIRS} - -## The project tpl libraries -${PROJECT_NAME}_TPL_LIBRARIES=${MAKEFILE_${PROJECT_NAME}_CONFIG_TPL_LIBRARIES} - -## --------------------------------------------------------------------------- -## MPI specific variables -## These variables are provided to make it easier to get the mpi libraries -## and includes on systems that do not use the mpi wrappers for compiling -## --------------------------------------------------------------------------- - -${PROJECT_NAME}_MPI_LIBRARIES=${MAKEFILE_TPL_MPI_LIBRARIES} -${PROJECT_NAME}_MPI_LIBRARY_DIRS=${MAKEFILE_TPL_MPI_LIBRARY_DIRS} -${PROJECT_NAME}_MPI_INCLUDE_DIRS=${MAKEFILE_TPL_MPI_INCLUDE_DIRS} -${PROJECT_NAME}_MPI_EXEC=${MPI_EXEC} -${PROJECT_NAME}_MPI_EXEC_MAX_NUMPROCS=${MPI_EXEC_MAX_NUMPROCS} -${PROJECT_NAME}_MPI_EXEC_NUMPROCS_FLAG=${MPI_EXEC_NUMPROCS_FLAG} - -## --------------------------------------------------------------------------- -## Set useful general variables -## --------------------------------------------------------------------------- - -## The packages enabled for this project -${PROJECT_NAME}_PACKAGE_LIST=${MAKEFILE_FULL_PACKAGE_SET} - -## The TPLs enabled for this project -${PROJECT_NAME}_TPL_LIST=${MAKEFILE_FULL_TPL_SET} - 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 3977fb6c1d5d..14054ad190fe 100644 --- a/cmake/tribits/core/installation/add_project_install_commands/CMakeLists.txt +++ b/cmake/tribits/core/installation/add_project_install_commands/CMakeLists.txt @@ -1,9 +1,8 @@ set(tribits_install_src "${${PROJECT_NAME}_TRIBITS_DIR}/${TRIBITS_CMAKE_INSTALLATION_FILES_DIR}") -if((${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES - OR ${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES) - AND NOT ${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING +if ( ${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES + AND NOT ${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING ) include(TribitsWriteClientExportFiles) diff --git a/cmake/tribits/core/package_arch/TribitsAddAdvancedTest.cmake b/cmake/tribits/core/package_arch/TribitsAddAdvancedTest.cmake index dd035e8de8be..caba3a442d09 100644 --- a/cmake/tribits/core/package_arch/TribitsAddAdvancedTest.cmake +++ b/cmake/tribits/core/package_arch/TribitsAddAdvancedTest.cmake @@ -37,15 +37,16 @@ # ************************************************************************ # @HEADER +include(TribitsCMakePolicies NO_POLICY_SCOPE) include(TribitsAddAdvancedTestHelpers) include(TribitsConstants) +include(TribitsPrintList) include(AppendStringVar) include(PrintVar) -# # @FUNCTION: tribits_add_advanced_test() # # Function that creates an advanced test defined by stringing together one or @@ -75,10 +76,11 @@ include(PrintVar) # [XHOSTTYPE ...] # [EXCLUDE_IF_NOT_TRUE ...] # [DISABLED ] -# [FINAL_PASS_REGULAR_EXPRESSION | -# FINAL_FAIL_REGULAR_EXPRESSION ] +# [FINAL_PASS_REGULAR_EXPRESSION "" | +# FINAL_FAIL_REGULAR_EXPRESSION ""] # [ENVIRONMENT = = ...] # [TIMEOUT ] +# [LIST_SEPARATOR ] # [ADDED_TEST_NAME_OUT ] # ) # @@ -102,7 +104,7 @@ include(PrintVar) # (EXEC [NOEXEPREFIX] [NOEXESUFFIX] [ADD_DIR_TO_NAME] # [DIRECTORY ] # | CMND ) -# [ARGS ... ] +# [ARGS "" "" ... ""] # [MESSAGE ""] # [WORKING_DIRECTORY ] # [SKIP_CLEAN_WORKING_DIRECTORY] @@ -111,10 +113,10 @@ include(PrintVar) # [OUTPUT_FILE ] # [NO_ECHO_OUTPUT]] # [PASS_ANY -# | PASS_REGULAR_EXPRESSION "" -# | PASS_REGULAR_EXPRESSION_ALL "" "" ... "" +# | PASS_REGULAR_EXPRESSION "" "" ... +# | PASS_REGULAR_EXPRESSION_ALL "" "" ... # | STANDARD_PASS_OUTPUT ] -# [FAIL_REGULAR_EXPRESSION ""] +# [FAIL_REGULAR_EXPRESSION "" "" ...] # [ALWAYS_FAIL_ON_NONZERO_RETURN | ALWAYS_FAIL_ON_ZERO_RETURN] # [WILL_FAIL] # @@ -295,11 +297,18 @@ include(PrintVar) # by CMake, then the test will be added by ctest but the ``DISABLED`` test # property will be set (see `tribits_add_test()`_). # -# ``ENVIRONMENT = = ..``. +# ``ENVIRONMENT "=" "=" ...``. # -# If passed in, the listed environment variables will be set before -# calling the test. This is set using the built-in CTest test property -# ``ENVIRONMENT``. +# If passed in, the listed environment variables will be set by CTest +# before calling the test. This is set using the built-in CTest test +# property ``ENVIRONMENT``. Note, if the env var values contain +# semi-colons ``';'``, then replace the semi-colons ``';'`` with another +# separator ``''`` and pass in ``LIST_SEPARATOR `` so ```` +# will be replaced with ``';'`` at point of usage. If the env var values +# contain any spaces, also quote the entire variable/value pair as +# ``"="``. For example, the env var and value +# ``my_env_var="arg1 b;arg2;I have spaces"`` would need to be passed as +# ``"my_env_var=arg1 barg2I have spaces"``. # # ``TIMEOUT `` # @@ -308,6 +317,18 @@ include(PrintVar) # tests (tribits_add_test())`_). This is for the full CTest test, not # individual ``TEST_`` commands! # +# ``LIST_SEPARATOR `` +# +# String used as placeholder for the semi-colon char ``';'`` in order to +# allow pass-through. For example, if arguments to the ``ARGS`` or +# ``ENVIRONMENT`` need to use semi-colons, then replace ``';'`` with +# ``''`` (for example) such as with +# ``"somearg=arg1arg2"``, then at the point of usage, +# ``''`` will be replaced with ``';'`` and it will be passed to +# the final command as ``"somearg=arg1;arg2"`` (with as many preceding +# escape backslashes ``'\'`` in front of ``';'`` as is needed for the +# given usage context). +# # ``ADDED_TEST_NAME_OUT `` # # If specified, then on output the variable ```` will be set @@ -358,7 +379,7 @@ include(PrintVar) # ``my_python_test.py`` with ``/usr/bin/env pyhton`` at the top, you can't # just use:: # -# CMND /my_python_test.py ARGS ... +# CMND /my_python_test.py ARGS "" "" ... # # The same goes for Perl or any other scripting language. # @@ -366,6 +387,15 @@ include(PrintVar) # # CMND ${PYTHON_EXECUTABLE} ARGS /my_python_test.py ... # +# ``ARGS "" "" ... ""`` +# +# The list of command-line arguments to pass to the ``CMND`` command or +# ``EXEC`` executable. Put each argument ```` in quotes ``""`` +# if it contains any spaces. Also, of any of the individual arguments need +# to contain semi-colons ``';'`` such as ``--my-arg=a;b a;c;d``, then pass +# that quoted as ``"--my-arg=ab acd"`` where ```` +# matches the ```` argument to the input ``LIST_SEPARATOR ``. +# # By default, the output (stdout/stderr) for each test command is captured and # is then echoed to stdout for the overall test. This is done in order to be # able to grep the result to determine pass/fail. @@ -463,17 +493,17 @@ include(PrintVar) # that is to follow will determine pass or fail based on output from this # command in some way. # -# ``PASS_REGULAR_EXPRESSION ""`` +# ``PASS_REGULAR_EXPRESSION "" "" ...`` # -# If specified, the test command will be assumed to pass if it matches the -# given regular expression. Otherwise, it is assumed to fail. TIPS: -# Replace ';' with '[;]' or CMake will interpret this as an array element -# boundary. To match '.', use '[.]'. +# If specified, the test command will be assumed to pass if it matches +# **any** of the given regular expressions. Otherwise, it is assumed to +# fail. TIPS: Replace ';' with '[;]' or CMake will interpret this as an +# array element boundary. To match '.', use '[.]'. # -# ``PASS_REGULAR_EXPRESSION_ALL "" "" ... ""`` +# ``PASS_REGULAR_EXPRESSION_ALL "" "" ...`` # # If specified, the test command will be assumed to pass if the output -# matches all of the provided regular expressions. Note that this is not +# matches **all** of the provided regular expressions. Note that this is not # a capability of raw ctest and represents an extension provided by # TriBITS. NOTE: It is critical that you replace ';' with '[;]' or CMake # will interpret this as an array element boundary. @@ -485,14 +515,14 @@ include(PrintVar) # This as the result of directly passing in ``PASS_REGULAR_EXPRESSION # "End Result: TEST PASSED"``. # -# ``FAIL_REGULAR_EXPRESSION ""`` +# ``FAIL_REGULAR_EXPRESSION "" "" ...`` # -# If specified, the test command will be assumed to fail if it matches the -# given regular expression. Otherwise, it is assumed to pass. This will -# be applied and take precedence over other above pass criteria. For -# example, if even if ``PASS_REGULAR_EXPRESSION`` or -# ``PASS_REGULAR_EXPRESSION_ALL`` match, then the test will be marked as -# failed if this fail regex matches the output. +# If specified, the test command will be assumed to fail if it matches +# **any** of the given regular expressions. This will be applied and take +# precedence over other above pass criteria. For example, if even if +# ``PASS_REGULAR_EXPRESSION`` or ``PASS_REGULAR_EXPRESSION_ALL`` match, +# then the test will be marked as failed if any of the fail regexes match +# the output. # # ``ALWAYS_FAIL_ON_NONZERO_RETURN`` # @@ -572,6 +602,15 @@ include(PrintVar) # # **Test case Pass/Fail (tribits_add_advanced_test())** # +# The logic given below can be used to determine pass/fail criteria for a test +# case both based on what is printed in the test output **and** the return +# code for the test block command. Raw CTest, as of version 3.23, does not +# allow that. With raw CTest, one can only set pass/fail criteria based the +# test output **or** the return code, but not both. This make +# `tribits_add_advanced_test()`_ more attractive to use than +# `tribits_add_test()`_ or raw ``add_test()`` in cases where it is important +# to check both. +# # The logic for how pass/fail for a ``TEST_`` ``EXEC`` or ``CMND`` case # is applied is given by:: # @@ -579,13 +618,19 @@ include(PrintVar) # TEST_CASE_PASSED = FALSE # If PASS_ANY specified: # TEST_CASE_PASSED = TRUE -# Else If PASS_REGULAR_EXPRESSION specified and "" matches: -# TEST_CASE_PASSED = TRUE +# Else If PASS_REGULAR_EXPRESSION is specified: +# For each "" in PASS_REGULAR_EXPRESSION: +# If "" matches STDOUT: +# TEST_CASE_PASSED = TRUE +# Endif +# Endforeach # Else if PASS_REGULAR_EXPRESSION_ALL specified: # TEST_CASE_PASSED = TRUE -# For each "": -# If "" does not match: +# For each "" in PASS_REGULAR_EXPRESSION_ALL: +# If "" does not match STDOUT: # TEST_CASE_PASSED = FALSE +# Endif +# Endforeach # Else # If command return code == 0: # TEST_CASE_PASSED = TRUE @@ -593,14 +638,18 @@ include(PrintVar) # Endif # # # B) Check for failing regex matching? -# If FAIL_REGULAR_EXPRESSION specified and "" matches: -# TEST_CASE_PASSED = FALSE +# If FAIL_REGULAR_EXPRESSION specified: +# For each "" in FAIL_REGULAR_EXPRESSION: +# If "" matches STDOUT: +# TEST_CASE_PASSED = FALSE +# Endif +# Endforeach # Endif # # # C) Check for return code always 0 or !=0? # If ALWAYS_FAIL_ON_NONZERO_RETURN specified and return code != 0: # TEST_CASE_PASSED = FALSE -# ElseIf ALWAYS_FAIL_ON_ZERO_RETURN specified and return code == 0: +# Else If ALWAYS_FAIL_ON_ZERO_RETURN specified and return code == 0: # TEST_CASE_PASSED = FALSE # Endif # @@ -613,6 +662,13 @@ include(PrintVar) # Endif # Endif # +# Note that the above is the exact same logic that CTest uses to determine +# pass/fail w.r.t. to the CTest properties ``PASS_REGULAR_EXPRESSION``, +# ``FAIL_REGULAR_EXPRESSION`` and ``WILL_FAIL``. (It is just that raw +# CMake/CTest, as of version 3.23, does not support any pass/fail criteria +# like ``PASS_REGULAR_EXPRESSION_ALL`` or +# ``ALWAYS_FAIL_ON_NONZERO_RETURN``/``ALWAYS_FAIL_ON_ZERO_RETURN``.) +# # .. _Overall Pass/Fail (tribits_add_advanced_test()): # # **Overall Pass/Fail (tribits_add_advanced_test())** @@ -623,26 +679,36 @@ include(PrintVar) # # However, this can be changed by setting one of the following optional arguments: # -# ``FINAL_PASS_REGULAR_EXPRESSION `` +# ``FINAL_PASS_REGULAR_EXPRESSION "" "" ...`` # # If specified, the test will be assumed to pass if the output matches -# ````. Otherwise, it will be assumed to fail. +# **any** of the provided regular expressions ````. (Sets the +# CTest property ``PASS_REGULAR_EXPRESSION`` for the overall test.) # -# ``FINAL_FAIL_REGULAR_EXPRESSION `` +# ``FINAL_FAIL_REGULAR_EXPRESSION "" "" ...`` # # If specified, the test will be assumed to fail if the output matches -# ````. Otherwise, it will be assumed to fail. +# **any** of the provided regular expressions ```` regardless if +# other criteria would have the test passing. (Sets the CTest property +# ``FAIL_REGULAR_EXPRESSION`` for the overall test.) +# +# **NOTE:** It is **not** recommended to set ``FINAL_PASS_REGULAR_EXPRESSION`` +# or ``FINAL_FAIL_REGULAR_EXPRESSION`` directly, but instead to determine +# pass/fail for each test case individually as described in `TEST_ +# EXEC/CMND Test Blocks and Arguments (tribits_add_advanced_test())`_ and +# `Test case Pass/Fail (tribits_add_advanced_test())`_. Otherwise, the test +# will confuse most people and the output behavior will seem very strange. # # .. _Argument Parsing and Ordering (tribits_add_advanced_test()): # # **Argument Parsing and Ordering (tribits_add_advanced_test())** # -# The basic tool used for parsing the arguments to this function is the macro -# ``cmake_parse_arguments()`` which has a certain set of behaviors. The -# parsing using ``cmake_parse_arguments()`` is actually done in two phases. -# There is a top-level parsing of the "overall" arguments listed in `Overall -# Arguments (tribits_add_advanced_test())`_ that also pulls out the test -# blocks. Then there is a second level of parsing using +# The basic tool used for parsing the arguments to this function is the +# command ``cmake_parse_arguments()`` which has a certain set of behaviors. +# The parsing using ``cmake_parse_arguments()`` is actually done in two +# phases. There is a top-level parsing of the "overall" arguments listed in +# `Overall Arguments (tribits_add_advanced_test())`_ that also pulls out the +# test blocks. Then there is a second level of parsing using # ``cmake_parse_arguments()`` for each of the ``TEST_`` blocks. Because # of this usage, there are a few restrictions that one needs to be aware of # when using ``tribits_add_advanced_test()``. This short sections tries to @@ -833,11 +899,6 @@ function(tribits_add_advanced_test TEST_NAME_IN) set(TEST_NAME ${TEST_NAME_IN}) endif() - # Avoid quoted strings lookup variables - cmake_policy(SET CMP0054 NEW) - # NOTE: For some reason, setting this policy at the top level with TriBITS - # in TribitsCMakePolices.cmake does not affect this function. Therefore, I - # have to set it again here. # # A) Parse the overall arguments and figure out how many tests @@ -852,20 +913,30 @@ function(tribits_add_advanced_test TEST_NAME_IN) foreach( TEST_CMND_IDX RANGE ${MAX_NUM_TEST_CMND_IDX}) list( APPEND TEST_IDX_LIST TEST_${TEST_CMND_IDX} ) endforeach() - #print_var(TEST_IDX_LIST) + + set(optionsList FAIL_FAST RUN_SERIAL SKIP_CLEAN_OVERALL_WORKING_DIRECTORY) + + set(oneValueKeywordsList DISABLED) + + set(multiValueKeywordsList + ${TEST_IDX_LIST} OVERALL_WORKING_DIRECTORY + LIST_SEPARATOR + OVERALL_NUM_MPI_PROCS OVERALL_NUM_TOTAL_CORES_USED + CATEGORIES COMM HOST XHOST HOSTTYPE XHOSTTYPE EXCLUDE_IF_NOT_TRUE + FINAL_PASS_REGULAR_EXPRESSION FINAL_FAIL_REGULAR_EXPRESSION + TIMEOUT ENVIRONMENT KEYWORDS + ADDED_TEST_NAME_OUT + ) cmake_parse_arguments( - #prefix - PARSE - #options - "FAIL_FAST;RUN_SERIAL;SKIP_CLEAN_OVERALL_WORKING_DIRECTORY" - # one_value_keywords - "DISABLED" - # multi_value_keywords - "${TEST_IDX_LIST};OVERALL_WORKING_DIRECTORY;KEYWORDS;COMM;OVERALL_NUM_MPI_PROCS;OVERALL_NUM_TOTAL_CORES_USED;FINAL_PASS_REGULAR_EXPRESSION;CATEGORIES;HOST;XHOST;HOSTTYPE;XHOSTTYPE;EXCLUDE_IF_NOT_TRUE;FINAL_FAIL_REGULAR_EXPRESSION;TIMEOUT;ENVIRONMENT;ADDED_TEST_NAME_OUT" - ${ARGN} - ) + PARSE_ARGV 1 # NOTE: One named argument to skip over + PARSE # prefix + "${optionsList}" + "${oneValueKeywordsList}" + "${multiValueKeywordsList}" + ) + tribits_check_for_unparsed_arguments() tribits_add_advanced_test_check_exceed_max_num_test_blocks() if(PARSE_ADDED_TEST_NAME_OUT) @@ -945,7 +1016,7 @@ function(tribits_add_advanced_test TEST_NAME_IN) set(TEST_SCRIPT_STR "") - append_string_var( TEST_SCRIPT_STR + string(APPEND TEST_SCRIPT_STR "\n" "#\n" "# This is a CMake script and must be run as \"cmake -P \"\n" @@ -960,6 +1031,7 @@ function(tribits_add_advanced_test TEST_NAME_IN) "#\n" "\n" "set( TEST_NAME ${TEST_NAME} )\n" + "set( LIST_SEPARATOR \"${PARSE_LIST_SEPARATOR}\" )\n" ) # Loop through each test case @@ -1001,8 +1073,6 @@ function(tribits_add_advanced_test TEST_NAME_IN) # Parse the test command case - #print_var(PARSE_TEST_${TEST_CMND_IDX}) - # Search to see if we are copying files or not for this TEST_ block ... set(PARSE_COPY_FILES_TO_TEST_DIR) @@ -1035,26 +1105,32 @@ function(tribits_add_advanced_test TEST_NAME_IN) tribits_assert_parse_arg_zero_or_one_value(PARSE SOURCE_DIR) tribits_assert_parse_arg_zero_or_one_value(PARSE DEST_DIR) - set(PARSE_EXEC) - set(PARSE_CMND) + set(PARSE_EXEC "") + set(PARSE_CMND "") else() # Parse TEST_ block args for types EXEC and CMND + set(testBlockOptionsList NOEXEPREFIX NOEXESUFFIX NO_ECHO_OUTPUT PASS_ANY + STANDARD_PASS_OUTPUT ALWAYS_FAIL_ON_NONZERO_RETURN ALWAYS_FAIL_ON_ZERO_RETURN + WILL_FAIL ADD_DIR_TO_NAME SKIP_CLEAN_WORKING_DIRECTORY + ) + + set(testBlockMultiValueKeywordsList EXEC CMND ARGS DIRECTORY MESSAGE + WORKING_DIRECTORY OUTPUT_FILE NUM_MPI_PROCS NUM_TOTAL_CORES_USED + PASS_REGULAR_EXPRESSION_ALL FAIL_REGULAR_EXPRESSION PASS_REGULAR_EXPRESSION + ) + cmake_parse_arguments( - #prefix - PARSE - #options - "NOEXEPREFIX;NOEXESUFFIX;NO_ECHO_OUTPUT;PASS_ANY;STANDARD_PASS_OUTPUT;ALWAYS_FAIL_ON_NONZERO_RETURN;ALWAYS_FAIL_ON_ZERO_RETURN;WILL_FAIL;ADD_DIR_TO_NAME;SKIP_CLEAN_WORKING_DIRECTORY" - # one_value_keywords - "" - # multi_value_keywords - "EXEC;CMND;ARGS;DIRECTORY;MESSAGE;WORKING_DIRECTORY;OUTPUT_FILE;NUM_MPI_PROCS;NUM_TOTAL_CORES_USED;PASS_REGULAR_EXPRESSION_ALL;FAIL_REGULAR_EXPRESSION;PASS_REGULAR_EXPRESSION" + PARSE #prefix + "${testBlockOptionsList}" + "" # one_value_keywords + "${testBlockMultiValueKeywordsList}" ${PARSE_TEST_${TEST_CMND_IDX}} ) - - tribits_check_for_unparsed_arguments() + + tribits_check_for_unparsed_arguments(PARSE) # ToDo: Use a different prefix! endif() @@ -1062,11 +1138,7 @@ function(tribits_add_advanced_test TEST_NAME_IN) # Set up the command that will be written into the cmake -P *.cmake file # - set(ARGS_STR ${PARSE_ARGS}) - #print_var(ARGS_STR) - #if (PARSE_ARGS) - # tribits_join_exec_process_set_args( ARGS_STR ${PARSE_ARGS} ) - #endif() + set(ARGS_STR "${PARSE_ARGS}") if (PARSE_EXEC) @@ -1131,7 +1203,6 @@ function(tribits_add_advanced_test TEST_NAME_IN) tribits_add_test_get_test_cmnd_array( TEST_CMND_ARRAY "${EXECUTABLE_PATH}" "${NUM_PROCS_USED}" ${ARGS_STR} ) - #print_var(TEST_CMND_ARRAY) elseif (PARSE_CMND) @@ -1187,7 +1258,7 @@ function(tribits_add_advanced_test TEST_NAME_IN) string(REPLACE ";" "," FILES_TO_COPY_COMMA_SEP "${FILES_TO_COPY_COMMA_SEP}" ) # NOTE: Above, we have to replace ';' with ',' or the lower commands - # append_string_var() will replace ';' with ''. This is *not* what we + # string(APPEND ) will replace ';' with ''. This is *not* what we # want. In DriveAdvancedTest.cmake, we will replace the ',' with ';' # again :-) @@ -1234,7 +1305,7 @@ function(tribits_add_advanced_test TEST_NAME_IN) # Write the vars for COPY_FILES_TO_TEST_DIR - append_string_var( TEST_SCRIPT_STR + string(APPEND TEST_SCRIPT_STR "\n" "set( TEST_${TEST_CMND_IDX}_COPY_FILES_TO_TEST_DIR" " \"${FILES_TO_COPY_COMMA_SEP}\")\n" @@ -1244,13 +1315,13 @@ function(tribits_add_advanced_test TEST_NAME_IN) "${TEST_CMND_STR}" ) endif() - append_string_var( TEST_SCRIPT_STR + string(APPEND TEST_SCRIPT_STR "\n" "set( TEST_${TEST_CMND_IDX}_SOURCE_DIR" " \"${COPY_FILES_TO_TEST_DIR_SOURCE_DIR}\")\n" ) - append_string_var( TEST_SCRIPT_STR + string(APPEND TEST_SCRIPT_STR "\n" "set( TEST_${TEST_CMND_IDX}_DEST_DIR" " \"${COPY_FILES_TO_TEST_DIR_DEST_DIR}\")\n" @@ -1261,9 +1332,8 @@ function(tribits_add_advanced_test TEST_NAME_IN) # Write the command to be run for EXEC and CMND blocks ... tribits_join_exec_process_set_args( TEST_CMND_STR "${TEST_CMND_ARRAY}" ) - #print_var(TEST_CMND_STR) - - append_string_var( TEST_SCRIPT_STR + + string(APPEND TEST_SCRIPT_STR "\n" "set( TEST_${TEST_CMND_IDX}_CMND ${TEST_CMND_STR} )\n" ) @@ -1275,7 +1345,7 @@ function(tribits_add_advanced_test TEST_NAME_IN) endif() if (PARSE_MESSAGE) - append_string_var( TEST_SCRIPT_STR + string(APPEND TEST_SCRIPT_STR "\n" "set( TEST_${TEST_CMND_IDX}_MESSAGE \"${PARSE_MESSAGE}\" )\n" ) @@ -1285,25 +1355,25 @@ function(tribits_add_advanced_test TEST_NAME_IN) if ("${PARSE_WORKING_DIRECTORY}" STREQUAL "TEST_NAME") set(PARSE_WORKING_DIRECTORY ${TEST_NAME}) endif() - append_string_var( TEST_SCRIPT_STR + string(APPEND TEST_SCRIPT_STR "\n" "set( TEST_${TEST_CMND_IDX}_WORKING_DIRECTORY \"${PARSE_WORKING_DIRECTORY}\" )\n" ) - append_string_var( TEST_SCRIPT_STR + string(APPEND TEST_SCRIPT_STR "\n" "set( TEST_${TEST_CMND_IDX}_SKIP_CLEAN_WORKING_DIRECTORY ${PARSE_SKIP_CLEAN_WORKING_DIRECTORY} )\n" ) endif() if (PARSE_OUTPUT_FILE) - append_string_var( TEST_SCRIPT_STR + string(APPEND TEST_SCRIPT_STR "\n" "set( TEST_${TEST_CMND_IDX}_OUTPUT_FILE \"${PARSE_OUTPUT_FILE}\" )\n" ) endif() if (PARSE_NO_ECHO_OUTPUT) - append_string_var( TEST_SCRIPT_STR + string(APPEND TEST_SCRIPT_STR "\n" "set( TEST_${TEST_CMND_IDX}_NO_ECHO_OUTPUT \"${PARSE_NO_ECHO_OUTPUT}\" )\n" ) @@ -1312,58 +1382,58 @@ function(tribits_add_advanced_test TEST_NAME_IN) # Set up pass/fail if (PARSE_PASS_ANY) - append_string_var( TEST_SCRIPT_STR + string(APPEND TEST_SCRIPT_STR "\n" "set( TEST_${TEST_CMND_IDX}_PASS_ANY TRUE )\n" ) elseif (PARSE_STANDARD_PASS_OUTPUT) - append_string_var( TEST_SCRIPT_STR + string(APPEND TEST_SCRIPT_STR "\n" "set( TEST_${TEST_CMND_IDX}_PASS_REGULAR_EXPRESSION \"End Result: TEST PASSED\" )\n" ) elseif (PARSE_PASS_REGULAR_EXPRESSION) - append_string_var( TEST_SCRIPT_STR + string(APPEND TEST_SCRIPT_STR "\n" "set( TEST_${TEST_CMND_IDX}_PASS_REGULAR_EXPRESSION \"${PARSE_PASS_REGULAR_EXPRESSION}\" )\n" ) elseif (PARSE_PASS_REGULAR_EXPRESSION_ALL) - append_string_var( TEST_SCRIPT_STR + string(APPEND TEST_SCRIPT_STR "\n" "set( TEST_${TEST_CMND_IDX}_PASS_REGULAR_EXPRESSION_ALL " ) foreach(REGEX_STR ${PARSE_PASS_REGULAR_EXPRESSION_ALL}) - append_string_var( TEST_SCRIPT_STR + string(APPEND TEST_SCRIPT_STR "\"${REGEX_STR}\" " ) endforeach() - append_string_var( TEST_SCRIPT_STR + string(APPEND TEST_SCRIPT_STR ")\n" ) endif() if (PARSE_FAIL_REGULAR_EXPRESSION) - append_string_var( TEST_SCRIPT_STR + string(APPEND TEST_SCRIPT_STR "\n" "set( TEST_${TEST_CMND_IDX}_FAIL_REGULAR_EXPRESSION \"${PARSE_FAIL_REGULAR_EXPRESSION}\" )\n" ) endif() if (PARSE_ALWAYS_FAIL_ON_NONZERO_RETURN) - append_string_var( TEST_SCRIPT_STR + string(APPEND TEST_SCRIPT_STR "\n" "set( TEST_${TEST_CMND_IDX}_ALWAYS_FAIL_ON_NONZERO_RETURN TRUE )\n" ) endif() if (PARSE_ALWAYS_FAIL_ON_ZERO_RETURN) - append_string_var( TEST_SCRIPT_STR + string(APPEND TEST_SCRIPT_STR "\n" "set( TEST_${TEST_CMND_IDX}_ALWAYS_FAIL_ON_ZERO_RETURN TRUE )\n" ) endif() if (PARSE_WILL_FAIL) - append_string_var( TEST_SCRIPT_STR + string(APPEND TEST_SCRIPT_STR "\n" "set( TEST_${TEST_CMND_IDX}_WILL_FAIL TRUE )\n" ) @@ -1451,7 +1521,7 @@ function(tribits_add_advanced_test TEST_NAME_IN) # F.2) Write the cmake -P script # - append_string_var( TEST_SCRIPT_STR + string(APPEND TEST_SCRIPT_STR "\n" "set(PROJECT_NAME ${PROJECT_NAME})\n" "\n" diff --git a/cmake/tribits/core/package_arch/TribitsAddExecutable.cmake b/cmake/tribits/core/package_arch/TribitsAddExecutable.cmake index 1c9294e98b48..285afc90825d 100644 --- a/cmake/tribits/core/package_arch/TribitsAddExecutable.cmake +++ b/cmake/tribits/core/package_arch/TribitsAddExecutable.cmake @@ -42,19 +42,14 @@ include(TribitsAddExecutableTestHelpers) include(TribitsCommonArgsHelpers) include(TribitsAddTestHelpers) include(TribitsGeneralMacros) +include(TribitsLibIsTestOnly) include(TribitsReportInvalidTribitsUsage) include(PrintVar) include(AppendSet) include(CMakeParseArguments) -### -### WARNING: See "NOTES TO DEVELOPERS" at the bottom of the file -### TribitsPackageMacros.cmake before trying to change anything in this file! -### - -# # @FUNCTION: tribits_add_executable() # # Function used to create an executable (typically for a test or example), @@ -180,19 +175,7 @@ include(CMakeParseArguments) # package or any upstream SE packages can *NOT* be listed! TriBITS # automatically links non ``TESTONLY`` libraries in this package and # upstream packages to the executable. The only libraries that should be -# listed in this argument are either ``TESTONLY`` libraries. The include -# directories for each test-only library will automatically be added -# using:: -# -# include_directories(${_INCLUDE_DIRS}) -# -# where ``_INCLUDE_DIRS`` was set by:: -# -# tribits_add_library( ... TESTONLY ...) -# -# Therefore, to link to a defined ``TESTONLY`` library in any upstream -# enabled package, one just needs to pass in the library name through -# ``TESTONLYLIBS ... ...`` and that is it! +# listed in this argument are either ``TESTONLY`` libraries. # # ``IMPORTEDLIBS ...`` # @@ -334,11 +317,138 @@ function(tribits_add_executable EXE_NAME) message("") message("TRIBITS_ADD_EXECUTABLE: ${EXE_NAME} ${ARGN}") endif() - + + tribits_add_executable_assert_correct_call_context() + + # + # A) Parse the input arguments + # + + cmake_parse_arguments( + #prefix + PARSE + #options + "NOEXEPREFIX;NOEXESUFFIX;ADD_DIR_TO_NAME;INSTALLABLE" + #one_value_keywords + "" + #multi_value_keywords + "SOURCES;CATEGORIES;HOST;XHOST;HOSTTYPE;XHOSTTYPE;EXCLUDE_IF_NOT_TRUE;DIRECTORY;TESTONLYLIBS;IMPORTEDLIBS;DEPLIBS;COMM;LINKER_LANGUAGE;TARGET_DEFINES;DEFINES;ADDED_EXE_TARGET_NAME_OUT" + ${ARGN} + ) + + tribits_check_for_unparsed_arguments() + + # Executable not added by default! + if(PARSE_ADDED_EXE_TARGET_NAME_OUT) + set(${PARSE_ADDED_EXE_TARGET_NAME_OUT} "" PARENT_SCOPE) + endif() + + set(EXE_BINARY_NAME ${EXE_NAME}) + tribits_add_executable_adjust_exe_name(EXE_BINARY_NAME) + + tribits_add_executable_is_skipped(skipAddExecutable) + if (skipAddExecutable) + return() + endif() + + tribits_add_executable_get_adjusted_sources_list(EXE_SOURCES) + + tribits_add_executable_assert_testonlylibs() + + tribits_add_executable_assert_importedlibs() + + tribits_add_executable_convert_from_deplibs() + + # + # B) Add the executable and set its properties + # + + if(${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("TRIBITS_ADD_EXECUTABLE: add_executable(${EXE_BINARY_NAME} ${EXE_SOURCES})") + endif() + add_executable(${EXE_BINARY_NAME} ${EXE_SOURCES}) + append_global_set(${PARENT_PACKAGE_NAME}_ALL_TARGETS ${EXE_BINARY_NAME}) + + if(PARSE_ADDED_EXE_TARGET_NAME_OUT) + set(${PARSE_ADDED_EXE_TARGET_NAME_OUT} ${EXE_BINARY_NAME} PARENT_SCOPE) + endif() + + if (PARSE_DEFINES) + message(WARNING "WARNING: Passing extra defines through 'DEFINES' ${PARSE_DEFINES}" + " is deprecated. Instead, pass them through 'TARGET_DEFINES'. The 'DEFINES'" + " argument was incorrectly implemented by calling add_definitions() which has" + " directory scope and not function scope as was documented. This resulted in" + " confusing behavior. If one wishes to set defines at the directly level," + " just call add_definitions() directly.") + add_definitions(${PARSE_DEFINES}) + endif() + + if (PARSE_TARGET_DEFINES) + target_compile_definitions(${EXE_BINARY_NAME} PUBLIC ${PARSE_TARGET_DEFINES}) + endif() + + if(PARSE_NOEXESUFFIX AND NOT WIN32) + set_target_properties(${EXE_BINARY_NAME} PROPERTIES SUFFIX "") + else() + set_target_properties(${EXE_BINARY_NAME} PROPERTIES SUFFIX + ${${PROJECT_NAME}_CMAKE_EXECUTABLE_SUFFIX}) + endif() + + tribits_set_linker_language_from_arg( ${EXE_BINARY_NAME} + "${PARSE_LINKER_LANGUAGE}" ) + + assert_defined(${PROJECT_NAME}_LINK_SEARCH_START_STATIC) + if (${PROJECT_NAME}_LINK_SEARCH_START_STATIC) + #message("${EXE_BINARY_NAME}: Adding property LINK_SEARCH_START_STATIC") + set_property(TARGET ${EXE_BINARY_NAME} PROPERTY LINK_SEARCH_START_STATIC 1) + endif() + + if(PARSE_DIRECTORY) + set_target_properties( ${EXE_BINARY_NAME} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${PARSE_DIRECTORY} ) + endif() + + set_property(TARGET ${EXE_BINARY_NAME} APPEND PROPERTY + LABELS ${PACKAGE_NAME}Exes ${PARENT_PACKAGE_NAME}Exes) + # - # Confirm that package and subpackage macros/functions have been called inteh correct order + # C) Link ${EXE_BINARY_NAME} to direct upstream libraries # - + + target_link_libraries(${EXE_BINARY_NAME} PUBLIC ${${PACKAGE_NAME}_LIBRARIES}) + foreach(depPkg IN LISTS ${PACKAGE_NAME}_LIB_ENABLED_DEPENDENCIES + ${PACKAGE_NAME}_TEST_ENABLED_DEPENDENCIES + ) + target_link_libraries(${EXE_BINARY_NAME} PUBLIC ${depPkg}::all_libs) + endforeach() + foreach(testOnlyLib ${PARSE_TESTONLYLIBS}) + target_link_libraries(${EXE_BINARY_NAME} PUBLIC + "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}${testOnlyLib}") + endforeach() + + # + # D) Install if asked + # + + if(${PROJECT_NAME}_INSTALL_EXECUTABLES AND PARSE_INSTALLABLE) + install( + TARGETS ${EXE_BINARY_NAME} + EXPORT ${PROJECT_NAME} + DESTINATION ${${PROJECT_NAME}_INSTALL_RUNTIME_DIR} + COMPONENT ${PACKAGE_NAME} + ) + endif() + +endfunction() + + +# Assert tribits_add_executable() is called in the correct context +# +# NOTE: This read the variables from the enclosing tribits_add_executable() +# function call scope. +# +function(tribits_add_executable_assert_correct_call_context) + if (CURRENTLY_PROCESSING_SUBPACKAGE) # This is a subpackage being processed @@ -373,142 +483,155 @@ function(tribits_add_executable EXE_NAME) endif() +endfunction() - # - # A) Parse the input arguments - # - cmake_parse_arguments( - #prefix - PARSE - #options - "NOEXEPREFIX;NOEXESUFFIX;ADD_DIR_TO_NAME;INSTALLABLE" - #one_value_keywords - "" - #multi_value_keywords - "SOURCES;CATEGORIES;HOST;XHOST;HOSTTYPE;XHOSTTYPE;EXCLUDE_IF_NOT_TRUE;DIRECTORY;TESTONLYLIBS;IMPORTEDLIBS;DEPLIBS;COMM;LINKER_LANGUAGE;TARGET_DEFINES;DEFINES;ADDED_EXE_TARGET_NAME_OUT" - ${ARGN} - ) +# Modify EXE_BINARY_NAME based in passed-in args +# +# NOTE: This read the variables from the enclosing tribits_add_executable() +# function call scope. +# +function(tribits_add_executable_adjust_exe_name exeBinaryNameInOut) - tribits_check_for_unparsed_arguments() + set(exeBinaryName ${${exeBinaryNameInOut}}) + if (PARSE_ADD_DIR_TO_NAME) + set(dirName "") + tribits_create_name_from_current_source_directory(dirName) + set(exeBinaryName ${dirName}_${exeBinaryName}) + endif() - if(PARSE_ADDED_EXE_TARGET_NAME_OUT) - set(${PARSE_ADDED_EXE_TARGET_NAME_OUT} PARENT_SCOPE) + if (DEFINED PACKAGE_NAME AND NOT PARSE_NOEXEPREFIX) + set(exeBinaryName ${PACKAGE_NAME}_${exeBinaryName}) endif() + set(${exeBinaryNameInOut} ${exeBinaryName} PARENT_SCOPE) - # - # B) Exclude building the test executable based on some criteria - # +endfunction() + + +# Check if to skip adding the executable based on different criteria +# +# NOTE: This read the variables from the enclosing tribits_add_executable() +# function call scope. +# +function(tribits_add_executable_is_skipped skipAddExecutableOut) + + set(skipAddExecutable FALSE) set(ADD_THE_TEST FALSE) set(TEST_NAME ${EXE_NAME}) # For error message tribits_add_test_process_categories(ADD_THE_TEST) if (NOT ADD_THE_TEST) - return() + set(skipAddExecutable TRUE) endif() - set(TEST_NAME) + set(TEST_NAME "") set(ADD_THE_TEST FALSE) tribits_add_test_process_host_hosttype(ADD_THE_TEST) if (NOT ADD_THE_TEST) - return() + set(skipAddExecutable TRUE) endif() tribits_process_comm_args(ADD_SERIAL_EXE ADD_MPI_EXE ${PARSE_COMM}) if (NOT ADD_SERIAL_EXE AND NOT ADD_MPI_EXE) - return() - endif() - - # - # C) Add the executable - # - - set(LIBRARY_NAME_PREFIX "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}") - - if (NOT TRIBITS_ADD_EXECUTABLE_UNIT_TESTING) - tribits_include_directories(REQUIRED_DURING_INSTALLATION_TESTING - ${${PACKAGE_NAME}_INCLUDE_DIRS}) -# set_property(DIRECTORY APPEND PROPERTY PACKAGE_LIBRARY_DIRS -# ${${PACKAGE_NAME}_LIBRARY_DIRS}) - endif() - - set (EXE_SOURCES) - set(EXE_BINARY_NAME ${EXE_NAME}) - - # If requested create a modifier for the name that will be inserted between - # the package name and the given name or exe_name for the test - if(PARSE_ADD_DIR_TO_NAME) - set(DIRECTORY_NAME "") - tribits_create_name_from_current_source_directory(DIRECTORY_NAME) - set(EXE_BINARY_NAME ${DIRECTORY_NAME}_${EXE_BINARY_NAME}) + set(skipAddExecutable TRUE) endif() - if(DEFINED PACKAGE_NAME AND NOT PARSE_NOEXEPREFIX) - set(EXE_BINARY_NAME ${PACKAGE_NAME}_${EXE_BINARY_NAME}) - endif() - - # Exclude the build if requested if (${EXE_BINARY_NAME}_EXE_DISABLE) message("-- " "${EXE_BINARY_NAME} EXE NOT being built due to ${EXE_BINARY_NAME}_EXE_DISABLE=" "'${${EXE_BINARY_NAME}_EXE_DISABLE}'") - return() + set(skipAddExecutable TRUE) endif() - # If exe is in subdirectory prepend that dir name to the source files + set(${skipAddExecutableOut} ${skipAddExecutable} PARENT_SCOPE) + +endfunction() + + +# Get adjusted list of source files +# +# NOTE: This read the variables from the enclosing tribits_add_executable() +# function call scope. +# +function(tribits_add_executable_get_adjusted_sources_list exeSourcesOut) + + set(exeSources "") if(PARSE_DIRECTORY ) - foreach( SOURCE_FILE ${PARSE_SOURCES} ) - if(IS_ABSOLUTE ${SOURCE_FILE}) - set (EXE_SOURCES ${EXE_SOURCES} ${SOURCE_FILE}) + foreach( srcFile ${PARSE_SOURCES} ) + if(IS_ABSOLUTE ${srcFile}) + list(APPEND exeSources "${srcFile}") else() - set (EXE_SOURCES ${EXE_SOURCES} ${PARSE_DIRECTORY}/${SOURCE_FILE}) + list(APPEND exeSources "${PARSE_DIRECTORY}/${srcFile}") endif() endforeach( ) else() - foreach( SOURCE_FILE ${PARSE_SOURCES} ) - set (EXE_SOURCES ${EXE_SOURCES} ${SOURCE_FILE}) + foreach( srcFile ${PARSE_SOURCES} ) + list(APPEND exeSources "${srcFile}") endforeach( ) endif() + set(${exeSourcesOut} ${exeSources} PARENT_SCOPE) + +endfunction() + + +# Assert tribits_add_executable() TESTONLYLIBS +# +# NOTE: This read the variables from the enclosing tribits_add_executable() +# function call scope. +# +function(tribits_add_executable_assert_testonlylibs) # Assert that TESTONLYLIBS only contains TESTONLY libs! - foreach(TESTONLYLIB ${PARSE_TESTONLYLIBS}) - set(PREFIXED_LIB "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}${TESTONLYLIB}") - if (NOT ${PREFIXED_LIB}_INCLUDE_DIRS) - message(FATAL_ERROR "ERROR: '${TESTONLYLIB}' in TESTONLYLIBS not a TESTONLY lib!" + foreach(testOnlyLib ${PARSE_TESTONLYLIBS}) + set(prefixedTestOnlyLib "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}${testOnlyLib}") + tribits_lib_is_testonly(${prefixedTestOnlyLib} libIsTestOnlyLib) + if (NOT libIsTestOnlyLib) + message(FATAL_ERROR "ERROR: '${testOnlyLib}' in TESTONLYLIBS not a TESTONLY lib!" " If this a regular library in this SE package or in an dependent upstream SE" " package then TriBITS will link automatically to it. If you remove this and it" " does not link, then you need to add a new SE package dependency to" " this SE package's dependencies file" " ${${PACKAGE_NAME}_SOURCE_DIR}/cmake/Dependencies.cmake") elseif(PARSE_INSTALLABLE) - message(FATAL_ERROR "ERROR: TESTONLY lib '${TESTONLYLIB}' not allowed with" + message(FATAL_ERROR "ERROR: TESTONLY lib '${testOnlyLib}' not allowed with" " INSTALLABLE executable! An INSTALLABLE executable can only depend on" " non-TESTONLY libraries! Otherwise, when shared libs are used, and" " TESTONLY library would not be installed and the installed executable" " would be unusable!" ) endif() endforeach() +endfunction() + + +# Assert tribits_add_executable() IMPORTEDLIBS +# +# NOTE: This read the variables from the enclosing tribits_add_executable() +# function call scope. +# +function(tribits_add_executable_assert_importedlibs) # Assert that IMPORTEDLIBS are not TESTONLY libs are not regular package # libs! - foreach(IMPORTEDLIB ${PARSE_IMPORTEDLIBS}) - set(PREFIXED_LIB "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}${IMPORTEDLIB}") - if (${PREFIXED_LIB}_INCLUDE_DIRS) + foreach(importedLib ${PARSE_IMPORTEDLIBS}) + set(prefixedImportedLib "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}${importedLib}") + tribits_lib_is_testonly(${prefixedImportedLib} importedLibIsTestOnlyLib) + if (libIsTestOnly) message(FATAL_ERROR - "ERROR: Lib '${IMPORTEDLIB}' being passed through" + "ERROR: Lib '${importedLib}' being passed through" " IMPORTEDLIBS is not allowed to be a TESTONLY lib!" " Use TESTONLYLIBS instead!" ) endif() - list(FIND ${PACKAGE_NAME}_LIBRARIES ${PREFIXED_LIB} FOUND_IDX) - if (NOT FOUND_IDX EQUAL -1) + list(FIND ${PACKAGE_NAME}_LIBRARIES "${PACKAGE_NAME}::${prefixedImportedLib}" + foundPrefixedImportedLibInPkgLibs_idx) + if (NOT foundPrefixedImportedLibInPkgLibs_idx EQUAL -1) message(FATAL_ERROR - "ERROR: Lib '${IMPORTEDLIB}' in IMPORTEDLIBS is in" + "ERROR: Lib '${importedLib}' in IMPORTEDLIBS is in" " this SE package and is *not* an external lib!" " TriBITS takes care of linking against libs the current" - " SE package automatically. Please remove '${IMPORTEDLIB}' from IMPORTEDLIBS!") - elseif (TARGET ${PREFIXED_LIB}) + " SE package automatically. Please remove '${importedLib}' from IMPORTEDLIBS!") + elseif (TARGET ${prefixedImportedLib}) message(FATAL_ERROR - "ERROR: Lib '${IMPORTEDLIB}' being passed through" + "ERROR: Lib '${importedLib}' being passed through" " IMPORTEDLIBS is *not* an external library but instead is a library" " defined in this CMake project!" " TriBITS takes care of linking against libraries in dependent upstream" @@ -519,173 +642,44 @@ function(tribits_add_executable EXE_NAME) endif() endforeach() +endfunction() + + +# Convert from tribits_add_executable() DEPLIBS to IMPORTEDLIBS and TESTONLYLIBS +# +# NOTE: This is a macro as it updates local variables in the +# tribits_add_executable() scope! +# +macro(tribits_add_executable_convert_from_deplibs) + # Convert from old DEPLIBS to TESTONLYLIBS and IMPORTEDLIBS - foreach(DEPLIB ${PARSE_DEPLIBS}) - set(PREFIXED_LIB "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}${DEPLIB}") - if (${PREFIXED_LIB}_INCLUDE_DIRS) - message(WARNING "WARNING: Passing TESTONLY lib '${DEPLIB}' through DEPLIBS" + foreach(depLib ${PARSE_DEPLIBS}) + set(prefixedDepLib "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}${depLib}") + tribits_lib_is_testonly(${prefixedDepLib} depLibIsTestOnlyLib) + if (depLibIsTestOnlyLib) + message(WARNING "WARNING: Passing TESTONLY lib '${depLib}' through DEPLIBS" " is deprecated! Instead, please pass through TESTONLYLIBS instead!" " DEPLIBS is deprecated!") - list(APPEND PARSE_TESTONLYLIBS ${DEPLIB}) - elseif (TARGET ${PREFIXED_LIB}) - message(WARNING "WARNING: Passing non-TESTONLY lib '${DEPLIB}' through DEPLIBS" - " is deprecated! The library '${DEPLIB}' appears to be a" + list(APPEND PARSE_TESTONLYLIBS ${depLib}) + elseif (TARGET ${prefixedDepLib}) + message(WARNING "WARNING: Passing non-TESTONLY lib '${depLib}' through DEPLIBS" + " is deprecated! The library '${depLib}' appears to be a" " library defined in this CMake project." " TriBITS takes care of linking against libraries in dependent upstream" - " SE packages. Therefore, please remove '${DEPLIB}' from this list." + " SE packages. Therefore, please remove '${depLib}' from this list." " If you want to link to a library from an upstream SE" " package, then add the SE package name to the appropriate category" " in this SE package's dependencies file: " " ${${PACKAGE_NAME}_SOURCE_DIR}/cmake/Dependencies.cmake") + # ToDo: Convert the above 'WARNING' to 'SEND_ERROR' else() - message(WARNING "WARNING: Passing external lib '${DEPLIB}' through" + message(WARNING "WARNING: Passing external lib '${depLib}' through" " DEPLIBS is deprecated! Instead, pass through IMPORTEDLIBS!" " DEPLIBS is deprecated!" " Please note that only external libs are allowed to be passed through" " IMPORTEDLIBS.") - list(APPEND PARSE_IMPORTEDLIBS ${DEPLIB}) - endif() - endforeach() - - foreach(TESTONLYLIB_IN ${PARSE_TESTONLYLIBS}) - set(TESTONLYLIB "${LIBRARY_NAME_PREFIX}${TESTONLYLIB_IN}") - if (${TESTONLYLIB}_INCLUDE_DIRS) - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message(STATUS "Adding include directories ${TESTONLYLIB}_INCLUDE_DIRS ...") - endif() - include_directories(${${TESTONLYLIB}_INCLUDE_DIRS}) + list(APPEND PARSE_IMPORTEDLIBS ${depLib}) endif() endforeach() - if (PARSE_DEFINES) - message(WARNING "WARNING: Passing extra defines through 'DEFINES' ${PARSE_DEFINES}" - " is deprecated. Instead, pass them through 'TARGET_DEFINES'. The 'DEFINES'" - " argument was incorrectly implemented by calling add_definitions() which has" - " directory scope and not function scope as was documented. This resulted in" - " confusing behavior. If one wishes to set defines at the directly level," - " just call add_definitions() directly.") - add_definitions(${PARSE_DEFINES}) - endif() - - if(${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("TRIBITS_ADD_EXECUTABLE: add_executable(${EXE_BINARY_NAME} ${EXE_SOURCES})") - endif() - add_executable(${EXE_BINARY_NAME} ${EXE_SOURCES}) - append_global_set(${PARENT_PACKAGE_NAME}_ALL_TARGETS ${EXE_BINARY_NAME}) - - if(PARSE_ADDED_EXE_TARGET_NAME_OUT) - set(${PARSE_ADDED_EXE_TARGET_NAME_OUT} ${EXE_BINARY_NAME} PARENT_SCOPE) - endif() - - if (PARSE_TARGET_DEFINES) - target_compile_definitions(${EXE_BINARY_NAME} PUBLIC ${PARSE_TARGET_DEFINES}) - endif() - - if(PARSE_NOEXESUFFIX AND NOT WIN32) - set_target_properties(${EXE_BINARY_NAME} PROPERTIES SUFFIX "") - else() - set_target_properties(${EXE_BINARY_NAME} PROPERTIES SUFFIX - ${${PROJECT_NAME}_CMAKE_EXECUTABLE_SUFFIX}) - endif() - - tribits_set_linker_language_from_arg( ${EXE_BINARY_NAME} - "${PARSE_LINKER_LANGUAGE}" ) - - set(LINK_LIBS) - - # First, add in the passed in TESTONLY dependent libraries - if (PARSE_TESTONLYLIBS) - foreach(LIB ${PARSE_TESTONLYLIBS}) - list(APPEND LINK_LIBS "${LIBRARY_NAME_PREFIX}${LIB}") - endforeach() - endif() - - # Second, add the package's own regular libraries - if(NOT ${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING) - list(APPEND LINK_LIBS ${${PACKAGE_NAME}_LIBRARIES}) - else() - list(APPEND LINK_LIBS ${${PACKAGE_NAME}_INSTALLATION_LIBRARIES}) - endif() - - # Third, add the IMPORTEDLIBS - if (PARSE_IMPORTEDLIBS) - list(APPEND LINK_LIBS ${PARSE_IMPORTEDLIBS}) - endif() - - # Call include_directories() and link_directories(...) for upstream - # dependent Packages and TPLs and accumulate the list of libraries that will - # need to be linked to. - - if(NOT ${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING - AND NOT ${PACKAGE_NAME}_INCLUDE_DIRS - ) - # No libraries have been added for this package so - # add the upstream package and TPL includes and libraries - tribits_sort_and_append_package_include_and_link_dirs_and_libs( - ${PACKAGE_NAME} LIB LINK_LIBS) - tribits_sort_and_append_tpl_include_and_link_dirs_and_libs( - ${PACKAGE_NAME} LIB LINK_LIBS) - endif() - - tribits_sort_and_append_package_include_and_link_dirs_and_libs( - ${PACKAGE_NAME} TEST LINK_LIBS) - - if(NOT ${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING) - tribits_sort_and_append_tpl_include_and_link_dirs_and_libs( - ${PACKAGE_NAME} TEST LINK_LIBS) - else() - list(APPEND LINK_LIBS ${${PACKAGE_NAME}_INSTALLATION_TPL_LIBRARIES}) - endif() - - # Last, add last_lib to get extra link options on the link line - if (${PROJECT_NAME}_EXTRA_LINK_FLAGS) - list(APPEND LINK_LIBS last_lib) - endif() - - if (${PROJECT_NAME}_DUMP_LINK_LIBS) - message("-- ${EXE_NAME}:LINK_LIBS='${LINK_LIBS}'") - endif() - - target_link_libraries(${EXE_BINARY_NAME} PUBLIC ${LINK_LIBS}) - - assert_defined(${PROJECT_NAME}_LINK_SEARCH_START_STATIC) - if (${PROJECT_NAME}_LINK_SEARCH_START_STATIC) - #message("${EXE_BINARY_NAME}: Adding property LINK_SEARCH_START_STATIC") - set_property(TARGET ${EXE_BINARY_NAME} PROPERTY LINK_SEARCH_START_STATIC 1) - endif() - - if(PARSE_DIRECTORY) - set_target_properties( ${EXE_BINARY_NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${PARSE_DIRECTORY} ) - endif() - - set_property(TARGET ${EXE_BINARY_NAME} APPEND PROPERTY - LABELS ${PACKAGE_NAME}Exes ${PARENT_PACKAGE_NAME}Exes) - - if(${PROJECT_NAME}_INSTALL_EXECUTABLES AND PARSE_INSTALLABLE) - install( - TARGETS ${EXE_BINARY_NAME} - EXPORT ${PROJECT_NAME} - DESTINATION ${${PROJECT_NAME}_INSTALL_RUNTIME_DIR} - COMPONENT ${PACKAGE_NAME} - ) - endif() -endfunction() - - -# -# Setup include directories and library dependencies -# - -#if (${PROJECT_NAME}_VERBOSE_CONFIGURE) -# message("TribitsAddExecutable.cmake") -# print_var(${PACKAGE_NAME}_INCLUDE_DIRS) -# print_var(${PACKAGE_NAME}_LIBRARY_DIRS) -#endif() -# -#if (NOT TRIBITS_ADD_EXECUTABLE_UNIT_TESTING) -# include_directories(REQUIRED_DURING_INSTALLATION_TESTING -# ${${PACKAGE_NAME}_INCLUDE_DIRS}) -# set_property(DIRECTORY APPEND PROPERTY PACKAGE_LIBRARY_DIRS -# ${${PACKAGE_NAME}_LIBRARY_DIRS}) -#endif() +endmacro() diff --git a/cmake/tribits/core/package_arch/TribitsAddExecutableAndTest.cmake b/cmake/tribits/core/package_arch/TribitsAddExecutableAndTest.cmake index 46b2b13a088d..298f64ac75c7 100644 --- a/cmake/tribits/core/package_arch/TribitsAddExecutableAndTest.cmake +++ b/cmake/tribits/core/package_arch/TribitsAddExecutableAndTest.cmake @@ -78,7 +78,7 @@ macro(tribits_add_test_wrapper) endif() endmacro() -# + # @FUNCTION: tribits_add_executable_and_test() # # Add an executable and a test (or several tests) all in one shot (just calls @@ -113,6 +113,7 @@ endmacro() # [ENVIRONMENT = = ...] # [INSTALLABLE] # [TIMEOUT ] +# [LIST_SEPARATOR ] # [ADDED_EXE_TARGET_NAME_OUT ] # [ADDED_TESTS_NAMES_OUT ] # ) @@ -159,7 +160,7 @@ function(tribits_add_executable_and_test EXE_NAME) #one_value_keywords "DISABLED" #mulit_value_keywords - "SOURCES;DEPLIBS;TESTONLYLIBS;IMPORTEDLIBS;NAME;NAME_POSTFIX;NUM_MPI_PROCS;DIRECTORY;KEYWORDS;COMM;ARGS;PASS_REGULAR_EXPRESSION;FAIL_REGULAR_EXPRESSION;ENVIRONMENT;TIMEOUT;CATEGORIES;HOST;XHOST;XHOST_TEST;HOSTTYPE;XHOSTTYPE;EXCLUDE_IF_NOT_TRUE;XHOSTTYPE_TEST;LINKER_LANGUAGE;TARGET_DEFINES;DEFINES;ADDED_EXE_TARGET_NAME_OUT;ADDED_TESTS_NAMES_OUT" + "SOURCES;DEPLIBS;TESTONLYLIBS;IMPORTEDLIBS;NAME;NAME_POSTFIX;NUM_MPI_PROCS;DIRECTORY;KEYWORDS;COMM;ARGS;PASS_REGULAR_EXPRESSION;FAIL_REGULAR_EXPRESSION;ENVIRONMENT;TIMEOUT;LIST_SEPARATOR;CATEGORIES;HOST;XHOST;XHOST_TEST;HOSTTYPE;XHOSTTYPE;EXCLUDE_IF_NOT_TRUE;XHOSTTYPE_TEST;LINKER_LANGUAGE;TARGET_DEFINES;DEFINES;ADDED_EXE_TARGET_NAME_OUT;ADDED_TESTS_NAMES_OUT" ${ARGN} ) @@ -193,7 +194,7 @@ function(tribits_add_executable_and_test EXE_NAME) tribits_fwd_parse_opt(COMMON_CALL_ARGS NOEXESUFFIX) # - # C) tribitsaddexecutable(...) + # C) tribits_add_executable(...) # set(CALL_ARGS "") @@ -219,7 +220,7 @@ function(tribits_add_executable_and_test EXE_NAME) endif() # - # D) tribitsaddtest(...) + # D) tribits_add_test(...) # set(CALL_ARGS "") @@ -236,6 +237,7 @@ function(tribits_add_executable_and_test EXE_NAME) tribits_fwd_parse_opt(CALL_ARGS STANDARD_PASS_OUTPUT) tribits_fwd_parse_opt(CALL_ARGS WILL_FAIL) tribits_fwd_parse_arg(CALL_ARGS TIMEOUT) + tribits_fwd_parse_arg(CALL_ARGS LIST_SEPARATOR) tribits_fwd_parse_opt(CALL_ARGS ADD_DIR_TO_NAME) tribits_fwd_parse_opt(CALL_ARGS ADDED_TESTS_NAMES_OUT) if (PARSE_XHOST_TEST) diff --git a/cmake/tribits/core/package_arch/TribitsAddExecutableTestHelpers.cmake b/cmake/tribits/core/package_arch/TribitsAddExecutableTestHelpers.cmake index 1121de2f3eb1..78f98f0bac4e 100644 --- a/cmake/tribits/core/package_arch/TribitsAddExecutableTestHelpers.cmake +++ b/cmake/tribits/core/package_arch/TribitsAddExecutableTestHelpers.cmake @@ -37,6 +37,8 @@ # ************************************************************************ # @HEADER +include(TribitsCMakePolicies NO_POLICY_SCOPE) + include(AdvancedSet) include(MessageWrapper) @@ -96,8 +98,9 @@ function( tribits_process_comm_args ADD_SERIAL_FEATURE_OUT ADD_MPI_FEATURE_OUT endfunction() -function( tribits_create_name_from_current_source_directory DIRECTORY_NAME ) - set(DIRECTORY_NAME "") +function(tribits_create_name_from_current_source_directory directoryNameOut) + set(directoryName "") + #Get the unique part of the path for this test directory string(REGEX REPLACE ${PACKAGE_SOURCE_DIR} "" unique_dir_path ${CMAKE_CURRENT_SOURCE_DIR}) @@ -111,8 +114,7 @@ function( tribits_create_name_from_current_source_directory DIRECTORY_NAME ) # compatible with windows since they use a "\" instead of a "/" for # directory delimiters. I'm not sure how this will react if we encounter a # directory name with a space in it. - string(REGEX REPLACE "/" "_" DIRECTORY_NAME ${unique_dir_path}) + string(REGEX REPLACE "/" "_" directoryName "${unique_dir_path}") - #print_var(DIRECTORY_NAME) - set(DIRECTORY_NAME ${DIRECTORY_NAME} PARENT_SCOPE) + set(${directoryNameOut} "${directoryName}" PARENT_SCOPE) endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsAddLibrary.cmake b/cmake/tribits/core/package_arch/TribitsAddLibrary.cmake new file mode 100644 index 000000000000..26bddd91931e --- /dev/null +++ b/cmake/tribits/core/package_arch/TribitsAddLibrary.cmake @@ -0,0 +1,802 @@ +# @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 + +include(TribitsLibIsTestOnly) +include(CMakeParseArguments) +include(GlobalSet) +include(AppendSet) +include(AppendGlob) +include(AppendGlobalSet) +include(AppendStringVar) +include(PrependGlobalSet) +include(RemoveGlobalDuplicates) +include(TribitsGeneralMacros) +include(TribitsReportInvalidTribitsUsage) +include(SetAndIncDirs) + + +# @FUNCTION: tribits_add_library() +# +# Function used to add a CMake library and target using ``add_library()`` and +# also the ALIAS target ``${PACKAGE_NAME}::`` (where ```` is +# the full CMake target name as returned from ``${}``). +# +# Usage:: +# +# tribits_add_library( +# +# [HEADERS

...] +# [HEADERS_INSTALL_SUBDIR ] +# [NOINSTALLHEADERS ...] +# [SOURCES ...] +# [DEPLIBS ...] +# [IMPORTEDLIBS ...] +# [STATIC|SHARED] +# [TESTONLY] +# [NO_INSTALL_LIB_OR_HEADERS] +# [CUDALIBRARY] +# [ADDED_LIB_TARGET_NAME_OUT ] +# ) +# +# *Sections:* +# +# * `Formal Arguments (tribits_add_library())`_ +# * `Include Directories (tribits_add_library())`_ +# * `Install Targets (tribits_add_library())`_ +# * `Additional Library and Source File Properties (tribits_add_library())`_ +# * `Miscellaneous Notes (tribits_add_library())`_ +# +# .. _Formal Arguments (tribits_add_library()): +# +# **Formal Arguments (tribits_add_library())** +# +# ```` +# +# Required base name of the library. The name of the actual library name +# will be prefixed by ``${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}`` to +# produce:: +# +# = ${${PROJECT_NAME}_LIBRARY_NAME_PREFIX} +# +# This is the name passed to ``add_library( ...)``. The +# name is *not* prefixed by the package name. CMake will of course add +# any standard prefix or post-fix to the library file name appropriate for +# the platform and if this is a static or shared library build (e.g. on +# Linux prefix = ``'lib'``, postfix = ``'.so'`` for shared lib and postfix +# = ``'.a'`` static lib) (see documentation for the built-in CMake command +# ``add_library()``. +# +# ``HEADERS

...`` +# +# List of public header files for using this library. By default, these +# header files are assumed to be in the current source directory. They +# can also contain the relative path or absolute path to the files if they +# are not in the current source directory. This list of headers is passed +# into ``add_library(...)`` as well (which is not strictly needed but is +# helpful for some build tools, like MS Visual Studio). By default, these +# headers will be installed (see `Install Targets +# (tribits_add_library())`_). +# +# ``HEADERS_INSTALL_SUBDIR `` +# +# Optional subdirectory that the headers will be installed under the +# standard installation directory. If ``!=""``, then the +# headers will be installed under +# ``${PROJECT_NAME}_INSTALL_INCLUDE_DIR}/``. Otherwise, +# they will be installed under ``${PROJECT_NAME}_INSTALL_INCLUDE_DIR}/``. +# `Install Targets (tribits_add_library())`_. +# +# ``NOINSTALLHEADERS ...`` +# +# List of private header files which are used by this library. These +# headers are not installed and do not needed to be passed in for any +# purpose other than to pass them into ``add_library()`` as some build +# tools like to have these listed (e.g. MS Visual Studio). +# +# ``SOURCES ...`` +# +# List of source files passed into ``add_library()`` that are compiled +# into header files and included in the library. The compiler used to +# compile the files is determined automatically based on the file +# extension (see CMake documentation for ``add_library()``). +# +# ``DEPLIBS ...`` +# +# List of dependent libraries that are built in the current SE package +# that this library is dependent on. These libraries are passed into +# ``target_link_libraries( ...)`` so that CMake knows about +# the dependency structure of the libraries within this SE package. +# **NOTE:** One must **not** list libraries in other upstream `TriBITS SE +# Packages`_ or libraries built externally from this TriBITS CMake project +# in ``DEPLIBS``. The TriBITS system automatically handles linking to +# libraries in upstream TriBITS SE packages. External libraries need to +# be listed in the ``IMPORTEDLIBS`` argument instead if they are not +# already specified automatically using a `TriBITS TPL`_. +# +# ``IMPORTEDLIBS ...`` +# +# List of dependent libraries built externally from this TriBITS CMake +# project. These libraries are passed into +# ``target_link_libraries( ...)`` so that CMake knows about +# the dependency. However, note that external libraries are often better +# handled as `TriBITS TPLs`_. A well constructed TriBITS package and +# library should never have to use this option! So far, the only case +# where ``IMPORTEDLIBS`` has been shown to be necessary is to pass in the +# standard C math library ``m``. In every other case, a TriBITS TPL +# should be used instead. +# +# ``STATIC`` or ``SHARED`` +# +# If ``STATIC`` is passed in, then a static library will be created +# independent of the value of ``BUILD_SHARED_LIBS``. If ``SHARED`` is +# passed in, then a shared library will be created independent of the +# value of ``BUILD_SHARED_LIBS``. If neither ``STATIC`` or ``SHARED`` are +# passed in, then a shared library will be created if +# ``BUILD_SHARED_LIBS`` evaluates to true, otherwise and a static library +# will be created. If both ``STATIC`` and ``SHARED`` are passed in (which +# is obviously a mistake), then a shared library will be created. +# WARNING: Once you mark a library with ``STATIC``, then all of the +# downstream libraries in the current SE package and all downstream SE +# packages must also be also be marked with ``STATIC``. That is because, +# generally, one can not link a link a static lib against a downstream +# shared lib since that is not portable (but can be done on some platforms +# if, for example, ``-fPIC`` is specified). So be careful to use +# ``STATIC`` in all downstream libraries! +# +# ``TESTONLY`` +# +# If passed in, then ```` will **not** be added to +# ``${PACKAGE_NAME}_LIBRARIES`` and an install target for the library will +# not be added. In this case, the current include directories will be set +# in the global variable ``_INCLUDE_DIR`` which will be +# used in `tribits_add_executable()`_ when a test-only library is linked +# in through its ``DEPLIBS`` argument. Also, the custom property +# ``TRIBITS_TESTONLY_LIB`` will be set to ``TRUE`` which will ensure that +# this library will not be added to the ``${PACKAGE_NAME}::all_libs`` +# target. +# +# ``NO_INSTALL_LIB_OR_HEADERS`` +# +# If specified, then no install targets will be added for the library +# ```` or the header files listed in ``HEADERS``. +# +# ``CUDALIBRARY`` +# +# If specified then ``cuda_add_library()`` is used instead of +# ``add_library()`` where ``cuda_add_library()`` is assumed to be defined +# by the standard ``FindCUDA.cmake`` module as processed using the +# standard TriBITS ``FindTPLCUDA.cmake`` file (see `Standard TriBITS +# TPLs`_). For this option to work, this SE package must have an enabled +# direct or indirect dependency on the TriBITS CUDA TPL or a +# configure-time error may occur about not knowing about +# ``cuda_all_library()``. +# +# ``ADDED_LIB_TARGET_NAME_OUT `` +# +# If specified, then on output the variable ```` will be +# set with the name of the library passed to ``add_library()``. Having +# this name allows the calling ``CMakeLists.txt`` file access and set +# additional target properties (see `Additional Library and Source File +# Properties (tribits_add_library())`_). +# +# .. _Include Directories (tribits_add_library()): +# +# **Include Directories (tribits_add_library())** +# +# Any base directories for the header files listed in the arguments +# ``HEADERS`` or ``NOINSTALLHEADERS`` should be passed into the standard CMake +# command ``include_directories()`` **before** calling this function. For +# example, a CMakeLists.txt file will look like:: +# +# ... +# +# tribits_configure_file(${PACKAGE_NAME}_config.h) +# configure_file(...) +# +# ... +# +# include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +# include_directories(${CMAKE_CURRENT_BINARY_DIR}) +# +# ... +# +# tribits_add_library( +# SOURCES +# .c +# /.cpp +# /.F90 +# ... +# HEADERS +# .h +# /.hpp +# ... +# NONINSTALLHEADERS .hpp .hpp ... +# ... +# ) +# +# The include of ``${CMAKE_CURRENT_BINARY_DIR}`` is needed for any generated +# header files (e.g. using raw ``configure_file()`` or +# `tribits_configure_file()`_) or any generated Fortran ``*.mod`` module files +# generated as a byproduct of compiling F90+ source files (that contain one or +# more Fortran module declarations). +# +# The function ``tribits_add_library()`` will grab the list of all of the +# include directories in scope from prior calls to ``include_directories()`` +# and will add this to the generated library target using +# ``target_link_libraries()`` so that they get propagated downstream as well. +# +# .. _Install Targets (tribits_add_library()): +# +# **Install Targets (tribits_add_library())** +# +# By default, an install target for the library is created using +# ``install(TARGETS ...)`` to install into the directory +# ``${CMAKE_INSTALL_PREFIX}/lib/`` (actual install directory is given by +# ``${PROJECT}_INSTALL_LIB_DIR``, see `Setting the install prefix`_). +# However, this install target will not get created if +# `${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS`_ is ``FASLE`` and +# ``BUILD_SHARD_LIBS=OFF``. But when ``BUILD_SHARD_LIBS=ON``, the install +# target will get added. Also, this install target will *not* get added if +# ``TESTONLY`` or ``NO_INSTALL_LIB_OR_HEADERS`` are passed in. +# +# By default, an install target for the headers listed in ``HEADERS`` will get +# added using ``install(FILES

...)``, but only if ``TESTONLY`` and +# ``NO_INSTALL_LIB_OR_HEADERS`` are not passed in as well. Also, the install +# target for the headers will not get added if +# `${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS`_ is ``FASLE``. If this +# install target is added, then the headers get installed into the flat +# directory ``${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}/`` (default is +# ``${CMAKE_INSTALL_PREFIX}/include/``, see `Setting the install prefix`_). +# If ``HEADERS_INSTALL_SUBDIR`` is set, then the headers will be installed +# under ``${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}//``. +# +# Note that an install target will *not* get created for the headers listed in +# ``NOINSTALLHEADERS``. +# +# .. _Additional Library and Source File Properties (tribits_add_library()): +# +# **Additional Library and Source File Properties (tribits_add_library())** +# +# Once ``add_library( ... ...)`` is called, one +# can set and change properties on the ```` library target +# using the built-in CMake command ``set_target_properties()`` as well as set +# and change properties on any of the source files listed in ``SOURCES`` using +# the built-in CMake command ``set_source_file_properties()`` just like in any +# CMake project. For example:: +# +# tribits_add_library( somelib ... +# ADDED_LIB_TARGET_NAME_OUT somelib_TARGET_NAME ) +# +# set_target_properties( ${somelib_TARGET_NAME} +# PROPERTIES LINKER_LANGUAGE CXX ) +# +# .. _Miscellaneous Notes (tribits_add_library()): +# +# **Miscellaneous Notes (tribits_add_library())** +# +# When the file ``Version.cmake`` exists and the CMake variables +# ``${PROJECT_NAME}_VERSION`` and ``${PROJECT_NAME}_MAJOR_VERSION`` are +# defined, then produced shared libraries will be given the standard SOVERSION +# symlinks (see `/Version.cmake`_). +# +# **WARNING:** Do **NOT** use the built-in CMake command ``add_definitions()`` +# to add defines ``-D`` to the compile command line that will +# affect any of the header files in the package! These CMake-added defines +# are only set locally in this directory and child directories. These defines +# will **NOT** be set when code in peer directories (e.g. a downstream TriBITS +# packages) compiles that may include these header files. To add defines that +# affect header files, please use a configured header file (see +# `tribits_configure_file()`_). +# +function(tribits_add_library LIBRARY_NAME_IN) + + tribits_add_library_assert_correct_call_context() + + # Set library prefix and name + + set(LIBRARY_NAME_PREFIX "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}") + set(LIBRARY_NAME ${LIBRARY_NAME_PREFIX}${LIBRARY_NAME_IN}) + + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("\nTRIBITS_ADD_LIBRARY: ${LIBRARY_NAME}") + if(${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING) + message("\n${PACKAGE_NAME}_LIBRARIES In installation testing mode," + " libraries will be found instead of created.") + endif() + print_var(${PACKAGE_NAME}_LIBRARIES) + endif() + + # Parse input args + + cmake_parse_arguments( + #prefix + PARSE + #Options + "STATIC;SHARED;TESTONLY;NO_INSTALL_LIB_OR_HEADERS;CUDALIBRARY" + #one_value_keywords + "" + #mulit_value_keywords + "HEADERS;HEADERS_INSTALL_SUBDIR;NOINSTALLHEADERS;SOURCES;DEPLIBS;IMPORTEDLIBS;DEFINES;ADDED_LIB_TARGET_NAME_OUT" + ${ARGN} + ) + + tribits_check_for_unparsed_arguments() + + # ToDo: Assert that HEADERS_INSTALL_SUBDIR has 0 or 1 entries! + # ToDo: Assert that ADDED_LIB_TARGET_NAME_OUT as 0 or 1 entries! + + if(PARSE_HEADERS) + list(REMOVE_DUPLICATES PARSE_HEADERS) + endif() + if(PARSE_SOURCES) + list(REMOVE_DUPLICATES PARSE_SOURCES) + endif() + + # Library not added by default + if(PARSE_ADDED_LIB_TARGET_NAME_OUT) + set(${PARSE_ADDED_LIB_TARGET_NAME_OUT} "" PARENT_SCOPE) + endif() + + # + # Create library target if not doing installation testing or if this is a + # TESTONLY library. + # + + if (NOT ${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING OR PARSE_TESTONLY) + + if (PARSE_DEPLIBS AND ${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("-- " "DEPLIBS = ${PARSE_DEPLIBS}") + endif() + if (PARSE_IMPORTEDLIBS AND ${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("-- " "IMPORTEDLIBS = ${PARSE_IMPORTEDLIBS}") + endif() + + # Assert DEPLIBS and IMPORTEDLIBS + + tribits_add_library_assert_deplibs() + tribits_add_library_assert_importedlibs() + + # Add the library and all the dependencies + + if (PARSE_DEFINES) + add_definitions(${PARSE_DEFINES}) + endif() + + if (PARSE_STATIC) + set(STATIC_KEYWORD "STATIC") + else() + set(STATIC_KEYWORD "") + endif() + + if (PARSE_SHARED) + set(SHARED_KEYWORD "SHARED") + else() + set(SHARED_KEYWORD "") + endif() + + if (NOT PARSE_CUDALIBRARY) + add_library( + ${LIBRARY_NAME} + ${STATIC_KEYWORD} + ${SHARED_KEYWORD} + ${PARSE_HEADERS} + ${PARSE_NOINSTALLHEADERS} + ${PARSE_SOURCES} + ) + else() + cuda_add_library( + ${LIBRARY_NAME} + ${PARSE_HEADERS} + ${PARSE_NOINSTALLHEADERS} + ${PARSE_SOURCES} + ) + endif() + + if(PARSE_ADDED_LIB_TARGET_NAME_OUT) + set(${PARSE_ADDED_LIB_TARGET_NAME_OUT} ${LIBRARY_NAME} PARENT_SCOPE) + endif() + + if (PARSE_TESTONLY) + tribits_set_lib_is_testonly(${LIBRARY_NAME}) + endif() + + set_property( + TARGET ${LIBRARY_NAME} + APPEND PROPERTY + LABELS ${PACKAGE_NAME}Libs ${PARENT_PACKAGE_NAME}Libs + ) + + if (NOT "${${PROJECT_NAME}_VERSION}" STREQUAL "" AND + NOT "${${PROJECT_NAME}_MAJOR_VERSION}" STREQUAL "" + ) + set_target_properties( + ${LIBRARY_NAME} + PROPERTIES + VERSION ${${PROJECT_NAME}_VERSION} + SOVERSION ${${PROJECT_NAME}_MAJOR_VERSION} + ) + endif() + + prepend_global_set(${PARENT_PACKAGE_NAME}_LIB_TARGETS ${LIBRARY_NAME}) + prepend_global_set(${PARENT_PACKAGE_NAME}_ALL_TARGETS ${LIBRARY_NAME}) + + # + # Link ${LIBRARY_NAME} to direct upstream libraries + # + + # DEPLIBS + foreach(depLib ${PARSE_DEPLIBS}) + target_link_libraries(${LIBRARY_NAME} PUBLIC "${LIBRARY_NAME_PREFIX}${depLib}") + endforeach() + # ${PACKAGE_NAME}_LIBRARIES + target_link_libraries(${LIBRARY_NAME} PUBLIC ${${PACKAGE_NAME}_LIBRARIES}) + # ${PACKAGE_NAME}_LIB_ENABLED_DEPENDENCIES + foreach(depPkg IN LISTS ${PACKAGE_NAME}_LIB_ENABLED_DEPENDENCIES) + target_link_libraries(${LIBRARY_NAME} PUBLIC ${depPkg}::all_libs) + endforeach() + # ${PACKAGE_NAME}_TEST_ENABLED_DEPENDENCIES (TESTONLY lib) + if (PARSE_TESTONLY) + foreach(depPkg IN LISTS ${PACKAGE_NAME}_TEST_ENABLED_DEPENDENCIES) + target_link_libraries(${LIBRARY_NAME} PUBLIC ${depPkg}::all_libs) + endforeach() + endif() + # IMPORTEDLIBS + foreach(importedLib ${PARSE_IMPORTEDLIBS}) + target_link_libraries(${LIBRARY_NAME} PUBLIC "${importedLib}") + endforeach() + + # ToDo: #63: Above, allow for other link visibilities other than 'PUBLIC'! + + if (${PROJECT_NAME}_CXX_STANDARD_FEATURE) + target_compile_features(${LIBRARY_NAME} PUBLIC + "${${PROJECT_NAME}_CXX_STANDARD_FEATURE}") + endif() + + # Add to the install target + + tribits_add_library_determine_install_lib_and_or_headers( + installLib installHeaders appendLibAndHeadersToPackageVars) + + if (installLib OR installHeaders) + set_property(GLOBAL PROPERTY ${PROJECT_NAME}_HAS_INSTALL_TARGETS ON) + set_property(GLOBAL PROPERTY ${PACKAGE_NAME}_HAS_INSTALL_TARGETS ON) + endif() + + if (installLib) + install( + TARGETS ${LIBRARY_NAME} + EXPORT ${PACKAGE_NAME} + INCLUDES DESTINATION "${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}" + RUNTIME DESTINATION "${${PROJECT_NAME}_INSTALL_RUNTIME_DIR}" + LIBRARY DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}" + ARCHIVE DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}" + COMPONENT ${PACKAGE_NAME} + ) + endif() + + if (installHeaders) + tribits_install_headers( + HEADERS ${PARSE_HEADERS} + INSTALL_SUBDIR ${PARSE_HEADERS_INSTALL_SUBDIR} + COMPONENT ${PACKAGE_NAME} + ) + endif() + + # Append the new libraries to this package's lists + + if (appendLibAndHeadersToPackageVars) + prepend_global_set(${PACKAGE_NAME}_LIBRARIES ${PACKAGE_NAME}::${LIBRARY_NAME}) + remove_global_duplicates(${PACKAGE_NAME}_LIBRARIES) + if (installLib) + global_set(${PACKAGE_NAME}_HAS_NATIVE_LIBRARIES_TO_INSTALL TRUE) + endif() + else() + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("-- " "Skipping augmentation of package's lists of libraries! ...") + endif() + endif() + + # Set INTERFACE_INCLUDE_DIRECTORIES property for added library and must + # only do for the build interface (not the install interface). + get_directory_property(INCLUDE_DIRS_CURRENT INCLUDE_DIRECTORIES) + set(buildInterfaceIncludeDirs) + foreach (includeDir IN LISTS INCLUDE_DIRS_CURRENT) + list(APPEND buildInterfaceIncludeDirs "$") + endforeach() + target_include_directories( ${LIBRARY_NAME} PUBLIC ${buildInterfaceIncludeDirs} ) + + # Add ALIAS library :: + add_library(${PACKAGE_NAME}::${LIBRARY_NAME} ALIAS ${LIBRARY_NAME}) + + # Optionally Set IMPORTED_NO_SYSTEM + if (${PROJECT_NAME}_IMPORTED_NO_SYSTEM) + set_target_properties(${LIBRARY_NAME} PROPERTIES IMPORTED_NO_SYSTEM TRUE) + endif() + + endif() #if not in installation testing mode + + # Adjust for installation testing + + if (${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING) + list(FIND ${PROJECT_NAME}_INSTALLATION_PACKAGE_LIST ${PACKAGE_NAME} + ${PACKAGE_NAME}_WAS_INSTALLED) + if(${${PACKAGE_NAME}_WAS_INSTALLED} EQUAL -1) + message(FATAL_ERROR + "The package ${PACKAGE_NAME} was not installed with ${PROJECT_NAME}!" + " Please disable package ${PACKAGE_NAME} or install it.") + endif() + global_set(${PACKAGE_NAME}_LIBRARIES ${${PACKAGE_NAME}_INSTALLATION_LIBRARIES}) + endif() + + # Print the updates to the linkage variables + + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + print_var(${PACKAGE_NAME}_LIBRARIES) + endif() + +endfunction() +# +# ToDo:, above Deprecate and remove the usage of DEFINES! People should be +# putting defines into configured header files, not adding -D to +# the compile lines! + + +# Function that asserts that tribits_add_library() is called in the correct +# context +# +function(tribits_add_library_assert_correct_call_context) + + if (CURRENTLY_PROCESSING_SUBPACKAGE) + + # This is a subpackage being processed + + if(NOT ${SUBPACKAGE_FULLNAME}_TRIBITS_SUBPACKAGE_CALLED) + tribits_report_invalid_tribits_usage( + "Must call tribits_subpackage() before tribits_add_library()" + " in ${CURRENT_SUBPACKAGE_CMAKELIST_FILE}") + endif() + + if(${SUBPACKAGE_FULLNAME}_TRIBITS_SUBPACKAGE_POSTPROCESS_CALLED) + tribits_report_invalid_tribits_usage( + "Must call tribits_add_library() before " + " tribits_subpackage_postprocess() in ${CURRENT_SUBPACKAGE_CMAKELIST_FILE}") + endif() + + else() + + # This is a package being processed + + if(NOT ${PACKAGE_NAME}_TRIBITS_PACKAGE_DECL_CALLED) + tribits_report_invalid_tribits_usage( + "Must call tribits_package() or tribits_package_decl() before" + " tribits_add_library() in ${TRIBITS_PACKAGE_CMAKELIST_FILE}") + endif() + + if(${PACKAGE_NAME}_TRIBITS_PACKAGE_POSTPROCESS_CALLED) + tribits_report_invalid_tribits_usage( + "Must call tribits_add_library() before " + " tribits_package_postprocess() in ${TRIBITS_PACKAGE_CMAKELIST_FILE}") + endif() + + endif() + +endfunction() + + +# Assert correct DEPSLIB passed to tribits_add_library() +# +# NOTE: This accesses vars from the enclosed calling function +# tribits_add_library() but does not set any variables in that scope! +# +# We also need to make special considerations for test libraries since +# things need to be handled a little bit differently (but not much). In the +# case of test libraries, we need to also pull the test-only dependencies. +# In this case, we will always assume that we will add in the test +# libraries. +# +# ToDo: Turn the below deprecated WARNING messages to FATAL_ERROR once we +# give enough time for people to clean up their codes. +# +function(tribits_add_library_assert_deplibs) + + foreach(depLib ${PARSE_DEPLIBS}) + + set(prefixedDepLib "${LIBRARY_NAME_PREFIX}${depLib}") + + # Is this lib already listed in ${PACKAGE_NAME}_LIBS? + list(FIND ${PACKAGE_NAME}_LIBRARIES "${PACKAGE_NAME}::${prefixedDepLib}" FOUND_IDX) + if (FOUND_IDX GREATER -1) + set(depLibAlreadyInPkgLibs TRUE) + else() + set(depLibAlreadyInPkgLibs FALSE) + endif() + + # ${PREFIXED_LIB" is TESTONLY? + tribits_lib_is_testonly(${prefixedDepLib} depLibIsTestOnlyLib) + + # Check for valid usage (sorted by most common to least common) + if (depLibAlreadyInPkgLibs AND NOT depLibIsTestOnlyLib) # PARSE_TESTONLY=any + # The library being created here is a (regular or testonly) library + # dependent on a regular (non-TESTONLY) lib in this package. This is + # valid usage of DEPLIBS. There is no need to link this new lib to + # the package's upstream dependent package and TPL libraries because + # these are already linked into one of the of the package's own + # upstream libs. + elseif (PARSE_TESTONLY AND depLibAlreadyInPkgLibs AND NOT depLibIsTestOnlyLib) + # The library being created here is TESTONLY library and is + # dependent on a regular (non-TESTONLY) lib. This is valid usage of + # DEPLIBS. In the case of test-only libraries, we always link in + # the upstream libs. + elseif (PARSE_TESTONLY AND depLibIsTestOnlyLib) # any depLibAlreadyInPkgLibs + # The library being created here is TESTONLY library and is dependent + # on another TESTONLY library. This is valid usage of DEPLIBS. In + # this case we just hope that this package correctly specified a TEST + # dependency on the upstream package that owns this upstream TESTONLY + # library if it comes from an upstream package. + elseif (NOT PARSE_TESTONLY AND depLibIsTestOnlyLib) # any depLibAlreadyInPkgLibs + message(WARNING "WARNING: '${depLib}' in DEPLIBS is a TESTONLY lib" + " and it is illegal to link to this non-TESTONLY library '${LIBRARY_NAME}'." + " Such usage is deprecated (and this warning will soon become an error)!" + " If this is a regular library in this package or in an dependent upstream" + " package then TriBITS will link automatically to it. If you remove this and it" + " does not link, then you need to add a new package dependency to" + " this package's dependencies file" + " ${${PACKAGE_NAME}_SOURCE_DIR}/cmake/Dependencies.cmake") + # ToDo: Turn the above to FATAL_ERROR after dropping deprecated code + elseif (NOT depLibAlreadyInPkgLibs AND TARGET ${prefixedDepLib}) # any PARSE_TESTONLY + message(WARNING "WARNING: '${depLib}' in DEPLIBS is not" + " a lib in this package but is a library defined in the current" + " cmake project! Such usage is deprecated (and" + " will result in a configure error soon). If this is a library in" + " a dependent upstream package, then simply remove '${depLib}' from this list." + " TriBITS automatically links in libraries in upstream packages." + " If you remove '${depLib}' from DEPLIBS and your code does" + " not link, then you need to add a new package dependency to" + " this package's dependencies file" + " ${${PACKAGE_NAME}_SOURCE_DIR}/cmake/Dependencies.cmake.") + elseif (NOT depLibAlreadyInPkgLibs AND NOT TARGET ${prefixedDepLib} ) + message(WARNING "WARNING: '${depLib}' in DEPLIBS is not" + " a lib defined in the current cmake project! Such usage is deprecated (and" + " will result in a configure error soon). If this is an external" + " lib you are trying to link in, it should likely be handled as a TriBITS" + " TPL. Otherwise, it should be passed in through IMPORTEDLIBS. However," + " the only case we have found where IMPORTEDLIBS had to be used instead of" + " through a proper TriBITS TPL is the C math library 'm'.") + else() + message(WARNING "WARNING: The case PARSE_TESTONLY=${PARSE_TESTONLY}," + " depLibAlreadyInPkgLibs=${depLibAlreadyInPkgLibs}," + " depLibIsTestOnlyLib=${depLibIsTestOnlyLib}, has" + " not yet been handled!") + endif() + + endforeach() + +endfunction() + + +# Assert correct IMPORTEDLIBS passed to tribits_add_library() +# +# NOTE: This accesses vars from the enclosed calling function +# tribits_add_library() but does not set any variables in that scope! +# +# ToDo: Turn the below deprecated WARNING messages to FATAL_ERROR once we +# give enough time for people to clean up their codes. +# +function(tribits_add_library_assert_importedlibs) + foreach(importedLib ${PARSE_IMPORTEDLIBS}) + set(prefixedImportedLib "${LIBRARY_NAME_PREFIX}${importedLib}") + list(FIND ${PACKAGE_NAME}_LIBRARIES "${PACKAGE_NAME}::${prefixedImportedLib}" + FOUND_IMPORTEDLIB_IN_LIBRARIES_IDX) + tribits_lib_is_testonly(${prefixedImportedLib} importedLibIsTestOnlyLib) + if (importedLibIsTestOnlyLib) + message(WARNING "WARNING: '${importedLib}' in IMPORTEDLIBS is a TESTONLY lib" + " and it is illegal to pass in through IMPORTEDLIBS!" + " Such usage is deprecated (and this warning will soon become an error)!" + " Should '${importedLib}' instead be passed through DEPLIBS?") + # ToDo: Turn the above to FATAL_ERROR after dropping deprecated code + elseif (FOUND_IMPORTEDLIB_IN_LIBRARIES_IDX GREATER -1) + message(WARNING "WARNING: Lib '${importedLib}' in IMPORTEDLIBS is in" + " this package and is *not* an external lib!" + " Please move '${importedLib}' from the list IMPORTEDLIBS to DEPLIBS.") + elseif (TARGET ${prefixedImportedLib}) + message(WARNING "WARNING: Lib '${importedLib}' being passed through" + " IMPORTEDLIBS is *not* an external library but instead is a library" + " defined in this CMake project!" + " TriBITS takes care of linking against libraries in dependent upstream" + " packages. If you want to link to a library in an upstream" + " package then add the package name to the appropriate category" + " in this package's dependencies file: " + " ${${PACKAGE_NAME}_SOURCE_DIR}/cmake/Dependencies.cmake.") + endif() + endforeach() +endfunction() + + +# Determine lib and/or headers should be installed and if the package vars +# should be updated +# +# NOTE: This reads the parsed arguments (prefixed with ``PARSE_``) from the +# calling tribits_add_library() function from the enclosing scope. +# +function(tribits_add_library_determine_install_lib_and_or_headers + installLibOut installHeadersOut appendLibAndHeadersToPackageVarsOut + ) + + set(installLib ON) + set(installHeaders ON) + set(appendLibAndHeadersToPackageVars ON) + + if (PARSE_TESTONLY) + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("-- " "Skipping installation hooks for this library" + " because 'TESTONLY' was passed in ...") + endif() + set(installLib OFF) + set(installHeaders OFF) + set(appendLibAndHeadersToPackageVars OFF) + elseif (PARSE_NO_INSTALL_LIB_OR_HEADERS) + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("-- " "Skipping installation hooks for this library" + " because 'NO_INSTALL_LIB_OR_HEADERS' was passed in ...") + endif() + set(installLib OFF) + set(installHeaders OFF) + elseif (NOT ${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS AND NOT BUILD_SHARED_LIBS) + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("-- " "Skipping installation of headers and libraries" + " because ${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS=FALSE and" + " BUILD_SHARED_LIBS=FALSE ...") + endif() + set(installLib OFF) + set(installHeaders OFF) + elseif (NOT ${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS AND BUILD_SHARED_LIBS) + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("-- " "Skipping installation of headers but installing libraries" + " because ${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS=FALSE and" + " BUILD_SHARED_LIBS=TRUE ...") + endif() + set(installHeaders OFF) + endif() + + set(${installLibOut} ${installLib} PARENT_SCOPE) + set(${installHeadersOut} ${installHeaders} PARENT_SCOPE) + set(${appendLibAndHeadersToPackageVarsOut} ${appendLibAndHeadersToPackageVars} + PARENT_SCOPE) + +endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsAddOptionAndDefine.cmake b/cmake/tribits/core/package_arch/TribitsAddOptionAndDefine.cmake index 534ef9e75d55..8c98b1717d74 100644 --- a/cmake/tribits/core/package_arch/TribitsAddOptionAndDefine.cmake +++ b/cmake/tribits/core/package_arch/TribitsAddOptionAndDefine.cmake @@ -40,7 +40,6 @@ include(GlobalSet) -# # @MACRO: tribits_add_option_and_define() # # Add an option and a define variable in one shot. diff --git a/cmake/tribits/core/package_arch/TribitsAddTest.cmake b/cmake/tribits/core/package_arch/TribitsAddTest.cmake index 9d98021f8729..bdf500b5bf1b 100644 --- a/cmake/tribits/core/package_arch/TribitsAddTest.cmake +++ b/cmake/tribits/core/package_arch/TribitsAddTest.cmake @@ -37,10 +37,10 @@ # ************************************************************************ # @HEADER +include(TribitsCMakePolicies NO_POLICY_SCOPE) include(TribitsAddTestHelpers) -# # @FUNCTION: tribits_add_test() # # Add a test or a set of tests for a single executable or command using CTest @@ -68,11 +68,12 @@ include(TribitsAddTestHelpers) # [EXCLUDE_IF_NOT_TRUE ...] # [DISABLED ] # [STANDARD_PASS_OUTPUT -# | PASS_REGULAR_EXPRESSION ";;..."] -# [FAIL_REGULAR_EXPRESSION ";;..."] +# | PASS_REGULAR_EXPRESSION "" "" ...] +# [FAIL_REGULAR_EXPRESSION "" "" ...] # [WILL_FAIL] # [ENVIRONMENT = = ...] # [TIMEOUT ] +# [LIST_SEPARATOR ] # [ADDED_TESTS_NAMES_OUT ] # ) # @@ -189,9 +190,9 @@ include(TribitsAddTestHelpers) # For example, a set of three different tests with argument lists can be # specified as:: # -# POSTIFX_AND_ARGS_0 postfix0 --arg1 --arg2="dummy" -# POSTIFX_AND_ARGS_1 postfix1 --arg2="fly" -# POSTIFX_AND_ARGS_2 postfix2 --arg2="bags" +# POSTIFX_AND_ARGS_0 postfix0 --arg1 --arg2=dummy +# POSTIFX_AND_ARGS_1 postfix1 --arg2=fly +# POSTIFX_AND_ARGS_2 postfix2 --arg2=bags # # This will create three different test cases with the postfix names # ``postfix0``, ``postfix1``, and ``postfix2``. The indexes must be @@ -202,6 +203,13 @@ include(TribitsAddTestHelpers) # allow long argument lists to span multiple lines. See `Adding Multiple # Tests (tribits_add_test())`_ for more details and examples. # +# Note that one of the `` arguments can be empty, in which case +# the base test name is not appended so:: +# +# POSTIFX_AND_ARGS_0 "" --arg1 --arg2=dummy +# +# would create one test without appending the test name. +# # ``COMM [serial] [mpi]`` # # If specified, determines if the test will be added in serial and/or MPI @@ -329,7 +337,7 @@ include(TribitsAddTestHelpers) # MPI executables is unreliable. This is set using the built-in CTest # property ``PASS_REGULAR_EXPRESSION``. # -# ``PASS_REGULAR_EXPRESSION ";;..."`` +# ``PASS_REGULAR_EXPRESSION "" "" ...`` # # If specified, then the test will be assumed to pass only if one of the # regular expressions ````, ```` etc. match the output @@ -339,7 +347,7 @@ include(TribitsAddTestHelpers) # CMake will interpret this as an array element boundary. To match '.', # use '[.]'. # -# ``FAIL_REGULAR_EXPRESSION ";;..."`` +# ``FAIL_REGULAR_EXPRESSION "" "" ...`` # # If specified, then a test will be assumed to fail if one of the regular # expressions ````, ```` etc. match the output send to @@ -354,11 +362,18 @@ include(TribitsAddTestHelpers) # using the built-in CTest property ``WILL_FAIL``. Consult standard CMake # documentation for full behavior. # -# ``ENVIRONMENT = = ...`` +# ``ENVIRONMENT "=" "=" ...``. # -# If passed in, the listed environment variables will be set before -# calling the test. This is set using the built-in CTest property -# ``ENVIRONMENT``. +# If passed in, the listed environment variables will be set by CTest +# before calling the test. This is set using the built-in CTest test +# property ``ENVIRONMENT``. Note, if the env var values contain +# semi-colons ``';'``, then replace the semi-colons ``';'`` with another +# separator ``''`` and pass in ``LIST_SEPARATOR `` so ```` +# will be replaced with ``';'`` at point of usage. If the env var values +# contain any spaces, also quote the entire variable/value pair as +# ``"="``. For example, the env var and value +# ``my_env_var="arg1 b;arg2;I have spaces"`` would need to be passed as +# ``"my_env_var=arg1 barg2I have spaces"``. # # ``TIMEOUT `` # @@ -374,6 +389,18 @@ include(TribitsAddTestHelpers) # ``HEAVY`` for extremely expensive tests). Expensive tests are one of # the worse forms of technical debt that a project can have! # +# ``LIST_SEPARATOR `` +# +# String used as placeholder for the semi-colon char ``';'`` in order to +# allow pass-through. For example, if arguments to the ``ARGS`` or +# ``ENVIRONMENT`` need to use semi-colons, then replace ``';'`` with +# ``''`` (for example) such as with +# ``"somearg=arg1arg2"``, then at the point of usage, +# ``''`` will be replaced with ``';'`` and it will be passed to +# the final command as ``"somearg=arg1;arg2"`` (with as many preceding +# escape backslashes ``'\'`` in front of ``';'`` as is needed for the +# given usage context). +# # ``ADDED_TESTS_NAMES_OUT `` # # If specified, then on output the variable ```` will be set @@ -807,15 +834,15 @@ function(tribits_add_test EXE_NAME) #print_var(POSTFIX_AND_ARGS_LIST) cmake_parse_arguments( + PARSE_ARGV 1 # One named argument #prefix PARSE # options "NOEXEPREFIX;NOEXESUFFIX;STANDARD_PASS_OUTPUT;WILL_FAIL;ADD_DIR_TO_NAME;RUN_SERIAL" #one_value_keywords - "DISABLED" + "DISABLED;LIST_SEPARATOR" #multi_value_keywords "DIRECTORY;KEYWORDS;COMM;NUM_MPI_PROCS;NUM_TOTAL_CORES_USED;ARGS;${POSTFIX_AND_ARGS_LIST};NAME;NAME_POSTFIX;CATEGORIES;HOST;XHOST;HOSTTYPE;XHOSTTYPE;EXCLUDE_IF_NOT_TRUE;PASS_REGULAR_EXPRESSION;FAIL_REGULAR_EXPRESSION;TIMEOUT;ENVIRONMENT;ADDED_TESTS_NAMES_OUT" - ${ARGN} ) tribits_check_for_unparsed_arguments() @@ -848,20 +875,20 @@ function(tribits_add_test EXE_NAME) # If requested create a modifier for the name that will be inserted between # the package name and the given name or exe_name for the test - set(DIRECTORY_NAME "") - if(PARSE_ADD_DIR_TO_NAME) - tribits_create_name_from_current_source_directory(DIRECTORY_NAME) - set(DIRECTORY_NAME "${DIRECTORY_NAME}_") + set(directoryName "") + if (PARSE_ADD_DIR_TO_NAME) + tribits_create_name_from_current_source_directory(directoryName) + set(directoryName "${directoryName}_") endif() #message("TRIBITS_ADD_TEST: ${EXE_NAME}: EXE_BINARY_NAME = ${EXE_BINARY_NAME}") if (PARSE_NAME) - set(TEST_NAME "${DIRECTORY_NAME}${PARSE_NAME}") + set(TEST_NAME "${directoryName}${PARSE_NAME}") elseif (PARSE_NAME_POSTFIX) - set(TEST_NAME "${DIRECTORY_NAME}${EXE_NAME}_${PARSE_NAME_POSTFIX}") + set(TEST_NAME "${directoryName}${EXE_NAME}_${PARSE_NAME_POSTFIX}") else() - set(TEST_NAME "${DIRECTORY_NAME}${EXE_NAME}") + set(TEST_NAME "${directoryName}${EXE_NAME}") endif() set(TEST_NAME "${PACKAGE_NAME}_${TEST_NAME}") @@ -1005,13 +1032,17 @@ function(tribits_add_test EXE_NAME) break() endif() - set( POSTFIX_AND_ARGS ${PARSE_POSTFIX_AND_ARGS_${POSTFIX_AND_ARGS_IDX}} ) + set( POSTFIX_AND_ARGS "${PARSE_POSTFIX_AND_ARGS_${POSTFIX_AND_ARGS_IDX}}" ) list( GET POSTFIX_AND_ARGS 0 POSTFIX ) - set( INARGS ${POSTFIX_AND_ARGS} ) # Initially contains postfix as ele 0 + set( INARGS "${POSTFIX_AND_ARGS}" ) # Initially contains postfix as ele 0 list( REMOVE_AT INARGS 0 ) # Strip off the postfix name - set(TEST_NAME_INSTANCE "${TEST_NAME}_${POSTFIX}${MPI_NAME_POSTFIX}") + if (NOT "${POSTFIX}" STREQUAL "") + set(TEST_NAME_INSTANCE "${TEST_NAME}_${POSTFIX}${MPI_NAME_POSTFIX}") + else() + set(TEST_NAME_INSTANCE "${TEST_NAME}${MPI_NAME_POSTFIX}") + endif() tribits_set_run_serial(${TEST_NAME_INSTANCE} "${PARSE_RUN_SERIAL}" SET_RUN_SERIAL) @@ -1022,7 +1053,6 @@ function(tribits_add_test EXE_NAME) tribits_add_test_add_test_all( ${TEST_NAME_INSTANCE} "${EXECUTABLE_PATH}" "${PARSE_CATEGORIES}" "${NUM_PROCS_USED}" "${NUM_TOTAL_CORES_USED}" - ${PARSE_CREATE_WORKING_DIR} "${SET_RUN_SERIAL}" "${SET_DISABLED_AND_MSG}" ADDED_TEST_NAME ${INARGS} "${${TEST_NAME_INSTANCE}_EXTRA_ARGS}" ) diff --git a/cmake/tribits/core/package_arch/TribitsAddTestHelpers.cmake b/cmake/tribits/core/package_arch/TribitsAddTestHelpers.cmake index f6f82ea09396..b5fe642c17e6 100644 --- a/cmake/tribits/core/package_arch/TribitsAddTestHelpers.cmake +++ b/cmake/tribits/core/package_arch/TribitsAddTestHelpers.cmake @@ -52,7 +52,6 @@ include(MessageWrapper) include(TribitsGetCategoriesString) -# # Do initialization for test helpers # # This must be run just before the packages define their tests and this macro @@ -66,34 +65,32 @@ macro(tribits_add_test_helpers_init) endmacro() -# # Wrapper function for set_tests_properties() to be used in unit testing. # - function(tribits_set_tests_properties) + cmake_parse_arguments(PARSE_ARGV 0 FWD "" "" "") if (NOT TRIBITS_ADD_TEST_ADD_TEST_UNITTEST) - set_tests_properties(${ARGN}) + set_tests_properties(${FWD_UNPARSED_ARGUMENTS}) endif() if (TRIBITS_SET_TEST_PROPERTIES_CAPTURE_INPUT) - append_global_set(TRIBITS_SET_TEST_PROPERTIES_INPUT ${ARGN}) + append_global_set(TRIBITS_SET_TEST_PROPERTIES_INPUT ${FWD_UNPARSED_ARGUMENTS}) endif() endfunction() -# + # Wrapper function for set_property(TEST ...) to be used in unit testing # - function(tribits_set_test_property) + cmake_parse_arguments(PARSE_ARGV 0 FWD "" "" "") if (NOT TRIBITS_ADD_TEST_ADD_TEST_UNITTEST) - set_property(TEST ${ARGN}) + set_property(TEST ${FWD_UNPARSED_ARGUMENTS}) endif() if (TRIBITS_SET_TEST_PROPERTIES_CAPTURE_INPUT) - append_global_set(TRIBITS_SET_TEST_PROPERTIES_INPUT ${ARGN}) + append_global_set(TRIBITS_SET_TEST_PROPERTIES_INPUT ${FWD_UNPARSED_ARGUMENTS}) endif() endfunction() -# # Scale a timeout by ${PROJECT_NAME}_SCALE_TEST_TIMEOUT # # This function will truncate input TIMEOUT_IN but will allow for a simple @@ -148,7 +145,6 @@ function(tribits_scale_timeout TIMEOUT_IN SCALED_TIMEOUT_OUT) endfunction() -# # Function that converts a complete string of command-line arguments # into a form that add_test(...) can correctly deal with. # @@ -159,7 +155,6 @@ endfunction() # active. This allows you to pass in quoted arguments and have them # treated as a single argument. # - function(tribits_convert_cmnd_arg_string_to_add_test_arg_array CMND_ARG_STRING ARG_ARRAY_VARNAME) #message("TRIBITS_CONVERT_CMND_ARG_STRING_TO_ADD_TEST_ARG_ARRAY") @@ -208,11 +203,9 @@ function(tribits_convert_cmnd_arg_string_to_add_test_arg_array CMND_ARG_STRING A endfunction() -# # Determine if to add the test based on if testing is enabled for the current # package or subpackage. # - function(tribits_add_test_process_enable_tests ADD_THE_TEST_OUT) if(${PACKAGE_NAME}_ENABLE_TESTS OR ${PARENT_PACKAGE_NAME}_ENABLE_TESTS) set(ADD_THE_TEST TRUE) @@ -233,13 +226,11 @@ function(tribits_add_test_process_enable_tests ADD_THE_TEST_OUT) endfunction() -# # Determine if to add the test or not based on [X]HOST and [X]HOSTTYPE arguments # # Warning: Arguments for [X]HOST and [X]HOSTTYPE arguments are passed in # implicitly due to scoping of CMake. # - function(tribits_add_test_process_host_hosttype ADD_THE_TEST_OUT) if ("${${PROJECT_NAME}_HOSTNAME}" STREQUAL "") @@ -318,7 +309,6 @@ function(tribits_add_test_process_host_hosttype ADD_THE_TEST_OUT) endfunction() -# # Determine if to add the test or not based on CATEGORIES arguments # # Warning: Argument PARSE_CATEGORIES is passed in implicitly due to scoping of @@ -390,7 +380,6 @@ function(tribits_add_test_process_categories ADD_THE_TEST_OUT) endfunction() -# # FUNCTION: tribits_add_test_get_exe_binary_name() # # Get the full name of a package executable given its root name and other @@ -432,7 +421,6 @@ function(tribits_add_test_get_exe_binary_name EXE_NAME_IN endfunction() -# # Adjust the directory path to an executable for a test # function(tribits_add_test_adjust_directory EXE_BINARY_NAME DIRECTORY @@ -462,7 +450,6 @@ function(tribits_add_test_adjust_directory EXE_BINARY_NAME DIRECTORY endfunction() -# # Get the number of MPI processes to use # function(tribits_add_test_get_num_procs_used NUM_MPI_PROCS_IN @@ -523,7 +510,6 @@ function(tribits_add_test_get_num_procs_used NUM_MPI_PROCS_IN endfunction() -# # Generate the array of arguments for an MPI run # # NOTE: The extra test program arguments are passed through ${ARGN}. @@ -551,7 +537,6 @@ function( tribits_add_test_get_test_cmnd_array CMND_ARRAY_OUT endfunction() -# # Get the number of cores used by process # function(tribits_add_test_get_num_total_cores_used TEST_NAME_IN @@ -595,7 +580,6 @@ function(tribits_add_test_get_num_total_cores_used TEST_NAME_IN endfunction() -# # Read ${TEST_NAME_IN}_SET_DISABLED_AND_MSG and set output var # as used by the TRIBITS_ADD[_ADVANCED]_test() # functions. @@ -622,7 +606,6 @@ function(tribits_set_disabled_and_msg TEST_NAME_IN PARSE_DISABLED endfunction() -# # Read ${TEST_NAME_IN}_SET_RUN_SERIAL and set output var SET_RUN_SERIAL_OUT as # used by the TRIBITS_ADD[_ADVANCED]_test() functions. # @@ -648,7 +631,6 @@ function(tribits_set_run_serial TEST_NAME_IN PARSE_RUN_SERIAL endfunction() -# # Determine if the test should be skipped due to a disable var set # # Usage: @@ -703,12 +685,14 @@ endfunction() # function(tribits_add_test_add_test TEST_NAME EXE_NAME) + string(REPLACE "${PARSE_LIST_SEPARATOR}" "\\;" args "${ARGN}") + if (TRIBITS_ADD_TEST_ADD_TEST_CAPTURE) - append_global_set(TRIBITS_ADD_TEST_ADD_TEST_INPUT NAME ${TEST_NAME} COMMAND ${ARGN}) + append_global_set(TRIBITS_ADD_TEST_ADD_TEST_INPUT NAME ${TEST_NAME} COMMAND ${args}) endif() if (NOT TRIBITS_ADD_TEST_ADD_TEST_UNITTEST) - add_test(NAME ${TEST_NAME} COMMAND ${ARGN}) + add_test(NAME ${TEST_NAME} COMMAND ${args}) endif() tribits_set_tests_properties(${TEST_NAME} PROPERTIES REQUIRED_FILES ${EXE_NAME}) @@ -731,7 +715,7 @@ function(tribits_private_add_test_set_passfail_properties TEST_NAME_IN) if (PARSE_PASS_REGULAR_EXPRESSION) tribits_set_tests_properties(${TEST_NAME_IN} PROPERTIES PASS_REGULAR_EXPRESSION - ${PARSE_PASS_REGULAR_EXPRESSION}) + "${PARSE_PASS_REGULAR_EXPRESSION}") endif() if (PARSE_WILL_FAIL) @@ -781,7 +765,10 @@ endfunction() function(tribits_private_add_test_set_environment TEST_NAME_IN) if (PARSE_ENVIRONMENT) - tribits_set_test_property(${TEST_NAME_IN} PROPERTY ENVIRONMENT ${PARSE_ENVIRONMENT}) + string(REPLACE "${PARSE_LIST_SEPARATOR}" "\\;" PARSE_ENVIRONMENT + "${PARSE_ENVIRONMENT}") + tribits_set_test_property(${TEST_NAME_IN} PROPERTY ENVIRONMENT + "${PARSE_ENVIRONMENT}") endif() endfunction() @@ -804,7 +791,6 @@ function(tribits_private_add_test_set_processors TEST_NAME_IN endfunction() -# # Print test added message! # function(tribits_private_add_test_print_added TEST_NAME_IN CATEGORIES_IN @@ -852,7 +838,6 @@ function(tribits_private_add_test_print_added TEST_NAME_IN CATEGORIES_IN endfunction() -# # Overall add test command # # NOTE: Pass the command arguments on the end in ARGSN. @@ -886,10 +871,8 @@ function(tribits_add_test_add_test_all TEST_NAME_IN endfunction() -# # Set the label and keywords # - function(tribits_private_add_test_add_label_and_keywords TEST_NAME_IN) tribits_set_test_property(${TEST_NAME_IN} APPEND PROPERTY @@ -903,10 +886,8 @@ function(tribits_private_add_test_add_label_and_keywords TEST_NAME_IN) endfunction() -# # Postprocess a test that was added # - function(tribits_private_add_test_post_process_added_test TEST_NAME_IN CATEGORIES_IN NUM_PROCS_USED_IN NUM_TOTAL_CORES_USED_IN RUN_SERIAL_IN DISABLED_MSG_IN @@ -938,10 +919,8 @@ function(tribits_private_add_test_post_process_added_test TEST_NAME_IN endfunction() -# # Add environment and resource properties to a test # - function(tribits_private_add_test_add_environment_and_resource TEST_NAME_IN NUM_PROCS_USED_IN ) diff --git a/cmake/tribits/core/package_arch/TribitsAdjustPackageEnables.cmake b/cmake/tribits/core/package_arch/TribitsAdjustPackageEnables.cmake index a08508730ff1..2cd518463fe0 100644 --- a/cmake/tribits/core/package_arch/TribitsAdjustPackageEnables.cmake +++ b/cmake/tribits/core/package_arch/TribitsAdjustPackageEnables.cmake @@ -41,6 +41,8 @@ include(TribitsProcessPackagesAndDirsLists) include(TribitsAddOptionAndDefine) include(TribitsGeneralMacros) +include(TribitsPrintEnabledPackagesLists) +include(TribitsPackageDependencies) include(AdvancedOption) include(AdvancedSet) @@ -49,6 +51,7 @@ include(CMakeBuildTypesList) include(FindListElement) include(GlobalNullSet) include(PrintNonemptyVar) +include(PrintVarWithSpaces) include(PrintNonemptyVarWithSpaces) include(PrintVar) include(RemoveGlobalDuplicates) @@ -57,6 +60,7 @@ include(MessageWrapper) include(DualScopeSet) include(CMakeParseArguments) + # # Private helper macros # @@ -149,8 +153,8 @@ macro(tribits_private_disable_tpl_required_package_enable # NOTE: We can't assert that ${PACKAGE_NAME}_ENABLE_TESTS or # ${PACKAGE_NAME}_ENABLE_EXAMPLES exists yet because - # tribits_add_optional_package_enables() which defines them is not - # called until after the final package enables are set. + # tribits_set_up_optional_package_enables_and_cache_vars() which defines + # them is not called until after the final package enables are set. endif() @@ -314,7 +318,6 @@ macro(tribits_disable_parents_subpackages PARENT_PACKAGE_NAME) endmacro() -# # Macro that enables all of the subpackages of a parent package. # macro(tribits_enable_parents_subpackages PARENT_PACKAGE_NAME) @@ -396,7 +399,7 @@ endmacro() # macro(tribits_print_package_dependencies PACKAGE_NAME) - set(PRINTED_VAR) + set(PRINTED_VAR "") print_nonempty_var_with_spaces(${PACKAGE_NAME}_LIB_REQUIRED_DEP_PACKAGES PRINTED_VAR) print_nonempty_var_with_spaces(${PACKAGE_NAME}_LIB_OPTIONAL_DEP_PACKAGES PRINTED_VAR) @@ -486,9 +489,12 @@ macro(tribits_private_add_optional_tpl_enable PACKAGE_NAME OPTIONAL_DEP_TPL endmacro() -# Macro that enables optional package interdependencies +# Macro that sets cache vars for optional package interdependencies +# +# This also will set ${PACKAGE_NAME}_ENABLE_TESTS and +# ${PACKAGE_NAME}_ENABLE_EXAMPLES to empty non-cache vars # -macro(tribits_add_optional_package_enables PACKAGE_NAME) +macro(tribits_set_up_optional_package_enables_and_cache_vars PACKAGE_NAME) #message("\nPACKAGE_ARCH_ADD_OPTIONAL_PACKAGE_ENABLES: ${PACKAGE_NAME}") @@ -550,6 +556,142 @@ macro(tribits_add_optional_package_enables PACKAGE_NAME) endmacro() +# Macro that sets up the flat list of direct package dependencies and enabled +# package dependencies and sets ${packageName}_ENABLE_${depPkg} for LIB +# dependencies +# +# This makes it easy to just loop over all of the direct upstream dependencies +# for a package or just the enabled dependencies. +# +# NOTES: +# +# * ${packageName}_LIB_ALL_DEPENDENCIES will be set regardless if +# ${packageName} is enabled or not. +# +# * ${packageName}_LIB_ENABLED_DEPENDENCIES is only set if ${packageName} is +# enabled and will only contain the names of direct library upstream +# internal and external packages ${depPkg} that are required or are +# optional and ${packageName}_ENABLE_${depPkg} is set to ON. +# +# * ${packageName}_TEST_ALL_DEPENDENCIES will be set regardless if +# ${packageName} is enabled or not. +# +# * ${packageName}_TEST_ENABLED_DEPENDENCIES is only set if ${packageName} is +# enabled and will only contain the names of direct test/example upstream +# internal and external packages ${depPkg} that are required or are +# optional and ${packageName}_ENABLE_${depPkg} is set to ON. +# +# * Sets ${packageName}_ENABLE_${depPkg}=ON for every required dep package +# for LIB dependencies (but not TEST dependencies). This allows looping +# over just ${packageName}_LIB_ALL_DEPENDENCIES looking at +# ${packageName}_ENABLE_${depPkg} to see if the package is enable or not. +# This also includes special logic for required subpackages for parent +# packages where only the shell of the parent package is enabled and not +# all of its required subpackages are enabled. +# +macro(tribits_setup_direct_package_dependencies_lists_and_lib_required_enable_vars + packageName + ) + + # LIB dependencies + + set(${packageName}_LIB_ALL_DEPENDENCIES "") + set(${packageName}_LIB_ENABLED_DEPENDENCIES "") + + foreach(depPkg ${${packageName}_LIB_REQUIRED_DEP_PACKAGES}) + list(APPEND ${packageName}_LIB_ALL_DEPENDENCIES ${depPkg}) + if (${PROJECT_NAME}_ENABLE_${packageName} AND ${PROJECT_NAME}_ENABLE_${depPkg}) + set(${packageName}_ENABLE_${depPkg} ON) + list(APPEND ${packageName}_LIB_ENABLED_DEPENDENCIES ${depPkg}) + endif() + endforeach() + # See below NOTE about required subpackage dependencies not being enabled in + # some cases! + + foreach(depPkg ${${packageName}_LIB_OPTIONAL_DEP_PACKAGES}) + list(APPEND ${packageName}_LIB_ALL_DEPENDENCIES ${depPkg}) + if (${PROJECT_NAME}_ENABLE_${packageName} AND ${packageName}_ENABLE_${depPkg}) + list(APPEND ${packageName}_LIB_ENABLED_DEPENDENCIES ${depPkg}) + endif() + endforeach() + + foreach(depPkg ${${packageName}_LIB_REQUIRED_DEP_TPLS}) + list(APPEND ${packageName}_LIB_ALL_DEPENDENCIES ${depPkg}) + if (${PROJECT_NAME}_ENABLE_${packageName}) + set(${packageName}_ENABLE_${depPkg} ON) + list(APPEND ${packageName}_LIB_ENABLED_DEPENDENCIES ${depPkg}) + endif() + endforeach() + + foreach(depPkg ${${packageName}_LIB_OPTIONAL_DEP_TPLS}) + list(APPEND ${packageName}_LIB_ALL_DEPENDENCIES ${depPkg}) + if (${PROJECT_NAME}_ENABLE_${packageName} AND ${packageName}_ENABLE_${depPkg}) + list(APPEND ${packageName}_LIB_ENABLED_DEPENDENCIES ${depPkg}) + endif() + endforeach() + + # TEST dependencies + + set(${packageName}_TEST_ALL_DEPENDENCIES "") + set(${packageName}_TEST_ENABLED_DEPENDENCIES "") + + if (${PROJECT_NAME}_ENABLE_${packageName} + AND + (${packageName}_ENABLE_TESTS OR ${packageName}_ENABLE_EXAMPLES) + ) + set(enablePkgAndTestsOrExamples ON) + else() + set(enablePkgAndTestsOrExamples OFF) + endif() + + foreach(depPkg ${${packageName}_TEST_REQUIRED_DEP_PACKAGES}) + list(APPEND ${packageName}_TEST_ALL_DEPENDENCIES ${depPkg}) + if (enablePkgAndTestsOrExamples) + list(APPEND ${packageName}_TEST_ENABLED_DEPENDENCIES ${depPkg}) + endif() + endforeach() + + foreach(depPkg ${${packageName}_TEST_OPTIONAL_DEP_PACKAGES}) + list(APPEND ${packageName}_TEST_ALL_DEPENDENCIES ${depPkg}) + if (enablePkgAndTestsOrExamples AND ${packageName}_ENABLE_${depPkg}) + list(APPEND ${packageName}_TEST_ENABLED_DEPENDENCIES ${depPkg}) + endif() + endforeach() + + foreach(depPkg ${${packageName}_TEST_REQUIRED_DEP_TPLS}) + list(APPEND ${packageName}_TEST_ALL_DEPENDENCIES ${depPkg}) + if (enablePkgAndTestsOrExamples) + list(APPEND ${packageName}_TEST_ENABLED_DEPENDENCIES ${depPkg}) + endif() + endforeach() + + foreach(depPkg ${${packageName}_TEST_OPTIONAL_DEP_TPLS}) + list(APPEND ${packageName}_TEST_ALL_DEPENDENCIES ${depPkg}) + if (enablePkgAndTestsOrExamples AND ${packageName}_ENABLE_${depPkg}) + list(APPEND ${packageName}_TEST_ENABLED_DEPENDENCIES ${depPkg}) + endif() + endforeach() + +endmacro() +# NOTE: Above, a required dependency of an enabled package may not actually be +# enabled if it is a required subpackage of a parent package and the parent +# package was not actually enabled due to a dependency but the shell of the +# parent package was only enabled at the very end. This is one of the more +# confusing aspects of the TriBITS dependency system. + + +# Function to print the direct package dependency lists +# +function(tribits_print_direct_package_dependencies_lists packageName) + set(PRINTED_VAR "") + message("") + print_nonempty_var_with_spaces(${packageName}_LIB_ENABLED_DEPENDENCIES PRINTED_VAR) + print_var_with_spaces(${packageName}_LIB_ALL_DEPENDENCIES PRINTED_VAR) + print_nonempty_var_with_spaces(${packageName}_TEST_ENABLED_DEPENDENCIES PRINTED_VAR) + print_nonempty_var_with_spaces(${packageName}_TEST_ALL_DEPENDENCIES PRINTED_VAR) +endfunction() + + # # Private helper macros # @@ -698,6 +840,8 @@ macro(tribits_postprocess_package_with_subpackages_enables PACKAGE_NAME) "Setting ${PROJECT_NAME}_ENABLE_${PACKAGE_NAME}=ON" " because ${PROJECT_NAME}_ENABLE_${SUBPACKAGE_FULLNAME}=ON") set(${PROJECT_NAME}_ENABLE_${PACKAGE_NAME} ON) + tribits_postprocess_package_with_subpackages_optional_subpackage_enables( + ${PACKAGE_NAME}) tribits_postprocess_package_with_subpackages_test_example_enables( ${PACKAGE_NAME} TESTS) tribits_postprocess_package_with_subpackages_test_example_enables( @@ -711,6 +855,27 @@ macro(tribits_postprocess_package_with_subpackages_enables PACKAGE_NAME) endmacro() +# Set _ENABLE_=ON if not already enabled for all +# subpackages of a parent package. +# +macro(tribits_postprocess_package_with_subpackages_optional_subpackage_enables + PACKAGE_NAME + ) + #message("TRIBITS_POSTPROCESS_PACKAGE_WITH_SUBPACKAGES_TEST_EXAMPLE_ENABLES '${PACKAGE_NAME}'") + foreach(TRIBITS_SUBPACKAGE ${${PACKAGE_NAME}_SUBPACKAGES}) + set(SUBPACKAGE_FULLNAME ${PACKAGE_NAME}${TRIBITS_SUBPACKAGE}) + if (${PROJECT_NAME}_ENABLE_${SUBPACKAGE_FULLNAME} + AND "${${PACKAGE_NAME}_ENABLE_${SUBPACKAGE_FULLNAME}}" STREQUAL "" + ) + message("-- " + "Setting ${PACKAGE_NAME}_ENABLE_${SUBPACKAGE_FULLNAME}=ON" + " because ${PROJECT_NAME}_ENABLE_${SUBPACKAGE_FULLNAME}=ON") + set(${PACKAGE_NAME}_ENABLE_${SUBPACKAGE_FULLNAME} ON) + endif() + endforeach() +endmacro() + + # Set the parent package tests/examples enables if one subpackage is enabled # and has its tests/examples # @@ -1288,7 +1453,7 @@ macro(tribits_adjust_package_enables) message("Set cache entries for optional packages/TPLs and tests/examples for packages actually enabled ...") message("") foreach(TRIBITS_PACKAGE ${${PROJECT_NAME}_ENABLED_SE_PACKAGES}) - tribits_add_optional_package_enables(${TRIBITS_PACKAGE}) + tribits_set_up_optional_package_enables_and_cache_vars(${TRIBITS_PACKAGE}) endforeach() # @@ -1307,16 +1472,46 @@ macro(tribits_adjust_package_enables) tribits_set_up_enabled_lists_and_se_pkg_idx() + # + # H) Set up flat list of direct external and inner package dependencies (even + # for non-enabled packages) and enabled package dependencies for enabled + # packages + # + + foreach(externalPkgName ${${PROJECT_NAME}_TPLS}) + tribits_extpkg_setup_enabled_dependencies(${externalPkgName}) + # ToDo: Assert that all of the listed dependencies in + # ${externalPkgName}_LIB_ENABLED_DEPENDENCIES exist and are upstream from + # ${externalPkgName} + endforeach() + + foreach(TRIBITS_PACKAGE ${${PROJECT_NAME}_SE_PACKAGES}) + tribits_setup_direct_package_dependencies_lists_and_lib_required_enable_vars( + ${TRIBITS_PACKAGE}) + endforeach() + + if (${PROJECT_NAME}_DUMP_PACKAGE_DEPENDENCIES) + message("\nDumping direct dependencies for each package ...") + foreach(tribitsPkg IN LISTS ${PROJECT_NAME}_DEFINED_TPLS ${PROJECT_NAME}_SE_PACKAGES) + tribits_print_direct_package_dependencies_lists(${tribitsPkg}) + endforeach() + endif() + endmacro() -# Function that sets up the full package dependencies for each enabled -# package. +# Function that sets up the full package dependencies for each enabled package +# including all of its indirect upstream package dependencies. # # This is needed in several different parts of the TriBITS implementation. # +# ToDo: #63: Remove this function since we should not need a full list of +# direct and indirect package dependencies! +# function(tribits_package_set_full_enabled_dep_packages PACKAGE_NAME) + set(PACKAGE_FULL_DEPS_LIST "") + foreach(DEP_PKG ${${PACKAGE_NAME}_LIB_REQUIRED_DEP_PACKAGES}) if (${PROJECT_NAME}_ENABLE_${DEP_PKG}) list(APPEND PACKAGE_FULL_DEPS_LIST ${DEP_PKG}) @@ -1340,7 +1535,7 @@ function(tribits_package_set_full_enabled_dep_packages PACKAGE_NAME) list(REMOVE_DUPLICATES PACKAGE_FULL_DEPS_LIST) endif() - set(ORDERED_PACKAGE_FULL_DEPS_LIST) + set(ORDERED_PACKAGE_FULL_DEPS_LIST "") foreach(DEP_PACKAGE ${PACKAGE_FULL_DEPS_LIST}) @@ -1383,6 +1578,9 @@ endfunction() # Function that creates enable-only dependency data-structures # +# ToDo: #63: Remove this function since we should not need a full list of +# direct and indirect package dependencies! +# function(tribits_set_up_enabled_only_dependencies) set(GENERATE_EXPORT_DEPENDENCIES ${${PROJECT_NAME}_GENERATE_EXPORT_FILE_DEPENDENCIES}) diff --git a/cmake/tribits/core/package_arch/TribitsCMakePolicies.cmake b/cmake/tribits/core/package_arch/TribitsCMakePolicies.cmake index 75569acb3905..eb67ee9d1053 100644 --- a/cmake/tribits/core/package_arch/TribitsCMakePolicies.cmake +++ b/cmake/tribits/core/package_arch/TribitsCMakePolicies.cmake @@ -39,8 +39,9 @@ # Define policies for CMake # It is assumed that the project has already called CMAKE_MINIMUM_REQUIRED. -cmake_policy(SET CMP0003 NEW) -cmake_policy(SET CMP0007 NEW) -cmake_policy(SET CMP0011 NEW) -cmake_policy(SET CMP0053 NEW) -cmake_policy(SET CMP0082 NEW) +cmake_policy(SET CMP0003 NEW) # Don't split up full lib paths to linker args +cmake_policy(SET CMP0007 NEW) # Don't ignore empty list items +cmake_policy(SET CMP0053 NEW) # Make var references much faster +cmake_policy(SET CMP0054 NEW) # Avoid quoted strings lookup variables +cmake_policy(SET CMP0057 NEW) # Support if ( ... IN_LIST ... ) +cmake_policy(SET CMP0082 NEW) # Install rules follow order install() called in subdirs diff --git a/cmake/tribits/core/package_arch/TribitsCommonArgsHelpers.cmake b/cmake/tribits/core/package_arch/TribitsCommonArgsHelpers.cmake index a6370f153723..9aaffca9828d 100644 --- a/cmake/tribits/core/package_arch/TribitsCommonArgsHelpers.cmake +++ b/cmake/tribits/core/package_arch/TribitsCommonArgsHelpers.cmake @@ -55,7 +55,9 @@ function(tribits_set_linker_language_from_arg TARGET_NAME_IN LINKER_LANGUAGE_I if (LINKER_LANGUAGE) - if (${PROJECT_NAME}_VERBOSE_CONFIGURE OR TRIBITS_SET_LINKER_LANGUAGE_FROM_ARG_DEBUG_DUMP) + if (${PROJECT_NAME}_VERBOSE_CONFIGURE + OR TRIBITS_SET_LINKER_LANGUAGE_FROM_ARG_DEBUG_DUMP + ) message("-- Setting linker language for target '${TARGET_NAME_IN}' to '${LINKER_LANGUAGE}'") endif() @@ -63,6 +65,7 @@ function(tribits_set_linker_language_from_arg TARGET_NAME_IN LINKER_LANGUAGE_I TARGET ${TARGET_NAME_IN} APPEND PROPERTY LINKER_LANGUAGE ${LINKER_LANGUAGE} ) + endif() endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsConfigureFile.cmake b/cmake/tribits/core/package_arch/TribitsConfigureFile.cmake new file mode 100644 index 000000000000..55ac9123cd38 --- /dev/null +++ b/cmake/tribits/core/package_arch/TribitsConfigureFile.cmake @@ -0,0 +1,180 @@ +# @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 + + + +# Macro that configures the package's main config.h file +# +function(tribits_add_config_define DEFINE) + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("-- " "Package ${PARENT_PACKAGE_NAME}: adding compiler" + " define to config file: ${DEFINE}") + endif() + global_set(${PARENT_PACKAGE_NAME}_CONFIG_DEFINES + "${${PARENT_PACKAGE_NAME}_CONFIG_DEFINES}\n#define ${DEFINE}") + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("-- ${${PARENT_PACKAGE_NAME}_CONFIG_DEFINES}") + endif() +endfunction() + + +# @FUNCTION: tribits_configure_file() +# +# Macro that configures the package's main configured header file (typically +# called ``${PACKAGE_NAME}_config.h`` but any name can be used). +# +# Usage:: +# +# tribits_configure_file() +# +# This function requires the file:: +# +# ${PACKAGE_SOURCE_DIR}/cmake/.in +# +# exists and it creates the file:: +# +# ${CMAKE_CURRENT_BINARY_DIR}/ +# +# by calling the built-in ``configure_file()`` command:: +# +# configure_file( +# ${PACKAGE_SOURCE_DIR}/cmake/.in +# ${CMAKE_CURRENT_BINARY_DIR}/ +# ) +# +# which does basic substitution of CMake variables (see documentation for +# built-in CMake `configure_file()`_ command for rules on how it performs +# substitutions). This command is typically used to configure the package's +# main `/cmake/_config.h.in`_ file. +# +# In addition to just calling ``configure_file()``, this function also aids in +# creating configured header files adding macros for deprecating code as +# described below. +# +# **Deprecated Code Macros** +# +# If ``${PARENT_PACKAGE_NAME}_SHOW_DEPRECATED_WARNINGS`` is ``TRUE`` (see +# `tribits_add_show_deprecated_warnings_option()`_), then the local CMake +# variable ``${PARENT_PACKAGE_NAME_UC}_DEPRECATED_DECLARATIONS`` is set which +# adds a define ``_DEPRECATED`` (where +# ```` is the package name in all upper-case letters) +# which adds a compiler-specific deprecated warning for an entity. To take +# advantage of this, just add the line:: +# +# @_DEPRECATED_DECLARATIONS@ +# +# to the ``.in`` file and it will be expanded at configure +# time. +# +# Then C/C++ code can use this macro to deprecate functions, variables, +# classes, etc., for example, using:: +# +# _DEPRECATED class SomeDepreatedClass { ... }. +# +# If the particular compiler does not support deprecated warnings, then this +# macro is defined to be empty. See `Regulated Backward Compatibility and +# Deprecated Code`_ for more details. +# +function(tribits_configure_file PACKAGE_NAME_CONFIG_FILE) + + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("\nPACKAGE_CONFIGURE_FILE: ${PACKAGE_NAME_CONFIG_FILE}") + endif() + + # Set up the deprecated attribute if showing deprecated warnings + if (${PARENT_PACKAGE_NAME}_SHOW_DEPRECATED_WARNINGS) + multiline_set(${PARENT_PACKAGE_NAME_UC}_DEPRECATED_DECLARATIONS + "#ifndef ${PARENT_PACKAGE_NAME_UC}_DEPRECATED\n" + "# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))\n" + "# define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED __attribute__((__deprecated__))\n" + "# else\n" + "# define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED\n" + "# endif\n" + "#endif\n" + "\n" + "#ifndef ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_MSG\n" + "# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))\n" + "# define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_MSG(MSG) __attribute__((__deprecated__ (#MSG) ))\n" + "# elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))\n" + "# define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_MSG(MSG) __attribute__((__deprecated__))\n" + "# else\n" + "# define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_MSG(MSG)\n" + "# endif\n" + "#endif\n" + ) + else() + multiline_set(${PARENT_PACKAGE_NAME_UC}_DEPRECATED_DECLARATIONS + "#define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED\n" + "#define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_MSG(MSG)\n" + ) + endif() + + if (${PARENT_PACKAGE_NAME}_HIDE_DEPRECATED_CODE) + string(APPEND ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_DECLARATIONS + "\n#define ${PARENT_PACKAGE_NAME_UC}_HIDE_DEPRECATED_CODE") + endif() + + # Set up the macro to create the define for time monitor + set(TIME_MONITOR_DEFINE_NAME ${PARENT_PACKAGE_NAME_UC}_TEUCHOS_TIME_MONITOR) + set(FUNC_TIME_MONITOR_MACRO_NAME ${PARENT_PACKAGE_NAME_UC}_FUNC_TIME_MONITOR) + set(FUNC_TIME_MONITOR_DIFF_MACRO_NAME ${PARENT_PACKAGE_NAME_UC}_FUNC_TIME_MONITOR_DIFF) + if (${PARENT_PACKAGE_NAME}_ENABLE_TEUCHOS_TIME_MONITOR) + multiline_set(${PARENT_PACKAGE_NAME_UC}_TEUCHOS_TIME_MONITOR_DECLARATIONS + "#ifndef ${FUNC_TIME_MONITOR_MACRO_NAME}\n" + "# define ${TIME_MONITOR_DEFINE_NAME}\n" + "# define ${FUNC_TIME_MONITOR_MACRO_NAME}(FUNCNAME) \\\n" + " TEUCHOS_FUNC_TIME_MONITOR_DIFF(FUNCNAME, ${PARENT_PACKAGE_NAME_UC})\n" + "# define ${FUNC_TIME_MONITOR_DIFF_MACRO_NAME}(FUNCNAME, DIFF) \\\n" + " TEUCHOS_FUNC_TIME_MONITOR_DIFF(FUNCNAME, DIFF)\n" + "#endif\n" + ) + else() + multiline_set(${PARENT_PACKAGE_NAME_UC}_TEUCHOS_TIME_MONITOR_DECLARATIONS + "#define ${FUNC_TIME_MONITOR_MACRO_NAME}(FUNCNAME)\n" + "#define ${FUNC_TIME_MONITOR_DIFF_MACRO_NAME}(FUNCNAME, DIFF)\n" + ) + endif() + + # Configure the file + configure_file( + ${PACKAGE_SOURCE_DIR}/cmake/${PACKAGE_NAME_CONFIG_FILE}.in + ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME_CONFIG_FILE} + ) + +endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsConstants.cmake b/cmake/tribits/core/package_arch/TribitsConstants.cmake index b13675fc14bc..efda842730a2 100644 --- a/cmake/tribits/core/package_arch/TribitsConstants.cmake +++ b/cmake/tribits/core/package_arch/TribitsConstants.cmake @@ -94,13 +94,17 @@ set(${PROJECT_NAME}_PACKAGE_DEPS_TABLE_HTML_FILE_NAME ${PROJECT_NAME}PackageDepe set(${PROJECT_NAME}_PACKAGE_DEPS_FILES_DIR "cmake/dependencies") +set(${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR "external_packages") + +set(${PROJECT_NAME}_BUILD_DIR_CMAKE_PKGS_DIR "cmake_packages") + # Other stuff if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Windows") #Apparently FIND_PROGRAM looks for an exact match of the file name. #So even though "git clone ..." is valid to use on windows we need to give the #full name of the command we want to run. - SET(GIT_NAME git.cmd) + set(GIT_NAME git.cmd) else() - SET(GIT_NAME git) + set(GIT_NAME git) endif() diff --git a/cmake/tribits/core/package_arch/TribitsCopyFilesToBinaryDir.cmake b/cmake/tribits/core/package_arch/TribitsCopyFilesToBinaryDir.cmake index b2f29290f503..514092c19af3 100644 --- a/cmake/tribits/core/package_arch/TribitsCopyFilesToBinaryDir.cmake +++ b/cmake/tribits/core/package_arch/TribitsCopyFilesToBinaryDir.cmake @@ -42,7 +42,6 @@ include(TribitsAddTestHelpers) include(CMakeParseArguments) -# # @FUNCTION: tribits_copy_files_to_binary_dir() # # Function that copies a list of files from a source directory to a diff --git a/cmake/tribits/core/package_arch/TribitsCreateClientTemplateHeaders.cmake b/cmake/tribits/core/package_arch/TribitsCreateClientTemplateHeaders.cmake index 3288e28ba4bf..cc2c6ca42e46 100644 --- a/cmake/tribits/core/package_arch/TribitsCreateClientTemplateHeaders.cmake +++ b/cmake/tribits/core/package_arch/TribitsCreateClientTemplateHeaders.cmake @@ -128,14 +128,14 @@ function(tribits_create_client_template_headers BASE_DIR) # Create the client header file set(CLIENT_HEADER_STR "") - append_string_var(CLIENT_HEADER_STR + string(APPEND CLIENT_HEADER_STR "#include \"${DECL_HEADER_BASE}${${PARENT_PACKAGE_NAME}_TEMPLATE_DECL_EXT}\"\n" ) if (HAVE_${PARENT_PACKAGE_NAME_UC}_EXPLICIT_INSTANTIATION) set(TEMPLATE_INSTANT_TYPE_NAME "explicit instantiation") else() set(TEMPLATE_INSTANT_TYPE_NAME "implicit instantiation") - append_string_var(CLIENT_HEADER_STR + string(APPEND CLIENT_HEADER_STR "#include \"${DECL_HEADER_BASE}${${PARENT_PACKAGE_NAME}_TEMPLATE_DEF_EXT}\"\n" ) endif() @@ -161,7 +161,7 @@ function(tribits_create_client_template_headers BASE_DIR) # Create the SIERRA BJAM version of the header file foreach(OUTPUT_DIR ${PARSE_ADDITIONAL_OUTPUT_DIRS}) set(EXTERNAL_CLIENT_HEADER_STR "") - append_string_var(EXTERNAL_CLIENT_HEADER_STR + string(APPEND EXTERNAL_CLIENT_HEADER_STR "#include \"${DECL_HEADER_BASE}${${PARENT_PACKAGE_NAME}_TEMPLATE_DECL_EXT}\"\n" "#ifndef HAVE_${PARENT_PACKAGE_NAME_UC}_EXPLICIT_INSTANTIATION\n" "# include \"${DECL_HEADER_BASE}${${PARENT_PACKAGE_NAME}_TEMPLATE_DEF_EXT}\"\n" diff --git a/cmake/tribits/core/package_arch/TribitsExternalPackageFindTplHelpers.cmake b/cmake/tribits/core/package_arch/TribitsExternalPackageFindTplHelpers.cmake new file mode 100644 index 000000000000..019911a89a63 --- /dev/null +++ b/cmake/tribits/core/package_arch/TribitsExternalPackageFindTplHelpers.cmake @@ -0,0 +1,132 @@ +# @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_create_imported_all_libs_target_and_config_file() +# +# Call from a ``FindTPL.cmake`` module that calls inner +# ``find_package()`` for external package that uses modern CMake +# IMPORTED targets. +# +# Usage:: +# +# tribits_extpkg_create_imported_all_libs_target_and_config_file( +# +# 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:: +# +# ${${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. +# +# For more details, see `Creating FindTPL.cmake using find_package() +# with IMPORTED targets`_. +# +function(tribits_extpkg_create_imported_all_libs_target_and_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) + + # Create imported target ::all_libs + add_library(${tplName}::all_libs INTERFACE IMPORTED GLOBAL) + foreach (importedTarget IN LISTS PARSE_IMPORTED_TARGETS_FOR_ALL_LIBS) + target_link_libraries(${tplName}::all_libs INTERFACE ${importedTarget}) + endforeach() + + # Create Config.cmake file + tribits_extpkg_create_package_config_file_with_imported_targets( + ${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" + "set(${externalPkg}_DIR \"${${externalPkg}_DIR}\")\n" + "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() diff --git a/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake b/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake new file mode 100644 index 000000000000..43c740484634 --- /dev/null +++ b/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake @@ -0,0 +1,822 @@ +# @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 + + +include_guard() + +include(TribitsGeneralMacros) +include(TribitsPackageDependencies) + +include(MessageWrapper) + + +# @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. +# +# Usage:: +# +# tribits_write_external_package_config_file( +# ) +# +# The arguments are: +# +# ````: Name of the external package/TPL +# +# ````: Full file path for the ``Config.cmake`` +# file that will be written out. +# +# This function just calls `tribits_extpkg_write_config_file_str()`_ +# and writes that text to the file ```` so see that function +# for more details. +# +function(tribits_extpkg_write_config_file tplName tplConfigFile) + tribits_extpkg_write_config_file_str(${tplName} tplConfigFileStr) + file(WRITE "${tplConfigFile}" "${tplConfigFileStr}") +endfunction() + + +# @FUNCTION: tribits_extpkg_write_config_version_file() +# +# Write out a ``ConfigVersion.cmake`` file. +# +# Usage:: +# +# tribits_write_external_package_config_version_file( +# ) +# +# ToDo: Add version arguments! +# +# The arguments are: +# +# ````: Name of the external package/TPL +# +# ````: Full file path for the +# ``ConfigVersion.cmake`` file that will be written out. +# +function(tribits_extpkg_write_config_version_file tplName tplConfigVersionFile) + set(tplConfigVersionFileStr "") + string(APPEND tplConfigVersionFileStr + "# Package config file for external package/TPL '${tplName}'\n" + "#\n" + "# Generated by CMake, do not edit!\n" + "\n" + "if (TRIBITS_FINDING_RAW_${tplName}_PACKAGE_FIRST)\n" + " set(PACKAGE_VERSION_COMPATIBLE FALSE)\n" + " set(PACKAGE_VERSION_UNSUITABLE TRUE)\n" + "else()\n" + " set(PACKAGE_VERSION_COMPATIBLE TRUE)\n" + "endif()\n" + "\n" + "# Currently there is no version information\n" + "set(PACKAGE_VERSION UNKNOWN)\n" + "set(PACKAGE_VERSION_EXACT FALSE)\n" + ) + file(WRITE "${tplConfigVersionFile}" "${tplConfigVersionFileStr}") +endfunction() + + +# @FUNCTION: tribits_extpkg_install_config_file() +# +# Install an already-generated ``Config.cmake`` file. +# +# Usage:: +# +# tribits_write_external_package_install_config_file( +# ) +# +# The arguments are: +# +# ````: Name of the external package/TPL +# +# ````: Full file path for the ``Config.cmake`` +# file that will be installed into the correct location. +# +function(tribits_extpkg_install_config_file tplName tplConfigFile) + install( + FILES "${tplConfigFile}" + DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}/external_packages/${tplName}" + ) +endfunction() + + +# @FUNCTION: tribits_extpkg_install_config_version_file() +# +# Install an already-generated ``ConfigVersion.cmake`` file. +# +# Usage:: +# +# tribits_write_external_package_install_config_version_file( +# ) +# +# The arguments are: +# +# ````: Name of the external package/TPL +# +# ````: Full file path for the +# ``ConfigVersion.cmake`` file that will be installed into the +# correct location ``${${PROJECT_NAME}_INSTALL_LIB_DIR}/external_packages/`` +# +function(tribits_extpkg_install_config_version_file tplName + tplConfigVersionFile + ) + install( + FILES "${tplConfigVersionFile}" + DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}/external_packages/${tplName}" + ) +endfunction() + + +# @FUNCTION: tribits_extpkg_write_config_file_str() +# +# Create the text string for a ``Config.cmake`` file given the list of +# include directories and libraries for an external package/TPL. +# +# Usage:: +# +# tribits_extpkg_write_config_file_str( +# ) +# +# The function arguments are: +# +# ````: Name of the external package/TPL +# +# ````: Name of variable that will contain the string +# for the config file on output. +# +# This function reads from the (cache) variables +# +# * ``TPL__INCLUDE_DIRS`` +# * ``TPL__LIBRARIES`` +# * ``_LIB_ENABLED_DEPENDENCIES`` +# +# (which must already be set) and uses that information to produce the +# contents of the ``Config.cmake`` which is returned as a string +# variable that contains IMPORTED targets to represent these libraries and +# include directories as well as ``find_dependency()`` calls for upstream +# packages listed in ``_LIB_ENABLED_DEPENDENCIES``. +# +# The arguments in ``TPL__LIBRARIES`` are handled in special ways in +# order to create the namespaced IMPORTED targets ``::`` and +# the ``::all_libs`` target that depends on these. The types of +# arguments that are handled and how the are interpreted: +# +# ``/[lib].`` +# +# Arguments that are absolute file paths are treated as libraries and an +# imported target name ```` is derived from the file name (of the +# form ``lib.`` removing beginning ``lib`` and file +# extension ``.``). The IMPORTED target +# ``::`` is created and the file path is set using the +# ``IMPORTED_LOCATION`` target property. +# +# ``-l`` +# +# Arguments of the form ``-l`` are used to create IMPORTED +# targets with the name ``::`` using the +# ``IMPORTED_LIBNAME`` target property. +# +# ```` +# +# Arguments that are a raw name that matches the regex +# ``^[a-zA-Z_][a-zA-Z0-9_-]*$`` are interpreted to be a library name +# ```` and is used to create an IMPORTED targets +# ``::`` using the ``IMPORTED_LIBNAME`` target property. +# +# ``-L`` +# +# Link directories. These are pulled off and added to the +# ``::all_libs`` using ``target_link_options()``. (The order of +# these options is maintained.) +# +# ``-`` +# +# Any other option that starts with ``-`` is assumed to +# be a link argument where the order does not matter in relation to the +# libraries (but the order of these extra options are maintained w.r.t. each +# other). +# +# ```` +# +# Any other argument that does not match one of the above patterns is +# regarded as an error. +# +# For more details on the handling of individual ``TPL__LIBRARIES`` +# arguments, see `tribits_tpl_libraries_entry_type()`_. +# +# The list of directories given in ``TPL__INCLUDE_DIRS`` is added to +# the ``::all_libs`` target using ``target_include_directories()``. +# +# Finally, for every ```` listed in +# ``_LIB_ENABLED_DEPENDENCIES``, a link dependency is created using +# ``target_link_library(::all_libs INTERFACE )``. +# +function(tribits_extpkg_write_config_file_str tplName tplConfigFileStrOut) + + # A) Set up beginning of config file text + set(configFileStr "") + string(APPEND configFileStr + "# Package config file for external package/TPL '${tplName}'\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" + ) + + # B) Call find_dependency() for all direct dependent upstream TPLs + tribits_extpkg_add_find_upstream_dependencies_str(${tplName} + configFileStr) + + # C) Create IMPORTED library targets from TPL_${tplName}_LIBRARIES + tribits_extpkg_process_libraries_list( + ${tplName} + LIB_TARGETS_LIST_OUT libTargets + LIB_LINK_FLAGS_LIST_OUT libLinkFlags + CONFIG_FILE_STR_INOUT configFileStr + ) + + # D) Create the ::all_libs target + tribits_extpkg_create_all_libs_target( + ${tplName} + LIB_TARGETS_LIST ${libTargets} + LIB_LINK_FLAGS_LIST ${libLinkFlags} + CONFIG_FILE_STR_INOUT configFileStr + ) + + # E) Set the output + set(${tplConfigFileStrOut} "${configFileStr}" PARENT_SCOPE) + +endfunction() + + +# @FUNCTION: tribits_extpkg_add_find_upstream_dependencies_str() +# +# Add code to call find_dependency() for all upstream external packages/TPLs +# listed in ``_LIB_ENABLED_DEPENDENCIES``. +# +# Usage:: +# +# tribits_extpkg_add_find_upstream_dependencies_str(tplName +# configFileFragStrInOut) +# +# NOTE: This also requires that ``_DIR`` be set for each +# external package/TPL listed in ``_LIB_ENABLED_DEPENDENCIES``. +# +function(tribits_extpkg_add_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!") + endif() + string(APPEND configFileFragStr + "set(${upstreamTplDepName}_DIR \"${${upstreamTplDepName}_DIR}\")\n" + "find_dependency(${upstreamTplDepName} REQUIRED CONFIG \${${tplName}_SearchNoOtherPathsArgs})\n" + "unset(${upstreamTplDepName}_DIR)\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 + + +# @FUNCTION: tribits_extpkg_process_libraries_list() +# +# Read the ``TPL__LIBRARIES`` and +# ``_LIB_ENABLED_DEPENDENCIES`` list variables and produce the string +# for the IMPORTED targets commands with upstream linkages and return list of +# targets and left over linker flags. +# +# Usage:: +# +# tribits_extpkg_process_libraries_list( +# +# LIB_TARGETS_LIST_OUT +# LIB_LINK_FLAGS_LIST_OUT +# CONFIG_FILE_STR_INOUT +# ) +# +# The arguments are: +# +# ````: [In] Name of the external package/TPL +# +# ````: [Out] Name of list variable that will be set with +# the list of IMPORTED library targets generated from this list. +# +# ````: [Out] Name of list variable that will be set +# with the list of ``-L`` library directory paths. +# +# ````: [Inout] A string variable that will be +# appended with the IMPORTED library commands for the list of targets given +# in ````. +# +function(tribits_extpkg_process_libraries_list tplName) + + # A) Parse commandline arguments + + cmake_parse_arguments( + PARSE #prefix + "" #options + "LIB_TARGETS_LIST_OUT;LIB_LINK_FLAGS_LIST_OUT;CONFIG_FILE_STR_INOUT" #one_value_keywords + "" #multi_value_keywords + ${ARGN} + ) + tribits_check_for_unparsed_arguments() + + # Capture the initial input string in case the name of the var + # 'configFileStr' is the same in the parent scope. + set(configFileStrInit "${${PARSE_CONFIG_FILE_STR_INOUT}}") + + # B) Create IMPORTED library targets from TPL_${tplName}_LIBRARIES + + set(configFileStr "") + set(libTargets "") + set(lastLibProcessed "") + + # 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. + + set(libLinkFlagsList "") # Will be filled in reverse order below + + set(reverseLibraries ${TPL_${tplName}_LIBRARIES}) + list(REVERSE reverseLibraries) + + foreach (libentry IN LISTS reverseLibraries) + #print_var(libentry) + tribits_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") + elseif (libEntryType STREQUAL "LIB_DIR_LINK_OPTION") + list(APPEND libLinkFlagsList "${libentry}") + elseif (libEntryType STREQUAL "GENERAL_LINK_OPTION") + message_wrapper("-- NOTE: Moving the general link argument '${libentry}' in TPL_${tplName}_LIBRARIES forward on the link line which may change the link and break the link!") + list(APPEND libLinkFlagsList "${libentry}") + else() + tribits_extpkg_process_libraries_list_library_entry( + ${tplName} "${libentry}" ${libEntryType} libTargets lastLibProcessed + configFileStr ) + endif() + endforeach() + + list(REVERSE libLinkFlagsList) # Put back in original order + + # C) Set output arguments: + set(${PARSE_LIB_TARGETS_LIST_OUT} "${libTargets}" PARENT_SCOPE) + set(${PARSE_LIB_LINK_FLAGS_LIST_OUT} "${libLinkFlagsList}" PARENT_SCOPE) + set(${PARSE_CONFIG_FILE_STR_INOUT} "${configFileStrInit}${configFileStr}" + PARENT_SCOPE) + +endfunction() + + +# @FUNCTION: tribits_tpl_libraries_entry_type() +# +# Returns the type of the library entry in the list TPL__LIBRARIES +# +# Usage:: +# +# tribits_tpl_libraries_entry_type( ) +# +# Arguments: +# +# ```` [in]: Element of ``TPL__LIBRARIES`` +# +# ```` [out]: Variable set on output to the type of entry. +# +# The types of entries set on ``libEntryTypeOut`` include: +# +# * ``FULL_LIB_PATH``: A full library path +# +# * ``LIB_NAME_LINK_OPTION``: A library name link option of the form +# ``-l`` +# +# * ``LIB_NAME``: A library name of the form ```` +# +# * ``LIB_DIR_LINK_OPTION``: A library directory search option of the form +# ``-L`` +# +# * ``GENERAL_LINK_OPTION``: Some other general link option that starts with +# ``-`` but is not ``-l`` or ``-L``. +# +# * ``UNSUPPORTED_LIB_ENTRY``: An unsupported lib option +# +function(tribits_tpl_libraries_entry_type libentry libEntryTypeOut) + string(SUBSTRING "${libentry}" 0 1 firstCharLibEntry) + string(SUBSTRING "${libentry}" 0 2 firstTwoCharsLibEntry) + if (firstTwoCharsLibEntry STREQUAL "-l") + set(libEntryType LIB_NAME_LINK_OPTION) + elseif (firstTwoCharsLibEntry STREQUAL "-L") + set(libEntryType LIB_DIR_LINK_OPTION) + elseif (firstCharLibEntry STREQUAL "-") + set(libEntryType GENERAL_LINK_OPTION) + elseif (IS_ABSOLUTE "${libentry}") + set(libEntryType FULL_LIB_PATH) + elseif (libentry MATCHES "^[a-zA-Z_][a-zA-Z0-9_-]*$") + set(libEntryType LIB_NAME) + else() + set(libEntryType UNSUPPORTED_LIB_ENTRY) + endif() + set(${libEntryTypeOut} ${libEntryType} PARENT_SCOPE) +endfunction() +# NOTE: Above, if libentry is only 1 char long, then firstTwoCharsLibEntry is +# also 1 char long and the above logic still works. + + +# Function to process a library inside of loop over +# ``TPL__LIBRARIES`` in the function +# tribits_extpkg_process_libraries_list(). +# +# This also puts in linkages to upstream TPLs ``::all_libs`` listed +# in ``_LIB_ENABLED_DEPENDENCIES``. +# +function(tribits_extpkg_process_libraries_list_library_entry + tplName libentry libEntryType + libTargetsInOut lastLibProcessedInOut configFileStrInOut + ) + # Set local vars for inout vars + set(libTargets ${${libTargetsInOut}}) + set(lastLibProcessed ${${lastLibProcessedInOut}}) + set(configFileStr ${${configFileStrInOut}}) + # Get libname + tribits_extpkg_get_libname_and_path_from_libentry( + "${libentry}" ${libEntryType} libname libpath) + # Create IMPORTED library target + set(prefixed_libname "${tplName}::${libname}") + if (NOT (prefixed_libname IN_LIST libTargets)) + tribits_extpkg_append_add_library_str (${libname} ${prefixed_libname} + ${libEntryType} "${libpath}" configFileStr) + if (lastLibProcessed) + string(APPEND configFileStr + "target_link_libraries(${prefixed_libname}\n" + " INTERFACE ${tplName}::${lastLibProcessed})\n" + ) + else() + tribits_extpkg_append_upstream_target_link_libraries_str( ${tplName} + ${prefixed_libname} configFileStr ) + endif() + string(APPEND configFileStr + "\n") + # Update for next loop + set(lastLibProcessed ${libname}) + list(APPEND libTargets ${prefixed_libname}) + endif() + # Set output vars + set(${libTargetsInOut} ${libTargets} PARENT_SCOPE) + set(${lastLibProcessedInOut} ${lastLibProcessed} PARENT_SCOPE) + set(${configFileStrInOut} ${configFileStr} PARENT_SCOPE) +endfunction() +# NOTE: Above, we only need to link the first library :: +# against the upstream TPL libraries ::all_libs. The other +# imported targets :: for this TPL are linked to this first +# :: which has the needed dependencies. + + +function(tribits_extpkg_get_libname_and_path_from_libentry + libentry libEntryType libnameOut libpathOut + ) + if (libEntryType STREQUAL "FULL_LIB_PATH") + tribits_extpkg_get_libname_from_full_lib_path("${libentry}" libname) + set(libpath "${libentry}") + elseif (libEntryType STREQUAL "LIB_NAME_LINK_OPTION") + tribits_extpkg_get_libname_from_lib_name_link_option("${libentry}" libname) + set(libpath "") + elseif (libEntryType STREQUAL "LIB_NAME") + set(libname "${libentry}") + set(libpath "") + else() + message(FATAL_ERROR "Error libEntryType='${libEntryType}' not supported here!") + endif() + set(${libnameOut} ${libname} PARENT_SCOPE) + set(${libpathOut} ${libpath} PARENT_SCOPE) +endfunction() + + +function(tribits_extpkg_append_add_library_str + libname prefix_libname libEntryType libpath + configFileStrInOut + ) + set(configFileStr "${${configFileStrInOut}}") + if (libEntryType STREQUAL "FULL_LIB_PATH") + string(APPEND configFileStr + "add_library(${prefixed_libname} IMPORTED UNKNOWN GLOBAL)\n" + "set_target_properties(${prefixed_libname} PROPERTIES\n" + " IMPORTED_LOCATION \"${libpath}\")\n" + ) + elseif ( + (libEntryType STREQUAL "LIB_NAME_LINK_OPTION") + OR (libEntryType STREQUAL "LIB_NAME") + ) + string(APPEND configFileStr + "add_library(${prefixed_libname} IMPORTED INTERFACE GLOBAL)\n" + "set_target_properties(${prefixed_libname} PROPERTIES\n" + " IMPORTED_LIBNAME \"${libname}\")\n" + ) + else() + message(FATAL_ERROR "Error libEntryType='${libEntryType}' not supported here!") + endif() + set(${configFileStrInOut} "${configFileStr}" PARENT_SCOPE) +endfunction() + + +function(tribits_extpkg_get_libname_from_full_lib_path full_lib_path + libnameOut + ) + # Should be an absolute library path + get_filename_component(full_libname "${full_lib_path}" NAME_WE) + # Begins with 'lib'? + tribits_extpkg_libname_begins_with_lib("${full_libname}" beginsWithLib) + # Assert is a valid lib name and get lib name + set(libname "") + string(LENGTH "${full_libname}" full_libname_len) + if (full_libname_len LESS 0) + tribits_print_invalid_lib_name(${tplName} "${full_lib_path}") + endif() + if (WIN32) + # Native windows compilers does not prepend library names with 'lib' + set(libname "${full_libname}") + elseif (APPLE) + # On MacOSX, CMake allows using frameworks that *don't* begin with 'lib' + # so we have to allow for that + if (beginsWithLib) + string(SUBSTRING "${full_libname}" 3 -1 libname) + else() + # Must be a framework dir with extension .framework + get_filename_component(last_ext "${full_lib_path}" LAST_EXT) + if (last_ext STREQUAL ".framework") + set(libname "${full_libname}") + else() + tribits_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}") + else() + string(SUBSTRING "${full_libname}" 3 -1 libname) + endif() + endif() + # Set output + set(${libnameOut} ${libname} PARENT_SCOPE) +endfunction() + + +function(tribits_extpkg_libname_begins_with_lib full_libname + libnameBeginsWithLibOut + ) + string(SUBSTRING "${full_libname}" 0 3 libPart) + if (libPart STREQUAL "lib") + set(libnameBeginsWithLib TRUE) + else() + set(libnameBeginsWithLib FALSE) + endif() + set(${libnameBeginsWithLibOut} ${libnameBeginsWithLib} PARENT_SCOPE) +endfunction() + + +function(tribits_extpkg_get_libname_from_lib_name_link_option + lib_name_link_option libnameOut + ) + # 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}") + endif() + # Get from -l + string(SUBSTRING "${lib_name_link_option}" 2 -1 libname) + # Set output + set(${libnameOut} ${libname} PARENT_SCOPE) +endfunction() + + +function(tribits_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) + 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 + tplName prefix_libname configFileStrInOut + ) + set(configFileStr "${${configFileStrInOut}}") + if (${tplName}_LIB_ENABLED_DEPENDENCIES) + string(APPEND configFileStr + "target_link_libraries(${prefix_libname}\n") + foreach (upstreamTplDepEntry IN LISTS ${tplName}_LIB_ENABLED_DEPENDENCIES) + tribits_extpkg_get_dep_name_and_vis( + "${upstreamTplDepEntry}" upstreamTplDepName upstreamTplDepVis) + if (upstreamTplDepVis STREQUAL "PUBLIC") + string(APPEND configFileStr + " INTERFACE ${upstreamTplDepName}::all_libs # i.e. PUBLIC\n") + elseif(upstreamTplDepVis STREQUAL "PRIVATE") + string(APPEND configFileStr + " INTERFACE $ # i.e. PRIVATE\n") + else() + message(FATAL_ERROR "ERROR: Invalid visibility in entry '${upstreamTplDepEntry}'") + endif() + endforeach() + string(APPEND configFileStr + " )\n") + endif() + set(${configFileStrInOut} "${configFileStr}" PARENT_SCOPE) +endfunction() +# +# NOTE: Above, the syntax for a private dependency is: +# +# INTERFACE $ +# +# This has the effect of not bringing along the INTERFACE_INCLUDE_DIRECTORIES +# for upstreamLib so the include dirs for upstreamLib will not be listed on +# the compile lines of downstream object builds. But it will result in the +# libraries being listed on link lines for downstsream library and exec links. + + +# @FUNCTION: tribits_extpkg_create_all_libs_target() +# +# Creates the ``::all_libs`` target command text using input info and +# from ``TPL__INCLUDE_DIRS``. +# +# Usage:: +# +# tribits_extpkg_create_all_libs_target( +# +# LIB_TARGETS_LIST +# LIB_LINK_FLAGS_LIST +# CONFIG_FILE_STR_INOUT +# ) +# +# The arguments are: +# +# ````: [in] Name of the external package/TPL +# +# ````: [in] List of targets created from processing +# ``TPL__LIBRARIES``. +# +# ````: [in] List of of ``-L`` library directory +# paths entries found while processing ``TPL__LIBRARIES``. +# +# ````: [out] A string variable that will be +# appended with the ``::all_libs`` target statements. +# +function(tribits_extpkg_create_all_libs_target tplName) + + # Parse commandline arguments + + cmake_parse_arguments( + PARSE #prefix + "" #options + "CONFIG_FILE_STR_INOUT" #one_value_keywords + "LIB_TARGETS_LIST;LIB_LINK_FLAGS_LIST" #multi_value_keywords + ${ARGN} + ) + tribits_check_for_unparsed_arguments() + + # Set short-hand local vars + set(libTarget "${PARSE_LIB_TARGETS_LIST}") + set(libLinkFlags "${PARSE_LIB_LINK_FLAGS_LIST}") + + # Capture the initial input string in case the name of the var + # 'configFileStr' is the same in the parent scope. + set(configFileStrInit "${${PARSE_CONFIG_FILE_STR_INOUT}}") + + set(configFileStr "") + + # add_library() + string(APPEND configFileStr + "add_library(${tplName}::all_libs INTERFACE IMPORTED GLOBAL)\n") + # target_link_libraries() + if (libTargets) + string(APPEND configFileStr + "target_link_libraries(${tplName}::all_libs\n") + foreach (libTarget IN LISTS libTargets) + string(APPEND configFileStr + " INTERFACE ${libTarget}\n") + endforeach() + string(APPEND configFileStr + " )\n") + endif() + # target_include_directories() + if (TPL_${tplName}_INCLUDE_DIRS) + string(APPEND configFileStr + "target_include_directories(${tplName}::all_libs SYSTEM\n") + foreach (inclDir IN LISTS TPL_${tplName}_INCLUDE_DIRS) + string(APPEND configFileStr + " INTERFACE \"${inclDir}\"\n") + endforeach() + string(APPEND configFileStr + " )\n") + endif() + # target_link_options() + if (libLinkFlags) + string(APPEND configFileStr + "target_link_options(${tplName}::all_libs\n") + foreach (likLinkFlag IN LISTS libLinkFlags) + string(APPEND configFileStr + " INTERFACE \"${likLinkFlag}\"\n") + endforeach() + string(APPEND configFileStr + " )\n") + endif() + # Add trailing newline + string(APPEND configFileStr + "\n") + + # C) Set output arguments + set(${PARSE_CONFIG_FILE_STR_INOUT} "${configFileStrInit}${configFileStr}" + PARENT_SCOPE) + +endfunction() + diff --git a/cmake/tribits/core/package_arch/TribitsFindMostRecentFileTimestamp.cmake b/cmake/tribits/core/package_arch/TribitsFindMostRecentFileTimestamp.cmake index be6881ab1623..c6f70cef0664 100644 --- a/cmake/tribits/core/package_arch/TribitsFindMostRecentFileTimestamp.cmake +++ b/cmake/tribits/core/package_arch/TribitsFindMostRecentFileTimestamp.cmake @@ -40,7 +40,6 @@ include(CMakeParseArguments) -# # @FUNCTION: tribits_find_most_recent_file_timestamp() # # Find the most modified file in a set of base directories and return its @@ -294,7 +293,6 @@ function(tribits_find_most_recent_file_timestamp) endfunction() -# # @FUNCTION: tribits_find_most_recent_source_file_timestamp() # # Find the most modified source file in a set of base directories and return @@ -381,7 +379,6 @@ function(tribits_find_most_recent_source_file_timestamp) endfunction() -# # @FUNCTION: tribits_find_most_recent_binary_file_timestamp() # # Find the most modified binary file in a set of base directories and return @@ -471,7 +468,6 @@ function(tribits_find_most_recent_binary_file_timestamp) endfunction() -# # @FUNCTION: tribits_determine_if_current_package_needs_rebuilt() # # Determine at configure time if any of the upstream dependencies for a diff --git a/cmake/tribits/core/package_arch/TribitsGeneralMacros.cmake b/cmake/tribits/core/package_arch/TribitsGeneralMacros.cmake index 3c83d5d108c9..cf2a680cb2b5 100644 --- a/cmake/tribits/core/package_arch/TribitsGeneralMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsGeneralMacros.cmake @@ -40,6 +40,7 @@ include(AppendSet) include(AssertDefined) include(MessageWrapper) +include(TribitsParseArgumentsHelpers) include(TribitsSortListAccordingToMasterList) @@ -372,151 +373,23 @@ function( tribits_gather_enabled_items PACKAGE_NAME LISTTYPE_PREFIX endfunction() -# Function that appends the Package/TPL include and library paths for given -# list of enabled Packages/TPLs +# @FUNCTION: tribits_trace_file_processing() # -# As a side effect of calling this function, include_directories(...) to set -# all of the include directories for a given set of enabled Packages/TPLs. +# Print trace of file processing when +# ``${PROJECT_NAME}_TRACE_FILE_PROCESSING`` is ``TRUE``. # -# NOTE: The Packages/TPLs should be sorted in descending dependency order -# before calling this function. +# Usage:: # -# NOTE: Because this function may be called in cases where a package's -# required subpackages are not actually enabled (e.g. SEACAS subpackages) +# tribits_trace_file_processing( ) # -function( tribits_append_include_and_link_dirs TPL_OR_PACKAGE PREFIX - LIST EXTRA_DEP_LIBS_INOUT - ) - if (TRIBITS_APPEND_INCLUDE_AND_LINK_DIRS_DEBUG_DUMP) - message("\nTRIBITS_APPEND_INCLUDE_AND_LINK_DIRS: '${TPL_OR_PACKAGE}'" - " '${PREFIX}' '${LIST}' '${EXTRA_DEP_LIBS_INOUT}'") - endif() - set(EXTRA_DEP_LIBS_INOUT_TMP ${${EXTRA_DEP_LIBS_INOUT}}) - cmake_policy(SET CMP0054 NEW) - if ( - "${TPL_OR_PACKAGE}" STREQUAL "TPL" - AND - ( - ${PROJECT_NAME}_TPL_SYSTEM_INCLUDE_DIRS - AND NOT - (${PARENT_PACKAGE_NAME}_SKIP_TPL_SYSTEM_INCLUDE_DIRS - OR ${PACKAGE_NAME}_SKIP_TPL_SYSTEM_INCLUDE_DIRS) - ) - ) - set(SYSTEM_ARG "SYSTEM") - else() - set(SYSTEM_ARG) - endif() - foreach(ITEM ${LIST}) - if (${PREFIX}${ITEM}_LIBRARIES) - append_set(EXTRA_DEP_LIBS_ARG_TMP ${${PREFIX}${ITEM}_LIBRARIES}) - endif() - if (${PREFIX}${ITEM}_INCLUDE_DIRS) - if (TRIBITS_APPEND_INCLUDE_AND_LINK_DIRS_DEBUG_DUMP) - message("-- " "include_directories(${SYSTEM_ARG} ${${PREFIX}${ITEM}_INCLUDE_DIRS})") - endif() - include_directories(${SYSTEM_ARG} ${${PREFIX}${ITEM}_INCLUDE_DIRS}) - endif() - if (${PREFIX}${ITEM}_LIBRARY_DIRS) - if (PREFIX) - # TODO: Is there a better way to know if we need this? - # We want LINK_DIRECTORIES for TPLs but not packages. - link_directories(${${PREFIX}${ITEM}_LIBRARY_DIRS}) - endif() - set_property(DIRECTORY APPEND PROPERTY PACKAGE_LIBRARY_DIRS - ${${PREFIX}${ITEM}_LIBRARY_DIRS}) - endif() - if (TRIBITS_APPEND_INCLUDE_AND_LINK_DIRS_DEBUG_DUMP) - print_var(${PREFIX}${ITEM}_LIBRARIES) - print_var(${PREFIX}${ITEM}_INCLUDE_DIRS) - print_var(${PREFIX}${ITEM}_LIBRARY_DIRS) - endif() - endforeach() - set(${EXTRA_DEP_LIBS_INOUT} ${EXTRA_DEP_LIBS_ARG_TMP} PARENT_SCOPE) -endfunction() - - -# Function that sorts and appends all the items in a dependency list for -# packages or TPLs. +# Arguments: # -function( tribits_sort_and_append_include_and_link_dirs_and_libs - TPL_OR_PACKAGE MASTER_SORT_LIST LIST PREFIX - EXTRA_DEP_LIBS_INOUT - ) - - if (TRIBITS_SORT_AND_APPEND_INCLUDE_AND_LINK_DIRS_AND_LIBS_DEBUG_DUMP) - message("TRIBITS_SORT_AND_APPEND_INCLUDE_AND_LINK_DIRS_AND_LIBS:") - print_var(MASTER_SORT_LIST) - print_var(LIST) - print_var(PREFIX) - print_var(EXTRA_DEP_LIBS_INOUT) - endif() - - set(LOCAL_LIST ${LIST}) - if (TRIBITS_SORT_AND_APPEND_INCLUDE_AND_LINK_DIRS_AND_LIBS_DEBUG_DUMP) - print_var(LOCAL_LIST) - endif() - - if (LOCAL_LIST) - - tribits_sort_list_according_to_master_list("${MASTER_SORT_LIST}" LOCAL_LIST) - if (TRIBITS_SORT_AND_APPEND_INCLUDE_AND_LINK_DIRS_AND_LIBS_DEBUG_DUMP) - print_var(LOCAL_LIST) - endif() - - set(EXTRA_DEP_LIBS_ARG_TMP ${${EXTRA_DEP_LIBS_INOUT}}) - tribits_append_include_and_link_dirs("${TPL_OR_PACKAGE}" "${PREFIX}" - "${LOCAL_LIST}" EXTRA_DEP_LIBS_ARG_TMP) - set(${EXTRA_DEP_LIBS_INOUT} ${EXTRA_DEP_LIBS_ARG_TMP} PARENT_SCOPE) - - endif() - -endfunction() - - -# Fully process the include and link directories and list of libraries for a -# package's list of dependent packages for use in creating a library or an -# executable +# * ````: Allowed values "PROJECT", "REPOSITORY", "PACKAGE", or "TPL" # -function( tribits_sort_and_append_package_include_and_link_dirs_and_libs - PACKAGE_NAME LIB_OR_TEST_ARG EXTRA_DEP_LIBS_INOUT - ) - - tribits_gather_enabled_items(${PACKAGE_NAME} ${LIB_OR_TEST_ARG} - PACKAGES ALL_DEP_PACKAGES) - - set(EXTRA_DEP_LIBS_TMP ${${EXTRA_DEP_LIBS_INOUT}}) - tribits_sort_and_append_include_and_link_dirs_and_libs( - "PACKAGE" - "${${PROJECT_NAME}_REVERSE_ENABLED_SE_PACKAGES}" - "${ALL_DEP_PACKAGES}" "" EXTRA_DEP_LIBS_TMP) - set(${EXTRA_DEP_LIBS_INOUT} ${EXTRA_DEP_LIBS_TMP} PARENT_SCOPE) - -endfunction() - - -# Fully process the include and link directories and list of libraries for a -# package's list of dependent TPLs for use in creating a library or an -# executable +# * ````: Allowed values "INCLUDE", "ADD_SUBDIR", "READ", or +# "CONFIGURE" # -function( tribits_sort_and_append_tpl_include_and_link_dirs_and_libs - PACKAGE_NAME LIB_OR_TEST_ARG EXTRA_DEP_LIBS_INOUT - ) - - tribits_gather_enabled_items(${PACKAGE_NAME} ${LIB_OR_TEST_ARG} - TPLS ALL_TPLS) - - set(EXTRA_DEP_LIBS_TMP ${${EXTRA_DEP_LIBS_INOUT}}) - tribits_sort_and_append_include_and_link_dirs_and_libs( - "TPL" - "${${PROJECT_NAME}_REVERSE_ENABLED_TPLS}" - "${ALL_TPLS}" TPL_ EXTRA_DEP_LIBS_TMP) - set(${EXTRA_DEP_LIBS_INOUT} ${EXTRA_DEP_LIBS_TMP} PARENT_SCOPE) - -endfunction() - - -# Print trace of file processing +# * ````: Path of the file being processed # function(tribits_trace_file_processing TYPE_IN PROCESSING_TYPE_IN FILE_PATH) @@ -553,48 +426,3 @@ function(tribits_trace_file_processing TYPE_IN PROCESSING_TYPE_IN FILE_PATH) endif() endfunction() - - -# Check to see if there are unparsed arguments after calling CMAKE_PARSE_ARGUMENTS -# -macro(tribits_check_for_unparsed_arguments) - - if( NOT "${PARSE_UNPARSED_ARGUMENTS}" STREQUAL "") - message( - ${${PROJECT_NAME}_CHECK_FOR_UNPARSED_ARGUMENTS} - "Arguments are being passed in but not used. UNPARSED_ARGUMENTS =" - " ${PARSE_UNPARSED_ARGUMENTS}" - ) - endif() - -endmacro() - - -# Check that a parase argument has at least one value -# -macro(tribits_assert_parse_arg_one_or_more_values PREFIX ARGNAME) - set(PREFIX_ARGNAME "${PREFIX}_${ARGNAME}") - list( LENGTH ${PREFIX_ARGNAME} ARG_NUM_VALS ) - if (ARG_NUM_VALS LESS 1) - message_wrapper(FATAL_ERROR - "ERROR: ${ARGNAME} must have at least one value!" ) - return() - # NOTE: The return is needed in unit testing mode - endif() -endmacro() - - -# Check that a parase argument has zero or one value -# -macro(tribits_assert_parse_arg_zero_or_one_value PREFIX ARGNAME) - set(PREFIX_ARGNAME "${PREFIX}_${ARGNAME}") - if (NOT "${${PREFIX_ARGNAME}}" STREQUAL "") - list( LENGTH ${PREFIX_ARGNAME} ARG_NUM_VALS ) - if (ARG_NUM_VALS GREATER 1) - message_wrapper(FATAL_ERROR - "ERROR: ${ARGNAME}='${${PREFIX_ARGNAME}}' can not have more than one value!" ) - return() - # NOTE: The return is needed in unit testing mode - endif() - endif() -endmacro() diff --git a/cmake/tribits/core/package_arch/TribitsGetVersionDate.cmake b/cmake/tribits/core/package_arch/TribitsGetVersionDate.cmake index 32a40b3eadf3..aa09836d628f 100644 --- a/cmake/tribits/core/package_arch/TribitsGetVersionDate.cmake +++ b/cmake/tribits/core/package_arch/TribitsGetVersionDate.cmake @@ -2,7 +2,6 @@ include("${${PROJECT_NAME}_TRIBITS_DIR}/core/utils/MessageWrapper.cmake") include("${${PROJECT_NAME}_TRIBITS_DIR}/core/utils/TribitsStripQuotesFromStr.cmake") -# # @FUNCTION: tribits_get_raw_git_commit_utc_time() # # Get the git commit date of a repo at a given commit in UTC in the format @@ -58,7 +57,6 @@ function(tribits_get_raw_git_commit_utc_time repo_base_dir commit_ref endfunction() -# # @FUNCTION: tribits_get_version_date_from_raw_git_commit_utc_time() # # Takes input of the form "YYYY-MM-DD hh:mm:ss +0000" from the git command:: diff --git a/cmake/tribits/core/package_arch/TribitsGitRepoVersionInfo.cmake b/cmake/tribits/core/package_arch/TribitsGitRepoVersionInfo.cmake new file mode 100644 index 000000000000..1b345ec0a2ac --- /dev/null +++ b/cmake/tribits/core/package_arch/TribitsGitRepoVersionInfo.cmake @@ -0,0 +1,164 @@ +# @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 containing functions for getting Git repo information +# +################################################################################ + + +# @FUNCTION: tribits_git_repo_sha1() +# +# Get the Git repo version SHA1. +# +# Usage:: +# +# tribits_git_repo_sha1( +# FAILURE_MESSAGE_OUT ) +# +# If ```` is non-empty on input, then the variable +# ```` will be set to a non-empty value on output with the +# error message if an error occurs and the SHA1 for ```` can not +# be computed. If ```` is empty in input, and there is an +# error, a ``FATAL_ERROR`` will be raised. +# +# NOTE: To get the SHA1 for the Git repo ````, it must contain the +# ``.git/`` directory and the ``git`` executable var ``GIT_EXECUTABLE`` must +# be set. Otherwise, it is an error. +# +function(tribits_git_repo_sha1 gitRepoDir gitRepoSha1Out) + + cmake_parse_arguments( PARSE_ARGV 2 + PARSE "" "" # prefix, options, one_value_keywords + "FAILURE_MESSAGE_OUT" # multi_value_keywords + ) + tribits_check_for_unparsed_arguments() + tribits_assert_parse_arg_zero_or_one_value(PARSE FAILURE_MESSAGE_OUT) + + set(failureMsg "") + + if (NOT GIT_EXECUTABLE) + set(failureMsg "ERROR: The program '${GIT_NAME}' could not be found!") + elseif (NOT IS_DIRECTORY "${gitRepoDir}/.git") + set(failureMsg "ERROR: The directory ${gitRepoDir}/.git does not exist!") + endif() + + set(gitRepoSha1 "") + if (failureMsg STREQUAL "") + execute_process( + COMMAND ${GIT_EXECUTABLE} log -1 "--pretty=format:%H" + WORKING_DIRECTORY ${gitRepoDir} + RESULT_VARIABLE gitCmndRtn OUTPUT_VARIABLE gitCmndOutput + ) + + if (NOT gitCmndRtn STREQUAL 0) + set(failureMsg "ERROR: ${GIT_EXECUTABLE} command returned ${gitCmndRtn}!=0 for repo ${gitRepoDir}!") + else() + set(gitRepoSha1 "${gitCmndOutput}") + endif() + endif() + + if (NOT failureMsg STREQUAL "" AND PARSE_FAILURE_MESSAGE_OUT STREQUAL "") + message(FATAL_ERROR "${failureMsg}") + elseif (PARSE_FAILURE_MESSAGE_OUT) + set(${PARSE_FAILURE_MESSAGE_OUT} "${failureMsg}" PARENT_SCOPE) + endif() + set(${gitRepoSha1Out} "${gitRepoSha1}" PARENT_SCOPE) + +endfunction() + + +# Run the git log command to get the version info for a git repo +# +function(tribits_generate_single_repo_version_string gitRepoDir + repoVersionStringOut + ) + + tribits_assert_git_executable() + + # A) Get the basic version info. + + execute_process( + COMMAND ${GIT_EXECUTABLE} log -1 "--pretty=format:%h [%ad] <%ae>" + WORKING_DIRECTORY ${gitRepoDir} + RESULT_VARIABLE gitCmndRtn + OUTPUT_VARIABLE gitCmndOutput + ) + + if (NOT gitCmndRtn STREQUAL 0) + message(FATAL_ERROR "ERROR, ${GIT_EXECUTABLE} command returned ${gitCmndRtn}!=0" + " for repo ${gitRepoDir}!") + set(gitVersionLine "Error, could not get version info!") + else() + set(gitVersionLine "${gitCmndOutput}") + endif() + + # B) Get the first 80 chars of the summary message for more info + + execute_process( + COMMAND ${GIT_EXECUTABLE} log -1 --pretty=format:%s + WORKING_DIRECTORY ${gitRepoDir} + RESULT_VARIABLE gitCmndRtn + OUTPUT_VARIABLE gitCmndOutput + ) + + if (NOT gitCmndRtn STREQUAL 0) + message(FATAL_ERROR "ERROR, ${GIT_EXECUTABLE} command returned ${gitCmndRtn}!=0" + " for extra repo ${gitRepoDir}!") + set(gitSummaryStr "Error, could not get version summary!") + else() + set(maxSummaryLen 80) + string(SUBSTRING "${gitCmndOutput}" 0 ${maxSummaryLen} gitSummaryStr) + endif() + + set(${repoVersionStringOut} + "${gitVersionLine}\n${gitSummaryStr}" PARENT_SCOPE) + +endfunction() +# NOTE: Above, it is fine if ${maxSummaryLen} > len(${gitCmndOutput}) as +# string(SUBSTRING ...) will just shorten this to the length of the string. + + +function(tribits_assert_git_executable) + if (NOT GIT_EXECUTABLE) + message(SEND_ERROR "ERROR, the program '${GIT_NAME}' could not be found!" + " We can not generate the repo version file!") + endif() +endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake b/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake index 567ce40546da..ca763c91480b 100644 --- a/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake @@ -50,6 +50,7 @@ include(TribitsGetVersionDate) include(TribitsReportInvalidTribitsUsage) include(TribitsReadAllProjectDepsFilesCreateDepsGraph) include(TribitsAdjustPackageEnables) +include(TribitsGitRepoVersionInfo) # Standard TriBITS utilities includes include(TribitsAddOptionAndDefine) @@ -84,7 +85,7 @@ include(TribitsTplDeclareLibraries) # Deprecated # macro(tribits_assert_and_setup_project_and_static_system_vars) - append_string_var(IN_SOURCE_ERROR_COMMON_MSG + string(APPEND IN_SOURCE_ERROR_COMMON_MSG "\nYou must now run something like:\n" " $ cd ${CMAKE_CURRENT_SOURCE_DIR}/\n" " $ rm -r CMakeCache.txt CMakeFiles/" @@ -291,7 +292,11 @@ macro(tribits_define_global_options_and_define_extra_repos) set(${PROJECT_NAME}_ENABLE_CXX11 ON) if ("${${PROJECT_NAME}_ENABLE_Fortran_DEFAULT}" STREQUAL "") - set(${PROJECT_NAME}_ENABLE_Fortran_DEFAULT ON) + if (WIN32) + set(${PROJECT_NAME}_ENABLE_Fortran_DEFAULT OFF) + else() + set(${PROJECT_NAME}_ENABLE_Fortran_DEFAULT ON) + endif() endif() option(${PROJECT_NAME}_ENABLE_Fortran @@ -531,6 +536,18 @@ macro(tribits_define_global_options_and_define_extra_repos) CACHE BOOL "If set TRUE, then 'SYSTEM' will be passed into include_directories() for TPL includes.") + if ("${${PROJECT_NAME}_IMPORTED_NO_SYSTEM_DEFAULT}" STREQUAL "") + set(${PROJECT_NAME}_IMPORTED_NO_SYSTEM_DEFAULT FALSE) + endif() + advanced_set(${PROJECT_NAME}_IMPORTED_NO_SYSTEM + ${${PROJECT_NAME}_IMPORTED_NO_SYSTEM_DEFAULT} + CACHE BOOL + "If set TRUE, then set IMPORTED_NO_SYSTEM property on all exported libraries.") + + if (CMAKE_VERSION VERSION_LESS 3.23 AND ${PROJECT_NAME}_IMPORTED_NO_SYSTEM) + message(FATAL_ERROR "Error, setting ${PROJECT_NAME}_IMPORTED_NO_SYSTEM='${${PROJECT_NAME}_IMPORTED_NO_SYSTEM}' for CMake version '${CMAKE_VERSION}' < 3.23 is not allowed!") + endif() + advanced_set(TPL_FIND_SHARED_LIBS ON CACHE BOOL "If ON, then the TPL system will find shared libs if they exist, otherwise will only find static libs." ) @@ -572,20 +589,6 @@ macro(tribits_define_global_options_and_define_extra_repos) "Install libraries and headers (default is ${${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS_DEFAULT}). NOTE: Shared libraries are always installed since they are needed by executables." ) - if ("${${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES_DEFAULT}" STREQUAL "") - if(WIN32 AND NOT CYGWIN) - set(${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES_DEFAULT OFF) - else() - set(${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES_DEFAULT ON) - endif() - endif() - - advanced_set(${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES - ${${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES_DEFAULT} - CACHE BOOL - "Determines if export makefiles will be created and installed." - ) - # Creating Config.cmake files is currently *very* expensive for large # TriBITS projects so we disable this by default for TriBITS. if ("${${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES_DEFAULT}" STREQUAL "") @@ -601,9 +604,7 @@ macro(tribits_define_global_options_and_define_extra_repos) if (NOT ${PROJECT_NAME}_GENERATE_EXPORT_FILE_DEPENDENCIES_DEFAULT) # We need to generate the dependency logic for export dependency files if # asked. - if (${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES OR - ${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES - ) + if (${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES) set(${PROJECT_NAME}_GENERATE_EXPORT_FILE_DEPENDENCIES_DEFAULT ON) else() set(${PROJECT_NAME}_GENERATE_EXPORT_FILE_DEPENDENCIES_DEFAULT OFF) @@ -665,7 +666,9 @@ macro(tribits_define_global_options_and_define_extra_repos) ) tribits_get_invalid_categories(${PROJECT_NAME}_TEST_CATEGORIES) - if ("${${PROJECT_NAME}_GENERATE_REPO_VERSION_FILE_DEFAULT}" STREQUAL "" ) + if (NOT GIT_EXECUTABLE) + set(${PROJECT_NAME}_GENERATE_REPO_VERSION_FILE_DEFAULT OFF) + elseif ("${${PROJECT_NAME}_GENERATE_REPO_VERSION_FILE_DEFAULT}" STREQUAL "" ) set(${PROJECT_NAME}_GENERATE_REPO_VERSION_FILE_DEFAULT OFF) endif() advanced_set( @@ -1249,75 +1252,6 @@ macro(tribits_copy_installer_resource _varname _source _destination) COPYONLY) endmacro() -# Run the git log command to get the version info for a git repo -# -function(tribits_generate_single_repo_version_string GIT_REPO_DIR - SINGLE_REPO_VERSION_STRING_OUT - ) - - if (NOT GIT_EXECUTABLE) - message(SEND_ERROR "ERROR, the program '${GIT_NAME}' could not be found!" - " We can not generate the repo version file!") - endif() - - # A) Get the basic version info. - - execute_process( - COMMAND ${GIT_EXECUTABLE} log -1 --pretty=format:"%h [%ad] <%ae>" - WORKING_DIRECTORY ${GIT_REPO_DIR} - RESULT_VARIABLE GIT_RETURN - OUTPUT_VARIABLE GIT_OUTPUT - ) - # NOTE: Above we have to add quotes '"' or CMake will not accept the - # command. However, git will put those quotes in the output so we have to - # strip them out later :-( - - if (NOT GIT_RETURN STREQUAL 0) - message(FATAL_ERROR "ERROR, ${GIT_EXECUTABLE} command returned ${GIT_RETURN}!=0" - " for extra repo ${GIT_REPO_DIR}!") - set(GIT_VERSION_INFO "Error, could not get version info!") - else() - # Strip the quotes off :-( - string(LENGTH "${GIT_OUTPUT}" GIT_OUTPUT_LEN) - math(EXPR OUTPUT_NUM_CHARS_TO_KEEP "${GIT_OUTPUT_LEN}-2") - string(SUBSTRING "${GIT_OUTPUT}" 1 ${OUTPUT_NUM_CHARS_TO_KEEP} - GIT_VERSION_INFO) - endif() - - # B) Get the first 80 chars of the summary message for more info - - execute_process( - COMMAND ${GIT_EXECUTABLE} log -1 --pretty=format:"%s" - WORKING_DIRECTORY ${GIT_REPO_DIR} - RESULT_VARIABLE GIT_RETURN - OUTPUT_VARIABLE GIT_OUTPUT - ) - - if (NOT GIT_RETURN STREQUAL 0) - message(FATAL_ERROR "ERROR, ${GIT_EXECUTABLE} command returned ${GIT_RETURN}!=0" - " for extra repo ${GIT_REPO_DIR}!") - set(GIT_VERSION_SUMMARY "Error, could not get version summary!") - else() - # Strip ouf quotes and quote the 80 char string - set(MAX_SUMMARY_LEN 80) - math(EXPR MAX_SUMMARY_LEN_PLUS_2 "${MAX_SUMMARY_LEN}+2") - string(LENGTH "${GIT_OUTPUT}" GIT_OUTPUT_LEN) - math(EXPR OUTPUT_NUM_CHARS_TO_KEEP "${GIT_OUTPUT_LEN}-2") - string(SUBSTRING "${GIT_OUTPUT}" 1 ${OUTPUT_NUM_CHARS_TO_KEEP} - GIT_OUTPUT_STRIPPED) - if (GIT_OUTPUT_LEN GREATER ${MAX_SUMMARY_LEN_PLUS_2}) - string(SUBSTRING "${GIT_OUTPUT_STRIPPED}" 0 ${MAX_SUMMARY_LEN} - GIT_SUMMARY_STR) - else() - set(GIT_SUMMARY_STR "${GIT_OUTPUT_STRIPPED}") - endif() - endif() - - set(${SINGLE_REPO_VERSION_STRING_OUT} - "${GIT_VERSION_INFO}\n${GIT_SUMMARY_STR}" PARENT_SCOPE) - -endfunction() - # Get the versions of all the git repos # @@ -1328,7 +1262,7 @@ function(tribits_generate_repo_version_file_string PROJECT_REPO_VERSION_FILE_ST tribits_generate_single_repo_version_string( ${CMAKE_CURRENT_SOURCE_DIR} SINGLE_REPO_VERSION) - append_string_var(REPO_VERSION_FILE_STR + string(APPEND REPO_VERSION_FILE_STR "*** Base Git Repo: ${PROJECT_NAME}\n" "${SINGLE_REPO_VERSION}\n" ) @@ -1352,7 +1286,7 @@ function(tribits_generate_repo_version_file_string PROJECT_REPO_VERSION_FILE_ST tribits_generate_single_repo_version_string( "${CMAKE_CURRENT_SOURCE_DIR}/${EXTRAREPO_DIR}" SINGLE_REPO_VERSION) - append_string_var(REPO_VERSION_FILE_STR + string(APPEND REPO_VERSION_FILE_STR "*** Git Repo: ${EXTRAREPO_DIR}\n" "${SINGLE_REPO_VERSION}\n" ) @@ -1403,6 +1337,7 @@ function(tribits_generate_repo_version_output_and_file_and_install) # A) Create the ${PROJECT_NAME}RepoVersion.txt file if requested # + print_var(${PROJECT_NAME}_GENERATE_REPO_VERSION_FILE) if (${PROJECT_NAME}_GENERATE_REPO_VERSION_FILE) # A) Make sure that there is a .git dir in the project before generating @@ -1438,134 +1373,63 @@ function(tribits_generate_repo_version_output_and_file_and_install) 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}") - else() - message("${DOCSTRING}: ${NUM_ELEMENTS}") - endif() -endfunction() - - -# Print the current set of enabled/disabled packages given input list of -# packages -# -function(tribits_print_enabled_packages_list_from_var PACKAGES_LIST_VAR - DOCSTRING ENABLED_FLAG INCLUDE_EMPTY - ) - if (ENABLED_FLAG AND NOT INCLUDE_EMPTY) - tribits_get_enabled_list(${PACKAGES_LIST_VAR} ${PROJECT_NAME} - ENABLED_PACKAGES NUM_ENABLED) - elseif (ENABLED_FLAG AND INCLUDE_EMPTY) - tribits_get_nondisabled_list(${PACKAGES_LIST_VAR} ${PROJECT_NAME} - ENABLED_PACKAGES NUM_ENABLED) - elseif (NOT ENABLED_FLAG AND NOT INCLUDE_EMPTY) - tribits_get_disabled_list(${PACKAGES_LIST_VAR} ${PROJECT_NAME} - ENABLED_PACKAGES NUM_ENABLED) - else() # NOT ENABLED_FLAG AND INCLUDE_EMPTY - tribits_get_nonenabled_list(${PACKAGES_LIST_VAR} ${PROJECT_NAME} - ENABLED_PACKAGES NUM_ENABLED) - endif() - tribits_print_prefix_string_and_list("${DOCSTRING}" "${ENABLED_PACKAGES}") -endfunction() - - -# Prints the current set of enabled/disabled packages -# -function(tribits_print_enabled_package_list DOCSTRING ENABLED_FLAG INCLUDE_EMPTY) - tribits_print_enabled_packages_list_from_var( ${PROJECT_NAME}_PACKAGES - "${DOCSTRING}" ${ENABLED_FLAG} ${INCLUDE_EMPTY} ) -endfunction() - - -# Prints the current set of enabled/disabled SE packages -# -function(tribits_print_enabled_se_package_list DOCSTRING ENABLED_FLAG INCLUDE_EMPTY) - if (ENABLED_FLAG AND NOT INCLUDE_EMPTY) - tribits_get_enabled_list( ${PROJECT_NAME}_SE_PACKAGES ${PROJECT_NAME} - ENABLED_SE_PACKAGES NUM_ENABLED) - elseif (ENABLED_FLAG AND INCLUDE_EMPTY) - tribits_get_nondisabled_list( ${PROJECT_NAME}_SE_PACKAGES ${PROJECT_NAME} - ENABLED_SE_PACKAGES NUM_ENABLED) - elseif (NOT ENABLED_FLAG AND NOT INCLUDE_EMPTY) - tribits_get_disabled_list( ${PROJECT_NAME}_SE_PACKAGES ${PROJECT_NAME} - ENABLED_SE_PACKAGES NUM_ENABLED) - else() # NOT ENABLED_FLAG AND INCLUDE_EMPTY - tribits_get_nonenabled_list( ${PROJECT_NAME}_SE_PACKAGES ${PROJECT_NAME} - ENABLED_SE_PACKAGES NUM_ENABLED) - endif() - tribits_print_prefix_string_and_list("${DOCSTRING}" "${ENABLED_SE_PACKAGES}") -endfunction() - - -# Print the current set of enabled/disabled TPLs -# -function(tribits_print_enabled_tpl_list DOCSTRING ENABLED_FLAG INCLUDE_EMPTY) - if (ENABLED_FLAG AND NOT INCLUDE_EMPTY) - tribits_get_enabled_list( ${PROJECT_NAME}_TPLS TPL - ENABLED_TPLS NUM_ENABLED) - elseif (ENABLED_FLAG AND INCLUDE_EMPTY) - tribits_get_nondisabled_list( ${PROJECT_NAME}_TPLS TPL - ENABLED_TPLS NUM_ENABLED) - elseif (NOT ENABLED_FLAG AND NOT INCLUDE_EMPTY) - tribits_get_disabled_list( ${PROJECT_NAME}_TPLS TPL - ENABLED_TPLS NUM_ENABLED) - else() # NOT ENABLED_FLAG AND INCLUDE_EMPTY - tribits_get_nonenabled_list( ${PROJECT_NAME}_TPLS TPL - ENABLED_TPLS NUM_ENABLED) - endif() - tribits_print_prefix_string_and_list("${DOCSTRING}" "${ENABLED_TPLS}") -endfunction() - - # Adjust package enable logic and print out before and after state # # On output sets: # -# ${PROJECT_NAME}_NUM_ENABLED_PACKAGES: Number of enabled packages (local variable) -# ${PROJECT_NAME}_ENABLE_${PACKAGE_NAME}: Enable status of PACKAGE_NAME (local variable) +# * ${PROJECT_NAME}_NUM_ENABLED_PACKAGES: Number of enabled packages (local variable) +# * ${PROJECT_NAME}_ENABLE_${PACKAGE_NAME}: Enable status of PACKAGE_NAME (local variable) # ToDo: Fill in others as well! # macro(tribits_adjust_and_print_package_dependencies) - tribits_config_code_start_timer(ADJUST_PACKAGE_DEPS_TIME_START_SECONDS) + tribits_print_enables_before_adjust_package_enables() + tribits_adjust_package_enables() + tribits_print_enables_after_adjust_package_enables() + tribits_handle_project_extra_link_flags_as_a_tpl() + tribits_set_up_enabled_only_dependencies() + tribits_config_code_stop_timer(ADJUST_PACKAGE_DEPS_TIME_START_SECONDS + "\nTotal time to adjust package and TPL enables") +endmacro() - tribits_print_enabled_package_list( - "\nExplicitly enabled packages on input (by user)" ON FALSE) - tribits_print_enabled_se_package_list( - "\nExplicitly enabled SE packages on input (by user)" ON FALSE) - tribits_print_enabled_package_list( - "\nExplicitly disabled packages on input (by user or by default)" OFF FALSE) - tribits_print_enabled_se_package_list( - "\nExplicitly disabled SE packages on input (by user or by default)" OFF FALSE) - tribits_print_enabled_tpl_list( - "\nExplicitly enabled TPLs on input (by user)" ON FALSE) - tribits_print_enabled_tpl_list( - "\nExplicitly disabled TPLs on input (by user or by default)" OFF FALSE) - tribits_adjust_package_enables() +# Tack on ${PROJECT_NAME}_EXTRA_LINK_LIBS as a TPL that every downstream +# external and internal package depends on +# +macro(tribits_handle_project_extra_link_flags_as_a_tpl) - tribits_print_prefix_string_and_list( - "\nFinal set of enabled packages" "${${PROJECT_NAME}_ENABLED_PACKAGES}") - tribits_print_prefix_string_and_list( - "\nFinal set of enabled SE packages" "${${PROJECT_NAME}_ENABLED_SE_PACKAGES}") - tribits_print_enabled_package_list( - "\nFinal set of non-enabled packages" OFF TRUE) - tribits_print_enabled_se_package_list( - "\nFinal set of non-enabled SE packages" OFF TRUE) - tribits_print_enabled_tpl_list( - "\nFinal set of enabled TPLs" ON FALSE) - tribits_print_enabled_tpl_list( - "\nFinal set of non-enabled TPLs" OFF TRUE) + if (${PROJECT_NAME}_EXTRA_LINK_FLAGS) - tribits_set_up_enabled_only_dependencies() + set(lastLibTplName ${PROJECT_NAME}TribitsLastLib) - tribits_config_code_stop_timer(ADJUST_PACKAGE_DEPS_TIME_START_SECONDS - "\nTotal time to adjust package and TPL enables") + # Define the TPL ${PROJECT_NAME}TribitsLastLib and its find module + 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}_TPLS}) + list(APPEND ${TPL_NAME}_LIB_ALL_DEPENDENCIES ${lastLibTplName}) + if (TPL_ENABLE_${TPL_NAME}) + list(APPEND ${TPL_NAME}_LIB_ENABLED_DEPENDENCIES ${lastLibTplName}) + endif() + endforeach() + + # Prepend ${PROJECT_NAME}TribitsLastLib to the list of external packages/TPLs + list(PREPEND ${PROJECT_NAME}_TPLS ${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}_PACKAGES}) + list(APPEND ${PACKAGE_NAME}_LIB_ALL_DEPENDENCIES ${lastLibTplName}) + if (${PROJECT_NAME}_ENABLE_${PACKAGE_NAME}) + list(APPEND ${PACKAGE_NAME}_LIB_ENABLED_DEPENDENCIES ${lastLibTplName}) + endif() + endforeach() + + endif() endmacro() @@ -1849,21 +1713,6 @@ macro(tribits_setup_env) # enable/disable the graphical dependency graphs in doxygen Doxyfiles. include(FindDoxygen) - # Set the hack library to get link options on - - if (${PROJECT_NAME}_EXTRA_LINK_FLAGS) - if (TRIBITS_SETUP_ENV_DEBUG) - message(STATUS "Creating dummy last_lib for appending the link flags: " - "${${PROJECT_NAME}_EXTRA_LINK_FLAGS}") - endif() - if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/last_lib_dummy.c) - file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/last_lib_dummy.c - "typedef int last_lib_dummy_t;\n") - endif() - add_library(last_lib STATIC ${CMAKE_CURRENT_BINARY_DIR}/last_lib_dummy.c) - target_link_libraries(last_lib ${${PROJECT_NAME}_EXTRA_LINK_FLAGS}) - endif() - # You have to override the configuration types for MSVS after the compiler # checks! set(CMAKE_CONFIGURATION_TYPES ${CMAKE_CONFIGURATION_TYPE} @@ -2186,7 +2035,7 @@ endfunction() # Configure the enabled packages # -# This macro actally calls add_subdirectory() on the enabled +# This macro actually calls add_subdirectory() on the enabled # TriBITS packages. # macro(tribits_configure_enabled_packages) @@ -2197,10 +2046,8 @@ macro(tribits_configure_enabled_packages) # A) Global variable initialization # - global_null_set(${PROJECT_NAME}_INCLUDE_DIRS) - global_null_set(${PROJECT_NAME}_LIBRARY_DIRS) - global_null_set(${PROJECT_NAME}_LIBRARIES) - global_null_set(${PROJECT_NAME}_ETI_PACKAGES) + global_null_set(${PROJECT_NAME}_LIBRARIES "") + global_null_set(${PROJECT_NAME}_ETI_PACKAGES "") # # B) Define the source and binary directories for all of the packages that @@ -2302,8 +2149,6 @@ macro(tribits_configure_enabled_packages) endif() list(APPEND ENABLED_PACKAGE_LIBS_TARGETS ${TRIBITS_PACKAGE}_libs) - list(APPEND ${PROJECT_NAME}_INCLUDE_DIRS ${${TRIBITS_PACKAGE}_INCLUDE_DIRS}) - list(APPEND ${PROJECT_NAME}_LIBRARY_DIRS ${${TRIBITS_PACKAGE}_LIBRARY_DIRS}) list(APPEND ${PROJECT_NAME}_LIBRARIES ${${TRIBITS_PACKAGE}_LIBRARIES}) tribits_package_config_code_stop_timer(PROCESS_THIS_PACKAGE_TIME_START_SECONDS @@ -2382,18 +2227,12 @@ macro(tribits_configure_enabled_packages) if (NOT ${PROJECT_NAME}_TRACE_DEPENDENCY_HANDLING_ONLY) - remove_global_duplicates(${PROJECT_NAME}_INCLUDE_DIRS) - remove_global_duplicates(${PROJECT_NAME}_LIBRARY_DIRS) remove_global_duplicates(${PROJECT_NAME}_LIBRARIES) # Add global 'libs' target if(ENABLED_PACKAGE_LIBS_TARGETS) list(REVERSE ENABLED_PACKAGE_LIBS_TARGETS) # Make it so when no packages are enabled it is not a cmake error - if (${PROJECT_NAME}_EXTRA_LINK_FLAGS) - append_set(ENABLED_PACKAGE_LIBS_TARGETS last_lib) - endif() - #print_var(ENABLED_PACKAGE_LIBS_TARGETS) if (NOT TARGET ${PROJECT_NAME}_libs) add_custom_target(${PROJECT_NAME}_libs) add_dependencies(${PROJECT_NAME}_libs ${ENABLED_PACKAGE_LIBS_TARGETS}) diff --git a/cmake/tribits/core/package_arch/TribitsIncludeDirectories.cmake b/cmake/tribits/core/package_arch/TribitsIncludeDirectories.cmake index c1de80edcc9b..3f90fc873d69 100644 --- a/cmake/tribits/core/package_arch/TribitsIncludeDirectories.cmake +++ b/cmake/tribits/core/package_arch/TribitsIncludeDirectories.cmake @@ -40,7 +40,6 @@ include(CMakeParseArguments) -# # @MACRO: tribits_include_directories() # # This function is to override the standard behavior of the built-in CMake diff --git a/cmake/tribits/core/package_arch/TribitsInstallHeaders.cmake b/cmake/tribits/core/package_arch/TribitsInstallHeaders.cmake index 8f875dfd95d6..c1bf53039796 100644 --- a/cmake/tribits/core/package_arch/TribitsInstallHeaders.cmake +++ b/cmake/tribits/core/package_arch/TribitsInstallHeaders.cmake @@ -41,7 +41,6 @@ include(CMakeParseArguments) -# # @FUNCTION: tribits_install_headers() # # Function used to (optionally) install header files using ``install()`` diff --git a/cmake/tribits/core/package_arch/TribitsLibIsTestOnly.cmake b/cmake/tribits/core/package_arch/TribitsLibIsTestOnly.cmake new file mode 100644 index 000000000000..1120b27045fd --- /dev/null +++ b/cmake/tribits/core/package_arch/TribitsLibIsTestOnly.cmake @@ -0,0 +1,77 @@ +# @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 + +include_guard() + + +# @FUNCTION: tribits_set_lib_is_testonly() +# +# See if a library is a TESTONLY library +# +# Usage:: +# +# tribits_set_lib_is_testonly() +# +# This sets the ``TRIBITS_TESTONLY_LIB`` on the library target ````. +# +function(tribits_set_lib_is_testonly libName) + set_target_properties(${libName} PROPERTIES TRIBITS_TESTONLY_LIB TRUE) +endfunction() + + +# @FUNCTION: tribits_lib_is_testonly() +# +# See if a library is a TESTONLY library +# +# Usage:: +# +# tribits_lib_is_testonly( ) +# +# This will only return ``TRUE`` in `` `` if ```` +# is a target and the target property ``TRIBITS_TESTONLY_LIB`` is set to +# ``TRUE``. +# +function(tribits_lib_is_testonly libName libIsTestOnlyOut) + if (TARGET ${libName}) + get_target_property(libIsTestOnly ${libName} TRIBITS_TESTONLY_LIB) + else() + set(libIsTestOnly FALSE) + endif() + set(${libIsTestOnlyOut} ${libIsTestOnly} PARENT_SCOPE) +endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsLibraryMacros.cmake b/cmake/tribits/core/package_arch/TribitsLibraryMacros.cmake index cc97f07b5e0f..27fdfc952501 100644 --- a/cmake/tribits/core/package_arch/TribitsLibraryMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsLibraryMacros.cmake @@ -38,968 +38,5 @@ # @HEADER include(TribitsCreateClientTemplateHeaders) -include(CMakeParseArguments) -include(GlobalSet) -include(AppendSet) -include(AppendGlob) -include(AppendGlobalSet) -include(AppendStringVar) -include(PrependGlobalSet) -include(RemoveGlobalDuplicates) -include(TribitsGeneralMacros) -include(TribitsReportInvalidTribitsUsage) -include(SetAndIncDirs) - -### -### WARNING: See "NOTES TO DEVELOPERS" at the bottom of the file -### TribitsPackageMacros.cmake! -### - - -# -# Macro that configures the package's main config.h file -# -function(tribits_add_config_define DEFINE) - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- " "Package ${PARENT_PACKAGE_NAME}: adding compiler" - " define to config file: ${DEFINE}") - endif() - global_set(${PARENT_PACKAGE_NAME}_CONFIG_DEFINES - "${${PARENT_PACKAGE_NAME}_CONFIG_DEFINES}\n#define ${DEFINE}") - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- ${${PARENT_PACKAGE_NAME}_CONFIG_DEFINES}") - endif() -endfunction() - - -# -# @FUNCTION: tribits_configure_file() -# -# Macro that configures the package's main configured header file (typically -# called ``${PACKAGE_NAME}_config.h`` but any name can be used). -# -# Usage:: -# -# tribits_configure_file() -# -# This function requires the file:: -# -# ${PACKAGE_SOURCE_DIR}/cmake/.in -# -# exists and it creates the file:: -# -# ${CMAKE_CURRENT_BINARY_DIR}/ -# -# by calling the built-in ``configure_file()`` command:: -# -# configure_file( -# ${PACKAGE_SOURCE_DIR}/cmake/.in -# ${CMAKE_CURRENT_BINARY_DIR}/ -# ) -# -# which does basic substitution of CMake variables (see documentation for -# built-in CMake `configure_file()`_ command for rules on how it performs -# substitutions). This command is typically used to configure the package's -# main `/cmake/_config.h.in`_ file. -# -# In addition to just calling ``configure_file()``, this function also aids in -# creating configured header files adding macros for deprecating code as -# described below. -# -# **Deprecated Code Macros** -# -# If ``${PARENT_PACKAGE_NAME}_SHOW_DEPRECATED_WARNINGS`` is ``TRUE`` (see -# `tribits_add_show_deprecated_warnings_option()`_), then the local CMake -# variable ``${PARENT_PACKAGE_NAME_UC}_DEPRECATED_DECLARATIONS`` is set which -# adds a define ``_DEPRECATED`` (where -# ```` is the package name in all upper-case letters) -# which adds a compiler-specific deprecated warning for an entity. To take -# advantage of this, just add the line:: -# -# @_DEPRECATED_DECLARATIONS@ -# -# to the ``.in`` file and it will be expanded at configure -# time. -# -# Then C/C++ code can use this macro to deprecate functions, variables, -# classes, etc., for example, using:: -# -# _DEPRECATED class SomeDepreatedClass { ... }. -# -# If the particular compiler does not support deprecated warnings, then this -# macro is defined to be empty. See `Regulated Backward Compatibility and -# Deprecated Code`_ for more details. -# -function(tribits_configure_file PACKAGE_NAME_CONFIG_FILE) - - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("\nPACKAGE_CONFIGURE_FILE: ${PACKAGE_NAME_CONFIG_FILE}") - endif() - - # Set up the deprecated attribute if showing deprecated warnings - if (${PARENT_PACKAGE_NAME}_SHOW_DEPRECATED_WARNINGS) - multiline_set(${PARENT_PACKAGE_NAME_UC}_DEPRECATED_DECLARATIONS - "#ifndef ${PARENT_PACKAGE_NAME_UC}_DEPRECATED\n" - "# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))\n" - "# define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED __attribute__((__deprecated__))\n" - "# else\n" - "# define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED\n" - "# endif\n" - "#endif\n" - "\n" - "#ifndef ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_MSG\n" - "# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))\n" - "# define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_MSG(MSG) __attribute__((__deprecated__ (#MSG) ))\n" - "# elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))\n" - "# define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_MSG(MSG) __attribute__((__deprecated__))\n" - "# else\n" - "# define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_MSG(MSG)\n" - "# endif\n" - "#endif\n" - ) - else() - multiline_set(${PARENT_PACKAGE_NAME_UC}_DEPRECATED_DECLARATIONS - "#define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED\n" - "#define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_MSG(MSG)\n" - ) - endif() - - if (${PARENT_PACKAGE_NAME}_HIDE_DEPRECATED_CODE) - append_string_var(${PARENT_PACKAGE_NAME_UC}_DEPRECATED_DECLARATIONS - "\n#define ${PARENT_PACKAGE_NAME_UC}_HIDE_DEPRECATED_CODE") - endif() - - # Set up the macro to create the define for time monitor - set(TIME_MONITOR_DEFINE_NAME ${PARENT_PACKAGE_NAME_UC}_TEUCHOS_TIME_MONITOR) - set(FUNC_TIME_MONITOR_MACRO_NAME ${PARENT_PACKAGE_NAME_UC}_FUNC_TIME_MONITOR) - set(FUNC_TIME_MONITOR_DIFF_MACRO_NAME ${PARENT_PACKAGE_NAME_UC}_FUNC_TIME_MONITOR_DIFF) - if (${PARENT_PACKAGE_NAME}_ENABLE_TEUCHOS_TIME_MONITOR) - multiline_set(${PARENT_PACKAGE_NAME_UC}_TEUCHOS_TIME_MONITOR_DECLARATIONS - "#ifndef ${FUNC_TIME_MONITOR_MACRO_NAME}\n" - "# define ${TIME_MONITOR_DEFINE_NAME}\n" - "# define ${FUNC_TIME_MONITOR_MACRO_NAME}(FUNCNAME) \\\n" - " TEUCHOS_FUNC_TIME_MONITOR_DIFF(FUNCNAME, ${PARENT_PACKAGE_NAME_UC})\n" - "# define ${FUNC_TIME_MONITOR_DIFF_MACRO_NAME}(FUNCNAME, DIFF) \\\n" - " TEUCHOS_FUNC_TIME_MONITOR_DIFF(FUNCNAME, DIFF)\n" - "#endif\n" - ) - else() - multiline_set(${PARENT_PACKAGE_NAME_UC}_TEUCHOS_TIME_MONITOR_DECLARATIONS - "#define ${FUNC_TIME_MONITOR_MACRO_NAME}(FUNCNAME)\n" - "#define ${FUNC_TIME_MONITOR_DIFF_MACRO_NAME}(FUNCNAME, DIFF)\n" - ) - endif() - - # Configure the file - configure_file( - ${PACKAGE_SOURCE_DIR}/cmake/${PACKAGE_NAME_CONFIG_FILE}.in - ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME_CONFIG_FILE} - ) - -endfunction() - - -# -# @FUNCTION: tribits_add_library() -# -# Function used to add a CMake library and target using ``add_library()``. -# -# Usage:: -# -# tribits_add_library( -# -# [HEADERS

...] -# [HEADERS_INSTALL_SUBDIR ] -# [NOINSTALLHEADERS ...] -# [SOURCES ...] -# [DEPLIBS ...] -# [IMPORTEDLIBS ...] -# [STATIC|SHARED] -# [TESTONLY] -# [NO_INSTALL_LIB_OR_HEADERS] -# [CUDALIBRARY] -# [ADDED_LIB_TARGET_NAME_OUT ] -# ) -# -# *Sections:* -# -# * `Formal Arguments (tribits_add_library())`_ -# * `Include Directories (tribits_add_library())`_ -# * `Install Targets (tribits_add_library())`_ -# * `Additional Library and Source File Properties (tribits_add_library())`_ -# * `Miscellaneous Notes (tribits_add_library())`_ -# -# .. _Formal Arguments (tribits_add_library()): -# -# **Formal Arguments (tribits_add_library())** -# -# ```` -# -# Required base name of the library. The name of the actual library name -# will be prefixed by ``${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}`` to -# produce:: -# -# = ${${PROJECT_NAME}_LIBRARY_NAME_PREFIX} -# -# This is the name passed to ``add_library( ...)``. The -# name is *not* prefixed by the package name. CMake will of course add -# any standard prefix or post-fix to the library file name appropriate for -# the platform and if this is a static or shared library build (e.g. on -# Linux prefix = ``'lib'``, postfix = ``'.so'`` for shared lib and postfix -# = ``'.a'`` static lib) (see documentation for the built-in CMake command -# ``add_library()``. -# -# ``HEADERS

...`` -# -# List of public header files for using this library. By default, these -# header files are assumed to be in the current source directory. They -# can also contain the relative path or absolute path to the files if they -# are not in the current source directory. This list of headers is passed -# into ``add_library(...)`` as well (which is not strictly needed but is -# helpful for some build tools, like MS Visual Studio). By default, these -# headers will be installed (see `Install Targets -# (tribits_add_library())`_). -# -# ``HEADERS_INSTALL_SUBDIR `` -# -# Optional subdirectory that the headers will be installed under the -# standard installation directory. If ``!=""``, then the -# headers will be installed under -# ``${PROJECT_NAME}_INSTALL_INCLUDE_DIR}/``. Otherwise, -# they will be installed under ``${PROJECT_NAME}_INSTALL_INCLUDE_DIR}/``. -# `Install Targets (tribits_add_library())`_. -# -# ``NOINSTALLHEADERS ...`` -# -# List of private header files which are used by this library. These -# headers are not installed and do not needed to be passed in for any -# purpose other than to pass them into ``add_library()`` as some build -# tools like to have these listed (e.g. MS Visual Studio). -# -# ``SOURCES ...`` -# -# List of source files passed into ``add_library()`` that are compiled -# into header files and included in the library. The compiler used to -# compile the files is determined automatically based on the file -# extension (see CMake documentation for ``add_library()``). -# -# ``DEPLIBS ...`` -# -# List of dependent libraries that are built in the current SE package -# that this library is dependent on. These libraries are passed into -# ``target_link_libraries( ...)`` so that CMake knows about -# the dependency structure of the libraries within this SE package. -# **NOTE:** One must **not** list libraries in other upstream `TriBITS SE -# Packages`_ or libraries built externally from this TriBITS CMake project -# in ``DEPLIBS``. The TriBITS system automatically handles linking to -# libraries in upstream TriBITS SE packages. External libraries need to -# be listed in the ``IMPORTEDLIBS`` argument instead if they are not -# already specified automatically using a `TriBITS TPL`_. -# -# ``IMPORTEDLIBS ...`` -# -# List of dependent libraries built externally from this TriBITS CMake -# project. These libraries are passed into -# ``target_link_libraries( ...)`` so that CMake knows about -# the dependency. However, note that external libraries are often better -# handled as `TriBITS TPLs`_. A well constructed TriBITS package and -# library should never have to use this option! So far, the only case -# where ``IMPORTEDLIBS`` has been shown to be necessary is to pass in the -# standard C math library ``m``. In every other case, a TriBITS TPL -# should be used instead. -# -# ``STATIC`` or ``SHARED`` -# -# If ``STATIC`` is passed in, then a static library will be created -# independent of the value of ``BUILD_SHARED_LIBS``. If ``SHARED`` is -# passed in, then a shared library will be created independent of the -# value of ``BUILD_SHARED_LIBS``. If neither ``STATIC`` or ``SHARED`` are -# passed in, then a shared library will be created if -# ``BUILD_SHARED_LIBS`` evaluates to true, otherwise and a static library -# will be created. If both ``STATIC`` and ``SHARED`` are passed in (which -# is obviously a mistake), then a shared library will be created. -# WARNING: Once you mark a library with ``STATIC``, then all of the -# downstream libraries in the current SE package and all downstream SE -# packages must also be also be marked with ``STATIC``. That is because, -# generally, one can not link a link a static lib against a downstream -# shared lib since that is not portable (but can be done on some platforms -# if, for example, ``-fPIC`` is specified). So be careful to use -# ``STATIC`` in all downstream libraries! -# -# ``TESTONLY`` -# -# If passed in, then ```` will **not** be added to -# ``${PACKAGE_NAME}_LIBRARIES`` and an install target for the library will -# not be added. In this case, the current include directories will be set -# in the global variable ``_INCLUDE_DIR`` which will be -# used in `tribits_add_executable()`_ when a test-only library is linked -# in through its ``DEPLIBS`` argument. -# -# ``NO_INSTALL_LIB_OR_HEADERS`` -# -# If specified, then no install targets will be added for the library -# ```` or the header files listed in ``HEADERS``. -# -# ``CUDALIBRARY`` -# -# If specified then ``cuda_add_library()`` is used instead of -# ``add_library()`` where ``cuda_add_library()`` is assumed to be defined -# by the standard ``FindCUDA.cmake`` module as processed using the -# standard TriBITS ``FindTPLCUDA.cmake`` file (see `Standard TriBITS -# TPLs`_). For this option to work, this SE package must have an enabled -# direct or indirect dependency on the TriBITS CUDA TPL or a -# configure-time error may occur about not knowing about -# ``cuda_all_library()``. -# -# ``ADDED_LIB_TARGET_NAME_OUT `` -# -# If specified, then on output the variable ```` will be -# set with the name of the library passed to ``add_library()``. Having -# this name allows the calling ``CMakeLists.txt`` file access and set -# additional target properties (see `Additional Library and Source File -# Properties (tribits_add_library())`_). -# -# .. _Include Directories (tribits_add_library()): -# -# **Include Directories (tribits_add_library())** -# -# Any base directories for the header files listed in the arguments -# ``HEADERS`` or ``NOINSTALLHEADERS`` should be passed into the standard CMake -# command ``include_directories()`` **before** calling this function. For -# example, a CMakeLists.txt file will look like:: -# -# ... -# -# tribits_configure_file(${PACKAGE_NAME}_config.h) -# configure_file(...) -# -# ... -# -# include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -# include_directories(${CMAKE_CURRENT_BINARY_DIR}) -# -# ... -# -# tribits_add_library( -# SOURCES -# .c -# /.cpp -# /.F90 -# ... -# HEADERS -# .h -# /.hpp -# ... -# NONINSTALLHEADERS .hpp .hpp ... -# ... -# ) -# -# The include of ``${CMAKE_CURRENT_BINARY_DIR}`` is needed for any generated -# header files (e.g. using raw ``configure_file()`` or -# `tribits_configure_file()`_) or any generated Fortran ``*.mod`` module files -# generated as a byproduct of compiling F90+ source files (that contain one or -# more Fortran module declarations). -# -# The function ``tribits_add_library()`` will grab the list of all of the -# include directories in scope from prior calls to ``include_directories()`` -# and will append these to the variable ``${PACKAGE_NAME}_INCLUDE_DIRS``. -# This list of include directories is exported to downstream SE packages so -# they appear on the compile lines of all downstream object file compiles. -# This is a critical part of the "glue" that allows TriBITS packages to link -# up automatically (just by clearing dependencies in -# `/cmake/Dependencies.cmake`_ files). -# -# .. _Install Targets (tribits_add_library()): -# -# **Install Targets (tribits_add_library())** -# -# By default, an install target for the library is created using -# ``install(TARGETS ...)`` to install into the directory -# ``${CMAKE_INSTALL_PREFIX}/lib/`` (actual install directory is given by -# ``${PROJECT}_INSTALL_LIB_DIR``, see `Setting the install prefix`_). -# However, this install target will not get created if -# `${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS`_ is ``FASLE`` and -# ``BUILD_SHARD_LIBS=OFF``. But when ``BUILD_SHARD_LIBS=ON``, the install -# target will get added. Also, this install target will *not* get added if -# ``TESTONLY`` or ``NO_INSTALL_LIB_OR_HEADERS`` are passed in. -# -# By default, an install target for the headers listed in ``HEADERS`` will get -# added using ``install(FILES

...)``, but only if ``TESTONLY`` and -# ``NO_INSTALL_LIB_OR_HEADERS`` are not passed in as well. Also, the install -# target for the headers will not get added if -# `${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS`_ is ``FASLE``. If this -# install target is added, then the headers get installed into the flat -# directory ``${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}/`` (default is -# ``${CMAKE_INSTALL_PREFIX}/include/``, see `Setting the install prefix`_). -# If ``HEADERS_INSTALL_SUBDIR`` is set, then the headers will be installed -# under ``${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}//``. -# -# Note that an install target will *not* get created for the headers listed in -# ``NOINSTALLHEADERS``. -# -# .. _Additional Library and Source File Properties (tribits_add_library()): -# -# **Additional Library and Source File Properties (tribits_add_library())** -# -# Once ``add_library( ... ...)`` is called, one -# can set and change properties on the ```` library target -# using the built-in CMake command ``set_target_properties()`` as well as set -# and change properties on any of the source files listed in ``SOURCES`` using -# the built-in CMake command ``set_source_file_properties()`` just like in any -# CMake project. For example:: -# -# tribits_add_library( somelib ... -# ADDED_LIB_TARGET_NAME_OUT somelib_TARGET_NAME ) -# -# set_target_properties( ${somelib_TARGET_NAME} -# PROPERTIES LINKER_LANGUAGE CXX ) -# -# .. _Miscellaneous Notes (tribits_add_library()): -# -# **Miscellaneous Notes (tribits_add_library())** -# -# When the file ``Version.cmake`` exists and the CMake variables -# ``${PROJECT_NAME}_VERSION`` and ``${PROJECT_NAME}_MAJOR_VERSION`` are -# defined, then produced shared libraries will be given the standard SOVERSION -# symlinks (see `/Version.cmake`_). -# -# **WARNING:** Do **NOT** use the built-in CMake command ``add_definitions()`` -# to add defines ``-D`` to the compile command line that will -# affect any of the header files in the package! These CMake-added defines -# are only set locally in this directory and child directories. These defines -# will **NOT** be set when code in peer directories (e.g. a downstream TriBITS -# packages) compiles that may include these header files. To add defines that -# affect header files, please use a configured header file (see -# `tribits_configure_file()`_). -# -function(tribits_add_library LIBRARY_NAME_IN) - - # - # Confirm that package and subpackage macros/functions have been called in the correct order - # - - if (CURRENTLY_PROCESSING_SUBPACKAGE) - - # This is a subpackage being processed - - if(NOT ${SUBPACKAGE_FULLNAME}_TRIBITS_SUBPACKAGE_CALLED) - tribits_report_invalid_tribits_usage( - "Must call tribits_subpackage() before tribits_add_library()" - " in ${CURRENT_SUBPACKAGE_CMAKELIST_FILE}") - endif() - - if(${SUBPACKAGE_FULLNAME}_TRIBITS_SUBPACKAGE_POSTPROCESS_CALLED) - tribits_report_invalid_tribits_usage( - "Must call tribits_add_library() before " - " tribits_subpackage_postprocess() in ${CURRENT_SUBPACKAGE_CMAKELIST_FILE}") - endif() - - else() - - # This is a package being processed - - if(NOT ${PACKAGE_NAME}_TRIBITS_PACKAGE_DECL_CALLED) - tribits_report_invalid_tribits_usage( - "Must call tribits_package() or tribits_package_decl() before" - " tribits_add_library() in ${TRIBITS_PACKAGE_CMAKELIST_FILE}") - endif() - - if(${PACKAGE_NAME}_TRIBITS_PACKAGE_POSTPROCESS_CALLED) - tribits_report_invalid_tribits_usage( - "Must call tribits_add_library() before " - " tribits_package_postprocess() in ${TRIBITS_PACKAGE_CMAKELIST_FILE}") - endif() - - endif() - - set(LIBRARY_NAME_PREFIX "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}") - set(LIBRARY_NAME ${LIBRARY_NAME_PREFIX}${LIBRARY_NAME_IN}) - - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("\nTRIBITS_ADD_LIBRARY: ${LIBRARY_NAME}") - if(${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING) - message("\n${PACKAGE_NAME}_LIBRARIES In installation testing mode," - " libraries will be found instead of created.") - endif() - endif() - - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - print_var(${PACKAGE_NAME}_INCLUDE_DIRS) - print_var(${PACKAGE_NAME}_LIBRARY_DIRS) - print_var(${PACKAGE_NAME}_LIBRARIES) - endif() - - cmake_parse_arguments( - #prefix - PARSE - #Options - "STATIC;SHARED;TESTONLY;NO_INSTALL_LIB_OR_HEADERS;CUDALIBRARY" - #one_value_keywords - "" - #mulit_value_keywords - "HEADERS;HEADERS_INSTALL_SUBDIR;NOINSTALLHEADERS;SOURCES;DEPLIBS;IMPORTEDLIBS;DEFINES;ADDED_LIB_TARGET_NAME_OUT" - ${ARGN} - ) - - tribits_check_for_unparsed_arguments() - - # ToDo: Assert that HEADERS_INSTALL_SUBDIR has 0 or 1 entries! - # ToDo: Assert that ADDED_LIB_TARGET_NAME_OUT as 0 or 1 entries! - - if(PARSE_HEADERS) - list(REMOVE_DUPLICATES PARSE_HEADERS) - endif() - if(PARSE_SOURCES) - list(REMOVE_DUPLICATES PARSE_SOURCES) - endif() - - if(PARSE_ADDED_LIB_TARGET_NAME_OUT) - set(${PARSE_ADDED_LIB_TARGET_NAME_OUT} PARENT_SCOPE) - endif() - - # ToDo: Deprecate and remove the usage of DEFINES! People should be putting - # defines into configured header files, not adding -D to the - # compile lines! - - if (NOT ${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING OR PARSE_TESTONLY) - - # Add the link directory for this library. - - set_property(DIRECTORY APPEND PROPERTY PACKAGE_LIBRARY_DIRS - ${CMAKE_CURRENT_BINARY_DIR}) - - # NOTE: Above, this link path not really used here for anything. - # Instead it is just added to the other set link library directories - # that are already set. These link directories are then extracted - # and stored into stored in ${PACKAGE_NAME}_LIBRARY_DIRS. - - # Add whatever include directories have been defined so far - - include_directories(AFTER ${${PACKAGE_NAME}_INCLUDE_DIRS}) - - # Add whatever link directories have been added so far - - set_property(DIRECTORY APPEND PROPERTY PACKAGE_LIBRARY_DIRS - ${${PACKAGE_NAME}_LIBRARY_DIRS}) - - # Local variable to hold all of the libraries that will be directly linked - # to this library. - set(LINK_LIBS) - - # Add dependent libraries passed directly in - - if (PARSE_DEPLIBS AND ${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- " "DEPLIBS = ${PARSE_DEPLIBS}") - endif() - if (PARSE_IMPORTEDLIBS AND ${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- " "IMPORTEDLIBS = ${PARSE_IMPORTEDLIBS}") - endif() - - # - # Add the DEPLIBS to the LINK_LIBS, assert correct usage of DEPLIBS, and - # see if we need to link in the upstream SE package and TPL libs. - # - # We only want to link to the upstream dependent SE package and TPL - # libraries if needed. We only need to link to these upstream dependent - # libraries when this is the first library being created for this SE - # package or if this library does not depend on other libraries created - # for this package. Otherwise, we don't need to add the include - # directories or link libraries because a dependent lib specified in - # PARSE_DEPLIBS already has everything that we need. - # - # We also need to make special considerations for test libraries since - # things need to be handled a little bit differently (but not much). In the - # case of test libraries, we need to also pull the test-only dependencies. - # In this case, we will always assume that we will add in the test - # libraries. - # - # ToDo: Turn the below deprecated WARNING messages to FATAL_ERROR once we - # give enough time for people to clean up their codes. - # - - set(ADD_DEP_PACKAGE_AND_TPL_LIBS TRUE) - - set(PREFIXED_DEPLIBS) - - foreach(LIB ${PARSE_DEPLIBS}) - - set(PREFIXED_LIB "${LIBRARY_NAME_PREFIX}${LIB}") - - # LIB_IN_SE_PKG? - list(FIND ${PACKAGE_NAME}_LIBRARIES ${PREFIXED_LIB} FOUND_IDX) - if (FOUND_IDX GREATER -1) - set(LIB_IN_SE_PKG TRUE) - else() - set(LIB_IN_SE_PKG FALSE) - endif() - - # PREFIXED_LIB_IS_TESTONLY? - if (${PREFIXED_LIB}_INCLUDE_DIRS) - set(LIB_TESTONLY TRUE) - else() - set(LIB_TESTONLY FALSE) - endif() - - # Check for valid usage (sorted by most common to least common) - if (LIB_IN_SE_PKG AND NOT LIB_TESTONLY) #PARSE_TESTONLY=TRUE/FASLE - # The library being created here is a library dependent on a regular - # (non-TESTONLY) lib in this SE package. This is valid usage of - # DEPLIBS. There is no need to link this new lib to the SE package's - # upstream dependent SE package and TPL libraries because thse are - # already linked into the lib ${LIB}. - set(ADD_DEP_PACKAGE_AND_TPL_LIBS FALSE) - elseif (PARSE_TESTONLY AND LIB_IN_SE_PKG AND NOT LIB_TESTONLY) - # The library being created here is TESTONLY library and is - # dependent on a regular (non-TESTONLY) lib. This is valid usage of - # DEPLIBS. In the case of test-only libraries, we always link in - # the upstream libs. - elseif (PARSE_TESTONLY AND LIB_TESTONLY) # LIB_IN_SE_PKG=TRUE/FASLE - # The library being created here is TESTONLY library and is dependent - # on another TESTONLY library. This is valid usage of DEPLIBS. In - # this case we just hope that this SE package correctly specified a - # TEST dependency on the upstream SE package that owns this upstream - # TESTONLY library. - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- " - "Adding include directories for TESTONLY ${PREFIXED_LIB}_INCLUDE_DIRS ...") - endif() - include_directories(${${PREFIXED_LIB}_INCLUDE_DIRS}) - elseif (NOT PARSE_TESTONLY AND LIB_TESTONLY) # LIB_IN_SE_PKG=TRUE/FASLE - message(WARNING "WARNING: '${LIB}' in DEPLIBS is a TESTONLY lib" - " and it is illegal to link to this non-TESTONLY library '${LIBRARY_NAME}'." - " Such usage is deprecated (and this warning will soon become an error)!" - " If this is a regular library in this SE package or in an dependent upstream SE" - " package then TriBITS will link automatically to it. If you remove this and it" - " does not link, then you need to add a new SE package dependency to" - " this SE package's dependencies file" - " ${${PACKAGE_NAME}_SOURCE_DIR}/cmake/Dependencies.cmake") - # ToDo: Turn the above to FATAL_ERROR after dropping deprecated code - elseif (NOT LIB_IN_SE_PKG AND TARGET ${PREFIXED_LIB} ) # PARSE_TESTONLY=TRUE/FALSE - message(WARNING "WARNING: '${LIB}' in DEPLIBS is not" - " a lib in this SE package but is a library defined in the current" - " cmake project! Such usage is deprecated (and" - " will result in a configure error soon). If this is a library in" - " a dependent upstream SE package, then simply remove it from this list." - " TriBITS automatically links in libraries in upstream SE packages." - " If you remove '${LIB}' from DEPLIBS and your code does" - " not link, then you need to add a new SE package dependency to" - " this SE package's dependencies file" - " ${${PACKAGE_NAME}_SOURCE_DIR}/cmake/Dependencies.cmake") - elseif (NOT LIB_IN_SE_PKG AND NOT TARGET ${PREFIXED_LIB} ) - message(WARNING "WARNING: '${LIB}' in DEPLIBS is not" - " a lib defined in the current cmake project! Such usage is deprecated (and" - " will result in a configure error soon). If this is an external" - " lib you are trying to link in, it should likely be handled as a TriBITS" - " TPL. Otherwise, it should be passed in through IMPORTEDLIBS. However," - " the only case we have found where IMPORTEDLIBS had to be used instead of" - " through a proper TriBITS TPL is the C math library 'm'.") - else() - message(WARNING "WARNING: The case PARSE_TESTONLY=${PARSE_TESTONLY}," - " LIB_IN_SE_PKG=${LIB_IN_SE_PKG}, LIB_TESTONLY=${LIB_TESTONLY}, has" - " not yet been handled!") - endif() - - list(APPEND PREFIXED_DEPLIBS "${LIBRARY_NAME_PREFIX}${LIB}") - - endforeach() - - append_set(LINK_LIBS ${PREFIXED_DEPLIBS}) - - # - # Check IMPORTEDLIBS - # - - foreach(IMPORTEDLIB ${PARSE_IMPORTEDLIBS}) - set(PREFIXED_LIB "${LIBRARY_NAME_PREFIX}${IMPORTEDLIB}") - list(FIND ${PACKAGE_NAME}_LIBRARIES ${PREFIXED_LIB} FOUND_IDX) - if (${PREFIXED_LIB}_INCLUDE_DIRS) - message(WARNING "WARNING: '${IMPORTEDLIB}' in IMPORTEDLIBS is a TESTONLY lib" - " and it is illegal to pass in through IMPORTEDLIBS!" - " Such usage is deprecated (and this warning will soon become an error)!" - " Should '${IMPORTEDLIB}' instead be passed through DEPLIBS?") - # ToDo: Turn the above to FATAL_ERROR after dropping deprecated code - elseif (FOUND_IDX GREATER -1) - message(WARNING "WARNING: Lib '${IMPORTEDLIB}' in IMPORTEDLIBS is in" - " this SE package and is *not* an external lib!" - " TriBITS takes care of linking against libs the current" - " SE package automatically. Please remove it from IMPORTEDLIBS!") - elseif (TARGET ${PREFIXED_LIB}) - message(WARNING "WARNING: Lib '${IMPORTEDLIB}' being passed through" - " IMPORTEDLIBS is *not* an external library but instead is a library" - " defined in this CMake project!" - " TriBITS takes care of linking against libraries in dependent upstream" - " SE packages. If you want to link to a library in an upstream SE" - " package then add the SE package name to the appropriate category" - " in this SE package's dependencies file: " - " ${${PACKAGE_NAME}_SOURCE_DIR}/cmake/Dependencies.cmake") - endif() - # ToDo: Assert that this is not a test-only lib - list(APPEND LINK_LIBS ${IMPORTEDLIB}) - endforeach() - - # - # Link in the upstream TEST SE package and TPL libs - # - # We link these before those in the LIB SE package and TPL libs because - # the TEST dependencies tend to be higher in the dependency tree. It - # should not really matter but it looks better on the link line. - # - - if (PARSE_TESTONLY) - - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- " "Pulling in header and libraries dependencies" - " for TEST dependencies ...") - endif() - - tribits_sort_and_append_package_include_and_link_dirs_and_libs( - ${PACKAGE_NAME} TEST LINK_LIBS) - - tribits_sort_and_append_tpl_include_and_link_dirs_and_libs( - ${PACKAGE_NAME} TEST LINK_LIBS) - - endif() - - # - # Add the dependent LIB SE package and TPL libs - # - - if (ADD_DEP_PACKAGE_AND_TPL_LIBS) - - # If there are no dependent libs passed in, then this library can not - # possibly depend on the package's other libraries so we must link to - # the dependent libraries in dependent libraries and TPLs. - - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- " "Pulling in header and libraries dependencies" - " for LIB dependencies ...") - endif() - - # - # Call include_directories() and link_directories(...) for all upstream - # dependent Packages and TPLs and accumulate the libraries to link against. - # - # NOTE: Adding these directories serves two purposes. First, so that the includes - # get added the the sources that get built for this library. Second, so - # that list full list of include directories can be extracted as a - # property and set on ${PACKAGE_NAME}_INCLUDE_DIRS - # - - tribits_sort_and_append_package_include_and_link_dirs_and_libs( - ${PACKAGE_NAME} LIB LINK_LIBS) - - tribits_sort_and_append_tpl_include_and_link_dirs_and_libs( - ${PACKAGE_NAME} LIB LINK_LIBS) - - endif() - - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - print_var(LINK_LIBS) - endif() - - # Add the library and all the dependencies - - if (PARSE_DEFINES) - add_definitions(${PARSE_DEFINES}) - endif() - - if (PARSE_STATIC) - set(STATIC_KEYWORD "STATIC") - else() - set(STATIC_KEYWORD) - endif() - - if (PARSE_SHARED) - set(SHARED_KEYWORD "SHARED") - else() - set(SHARED_KEYWORD) - endif() - - if (NOT PARSE_CUDALIBRARY) - add_library( - ${LIBRARY_NAME} - ${STATIC_KEYWORD} - ${SHARED_KEYWORD} - ${PARSE_HEADERS} - ${PARSE_NOINSTALLHEADERS} - ${PARSE_SOURCES} - ) - else() - cuda_add_library( - ${LIBRARY_NAME} - ${PARSE_HEADERS} - ${PARSE_NOINSTALLHEADERS} - ${PARSE_SOURCES} - ) - endif() - - if(PARSE_ADDED_LIB_TARGET_NAME_OUT) - set(${PARSE_ADDED_LIB_TARGET_NAME_OUT} ${LIBRARY_NAME} PARENT_SCOPE) - endif() - - set_property( - TARGET ${LIBRARY_NAME} - APPEND PROPERTY - LABELS ${PACKAGE_NAME}Libs ${PARENT_PACKAGE_NAME}Libs - ) - - if (NOT "${${PROJECT_NAME}_VERSION}" STREQUAL "" AND - NOT "${${PROJECT_NAME}_MAJOR_VERSION}" STREQUAL "" - ) - set_target_properties( - ${LIBRARY_NAME} - PROPERTIES - VERSION ${${PROJECT_NAME}_VERSION} - SOVERSION ${${PROJECT_NAME}_MAJOR_VERSION} - ) - endif() - - prepend_global_set(${PARENT_PACKAGE_NAME}_LIB_TARGETS ${LIBRARY_NAME}) - prepend_global_set(${PARENT_PACKAGE_NAME}_ALL_TARGETS ${LIBRARY_NAME}) - - if (${PROJECT_NAME}_DUMP_LINK_LIBS) - message("-- ${LIBRARY_NAME_IN}:LINK_LIBS='${LINK_LIBS}'") - endif() - - target_link_libraries(${LIBRARY_NAME} PUBLIC ${LINK_LIBS}) - - if (${PROJECT_NAME}_CXX_STANDARD_FEATURE) - target_compile_features(${LIBRARY_NAME} PUBLIC "${${PROJECT_NAME}_CXX_STANDARD_FEATURE}") - ENDIF () - - # Add to the install target - - set(INSTALL_LIB ON) - set(INSTALL_HEADERS ON) - set(APPEND_LIB_AND_HEADERS_TO_PACKAGE ON) - - if (PARSE_TESTONLY) - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- " "Skipping installation hooks for this library" - " because 'TESTONLY' was passed in ...") - endif() - set(INSTALL_LIB OFF) - set(INSTALL_HEADERS OFF) - set(APPEND_LIB_AND_HEADERS_TO_PACKAGE OFF) - elseif (PARSE_NO_INSTALL_LIB_OR_HEADERS) - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- " "Skipping installation hooks for this library" - " because 'NO_INSTALL_LIB_OR_HEADERS' was passed in ...") - endif() - set(INSTALL_LIB OFF) - set(INSTALL_HEADERS OFF) - elseif (NOT ${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS AND NOT BUILD_SHARED_LIBS) - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- " "Skipping installation of headers and libraries" - " because ${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS=FALSE and BUILD_SHARED_LIBS=FALSE ...") - endif() - set(INSTALL_LIB OFF) - set(INSTALL_HEADERS OFF) - elseif (NOT ${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS AND BUILD_SHARED_LIBS) - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- " "Skipping installation of headers but installing libraries" - " because ${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS=FALSE and BUILD_SHARED_LIBS=TRUE ...") - endif() - set(INSTALL_HEADERS OFF) - endif() - - if (INSTALL_LIB OR INSTALL_HEADERS) - set_property(GLOBAL PROPERTY ${PROJECT_NAME}_HAS_INSTALL_TARGETS ON) - set_property(GLOBAL PROPERTY ${PACKAGE_NAME}_HAS_INSTALL_TARGETS ON) - endif() - - if (INSTALL_LIB) - install( - TARGETS ${LIBRARY_NAME} - EXPORT ${PACKAGE_NAME} - RUNTIME DESTINATION "${${PROJECT_NAME}_INSTALL_RUNTIME_DIR}" - LIBRARY DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}" - ARCHIVE DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}" - COMPONENT ${PACKAGE_NAME} - ) - endif() - - if (INSTALL_HEADERS) - tribits_install_headers( - HEADERS ${PARSE_HEADERS} - INSTALL_SUBDIR ${PARSE_HEADERS_INSTALL_SUBDIR} - COMPONENT ${PACKAGE_NAME} - ) - endif() - - # Append the new include dirs, library dirs, and libraries to this package's lists - - get_directory_property(INCLUDE_DIRS_CURRENT INCLUDE_DIRECTORIES) - get_directory_property(LIBRARY_DIRS_CURRENT PACKAGE_LIBRARY_DIRS) - - if (APPEND_LIB_AND_HEADERS_TO_PACKAGE) - - prepend_global_set(${PACKAGE_NAME}_INCLUDE_DIRS ${INCLUDE_DIRS_CURRENT}) - prepend_global_set(${PACKAGE_NAME}_LIBRARY_DIRS ${LIBRARY_DIRS_CURRENT}) - prepend_global_set(${PACKAGE_NAME}_LIBRARIES ${LIBRARY_NAME}) - - remove_global_duplicates(${PACKAGE_NAME}_INCLUDE_DIRS) - remove_global_duplicates(${PACKAGE_NAME}_LIBRARY_DIRS) - remove_global_duplicates(${PACKAGE_NAME}_LIBRARIES) - - if (INSTALL_LIB) - global_set(${PACKAGE_NAME}_HAS_NATIVE_LIBRARIES_TO_INSTALL TRUE) - endif() - - else() - - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- " "Skipping augmentation of package's lists of include" - " directories and libraries! ...") - endif() - - list(REMOVE_DUPLICATES INCLUDE_DIRS_CURRENT) - global_set(${LIBRARY_NAME}_INCLUDE_DIRS ${INCLUDE_DIRS_CURRENT}) - - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - print_var(${LIBRARY_NAME}_INCLUDE_DIRS) - endif() - - endif() - endif() #if not in installation testing mode - - # - # Adjust for installation testing - # - - if (${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING) - - list(FIND ${PROJECT_NAME}_INSTALLATION_PACKAGE_LIST ${PACKAGE_NAME} - ${PACKAGE_NAME}_WAS_INSTALLED) - if(${${PACKAGE_NAME}_WAS_INSTALLED} EQUAL -1) - message(FATAL_ERROR - "The package ${PACKAGE_NAME} was not installed with ${PROJECT_NAME}!" - " Please disable package ${PACKAGE_NAME} or install it.") - endif() - - include_directories(REQUIRED_DURING_INSTALLATION_TESTING BEFORE - ${${PACKAGE_NAME}_INSTALLATION_INCLUDE_DIRS} - ${${TRIBITS_PACKAGE}_INSTALLATION_TPL_INCLUDE_DIRS}) - set_property(DIRECTORY APPEND PROPERTY PACKAGE_LIBRARY_DIRS - ${${PACKAGE_NAME}_INSTALLATION_LIBRARY_DIRS}) - - get_directory_property(INCLUDE_DIRS_CURRENT INCLUDE_DIRECTORIES) - get_directory_property(LIBRARY_DIRS_CURRENT PACKAGE_LIBRARY_DIRS) - - global_set(${PACKAGE_NAME}_INCLUDE_DIRS ${INCLUDE_DIRS_CURRENT}) - global_set(${PACKAGE_NAME}_LIBRARY_DIRS ${LIBRARY_DIRS_CURRENT}) - global_set(${PACKAGE_NAME}_LIBRARIES ${${PACKAGE_NAME}_INSTALLATION_LIBRARIES}) - - endif() #installation testing mode - - # - # Print the updates to the linkage variables - # - - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - print_var(${PACKAGE_NAME}_INCLUDE_DIRS) - print_var(${PACKAGE_NAME}_LIBRARY_DIRS) - print_var(${PACKAGE_NAME}_LIBRARIES) - endif() - -endfunction() +include(TribitsConfigureFile) +include(TribitsAddLibrary) diff --git a/cmake/tribits/core/package_arch/TribitsListHelpers.cmake b/cmake/tribits/core/package_arch/TribitsListHelpers.cmake index f500bf863364..ea94d8cb1e91 100644 --- a/cmake/tribits/core/package_arch/TribitsListHelpers.cmake +++ b/cmake/tribits/core/package_arch/TribitsListHelpers.cmake @@ -81,7 +81,6 @@ macro(tribits_set_package_to_ex PACKAGE_NAME) endmacro() -# # @MACRO: tribits_disable_package_on_platforms() # # Disable a package automatically for a list of platforms. diff --git a/cmake/tribits/core/package_arch/TribitsPackageDependencies.cmake b/cmake/tribits/core/package_arch/TribitsPackageDependencies.cmake new file mode 100644 index 000000000000..bfcf785a4382 --- /dev/null +++ b/cmake/tribits/core/package_arch/TribitsPackageDependencies.cmake @@ -0,0 +1,212 @@ +# @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 + + +################################################################################ +# +# TribitPackageDependencies.cmake +# +# Contains macros and functions related to defining internal package and +# external package/TPL dependencies with a little bit of logic. +# +################################################################################ + + +include_guard() + +include(TribitsCMakePolicies NO_POLICY_SCOPE) + +include(TribitsParseArgumentsHelpers) +include(MessageWrapper) + + +# @MACRO: tribits_extpkg_define_dependencies() +# +# Macro called from inside of a `FindTPLDependencies.cmake`_ file to +# define the direct upstream dependencies an external package/TPL. +# +# Usage:: +# +# tribits_extpkg_define_dependencies( +# DEPENDENCIES : ... ) +# +# The listed upstream dependencies ```` are other external +# packages/TPLs listed before this external packages/TPL ```` in a +# `/TPLsList.cmake`_ file. Each upstream dependency can include a +# visibility specification ```` that can be added to the dependency +# using a colon ``:`` with ``:`` where ```` can +# take the allowed values: +# +# * ``PUBLIC``: The include directories along with the libraries will be +# propagated downstream to clients of ````. +# +# * ``PRIVATE``: Only the libraries will be propagated downstream to clients +# of ````. +# +# If ```` is not specified, then the default is ``PRIVATE``. (If a +# package needs the include directories from some external package/TPL, then +# it should list that external package/TPL as a direct dependency and not +# expect to get include directories from indirect dependencies.) +# +macro(tribits_extpkg_define_dependencies + tplName + ) + + # Parse arguments + cmake_parse_arguments( + PARSE "" "" # prefix, options, one_value_keywords + "DEPENDENCIES" # multi_value_keywords + ${ARGN} + ) + tribits_check_for_unparsed_arguments(PARSE) + tribits_assert_parse_arg_one_or_more_values(PARSE DEPENDENCIES) + + set(${tplName}_LIB_ALL_DEPENDENCIES ${PARSE_DEPENDENCIES} CACHE STRING + "List of all potential dependencies for external package/TPL '${tplName}'") + mark_as_advanced(${tplName}_LIB_ALL_DEPENDENCIES) + +endmacro() +# +# NOTE: Above, we use a cache var for ${tplName}_LIB_ALL_DEPENDENCIES to allow +# the user to override what dependencies a TPL can depend on. Since this does +# not depend on what actual TPLs are enabled, it is okay to set this as a +# cache var. As with any genetic change to a CMakeLists.txt file, you always +# need to blow a way the cache and configure from scratch to get a correct +# configuration. (Only some types of changes to CMakeLists.txt files allow +# for correct reconfiguration.) + + +# @MACRO: tribits_extpkg_setup_enabled_dependencies() +# +# Usage:: +# +# tribits_extpkg_setup_enabled_dependencies() +# +# Macro that sets up the list of enabled external package/TPL dependencies +# +# Takes the list ``_LIB_ALL_DEPENDENCIES`` and sets the +# default entries of the non-cache var +# ``_LIB_ENABLED_DEPENDENCIES``. However, if +# ``${_LIB_ALL_DEPENDENCIES}`` is non-empty when this macro +# is called, then it will not be changed. That allows the user to override +# the list of enabled TPL dependencies in the cache. This also sets the +# non-cache vars ``_ENABLE_=ON`` for each +# enabled package listed in ``_LIB_ENABLED_DEPENDENCIES`` and +# to ``OFF`` for each ```` listed in +# ``_LIB_ENABLED_DEPENDENCIES`` but not in +# ``_LIB_ENABLED_DEPENDENCIES``. +# +macro(tribits_extpkg_setup_enabled_dependencies externalPkgName) + + set(libEnabledDependencies "") + + if (TPL_ENABLE_${externalPkgName}) + foreach(upstreamPkgEntry IN LISTS ${externalPkgName}_LIB_ALL_DEPENDENCIES) + tribits_extpkg_get_dep_name_and_vis(${upstreamPkgEntry} + upstreamPkgName upstreamPkgVis) + if (TPL_ENABLE_${upstreamPkgName}) + list(APPEND libEnabledDependencies ${upstreamPkgEntry}) + else() + set(${externalPkgName}_ENABLE_${upstreamPkgName} OFF) + endif() + endforeach() + endif() + + if ("${${externalPkgName}_LIB_ENABLED_DEPENDENCIES}" STREQUAL "") + # Only set of not already set as a cache var, for example + set(${externalPkgName}_LIB_ENABLED_DEPENDENCIES ${libEnabledDependencies}) + endif() + + foreach(upstreamPkgEntry IN LISTS ${externalPkgName}_LIB_ENABLED_DEPENDENCIES) + tribits_extpkg_get_dep_name_and_vis( ${upstreamPkgEntry} + upstreamPkgName upstreamPkgVis) + set(${externalPkgName}_ENABLE_${upstreamPkgName} ON) + endforeach() + +endmacro() +# +# NOTE: Above we set ${externalPkgName}_LIB_ENABLED_DEPENDENCIES as a regular +# project-level variable, not as a cache var. That is because we want it to +# update when the set of enabled TPLs changes without having to reconfigure +# from scratch. However, we use the if statement to allow the user to +# override the default logic on the dependencies for an enabled TPL. + + +# @FUNCTION: tribits_extpkg_get_dep_name_and_vis() +# +# Extract ```` and ```` from ``[:]`` input with +# default ```` of ``PRIVATE``. +# +# Usage:: +# +# tribits_extpkg_get_dep_name_and_vis( +# ) +# +function(tribits_extpkg_get_dep_name_and_vis + upstreamTplDepEntry upstreamTplDepNameOut upstreamTplDepVisOut + ) + # Split on ':' to get [:] + string(REPLACE ":" ";" upstreamTplAndVisList "${upstreamTplDepEntry}") + list(LENGTH upstreamTplAndVisList upstreamTplAndVisListLen) + # Validate one or two entries only + if (upstreamTplAndVisListLen GREATER 2) + math(EXPR numColons "${upstreamTplAndVisListLen}-1") + message_wrapper(FATAL_ERROR + "ERROR: '${upstreamTplDepEntry}' has ${numColons} ':' but only 1 is allowed!") + endif() + # Set + list(GET upstreamTplAndVisList 0 upstreamTplDepName) + # Set + if (upstreamTplAndVisListLen EQUAL 2) + list(GET upstreamTplAndVisList 1 upstreamTplDepVis) + else() + set(upstreamTplDepVis PRIVATE) + endif() + # Assert valid + set(validVisValues "PUBLIC" "PRIVATE") + if (NOT upstreamTplDepVis IN_LIST validVisValues) + message_wrapper(FATAL_ERROR + "ERROR: '${upstreamTplDepEntry}' has invalid visibility '${upstreamTplDepVis}'." + " Only 'PUBLIC' or 'PRIVATE' allowed!") + return() # Only executed in unit-test mode! + endif() + # Set outputs + set(${upstreamTplDepNameOut} ${upstreamTplDepName} PARENT_SCOPE) + set(${upstreamTplDepVisOut} ${upstreamTplDepVis} PARENT_SCOPE) +endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake b/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake index 615830b9b94b..cee06a2d8e58 100644 --- a/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake @@ -40,6 +40,7 @@ include(TribitsPackageSetupCompilerFlags) include(TribitsWriteClientExportFiles) include(TribitsGeneralMacros) +include(TribitsLibIsTestOnly) include(CMakeParseArguments) include(GlobalNullSet) @@ -48,6 +49,7 @@ include(PrintVar) include(PrependSet) include(PrependGlobalSet) include(RemoveGlobalDuplicates) +include(TribitsGatherBuildTargets) include(TribitsAddOptionAndDefine) include(TribitsLibraryMacros) @@ -59,17 +61,11 @@ include(TribitsCopyFilesToBinaryDir) include(TribitsReportInvalidTribitsUsage) -### -### WARNING: See "NOTES TO DEVELOPERS" at the bottom of file! -### - - # # Utility macros # -# # Macro that defines the package architecture system variables used to link # different SE packages together # @@ -77,14 +73,11 @@ include(TribitsReportInvalidTribitsUsage) # they are used. # macro(tribits_define_linkage_vars PACKAGE_NAME_IN) - global_null_set(${PACKAGE_NAME_IN}_INCLUDE_DIRS) - global_null_set(${PACKAGE_NAME_IN}_LIBRARY_DIRS) - global_null_set(${PACKAGE_NAME_IN}_LIBRARIES) + global_null_set(${PACKAGE_NAME_IN}_LIBRARIES "") global_set(${PACKAGE_NAME_IN}_HAS_NATIVE_LIBRARIES_TO_INSTALL FALSE) endmacro() -# # Macro that defines variables that create global targets # macro(tribits_define_target_vars PARENT_PACKAGE_NAME_IN) @@ -92,10 +85,9 @@ macro(tribits_define_target_vars PARENT_PACKAGE_NAME_IN) global_null_set(${PARENT_PACKAGE_NAME_IN}_ALL_TARGETS) endmacro() -# + # Set up some common variables used in the creation of an SE package # - macro(tribits_set_common_vars PACKAGE_NAME_IN) string(TOUPPER ${PACKAGE_NAME_IN} PACKAGE_NAME_UC) @@ -111,7 +103,6 @@ macro(tribits_set_common_vars PACKAGE_NAME_IN) endmacro() -# # @MACRO: tribits_package_decl() # # Macro called at the very beginning of a package's top-level @@ -277,7 +268,6 @@ macro(tribits_package_decl PACKAGE_NAME_IN) endmacro() -# # @MACRO: tribits_package_def() # # Macro called in `/CMakeLists.txt`_ after subpackages are @@ -343,7 +333,6 @@ macro(tribits_package_def) endmacro() -# # @MACRO: tribits_package() # # Macro called at the very beginning of a package's top-level @@ -397,7 +386,6 @@ macro(tribits_package PACKAGE_NAME_IN) endmacro() -# # @MACRO: tribits_add_test_directories() # # Macro called to add a set of test directories for an SE package. @@ -471,7 +459,6 @@ endmacro() # -# # @MACRO: tribits_add_debug_option() # # Add the standard cache variable option ``${PACKAGE_NAME}_ENABLE_DEBUG`` for @@ -481,10 +468,12 @@ endmacro() # # tribits_add_debug_option() # -# This option is given the default ``${${PROJECT_NAME}_ENABLE_DEBUG}`` and if -# true, will set the variable ``HAVE_${PACKAGE_NAME_UC}_DEBUG`` (to be used in -# the package's configured header file). This macro is typically called in -# the package's `/CMakeLists.txt`_ file. +# This option is given the default value ``${${PROJECT_NAME}_ENABLE_DEBUG}``, +# and if true, this macro will set the variable +# ``HAVE_${PACKAGE_NAME_UC}_DEBUG`` (to be used in the package's configured +# header file `/cmake/_config.h.in`_). This macro is +# typically called in the package's `/CMakeLists.txt`_ file (see +# the example ``SimpleCxx/CMakeLists.txt``). # macro(tribits_add_debug_option) tribits_add_option_and_define( @@ -505,7 +494,6 @@ macro(tribits_add_enable_teuchos_time_monitor_option) endmacro() -# # @MACRO: tribits_add_show_deprecated_warnings_option() # # Add the standard option ``${PACKAGE_NAME}_SHOW_DEPRECATED_WARNINGS`` for the @@ -551,7 +539,6 @@ macro(tribits_add_eti_support) endmacro() -# # @MACRO: tribits_add_example_directories() # # Macro called to conditionally add a set of example directories for an SE @@ -619,11 +606,9 @@ macro(tribits_add_example_directories) endmacro() -# # Utility function that sets up package linkage linkage variables in case the # package has no libraries. # - function(tribits_package_finalize_dependency_vars) if(${PACKAGE_NAME}_SUBPACKAGES) @@ -631,9 +616,7 @@ function(tribits_package_finalize_dependency_vars) # A package with subpackages should get all of its dependency vars from # its enabled subpackages. - set(PARENT_PACKAGE_INCLUDE_DIRS) - set(PARENT_PACKAGE_LIBRARY_DIRS) - set(PARENT_PACKAGE_LIBRARIES) + set(PARENT_PACKAGE_LIBRARIES "") set(SUBPACKAGE_IDX 0) foreach(TRIBITS_SUBPACKAGE ${${PARENT_PACKAGE_NAME}_SUBPACKAGES}) @@ -642,10 +625,6 @@ function(tribits_package_finalize_dependency_vars) set(SUBPACKAGE_FULLNAME ${PARENT_PACKAGE_NAME}${TRIBITS_SUBPACKAGE}) if (${PROJECT_NAME}_ENABLE_${SUBPACKAGE_FULLNAME}) - prepend_set(PARENT_PACKAGE_INCLUDE_DIRS - ${${SUBPACKAGE_FULLNAME}_INCLUDE_DIRS}) - prepend_set(PARENT_PACKAGE_LIBRARY_DIRS - ${${SUBPACKAGE_FULLNAME}_LIBRARY_DIRS}) prepend_set(PARENT_PACKAGE_LIBRARIES ${${SUBPACKAGE_FULLNAME}_LIBRARIES}) endif() @@ -654,64 +633,29 @@ function(tribits_package_finalize_dependency_vars) endforeach() - if (PARENT_PACKAGE_INCLUDE_DIRS) - list(REMOVE_DUPLICATES PARENT_PACKAGE_INCLUDE_DIRS) - endif() - if (PARENT_PACKAGE_LIBRARY_DIRS) - list(REMOVE_DUPLICATES PARENT_PACKAGE_LIBRARY_DIRS) - endif() - # NOTE: Above, in the rare case that none of the subpackages contain any - # libraries or any include directories, we need to not call - # list(REMOVE_DUPLICATES ...). - # NOTE: There can't be any duplicate libraries in PARENT_PACKAGE_LIBRARIES # so no need to remove them. - - global_set(${PACKAGE_NAME}_INCLUDE_DIRS "${PARENT_PACKAGE_INCLUDE_DIRS}") - global_set(${PACKAGE_NAME}_LIBRARY_DIRS "${PARENT_PACKAGE_LIBRARY_DIRS}") global_set(${PACKAGE_NAME}_LIBRARIES "${PARENT_PACKAGE_LIBRARIES}") - elseif(NOT ${PACKAGE_NAME}_INCLUDE_DIRS) - - # No libraries have been defined for this package so we are going to set - # them based on this package's dependencies. - - tribits_sort_and_append_package_include_and_link_dirs_and_libs( - ${PACKAGE_NAME} LIB LINK_LIBS) - - tribits_sort_and_append_tpl_include_and_link_dirs_and_libs( - ${PACKAGE_NAME} LIB LINK_LIBS) - - get_directory_property(INCLUDE_DIRS_CURRENT INCLUDE_DIRECTORIES) - get_directory_property(LIBRARY_DIRS_CURRENT PACKAGE_LIBRARY_DIRS) - - prepend_global_set(${PACKAGE_NAME}_INCLUDE_DIRS ${INCLUDE_DIRS_CURRENT}) - prepend_global_set(${PACKAGE_NAME}_LIBRARY_DIRS ${LIBRARY_DIRS_CURRENT}) - prepend_global_set(${PACKAGE_NAME}_LIBRARIES ${LINK_LIBS}) - endif() endfunction() -# # Helper macro for [SUB]tribits_package_postprocess() # macro(tribits_package_postprocess_common) if (${PROJECT_NAME}_VERBOSE_CONFIGURE) message("\nTRIBITS_PACKAGE_POSTPROCESS_COMMON: ${PACKAGE_NAME}") - print_var(${PACKAGE_NAME}_INCLUDE_DIRS) - print_var(${PACKAGE_NAME}_LIBRARY_DIRS) print_var(${PACKAGE_NAME}_LIBRARIES) endif() - if (${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES OR - ${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES - ) + tribits_package_create_all_libs_interface_library() + + if (${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES) # Create the configure file so external projects can find packages with a - # call to find_package(). This also creates the - # Makefile.export.* files. + # call to find_package(). tribits_write_package_client_export_files(${PACKAGE_NAME}) endif() @@ -721,7 +665,64 @@ macro(tribits_package_postprocess_common) endmacro() +# Macro to create the ${PACKAGE_NAME}::all_libs INTERFACE target # +macro(tribits_package_create_all_libs_interface_library) + + if (NOT TARGET ${PACKAGE_NAME}_all_libs) + + # Find all of the non-TESTONLY library targets + tribits_get_all_build_targets_including_in_subdirs("${CMAKE_CURRENT_SOURCE_DIR}" + "STATIC_LIBRARY;SHARED_LIBRARY" + allPackageBuildableLibTargetsList ) + #print_var(allPackageBuildableLibTargetsList) + set(packageLibsInAllLibsList) + foreach (libTarget IN LISTS allPackageBuildableLibTargetsList) + tribits_lib_is_testonly(${libTarget} isTestOnlyLib) + #print_var(isTestOnlyLib) + if (NOT isTestOnlyLib) + list(APPEND packageLibsInAllLibsList ${libTarget}) + endif() + endforeach() + global_set(${PACKAGE_NAME}_EXPORTED_PACKAGE_LIBS_NAMES + ${packageLibsInAllLibsList}) + + # Create the ${PACKAGE_NAME}_all_libs INTERFACE interface target + add_library(${PACKAGE_NAME}_all_libs INTERFACE) + target_link_libraries(${PACKAGE_NAME}_all_libs + INTERFACE ${packageLibsInAllLibsList} ) + set_target_properties(${PACKAGE_NAME}_all_libs PROPERTIES + EXPORT_NAME all_libs) + if (${PROJECT_NAME}_IMPORTED_NO_SYSTEM) + set_target_properties(${PACKAGE_NAME}_all_libs PROPERTIES IMPORTED_NO_SYSTEM TRUE) + endif() + + # Install the interface target (makes sure it gets put in + # Targets.cmake file) + install( + TARGETS ${PACKAGE_NAME}_all_libs + EXPORT ${PACKAGE_NAME} + INCLUDES DESTINATION "${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}" + RUNTIME DESTINATION "${${PROJECT_NAME}_INSTALL_RUNTIME_DIR}" + LIBRARY DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}" + ARCHIVE DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}" + COMPONENT ${PACKAGE_NAME} + ) + + if (NOT TARGET ${PACKAGE_NAME}::all_libs) + # Create ALIAS ${PACKAGE_NAME}::all_libs target + add_library(${PACKAGE_NAME}::all_libs ALIAS ${PACKAGE_NAME}_all_libs) + endif() + + endif() + + #include(CMakePrintHelpers) + #cmake_print_properties(TARGETS ${PACKAGE_NAME}_all_libs ${PACKAGE_NAME}::all_libs + # PROPERTIES TYPE ALIASED_TARGET INTERFACE_LINK_LIBRARIES) + +endmacro() + + # @MACRO: tribits_package_postprocess() # # Macro called at the very end of a package's top-level @@ -732,7 +733,11 @@ endmacro() # # tribits_package_postprocess() # -# NOTE: It is unfortunate that this macro must be called in a packages's +# NOTE: This creates the aliased target ``${PACKAGE_NAME}::all_libs`` for all +# libraries in all subdirectories that don't have the TRIBITS_TESTONLY_LIB +# target property set on them. +# +# NOTE: It is unfortunate that this macro must be called in a package's # top-level ``CMakeLists.txt`` file but limitations of the CMake language make # it necessary to do so. # @@ -828,7 +833,6 @@ macro(tribits_package_postprocess) endmacro() -# # @MACRO: tribits_process_subpackages() # # Macro that processes the `TriBITS Subpackages`_ for a parent `TriBITS @@ -917,25 +921,3 @@ macro(tribits_process_subpackages) set(${PACKAGE_NAME}_TRIBITS_PROCESS_SUBPACKAGES_CALLED TRUE) endmacro() - - -################################################################## -# -# NOTES TO DEVELOPERS -# -# Don't even attempt to touch the logic that goes into setting up and -# modifying the variables: -# -# ${PACKAGE_NAME}_INCLUDE_DIRS -# ${PACKAGE_NAME}_LIBRARY_DIRS -# ${PACKAGE_NAME}_LIBRARIES -# ${PACKAGE_NAME}_HAS_NATIVE_LIBRARIES_TO_INSTALL -# ${PACKAGE_NAME}_FULL_ENABLED_DEP_PACKAGES -# ${PARENT_PACKAGE_NAME}_LIB_TARGETS -# ${PARENT_PACKAGE_NAME}_ALL_TARGETS -# -# without carefully studying the documentation in README.DEPENDENCIES and then -# carefully studying all of the code and issues that modify these variables! -# -# ToDo: Write some good unit tests that pin down the behavior of all of this! -# diff --git a/cmake/tribits/core/package_arch/TribitsPrintEnabledPackagesLists.cmake b/cmake/tribits/core/package_arch/TribitsPrintEnabledPackagesLists.cmake new file mode 100644 index 000000000000..c1fd99ba4c83 --- /dev/null +++ b/cmake/tribits/core/package_arch/TribitsPrintEnabledPackagesLists.cmake @@ -0,0 +1,172 @@ +# @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_print_enables_before_adjust_package_enables() +# +# Call this to print the package enables before calling +# tribits_adjust_package_enables(). +# +# Usage:: +# +# tribits_print_enables_before_adjust_package_enables() +# +function(tribits_print_enables_before_adjust_package_enables) + tribits_print_enabled_package_list( + "\nExplicitly enabled packages on input (by user)" ON FALSE) + tribits_print_enabled_se_package_list( + "\nExplicitly enabled SE packages on input (by user)" ON FALSE) + tribits_print_enabled_package_list( + "\nExplicitly disabled packages on input (by user or by default)" OFF FALSE) + tribits_print_enabled_se_package_list( + "\nExplicitly disabled SE packages on input (by user or by default)" OFF FALSE) + tribits_print_enabled_tpl_list( + "\nExplicitly enabled TPLs on input (by user)" ON FALSE) + tribits_print_enabled_tpl_list( + "\nExplicitly disabled TPLs on input (by user or by default)" OFF FALSE) +endfunction() + + +# @FUNCTION: tribits_print_enables_after_adjust_package_enables() +# +# Call this to print the package enables before calling +# tribits_adjust_package_enables(). +# +# Usage:: +# +# 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 packages" "${${PROJECT_NAME}_ENABLED_PACKAGES}") + tribits_print_prefix_string_and_list( + "\nFinal set of enabled SE packages" "${${PROJECT_NAME}_ENABLED_SE_PACKAGES}") + tribits_print_enabled_package_list( + "\nFinal set of non-enabled packages" OFF TRUE) + tribits_print_enabled_se_package_list( + "\nFinal set of non-enabled SE packages" OFF TRUE) + tribits_print_enabled_tpl_list( + "\nFinal set of enabled TPLs" ON FALSE) + tribits_print_enabled_tpl_list( + "\nFinal set of non-enabled TPLs" OFF TRUE) +endfunction() + + +# Function that prints the current set of enabled/disabled packages +# +function(tribits_print_enabled_package_list DOCSTRING ENABLED_FLAG INCLUDE_EMPTY) + tribits_print_enabled_packages_list_from_var( ${PROJECT_NAME}_PACKAGES + "${DOCSTRING}" ${ENABLED_FLAG} ${INCLUDE_EMPTY} ) +endfunction() + + +# Prints the current set of enabled/disabled SE packages +# +function(tribits_print_enabled_se_package_list DOCSTRING ENABLED_FLAG INCLUDE_EMPTY) + if (ENABLED_FLAG AND NOT INCLUDE_EMPTY) + tribits_get_enabled_list( ${PROJECT_NAME}_SE_PACKAGES ${PROJECT_NAME} + ENABLED_SE_PACKAGES NUM_ENABLED) + elseif (ENABLED_FLAG AND INCLUDE_EMPTY) + tribits_get_nondisabled_list( ${PROJECT_NAME}_SE_PACKAGES ${PROJECT_NAME} + ENABLED_SE_PACKAGES NUM_ENABLED) + elseif (NOT ENABLED_FLAG AND NOT INCLUDE_EMPTY) + tribits_get_disabled_list( ${PROJECT_NAME}_SE_PACKAGES ${PROJECT_NAME} + ENABLED_SE_PACKAGES NUM_ENABLED) + else() # NOT ENABLED_FLAG AND INCLUDE_EMPTY + tribits_get_nonenabled_list( ${PROJECT_NAME}_SE_PACKAGES ${PROJECT_NAME} + ENABLED_SE_PACKAGES NUM_ENABLED) + endif() + tribits_print_prefix_string_and_list("${DOCSTRING}" "${ENABLED_SE_PACKAGES}") +endfunction() + + +# Print the current set of enabled/disabled TPLs +# +function(tribits_print_enabled_tpl_list DOCSTRING ENABLED_FLAG INCLUDE_EMPTY) + if (ENABLED_FLAG AND NOT INCLUDE_EMPTY) + tribits_get_enabled_list( ${PROJECT_NAME}_TPLS TPL + ENABLED_TPLS NUM_ENABLED) + elseif (ENABLED_FLAG AND INCLUDE_EMPTY) + tribits_get_nondisabled_list( ${PROJECT_NAME}_TPLS TPL + ENABLED_TPLS NUM_ENABLED) + elseif (NOT ENABLED_FLAG AND NOT INCLUDE_EMPTY) + tribits_get_disabled_list( ${PROJECT_NAME}_TPLS TPL + ENABLED_TPLS NUM_ENABLED) + else() # NOT ENABLED_FLAG AND INCLUDE_EMPTY + tribits_get_nonenabled_list( ${PROJECT_NAME}_TPLS TPL + ENABLED_TPLS NUM_ENABLED) + endif() + tribits_print_prefix_string_and_list("${DOCSTRING}" "${ENABLED_TPLS}") +endfunction() + + +# Print the current set of enabled/disabled packages given input list of +# packages +# +function(tribits_print_enabled_packages_list_from_var PACKAGES_LIST_VAR + DOCSTRING ENABLED_FLAG INCLUDE_EMPTY + ) + if (ENABLED_FLAG AND NOT INCLUDE_EMPTY) + tribits_get_enabled_list(${PACKAGES_LIST_VAR} ${PROJECT_NAME} + ENABLED_PACKAGES NUM_ENABLED) + elseif (ENABLED_FLAG AND INCLUDE_EMPTY) + tribits_get_nondisabled_list(${PACKAGES_LIST_VAR} ${PROJECT_NAME} + ENABLED_PACKAGES NUM_ENABLED) + elseif (NOT ENABLED_FLAG AND NOT INCLUDE_EMPTY) + tribits_get_disabled_list(${PACKAGES_LIST_VAR} ${PROJECT_NAME} + ENABLED_PACKAGES NUM_ENABLED) + else() # NOT ENABLED_FLAG AND INCLUDE_EMPTY + tribits_get_nonenabled_list(${PACKAGES_LIST_VAR} ${PROJECT_NAME} + ENABLED_PACKAGES NUM_ENABLED) + endif() + tribits_print_prefix_string_and_list("${DOCSTRING}" "${ENABLED_PACKAGES}") +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}") + else() + message("${DOCSTRING}: ${NUM_ELEMENTS}") + endif() +endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsProcessEnabledTpl.cmake b/cmake/tribits/core/package_arch/TribitsProcessEnabledTpl.cmake index dd4eece4a5cf..c8cbdb4a90a6 100644 --- a/cmake/tribits/core/package_arch/TribitsProcessEnabledTpl.cmake +++ b/cmake/tribits/core/package_arch/TribitsProcessEnabledTpl.cmake @@ -39,6 +39,8 @@ # Standard TriBITS Includes +include(TribitsExternalPackageFindTplHelpers) +include(TribitsExternalPackageWriteConfigFile) include(TribitsTplFindIncludeDirsAndLibraries) include(TribitsGeneralMacros) @@ -47,7 +49,6 @@ include(AppendStringVar) include(TribitsStandardizePaths) -# # @FUNCTION: tribits_process_enabled_tpl() # # Process an enabled TPL's FindTPL${TPL_NAME}.cmake module. @@ -57,13 +58,13 @@ function(tribits_process_enabled_tpl TPL_NAME) # Setup the processing string set(PROCESSING_MSG_STRING "Processing enabled TPL: ${TPL_NAME} (") if (TPL_${TPL_NAME}_ENABLING_PKG) - append_string_var(PROCESSING_MSG_STRING + string(APPEND PROCESSING_MSG_STRING "enabled by ${TPL_${TPL_NAME}_ENABLING_PKG}," ) else() - append_string_var(PROCESSING_MSG_STRING + string(APPEND PROCESSING_MSG_STRING "enabled explicitly," ) endif() - append_string_var(PROCESSING_MSG_STRING + string(APPEND PROCESSING_MSG_STRING " disable with -DTPL_ENABLE_${TPL_NAME}=OFF)" ) # Print the processing header @@ -75,22 +76,14 @@ function(tribits_process_enabled_tpl TPL_NAME) if (${PROJECT_NAME}_VERBOSE_CONFIGURE) print_var(${TPL_NAME}_FINDMOD) endif() - #print_var(${TPL_NAME}_FINDMOD) 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) - #print_var(${TPL_NAME}_INCLUDE_DIRS) - #print_var(${TPL_NAME}_LIBRARIES) - tribits_standardize_abs_paths(THIS_TPL_INCLUDE_DIRS - ${${TPL_NAME}_INCLUDE_DIRS} ${${TPL_NAME}_TPL_INCLUDE_DIRS}) - global_set(TPL_${TPL_NAME}_INCLUDE_DIRS ${THIS_TPL_INCLUDE_DIRS}) global_set(TPL_${TPL_NAME}_LIBRARIES "${${TPL_NAME}_LIBRARIES}" "${${TPL_NAME}_TPL_LIBRARIES}") global_set(TPL_${TPL_NAME}_PARTS_ALREADY_SET TRUE) endif() - #print_var(TPL_${TPL_NAME}_INCLUDE_DIRS) - #print_var(TPL_${TPL_NAME}_LIBRARIES) return() elseif (IS_ABSOLUTE ${${TPL_NAME}_FINDMOD}) #message("${${TPL_NAME}_FINDMOD} is absolute!") @@ -103,7 +96,18 @@ function(tribits_process_enabled_tpl TPL_NAME) # 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) @@ -145,12 +149,19 @@ function(tribits_process_enabled_tpl TPL_NAME) "ERROR: TPL_${TPL_NAME}_NOT_FOUND=${TPL_${TPL_NAME}_NOT_FOUND}, aborting!") endif() - # Assert that the TPL correctly defined all of these variables - assert_defined(TPL_${TPL_NAME}_INCLUDE_DIRS) - assert_defined(TPL_${TPL_NAME}_LIBRARIES) - assert_defined(TPL_${TPL_NAME}_LIBRARY_DIRS) - # ToDo: Make TPL_${TPL_NAME}_LIBRARY_DIRS go away. It is not needed for - # anything. + # 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() diff --git a/cmake/tribits/core/package_arch/TribitsProcessExtraRepositoriesList.cmake b/cmake/tribits/core/package_arch/TribitsProcessExtraRepositoriesList.cmake index 01b7b5274cb1..d9bdf527f03b 100644 --- a/cmake/tribits/core/package_arch/TribitsProcessExtraRepositoriesList.cmake +++ b/cmake/tribits/core/package_arch/TribitsProcessExtraRepositoriesList.cmake @@ -47,7 +47,6 @@ include(MessageWrapper) include(TribitsSortListAccordingToMasterList) -# # @MACRO: tribits_project_define_extra_repositories() # # Declare a set of extra repositories for the `TriBITS Project`_ (i.e. in the diff --git a/cmake/tribits/core/package_arch/TribitsProcessPackagesAndDirsLists.cmake b/cmake/tribits/core/package_arch/TribitsProcessPackagesAndDirsLists.cmake index 0987844d45e8..92e5175e1b37 100644 --- a/cmake/tribits/core/package_arch/TribitsProcessPackagesAndDirsLists.cmake +++ b/cmake/tribits/core/package_arch/TribitsProcessPackagesAndDirsLists.cmake @@ -557,6 +557,7 @@ macro(tribits_process_packages_and_dirs_lists REPOSITORY_NAME REPOSITORY_DIR) list(APPEND ${PROJECT_NAME}_PACKAGES ${TRIBITS_PACKAGE}) tribits_insert_standard_package_options(${TRIBITS_PACKAGE} ${PACKAGE_TESTGROUP}) + set(${TRIBITS_PACKAGE}_PACKAGE_BUILD_STATUS INTERNAL) set(${TRIBITS_PACKAGE}_SOURCE_DIR "${PROJECT_SOURCE_DIR}/${REPOSITORY_AND_PACKAGE_DIR}") set(${TRIBITS_PACKAGE}_REL_SOURCE_DIR diff --git a/cmake/tribits/core/package_arch/TribitsProcessTplsLists.cmake b/cmake/tribits/core/package_arch/TribitsProcessTplsLists.cmake index 4009ac400928..f4a66094b82c 100644 --- a/cmake/tribits/core/package_arch/TribitsProcessTplsLists.cmake +++ b/cmake/tribits/core/package_arch/TribitsProcessTplsLists.cmake @@ -44,7 +44,7 @@ include(TribitsListHelpers) include(PrintVar) include(Split) -# + # @MACRO: tribits_repository_define_tpls() # # Define the list of `TriBITS TPLs`_ for a given `TriBITS Repository`_ which @@ -74,13 +74,13 @@ include(Split) # ``SOMETPL``). # # 1. **FINDMOD** (````): The relative path for the find module, -# usually with the name ``FindTPL.cmake``. This path is 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 (e.g. ``cmake/tpls/FindTPL.cmake``). A standard -# way to write a ``FindTPL.cmake`` module is to use the function -# `tribits_tpl_find_include_dirs_and_libraries()`_. +# usually with the name `FindTPL.cmake`_. This path is 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`_.) # # 2. **CLASSIFICATION** (````): Gives the `SE Package Test # Group`_ `PT`_, `ST`_, or `EX`_ and the maturity level ``EP``, ``RS``, @@ -130,13 +130,15 @@ endmacro() # and updates the project-level variables:: # # ${PROJECT_NAME}_TPLS -# ${PROJECT_NAME}_NUM_TPLS, +# ${PROJECT_NAME}_NUM_TPLS # ${PROJECT_NAME}_REVERSE_TPLS # # For each TPL, it also sets the variables:: # # ${TPL_NAME}_FINDMOD # ${TPL_NAME}_TESTGROUP +# ${TPL_NAME}_DEPENDENCIES_FILE +# ${TPL_NAME}_TPLS_LIST_FILE # # See `Function call tree for constructing package dependency graph`_ # @@ -215,6 +217,10 @@ macro(tribits_process_tpls_lists REPOSITORY_NAME REPOSITORY_DIR) list(APPEND ${PROJECT_NAME}_TPLS ${TPL_NAME}) endif() + # Set ${TPL_NAME}_PACKAGE_BUILD_STATUS + + SET(${TPL_NAME}_PACKAGE_BUILD_STATUS EXTERNAL) + # Set ${TPL_NAME}_TESTGROUP if (TPL_TESTGROUP STREQUAL PT @@ -233,23 +239,18 @@ macro(tribits_process_tpls_lists REPOSITORY_NAME REPOSITORY_DIR) # Set ${TPL_NAME}_FINDMOD - #print_var(REPOSITORY_DIR) - if ("${REPOSITORY_DIR}" STREQUAL "." OR IS_ABSOLUTE ${TPL_FINDMOD}) set(REPOSITORY_DIR_AND_SEP "") else() set(REPOSITORY_DIR_AND_SEP "${REPOSITORY_DIR}/") endif() - #print_var(REPOSITORY_DIR_AND_SEP) set(TPL_FINDMOD "${REPOSITORY_DIR_AND_SEP}${TPL_FINDMOD}") - #print_var(TPL_FINDMOD) set(TPL_FINDMOD_STD_NAME "FindTPL${TPL_NAME}.cmake") if (TPL_FINDMOD) string(REGEX MATCH ".+/$" FINDMOD_IS_DIR "${TPL_FINDMOD}") - #print_var(FINDMOD_IS_DIR) if (FINDMOD_IS_DIR) set(${TPL_NAME}_FINDMOD "${TPL_FINDMOD}${TPL_FINDMOD_STD_NAME}") else() @@ -259,16 +260,31 @@ macro(tribits_process_tpls_lists REPOSITORY_NAME REPOSITORY_DIR) set(${TPL_NAME}_FINDMOD ${TPL_FINDMOD_STD_NAME}) endif() + # Set ${TPL_NAME}_DEPENDENCIES_FILE + + # Breakdown ${${TPL_NAME}_FINDMOD} into parts /. + get_filename_component(tpl_findmod_dir ${${TPL_NAME}_FINDMOD} DIRECTORY) + get_filename_component(tpl_findmod_base ${${TPL_NAME}_FINDMOD} NAME_WLE) + get_filename_component(tpl_findmod_ext ${${TPL_NAME}_FINDMOD} LAST_EXT) + + set(${TPL_NAME}_DEPENDENCIES_FILE + "${tpl_findmod_dir}/${tpl_findmod_base}Dependencies${tpl_findmod_ext}") + + # Set ${TPL_NAME}_TPLS_LIST_FILE + assert_defined(${REPOSITORY_NAME}_TPLS_FILE) set(${TPL_NAME}_TPLS_LIST_FILE ${${REPOSITORY_NAME}_TPLS_FILE}) - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - print_var(${TPL_NAME}_FINDMOD) + # Print variables/properties for the TPL + + if (${PROJECT_NAME}_VERBOSE_CONFIGURE OR TRIBITS_PROCESS_TPLS_LISTS_VERBOSE) print_var(${TPL_NAME}_TESTGROUP) + print_var(${TPL_NAME}_FINDMOD) + print_var(${TPL_NAME}_DEPENDENCIES_FILE) print_var(${TPL_NAME}_TPLS_LIST_FILE) endif() - # Set the enable cache variable for ${TPL_NAME} + # Set cache var TPL_ENABLE_${TPL_NAME} with default "" multiline_set(DOCSTR "Enable support for the TPL ${TPL_NAME} in all supported ${PROJECT_NAME} packages." @@ -278,8 +294,9 @@ macro(tribits_process_tpls_lists REPOSITORY_NAME REPOSITORY_DIR) # 2008/11/25: rabartl: Above, we use the prefix TPL_ instead of # ${PROJECT_NAME}_ in order to make it clear that external TPLs are - # different from packages so users don't get confused and - # think that the project actually includes some TPL when it does not! + # different from packages so users don't get confused and think that the + # project actually includes the source code and internal build for some + # TPL when it does not! endforeach() diff --git a/cmake/tribits/core/package_arch/TribitsProject.cmake b/cmake/tribits/core/package_arch/TribitsProject.cmake index c1e3837aa639..035e089e3ad1 100644 --- a/cmake/tribits/core/package_arch/TribitsProject.cmake +++ b/cmake/tribits/core/package_arch/TribitsProject.cmake @@ -66,11 +66,10 @@ if (${PROJECT_NAME}_VERBOSE_CONFIGURE) endif() # Overrides that we have for CMake functions -include(TribitsCMakePolicies) +include(TribitsCMakePolicies NO_POLICY_SCOPE) include(TribitsProjectImpl) -# # @MACRO: tribits_project() # # Processes a `TriBITS Project`_'s files and configures its software which is diff --git a/cmake/tribits/core/package_arch/TribitsProjectImpl.cmake b/cmake/tribits/core/package_arch/TribitsProjectImpl.cmake index 62ff4e883e0f..dfb8a60b41d3 100644 --- a/cmake/tribits/core/package_arch/TribitsProjectImpl.cmake +++ b/cmake/tribits/core/package_arch/TribitsProjectImpl.cmake @@ -59,13 +59,14 @@ endif() include(TribitsConstants) tribits_asesrt_minimum_cmake_version() -include(TribitsCMakePolicies) +include(TribitsCMakePolicies NO_POLICY_SCOPE) include(TribitsIncludeDirectories) include(TribitsFindPythonInterp) include(TribitsGlobalMacros) include(TribitsConfigureCTestCustom) include(TribitsGenerateResourceSpecFile) +include(TribitsPackageDependencies) include(TribitsPrintDependencyInfo) include(AdvancedSet) @@ -323,7 +324,6 @@ macro(tribits_project_impl) endmacro() -# # @MACRO: tribits_project_enable_all() # # Process a project where you enable all of the packages by default. diff --git a/cmake/tribits/core/package_arch/TribitsReadDepsFilesCreateDepsGraph.cmake b/cmake/tribits/core/package_arch/TribitsReadDepsFilesCreateDepsGraph.cmake index c344680041de..803dca88b248 100644 --- a/cmake/tribits/core/package_arch/TribitsReadDepsFilesCreateDepsGraph.cmake +++ b/cmake/tribits/core/package_arch/TribitsReadDepsFilesCreateDepsGraph.cmake @@ -179,17 +179,21 @@ endmacro() # macro(tribits_read_all_package_deps_files_create_deps_graph) - set(${PROJECT_NAME}_SE_PACKAGES) # Packages and subpackages + foreach(tribitsExternalPkg IN LISTS ${PROJECT_NAME}_DEFINED_TPLS) + tribits_read_external_package_deps_files_add_to_graph(${tribitsExternalPkg}) + endforeach() + + set(${PROJECT_NAME}_SE_PACKAGES "") # Packages and subpackages - foreach(TRIBITS_PACKAGE ${${PROJECT_NAME}_PACKAGES}) + foreach(TRIBITS_PACKAGE IN LISTS ${PROJECT_NAME}_PACKAGES) tribits_read_toplevel_package_deps_files_add_to_graph(${TRIBITS_PACKAGE} ${${TRIBITS_PACKAGE}_REL_SOURCE_DIR}) endforeach() # Create a reverse SE packages list for later use - set(${PROJECT_NAME}_REVERSE_SE_PACKAGES ${${PROJECT_NAME}_SE_PACKAGES}) + set(${PROJECT_NAME}_REVERSE_SE_PACKAGES ${${PROJECT_NAME}_SE_PACKAGES}) if (${PROJECT_NAME}_REVERSE_SE_PACKAGES) - list(REVERSE ${PROJECT_NAME}_REVERSE_SE_PACKAGES) + list(REVERSE ${PROJECT_NAME}_REVERSE_SE_PACKAGES) endif() list(LENGTH ${PROJECT_NAME}_SE_PACKAGES ${PROJECT_NAME}_NUM_SE_PACKAGES) @@ -198,11 +202,36 @@ macro(tribits_read_all_package_deps_files_create_deps_graph) endmacro() +# @MACRO: tribits_read_external_package_deps_files_add_to_graph() +# +# Reads in dependencies for the external packages/TPL ```` and +# creates the package dependency graph entries for it. +# +# Usage:: +# +# tribits_read_external_package_deps_files_add_to_graph() +# +# This reads in the file ``${_DEPENDENCIES_FILE}`` and sets the +# varaible:: +# +# _LIB_ALL_DEPENDENCIES +# +# See `Function call tree for constructing package dependency graph`_ +# +macro(tribits_read_external_package_deps_files_add_to_graph tplName) + set(absTplDepsFile "${${PROJECT_NAME}_SOURCE_DIR}/${${tplName}_DEPENDENCIES_FILE}") + if (EXISTS "${absTplDepsFile}") + tribits_trace_file_processing(TPL INCLUDE "${absTplDepsFile}") + include(${absTplDepsFile}) + endif() +endmacro() + + # @MACRO: tribits_read_toplevel_package_deps_files_add_to_graph() # # Usage:: # -# tribits_read_toplevel_package_deps_files_add_to_graph() +# tribits_read_toplevel_package_deps_files_add_to_graph() # # Macro that reads in package dependencies for a top-level package from the # file `/cmake/Dependencies.cmake`_ and appends the forward @@ -476,7 +505,7 @@ function(tribits_set_dep_packages PACKAGE_NAME LIB_OR_TEST REQUIRED_OR_OPTIO endif() set(LIST_TYPE ${LIB_OR_TEST}_${REQUIRED_OR_OPTIONAL}_DEP_PACKAGES) - set(PACKAGE_DEPS_LIST) + set(PACKAGE_DEPS_LIST "") set(SE_PACKAGE_ENABLE_VAR ${PROJECT_NAME}_ENABLE_${PACKAGE_NAME}) foreach(DEP_PKG ${${LIST_TYPE}}) @@ -810,6 +839,8 @@ macro(tribits_parse_subpackages_append_se_packages_add_options print_var(${SUBPACKAGE_FULLNAME}_PARENT_REPOSITORY) endif() + set(${SUBPACKAGE_FULLNAME}_PACKAGE_BUILD_STATUS INTERNAL) + # Set up the input options for this subpackage tribits_insert_standard_package_options(${SUBPACKAGE_FULLNAME} ${SUBPACKAGE_TESTGROUP}) diff --git a/cmake/tribits/core/package_arch/TribitsReportInvalidTribitsUsage.cmake b/cmake/tribits/core/package_arch/TribitsReportInvalidTribitsUsage.cmake index 4db279fd387e..442a4928fbcd 100644 --- a/cmake/tribits/core/package_arch/TribitsReportInvalidTribitsUsage.cmake +++ b/cmake/tribits/core/package_arch/TribitsReportInvalidTribitsUsage.cmake @@ -37,11 +37,7 @@ # ************************************************************************ # @HEADER -if (__TribitsReportInvalidTribitsUsage_INCLUDED__) - return() -else() - set(__TribitsReportInvalidTribitsUsage_INCLUDED__ TRUE) -endif() +include_guard() include(MessageWrapper) diff --git a/cmake/tribits/core/package_arch/TribitsSubPackageMacros.cmake b/cmake/tribits/core/package_arch/TribitsSubPackageMacros.cmake index 19afd7ddd3bf..60a7c668e9a5 100644 --- a/cmake/tribits/core/package_arch/TribitsSubPackageMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsSubPackageMacros.cmake @@ -150,6 +150,10 @@ endfunction() # # tribits_subpackage_postprocess() # +# NOTE: This creates the aliased target ``${PACKAGE_NAME}::all_libs`` for all +# libraries in all subdirectories that don't have the TRIBITS_TESTONLY_LIB +# target property set on them. +# # NOTE: It is unfortunate that a Subpackages's CMakeLists.txt file must call # this macro but limitations of the CMake language make it necessary to do so. # diff --git a/cmake/tribits/core/package_arch/TribitsSystemDataStructuresMacrosFunctions.rst b/cmake/tribits/core/package_arch/TribitsSystemDataStructuresMacrosFunctions.rst index 00cdb56c7ee7..bcf012bdd97f 100644 --- a/cmake/tribits/core/package_arch/TribitsSystemDataStructuresMacrosFunctions.rst +++ b/cmake/tribits/core/package_arch/TribitsSystemDataStructuresMacrosFunctions.rst @@ -10,13 +10,19 @@ graph of external packages (i.e. TPLs) and internal packages (i.e. buildable CMake packages). This information is meant for maintainers of the TriBITS system itself and should not need to be known by TriBITS Project maintainers. -In addition to the variables listed below are the variables documented in: +Basic TriBITS Project, Repository, Package, and Subpackage Core Variables ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +The basic variables that define a TriBITS Project, Repository, Package and +Subpackage are listed at the below links: * `TriBITS Project Core Variables`_ * `TriBITS Repository Core Variables`_ * `TriBITS Package Core Variables`_ * `TriBITS Subpackage Core Variables`_ +These are variables that can be accessed by `TriBITS Project Developers`_ but +are also used in the internal implementation of TriBITS functionality. Lists of external and internal packages +++++++++++++++++++++++++++++++++++++++ @@ -66,7 +72,7 @@ out on the system as pre-built/pre-installed packages using ``find_package()``. The final decision for if a package is treated as an internal or external package is determined by the variable:: - ${PACKAGE_NAME}_PACKAGE_STATUS=[INTERNAL|EXTERNAL] + ${PACKAGE_NAME}_PACKAGE_BUILD_STATUS=[INTERNAL|EXTERNAL] which gets set various criteria as described in section `Determining if a package is internal or external`_. This variable determines what @@ -201,16 +207,22 @@ a package's `/cmake/Dependencies.cmake`_ file. (These lists should **not** contain any *indirect* dependencies as the dependency system already handles these automatically.) + .. _${PACKAGE_NAME}_LIB_REQUIRED_DEP_PACKAGES: + ``${PACKAGE_NAME}_LIB_REQUIRED_DEP_PACKAGES`` List of *direct* package dependencies that are required for the libraries and non-test executables built by ``${PACKAGE_NAME}``. + .. _${PACKAGE_NAME}_LIB_OPTIONAL_DEP_PACKAGES: + ``${PACKAGE_NAME}_LIB_OPTIONAL_DEP_PACKAGES`` List of *direct* package dependencies that are only optional for the libraries and non-test executables built by ``${PACKAGE_NAME}``. + .. _${PACKAGE_NAME}_TEST_REQUIRED_DEP_PACKAGES: + ``${PACKAGE_NAME}_TEST_REQUIRED_DEP_PACKAGES`` List of *direct* package dependencies that are required for the @@ -218,6 +230,8 @@ already handles these automatically.) contain any of the packages already listed in ``${PACKAGE_NAME}_LIB_REQUIRED_DEP_PACKAGES``. + .. _${PACKAGE_NAME}_TEST_OPTIONAL_DEP_PACKAGES: + ``${PACKAGE_NAME}_TEST_OPTIONAL_DEP_PACKAGES``` List of *direct* package dependencies that are optional for the @@ -274,20 +288,20 @@ or:: The final status of whether a listed package is an internal package or an external package is provided by the variable:: - ${PACKAGE_NAME}_PACKAGE_STATUS=[INTERNAL|EXTERNAL] + ${PACKAGE_NAME}_PACKAGE_BUILD_STATUS=[INTERNAL|EXTERNAL] As a result, every other package upstream from any of these ```` packages must therefore also be treated as external packages automatically. -The primary TriBITS file that processes and defines these variables is: +The primary TriBITS file that processes and defines these variables is:: TribitsAdjustPackageEnables.cmake There are pretty good unit and regression tests to demonstrate and protect -this functionality in the directory: +this functionality in the directory:: - tribits/package_arch/UntiTests/ + TriBITS/test/core/ External package dependencies @@ -300,6 +314,71 @@ in ``FindTPLDependencies.cmake`` files and overridden in the cache. +Flat lists of direct package dependencies ++++++++++++++++++++++++++++++++++++++++++ + +TriBITS sets up the following lists of dependencies for each internal and +external package/TPL: + + .. _${PACKAGE_NAME}_LIB_ALL_DEPENDENCIES: + + ``${PACKAGE_NAME}_LIB_ALL_DEPENDENCIES`` + + The list of all **direct** required and optional upstream internal and + external packages/TPL dependencies, regardless if they are enabled or not. + This is concatenation of lists + `${PACKAGE_NAME}_LIB_REQUIRED_DEP_PACKAGES`_, + `${PACKAGE_NAME}_LIB_OPTIONAL_DEP_PACKAGES`_, + ``${PACKAGE_NAME}_LIB_REQUIRED_DEP_TPLS``, and + ``${PACKAGE_NAME}_LIB_OPTIONAL_DEP_TPLS`` (with the latter two lists soon + to disappear as part of #63). To determine if a given direct upstream + package ```` in this list is enabled/supported or not for this + package ``${PACKAGE_NAME}``, check the value of + ``${PACKAGE_NAME}_ENABLE_``. NOTE: The variables + ``${PACKAGE_NAME}_ENABLE_`` will be set even for required upstream + internal and external packages/tpls to allow for uniform loops involving + required and optional upstream dependencies. (And for a parent package + with subpackages, it is possible for a required subpackage to **not** be + enabled and for ``${PACKAGE_NAME}_ENABLE_`` to be ``OFF`` as + explained in `Subpackage enable does not auto-enable the parent + package`_.) This list will be set regardless of if the package + ``${PACKAGE_NAME}`` is enabled or not. + + .. _${PACKAGE_NAME}_LIB_ENABLED_DEPENDENCIES: + + ``${PACKAGE_NAME}_LIB_ENABLED_DEPENDENCIES`` + + List of all **enabled** **direct** required and optional upstream internal + and external packages/TPL dependencies. This is strict subset + `${PACKAGE_NAME}_LIB_ALL_DEPENDENCIES`_ (i.e. all of the ```` + items in this list will have ``${PACKAGE_NAME}_ENABLE_`` set to + ``ON``). + + .. _${PACKAGE_NAME}_TEST_ALL_DEPENDENCIES: + + ``${PACKAGE_NAME}_TEST_ALL_DEPENDENCIES`` + + This list of all **direct** extra package test required and optional + upstream internal and external packages/TPLs. This list includes just the + extra dependencies not already listed in + `${PACKAGE_NAME}_LIB_ALL_DEPENDENCIES`_. This is a concatenation of the + lists `${PACKAGE_NAME}_TEST_REQUIRED_DEP_PACKAGES`_, + `${PACKAGE_NAME}_TEST_OPTIONAL_DEP_PACKAGES`_, + ``${PACKAGE_NAME}_TEST_REQUIRED_DEP_TPLS``, and + ``${PACKAGE_NAME}_TEST_OPTIONAL_DEP_TPLS`` (with the latter two lists soon + to disappear as part of #63). This list is set regardless if the package + ``${PACKAGE_NAME}`` is enabled or not. + + .. _${PACKAGE_NAME}_TEST_ENABLED_DEPENDENCIES: + + ``${PACKAGE_NAME}_TEST_ENABLED_DEPENDENCIES`` + + The list of all **enabled** **direct** extra required and optional + upstream internal and external packages/TPL dependencies. This is a + strict subset of `${PACKAGE_NAME}_TEST_ALL_DEPENDENCIES`_. This list + includes just the extra dependencies not already listed in + `${PACKAGE_NAME}_LIB_ENABLED_DEPENDENCIES`_. + List variables defining include directories and libraries +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -310,30 +389,6 @@ targets as part of #299. The following global internal cache variables are used to communicate the required header directory paths and libraries needed to build and link against a given package's capabilities: - - ``${PACKAGE_NAME}_INCLUDE_DIRS`` - - Defines a list of include paths needed to find all of the headers needed - to compile client code against this (sub)packages sources and it's - upstream packages and TPL sources. This variable is used whenever - building downstream code including downstream libraries or executables in - the same package, or libraries or executables in downstream packages. It - is also used to list out in ${PACKAGE_NAME}Config.cmake and - Makefile.export.${PACKAGE_NAME} files. - - ToDo: Look to eliminate this variable and just add it to the package's - library targets with target_include_directories(). - - ToDo: Split off ${PACKAGE_NAME}_TPL_INCLUDE_DIRS - - ``${PACKAGE_NAME}_LIBRARY_DIRS`` - - Defines as list of the link directories needed to find all of the - libraries for this packages and it's upstream packages and TPLs. Adding - these library directories to the CMake link line is unnecessary and would - cause link-line too long errors on some systems. Instead, this list of - library directories is used when creating ${PACKAGE_NAME}Config.cmake and - Makefile.export.${PACKAGE_NAME} files. ``${PACKAGE_NAME}_LIBRARIES`` @@ -359,13 +414,12 @@ a given package's capabilities: ``${PACKAGE_NAME}_FULL_ENABLED_DEP_PACKAGES`` - Lists out, in order, all of the enabled upstream packages that the - given package depends on and support that package is enabled in the given + Lists out, in order, all of the enabled upstream packages that the given + package depends on and support that package is enabled in the given package. This is only computed if - ${PROJECT_NAME}_GENERATE_EXPORT_FILE_DEPENDENCIES=ON. This is needed to - generate the export makefile Makefile.export.${PACKAGE_NAME}. NOTE: This - list does *not* include the package itself. This list is created after - all of the enable/disable logic is applied. + ${PROJECT_NAME}_GENERATE_EXPORT_FILE_DEPENDENCIES=ON. NOTE: This list + does *not* include the package itself. This list is created after all of + the enable/disable logic is applied. ``${PARENT_PACKAGE_NAME}_LIB_TARGETS`` @@ -418,7 +472,7 @@ Logic`_. There are pretty good unit and regression tests to demonstrate and protect this functionality in the directory:: - tribits/package_arch/UntiTests/ + TriBITS/test/core/ Function call tree for constructing package dependency graph @@ -441,7 +495,9 @@ lists and dependency data-structures described above. | `tribits_process_project_dependency_setup_file()`_ | ``include(`` `/cmake/ProjectDependenciesSetup.cmake`_ ``)`` | `tribits_read_all_package_deps_files_create_deps_graph()`_ -| Foreach ``TOPLEVEL_PACKAGE``: +| Foreach ``EXTERNAL_PACKAGE`` in ``${PROJECT_NAME}_DEFINED_TPLS``: +| `tribits_read_external_package_deps_files_add_to_graph()`_ +| Foreach ``TOPLEVEL_PACKAGE`` in ``${PACKAGE_NAME}_DEFINED_INTERNAL_TOPLEVEL_PACKAGES``: | `tribits_read_toplevel_package_deps_files_add_to_graph()`_ | `tribits_prep_to_read_dependencies()`_ | ``include(`` `/cmake/Dependencies.cmake`_ ``)`` @@ -511,4 +567,5 @@ allow it to be efficiently tested outside of the actual build. But there are a number of example projects that are part of the automated TriBITS test suite that do test much of the logic used in these variables. -.. LocalWords: acyclic TriBITS SUBPACKAGES CTEST subpackages +.. LocalWords: acyclic TriBITS SUBPACKAGES CTEST subpackages buildable TPLs TPLS +.. LocalWords: Subpackage CMake CMakeLists diff --git a/cmake/tribits/core/package_arch/TribitsTplFindIncludeDirsAndLibraries.cmake b/cmake/tribits/core/package_arch/TribitsTplFindIncludeDirsAndLibraries.cmake index dfcedc290a7a..987aaf8dd3b9 100644 --- a/cmake/tribits/core/package_arch/TribitsTplFindIncludeDirsAndLibraries.cmake +++ b/cmake/tribits/core/package_arch/TribitsTplFindIncludeDirsAndLibraries.cmake @@ -37,11 +37,9 @@ # ************************************************************************ # @HEADER -if (TribitsTplFindIncludeDirsAndLibraries_INCLUDED) - return() -else() - set(TribitsTplFindIncludeDirsAndLibraries_INCLUDED TRUE) -endif() +include_guard() + +include(TribitsExternalPackageWriteConfigFile) include(AdvancedSet) include(AppendSet) @@ -54,7 +52,7 @@ include(CMakeParseArguments) include(SetNotFound) include(Split) -# + # @FUNCTION: tribits_tpl_allow_pre_find_package() # # Function that determines if a TriBITS find module file @@ -80,12 +78,13 @@ include(Split) # the search for the library components and just specify the absolute # locations. The function will also set ```` to # ``FALSE`` if ``_INCLUDE_DIRS``, ``_LIBRARY_NAMES``, or -# ``_LIBRARY_DIRS`` is set and ``_FORCE_PRE_FIND_PACKAGE`` is -# set to ``FALSE``. Otherwise, if ``_FORCE_PRE_FIND_PACKAGE`` is set -# to ``TRUE``, the function will not return ``FALSE`` for +# ``_LIBRARY_DIRS`` is set and ``_FORCE_PRE_FIND_PACKAGE`` +# is set to ``FALSE``. Otherwise, if ``_FORCE_PRE_FIND_PACKAGE`` is +# set to ``TRUE``, the function will not return ``FALSE`` for # ```` no matter what the values of # ``_INCLUDE_DIRS``, ``_LIBRARY_NAMES``, or -# ``_LIBRARY_DIRS``. +# ``_LIBRARY_DIRS``. Finally, ```` is set to +# ``FALSE`` if ``_ALLOW_PACKAGE_PREFIND=OFF`` is set in the cache. # # The variable ``_FORCE_PRE_FIND_PACKAGE`` is needed to allow users # (or the ``FindTPL.cmake`` module itself) to avoid name clashes with @@ -96,8 +95,13 @@ include(Split) # value ``FALSE`` to maintain backward compatibility with existing # ``FindTPL.cmake`` modules. # -# See `How to use find_package() for a TriBITS TPL`_ for details in how to use -# this function to create a ``FindTPL.cmake`` module file. +# The cache variable ``_ALLOW_PACKAGE_PREFIND`` is to allow the user +# to disable the prefind call to ``find_package()`` even if it would be +# allowed otherwise. +# +# See `Creating FindTPL.cmake using find_package() without IMPORTED +# targets`_ for details in how to use this function to create a +# ``FindTPL.cmake`` module file. # function(tribits_tpl_allow_pre_find_package TPL_NAME ALLOW_PACKAGE_PREFIND_OUT) @@ -113,10 +117,16 @@ function(tribits_tpl_allow_pre_find_package TPL_NAME ALLOW_PACKAGE_PREFIND_OUT CACHE BOOL "Determines if the variables ${TPL_NAME}_[INCLUDE_DIRS,LIBRARY_NAMES,LIBRARY_DIRS] should be ignored and the pre-find find_package(${TPL_NAME} should be performed anyway. But this will *not* do the pre-find if any of the TPL_${TPL_NAME}_[INCLUDE_DIRS,LIBRARY_NAMES,LIBRARY_DIRS] vars are set." ) + # Start out with TRUE and set to FALSE in logic below + set(${TPL_NAME}_ALLOW_PACKAGE_PREFIND TRUE CACHE BOOL + "Set to FALSE to skip find_package() prefind for the TriBITS TPL '${TPL_NAME}'") + # Start out with TRUE and set to FALSE in logic below set(ALLOW_PACKAGE_PREFIND TRUE) - if ( + if (NOT ${TPL_NAME}_ALLOW_PACKAGE_PREFIND) + set(ALLOW_PACKAGE_PREFIND FALSE) + elseif ( (NOT "${TPL_${TPL_NAME}_INCLUDE_DIRS}" STREQUAL "") OR (NOT "${TPL_${TPL_NAME}_LIBRARIES}" STREQUAL "") OR (NOT "${TPL_${TPL_NAME}_LIBRARY_DIRS}" STREQUAL "") @@ -146,13 +156,14 @@ function(tribits_tpl_allow_pre_find_package TPL_NAME ALLOW_PACKAGE_PREFIND_OUT endfunction() -# # @FUNCTION: tribits_tpl_find_include_dirs_and_libraries() # -# Function that sets up cache variables for users to specify where to find a -# `TriBITS TPL`_'s headers and libraries. This function is typically called -# inside of a ``FindTPL.cmake`` module file (see -# `${TPL_NAME}_FINDMOD`_). +# This function reads (cache) variables that specify where to find a `TriBITS +# TPL`_'s headers and libraries and then creates IMPORTED targets, the +# ``::all_libs`` target, and writes the file +# ``Config.cmake`` into the standard location in the build directory. +# This function is typically called inside of a ``FindTPL.cmake`` +# module file (see `${TPL_NAME}_FINDMOD`_). # # Usage:: # @@ -182,22 +193,23 @@ endfunction() # ``MUST_FIND_ALL_HEADERS`` # # If set, then all of the header files listed in ``REQUIRED_HEADERS`` must -# be found in order for ``TPL__INCLUDE_DIRS`` to be defined. +# be found (unless ``TPL__INCLUDE_DIRS`` is already set). # # ``REQUIRED_LIBS_NAMES`` # # List of libraries that are searched for when looking for the TPL's # libraries using ``find_library()``. This list can be overridden by the -# user by setting ``_LIBRARY_DIRS`` (see below). +# user by setting ``_LIBRARY_NAMES`` (see below). # # ``MUST_FIND_ALL_LIBS`` # # If set, then all of the library files listed in ``REQUIRED_LIBS_NAMES`` -# must be found or the TPL is considered not found! If the global cache -# var ``_MUST_FIND_ALL_TPL_LIBS`` is set to ``TRUE``, then this -# is turned on as well. WARNING: The default is not to require finding -# all of the listed libs. This is to maintain backward compatibility with -# some older ``FindTPL.cmake`` modules. +# must be found or the TPL is considered not found (unless +# ``TPL__LIBRARIES`` is already set). If the global cache var +# ``_MUST_FIND_ALL_TPL_LIBS`` is set to ``TRUE``, then this is +# turned on as well. WARNING: The default is not to require finding all +# of the listed libs. (This is to maintain backward compatibility with +# some older ``FindTPL.cmake`` modules.) # # ``NO_PRINT_ENABLE_SUCCESS_FAIL`` # @@ -206,50 +218,69 @@ endfunction() # This function implements the TPL find behavior described in `Enabling # support for an optional Third-Party Library (TPL)`_. # -# The following (cache) variables, if set, will be used by that this function: +# The following (cache) variables, if set, will be used by this function: # # ``_INCLUDE_DIRS`` (type ``PATH``) # # List of paths to search first for header files defined in -# ``REQUIRED_HEADERS``. +# ``REQUIRED_HEADERS ...``. # # ``_LIBRARY_DIRS`` (type ``PATH``) # # The list of directories to search first for libraries defined in -# ``REQUIRED_LIBS_NAMES``. If, for some reason, no libraries should be -# linked in for this particular configuration, then setting -# ``_LIBRARY_DIRS=OFF`` will +# ``REQUIRED_LIBS_NAMES ...``. If, for some reason, +# no libraries should be linked in for this particular configuration, then +# setting ``_LIBRARY_DIRS=OFF`` or is empty will no special paths +# will be searched. # # ``_LIBRARY_NAMES`` (type ``STRING``) # # List of library names to be looked for instead of what is specified in -# ``REQUIRED_LIBS_NAMES``. +# ``REQUIRED_LIBS_NAMES ...``. +# +# ``_LIB_ENABLED_DEPENDENCIES`` # -# This function sets global variables to return state so it can be called from -# anywhere in the call stack. The following cache variables are defined that -# are intended for the user to set and/or use: +# List of direct upstream external package/TPL dependencies that also +# define ``::all_libs`` targets. +# +# An addition, the function will avoid calling the find operations if the +# following (cache) variables are set on input: # # ``TPL__INCLUDE_DIRS`` (type ``PATH``) # # A list of common-separated full directory paths that contain the TPL's -# header files. If this variable is set before calling this function, -# then no headers are searched for and this variable will be assumed to -# have the correct list of header paths. +# header files. # # ``TPL__LIBRARIES`` (type ``FILEPATH``) # # A list of commons-separated full library names (i.e. output from -# ``find_library()``) for all of the libraries found for the TPL. If this -# variable is set before calling this function, then no libraries are -# searched for and this variable will be assumed to have the correct list -# of libraries to link to. +# ``find_library()``) for all of the libraries for the TPL. +# +# This function produces the following: # # ``TPL__NOT_FOUND`` (type ``BOOL``) # # Will be set to ``ON`` if all of the parts of the TPL could not be found. # -# ToDo: Document the behavior of this function for finding headers and -# libraries and when a find is successful and when it is not. +# ``::`` +# +# Namespaced IMPORTED target for every library found or specified in +# ``TPL__LIBRARIES``. These IMPORTED targets will have the +# ``::all_libs`` for the upstream external packages/TPLs +# listed in ``_LIB_ENABLED_DEPENDENCIES``. +# +# ``::all_libs`` +# +# INTERFACE target that depends on all of the created IMPORTED targets. +# +# ``/external_packages//Config.cmake`` +# +# A package configure file that contains all of the generated IMPORTED +# targets ``::`` and the ``::all_libs`` target. +# This fill will also call ``find_dependency()`` to pull in +# ``Config.cmake`` files for upstream TPLs that are +# listed in ``_LIB_ENABLED_DEPENDENCIES``. (For more +# information, see `tribits_extpkg_write_config_file()`_.) # # Note, if ``TPL_TENTATIVE_ENABLE_=ON``, then if all of the parts of # the TPL can't be found, then ``TPL_ENABLE_`` will be (forced) set @@ -293,11 +324,30 @@ function(tribits_tpl_find_include_dirs_and_libraries TPL_NAME) set(ERROR_MSG_MODE SEND_ERROR) endif() + # Allow user override for finding libraries even if REQUIRED_LIBS_NAMES is + # empty on input + + multiline_set(DOCSTR + "List of semi-colon separated names of libraries needed to link to for" + " the TPL ${TPL_NAME}. This list of libraries will be search for in" + " find_library(...) calls along with the directories specified with" + " ${TPL_NAME}_LIBRARY_DIRS. NOTE: This is not the final list of libraries" + " used for linking. That is specified by TPL_${TPL_NAME}_LIBRARIES!" + ) + advanced_set(${TPL_NAME}_LIBRARY_NAMES ${PARSE_REQUIRED_LIBS_NAMES} + CACHE STRING ${DOCSTR}) + split("${${TPL_NAME}_LIBRARY_NAMES}" "," ${TPL_NAME}_LIBRARY_NAMES) + print_var(${TPL_NAME}_LIBRARY_NAMES) + + # Let the user override what the names of the libraries which might + # actually mean that no libraries are searched for. + set(REQUIRED_LIBS_NAMES ${${TPL_NAME}_LIBRARY_NAMES}) + # # User options # - if (PARSE_REQUIRED_LIBS_NAMES) + if (REQUIRED_LIBS_NAMES) # Library directories @@ -318,22 +368,6 @@ function(tribits_tpl_find_include_dirs_and_libraries TPL_NAME) # Libraries - multiline_set(DOCSTR - "List of semi-colon separated names of libraries needed to link to for" - " the TPL ${TPL_NAME}. This list of libraries will be search for in" - " find_library(...) calls along with the directories specified with" - " ${TPL_NAME}_LIBRARY_DIRS. NOTE: This is not the final list of libraries" - " used for linking. That is specified by TPL_${TPL_NAME}_LIBRARIES!" - ) - advanced_set(${TPL_NAME}_LIBRARY_NAMES ${PARSE_REQUIRED_LIBS_NAMES} - CACHE STRING ${DOCSTR}) - split("${${TPL_NAME}_LIBRARY_NAMES}" "," ${TPL_NAME}_LIBRARY_NAMES) - print_var(${TPL_NAME}_LIBRARY_NAMES) - - # Let the user override what the names of the libraries which might - # actually mean that no libraries are searched for. - set(REQUIRED_LIBS_NAMES ${${TPL_NAME}_LIBRARY_NAMES}) - if (${PROJECT_NAME}_MUST_FIND_ALL_TPL_LIBS) set(MUST_FIND_ALL_LIBS TRUE) else() @@ -347,7 +381,7 @@ function(tribits_tpl_find_include_dirs_and_libraries TPL_NAME) else() - set(${TPL_NAME}_LIBRARY_DIRS) # Just to ignore below! + set(${TPL_NAME}_LIBRARY_DIRS "") # Just to ignore below! endif() @@ -423,7 +457,7 @@ function(tribits_tpl_find_include_dirs_and_libraries TPL_NAME) set(LIBRARIES_FOUND) - foreach(LIBNAME_SET ${${TPL_NAME}_LIBRARY_NAMES}) + foreach(LIBNAME_SET ${REQUIRED_LIBS_NAMES}) message("-- Searching for a lib in the set \"${LIBNAME_SET}\":") @@ -680,10 +714,23 @@ function(tribits_tpl_find_include_dirs_and_libraries TPL_NAME) global_set(TPL_${TPL_NAME}_NOT_FOUND FALSE) endif() + set(buildDirExternalPkgsDir + "${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR}") + set(tplConfigFileBaseDir "${buildDirExternalPkgsDir}/${TPL_NAME}") + set(tplConfigFile "${tplConfigFileBaseDir}/${TPL_NAME}Config.cmake") + 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 + # ConfigVersion.cmake. + endfunction() -# # @FUNCTION: tribits_tpl_tentatively_enable() # # Function that sets up for an optionally enabled TPL that is attempted to be @@ -728,10 +775,8 @@ function(tribits_tpl_tentatively_enable TPL_NAME) endfunction() +# Set find error and print error message # -# Utility macro -# - macro(tribits_tpl_find_include_dirs_and_libraries_handle_fail) set(_${TPL_NAME}_ENABLE_SUCCESS FALSE) global_set(TPL_${TPL_NAME}_NOT_FOUND TRUE) diff --git a/cmake/tribits/core/package_arch/TribitsVerbosePrintVar.cmake b/cmake/tribits/core/package_arch/TribitsVerbosePrintVar.cmake index ef4496c92d4b..e6021d60f479 100644 --- a/cmake/tribits/core/package_arch/TribitsVerbosePrintVar.cmake +++ b/cmake/tribits/core/package_arch/TribitsVerbosePrintVar.cmake @@ -40,7 +40,7 @@ if (${PROJECT_NAME}_VERBOSE_CONFIGURE) -# + # @FUNCTION: tribits_verbose_print_var() # # print a variable giving its name then value if diff --git a/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake b/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake index 537ff85e9558..6a91545524e6 100644 --- a/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake +++ b/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake @@ -44,7 +44,6 @@ include(TribitsGeneralMacros) ### 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. # @@ -58,7 +57,6 @@ function(tribits_list_to_string LIST PREFIX OUTPUT_STRING) set(${OUTPUT_STRING} ${LIST_STRING} PARENT_SCOPE) endfunction() -# # 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 @@ -81,55 +79,21 @@ function(tribits_library_list_to_string LIST PREFIX OUTPUT_STRING) set(${OUTPUT_STRING} ${LIST_STRING} PARENT_SCOPE) endfunction() -# -# CMAKE_CURRENT_LIST_DIR is not defined in CMake versions < 2.8.3, but the -# Trilinos writes paths that use the value of that variable to this file. -# Make sure it is available at *find_package* time. Note that all variable -# references in the code snippet are escaped. This is to keep them from -# being evaluated until they are actually in the install tree. This is -# done to handle movable install trees. -# -# This function defines the variable -# DEFINE_CMAKE_CURRENT_LIST_DIR_CODE_CODE_SNIPPET in the caller's scope -# as a string that can be referenced from CONFIGURE_FILE input files -# to ensure that the CMAKE_CURRENT_LIST_DIR will be defined on the installation -# target machine, even if it has an older version of cmake. -# -function(tribits_set_define_cmake_current_list_dir_code_snippet) - set(DEFINE_CMAKE_CURRENT_LIST_DIR_CODE_SNIPPET " -# Include guard -if (${EXPORT_FILE_VAR_PREFIX}_CONFIG_INCLUDED) - return() -endif() -set(${EXPORT_FILE_VAR_PREFIX}_CONFIG_INCLUDED TRUE) - -# Make sure CMAKE_CURRENT_LIST_DIR is usable -if (NOT DEFINED CMAKE_CURRENT_LIST_DIR) - get_filename_component(_THIS_SCRIPT_PATH \${CMAKE_CURRENT_LIST_FILE} PATH) - set(CMAKE_CURRENT_LIST_DIR \${_THIS_SCRIPT_PATH}) -endif() -" - PARENT_SCOPE ) -endfunction() - -# # @FUNCTION: tribits_write_flexible_package_client_export_files() # -# Utility function for writing ``${PACKAGE_NAME}Config.cmake`` and/or the -# ``Makefile.export.${PACKAGE_NAME}`` files for package ``${PACKAGE_NAME}`` -# with some greater flexibility than what is provided by the function -# ``tribits_write_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 ] -# [WRITE_CMAKE_CONFIG_FILE ] -# [WRITE_EXPORT_MAKEFILE ] -# [WRITE_INSTALL_CMAKE_CONFIG_FILE] -# [WRITE_INSTALL_EXPORT_MAKEFILE] +# [PACKAGE_CONFIG_FOR_BUILD_BASE_DIR ] +# [PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR ] # ) # # The arguments are: @@ -145,45 +109,30 @@ endfunction() # will be prefixed with ``_`` instead of # ``_``. # -# ``WRITE_CMAKE_CONFIG_FILE `` +# ``PACKAGE_CONFIG_FOR_BUILD_BASE_DIR `` # -# If specified, then the package's (````) cmake configure -# export file for use by external CMake client projects will be created as -# the file ````. NOTE: the argument should be -# the full path! +# 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. # -# ``WRITE_EXPORT_MAKEFILE `` +# ``PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR `` # -# If specified, then the package's (````) export makefile for -# use by external Makefile client projects will be created in the file -# . NOTE: the argument should be the full -# path! +# 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. # -# ``WRITE_INSTALL_CMAKE_CONFIG_FILE`` -# -# If specified, then the package's (````) install cmake -# configured export file will be installed in to the install tree as well. -# The name and location of this file is hard-coded. -# -# ``WRITE_INSTALL_EXPORT_MAKEFILE`` -# -# If specified, then the package's (````) install export -# makefile to be installed into the install tree as well. The name and -# location of this file is hard-coded. -# -# NOTE: The arguments to this function may look strange but the motivation is -# to support very specialized use cases such as when a TriBITS package needs -# to generate an export makefile for a given package but the name of the -# export makefile must be different and use different variable name prefixes. -# The particular use case is when wrapping an external autotools project that -# depends on Trilinos and needs to read in the ``Makefile.export.Trilinos`` -# file but this file needs to be generated for a subset of enabled packages on -# the fly during a one-pass configure. -# -# NOTE: This function does *not* contain the ``install()`` commands because -# CMake will not allow those to even be present in scripting mode that is used -# for unit testing this function. Instead, the files to be installed are only -# generated in the build tree and the install targets are added else where. +# 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) @@ -199,11 +148,11 @@ function(tribits_write_flexible_package_client_export_files) #prefix PARSE #options - "WRITE_INSTALL_CMAKE_CONFIG_FILE;WRITE_INSTALL_EXPORT_MAKEFILE" + "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 - "PACKAGE_NAME;WRITE_CMAKE_CONFIG_FILE;WRITE_EXPORT_MAKEFILE;EXPORT_FILE_VAR_PREFIX" + "" ${ARGN} ) @@ -228,8 +177,6 @@ function(tribits_write_flexible_package_client_export_files) print_var(EXPORT_FILE_VAR_PREFIX) endif() - tribits_set_define_cmake_current_list_dir_code_snippet() - # # B) Get the set of upstream packages for this package that are enabled, # libraries, library dirs, and include dirs @@ -238,15 +185,6 @@ function(tribits_write_flexible_package_client_export_files) set(FULL_PACKAGE_SET "") set(FULL_LIBRARY_SET "") - set(SET_INCLUDE_LIBRARY_DIRS_FROM_UPSTREAM TRUE) - if (${PACKAGE_NAME}_INCLUDE_DIRS) - set(FULL_INCLUDE_DIRS_SET ${${PACKAGE_NAME}_INCLUDE_DIRS}) - set(FULL_LIBRARY_DIRS_SET ${${PACKAGE_NAME}_LIBRARY_DIRS}) - set(SET_INCLUDE_LIBRARY_DIRS_FROM_UPSTREAM FALSE) - else() - set(FULL_INCLUDE_DIRS_SET "") - set(FULL_LIBRARY_DIRS_SET "") - endif() if (TRIBITS_WRITE_FLEXIBLE_PACKAGE_CLIENT_EXPORT_FILES_DEBUG_DUMP) print_var(${PACKAGE_NAME}_FULL_ENABLED_DEP_PACKAGES) @@ -272,10 +210,6 @@ function(tribits_write_flexible_package_client_export_files) list(APPEND FULL_PACKAGE_SET ${TRIBITS_PACKAGE}) if (APPEND_THE_PACKAGE_LIBS) append_set(FULL_LIBRARY_SET ${${TRIBITS_PACKAGE}_LIBRARIES}) - if (SET_INCLUDE_LIBRARY_DIRS_FROM_UPSTREAM) - append_set(FULL_INCLUDE_DIRS_SET ${${TRIBITS_PACKAGE}_INCLUDE_DIRS}) - append_set(FULL_LIBRARY_DIRS_SET ${${TRIBITS_PACKAGE}_LIBRARY_DIRS}) - endif() else() if (TRIBITS_WRITE_FLEXIBLE_PACKAGE_CLIENT_EXPORT_FILES_DEBUG_DUMP) message("-- " "Skipping adding the package libs!") @@ -290,10 +224,6 @@ function(tribits_write_flexible_package_client_export_files) if (TRIBITS_WRITE_FLEXIBLE_PACKAGE_CLIENT_EXPORT_FILES_DEBUG_DUMP) print_var(FULL_PACKAGE_SET) print_var(FULL_LIBRARY_SET) - if (SET_INCLUDE_LIBRARY_DIRS_FROM_UPSTREAM) - print_var(FULL_INCLUDE_DIRS_SET) - print_var(FULL_LIBRARY_DIRS_SET) - endif() endif() endforeach() @@ -309,21 +239,10 @@ function(tribits_write_flexible_package_client_export_files) prepend_set(FULL_LIBRARY_SET ${${PACKAGE_NAME}_LIBRARIES}) endif() - if (SET_INCLUDE_LIBRARY_DIRS_FROM_UPSTREAM) - if (FULL_INCLUDE_DIRS_SET) - list(REMOVE_DUPLICATES FULL_INCLUDE_DIRS_SET) - endif() - if (FULL_LIBRARY_DIRS_SET) - list(REMOVE_DUPLICATES FULL_LIBRARY_DIRS_SET) - endif() - endif() - if (TRIBITS_WRITE_FLEXIBLE_PACKAGE_CLIENT_EXPORT_FILES_DEBUG_DUMP) message("-- " "*** Final sets of packages, libs, include dirs, and lib dirs:") print_var(FULL_PACKAGE_SET) print_var(FULL_LIBRARY_SET) - print_var(FULL_INCLUDE_DIRS_SET) - print_var(FULL_LIBRARY_DIRS_SET) endif() # @@ -368,12 +287,8 @@ function(tribits_write_flexible_package_client_export_files) # set(${PACKAGE_NAME}_TPL_LIBRARIES "") - set(${PACKAGE_NAME}_TPL_INCLUDE_DIRS "") - set(${PACKAGE_NAME}_TPL_LIBRARY_DIRS "") foreach(TPL ${ORDERED_FULL_TPL_SET}) - list(APPEND ${PACKAGE_NAME}_TPL_LIBRARIES ${TPL_${TPL}_LIBRARIES}) - list(APPEND ${PACKAGE_NAME}_TPL_INCLUDE_DIRS ${TPL_${TPL}_INCLUDE_DIRS}) - list(APPEND ${PACKAGE_NAME}_TPL_LIBRARY_DIRS ${TPL_${TPL}_LIBRARY_DIRS}) + list(APPEND ${PACKAGE_NAME}_TPL_LIBRARIES ${TPL}::all_libs) endforeach() # Generate a note discouraging editing of the Config.cmake file @@ -393,26 +308,76 @@ function(tribits_write_flexible_package_client_export_files) endif() # - # F) Create the contents of the cmake Config.cmake file for the build tree + # F) 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}) + # - # Creating this file in the base dir of the package since it is possible - # that the cmake returned path where the file was found would be useful for - # a package, and having to dig through the hiding that is done wouldn't be - # nice. + # G) Create Config_install.cmake file for the install tree # - if (PARSE_WRITE_CMAKE_CONFIG_FILE) - # Custom code in configuration file. + tribits_generate_package_config_file_for_install_tree(${PACKAGE_NAME} + EXPORT_FILE_VAR_PREFIX ${EXPORT_FILE_VAR_PREFIX}) + +endfunction() + + +# @FUNCTION: tribits_generate_package_config_file_for_build_tree() +# +# Called from tribits_write_flexible_package_client_export_files() to finish +# up generating text for and writing the file `Config.cmake` for the +# build tree. +# +# Usage:: +# +# tribits_generate_package_config_file_for_build_tree( +# [EXPORT_FILE_VAR_PREFIX ] +# ) +# +# These files get placed under /cmake_packages// +# +# That makes them easy to find by find_package() by adding +# /cmake_packages/ to CMAKE_PREFIX_PATH. +# +function(tribits_generate_package_config_file_for_build_tree packageName) + + if (TRIBITS_WRITE_FLEXIBLE_PACKAGE_CLIENT_EXPORT_FILES_DEBUG_DUMP) + message("tribits_generate_package_config_file_for_build_tree(${ARGV})") + endif() + + cmake_parse_arguments( + PARSE #prefix + "" #options + "EXPORT_FILE_VAR_PREFIX" #one_value_keywords + "" #multi_value_keywords + ${ARGN} + ) + + if (PARSE_EXPORT_FILE_VAR_PREFIX) + set(EXPORT_FILE_VAR_PREFIX ${PARSE_EXPORT_FILE_VAR_PREFIX}) + else() + set(EXPORT_FILE_VAR_PREFIX ${packageName}) + endif() + + set(buildDirExtPkgsDir + "${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR}") + set(buildDirCMakePkgsDir + "${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_CMAKE_PKGS_DIR}") + + if (PARSE_PACKAGE_CONFIG_FOR_BUILD_BASE_DIR + OR PARSE_PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR + ) + # Custom code in configuration file (gets pulled from by configure_file() + # below) set(PACKAGE_CONFIG_CODE "") - # Include configurations of dependent packages - foreach(DEP_PACKAGE ${${PACKAGE_NAME}_FULL_ENABLED_DEP_PACKAGES}) - # Could use file(RELATIVE_PATH ...), but probably not necessary - # since unlike install trees, build trees need not be relocatable - set(PACKAGE_CONFIG_CODE "${PACKAGE_CONFIG_CODE} -include(\"${${DEP_PACKAGE}_BINARY_DIR}/${DEP_PACKAGE}Config.cmake\")" - ) - endforeach() + tribits_append_dependent_package_config_file_includes_and_enables(${packageName} + EXPORT_FILE_VAR_PREFIX ${EXPORT_FILE_VAR_PREFIX} + EXT_PKG_CONFIG_FILE_BASE_DIR "${buildDirExtPkgsDir}" + PKG_CONFIG_FILE_BASE_DIR "${buildDirCMakePkgsDir}" + CONFIG_FILE_STR_INOUT PACKAGE_CONFIG_CODE ) # Import build tree targets into applications. # @@ -423,13 +388,12 @@ include(\"${${DEP_PACKAGE}_BINARY_DIR}/${DEP_PACKAGE}Config.cmake\")" # are sub-packages. We'd like to export per-package, but deps # won't be satisfied, so we export one file for the project for # now... - if(${TRIBITS_PACKAGE}_HAS_NATIVE_LIBRARIES_TO_INSTALL) - export(TARGETS ${${PACKAGE_NAME}_LIBRARIES} FILE - "${${PROJECT_NAME}_BINARY_DIR}/${PROJECT_NAME}Targets.cmake" APPEND) - set(PACKAGE_CONFIG_CODE "${PACKAGE_CONFIG_CODE} -# Import ${PACKAGE_NAME} targets -include(\"${${PROJECT_NAME}_BINARY_DIR}/${PROJECT_NAME}Targets.cmake\")" - ) + if (PARSE_PACKAGE_CONFIG_FOR_BUILD_BASE_DIR) + tribits_get_package_config_build_dir_targets_file(${packageName} + "${PACKAGE_CONFIG_FOR_BUILD_BASE_DIR}" packageConfigBuildDirTargetsFile ) + string(APPEND PACKAGE_CONFIG_CODE + "\n# Import ${packageName} targets\n" + "include(\"${packageConfigBuildDirTargetsFile}\")") endif() tribits_set_compiler_vars_for_config_file(BUILD_DIR) @@ -440,58 +404,62 @@ include(\"${${PROJECT_NAME}_BINARY_DIR}/${PROJECT_NAME}Targets.cmake\")" # Replace " by \". string(REGEX REPLACE "\"" "\\\\\"" CMAKE_CXX_FLAGS_ESCAPED ${CMAKE_CXX_FLAGS}) endif() - configure_file( - ${${PROJECT_NAME}_TRIBITS_DIR}/${TRIBITS_CMAKE_INSTALLATION_FILES_DIR}/TribitsPackageConfigTemplate.cmake.in - "${PARSE_WRITE_CMAKE_CONFIG_FILE}" - ) - endif() - # - # G) Create the export makefile for the build tree - # - # This is the equivalent of the cmake version only slightly changed so that - # it can be directly imported into a Makefile. - # + # Used in configured file below + set(EXPORTED_PACKAGE_LIBS_NAMES ${${packageName}_EXPORTED_PACKAGE_LIBS_NAMES}) + set(PDOLLAR "$") - if(PARSE_WRITE_EXPORT_MAKEFILE) + set(tribitsConfigFilesDir + "${${PROJECT_NAME}_TRIBITS_DIR}/${TRIBITS_CMAKE_INSTALLATION_FILES_DIR}") + configure_file( + "${tribitsConfigFilesDir}/TribitsPackageConfigTemplate.cmake.in" + "${PARSE_PACKAGE_CONFIG_FOR_BUILD_BASE_DIR}/${packageName}Config.cmake" + ) - tribits_list_to_string("${FULL_LIBRARY_SET}" ${CMAKE_LINK_LIBRARY_FLAG} MAKEFILE_FULL_LIBRARY_SET) - tribits_list_to_string("${FULL_LIBRARY_DIRS_SET}" ${CMAKE_LIBRARY_PATH_FLAG} MAKEFILE_LIBRARY_DIRS) - tribits_list_to_string("${FULL_INCLUDE_DIRS_SET}" "-I" MAKEFILE_INCLUDE_DIRS) - tribits_list_to_string("${${PACKAGE_NAME}_TPL_INCLUDE_DIRS}" "-I" MAKEFILE_${PACKAGE_NAME}_TPL_INCLUDE_DIRS) - tribits_list_to_string("${${PACKAGE_NAME}_TPL_LIBRARY_DIRS}" ${CMAKE_LIBRARY_PATH_FLAG} MAKEFILE_${PACKAGE_NAME}_TPL_LIBRARY_DIRS) - #the TPL library names have to be treated differently - tribits_library_list_to_string("${${PACKAGE_NAME}_TPL_LIBRARIES}" ${CMAKE_LINK_LIBRARY_FLAG} MAKEFILE_${PACKAGE_NAME}_TPL_LIBRARIES) + endif() - tribits_library_list_to_string("${${TPL_MPI_LIBRARIES}}" ${CMAKE_LINK_LIBRARY_FLAG} "MAKEFILE_TPL_MPI_LIBRARIES") - tribits_list_to_string("${${TPL_MPI_LIBRARY_DIRS}}" ${CMAKE_LIBRARY_PATH_FLAG} "MAKEFILE_TPL_MPI_LIBRARY_DIRS") - tribits_list_to_string("${${TPL_MPI_INCLUDE_DIRS}}" "-I" "MAKEFILE_TPL_MPI_INCLUDE_DIRS") +endfunction() - tribits_list_to_string("${FULL_PACKAGE_SET}" "" MAKEFILE_FULL_PACKAGE_SET) - tribits_list_to_string("${ORDERED_FULL_TPL_SET}" "" MAKEFILE_ORDERED_FULL_TPL_SET) - # create an upper case name of the package so that we can make deprecated - # versions of them to help people transistioning from the autotools - # version diagnose any missed variables. - string(TOUPPER ${EXPORT_FILE_VAR_PREFIX} EXPORT_FILE_VAR_PREFIX_UPPER) +# @FUNCTION: tribits_generate_package_config_file_for_install_tree() +# +# Called from tribits_write_flexible_package_client_export_files() to finish +# up generating text for and writing the file `Config_install.cmake` +# that will get installed. +# +# Usage:: +# +# tribits_generate_package_config_file_for_install_tree( +# [EXPORT_FILE_VAR_PREFIX ] +# ) +# +# The export files are typically installed in +# //cmake//. +# +# This file isn't generally useful inside the build tree so it is being +# "hidden" in the CMakeFiles directory. It gets installed in a separate +# function. (NOTE: The install target is added in a different function to +# allow this function to be unit tested in a cmake -P script.) +# +function(tribits_generate_package_config_file_for_install_tree packageName) - assert_defined(${PROJECT_NAME}_TRIBITS_DIR) - configure_file( - ${${PROJECT_NAME}_TRIBITS_DIR}/${TRIBITS_CMAKE_INSTALLATION_FILES_DIR}/TribitsPackageConfigTemplate.export.in - "${PARSE_WRITE_EXPORT_MAKEFILE}" - ) + if (TRIBITS_WRITE_FLEXIBLE_PACKAGE_CLIENT_EXPORT_FILES_DEBUG_DUMP) + message("tribits_generate_package_config_file_for_install_tree(${ARGV})") endif() - # - # H) Create the cmake Config.cmake file for the install tree. - # - - # This file isn't generally useful inside the build tree so it is being - # "hidden" in the CMakeFiles directory. It will be placed in the base - # install directory for ${PROJECT_NAME} when installed. + cmake_parse_arguments( + PARSE #prefix + "" #options + "EXPORT_FILE_VAR_PREFIX" #one_value_keywords + "" #multi_value_keywords + ${ARGN} + ) - # NOTE: The install target is added in a different function to allow this - # function to be unit tested in a cmake -P script. + if (PARSE_EXPORT_FILE_VAR_PREFIX) + set(EXPORT_FILE_VAR_PREFIX ${PARSE_EXPORT_FILE_VAR_PREFIX}) + else() + 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 @@ -501,9 +469,9 @@ include(\"${${PROJECT_NAME}_BINARY_DIR}/${PROJECT_NAME}Targets.cmake\")" # installers that allow relocation of the install tree at *install* # time. # The export files are typically installed in - # //cmake//. + # //cmake//. # The relative path to the installation dir is hence k*(../) + ../../, where - # k is the number of components in . Extract those here. + # 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(). @@ -512,170 +480,245 @@ include(\"${${PROJECT_NAME}_BINARY_DIR}/${PROJECT_NAME}Targets.cmake\")" foreach(PATH ${PATH_LIST}) set(RELATIVE_PATH "${RELATIVE_PATH}/..") endforeach() - set(FULL_LIBRARY_DIRS_SET "\${CMAKE_CURRENT_LIST_DIR}/${RELATIVE_PATH}/${${PROJECT_NAME}_INSTALL_LIB_DIR}") - set(FULL_INCLUDE_DIRS_SET "\${CMAKE_CURRENT_LIST_DIR}/${RELATIVE_PATH}/${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}") # Custom code in configuration file. set(PACKAGE_CONFIG_CODE "") - if (${PACKAGE_NAME}_FULL_ENABLED_DEP_PACKAGES) - set(PACKAGE_CONFIG_CODE "${PACKAGE_CONFIG_CODE} -# Include configuration of dependent packages") - endif() - foreach(DEP_PACKAGE ${${PACKAGE_NAME}_FULL_ENABLED_DEP_PACKAGES}) - set(PACKAGE_CONFIG_CODE "${PACKAGE_CONFIG_CODE} -include(\"\${CMAKE_CURRENT_LIST_DIR}/../${DEP_PACKAGE}/${DEP_PACKAGE}Config.cmake\")" -) - endforeach() - if(${PACKAGE_NAME}_FULL_ENABLED_DEP_PACKAGES) - set(PACKAGE_CONFIG_CODE "${PACKAGE_CONFIG_CODE}\n") - endif() + tribits_append_dependent_package_config_file_includes_and_enables(${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}" + PKG_CONFIG_FILE_BASE_DIR "\${CMAKE_CURRENT_LIST_DIR}/.." + CONFIG_FILE_STR_INOUT PACKAGE_CONFIG_CODE ) - # Import install tree targets into applications. - get_property(HAS_INSTALL_TARGETS GLOBAL PROPERTY ${PACKAGE_NAME}_HAS_INSTALL_TARGETS) - if(HAS_INSTALL_TARGETS) - set(PACKAGE_CONFIG_CODE "${PACKAGE_CONFIG_CODE} -# Import ${PACKAGE_NAME} targets -include(\"\${CMAKE_CURRENT_LIST_DIR}/${PACKAGE_NAME}Targets.cmake\")" -) - endif() + # Import install targets + string(APPEND PACKAGE_CONFIG_CODE + "\n# Import ${packageName} targets\n" + "include(\"\${CMAKE_CURRENT_LIST_DIR}/${packageName}Targets.cmake\")") - # 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}) + # 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() tribits_set_compiler_vars_for_config_file(INSTALL_DIR) - if (PARSE_WRITE_INSTALL_CMAKE_CONFIG_FILE) + # Used in configure file below + set(EXPORTED_PACKAGE_LIBS_NAMES ${${packageName}_EXPORTED_PACKAGE_LIBS_NAMES}) + set(PDOLLAR "$") + if (PARSE_PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR) configure_file( - ${${PROJECT_NAME}_TRIBITS_DIR}/${TRIBITS_CMAKE_INSTALLATION_FILES_DIR}/TribitsPackageConfigTemplate.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${PACKAGE_NAME}Config_install.cmake + "${${PROJECT_NAME}_TRIBITS_DIR}/${TRIBITS_CMAKE_INSTALLATION_FILES_DIR}/TribitsPackageConfigTemplate.cmake.in" + "${PARSE_PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR}/${packageName}Config_install.cmake" ) + endif() + +endfunction() + +# @FUNCTION: tribits_append_dependent_package_config_file_includes_and_enables() +# +# Append the includes for upstream external packages (TPLs) and internal +# packages as well as the enables/disables for upstream dependencies to an +# output `Config.cmake` file string. +# +# Usage:: +# +# tribits_append_dependent_package_config_file_includes_and_enables( +# +# EXPORT_FILE_VAR_PREFIX +# EXT_PKG_CONFIG_FILE_BASE_DIR +# PKG_CONFIG_FILE_BASE_DIR +# CONFIG_FILE_STR_INOUT +# ) +# +function(tribits_append_dependent_package_config_file_includes_and_enables packageName) + + if (TRIBITS_WRITE_FLEXIBLE_PACKAGE_CLIENT_EXPORT_FILES_DEBUG_DUMP) + message("tribits_append_dependent_package_config_file_includes_and_enables(${ARGV})") endif() - # - # I) Write the export makefile for the install tree - # + # Parse input - if (PARSE_WRITE_INSTALL_EXPORT_MAKEFILE) + cmake_parse_arguments( + PARSE #prefix + "" #options + #one_value_keywords + "EXPORT_FILE_VAR_PREFIX;EXT_PKG_CONFIG_FILE_BASE_DIR;PKG_CONFIG_FILE_BASE_DIR;CONFIG_FILE_STR_INOUT" + "" #multi_value_keywords + ${ARGN} + ) + tribits_check_for_unparsed_arguments() - # Generated Make imports must use CMAKE_INSTALL_PREFIX, rather - # than the more platform friendly method of locating the libraries - # and includes using the config file path above. The underlying - # assumption here is that a generator that uses - # CMAKE_INSTALL_PREFIX is being used. - set(FULL_LIBRARY_DIRS_SET ${CMAKE_INSTALL_PREFIX}/${${PROJECT_NAME}_INSTALL_LIB_DIR}) - set(FULL_INCLUDE_DIRS_SET ${CMAKE_INSTALL_PREFIX}/${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}) + if (PARSE_EXPORT_FILE_VAR_PREFIX) + set(EXPORT_FILE_VAR_PREFIX ${PARSE_EXPORT_FILE_VAR_PREFIX}) + else() + set(EXPORT_FILE_VAR_PREFIX ${packageName}) + endif() + + set(extPkgConfigFileBaseDir "${PARSE_EXT_PKG_CONFIG_FILE_BASE_DIR}") + set(pkgConfigFileBaseDir "${PARSE_PKG_CONFIG_FILE_BASE_DIR}") + set(configFileStr "${${PARSE_CONFIG_FILE_STR_INOUT}}") + + # Add set of enables/disables for all upstream dependencies + string(APPEND configFileStr + "# Enables/Disables for upstream package dependencies\n") + foreach(depPkg IN LISTS ${packageName}_LIB_ALL_DEPENDENCIES) + if (${packageName}_ENABLE_${depPkg}) + set(enableVal ON) + else() + set(enableVal OFF) + endif() + string(APPEND configFileStr + "set(${EXPORT_FILE_VAR_PREFIX}_ENABLE_${depPkg} ${enableVal})\n") + endforeach() - tribits_list_to_string("${FULL_LIBRARY_DIRS_SET}" ${CMAKE_LIBRARY_PATH_FLAG} MAKEFILE_LIBRARY_DIRS) - tribits_list_to_string("${FULL_INCLUDE_DIRS_SET}" "-I" MAKEFILE_INCLUDE_DIRS) + # Include configurations of dependent packages + string(APPEND configFileStr + "\n# Include configuration of dependent packages\n") + 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}") + elseif (${depPkg}_PACKAGE_BUILD_STATUS STREQUAL "EXTERNAL") + set(packageConfigBaseDir "${extPkgConfigFileBaseDir}/${depPkg}") + else() + message(FATAL_ERROR "ERROR: ${depPkg}_PACKAGE_BUILD_STATUS='${${depPkg}_PACKAGE_BUILD_STATUS}' invalid!") + endif() + if (packageConfigBaseDir) + string(APPEND configFileStr + "include(\"${packageConfigBaseDir}/${depPkg}Config.cmake\")\n") + endif() + endforeach() - configure_file( - ${${PROJECT_NAME}_TRIBITS_DIR}/${TRIBITS_CMAKE_INSTALLATION_FILES_DIR}/TribitsPackageConfigTemplate.export.in - ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Makefile.export.${PACKAGE_NAME}_install - ) - endif() + # Set the output + set(${PARSE_CONFIG_FILE_STR_INOUT} "${configFileStr}" PARENT_SCOPE) 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:: # -# Set the install targets for the package config and export makefiles. +# 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) -function(tribits_write_project_client_export_files_install_targets PACKAGE_NAME) + 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} + ) - if (${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES) - install( - FILES ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${PACKAGE_NAME}Config_install.cmake - DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}/cmake/${PACKAGE_NAME}" - RENAME ${PACKAGE_NAME}Config.cmake - ) + set(PACKAGE_NAME ${PARSE_PACKAGE_NAME}) - if(${PACKAGE_NAME}_HAS_NATIVE_LIBRARIES_TO_INSTALL) - install( - EXPORT ${PACKAGE_NAME} - DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}/cmake/${PACKAGE_NAME}" - FILE ${PACKAGE_NAME}Targets.cmake - ) - endif() + 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(${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES) - + if (PARSE_PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR) install( - FILES ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Makefile.export.${PACKAGE_NAME}_install - DESTINATION "${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}" - RENAME Makefile.export.${PACKAGE_NAME} + 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. # -# Generate the ${PACKAGE_NAME}Config.cmake and/or the Makefile.export.${PACKAGE_NAME} -# for package PACKAGE_NAME. +function(tribits_get_package_config_build_dir_targets_file PACKAGE_NAME + packageConfigForBuildBaseDir packageConfigBuildDirTargetsFileOut + ) + set(${packageConfigBuildDirTargetsFileOut} + "${PACKAGE_CONFIG_FOR_BUILD_BASE_DIR}/${PACKAGE_NAME}Targets.cmake" + PARENT_SCOPE ) +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) - set(WRITE_CMAKE_CONFIG_FILE - ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME}Config.cmake) - if(${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("For package ${PACKAGE_NAME} creating ${WRITE_CMAKE_CONFIG_FILE}") - endif() - append_set(EXPORT_FILES_ARGS - WRITE_CMAKE_CONFIG_FILE "${WRITE_CMAKE_CONFIG_FILE}" - WRITE_INSTALL_CMAKE_CONFIG_FILE) - endif() - - if(${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES) - set(WRITE_EXPORT_MAKEFILE - ${CMAKE_CURRENT_BINARY_DIR}/Makefile.export.${PACKAGE_NAME}) if(${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("For package ${PACKAGE_NAME} creating ${WRITE_EXPORT_MAKEFILE}") + 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 - WRITE_EXPORT_MAKEFILE "${WRITE_EXPORT_MAKEFILE}" - WRITE_INSTALL_EXPORT_MAKEFILE) + 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_project_client_export_files_install_targets(${PACKAGE_NAME}) + tribits_write_package_client_export_files_install_targets(${EXPORT_FILES_ARGS}) endfunction() -# -# Write the outer TriBITS project configure and/or export makefiles +# 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}) - tribits_set_define_cmake_current_list_dir_code_snippet() # Reversing the package list so that libraries will be produced in order of # most dependent to least dependent. @@ -688,14 +731,10 @@ function(tribits_write_project_client_export_files) # of all their libraries/includes in the proper order for linking set(FULL_PACKAGE_SET "") set(FULL_LIBRARY_SET "") - set(FULL_INCLUDE_DIRS_SET "") - set(FULL_LIBRARY_DIRS_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}) - list(APPEND FULL_INCLUDE_DIRS_SET ${${TRIBITS_PACKAGE}_INCLUDE_DIRS}) - list(APPEND FULL_LIBRARY_DIRS_SET ${${TRIBITS_PACKAGE}_LIBRARY_DIRS}) endif() endforeach() @@ -712,43 +751,28 @@ function(tribits_write_project_client_export_files) # of all their libraries/includes in the proper order for linking set(FULL_TPL_SET "") set(FULL_TPL_LIBRARY_SET "") - set(FULL_TPL_INCLUDE_DIRS_SET "") - set(FULL_TPL_LIBRARY_DIRS_SET "") foreach(TPL ${TPL_LIST}) if(TPL_ENABLE_${TPL}) list(APPEND FULL_TPL_SET ${TPL}) list(APPEND FULL_TPL_LIBRARY_SET ${TPL_${TPL}_LIBRARIES}) - list(APPEND FULL_TPL_INCLUDE_DIRS_SET ${TPL_${TPL}_INCLUDE_DIRS}) - list(APPEND FULL_TPL_LIBRARY_DIRS_SET ${TPL_${TPL}_LIBRARY_DIRS}) endif() endforeach() - # it is possible that tpls are in the same directory, to keep from - # having a very long include path or library path we will strip out - # any duplicates. This shouldn't affect which include or library is - # found since the first instance of any path will be the one that is - # kept. - list(REMOVE_DUPLICATES FULL_TPL_INCLUDE_DIRS_SET) - list(REMOVE_DUPLICATES FULL_TPL_LIBRARY_DIRS_SET) - - set(${PROJECT_NAME}_CONFIG_TPL_INCLUDE_DIRS ${FULL_TPL_INCLUDE_DIRS_SET}) - set(${PROJECT_NAME}_CONFIG_TPL_LIBRARY_DIRS ${FULL_TPL_LIBRARY_DIRS_SET}) 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 + # 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.") - #Config file for setting variables and finding include/library paths from the build directory - set(${PROJECT_NAME}_CONFIG_INCLUDE_DIRS ${FULL_INCLUDE_DIRS_SET}) - set(${PROJECT_NAME}_CONFIG_LIBRARY_DIRS ${FULL_LIBRARY_DIRS_SET}) - - # Write the specification of the rpath if necessary. This is only needed if we're building shared libraries. + # 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}") + 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() @@ -794,45 +818,12 @@ include(\"${${TRIBITS_PACKAGE}_BINARY_DIR}/${TRIBITS_PACKAGE}Config.cmake\")") # 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( - ${${PROJECT_NAME}_TRIBITS_DIR}/${TRIBITS_CMAKE_INSTALLATION_FILES_DIR}/TribitsProjectConfigTemplate.cmake.in - ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake ) - endif() - - if(${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES) - ###### - # Create a Makefile.export. for the build tree. This is the equivalent - # of the cmake version only slightly changed so that it can be directly imported into - # a Makefile. - ###### - - tribits_list_to_string("${${PROJECT_NAME}_CONFIG_LIBRARIES}" ${CMAKE_LINK_LIBRARY_FLAG} MAKEFILE_${PROJECT_NAME}_CONFIG_LIBRARIES) - tribits_list_to_string("${${PROJECT_NAME}_CONFIG_LIBRARY_DIRS}" ${CMAKE_LIBRARY_PATH_FLAG} MAKEFILE_${PROJECT_NAME}_CONFIG_LIBRARY_DIRS) - tribits_list_to_string("${${PROJECT_NAME}_CONFIG_INCLUDE_DIRS}" "-I" MAKEFILE_${PROJECT_NAME}_CONFIG_INCLUDE_DIRS) - tribits_list_to_string("${${PROJECT_NAME}_CONFIG_TPL_INCLUDE_DIRS}" "-I" MAKEFILE_${PROJECT_NAME}_CONFIG_TPL_INCLUDE_DIRS) - tribits_list_to_string("${${PROJECT_NAME}_CONFIG_TPL_LIBRARY_DIRS}" ${CMAKE_LIBRARY_PATH_FLAG} MAKEFILE_${PROJECT_NAME}_CONFIG_TPL_LIBRARY_DIRS) - #the TPL library names have to be treated differently - tribits_library_list_to_string("${${PROJECT_NAME}_CONFIG_TPL_LIBRARIES}" ${CMAKE_LINK_LIBRARY_FLAG} MAKEFILE_${PROJECT_NAME}_CONFIG_TPL_LIBRARIES) - - tribits_library_list_to_string("${${TPL_MPI_LIBRARIES}}" ${CMAKE_LINK_LIBRARY_FLAG} "MAKEFILE_TPL_MPI_LIBRARIES") - tribits_list_to_string("${${TPL_MPI_LIBRARY_DIRS}}" ${CMAKE_LIBRARY_PATH_FLAG} "MAKEFILE_TPL_MPI_LIBRARY_DIRS") - tribits_list_to_string("${${TPL_MPI_INCLUDE_DIRS}}" "-I" "MAKEFILE_TPL_MPI_INCLUDE_DIRS") - - tribits_list_to_string("${FULL_PACKAGE_SET}" "" MAKEFILE_FULL_PACKAGE_SET) - tribits_list_to_string("${FULL_TPL_SET}" "" MAKEFILE_FULL_TPL_SET) - - 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 "$") - configure_file( - ${${PROJECT_NAME}_TRIBITS_DIR}/${TRIBITS_CMAKE_INSTALLATION_FILES_DIR}/TribitsProjectConfigTemplate.export.in - ${PROJECT_BINARY_DIR}/Makefile.export.${PROJECT_NAME}) - endif() + "${tribitsInstallationDir}/TribitsProjectConfigTemplate.cmake.in" + "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" ) endif() ###### @@ -860,57 +851,40 @@ include(\"${${TRIBITS_PACKAGE}_BINARY_DIR}/${TRIBITS_PACKAGE}Config.cmake\")") foreach(PATH ${PATH_LIST}) set(RELATIVE_PATH "${RELATIVE_PATH}/..") endforeach() - set(${PROJECT_NAME}_CONFIG_INCLUDE_DIRS "\${CMAKE_CURRENT_LIST_DIR}/${RELATIVE_PATH}/${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}") - set(${PROJECT_NAME}_CONFIG_LIBRARY_DIRS "\${CMAKE_CURRENT_LIST_DIR}/${RELATIVE_PATH}/${${PROJECT_NAME}_INSTALL_LIB_DIR}") - # Write the specification of the rpath if necessary. This is only needed if we're building shared libraries. + # 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}) + set(SHARED_LIB_RPATH_COMMAND + "${CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG}${CMAKE_INSTALL_PREFIX}/${${PROJECT_NAME}_INSTALL_LIB_DIR}" + ) endif() - # Custom code in configuration file. - set(PROJECT_CONFIG_CODE "") - - tribits_set_compiler_vars_for_config_file(INSTALL_DIR) - if (${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES) - 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() + tribits_set_compiler_vars_for_config_file(INSTALL_DIR) - if(${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES) - ###### - # Create a Makefile.export. for the install tree. This is the equivalent - # of the cmake version only slightly changed so that it can be directly imported into - # a Makefile. - ###### + # Custom code in configuration file. + set(PROJECT_CONFIG_CODE "") - # Generated Make imports must use CMAKE_INSTALL_PREFIX, rather - # than the more platform friendly method of locating the libraries - # and includes using the config file path above. The underlying - # assumption here is that a generator that uses - # CMAKE_INSTALL_PREFIX is being used. - set(${PROJECT_NAME}_CONFIG_INCLUDE_DIRS ${CMAKE_INSTALL_PREFIX}/${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}) - set(${PROJECT_NAME}_CONFIG_LIBRARY_DIRS ${CMAKE_INSTALL_PREFIX}/${${PROJECT_NAME}_INSTALL_LIB_DIR}) + set(PDOLLAR "$") # Hack used in configure file below - tribits_list_to_string("${${PROJECT_NAME}_CONFIG_LIBRARY_DIRS}" ${CMAKE_LIBRARY_PATH_FLAG} MAKEFILE_${PROJECT_NAME}_CONFIG_LIBRARY_DIRS) - tribits_list_to_string("${${PROJECT_NAME}_CONFIG_INCLUDE_DIRS}" "-I" MAKEFILE_${PROJECT_NAME}_CONFIG_INCLUDE_DIRS) + 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.export.in - ${PROJECT_BINARY_DIR}/Makefile.export.${PROJECT_NAME}_install ) + "${${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}/Makefile.export.${PROJECT_NAME}_install - DESTINATION "${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}" - RENAME Makefile.export.${PROJECT_NAME} + FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config_install.cmake" + DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}/cmake/${PROJECT_NAME}" + RENAME ${PROJECT_NAME}Config.cmake ) endif() @@ -927,13 +901,14 @@ include(\"${${TRIBITS_PACKAGE}_BINARY_DIR}/${TRIBITS_PACKAGE}Config.cmake\")") COMPATIBILITY SameMajorVersion ) install( - FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake + 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/tribits_get_version_date.cmake b/cmake/tribits/core/package_arch/tribits_get_version_date.cmake index e51b64d8a422..e40365f0774f 100644 --- a/cmake/tribits/core/package_arch/tribits_get_version_date.cmake +++ b/cmake/tribits/core/package_arch/tribits_get_version_date.cmake @@ -11,6 +11,8 @@ # -P tribits_get_version_date.cmake # +cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR) + # A) Validate input if ("${PROJECT_NAME}" STREQUAL "") diff --git a/cmake/tribits/core/std_tpls/FindTPLCUDA.cmake b/cmake/tribits/core/std_tpls/FindTPLCUDA.cmake index 86028fd4b666..b21487909c51 100644 --- a/cmake/tribits/core/std_tpls/FindTPLCUDA.cmake +++ b/cmake/tribits/core/std_tpls/FindTPLCUDA.cmake @@ -109,11 +109,17 @@ if(NOT _CUDA_FAILURE) macro(package_add_cuda_library cuda_target) tribits_add_library(${cuda_target} ${ARGN} CUDALIBRARY) endmacro() - global_set(TPL_CUDA_LIBRARY_DIRS) - global_set(TPL_CUDA_INCLUDE_DIRS ${CUDA_TOOLKIT_INCLUDE}) - global_set(TPL_CUDA_LIBRARIES ${CUDA_CUDART_LIBRARY} ${CUDA_cublas_LIBRARY} + set(TPL_CUDA_INCLUDE_DIRS ${CUDA_TOOLKIT_INCLUDE}) + set(TPL_CUDA_LIBRARIES ${CUDA_CUDART_LIBRARY} ${CUDA_cublas_LIBRARY} ${CUDA_cufft_LIBRARY}) else() - set(TPL_ENABLE_CUDA OFF PARENT_SCOPE) message(FATAL_ERROR "\nDid not find acceptable version of CUDA compiler") endif() + +tribits_tpl_find_include_dirs_and_libraries(CUDA) + +unset(TPL_CUDA_INCLUDE_DIRS) +unset(TPL_CUDA_LIBRARIES) + +# NOTE: Above, we need to generate the CUDA::all_libs target and the +# CUDAConfig.cmake file that will also provide the CUDA::all_libs target. diff --git a/cmake/tribits/core/std_tpls/FindTPLMPI.cmake b/cmake/tribits/core/std_tpls/FindTPLMPI.cmake index b3a5bf4644c3..f4917fd6a050 100644 --- a/cmake/tribits/core/std_tpls/FindTPLMPI.cmake +++ b/cmake/tribits/core/std_tpls/FindTPLMPI.cmake @@ -50,3 +50,7 @@ if(WIN32 AND TPL_ENABLE_MPI) global_set(TPL_MPI_LIBRARIES ${MPI_LIBRARIES}) endif() +tribits_tpl_find_include_dirs_and_libraries(MPI) + +# NOTE: Above, we need to generate the MPI::all_libs target and the +# MPIConfig.cmake file that will also provide the MPI::all_libs target. diff --git a/cmake/tribits/core/utils/AddSubdirectories.cmake b/cmake/tribits/core/utils/AddSubdirectories.cmake index 5ce3615c5eb3..20ac8b164725 100644 --- a/cmake/tribits/core/utils/AddSubdirectories.cmake +++ b/cmake/tribits/core/utils/AddSubdirectories.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @MACRO: add_subdirectories() # # Macro that adds a list of subdirectories all at once (removes boiler-plate diff --git a/cmake/tribits/core/utils/AdvancedOption.cmake b/cmake/tribits/core/utils/AdvancedOption.cmake index 22eee54e1ebe..49eed3c915e2 100644 --- a/cmake/tribits/core/utils/AdvancedOption.cmake +++ b/cmake/tribits/core/utils/AdvancedOption.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @MACRO: advanced_option() # # Macro that sets an option and marks it as advanced (removes boiler-plate and diff --git a/cmake/tribits/core/utils/AdvancedSet.cmake b/cmake/tribits/core/utils/AdvancedSet.cmake index 1939e14e67b1..97cf6d2643c7 100644 --- a/cmake/tribits/core/utils/AdvancedSet.cmake +++ b/cmake/tribits/core/utils/AdvancedSet.cmake @@ -38,7 +38,6 @@ # @HEADER -# # @MACRO: advanced_set() # # Macro that sets a variable and marks it as advanced (removes boiler-plate diff --git a/cmake/tribits/core/utils/AppendCmndlineArgs.cmake b/cmake/tribits/core/utils/AppendCmndlineArgs.cmake index f444b3daecd6..f004a71c772a 100644 --- a/cmake/tribits/core/utils/AppendCmndlineArgs.cmake +++ b/cmake/tribits/core/utils/AppendCmndlineArgs.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @FUNCTION: append_cmndline_args() # # Utility function that appends command-line arguments to a variable of diff --git a/cmake/tribits/core/utils/AppendGlob.cmake b/cmake/tribits/core/utils/AppendGlob.cmake index 7576f2595cce..14eab3155da6 100644 --- a/cmake/tribits/core/utils/AppendGlob.cmake +++ b/cmake/tribits/core/utils/AppendGlob.cmake @@ -39,7 +39,7 @@ include(AppendSet) -# + # @MACRO: append_glob() # # Utility macro that does a ``file(GLOB ...)`` and appends to an existing list diff --git a/cmake/tribits/core/utils/AppendGlobalSet.cmake b/cmake/tribits/core/utils/AppendGlobalSet.cmake index 1280ffb2ae98..51251dc326e9 100644 --- a/cmake/tribits/core/utils/AppendGlobalSet.cmake +++ b/cmake/tribits/core/utils/AppendGlobalSet.cmake @@ -40,7 +40,7 @@ include(GlobalSet) include(AssertDefined) -# + # @FUNCTION: append_global_set() # # Utility macro that appends arguments to a global variable (reduces diff --git a/cmake/tribits/core/utils/AppendSet.cmake b/cmake/tribits/core/utils/AppendSet.cmake index 2ae8decbf560..592a6de189ab 100644 --- a/cmake/tribits/core/utils/AppendSet.cmake +++ b/cmake/tribits/core/utils/AppendSet.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @MACRO: append_set() # # Utility function to append elements to a variable (reduces boiler-plate diff --git a/cmake/tribits/core/utils/AppendStringVar.cmake b/cmake/tribits/core/utils/AppendStringVar.cmake index 63d5cc7b4a7f..9b4e553a1494 100644 --- a/cmake/tribits/core/utils/AppendStringVar.cmake +++ b/cmake/tribits/core/utils/AppendStringVar.cmake @@ -40,7 +40,7 @@ include(ConcatStrings) include(PrintVar) -# + # @FUNCTION: append_string_var() # # Append strings to an existing string variable (reduces boiler-place code and @@ -55,6 +55,10 @@ include(PrintVar) # If one wants to ignore the meaning of these special characters and are okay # with just adding one string at a time, then use `append_string_var_ext()`_. # +# **DEPRECATED**: Instead, use:: +# +# string(APPEND "" "" ...) +# function(append_string_var STRING_VAR_OUT) #message("APPEND_STRING_VAR: ${STRING_VAR_OUT} {${ARGN}}") concat_strings( STRING_VAR "${${STRING_VAR_OUT}}" ${ARGN} ) @@ -64,7 +68,6 @@ function(append_string_var STRING_VAR_OUT) endfunction() -# # @FUNCTION: append_string_var_ext() # # Append a single string to an existing string variable, ignoring ';' (reduces diff --git a/cmake/tribits/core/utils/AppendStringVarWithSep.cmake b/cmake/tribits/core/utils/AppendStringVarWithSep.cmake index b08a042e791e..c671ff582ea0 100644 --- a/cmake/tribits/core/utils/AppendStringVarWithSep.cmake +++ b/cmake/tribits/core/utils/AppendStringVarWithSep.cmake @@ -39,7 +39,7 @@ include(ConcatStrings) -# + # @FUNCTION: append_string_var_with_sep() # # Append strings to a given string variable, joining them using a separator diff --git a/cmake/tribits/core/utils/AssertDefined.cmake b/cmake/tribits/core/utils/AssertDefined.cmake index 6b60ed267ae9..a7918483ec32 100644 --- a/cmake/tribits/core/utils/AssertDefined.cmake +++ b/cmake/tribits/core/utils/AssertDefined.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @FUNCTION: assert_defined() # # Assert that a variable is defined and if not call ``message(SEND_ERROR @@ -81,6 +81,6 @@ function(assert_defined VARS) endforeach() endfunction() -# ToDo: The VARS arg This really needs to be repalced with ${ARGV}. I fear +# ToDo: The VARS arg This really needs to be replaced with ${ARGV}. I fear # that only the first arg passed in is asserted. However, to change this now # is breaking backward compatibility. diff --git a/cmake/tribits/core/utils/CMakeBuildTypesList.cmake b/cmake/tribits/core/utils/CMakeBuildTypesList.cmake index f10c485ddc1e..381f923e8467 100644 --- a/cmake/tribits/core/utils/CMakeBuildTypesList.cmake +++ b/cmake/tribits/core/utils/CMakeBuildTypesList.cmake @@ -39,3 +39,6 @@ set(CMAKE_BUILD_TYPES_LIST DEBUG MINSIZEREL RELEASE RELWITHDEBINFO NONE) + +set(CMAKE_CONFIG_FILE_BUILD_TYPES_LIST + Debug Release RelWithDebInfo MinSizeRel NoConfig) diff --git a/cmake/tribits/core/utils/CombinedOption.cmake b/cmake/tribits/core/utils/CombinedOption.cmake index 6d5480931509..2cf0c8dd3d13 100644 --- a/cmake/tribits/core/utils/CombinedOption.cmake +++ b/cmake/tribits/core/utils/CombinedOption.cmake @@ -42,7 +42,6 @@ include(MultilineSet) include(ConcatStrings) -# # @FUNCTION: combined_option() # # Set up a ``BOOL`` cache variable (i.e. an option) based on a set of diff --git a/cmake/tribits/core/utils/ConcatStrings.cmake b/cmake/tribits/core/utils/ConcatStrings.cmake index 0f49ac1a15ca..a2fdc3c41ae7 100644 --- a/cmake/tribits/core/utils/ConcatStrings.cmake +++ b/cmake/tribits/core/utils/ConcatStrings.cmake @@ -40,7 +40,6 @@ include(PrintVar) -# # @FUNCTION: concat_strings() # # Concatenate a set of string arguments. diff --git a/cmake/tribits/core/utils/DriveAdvancedTest.cmake b/cmake/tribits/core/utils/DriveAdvancedTest.cmake index 1950cac801b1..87a4a82308af 100644 --- a/cmake/tribits/core/utils/DriveAdvancedTest.cmake +++ b/cmake/tribits/core/utils/DriveAdvancedTest.cmake @@ -58,11 +58,29 @@ function(print_uptime PREFIX_STR) endfunction() -function(print_single_check_result MSG_BEGIN TEST_CASE_PASSED_IN) +function(print_single_check_result msgBegin TEST_CASE_PASSED_IN) if (TEST_CASE_PASSED_IN) - message("${MSG_BEGIN} [PASSED]") + message("${msgBegin} [PASSED]") else() - message("${MSG_BEGIN} [FAILED]") + message("${msgBegin} [FAILED]") + endif() +endfunction() + + +function(print_any_regex_pass_match msgBegin regexMatch) + if (regexMatch) + message("${msgBegin} [PASSED]") + else() + message("${msgBegin} [not matched]") + endif() +endfunction() + + +function(print_any_regex_fail_match msgBegin regexMatch) + if (regexMatch) + message("${msgBegin} [FAILED]") + else() + message("${msgBegin} [does not match]") endif() endfunction() @@ -160,10 +178,12 @@ macro(setup_and_run_test_idx_cmnd_block) # Set up the TEST_ command block join( TEST_CMND_STR " " TRUE ${TEST_${CMND_IDX}_CMND} ) + string(REPLACE "${LIST_SEPARATOR}" ";" TEST_CMND_STR "${TEST_CMND_STR}") message("Running: ${TEST_CMND_STR}\n") set(EXEC_CMND COMMAND ${TEST_${CMND_IDX}_CMND}) + string(REPLACE "${LIST_SEPARATOR}" "\\\;" EXEC_CMND "${EXEC_CMND}") - # Set up the workig directory that this TEST_ CMND block will run in + # Set up the working directory that this TEST_ CMND block will run in set(WORKING_DIR_SET) if (TEST_${CMND_IDX}_WORKING_DIRECTORY) @@ -247,16 +267,16 @@ macro(determine_test_idx_cmnd_block_pass_fail) "TEST_${CMND_IDX}: Pass criteria = Pass Any" ${TEST_CASE_PASSED} ) elseif (TEST_${CMND_IDX}_PASS_REGULAR_EXPRESSION) - string(REGEX MATCH "${TEST_${CMND_IDX}_PASS_REGULAR_EXPRESSION}" - MATCH_STR "${TEST_CMND_OUT}" ) - if (MATCH_STR) - set(TEST_CASE_PASSED TRUE) - else() - set(TEST_CASE_PASSED FALSE) - endif() - print_single_check_result( - "TEST_${CMND_IDX}: Pass criteria = Match REGEX {${TEST_${CMND_IDX}_PASS_REGULAR_EXPRESSION}}" - ${TEST_CASE_PASSED}) + set(TEST_CASE_PASSED FALSE) + foreach(REGEX_STR ${TEST_${CMND_IDX}_PASS_REGULAR_EXPRESSION}) + string(REGEX MATCH "${REGEX_STR}" MATCH_STR "${TEST_CMND_OUT}") + if (MATCH_STR) + set(TEST_CASE_PASSED TRUE) + endif() + print_any_regex_pass_match( + "TEST_${CMND_IDX}: Pass criteria = Match any REGEX {${REGEX_STR}}" + "${MATCH_STR}") + endforeach() elseif (TEST_${CMND_IDX}_PASS_REGULAR_EXPRESSION_ALL) set(TEST_CASE_PASSED TRUE) foreach(REGEX_STR ${TEST_${CMND_IDX}_PASS_REGULAR_EXPRESSION_ALL}) @@ -270,7 +290,7 @@ macro(determine_test_idx_cmnd_block_pass_fail) set(TEST_CASE_PASSED FALSE) endif() print_single_check_result( - "TEST_${CMND_IDX}: Pass criteria = Match REGEX {${REGEX_STR}}" + "TEST_${CMND_IDX}: Pass criteria = Match all REGEX {${REGEX_STR}}" ${THIS_REGEX_MATCHED} ) endforeach() else() @@ -286,14 +306,15 @@ macro(determine_test_idx_cmnd_block_pass_fail) # B) Check for failing regex matching? if (TEST_${CMND_IDX}_FAIL_REGULAR_EXPRESSION) - string(REGEX MATCH "${TEST_${CMND_IDX}_FAIL_REGULAR_EXPRESSION}" - MATCH_STR "${TEST_CMND_OUT}" ) - if (MATCH_STR) - set(TEST_CASE_PASSED FALSE) - endif() - print_single_check_result( - "TEST_${CMND_IDX}: Pass criteria = Not match REGEX {${TEST_${CMND_IDX}_FAIL_REGULAR_EXPRESSION}}" - ${TEST_CASE_PASSED} ) + foreach(REGEX_STR ${TEST_${CMND_IDX}_FAIL_REGULAR_EXPRESSION}) + string(REGEX MATCH "${REGEX_STR}" MATCH_STR "${TEST_CMND_OUT}") + if (MATCH_STR) + set(TEST_CASE_PASSED FALSE) + endif() + print_any_regex_fail_match( + "TEST_${CMND_IDX}: Pass criteria = Not match REGEX {${REGEX_STR}}" + "${MATCH_STR}") + endforeach() endif() # C) Check for return code always 0? @@ -387,7 +408,7 @@ function(drive_advanced_test) if (CMND_IDX EQUAL 0) set(TEST_NAMES_STR "TEST_0") else() - append_string_var( TEST_NAMES_STR ", TEST_${CMND_IDX}" ) + string(APPEND TEST_NAMES_STR ", TEST_${CMND_IDX}" ) endif() endforeach() message("Running test commands: ${TEST_NAMES_STR}") diff --git a/cmake/tribits/core/utils/DualScopeAppendCmndlineArgs.cmake b/cmake/tribits/core/utils/DualScopeAppendCmndlineArgs.cmake index 65c6738d8b65..4dd32caaa9b0 100644 --- a/cmake/tribits/core/utils/DualScopeAppendCmndlineArgs.cmake +++ b/cmake/tribits/core/utils/DualScopeAppendCmndlineArgs.cmake @@ -40,7 +40,7 @@ include(AppendCmndlineArgs) include(DualScopeSet) -# + # @MACRO: dual_scope_append_cmndline_args() # # Utility function that appends command-line arguments to a variable of diff --git a/cmake/tribits/core/utils/DualScopePrependCmndlineArgs.cmake b/cmake/tribits/core/utils/DualScopePrependCmndlineArgs.cmake index a4a8a627cd47..432c27f72251 100644 --- a/cmake/tribits/core/utils/DualScopePrependCmndlineArgs.cmake +++ b/cmake/tribits/core/utils/DualScopePrependCmndlineArgs.cmake @@ -40,7 +40,7 @@ include(PrependCmndlineArgs) include(DualScopeSet) -# + # @MACRO: dual_scope_prepend_cmndline_args() # # Utility function that prepends command-line arguments to a variable of diff --git a/cmake/tribits/core/utils/DualScopeSet.cmake b/cmake/tribits/core/utils/DualScopeSet.cmake index 8ea8ecb5fa06..e17234628acb 100644 --- a/cmake/tribits/core/utils/DualScopeSet.cmake +++ b/cmake/tribits/core/utils/DualScopeSet.cmake @@ -38,7 +38,6 @@ # @HEADER -# # @MACRO: dual_scope_set() # # Macro that sets a variable name both in the current scope and the diff --git a/cmake/tribits/core/utils/GlobalNullSet.cmake b/cmake/tribits/core/utils/GlobalNullSet.cmake index 728d06f06c4e..ae1125bc3012 100644 --- a/cmake/tribits/core/utils/GlobalNullSet.cmake +++ b/cmake/tribits/core/utils/GlobalNullSet.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @MACRO: global_null_set() # # Set a variable as a null internal global (cache) variable (removes diff --git a/cmake/tribits/core/utils/GlobalSet.cmake b/cmake/tribits/core/utils/GlobalSet.cmake index 7eb1ba20a421..b3c04aae0b20 100644 --- a/cmake/tribits/core/utils/GlobalSet.cmake +++ b/cmake/tribits/core/utils/GlobalSet.cmake @@ -38,7 +38,6 @@ # @HEADER -# # @MACRO: global_set() # # Set a variable as an internal global (cache) variable (removes boiler-plate diff --git a/cmake/tribits/core/utils/Join.cmake b/cmake/tribits/core/utils/Join.cmake index 0f9fe323bce1..288999b8e67d 100644 --- a/cmake/tribits/core/utils/Join.cmake +++ b/cmake/tribits/core/utils/Join.cmake @@ -38,7 +38,6 @@ # @HEADER -# # @FUNCTION: join() # # Join a set of strings into a single string using a join string. diff --git a/cmake/tribits/core/utils/MessageWrapper.cmake b/cmake/tribits/core/utils/MessageWrapper.cmake index 59b17d13a15c..bdcd9e5e2966 100644 --- a/cmake/tribits/core/utils/MessageWrapper.cmake +++ b/cmake/tribits/core/utils/MessageWrapper.cmake @@ -37,14 +37,10 @@ # ************************************************************************ # @HEADER -if (MESSAGE_WRAPPER_INCLUDED) - return() -endif() -set(MESSAGE_WRAPPER_INCLUDED TRUE) +include_guard() include(GlobalSet) -# # @FUNCTION: message_wrapper() # # Function that wraps the standard CMake/CTest ``message()`` function call in @@ -72,11 +68,13 @@ include(GlobalSet) # verify that they say the right thing. # function(message_wrapper) - #message("MESSAGE_WRAPPER: ${ARGN}") + cmake_parse_arguments(PARSE_ARGV 0 FWD "" "" "") + #message("MESSAGE_WRAPPER: ${FWD_UNPARSED_ARGUMENTS}") if (MESSAGE_WRAPPER_UNIT_TEST_MODE) - global_set(MESSAGE_WRAPPER_INPUT "${MESSAGE_WRAPPER_INPUT}" ${ARGN}) + global_set(MESSAGE_WRAPPER_INPUT "${MESSAGE_WRAPPER_INPUT}" + ${FWD_UNPARSED_ARGUMENTS}) else() - message(${ARGN}) + message(${FWD_UNPARSED_ARGUMENTS}) endif() endfunction() diff --git a/cmake/tribits/core/utils/MultilineSet.cmake b/cmake/tribits/core/utils/MultilineSet.cmake index 923d65c5d217..dde0b471e424 100644 --- a/cmake/tribits/core/utils/MultilineSet.cmake +++ b/cmake/tribits/core/utils/MultilineSet.cmake @@ -38,7 +38,6 @@ # @HEADER -# # @FUNCTION: multiline_set() # # Function to set a single string by concatenating a list of separate strings diff --git a/cmake/tribits/core/utils/ParseVariableArguments.cmake b/cmake/tribits/core/utils/ParseVariableArguments.cmake index a3c278a7b8c0..92e1b060fd15 100644 --- a/cmake/tribits/core/utils/ParseVariableArguments.cmake +++ b/cmake/tribits/core/utils/ParseVariableArguments.cmake @@ -43,7 +43,7 @@ include(CMakeParseArguments) # natively implemented function cmake_parse_arguments() will get used! macro(parse_arguments_deprecated_warning) - message(WARNING "parse_arguments() is deprecated and should not be used." + message(DEPRECATION "parse_arguments() is deprecated and should not be used." " Instead use cmake_parse_arguments()") endmacro() @@ -57,7 +57,7 @@ function(parse_arguments_dump_output OUTPUT_STR) endif() endfunction() -# + # @MACRO: parse_arguments() # # Parse a set of macro/function input arguments into different lists. This @@ -248,12 +248,12 @@ endmacro() # NOTE: If the above function turns out to be a performance bottle neck, there # are a few things that could be done to improve performance. One thing you -# could do is repalce the o(len(arg_names)) and o(len(option_names)) lookups +# could do is replace the o(len(arg_names)) and o(len(option_names)) lookup # with o(1) lookups by creating CMake variables of the name # ${OUTER_FUNC_NAME}_arg_ and then just look of that variable exists # or not. That should use a hash function. That might actually slow things # down for short lists however so we would have to measure, measure, -# measure. I would have to pass in the function/macro name to disabiguate -# the variable names. It would really be better if cmake would provide a +# measure. I would have to pass in the function/macro name to disambiguate +# the variable names. It would really be better if CMake would provide a # sorted list find operation. That would make this much faster for large # numbers of argument and option names. diff --git a/cmake/tribits/core/utils/PrependCmndlineArgs.cmake b/cmake/tribits/core/utils/PrependCmndlineArgs.cmake index 29ee4c4b9110..08425aa2dcf6 100644 --- a/cmake/tribits/core/utils/PrependCmndlineArgs.cmake +++ b/cmake/tribits/core/utils/PrependCmndlineArgs.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @FUNCTION: prepend_cmndline_args() # # Utility function that prepends command-line arguments to a variable of diff --git a/cmake/tribits/core/utils/PrependGlobalSet.cmake b/cmake/tribits/core/utils/PrependGlobalSet.cmake index edd27338675c..1c827783ea14 100644 --- a/cmake/tribits/core/utils/PrependGlobalSet.cmake +++ b/cmake/tribits/core/utils/PrependGlobalSet.cmake @@ -40,7 +40,7 @@ include(GlobalSet) include(AssertDefined) -# + # @MACRO: prepend_global_set() # # Utility macro that prepends arguments to a global variable (reduces diff --git a/cmake/tribits/core/utils/PrependSet.cmake b/cmake/tribits/core/utils/PrependSet.cmake index 3b20d40d1411..0f022c83c779 100644 --- a/cmake/tribits/core/utils/PrependSet.cmake +++ b/cmake/tribits/core/utils/PrependSet.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @MACRO: prepend_set() # # Utility macro to prepend elements to a variable (reduces boiler-plate code). diff --git a/cmake/tribits/core/utils/PrintNonemptyVar.cmake b/cmake/tribits/core/utils/PrintNonemptyVar.cmake index 7c2b17ee4f15..064357adda3f 100644 --- a/cmake/tribits/core/utils/PrintNonemptyVar.cmake +++ b/cmake/tribits/core/utils/PrintNonemptyVar.cmake @@ -41,7 +41,6 @@ include(AssertDefined) include(PrintVar) -# # @FUNCTION: print_nonempty_var() # # Print a defined variable giving its name then value only if it is not empty. diff --git a/cmake/tribits/core/utils/PrintNonemptyVarWithSpaces.cmake b/cmake/tribits/core/utils/PrintNonemptyVarWithSpaces.cmake index cfb1c7148e06..64ebe2a579f8 100644 --- a/cmake/tribits/core/utils/PrintNonemptyVarWithSpaces.cmake +++ b/cmake/tribits/core/utils/PrintNonemptyVarWithSpaces.cmake @@ -40,7 +40,7 @@ include(AssertDefined) include(AppendStringVarWithSep) -# + # @FUNCTION: print_nonempty_var_with_spaces() # # Print a defined variable giving its name then value printed with spaces diff --git a/cmake/tribits/core/utils/PrintVar.cmake b/cmake/tribits/core/utils/PrintVar.cmake index 7b60a9b0c9dc..bf0290aa1b41 100644 --- a/cmake/tribits/core/utils/PrintVar.cmake +++ b/cmake/tribits/core/utils/PrintVar.cmake @@ -37,12 +37,8 @@ # ************************************************************************ # @HEADER -if (PRINT_VAR_INCLUDED) - return() -endif() -set(PRINT_VAR_INCLUDED TRUE) +include_guard() -# # @FUNCTION: print_var() # # Unconditionally print a variable giving its name then value. diff --git a/cmake/tribits/core/utils/PrintVarWithSpaces.cmake b/cmake/tribits/core/utils/PrintVarWithSpaces.cmake new file mode 100644 index 000000000000..356826756a94 --- /dev/null +++ b/cmake/tribits/core/utils/PrintVarWithSpaces.cmake @@ -0,0 +1,66 @@ +# @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 + +include(AssertDefined) +include(AppendStringVarWithSep) + + +# @FUNCTION: print_var_with_spaces() +# +# Print a defined variable giving its name then value printed with spaces +# instead of ``';'``. +# +# Usage:: +# +# print_var_with_spaces( ) +# +# Prints the variable as:: +# +# : ... +# +# If ``$`` is ``TRUE`` on input, then the variable is not +# touched. If however, the variable ``$`` is not ``TRUE`` on +# input, then it is set to ``TRUE`` on output. +# +function(print_var_with_spaces VARIBLE_NAME PRINTED_VAR_OUT) + assert_defined(VARIBLE_NAME) + string(REPLACE ";" " " OUTSTR "${${VARIBLE_NAME}}") + message("-- ${VARIBLE_NAME}: ${OUTSTR}") + set(${PRINTED_VAR_OUT} TRUE PARENT_SCOPE) +endfunction() diff --git a/cmake/tribits/core/utils/RemoveGlobalDuplicates.cmake b/cmake/tribits/core/utils/RemoveGlobalDuplicates.cmake index 69ee668c46e7..f43ca43c89d2 100644 --- a/cmake/tribits/core/utils/RemoveGlobalDuplicates.cmake +++ b/cmake/tribits/core/utils/RemoveGlobalDuplicates.cmake @@ -40,7 +40,7 @@ include(AssertDefined) include(GlobalSet) -# + # @FUNCTION: remove_global_duplicates() # # Remove duplicate elements from a global list variable (removes boiler-plate diff --git a/cmake/tribits/core/utils/SetAndIncDirs.cmake b/cmake/tribits/core/utils/SetAndIncDirs.cmake index a305b424debe..80d4f688c40b 100644 --- a/cmake/tribits/core/utils/SetAndIncDirs.cmake +++ b/cmake/tribits/core/utils/SetAndIncDirs.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @MACRO: set_and_inc_dirs() # # Set a variable to an include directory and call ``include_directories()`` diff --git a/cmake/tribits/core/utils/SetCacheOnOffEmpty.cmake b/cmake/tribits/core/utils/SetCacheOnOffEmpty.cmake index caa3b1d3b493..0d9970731f54 100644 --- a/cmake/tribits/core/utils/SetCacheOnOffEmpty.cmake +++ b/cmake/tribits/core/utils/SetCacheOnOffEmpty.cmake @@ -38,7 +38,6 @@ # @HEADER -# # @FUNCTION: set_cache_on_off_empty() # # Usage:: diff --git a/cmake/tribits/core/utils/SetDefault.cmake b/cmake/tribits/core/utils/SetDefault.cmake index 3e2cdae73d28..87a25e275a29 100644 --- a/cmake/tribits/core/utils/SetDefault.cmake +++ b/cmake/tribits/core/utils/SetDefault.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @MACRO: set_default() # # Give a local variable a default value if a non-empty value is not already diff --git a/cmake/tribits/core/utils/SetDefaultAndFromEnv.cmake b/cmake/tribits/core/utils/SetDefaultAndFromEnv.cmake index 7f604c378f04..b407b571052a 100644 --- a/cmake/tribits/core/utils/SetDefaultAndFromEnv.cmake +++ b/cmake/tribits/core/utils/SetDefaultAndFromEnv.cmake @@ -38,11 +38,10 @@ # @HEADER - include(SetDefault) include(PrintVar) -# + # @MACRO: set_default_and_from_env() # # Set a default value for a local variable and override from an environment diff --git a/cmake/tribits/core/utils/Split.cmake b/cmake/tribits/core/utils/Split.cmake index 0a5f1ceb2b82..e18250c4b990 100644 --- a/cmake/tribits/core/utils/Split.cmake +++ b/cmake/tribits/core/utils/Split.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @FUNCTION: split() # # Split a string variable into a string array/list variable. diff --git a/cmake/tribits/core/utils/TimingUtils.cmake b/cmake/tribits/core/utils/TimingUtils.cmake index 19d39b53ea85..a83445663f02 100644 --- a/cmake/tribits/core/utils/TimingUtils.cmake +++ b/cmake/tribits/core/utils/TimingUtils.cmake @@ -46,7 +46,7 @@ include(Split) -# + # @FUNCTION: timer_get_raw_seconds() # # Return the raw time in seconds (nano-second accuracy) since epoch, i.e., @@ -76,7 +76,6 @@ function(timer_get_raw_seconds SECONDS_DEC_OUT) endfunction() -# # @FUNCTION: timer_get_rel_seconds() # # Return the relative time between start and stop seconds. @@ -114,7 +113,6 @@ function(timer_get_rel_seconds ABS_SECONDS_DEC_START endfunction() -# # @FUNCTION: timer_print_rel_time() # # Print the relative time between start and stop timers in ``ms`` diff --git a/cmake/tribits/core/utils/TribitsFilepathHelpers.cmake b/cmake/tribits/core/utils/TribitsFilepathHelpers.cmake index a367ff966d9c..1ee0489445c9 100644 --- a/cmake/tribits/core/utils/TribitsFilepathHelpers.cmake +++ b/cmake/tribits/core/utils/TribitsFilepathHelpers.cmake @@ -1,7 +1,7 @@ include(MessageWrapper) include(Split) -# + # @FUNCTION: tribits_dir_is_basedir() # # Function to determine if a given path is a base dir of another path. @@ -49,7 +49,6 @@ function(tribits_dir_is_basedir absBaseDir absFullDir isBaseDirVarOut) endfunction() -# # @FUNCTION: tribits_get_dir_array_below_base_dir() # # Returns the array of directories below a base directory. diff --git a/cmake/tribits/core/utils/TribitsGatherBuildTargets.cmake b/cmake/tribits/core/utils/TribitsGatherBuildTargets.cmake new file mode 100644 index 000000000000..6056d777f5d8 --- /dev/null +++ b/cmake/tribits/core/utils/TribitsGatherBuildTargets.cmake @@ -0,0 +1,104 @@ +# @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 to get a list all of buildsystem targets of the type matching the +# given list starting in a subdir and in below subdirs. +# +# Usage:: +# +# tribits_get_all_build_targets_including_in_subdirs( +# ) +# +# On output the variable ```` will contain a list of all of +# the build targets match match the targets types listed in +# ```` which is a quoted list of the form +# ``";;..."``. For example, to get all of the +# real library and executable targets, run:: +# +# tribits_get_all_build_targets_including_in_subdirs( +# +# "STATIC_LIBRARY;SHARED_LIBRARY;EXECUTABLE" +# ) +# +function(tribits_get_all_build_targets_including_in_subdirs srcdir targetTypesList + targetsListVarOut + ) + + set(targetsList "") + + # Recurse into subdirectories. + get_property(dirs DIRECTORY "${srcdir}" PROPERTY SUBDIRECTORIES) + foreach(d IN LISTS dirs) + tribits_get_all_build_targets_including_in_subdirs(${d} "${targetTypesList}" + targetsSubdirList) + list(APPEND targetsList ${targetsSubdirList}) + endforeach() + + # Get the targets from this directory. + get_property(allTargetsThisDir DIRECTORY "${srcdir}" PROPERTY BUILDSYSTEM_TARGETS) + tribits_filter_only_build_targets(allTargetsThisDir "${targetTypesList}" + buildTargetsThisDir) + list(APPEND targetsList ${buildTargetsThisDir}) + + # Return + set(${targetsListVarOut} ${targetsList} PARENT_SCOPE) + +endfunction() + + +function(tribits_filter_only_build_targets targetListInVar targetTypesList + targetListOutVar + ) + + set(targetListOut "") + + foreach (target IN LISTS ${targetListInVar}) + get_property(targetType TARGET ${target} PROPERTY TYPE) + foreach (desiredTargetType IN ITEMS ${targetTypesList}) + if (desiredTargetType STREQUAL targetType) + list(APPEND targetListOut ${target}) + break() + endif() + endforeach() + endforeach() + + set(${targetListOutVar} ${targetListOut} PARENT_SCOPE) + +endfunction() diff --git a/cmake/tribits/core/utils/TribitsGetImportedLocationProperty.cmake b/cmake/tribits/core/utils/TribitsGetImportedLocationProperty.cmake new file mode 100644 index 000000000000..8e22614b16d9 --- /dev/null +++ b/cmake/tribits/core/utils/TribitsGetImportedLocationProperty.cmake @@ -0,0 +1,62 @@ +# @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 + +include_guard() + +include(CMakeBuildTypesList) + + +# Return the value of the target property IMPORTED_LOCATION_ for every +# known and returns the fist non-null value. Otherwise, returns +# empty. +# +function(tribits_get_imported_location_property targetName importedLocationOut) + + set(importedLocation "") + foreach (cmakeBuildType IN LISTS CMAKE_CONFIG_FILE_BUILD_TYPES_LIST) + string(TOUPPER ${cmakeBuildType} cmakeBuildTypeUpper) + get_target_property(importedLoc ${targetName} + IMPORTED_LOCATION_${cmakeBuildTypeUpper}) + if (importedLoc) + set(importedLocation "${importedLoc}") + break() + endif() + endforeach() + set(${importedLocationOut} ${importedLocation} PARENT_SCOPE) +endfunction() diff --git a/cmake/tribits/core/utils/TribitsParseArgumentsHelpers.cmake b/cmake/tribits/core/utils/TribitsParseArgumentsHelpers.cmake new file mode 100644 index 000000000000..75327668f67f --- /dev/null +++ b/cmake/tribits/core/utils/TribitsParseArgumentsHelpers.cmake @@ -0,0 +1,156 @@ +# @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 + + +################################################################################ +# +# This module contains function to aid with the usage of +# cmake_parse_arguments(). +# +################################################################################ + + +include(MessageWrapper) + + +# @FUNCTION: tribits_check_for_unparsed_arguments() +# +# Check to see if there are unparsed arguments after calling +# ``cmake_parse_arguments()`` or ``tribits_parse_arguments_from_list()`` +# +# Usage:: +# +# tribits_check_for_unparsed_arguments([]) +# +# If `` is not given, it is assumed to be `PARSE`. +# +function(tribits_check_for_unparsed_arguments) + + if ("${ARGC}" GREATER 1) + message(FATAL_ERROR + "ERROR tribits_check_for_unparsed_arguments() passed arguments '${ARGV}' but only accepts 0 or 1 arguments (for )") + endif() + + set(prefix "PARSE") + foreach(arg ${ARGV}) + set(prefix "${arg}") + endforeach() + + if( NOT "${${prefix}_UNPARSED_ARGUMENTS}" STREQUAL "") + message_wrapper( + ${${PROJECT_NAME}_CHECK_FOR_UNPARSED_ARGUMENTS} + "Arguments passed in unrecognized. ${prefix}_UNPARSED_ARGUMENTS = '${${prefix}_UNPARSED_ARGUMENTS}'" + ) + endif() + +endfunction() + + +# @MACRO: tribits_assert_parse_arg_one_or_more_values() +# +# Assert that a set of parse arguments have at least one value +# +# Usage:: +# +# tribits_assert_parse_arg_one_or_more_values( ...) +# +macro(tribits_assert_parse_arg_one_or_more_values PREFIX) + foreach(ARGNAME ${ARGN}) + set(PREFIX_ARGNAME "${PREFIX}_${ARGNAME}") + list( LENGTH ${PREFIX_ARGNAME} ARG_NUM_VALS ) + if (ARG_NUM_VALS LESS 1) + message_wrapper(FATAL_ERROR + "ERROR: ${ARGNAME} must have at least one value!" ) + return() + # NOTE: The return() is needed in unit testing mode + endif() + endforeach() +endmacro() + + +# @MACRO: tribits_assert_parse_arg_zero_or_one_value() +# +# Assert a set of parse arguments have zero or one value +# +# Usage:: +# +# tribits_assert_parse_arg_zero_or_one_value( ...) +# +macro(tribits_assert_parse_arg_zero_or_one_value PREFIX) + foreach(ARGNAME ${ARGN}) + set(PREFIX_ARGNAME "${PREFIX}_${ARGNAME}") + if (NOT "${${PREFIX_ARGNAME}}" STREQUAL "") + list( LENGTH ${PREFIX_ARGNAME} ARG_NUM_VALS ) + if (ARG_NUM_VALS GREATER 1) + message_wrapper(FATAL_ERROR + "ERROR: ${ARGNAME}='${${PREFIX_ARGNAME}}' can not have more than one value!" ) + return() + # NOTE: The macro return() is needed in unit testing mode + endif() + endif() + endforeach() +endmacro() + + +# @MACRO: tribits_assert_parse_arg_one_value() +# +# Assert that a set of parse arguments have exactly one value +# +# Usage:: +# +# tribits_assert_parse_arg_one_value( ...) +# +macro(tribits_assert_parse_arg_one_value PREFIX) + foreach(ARGNAME ${ARGN}) + set(PREFIX_ARGNAME "${PREFIX}_${ARGNAME}") + if (NOT "${${PREFIX_ARGNAME}}" STREQUAL "") + list( LENGTH ${PREFIX_ARGNAME} ARG_NUM_VALS ) + if (NOT ARG_NUM_VALS EQUAL 1) + message_wrapper(FATAL_ERROR + "ERROR: ${ARGNAME}='${${PREFIX_ARGNAME}}' Must have exactly one value!" ) + return() + # NOTE: The macro return() is needed in unit testing mode + endif() + endif() + endforeach() +endmacro() + + +# NOTE: Above, we use macros for the assert functions with returns in unit +# test mode so that it will abort the calling function these are called from! diff --git a/cmake/tribits/core/utils/TribitsPrintList.cmake b/cmake/tribits/core/utils/TribitsPrintList.cmake new file mode 100644 index 000000000000..227ab9fcfa36 --- /dev/null +++ b/cmake/tribits/core/utils/TribitsPrintList.cmake @@ -0,0 +1,73 @@ +# @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 + +include_guard() + +# @FUNCTION: tribits_print_list() +# +# Unconditionally the name and values of a list var. +# +# Usage:: +# +# tribits_print_list() +# +# This prints:: +# +# -- (size=): +# -- +# -- +# ... +# -- +# +# The variable ```` can be defined or undefined or empty. This uses +# an explicit "-- " line prefix so that it prints nice even on Windows CMake. +# +function(tribits_print_list listName) + list(LENGTH ${listName} len) + message("-- " "${listName} (size=${len})") + foreach(ele IN LISTS ${listName}) + message("-- " " '${ele}'") + endforeach() +endfunction() + +# NOTE: Above, I was not able to call message_wrapper() directly because it +# was removing the ';' in array arguments. This broke a bunch of unit tests. +# Therefore, I have to duplicate code and call it in two separate places. I +# have to admit that CMake behavior surprises me many times. This is not a +# great programming language. diff --git a/cmake/tribits/core/utils/TribitsStandardizePaths.cmake b/cmake/tribits/core/utils/TribitsStandardizePaths.cmake index 0a4f78e56d39..b442ce36bc4e 100644 --- a/cmake/tribits/core/utils/TribitsStandardizePaths.cmake +++ b/cmake/tribits/core/utils/TribitsStandardizePaths.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @FUNCTION: tribits_standardize_abs_paths() # # Function uses get_filename_component() to standardize a list of paths to be diff --git a/cmake/tribits/core/utils/TribitsStripQuotesFromStr.cmake b/cmake/tribits/core/utils/TribitsStripQuotesFromStr.cmake index 86abcfc51dfd..ff7edc0f36e2 100644 --- a/cmake/tribits/core/utils/TribitsStripQuotesFromStr.cmake +++ b/cmake/tribits/core/utils/TribitsStripQuotesFromStr.cmake @@ -1,4 +1,3 @@ -# # @FUNCTION: tribits_strip_quotes_from_str() # # Remove one set of quotes from the outside of a string if they exist. @@ -38,4 +37,4 @@ function(tribits_strip_quotes_from_str str_in str_var_out) # If we get here, there were not \" chars as the first and last char so # return the entire input string! set(${str_var_out} "${str_in}" PARENT_SCOPE) -endfunction() \ No newline at end of file +endfunction() diff --git a/cmake/tribits/core/utils/UnitTestHelpers.cmake b/cmake/tribits/core/utils/UnitTestHelpers.cmake index 183d3d949f5b..889f2537b728 100644 --- a/cmake/tribits/core/utils/UnitTestHelpers.cmake +++ b/cmake/tribits/core/utils/UnitTestHelpers.cmake @@ -40,8 +40,27 @@ include(CMakeParseArguments) include(GlobalSet) +# Set policy here instead of including TribitCTestPolicis.cmake since we want +# this to be a standalone module +cmake_policy(SET CMP0007 NEW) # Don't ignore empty list items + +# @MACRO: unittest_initialize_vars() +# +# Call to initialize the unit test variables before running unit tests. +# +# Usage:: # +# unittest_initialize_vars() +# +macro(unittest_initialize_vars) + # Assume that all unit tests will pass by default + global_set(UNITTEST_OVERALL_PASS TRUE) + global_set(UNITTEST_OVERALL_NUMPASSED 0) + global_set(UNITTEST_OVERALL_NUMRUN 0) +endmacro() + + # @FUNCTION: unittest_compare_const() # # Perform a single unit test equality check and update overall test statistics @@ -83,15 +102,148 @@ function(unittest_compare_const VAR_NAME CONST_VAL) endfunction() +# @FUNCTION: unittest_compare_list_ele_const() +# +# Perform a single unit test equality check for a single list element +# +# Usage:: +# +# unittest_compare_list_ele_const( ) +# +# If ``${[]} == ``, then the check passes, otherwise it +# fails. This prints the variable name and values and shows the test result. +# +# This updates the global variables ``UNITTEST_OVERALL_NUMRUN``, +# ``UNITTEST_OVERALL_NUMPASSED``, and ``UNITTEST_OVERALL_PASS`` which are used +# by the unit test harness system to assess overall pass/fail. # +function(unittest_compare_list_ele_const listName idx expectedConstValue) + + math( EXPR NUMRUN ${UNITTEST_OVERALL_NUMRUN}+1 ) + global_set(UNITTEST_OVERALL_NUMRUN ${NUMRUN}) + + list(GET "${listName}" ${idx} listEleIdx) + set(listNameAndIdx "${listName}[${idx}]") + + message( + "\nCheck:\n" + " ${listNameAndIdx} =\n" + " [${listEleIdx}]\n" + " EQUALS:\n" + " [${expectedConstValue}]" + ) + + if ("${listEleIdx}" STREQUAL "${expectedConstValue}") + message(" [PASSED]\n") + math( EXPR NUMPASSED ${UNITTEST_OVERALL_NUMPASSED}+1 ) + global_set(UNITTEST_OVERALL_NUMPASSED ${NUMPASSED}) + else() + message(" [FAILED]\n") + global_set(UNITTEST_OVERALL_PASS FALSE) + message(WARNING "Stack trace for failed unit test") + endif() + +endfunction() + + +# @FUNCTION: unittest_string_block_compare() +# +# Compare two string blocks (with multiple newlines '\n') line-by-line and +# print the first line that fails the comparison. +# +# Usage:: +# +# unittest_string_block_compare( +# "" +# ) +# +# This updates the global variables ``UNITTEST_OVERALL_NUMRUN``, +# ``UNITTEST_OVERALL_NUMPASSED``, and ``UNITTEST_OVERALL_PASS`` which are used +# by the unit test harness system to assess overall pass/fail. +# +function(unittest_string_block_compare stringVar stringExpected) + + message("\nCheck: ${stringVar} equals expected string:") + + math( EXPR NUMRUN ${UNITTEST_OVERALL_NUMRUN}+1 ) + global_set(UNITTEST_OVERALL_NUMRUN ${NUMRUN}) + + string(REPLACE "\n" ";" stringList "${${stringVar}}") + string(REPLACE "\n" ";" stringExpectedList "${stringExpected}") + + list(LENGTH stringList stringLen) + list(LENGTH stringExpectedList stringExpectedLen) + + # minLen = min(stringLen, stringExpectedLen) + set(minLen ${stringLen}) + if (stringExpectedLen LESS minLen) + set(minLen ${stringExpectedLen}) + endif() + + set(allMatched TRUE) + set(idx 0) + while (idx LESS minLen) + list(GET stringList ${idx} stringEle) + list(GET stringExpectedList ${idx} stringExpectedEle) + if (NOT stringEle STREQUAL stringExpectedEle) + message( + " Error: Line ${idx} of ${stringVar}:\n" + " '${stringEle}'\n" + " !=\n" + " '${stringExpectedEle}'\n" + " [FAILED]\n" + ) + global_set(UNITTEST_OVERALL_PASS FALSE) + message(WARNING "Stack trace for failed unit test") + set(allMatched FALSED) + break() + endif() + math(EXPR idx "${idx}+1") + endwhile() + + if (NOT allMatched) + # The error handling was already handled above + elseif (NOT stringLen EQUAL stringExpectedLen) + # The lines of the strings matched but one of the strings had more lines + # than the other + if (stringLen GREATER stringExpectedLen) + list(GET stringList ${stringExpectedLen} nextLine) + message( + " Error: ${stringVar} has ${stringLen} lines where expected string has" + " only ${stringExpectedLen} lines and the next extra line is:\n" + " '${nextLine}'\n" + " [FAILED]\n" + ) + elseif (stringExpectedLen GREATER stringLen) + list(GET stringExpectedList ${stringLen} nextLine) + message( + " Error: Expected string has ${stringExpectedLen} lines where ${stringVar} has" + "only ${stringLen} lines and the next extra line is:\n" + " '${nextLine}'\n" + " [FAILED]\n" + ) + endif() + global_set(UNITTEST_OVERALL_PASS FALSE) + message(WARNING "Stack trace for failed unit test") + else() + # The strings matched exactly! + message(" [PASSED]\n") + math( EXPR NUMPASSED ${UNITTEST_OVERALL_NUMPASSED}+1 ) + global_set(UNITTEST_OVERALL_NUMPASSED ${NUMPASSED}) + endif() + +endfunction() + + # @FUNCTION: unittest_string_regex() # -# Perform a series regexes of given strings and update overall test statistics. +# Perform a series of regexes on a given string and update overall test +# statistics. # # Usage:: # # unittest_string_regex( -# +# "" # REGEX_STRINGS "" "" ... # ) # @@ -125,12 +277,14 @@ function(unittest_string_regex INPUT_STRING) string(REGEX MATCH "${REGEX}" REGEX_MATCH_RESULT "${INPUT_STRING}") + message(" Searching string:") + message(" '${INPUT_STRING}'") if (REGEX_MATCH_RESULT) - message(" Searching for REGEX {${REGEX}}: [PASSED]\n") + message(" for REGEX {${REGEX}}: [PASSED]\n") math( EXPR NUMPASSED ${UNITTEST_OVERALL_NUMPASSED}+1 ) global_set(UNITTEST_OVERALL_NUMPASSED ${NUMPASSED}) else() - message(" Searching for REGEX {${REGEX}}: [FAILED]\n") + message(" for REGEX {${REGEX}}: [FAILED]\n") global_set(UNITTEST_OVERALL_PASS FALSE) message(WARNING "Stack trace for failed unit test") endif() @@ -140,7 +294,57 @@ function(unittest_string_regex INPUT_STRING) endfunction() +# @FUNCTION: unittest_string_var_regex() +# +# Perform a series of regexes on a given string variable and update overall +# test statistics. +# +# Usage:: +# +# unittest_string_var_regex( +# +# REGEX_STRINGS "" "" ... +# ) # +# If the ``"${}"`` matches all of the of the regexs +# ``""``, ``""``, ..., then the test passes. Otherwise it fails. +# +# This updates the global variables ``UNITTEST_OVERALL_NUMRUN``, +# ``UNITTEST_OVERALL_NUMPASSED``, and ``UNITTEST_OVERALL_PASS`` which are used +# by the unit test harness system to assess overall pass/fail. +# +function(unittest_string_var_regex inputStringVar) + + cmake_parse_arguments(PARSE_ARGV 1 + PARSE "" "" # prefix, options, one_value_keywords + "REGEX_STRINGS" #multi_value_keywords + ) + tribits_check_for_unparsed_arguments(PARSE) + + foreach(REGEX ${PARSE_REGEX_STRINGS}) + + math( EXPR NUMRUN ${UNITTEST_OVERALL_NUMRUN}+1 ) + global_set(UNITTEST_OVERALL_NUMRUN ${NUMRUN}) + + string(REGEX MATCH "${REGEX}" REGEX_MATCH_RESULT "${${inputStringVar}}") + + message("Searching string variable value '${inputStringVar}':") + message(" '${${inputStringVar}}'") + if (REGEX_MATCH_RESULT) + message(" for REGEX {${REGEX}}: [PASSED]\n") + math( EXPR NUMPASSED ${UNITTEST_OVERALL_NUMPASSED}+1 ) + global_set(UNITTEST_OVERALL_NUMPASSED ${NUMPASSED}) + else() + message(" for REGEX {${REGEX}}: [FAILED]\n") + global_set(UNITTEST_OVERALL_PASS FALSE) + message(WARNING "Stack trace for failed unit test") + endif() + + endforeach() + +endfunction() + + # @FUNCTION: unittest_has_substr_const() # # Check that a given string var contains the given substring and update @@ -187,7 +391,6 @@ function(unittest_has_substr_const VAR_NAME SUBSTR_VAL) endfunction() -# # @FUNCTION: unittest_not_has_substr_const() # # Check that a given string var does **NOT** contains the given substring and @@ -234,7 +437,6 @@ function(unittest_not_has_substr_const VAR_NAME SUBSTR_VAL) endfunction() -# # @FUNCTION: unittest_file_regex() # # Perform a series regexes of given strings and update overall test statistics. @@ -256,7 +458,6 @@ function(unittest_file_regex INPUT_FILE) endfunction() -# # @FUNCTION: unittest_final_result() # # Print final statistics from all tests and assert final pass/fail diff --git a/cmake/tribits/ctest_driver/TribitsAddDashboardTarget.cmake b/cmake/tribits/ctest_driver/TribitsAddDashboardTarget.cmake index 3e7b85dcd1fe..a9a8b6992f21 100644 --- a/cmake/tribits/ctest_driver/TribitsAddDashboardTarget.cmake +++ b/cmake/tribits/ctest_driver/TribitsAddDashboardTarget.cmake @@ -38,11 +38,14 @@ # @HEADER +################################################################################ # # This file gets included in the main TriBITS framework. It is put here to # reduce the size of the tribits/core/ directory. # +################################################################################ +include(TribitsGitRepoVersionInfo) # # Macro that drives a experimental 'dashboard' target @@ -95,6 +98,13 @@ macro(tribits_add_dashboard_target) append_set(EXPR_CMND_ARGS "${PROJECT_NAME}_WARNINGS_AS_ERRORS_FLAGS='${${PROJECT_NAME}_WARNINGS_AS_ERRORS_FLAGS}'") append_set(EXPR_CMND_ARGS "${PROJECT_NAME}_ENABLE_SECONDARY_TESTED_CODE=${${PROJECT_NAME}_ENABLE_SECONDARY_TESTED_CODE}") + # Determine if base repo is a git repo (by seeing if SHA1 can be extracted) + tribits_git_repo_sha1("${PROJECT_SOURCE_DIR}" projectGitRepoSha1 + FAILURE_MESSAGE_OUT projectGitRepoSha1FailureMsg) + if (projectGitRepoSha1 STREQUAL "") + append_set(EXPR_CMND_ARGS "CTEST_DO_UPDATES=OFF") + endif() + # Conditionally override options used only for the 'dashboard' target. # These options have no use in a a basic build/test so we don't want to # interfere with options users might set on the env. diff --git a/cmake/tribits/ctest_driver/TribitsCTestDriverCore.cmake b/cmake/tribits/ctest_driver/TribitsCTestDriverCore.cmake index 7449d172386d..da12e79f96fe 100644 --- a/cmake/tribits/ctest_driver/TribitsCTestDriverCore.cmake +++ b/cmake/tribits/ctest_driver/TribitsCTestDriverCore.cmake @@ -151,7 +151,7 @@ set( CMAKE_MODULE_PATH include(TribitsConstants) tribits_asesrt_minimum_cmake_version() -include(TribitsCMakePolicies) +include(TribitsCMakePolicies NO_POLICY_SCOPE) include(Split) include(PrintVar) @@ -210,7 +210,6 @@ site_name(CTEST_SITE_DEFAULT) include(TribitsCTestDriverCoreHelpers) -# # @FUNCTION: tribits_ctest_driver() # # Universal platform-independent CTest/CDash driver function for CTest -S @@ -323,9 +322,10 @@ include(TribitsCTestDriverCoreHelpers) # * `Determining what testing-related actions are performed (tribits_ctest_driver())`_ # * `Determining how the results are displayed on CDash (tribits_ctest_driver())`_ # * `Specifying where the results go to CDash (tribits_ctest_driver())`_ +# * `Links to results on CDash (tribits_ctest_driver())`_ # * `Determining what TriBITS repositories are included (tribits_ctest_driver())`_ # * `All-at-once versus package-by-package mode (tribits_ctest_driver())`_ -# * `Mutiple ctest -S invocations (tribits_ctest_driver())`_ +# * `Multiple ctest -S invocations (tribits_ctest_driver())`_ # * `Repository Updates (tribits_ctest_driver())`_ # * `Other CTest Driver options (tribits_ctest_driver())`_ # * `Return value (tribits_ctest_driver())`_ @@ -1166,6 +1166,63 @@ include(TribitsCTestDriverCoreHelpers) # not be performed. For more details, see `TRIBITS_2ND_CTEST_DROP_SITE`_ and # `TRIBITS_2ND_CTEST_DROP_LOCATION`_. # +# .. _Links to results on CDash (tribits_ctest_driver()): +# +# **Links to results on CDash (tribits_ctest_driver()):** +# +# Links to where the results will be posted on CDash are printed to STDOUT +# before it performs any actions and at end after all of the actions and +# submits have been completed. +# +# The results are printed to STDOUT in a section that looks like:: +# +# Link to this build's results on CDash: +# +# +# +# Link to all builds for this repo version on CDash: +# +# +# +# Link to all nonpassing tests for all builds for this repo version on CDash: +# +# +# +# The URL ```` is created from the buildname, site, and +# buildstartime fields which is known from the TAG file created by CTest. +# This allows access the results for this particular build on CDash by just +# clicking that link. +# +# The URL ```` provides a link to a CDash +# ``index.php`` query that includes all of the builds with the same base Git +# repo SHA1. This allows comparing the results of this build for other builds +# for this same version of the base Git repository. +# +# The URL ```` gives a link to a CDash +# ``queryTests.php`` query for all of the nonpassing tests for all of the +# builds with this same base project Git repo SHA1. This allows comparing +# test failures across all of the builds for the same base project Git repo +# version. +# +# NOTE: The links ```` and +# ```` are only provided if the base +# project Git repo has the ``.git/`` subdirectory and if ``git log`` +# successfully returns the SHA1 for that base Git repo. +# +# NOTE: The links ```` and +# ```` only consider the Git SHA1 of the +# base project Git repo. For multi-repo projects (see `Multi-Repository +# Support`_), you may get results for builds with different subrepo versions +# and therefore may be comparing apples and oranges. (Projects that commit a +# ``SubRepoVersion.txt`` file to their base Git repo or use Git +# Submodules will have unique base project Git repo SHA1s for different +# versions of the project's repos.) +# +# In addition, a text file ``CDashResults.txt`` will be written in the build +# directory that contains this same CDash link information shown above. This +# allows a process to cat the file ``CDashResults.txt`` to get links to the +# results on CDash. +# # .. _Determining what TriBITS repositories are included (tribits_ctest_driver()): # # **Determining what TriBITS repositories are included (tribits_ctest_driver()):** @@ -2093,9 +2150,15 @@ function(tribits_ctest_driver) ctest_start(${CTEST_START_ARGS}) tribits_remember_if_configure_attempted() - tribits_get_build_url_and_write_to_file(CDASH_BUILD_URL - "${CTEST_BINARY_DIRECTORY}/CDashBuildUrl.txt") - tribits_print_build_url("Results will be submitted on CDash at:" "${CDASH_BUILD_URL}") + + tribits_get_cdash_results_string_and_write_to_file( + CDASH_RESULTS_STRING_OUT CDASH_RESULTS_STRING + CDASH_RESULTS_FILE_OUT "${CTEST_BINARY_DIRECTORY}/CDashResults.txt" ) + message("Results will be submitted on CDash at the following links:\n\n" + "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n" + "${CDASH_RESULTS_STRING}\n" + "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n" + ) message( "\n***" @@ -2369,7 +2432,11 @@ function(tribits_ctest_driver) report_queued_errors() - tribits_print_build_url("See results submitted on CDash at:" "${CDASH_BUILD_URL}") + message("\nSee results submitted on CDash at the following links:\n\n" + "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n" + "${CDASH_RESULTS_STRING}\n" + "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n" + ) if ((NOT UPDATE_FAILED) AND ("${${PROJECT_NAME}_FAILED_PACKAGES}" STREQUAL "")) message( diff --git a/cmake/tribits/ctest_driver/TribitsCTestDriverCoreHelpers.cmake b/cmake/tribits/ctest_driver/TribitsCTestDriverCoreHelpers.cmake index 350652e60164..f54285bb8c1f 100644 --- a/cmake/tribits/ctest_driver/TribitsCTestDriverCoreHelpers.cmake +++ b/cmake/tribits/ctest_driver/TribitsCTestDriverCoreHelpers.cmake @@ -38,7 +38,7 @@ # @HEADER -include(TribitsGetCDashUrlFromTagFile) +include(TribitsGetCDashUrlsInsideCTestS) # Wrapper used for unit testing purposes @@ -394,7 +394,7 @@ macro(enable_only_modified_packages) file(STRINGS ${EXTRAREPO_MODIFIED_FILES_FILE_NAME} EXTRAREPO_MODIFIED_FILES_STR) set(EXTRAREPO_FILES_STR "") foreach(STR_LINE ${EXTRAREPO_MODIFIED_FILES_STR}) - append_string_var(EXTRAREPO_FILES_STR "${EXTRAREPO_DIR}/${STR_LINE}\n") + string(APPEND EXTRAREPO_FILES_STR "${EXTRAREPO_DIR}/${STR_LINE}\n") endforeach() file(APPEND "${MODIFIED_FILES_FILE_NAME}" ${EXTRAREPO_FILES_STR}) @@ -1262,7 +1262,7 @@ endmacro() # ${PROJECT_NAME}_DISABLE_ENABLED_FORWARD_DEP_PACKAGES=ON but the target # _libs is attempted to be built anyway and we expect it to build # nothing and result in no error. (The outer ctest -S driver is not smart -# enough to know all the lgoic for if a package will actaully be enabled or +# enough to know all the lgoic for if a package will actually be enabled or # not. That is the job of the inner TriBITS dependency logic and # ${PROJECT_NAME}_DISABLE_ENABLED_FORWARD_DEP_PACKAGES=ON.) Otherwise, with # CMake 3.19+, cmake_build() catches errors in undefined global build targets diff --git a/cmake/tribits/ctest_driver/TribitsGetCDashUrlFromTagFile.cmake b/cmake/tribits/ctest_driver/TribitsGetCDashUrlFromTagFile.cmake deleted file mode 100644 index 944a598d688c..000000000000 --- a/cmake/tribits/ctest_driver/TribitsGetCDashUrlFromTagFile.cmake +++ /dev/null @@ -1,194 +0,0 @@ -include(TribitsReadTagFile) - - -# @FUNCTION: tribits_get_build_url_and_write_to_file() -# -# Construct the build URL on CDash given the site name, buildname, and -# buildstamp (take from the TAG file) from inside of a running ctest -S -# program and optionally write it to a file as well. -# -# Usage:: -# -# tribits_get_build_url_and_write_to_file( -# [ ] ) -# -# Here, ```` returns the CDash Build URL constructed from -# the following CMake variables already set in a ``ctest -S`` process: -# -# * ``CTEST_DROP_SITE`` -# * ``CTEST_DROP_LOCATION`` (``submit.php`` is replaced with ``index.php``) -# * ``CTEST_PROJECT_NAME`` -# * ``CTEST_SITE`` -# * ``CTEST_BUILD_NAME`` -# -# and the buildstamp read in from the file -# ``${CTEST_BINARY_DIRECTORY}/Testing/TAG``. -# -# Note that ```` will have ``https://`` added to the -# beginning of it so that GitHub Actions and other systems will put in a link -# to them. -# -# If the file name argument ```` is non-empty, then that -# CDash URL will be written to the file as a single line. -# -function(tribits_get_build_url_and_write_to_file cdashBuildUrlOut cdashBuildUrlFile) - tribits_get_cdash_index_php_from_drop_site_and_location( - CTEST_DROP_SITE "${CTEST_DROP_SITE}" - CTEST_DROP_LOCATION "${CTEST_DROP_LOCATION}" - INDEX_PHP_URL_OUT indexPhpUrl - ) - tribits_get_cdash_build_url_from_tag_file( - INDEX_PHP_URL "${indexPhpUrl}" - PROJECT_NAME "${CTEST_PROJECT_NAME}" - SITE_NAME "${CTEST_SITE}" - BUILD_NAME "${CTEST_BUILD_NAME}" - TAG_FILE "${CTEST_BINARY_DIRECTORY}/Testing/TAG" - CDASH_BUILD_URL_OUT cdashBuildUrl - ) - set(cdashBuildUrl "https://${cdashBuildUrl}") - if (cdashBuildUrlFile) - file(WRITE "${cdashBuildUrlFile}" "${cdashBuildUrl}") - endif() - set(${cdashBuildUrlOut} "${cdashBuildUrl}" PARENT_SCOPE) -endfunction() - - -# @FUNCTION: tribits_print_build_url() -# -# Print the URL on CDash where build results can be found. -# -# Usage:: -# -# tribits_print_build_url( ) -# -function(tribits_print_build_url msg cdashBuildUrl) - message("\n${msg}\n") - message(" ${cdashBuildUrl}\n") -endfunction() - - -# @FUNCTION: tribits_get_cdash_build_url_from_tag_file() -# -# Create CDash index.php URL from the build parts. -# -# Usage:: -# -# tribits_get_cdash_build_url_from_tag_file( -# INDEX_PHP_URL -# PROJECT_NAME -# SITE_NAME -# BUILD_NAME -# TAG_FILE -# CDASH_BUILD_URL_OUT -# ) -# -# Note that spaces are allowed ```` or ```` and those -# will be handled correctly to produce a valid URL. -# -function(tribits_get_cdash_build_url_from_tag_file) - # Get arguments - cmake_parse_arguments( - PREFIX #prefix - "" #options - "INDEX_PHP_URL;PROJECT_NAME;SITE_NAME;BUILD_NAME;TAG_FILE;CDASH_BUILD_URL_OUT" #one_value_keywords - "" #multi_value_keywords - ${ARGN} - ) - # Read in the tag file and get the build stamp from that - tribits_read_ctest_tag_file(${PREFIX_TAG_FILE} buildStartTime cdashGroup - cdashModel # The model is not used here but we still need to include this arg - ) - set(buildstamp "${buildStartTime}-${cdashGroup}") - # Build the URL and return it - tribits_get_cdash_build_url_from_parts( - INDEX_PHP_URL "${PREFIX_INDEX_PHP_URL}" - PROJECT_NAME "${PREFIX_PROJECT_NAME}" - SITE_NAME "${PREFIX_SITE_NAME}" - BUILD_NAME "${PREFIX_BUILD_NAME}" - BUILD_STAMP "${buildstamp}" - CDASH_BUILD_URL_OUT cdashBuildUrl - ) - set(${PREFIX_CDASH_BUILD_URL_OUT} "${cdashBuildUrl}" PARENT_SCOPE) -endfunction() - - -# @FUNCTION: tribits_get_cdash_index_php_from_drop_site_and_location() -# -# Get the CDash index.php URL from the input CTEST_DROP_SITE and -# CTEST_DROP_LOCATION vars used in a ctest -S script. -# -function(tribits_get_cdash_index_php_from_drop_site_and_location) - cmake_parse_arguments( - PREFIX #prefix - "" #options - "CTEST_DROP_SITE;CTEST_DROP_LOCATION;INDEX_PHP_URL_OUT" #one_value_keywords - "" #multi_value_keywords - ${ARGN} - ) - string(FIND "${PREFIX_CTEST_DROP_LOCATION}" "?" endOfSubmitPhpIdx) - string(SUBSTRING "${PREFIX_CTEST_DROP_LOCATION}" 0 ${endOfSubmitPhpIdx} submitPhpPart) - string(REPLACE "submit.php" "index.php" indexPhpPart "${submitPhpPart}") - set(indexPhpUrl "${PREFIX_CTEST_DROP_SITE}${indexPhpPart}") - SET(${PREFIX_INDEX_PHP_URL_OUT} "${indexPhpUrl}" PARENT_SCOPE) -endfunction() - - -# @FUNCTION: tribits_get_cdash_build_url_from_parts() -# -# Create CDash index.php URL from the build parts. -# -# Usage:: -# -# tribits_get_cdash_build_url_from_parts( -# INDEX_PHP_URL -# PROJECT_NAME -# SITE_NAME -# BUILD_NAME -# BUILD_STAMP -# CDASH_BUILD_URL_OUT -# ) -# -# Note that spaces are allowed ````, ```` or -# ```` and those will be handled correctly to produce a valid URL. -# -function(tribits_get_cdash_build_url_from_parts) - # Get arguments - cmake_parse_arguments( - PREFIX #prefix - "" #options - "INDEX_PHP_URL;PROJECT_NAME;SITE_NAME;BUILD_NAME;BUILD_STAMP;CDASH_BUILD_URL_OUT" #one_value_keywords - "" #multi_value_keywords - ${ARGN} - ) - # Do replacements for spaces and special chars in data - tribits_replace_chars_for_url("${PREFIX_PROJECT_NAME}" project) - tribits_replace_chars_for_url("${PREFIX_SITE_NAME}" site) - tribits_replace_chars_for_url("${PREFIX_BUILD_NAME}" buildname) - tribits_replace_chars_for_url("${PREFIX_BUILD_STAMP}" buildstamp) - # Build the URL - set(cdashIndexProj "${PREFIX_INDEX_PHP_URL}?project=${project}") - set(filtersPreTxt "filtercount=3&showfilters=1&filtercombine=and") - set(siteFlt "field1=site&compare1=61&value1=${site}") - set(buildnameFlt "field2=buildname&compare2=61&value2=${buildname}") - set(buildStampFlt "field3=buildstamp&compare3=61&value3=${buildstamp}") - set(cdashBuildUrl - "${cdashIndexProj}&${filtersPreTxt}&${siteFlt}&${buildnameFlt}&${buildStampFlt}") - set(${PREFIX_CDASH_BUILD_URL_OUT} "${cdashBuildUrl}" PARENT_SCOPE) -endfunction() - - -# Replace chars in a regular string for usage in a URL with CDash -# -function(tribits_replace_chars_for_url inputStr outputStrForUrlOutVar) - set(outputStrForUrl "${inputStr}") - string(REPLACE " " "%20" outputStrForUrl "${outputStrForUrl}") - string(REPLACE "+" "%2B" outputStrForUrl "${outputStrForUrl}") - set(${outputStrForUrlOutVar} "${outputStrForUrl}" PARENT_SCOPE) -endfunction() - -# LocalWords: GitHub tribits url buildname buildstamp -# LocalWords: tribits TRIBITS -# LocalWords: cmake CMake CMAKE -# LocalWords: ctest CTEST cdash CDash CDASH -# LocalWords: SUBSTRING -# LocalWords: endif endfunction diff --git a/cmake/tribits/ctest_driver/TribitsGetCDashUrlsInsideCTestS.cmake b/cmake/tribits/ctest_driver/TribitsGetCDashUrlsInsideCTestS.cmake new file mode 100644 index 000000000000..c6904f1195c9 --- /dev/null +++ b/cmake/tribits/ctest_driver/TribitsGetCDashUrlsInsideCTestS.cmake @@ -0,0 +1,527 @@ +# @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 + + +include(PrintVar) +include(TribitsParseArgumentsHelpers) +include(TribitsReadTagFile) + + +################################################################################ +# +# This module contains functions for constructing CDash URLs to build and test +# results from inside of a CTest -S script. +# +################################################################################ + + +# @FUNCTION: tribits_get_cdash_results_string_and_write_to_file() +# +# Calls `tribits_get_cdash_results_urls_string()`_ and then writes the CDash +# URLs to a file. +# +# Usage:: +# +# tribits_get_cdash_results_string_and_write_to_file( +# [CDASH_RESULTS_STRING_OUT ] +# [CDASH_RESULTS_FILE_OUT ] +# ) +# +function(tribits_get_cdash_results_string_and_write_to_file) + # Parse args + cmake_parse_arguments( PARSE_ARGV 0 + PARSE "" "" # prefix, options, one_value_keywords + "CDASH_RESULTS_STRING_OUT;CDASH_RESULTS_FILE_OUT" # multi_value_keywords + ) + tribits_check_for_unparsed_arguments(PARSE) + tribits_assert_parse_arg_zero_or_one_value(PARSE CDASH_RESULTS_STRING_OUT + CDASH_RESULTS_FILE_OUT ) + # Get and set CDash results URL + tribits_get_cdash_results_urls_string(cdashResultsString) + if (PARSE_CDASH_RESULTS_STRING_OUT) + set(${PARSE_CDASH_RESULTS_STRING_OUT} "${cdashResultsString}" PARENT_SCOPE) + endif() + if (PARSE_CDASH_RESULTS_FILE_OUT) + file(WRITE "${PARSE_CDASH_RESULTS_FILE_OUT}" "${cdashResultsString}") + endif() +endfunction() + + +# @FUNCTION: tribits_get_cdash_results_urls_string() +# +# Call `tribits_get_cdash_results_urls()`_ and then construct a CDash URLs +# string fit for printing. +# +# Usage:: +# +# tribits_get_cdash_results_urls_string( +# +# ) +# +# Construct the build and test URLs on CDash given the site name, buildname, +# and buildstamp (taken from the TAG file) from inside of a running ctest -S +# program and optionally write it to a file as well. +# +function(tribits_get_cdash_results_urls_string cdashResultsUrlsStringOut) + tribits_get_cdash_results_urls( + CDASH_BUILD_URL_OUT cdashBuildUrl + CDASH_REVISION_BUILDS_URL_OUT cdashRevisionBuildsUrl + CDASH_REVISION_NONPASSING_TESTS_URL_OUT cdashRevisionNonpassingTestsUrl + ) + tribits_generate_cdash_results_string_from_urls( + CDASH_BUILD_URL "${cdashBuildUrl}" + CDASH_REVISION_BUILDS_URL "${cdashRevisionBuildsUrl}" + CDASH_REVISION_NONPASSING_TESTS_URL "${cdashRevisionNonpassingTestsUrl}" + CDASH_RESULTS_STRING_OUT cdashResultsUrlsString + ) + set(${cdashResultsUrlsStringOut} "${cdashResultsUrlsString}" PARENT_SCOPE) +endfunction() + + +# @FUNCTION: tribits_generate_cdash_results_string_from_urls() +# +# Generate the CDash results URL string given the individual URLs. +# +# Usage:: +# +# tribits_generate_cdash_results_string_from_urls( +# CDASH_BUILD_URL "" +# [CDASH_REVISION_BUILDS_URL ""] +# [CDASH_REVISION_NONPASSING_TESTS_URL ""] +# CDASH_RESULTS_STRING_OUT +# ) +# +# Takes the URLs returned from `tribits_get_cdash_results_urls()`_ and +# generates a string out of them which is set in the return var +# ````. +# +function(tribits_generate_cdash_results_string_from_urls) + # Parse args + cmake_parse_arguments(PARSE_ARGV 0 + PARSE "" "" # prefix, options, one_value_keywords + # multi_value_keywords + "CDASH_BUILD_URL;CDASH_REVISION_BUILDS_URL;CDASH_REVISION_NONPASSING_TESTS_URL;CDASH_RESULTS_STRING_OUT" + ) + tribits_check_for_unparsed_arguments() + tribits_assert_parse_arg_one_value(PARSE CDASH_BUILD_URL + CDASH_RESULTS_STRING_OUT) + tribits_assert_parse_arg_zero_or_one_value(PARSE CDASH_REVISION_BUILDS_URL + CDASH_REVISION_NONPASSING_TESTS_URL) + # Construct CDash results URLs string + set(cdashResultsString "") + string(APPEND cdashResultsString + "Link to this build's results on CDash:\n" + "\n" + " ${PARSE_CDASH_BUILD_URL}\n") + if (PARSE_CDASH_REVISION_BUILDS_URL) + string(APPEND cdashResultsString + "\nLink to all builds for this repo version on CDash:\n" + "\n" + " ${PARSE_CDASH_REVISION_BUILDS_URL}\n") + endif() + if (PARSE_CDASH_REVISION_NONPASSING_TESTS_URL) + string(APPEND cdashResultsString + "\nLink to all nonpassing tests for all builds for this repo version on CDash:\n" + "\n" + " ${PARSE_CDASH_REVISION_NONPASSING_TESTS_URL}\n") + endif() + # Set output + set(${PARSE_CDASH_RESULTS_STRING_OUT} ${cdashResultsString} PARENT_SCOPE) +endfunction() + + +# @FUNCTION: tribits_get_cdash_results_urls() +# +# Construct the build and test URLs on CDash given the site name, buildname, +# and buildstamp (taken from the TAG file) from inside of a running ctest -S +# program and optionally write it to a file as well. +# +# Usage:: +# +# tribits_get_cdash_results_urls( +# CDASH_BUILD_URL_OUT +# [CDASH_REVISION_BUILDS_URL_OUT ] +# [CDASH_REVISION_NONPASSING_TESTS_URL_OUT ] +# ) +# +# Here, the CDash URLs are constructed the following CMake variables already +# set in a ``ctest -S`` process: +# +# * ``CTEST_DROP_SITE`` +# * ``CTEST_DROP_LOCATION`` (``submit.php`` is replaced with ``index.php``) +# * ``CTEST_PROJECT_NAME`` +# * ``CTEST_SITE`` +# * ``CTEST_BUILD_NAME`` +# * ``CTEST_BINARY_DIRECTORY`` +# * ``CTEST_SOURCE_DIRECTORY`` +# +# and other information derived from that. +# +# The buildstamp is read in from the file +# ``${CTEST_BINARY_DIRECTORY}/Testing/TAG``. +# +# If available, the revision SHA1 is obtained from the git repo at +# ``CTEST_SOURCE_DIRECTORY`` if the directory +# ``${CTEST_SOURCE_DIRECTORY}/.git`` exists. If the base project source +# directory is not a git reposistory, then ```` and +# ````, if requested, will be set to +# empty. +# +# Note that the CDash URLs will have ``https://`` added to the beginning so +# that GitHub Actions and other systems will put in a hyperlink to them. +# +function(tribits_get_cdash_results_urls) + # Parse args + cmake_parse_arguments(PARSE_ARGV 0 + PARSE "" "" # prefix, options, one_value_keywords + # multi_value_keywords + "CDASH_BUILD_URL_OUT;CDASH_REVISION_BUILDS_URL_OUT;CDASH_REVISION_NONPASSING_TESTS_URL_OUT" + ) + tribits_check_for_unparsed_arguments(PARSE) + tribits_assert_parse_arg_one_value(PARSE CDASH_BUILD_URL_OUT) + tribits_assert_parse_arg_zero_or_one_value(PARSE CDASH_REVISION_BUILDS_URL_OUT + CDASH_REVISION_NONPASSING_TESTS_URL_OUT) + # Get the info + tribits_get_cdash_build_url(cdashBuildUrl) + tribits_git_repo_sha1("${CTEST_SOURCE_DIRECTORY}" gitRepoSha1 + FAILURE_MESSAGE_OUT gitRepoSha1FailureMsg) + if (gitRepoSha1) + tribits_get_cdash_site_from_drop_site_and_location( + CTEST_DROP_SITE "${CTEST_DROP_SITE}" + CTEST_DROP_LOCATION "${CTEST_DROP_LOCATION}" + CDASH_SITE_URL_OUT cdashSiteUrl + ) + tribits_get_cdash_revision_builds_url( + CDASH_SITE_URL "${cdashSiteUrl}" + PROJECT_NAME "${CTEST_PROJECT_NAME}" + GIT_REPO_SHA1 "${gitRepoSha1}" + CDASH_REVISION_BUILDS_URL_OUT cdashRevisionBuildsUrl + ) + tribits_get_cdash_revision_nonpassing_tests_url( + CDASH_SITE_URL "${cdashSiteUrl}" + PROJECT_NAME "${CTEST_PROJECT_NAME}" + GIT_REPO_SHA1 "${gitRepoSha1}" + CDASH_REVISION_NONPASSING_TESTS_URL_OUT cdashRevisionNonpassingTestsUrl + ) + else() + set(cdashRevisionBuildsUrl "") + set(cdashRevisionNonpassingTestsUrl "") + endif() + # Set the outputs + set(${PARSE_CDASH_BUILD_URL_OUT} "${cdashBuildUrl}" PARENT_SCOPE) + set(${PARSE_CDASH_REVISION_BUILDS_URL_OUT} "${cdashRevisionBuildsUrl}" + PARENT_SCOPE) + set(${PARSE_CDASH_REVISION_NONPASSING_TESTS_URL_OUT} "${cdashRevisionNonpassingTestsUrl}" + PARENT_SCOPE) +endfunction() + + +# @FUNCTION: tribits_get_cdash_revision_builds_url() +# +# Get the CDash URL for all builds with the same repo version SHA1 +# +# Usage:: +# +# tribits_get_cdash_revision_builds_url( +# CDASH_SITE_URL +# PROJECT_NAME +# GIT_REPO_SHA1 +# CDASH_REVISION_BUILDS_URL_OUT +# ) +# +function(tribits_get_cdash_revision_builds_url) + cmake_parse_arguments(PARSE_ARGV 0 + PARSE "" "" # prefix, options, one_value_keywords + # multi_value_keywords + "CDASH_SITE_URL;PROJECT_NAME;GIT_REPO_SHA1;CDASH_REVISION_BUILDS_URL_OUT" + ) + tribits_check_for_unparsed_arguments() + tribits_assert_parse_arg_one_value(PARSE CDASH_SITE_URL PROJECT_NAME + GIT_REPO_SHA1 CDASH_REVISION_BUILDS_URL_OUT) + set(${PARSE_CDASH_REVISION_BUILDS_URL_OUT} + "${PARSE_CDASH_SITE_URL}/index.php?project=${PARSE_PROJECT_NAME}&filtercount=1&showfilters=1&field1=revision&compare1=61&value1=${PARSE_GIT_REPO_SHA1}" + PARENT_SCOPE) +endfunction() + + +# @FUNCTION: tribits_get_cdash_revision_nonpassing_tests_url() +# +# Get the CDash URL for all non-passing tests with the same repo version SHA1 +# +# Usage:: +# +# tribits_get_cdash_revision_nonpassing_tests_url( +# CDASH_SITE_URL +# PROJECT_NAME +# GIT_REPO_SHA1 +# CDASH_REVISION_NONPASSING_TESTS_URL_OUT +# ) +# +function(tribits_get_cdash_revision_nonpassing_tests_url) + cmake_parse_arguments( PARSE_ARGV 0 + PARSE "" "" # prefix, options, one_value_keywords + # multi_value_keywords + "CDASH_SITE_URL;PROJECT_NAME;GIT_REPO_SHA1;CDASH_REVISION_NONPASSING_TESTS_URL_OUT" + ) + tribits_check_for_unparsed_arguments() + tribits_assert_parse_arg_one_value(PARSE CDASH_SITE_URL PROJECT_NAME + GIT_REPO_SHA1 CDASH_REVISION_NONPASSING_TESTS_URL_OUT) + set(${PARSE_CDASH_REVISION_NONPASSING_TESTS_URL_OUT} + "${PARSE_CDASH_SITE_URL}/queryTests.php?project=${PARSE_PROJECT_NAME}&filtercount=2&showfilters=1&filtercombine=and&field1=revision&compare1=61&value1=${PARSE_GIT_REPO_SHA1}&field2=status&compare2=62&value2=passed" + PARENT_SCOPE) +endfunction() + + +# @FUNCTION: tribits_get_cdash_build_url() +# +# Construct the build URL on CDash given the site name, buildname, and +# buildstamp (taken from the TAG file) from inside of a running ctest -S +# program. +# +# Usage:: +# +# tribits_get_cdash_build_url() +# +# Here, ```` returns the CDash Build URL constructed from +# the following CMake variables already set in a ``ctest -S`` process: +# +# * ``CTEST_DROP_SITE`` +# * ``CTEST_DROP_LOCATION`` (``submit.php`` is replaced with ``index.php``) +# * ``CTEST_PROJECT_NAME`` +# * ``CTEST_SITE`` +# * ``CTEST_BUILD_NAME`` +# +# and the buildstamp read in from the file +# ``${CTEST_BINARY_DIRECTORY}/Testing/TAG``. +# +# Note that ```` will have ``https://`` added to the +# beginning of it so that GitHub Actions and other systems will put in a link +# to them. +# +function(tribits_get_cdash_build_url cdashBuildUrlOut) + tribits_get_cdash_index_php_from_drop_site_and_location( + CTEST_DROP_SITE "${CTEST_DROP_SITE}" + CTEST_DROP_LOCATION "${CTEST_DROP_LOCATION}" + INDEX_PHP_URL_OUT indexPhpUrl + ) + tribits_get_cdash_build_url_from_tag_file( + INDEX_PHP_URL "${indexPhpUrl}" + PROJECT_NAME "${CTEST_PROJECT_NAME}" + SITE_NAME "${CTEST_SITE}" + BUILD_NAME "${CTEST_BUILD_NAME}" + TAG_FILE "${CTEST_BINARY_DIRECTORY}/Testing/TAG" + CDASH_BUILD_URL_OUT cdashBuildUrl + ) + set(${cdashBuildUrlOut} "${cdashBuildUrl}" PARENT_SCOPE) +endfunction() + + +# @FUNCTION: tribits_print_cdash_url() +# +# Print the URL on CDash where build results can be found. +# +# Usage:: +# +# tribits_print_cdash_url( ) +# +function(tribits_print_cdash_url msg cdashUrl) + message("\n${msg}\n") + message(" ${cdashUrl}\n") +endfunction() + + +# @FUNCTION: tribits_get_cdash_build_url_from_tag_file() +# +# Create CDash index.php URL from the build parts. +# +# Usage:: +# +# tribits_get_cdash_build_url_from_tag_file( +# INDEX_PHP_URL +# PROJECT_NAME +# SITE_NAME +# BUILD_NAME +# TAG_FILE +# CDASH_BUILD_URL_OUT +# ) +# +# Note that spaces are allowed ```` or ```` and those +# will be handled correctly to produce a valid URL. +# +function(tribits_get_cdash_build_url_from_tag_file) + # Get arguments + cmake_parse_arguments( + PREFIX #prefix + "" #options + "INDEX_PHP_URL;PROJECT_NAME;SITE_NAME;BUILD_NAME;TAG_FILE;CDASH_BUILD_URL_OUT" #one_value_keywords + "" #multi_value_keywords + ${ARGN} + ) + # Read in the tag file and get the build stamp from that + tribits_read_ctest_tag_file(${PREFIX_TAG_FILE} buildStartTime cdashGroup + cdashModel # The model is not used here but we still need to include this arg + ) + set(buildstamp "${buildStartTime}-${cdashGroup}") + # Build the URL and return it + tribits_get_cdash_build_url_from_parts( + INDEX_PHP_URL "${PREFIX_INDEX_PHP_URL}" + PROJECT_NAME "${PREFIX_PROJECT_NAME}" + SITE_NAME "${PREFIX_SITE_NAME}" + BUILD_NAME "${PREFIX_BUILD_NAME}" + BUILD_STAMP "${buildstamp}" + CDASH_BUILD_URL_OUT cdashBuildUrl + ) + set(${PREFIX_CDASH_BUILD_URL_OUT} "${cdashBuildUrl}" PARENT_SCOPE) +endfunction() + + +# @FUNCTION: tribits_get_cdash_index_php_from_drop_site_and_location() +# +# Get the CDash index.php URL from the input CTEST_DROP_SITE and +# CTEST_DROP_LOCATION vars used in a ctest -S script. +# +function(tribits_get_cdash_index_php_from_drop_site_and_location) + cmake_parse_arguments( + PREFIX #prefix + "" #options + "CTEST_DROP_SITE;CTEST_DROP_LOCATION;INDEX_PHP_URL_OUT" #one_value_keywords + "" #multi_value_keywords + ${ARGN} + ) + tribits_get_cdash_site_from_drop_site_and_location( + CTEST_DROP_SITE ${PREFIX_CTEST_DROP_SITE} + CTEST_DROP_LOCATION ${PREFIX_CTEST_DROP_LOCATION} + CDASH_SITE_URL_OUT cdashSiteUrl ) + SET(${PREFIX_INDEX_PHP_URL_OUT} "${cdashSiteUrl}/index.php" PARENT_SCOPE) +endfunction() + + +# @FUNCTION: tribits_get_cdash_site_from_drop_site_and_location() +# +# Get the full CDash site base URL from the input CTEST_DROP_SITE and +# CTEST_DROP_LOCATION vars used in a ctest -S script. +# +# Usage:: +# +# tribits_get_cdash_site_from_drop_site_and_location( +# CTEST_DROP_SITE +# CTEST_DROP_LOCATION +# CDASH_SITE_URL_OUT +# ) +# +function(tribits_get_cdash_site_from_drop_site_and_location) + # Parse args + cmake_parse_arguments(PARSE_ARGV 0 + PREFIX #prefix + "" #options + "CTEST_DROP_SITE;CTEST_DROP_LOCATION;CDASH_SITE_URL_OUT" #one_value_keywords + "" #multi_value_keywords + ) + tribits_check_for_unparsed_arguments(PREFIX) + tribits_assert_parse_arg_one_value(PREFIX CTEST_DROP_SITE) + tribits_assert_parse_arg_one_value(PREFIX CTEST_DROP_LOCATION) + tribits_assert_parse_arg_one_value(PREFIX CDASH_SITE_URL_OUT) + # Get the full CDash site from parts + string(FIND "${PREFIX_CTEST_DROP_LOCATION}" "?" beginningOfQueryString) + string(SUBSTRING "${PREFIX_CTEST_DROP_LOCATION}" 0 ${beginningOfQueryString} submitPhpPart) + string(REPLACE "/submit.php" "" endCDashUrl "${submitPhpPart}") + set(cdashSiteUrl "${PREFIX_CTEST_DROP_SITE}${endCDashUrl}") + set(${PREFIX_CDASH_SITE_URL_OUT} "https://${cdashSiteUrl}" PARENT_SCOPE) +endfunction() + + +# @FUNCTION: tribits_get_cdash_build_url_from_parts() +# +# Create CDash index.php URL from the build parts. +# +# Usage:: +# +# tribits_get_cdash_build_url_from_parts( +# INDEX_PHP_URL +# PROJECT_NAME +# SITE_NAME +# BUILD_NAME +# BUILD_STAMP +# CDASH_BUILD_URL_OUT +# ) +# +# Note that spaces are allowed ````, ```` or +# ```` and those will be handled correctly to produce a valid URL. +# +function(tribits_get_cdash_build_url_from_parts) + # Get arguments + cmake_parse_arguments( + PREFIX #prefix + "" #options + "INDEX_PHP_URL;PROJECT_NAME;SITE_NAME;BUILD_NAME;BUILD_STAMP;CDASH_BUILD_URL_OUT" #one_value_keywords + "" #multi_value_keywords + ${ARGN} + ) + # Do replacements for spaces and special chars in data + tribits_replace_chars_for_url("${PREFIX_PROJECT_NAME}" project) + tribits_replace_chars_for_url("${PREFIX_SITE_NAME}" site) + tribits_replace_chars_for_url("${PREFIX_BUILD_NAME}" buildname) + tribits_replace_chars_for_url("${PREFIX_BUILD_STAMP}" buildstamp) + # Build the URL + set(cdashIndexProj "${PREFIX_INDEX_PHP_URL}?project=${project}") + set(filtersPreTxt "filtercount=3&showfilters=1&filtercombine=and") + set(siteFlt "field1=site&compare1=61&value1=${site}") + set(buildnameFlt "field2=buildname&compare2=61&value2=${buildname}") + set(buildStampFlt "field3=buildstamp&compare3=61&value3=${buildstamp}") + set(cdashBuildUrl + "${cdashIndexProj}&${filtersPreTxt}&${siteFlt}&${buildnameFlt}&${buildStampFlt}") + set(${PREFIX_CDASH_BUILD_URL_OUT} "${cdashBuildUrl}" PARENT_SCOPE) +endfunction() + + +# Replace chars in a regular string for usage in a URL with CDash +# +function(tribits_replace_chars_for_url inputStr outputStrForUrlOutVar) + set(outputStrForUrl "${inputStr}") + string(REPLACE " " "%20" outputStrForUrl "${outputStrForUrl}") + string(REPLACE "+" "%2B" outputStrForUrl "${outputStrForUrl}") + set(${outputStrForUrlOutVar} "${outputStrForUrl}" PARENT_SCOPE) +endfunction() + +# LocalWords: GitHub tribits url buildname buildstamp +# LocalWords: tribits TRIBITS +# LocalWords: cmake CMake CMAKE +# LocalWords: ctest CTEST cdash CDash CDASH +# LocalWords: SUBSTRING +# LocalWords: endif endfunction diff --git a/cmake/tribits/ctest_driver/TribitsGetCTestTestXmlDir.cmake b/cmake/tribits/ctest_driver/TribitsGetCTestTestXmlDir.cmake index 311954374238..71d54e1df099 100644 --- a/cmake/tribits/ctest_driver/TribitsGetCTestTestXmlDir.cmake +++ b/cmake/tribits/ctest_driver/TribitsGetCTestTestXmlDir.cmake @@ -14,6 +14,8 @@ # then prints the directory /Testing/ to STDOUT. # +cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR) + if ("${PROJECT_NAME}" STREQUAL "") message(FATAL_ERROR "Error, PROJECT_NAME must be set!") endif() diff --git a/cmake/tribits/ctest_driver/TribitsReadTagFile.cmake b/cmake/tribits/ctest_driver/TribitsReadTagFile.cmake index 6fac636d75cc..9de13e3aac25 100644 --- a/cmake/tribits/ctest_driver/TribitsReadTagFile.cmake +++ b/cmake/tribits/ctest_driver/TribitsReadTagFile.cmake @@ -1,3 +1,8 @@ +# Set policy here instead of including TribitCTestPolicis.cmake since we want +# this to be a standalone module +cmake_policy(SET CMP0007 NEW) + + # @FUNCTION: tribits_read_ctest_tag_file() # # Read in the /Testing/TAG file contents diff --git a/cmake/tribits/ctest_driver/experimental_build_test.cmake b/cmake/tribits/ctest_driver/experimental_build_test.cmake index 0b36b05e8f67..0c70ab4a7004 100644 --- a/cmake/tribits/ctest_driver/experimental_build_test.cmake +++ b/cmake/tribits/ctest_driver/experimental_build_test.cmake @@ -100,7 +100,7 @@ include(SetDefaultAndFromEnv) # All these can be changed by env vars set(CTEST_TEST_TYPE Experimental) -set(CTEST_DO_UPDATES FALSE) +set(CTEST_UPDATE_VERSION_ONLY TRUE) set(${PROJECT_NAME}_WARNINGS_AS_ERRORS_FLAGS "-Werror") # Don't change these in the env! diff --git a/cmake/tribits/ctest_driver/tribits_ctest_update_commands.cmake b/cmake/tribits/ctest_driver/tribits_ctest_update_commands.cmake index 56f786f6d2da..81c22cc41730 100644 --- a/cmake/tribits/ctest_driver/tribits_ctest_update_commands.cmake +++ b/cmake/tribits/ctest_driver/tribits_ctest_update_commands.cmake @@ -18,6 +18,8 @@ # 3.12) crash in that case. # +cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR) + message("\ncmake -P tribits_ctest_update_commands.cmake:") message("-- GIT_EXE=${GIT_EXE}") message("-- REMOTE_NAME=${REMOTE_NAME}") 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 02f0f9ce3ac2..9c18b0d1273b 100644 --- a/cmake/tribits/ctest_driver/tribits_ctest_update_commands_wrapper.cmake +++ b/cmake/tribits/ctest_driver/tribits_ctest_update_commands_wrapper.cmake @@ -7,6 +7,8 @@ # the output (and does not send it to CDash). # +cmake_minimum_required(VERSION 3.17.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/install-cmake.py b/cmake/tribits/devtools_install/install-cmake.py index b9240c20cc68..5b5b48ea76bf 100755 --- a/cmake/tribits/devtools_install/install-cmake.py +++ b/cmake/tribits/devtools_install/install-cmake.py @@ -108,7 +108,24 @@ def getExtraHelpStr(self, version): 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 +which creates temp directories based in the CMake version. For example, to +cone and install the tip of the CMake 'master' branch one can run: + + install-cmake.py \\ + --install-dir=.cmake``, see below). One can use the ``FORCE`` option in the ``set()`` commands shown above and @@ -277,7 +277,7 @@ b) Create a ``*.cmake`` file and point to it [Most Recommended]. contents of the ``*.cmake`` file reread on reconfigures, then one would want to use ``-C``. - 3) One can create and use parametrized ``*.cmake`` files that can be used + 3) One can create and use parameterized ``*.cmake`` files that can be used with multiple TriBITS projects. For example, one can have set statements like ``set(${PROJECT_NAME}_ENABLE_Fortran OFF ...)`` since ``PROJECT_NAME`` is known before the file is included. One can't do that with ``cmake -C`` @@ -506,7 +506,7 @@ pre-push testing. Enable all packages (and optionally all tests) ++++++++++++++++++++++++++++++++++++++++++++++ -To enable all defined packages and subpakages add the configure option:: +To enable all defined packages and subpackages add the configure option:: -D _ENABLE_ALL_PACKAGES=ON \ @@ -797,7 +797,7 @@ package. NOTES: -1) Setting ``CMAKE__FLAGS`` as a cache varible by the user on input be +1) Setting ``CMAKE__FLAGS`` as a cache variable by the user on input be listed after and therefore override, but will not replace, any internally set flags in ``CMAKE__FLAGS`` defined by the CMake system. To get rid of these project/TriBITS set compiler flags/options, see the below items. @@ -1401,6 +1401,52 @@ search for extra required libraries (such as the mpi library and the gfortran library for gnu compilers) to locate static versions. +Changing include directories in downstream CMake projects to non-system +----------------------------------------------------------------------- + +By default, include directories from IMPORTED library targets from the + project's installed ``Config.cmake`` files will be +considered ``SYSTEM`` headers and therefore will be included on the compile +lines of downstream CMake projects with ``-isystem`` with most compilers. +However, when using CMake 3.23+, by configuring with:: + + -D _IMPORTED_NO_SYSTEM=ON + +then all of the IMPORTED library targets in the set of installed +``Config.cmake`` files will have the ``IMPORTED_NO_SYSTEM`` target +property set. This will cause downstream customer CMake projects to apply the +include directories from these IMPORTED library targets as non-SYSTEM include +directories. On most compilers, that means that the include directories will +be listed on the compile lines with ``-I`` instead of with ``-isystem`` (for +compilers that support the ``-isystem`` option). (Changing from ``-isystem +`` to ``-I `` moves ```` forward in the +compiler's include directory search order and could also result in the found +header files emitting compiler warnings that would other otherwise be silenced +when the headers were found in include directories pulled in with +``-isystem``.) + +**NOTE:** Setting ``_IMPORTED_NO_SYSTEM=ON`` when using a CMake +version less than 3.23 will result in a fatal configure error (so don't do +that). + +**A workaround for CMake versions less than 3.23** is for **downstream +customer CMake projects** to set the native CMake cache variable:: + + -D CMAKE_NO_SYSTEM_FROM_IMPORTED=TRUE + +This will result in **all** include directories from **all** IMPORTED library +targets used in the downstream customer CMake project to be listed on the +compile lines using ``-I`` instead of ``-isystem``, and not just for the +IMPORTED library targets from this project's installed +``Config.cmake`` files! + +**NOTE:** Setting ``CMAKE_NO_SYSTEM_FROM_IMPORTED=TRUE`` in the +CMake configure will **not** result in changing how include directories from +'s IMPORTED targets are handled in a downstream customer CMake +project! It will only change how include directories from upstream package's +IMPORTED targets are handled in the CMake project build itself. + + Enabling the usage of resource files to reduce length of build lines -------------------------------------------------------------------- @@ -1522,13 +1568,14 @@ compiles and links. (This can actually be a feature in rare cases the libraries and header files don't actually get created until after the configure step is complete but before the build step.) -**WARNING:** Do **not** try to hack the system and set, for example:: +**WARNING:** It is **not recommended** to specify the TPLs libraries as just a set +of link options as, for example:: - TPL_BLAS_LIBRARIES="-L/some/dir -llib1 -llib2 ..." + TPL_SomeTPL_LIBRARIES="-L/some/dir;-llib1;-llib2;..." This is not compatible with proper CMake usage and it not guaranteed to be -supported for all use cases or all platforms! You should instead always use -the full library paths when setting ``TPL__LIBRARIES``. +supported for all use cases or all platforms. (CMake really wants to have +full library paths when linking.) When the variables ``TPL__INCLUDE_DIRS`` and ``TPL__LIBRARIES`` are not specified, then most @@ -1536,7 +1583,11 @@ When the variables ``TPL__INCLUDE_DIRS`` and call ``find_package()`` internally by default and some may implement the default find in some other way. To know for sure, see the documentation for the specific TPL (e.g. looking in the ``FindTPL.cmake`` file to -be sure). +be sure). NOTE: if a given ``FindTPL.cmake`` would use +``find_package()`` by default, this can be disabled by configuring +with:: + + -D_ALLOW_PACKAGE_PREFIND=OFF Most TPLs, however, use a standard system for finding include directories and/or libraries based on the function @@ -1563,6 +1614,19 @@ Most ``FindTPL.cmake`` modules will define a default set of libraries to look for and therefore ``_LIBRARY_NAMES`` can typically be left off. +Therefore, to find the same set of libraries for ``SimpleTPL`` shown +above, one would specify:: + + -D SomeTPL_LIBRARY_DIRS="${LIB_BASE}/lib" + +and if the set of libraries to be found is different than the default, one can +override that using:: + + -D SomeTPL_LIBRARY_NAMES="lib1;lib2" + +Therefore, this is in fact the preferred way to specify the libraries for a +TPL. + In order to allow a TPL that normally requires one or more libraries to ignore the libraries, one can set ``_LIBRARY_NAMES`` to empty, for example:: @@ -1573,7 +1637,7 @@ Optional package-specific support for a TPL can be turned off by setting:: -D _ENABLE_=OFF This gives the user full control over what TPLs are supported by which package -independently. +independent of whether the TPL is enabled or not. Support for an optional TPL can also be turned on implicitly by setting:: @@ -1584,14 +1648,14 @@ dependency on ````. That will result in setting ``TPL_ENABLE_=ON`` internally (but not set in the cache) if ``TPL_ENABLE_=OFF`` is not already set. -If all the parts of a TPL are not found on an initial configure the configure +If all the parts of a TPL are not found on an initial configure, the configure will error out with a helpful error message. In that case, one can change the variables ``_INCLUDE_DIRS``, ``_LIBRARY_NAMES``, and/or ``_LIBRARY_DIRS`` in order to help fund the parts of the TPL. One -can do this over and over until the TPL is found. By reconfiguring, one avoid +can do this over and over until the TPL is found. By reconfiguring, one avoids a complete configure from scratch which saves time. Or, one can avoid the find operations by directly setting ``TPL__INCLUDE_DIRS`` and -``TPL__LIBRARIES``. +``TPL__LIBRARIES`` as described above. **WARNING:** The cmake cache variable ``TPL__LIBRARY_DIRS`` does **not** control where libraries are found. Instead, this variable is set @@ -1659,7 +1723,7 @@ For example, the Intel Math Kernel Library (MKL) implementation for the BLAS is usually given in several libraries. The exact set of libraries needed depends on the version of MKL, whether 32bit or 64bit libraries are needed, etc. Figuring out the correct set and ordering of these libraries for a given -platform may not be trivial. But once the set and the order of the libraries +platform may be non-trivial. But once the set and the order of the libraries is known, then one can provide the correct list at configure time. For example, suppose one wants to use the threaded MKL libraries listed in the @@ -1703,6 +1767,34 @@ libraries in the right order by configuring with:: (where ``...`` are the rest of the libraries found in order). +Adjusting upstream dependencies for a Third-Party Library (TPL) +--------------------------------------------------------------- + +Some TPLs have dependencies on one or more upstream TPLs. These dependencies +must be specified correctly for the compile and links to work correctly. The + Project already defines these dependencies for the average situation +for all of these TPLs. However, there may be situations where the +dependencies may need to be tweaked to match how these TPLs were actually +installed on some systems. To redefine what dependencies a TPL can have (if +the upstream TPLs are enabled), set:: + + -D _LIB_ALL_DEPENDENCIES=";;..." + +A dependency on an upstream TPL ```` will be set if the an upstream TPL +```` is actually enabled. + +If any of the specified TPLs are listed after ```` in the +``TPLsList.cmake`` file or are not enabled, then a configure-time error will +occur. + +To take complete control over what dependencies an TPL has, set:: + + -D _LIB_ENABLED_DEPENDENCIES=";;..." + +If the upstream TPLs listed here are not defined upstream and enabled TPLs, +then an error will occur. + + Disabling support for a Third-Party Library (TPL) -------------------------------------------------- @@ -2545,7 +2637,7 @@ To add timers to various configure steps, configure with:: -D _ENABLE_CONFIGURE_TIMING=ON -This will do baulk timing for the major configure steps which is independent +This will do bulk timing for the major configure steps which is independent of the number of packages in the project. To additionally add timing for the configure of individual packages, configure @@ -2597,15 +2689,6 @@ This will generate the file ``Config.cmake`` for the project and the files ``Config.cmake`` for each enabled package in the build tree. In addition, this will install versions of these files into the install tree. -To configure Makefile export files, configure with:: - - -D _ENABLE_EXPORT_MAKEFILES=ON - -which will generate the file ``Makefile.export.`` for the project and -the files ``Makefile.export.`` for each enabled package in the build -tree. In addition, this will install versions of these files into the install -tree. - The list of export files generated can be reduced by specifying the exact list of packages the files are requested for with:: @@ -2752,7 +2835,7 @@ trigger warnings in CDash) about missing inserted/external packages will print regardless of the setting for ``_ASSERT_MISSING_PACKAGES``. Finally, ``_ENABLE_DEVELOPMENT_MODE=ON`` results in a number of -checks for invalid usage of TriBITS in the project's ``CMakeList.txt`` files +checks for invalid usage of TriBITS in the project's ``CMakeLists.txt`` files and will abort configure with a fatal error on the first check failure. This is appropriate for development mode when a project is clean of all such invalid usage patterns but there are times when it makes sense to report these @@ -3306,6 +3389,8 @@ For more details, see the following subsections: * `Setting install RPATH`_ * `Avoiding installing libraries and headers`_ * `Installing the software`_ +* `Using the installed software in downstream CMake projects`_ +* `Using packages from the build tree in downstream CMake projects`_ Setting the install prefix @@ -3678,6 +3763,110 @@ This will ensure that every package that builds correctly will get installed. (The default 'install' target aborts on the first file install failure.) +Using the installed software in downstream CMake projects +--------------------------------------------------------- + +As described in `Generating export files`_, when ``-D +_ENABLE_INSTALL_CMAKE_CONFIG_FILES=ON`` is set at configure time, a +``Config.cmake`` file and a different ``Config.cmake`` file +for each enabled package is installed into the install tree under ``-D +CMAKE_INSTALL_PREFIX=``. A downstream CMake project can +then pull in CMake targets for the installed libraries using +``find_package()`` in the downstream project's ``CMakeLists.txt`` file. All +of the built and installed libraries can be pulled in and built against at the +project level by configuring the downstream CMake project with:: + + -D CMAKE_PREFIX_PATH= + +and having the downstream project's ``CMakeLists.txt`` file call, for +example:: + + find_package( REQUIRED) + ... + target_link_libraries( + PRIVATE ::all_libs ) + +This will put the needed include directories and other imported compiler +options on the downstream compile lines as specified through the IMPORTED +library targets and will put the needed libraries on the link line. + +To pull in libraries from only a subset of the installed packages `` + ...``, use, for example:: + + find_package( REQUIRED COMPONENTS ...) + ... + target_link_libraries( + PRIVATE ::all_selected_libs ) + +The target ``::all_selected_libs`` only contains the library targets +for the selected packages (through their ``::all_libs`` targets) for +the packages requested in the ``COMPONENTS ...`` argument. +(NOTE, the target ``::all_libs`` is unaffected by the ``COMPONENTS`` +argument and always links to all of the enabled package's libraries.) + +Downstream projects can also pull in and use installed libraries by finding +individual packages by calling ``find_package( REQUIRED)`` for each +package ```` and then linking against the defined IMPORTED CMake +target ``::all_libs`` such as:: + + find_package( REQUIRED) + find_package( REQUIRED) + ... + target_link_libraries( + PUBLIC ::all_libs + PRIVATE ::all_libs + ) + +Finding and using libraries for packages at the package-level provides better +fine-grained control over internal linking and provides greater flexibility in +case these packages are not all installed in the same upstream CMake project +in the future. + +To see an example of all of these use cases being demonstrated, see +`TribitsExampleApp`_ and the `TriBITS TribitsExampleApp Tests`_. + + +Using packages from the build tree in downstream CMake projects +------------------------------------------------------------------ + +Note that libraries from enabled and built packages can also be used from the +```` build tree without needing to install. Being able to build +against pre-built packages in the build tree can be very useful such as when +the project is part of a CMake super-build where one does not want to install +the intermediate packages. + +Let ```` be the build directory for ```` that has +already been configured and built (but not necessarily installed). A +downstream CMake project can pull in and link against any of the enabled +libraries in the upstream ```` configuring the downstream CMake +project with:: + + -D CMAKE_PREFIX_PATH=/cmake_packages + +and then finding the individual packages and linking to them in the downstream +CMake project's ``CMakeLists.txt`` file as usual using, for example:: + + find_package( REQUIRED) + find_package( REQUIRED) + ... + target_link_libraries( + PUBLIC ::all_libs + PRIVATE ::all_libs + ) + +Note that in this case, ``target_link_libraries()`` ensures that the include +directories and other imported compiler options from the source tree and the +build tree are automatically injected into the build targets associated with +the ```` object compile lines and link lines. + +Also note that package config files for all of the enabled external +packages/TPLs will also be written into the build tree under +``/external_packages``. These contain modern CMake targets +that are pulled in by the downstream ``Config.cmake`` files under +``/external_packages``. These external package/TPL config +files are placed in a separate directory to avoid being found by accident. + + Installation Testing ==================== @@ -3689,7 +3878,7 @@ build, and install just the libraries and header files using:: $ cd BUILD_LIBS/ $ cmake \ - -DCMAKE_INSTLAL_PREFIX= \ + -DCMAKE_INSTALL_PREFIX= \ -D_ENABLE_ALL_PACKAGES=ON \ -D_ENABLE_TESTS=OFF \ [other options] \ @@ -3796,7 +3985,7 @@ Dashboard submissions ===================== All TriBITS projects have built-in support for submitting configure, build, -and test results to CDash using the custom ``dashbaord`` target. This uses +and test results to CDash using the custom ``dashboard`` target. This uses the `tribits_ctest_driver()`_ function internally set up to work correctly from an existing binary directory with a valid initial configure. The few of the advantages of using the custom TriBITS-enabled ``dashboard`` target over @@ -4029,4 +4218,8 @@ with an invalid configuration of the project. In these cases, one may need to configure from scratch to get back to the original state before calling ``make dashboard``. +.. _TribitsExampleApp: https://github.com/TriBITSPub/TriBITS/tree/master/tribits/examples/TribitsExampleApp + +.. _TriBITS TribitsExampleApp Tests: https://github.com/TriBITSPub/TriBITS/blob/master/test/core/ExamplesUnitTests/TribitsExampleApp_Tests.cmake + .. LocalWords: templated instantiation Makefiles CMake diff --git a/cmake/tribits/doc/guides/Makefile.common_generated_files b/cmake/tribits/doc/guides/Makefile.common_generated_files index 25bcf0b69277..c6a352d1228f 100644 --- a/cmake/tribits/doc/guides/Makefile.common_generated_files +++ b/cmake/tribits/doc/guides/Makefile.common_generated_files @@ -1,6 +1,7 @@ COMMON_DEPENDENT_FILES = \ Makefile \ ../generate-guide.sh \ + ../TribitsCoreDetailedReference.rst \ ../TribitsGuidesBody.rst \ ../TribitsGuidesReferences.rst \ ../TribitsFAQ.rst \ diff --git a/cmake/tribits/doc/guides/ReducedMockTrilinosOutput/ExpectedDependencies.txt b/cmake/tribits/doc/guides/ReducedMockTrilinosOutput/ExpectedDependencies.txt index 389c30f20245..e176a320e287 100644 --- a/cmake/tribits/doc/guides/ReducedMockTrilinosOutput/ExpectedDependencies.txt +++ b/cmake/tribits/doc/guides/ReducedMockTrilinosOutput/ExpectedDependencies.txt @@ -27,3 +27,46 @@ Printing package dependencies ... -- Thyra_LIB_REQUIRED_DEP_PACKAGES: ThyraCoreLibs -- Thyra_LIB_OPTIONAL_DEP_PACKAGES: ThyraGoodStuff ThyraCrazyStuff ThyraEpetra ThyraEpetraExt +Dumping direct dependencies for each package ... + +-- MPI_LIB_ALL_DEPENDENCIES: + +-- BLAS_LIB_ALL_DEPENDENCIES: + +-- LAPACK_LIB_ALL_DEPENDENCIES: + +-- Boost_LIB_ALL_DEPENDENCIES: + +-- UMFPACK_LIB_ALL_DEPENDENCIES: + +-- AMD_LIB_ALL_DEPENDENCIES: + +-- PETSC_LIB_ALL_DEPENDENCIES: + +-- Teuchos_LIB_ENABLED_DEPENDENCIES: BLAS LAPACK +-- Teuchos_LIB_ALL_DEPENDENCIES: BLAS LAPACK Boost MPI + +-- RTOp_LIB_ENABLED_DEPENDENCIES: Teuchos +-- RTOp_LIB_ALL_DEPENDENCIES: Teuchos + +-- Epetra_LIB_ENABLED_DEPENDENCIES: BLAS LAPACK +-- Epetra_LIB_ALL_DEPENDENCIES: BLAS LAPACK MPI + +-- Triutils_LIB_ALL_DEPENDENCIES: Epetra + +-- EpetraExt_LIB_ALL_DEPENDENCIES: Teuchos Epetra Triutils UMFPACK AMD PETSC + +-- ThyraCoreLibs_LIB_ENABLED_DEPENDENCIES: Teuchos RTOp +-- ThyraCoreLibs_LIB_ALL_DEPENDENCIES: Teuchos RTOp + +-- ThyraGoodStuff_LIB_ALL_DEPENDENCIES: ThyraCoreLibs + +-- ThyraCrazyStuff_LIB_ALL_DEPENDENCIES: ThyraGoodStuff + +-- ThyraEpetra_LIB_ENABLED_DEPENDENCIES: Epetra ThyraCoreLibs +-- ThyraEpetra_LIB_ALL_DEPENDENCIES: Epetra ThyraCoreLibs + +-- ThyraEpetraExt_LIB_ALL_DEPENDENCIES: ThyraEpetra EpetraExt + +-- Thyra_LIB_ENABLED_DEPENDENCIES: ThyraCoreLibs ThyraEpetra +-- Thyra_LIB_ALL_DEPENDENCIES: ThyraCoreLibs ThyraGoodStuff ThyraCrazyStuff ThyraEpetra ThyraEpetraExt diff --git a/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst b/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst index eee58675ddc2..dfd5e4320172 100644 --- a/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst +++ b/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst @@ -72,7 +72,6 @@ a given TriBITS project are: * `${PROJECT_NAME}_ENABLE_CXX`_ * `${PROJECT_NAME}_ENABLE_C`_ * `${PROJECT_NAME}_ENABLE_DEVELOPMENT_MODE`_ -* `${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES`_ * `${PROJECT_NAME}_ENABLE_Fortran`_ * `${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES`_ * `${PROJECT_NAME}_ENABLE_SECONDARY_TESTED_CODE`_ @@ -80,6 +79,7 @@ a given TriBITS project are: * `${PROJECT_NAME}_GENERATE_EXPORT_FILE_DEPENDENCIES`_ * `${PROJECT_NAME}_GENERATE_VERSION_DATE_FILES`_ * `${PROJECT_NAME}_GENERATE_REPO_VERSION_FILE`_ +* `${PROJECT_NAME}_IMPORTED_NO_SYSTEM`_ * `${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS`_ * `${PROJECT_NAME}_MAKE_INSTALL_GROUP_READABLE`_ * `${PROJECT_NAME}_MAKE_INSTALL_GROUP_WRITABLE`_ @@ -354,23 +354,6 @@ These options are described below. default in release mode. In addition, strong compiler warnings are enabled by default in development mode but are disabled by default in release mode. This variable also affects the behavior of `tribits_set_st_for_dev_mode()`_. - -.. _${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES: - -**${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES** - - If ``${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES`` is ``ON``, then - ``Makefile.export.`` will get created at configure time in the - build tree and installed into the install tree. See `TribitsBuildReference`_ - for details. The TriBITS default is ``ON`` but a project can decide to turn - this off by default by setting:: - - set(${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES_DEFAULT OFF) - - A project might want to disable the generation of export makefiles by default - if its main purpose is to provide executables. There is no reason to provide - an export makefile if libraries and headers are not actually installed (see - `${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS`_) .. _${PROJECT_NAME}_ENABLE_Fortran: @@ -386,6 +369,10 @@ These options are described below. This default can be set in `/ProjectName.cmake`_ or `/CMakeLists.txt`_. + On WIN32 systems, the default for ``${PROJECT_NAME}_ENABLE_Fortran_DEFAULT`` + is set to ``OFF`` since it can be difficult to get a Fortran compiler for + native Windows. + Given that a native Fortran compiler is not supported by default on Windows and on most Mac OSX systems, projects that have optional Fortran code may decide to set the default depending on the platform by setting, for example:: @@ -455,13 +442,12 @@ These options are described below. **${PROJECT_NAME}_GENERATE_EXPORT_FILE_DEPENDENCIES** If ``${PROJECT_NAME}_GENERATE_EXPORT_FILE_DEPENDENCIES`` is ``ON``, then the - data-structures needed to generate ``Makefile.export.`` and - ``Config.cmake`` are created. These data structures are also - needed in order to generate export makefiles on demand using the function + data-structures needed to generate ``Config.cmake`` files are + created. These data structures are also needed in order to generate export + makefiles on demand using the function `tribits_write_flexible_package_client_export_files()`_. The default in TriBITS is to turn this ``ON`` automatically by default if - ``${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES`` or - ``${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES`` are ``ON``. Else, by + ``${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES`` is ``ON``. Else, by default, TriBITS sets this to ``OFF``. The only reason for the project to override the default is to set it to ``ON`` as with:: @@ -498,7 +484,46 @@ These options are described below. set(${PROJECT_NAME}_GENERATE_REPO_VERSION_FILE_DEFAULT ON) in the `/ProjectName.cmake`_ file. - + + Note that if a ``git`` exectauble cannot be found at configure time, then + the default ``${PROJECT_NAME}_GENERATE_REPO_VERSION_FILE_DEFAULT`` will be + overridden to ``OFF``. But if the user sets + ``${PROJECT_NAME}_GENERATE_REPO_VERSION_FILE=ON`` in the cache and ``git`` + can't be found, then an configure-time error will occur. + + +.. _${PROJECT_NAME}_IMPORTED_NO_SYSTEM: + +**${PROJECT_NAME}_IMPORTED_NO_SYSTEM** + + By default, include directories from IMPORTED library targets from the + TriBITS project's installed ``Config.cmake`` files will be + considered ``SYSTEM`` headers and therefore be included on the compile lines + of downstream CMake projects with ``-isystem`` with most compilers. + However, if ``${PROJECT_NAME}_IMPORTED_NO_SYSTEM`` is set to ``ON`` (only + supported for CMake versions 3.23 or greater), then all of the IMPORTED + library targets exported into the set of installed ``Config.cmake`` + files will have the ``IMPORTED_NO_SYSTEM`` property set. This will cause + downstream customer CMake projects to apply the include directories from + these IMPORTED library targets as non-system include directories. On most + compilers, that means that the include directories will be listed on the + compile lines with ``-I`` instead of with ``-isystem``. (See more details + in the TriBITS Build Reference for ``_IMPORTED_NO_SYSTEM``.) + + The default value set by TriBITS itself is ``OFF`` but a TriBITS project can + change the default value to ``ON`` by adding:: + + if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.23) + set(${PROJECT_NAME}_IMPORTED_NO_SYSTEM_DEFAULT ON) + endif() + + in the `/ProjectName.cmake`_ file. (NOTE: The above ``if()`` + statement ensures that a configure error will not occur if a version of + CMake less than 3.23 is used. But if the TriBITS project minimum CMake + version is 3.23 or greater, then the above ``if()`` statement guard can be + removed.) + + .. _${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS: **${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS** @@ -735,7 +760,7 @@ These options are described below. A project can use the paths given the cmake module ``GNUInstallDirs`` by default by setting:: - set(${PROJECT_NAME}_USE_GNUINSTALLDIRS_DEFAULT FALSE) + set(${PROJECT_NAME}_USE_GNUINSTALLDIRS_DEFAULT TRUE) in the project's top-level `/CMakeLists.txt`_ file or its `/ProjectName.cmake`_ file. The default is ``FALSE``. diff --git a/cmake/tribits/doc/guides/TribitsGuidesBody.rst b/cmake/tribits/doc/guides/TribitsGuidesBody.rst index 190d97e286d1..23b477d86617 100644 --- a/cmake/tribits/doc/guides/TribitsGuidesBody.rst +++ b/cmake/tribits/doc/guides/TribitsGuidesBody.rst @@ -2,12 +2,12 @@ Background ========== In order to easily find the most appropriate documentation, see the `TriBITS -Developer and User Roles`_ guide. This guide describes the different roles +Developer and User Roles`_ guide. This guide describes the different roles that users of TriBITS may play and offers links to relevant sections of the -documentation. Additionally, the reader may wish to review the `CMake Language -Overview and Gotchas`_ section which is meant for users that are new to both +documentation. Additionally, the reader may wish to review the `CMake Language +Overview and Gotchas`_ section which is meant for users that are new to both CMake and TriBITS. This section gives a brief overview of getting started with -CMake and provides some warnings about non-obvious CMake behavior that often +CMake and provides some warnings about non-obvious CMake behavior that often trips up new users of TriBITS. @@ -21,7 +21,7 @@ Project User`_, 2) `TriBITS Project Developer`_, 3) `TriBITS Project Architect`_, 4) `TriBITS System Developer`_, and 5) `TriBITS System Architect`_. Each of these roles builds on the necessary knowledge of the lower-level roles. - + .. _TriBITS Project User: .. _TriBITS Project Users: @@ -91,7 +91,7 @@ entire TriBITS system, the design philosophy that provides the foundation for TriBITS and be an expert in CMake, CTest, and CDash. Much of what needs to be known by a TriBITS System Developer and a TriBITS System Architect is contained in the document `TriBITS Maintainers Guide and Reference`_. The -rest of the the primary documentation for these roles will be in the TriBITS +rest of the primary documentation for these roles will be in the TriBITS CMake source code and various unit tests itself defined in `The TriBITS Test Package`_. At the time of this writing, there is currently there is only one TriBITS System Architect (who also happens to be the primary author of this @@ -119,12 +119,12 @@ 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 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 +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 +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:: @@ -143,15 +143,15 @@ 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 +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 @@ -217,9 +217,9 @@ control structures (i.e. see ``cmake --help-command if`` and ``cmake 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 +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 @@ -315,21 +315,20 @@ 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 all - caps for functions and macros (which was adopted by following the - conventions used in the early versions of TriBITS, see the `History of - TriBITS`_). The convention in CMake literature from Kitware seems to use - lower-case letters for functions and macros. + 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 variables have mostly - upper-case letters except for parts that are proper nouns like the project, - package or TPL name (e.g. ``TribitsProj_TRIBITS_DIR``, - ``TriBITS_SOURCE_DIR``, ``Boost_INCLUDE_DIRS``). + 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 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 @@ -341,7 +340,7 @@ 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 +``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 @@ -599,7 +598,7 @@ ${PROJECT_SOURCE_DIR}``) are:: project-checkin-test-config.py # [Optional] checkin-test.py config cmake/ NativeRepositoriesList.cmake # [Optional] Rarely used - ExtraRepositoriesList.cmake # [Optional] Lists repos and VC URLs + ExtraRepositoriesList.cmake # [Optional] Lists repos and VC URLs ProjectCiFileChangeLogic.py # [Optional] CI global change/test logic ProjectCompilerPostConfig.cmake # [Optional] Override/tweak build flags ProjectDependenciesSetup.cmake # [Optional] Project deps overrides @@ -700,7 +699,7 @@ The minimum CMake version must also be declared in the top-level version avoids strange errors that can occur when someone tries to build the project using a version of CMake that is too old. The project should set the minimum CMake version based on the CMake features used in that project's own -CMake files. The minimum CMake version required by TriBITS is defined in in +CMake files. The minimum CMake version required by TriBITS is defined in 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:: @@ -904,16 +903,16 @@ are set. This file in Trilinos looked like:: ... include(${Kokkos_GEN_DIR}/kokkos_generated_settings.cmake) - + if (NOT KOKKOS_ARCH STREQUAL "None") - + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KOKKOS_CXX_FLAGS}") - + message("-- " "Skip adding flags for OpenMP because Kokkos flags does that ...") set(OpenMP_CXX_FLAGS_OVERRIDE " ") - + endif() - + endif() The exact context where this file is processed (if it exists) is described in @@ -1572,13 +1571,31 @@ Other TriBITS macros/functions that can be called in this file include `tribits_tpl_tentatively_enable()`_ and `tribits_allow_missing_external_packages()`_. +.. __config.h.in: .. _/cmake/_config.h.in: **/cmake/_config.h.in**: [Optional] The package's configured header file. This file will contain placeholders for variables that will be substitute at configure time with `tribits_configure_file()`_. This includes usage of ``#cmakedefine `` and other standard CMake -file configuration features. +file configuration features used by CMake's ``configure_file()`` command. + +An example of this file is shown in: + + `TribitsExampleProject`_/``packages/simple_cxx/cmake/SimpleCxx_config.h.in`` + +which is: + +.. include:: ../../examples/TribitsExampleProject/packages/simple_cxx/cmake/SimpleCxx_config.h.in + :literal: + +The variable ``HAVE_SIMPLECXX___INT64`` is set up in the base file +``SimpleCxx/CMakeLists.txt`` (see `/CMakeLists.txt`_ below). For +an explanation of ``HAVE_SIMPLECXX_DEBUG``, see `tribits_add_debug_option()`_. +For an explanation of ``HAVE_SIMPLECXX_SIMPLETPL``, see `How to add a new +TriBITS TPL dependency`_. For an explanation of +``@SIMPLECXX_DEPRECATED_DECLARATIONS@``, see `Setting up support for +deprecated code handling`_. **NOTE:** The file name ``_config.h.in`` is not at all fixed and the package can call this file anything it wants. Also, a package can @@ -1765,7 +1782,13 @@ defined before a (SE) Package's ``CMakeLists.txt`` file is processed: ``${PROJECT_NAME}_ENABLE_${PACKAGE_NAME}`` - Set to ``ON`` if the package is enabled and is to be 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 + 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 + parent package will be processed). .. _${PACKAGE_NAME}_ENABLE_${OPTIONAL_DEP_PACKAGE_NAME}: @@ -1788,6 +1811,10 @@ defined before a (SE) Package's ``CMakeLists.txt`` file is processed: ``${OPTIONAL_DEP_PACKAGE_NAME}`` are both enabled at the project level! See `Support for optional SE package/TPL can be explicitly disabled`_. + **NOTE:** This variable will also be set for required dependencies as well + to allow for uniform processing such as when looping over the items in + `${PACKAGE_NAME}_LIB_ALL_DEPENDENCIES`_. + .. _${PACKAGE_NAME}_ENABLE_${OPTIONAL_DEP_TPL_NAME}: ``${PACKAGE_NAME}_ENABLE_${OPTIONAL_DEP_TPL_NAME}`` @@ -1916,7 +1943,7 @@ A TriBITS Subpackage: ``${PARENT_PACKAGE_NAME}_ENABLE_TESTS=ON``. The contents of a TriBITS Subpackage are almost identical to those of a -TriBITS Package. The differences are described below and in `How is a TriBITS +TriBITS Package. The differences are described below and in `How is a TriBITS Subpackage different from a TriBITS Package?`_. For more details on the definition of a TriBITS Package (or subpackage), see: @@ -2123,70 +2150,156 @@ are some of the issues to consider when breaking up software into packages and subpackages that will be mentioned in other sections as well. -TriBITS TPL -+++++++++++ - -A *TriBITS TPL*: +.. _TriBITS TPL: -* Defines a set of pre-built libraries and/or header files and/or executables - and/or some other resources used by one or more TriBITS Packages for which - TriBITS publishes the list of include directories and/or libraries and/or - executables provided by the TPL to the TriBITS project. -* Has a globally unique name (see `Globally unique TriBITS TPL names`_) that - is declared in a `/TPLsList.cmake`_ file. -* Is listed as an explicit optional or required dependency in one or more - TriBITS SE package's `/cmake/Dependencies.cmake`_ files. +TriBITS External Package/TPL +++++++++++++++++++++++++++++ -.. _Globally unique TriBITS TPL names: +A *TriBITS External Package/TPL*: -**WARNING:** One must be very careful to pick **Globally unique TriBITS TPL -names** across all TPLs in all TriBITS repositories that ever might be cobbled -together into a single TriBITS (meta) project! However, choosing TPL names is -usually much easier and less risky than choosing `Globally unique TriBITS -package names`_ because the native TPLs themselves tend to be uniquely named. -For example, the TPL names ``BLAS`` and ``LAPACK`` are well defined in the -applied math and computational science community and are not likely to clash. - -Using a TriBITS TPL is to be preferred over using raw CMake -``find_package()`` because the TriBITS system guarantees -that only a single unique version of TPL of the same version will be used by -multiple packages. Also, by defining a TriBITS TPL, automatic enable/disable -logic will be applied as described in `Package Dependencies and Enable/Disable +* Provides access to a set of pre-built/installed libraries and/or header + files and/or executables and/or some other resources through a standard + 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). +* 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 + downstream packages (see `TriBITS Dependency Handling Behaviors`_). + +The TriBITS external package/TPL mechanism provides a uniform way to find and +provide access to any type of external resource no matter how it might be +installed or ways to provide access to it. Using a TriBITS TPL is to be +preferred over using raw CMake ``find_package()`` call because +the TriBITS system guarantees that only a single unique version of an external +package/TPL of the same version will be used all of the downstream packages +that uses it. Also, by defining a TriBITS TPL, automatic enable/disable logic +will be applied as described in `Package Dependencies and Enable/Disable Logic`_. For example, if a TPL is explicitly disabled, all of the downstream packages that depend on that TPL will be automatically disabled as well (see `TPL disable triggers auto-disables of downstream dependencies`_). -For each TPL referenced in a `/TPLsList.cmake`_ file using the macro -`tribits_repository_define_tpls()`_, there must exist a file, typically called -``FindTPL${TPL_NAME}.cmake``, that once processed, produces the variables -``TPL_${TPL_NAME}_LIBRARIES`` and ``TPL_${TPL_NAME}_INCLUDE_DIRS``. Most -``FindTPL${TPL_NAME}.cmake`` files just use the function -`tribits_tpl_find_include_dirs_and_libraries()`_ the define the TriBITS TPL. -A simple example of such a file is the common TriBITS ``FindTPLPETSC.cmake`` -module which is currently: +.. _Globally unique TriBITS TPL names: + +**WARNING:** One must be very careful to pick **Globally unique TriBITS +External Package/TPL names** ```` across all TPLs in all TriBITS +repositories that ever might be cobbled together into a single TriBITS (meta) +project! However, choosing TPL names is usually much easier and less risky +than choosing `Globally unique TriBITS package names`_ because the native TPLs +themselves tend to be uniquely named. For example, the TPL names ``BLAS`` and +``LAPACK`` are well defined in the applied math and computational science +community and are not likely to clash. + + +TriBITS External Package/TPL Core Files +....................................... + +The core files that define a *TriBITS External Package/TPL* are:: + + / + FindTPL.cmake # The name is not fixed (see _FINDMOD) + FindTPLDependencies.cmake # [Optional], defines upstream dependencies + +Above, ``/`` can be a subdirectory under a TriBITS repository +``/`` (e.g. ``/cmake/tpls/``) or can be under a TriBITS +package directory ``/`` (e.g. ``/cmake/tpls/``). + +The following TriBITS External Package/TPL files are documented in more detail +below: + +* `/FindTPL.cmake`_ +* `/FindTPLDependencies.cmake`_ + + +.. _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`_). + +The form of a simple ``FindTPL.cmake`` file that uses an internal +call to ``find_package()`` which provides modern IMPORTED CMake +targets looks like:: + + find_package( REQUIRED) + tribits_extpkg_create_imported_all_libs_target_and_config_file( + + INNER_FIND_PACKAGE_NAME + IMPORTED_TARGETS_FOR_ALL_LIBS ... ) + +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.). + +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 +to ``find_package()`` looks like:: + + tribits_tpl_find_include_dirs_and_libraries( + REQUIRED_HEADERS ... + REQUIRED_LIBS_NAMES ... + MUST_FIND_ALL_LIBS + ) + +An example concrete file is ``tribits/common_tpls/FindTPLPETSC.cmake``: .. include:: ../../common_tpls/FindTPLPETSC.cmake :literal: -Some concrete ``FindTPL${TPL_NAME}.cmake`` files actually do use -``find_package()`` and a standard CMake package find module to fill in the -guts of finding at TPL which is perfectly fine. In this case, the purpose for -the wrapping ``FindTPL${TPL_NAME}.cmake`` file is to standardize the output -variables ``TPL_${TPL_NAME}_INCLUDE_DIRS`` and ``TPL_${TPL_NAME}_LIBRARIES``. -For more details on properly using ``find_package()`` to define a -``FindTPL${TPL_NAME}.cmake`` file, see `How to use find_package() for a -TriBITS TPL`_. +For complete details, see `Creating the FindTPL.cmake file`_. + + +.. _FindTPLDependencies.cmake: +.. _/FindTPLDependencies.cmake: + +**/FindTPLDependencies.cmake**: [Optional] +Declares dependencies on upstream external packages/TPLs for the external +package/TPL ````. Many external packages/TPLs defined with a +`FindTPL.cmake`_ file do not have any upstream dependencies or have +internal mechanisms to get those (such as when using +``find_package()`` where the ``Config.cmake`` file +which recursively uses ``find_dependency()`` to get its upstream +dependencies). But for ``FindTPL.cmake`` files that just use +`tribits_tpl_find_include_dirs_and_libraries()`_ (see `Creating a +FindTPL.cmake module without find_package()`_), TriBITS needs to be told +about any upstream external packages/TPLs that it may depend on so it can add +the dependencies between the created IMPORTED target libraries. + +The file ``FindTPLDependencies.cmake`` is typically just a single +call to `tribits_extpkg_define_dependencies()`_ and takes the form:: + + tribits_extpkg_define_dependencies( + DEPENDENCIES ... ) + +This defines all of the TPLs that ```` could directly depends on but +only dependencies for enabled upstream TPLs will be added to the IMPORTED +targets. + + +TriBITS External Package/TPL Core Variables +........................................... Once the `/TPLsList.cmake`_ files are all processed, then each defined TPL ``TPL_NAME`` is assigned the following global non-cache variables: .. _${PACKAGE_NAME}_FINDMOD: - + .. __FINDMOD: .. _${TPL_NAME}_FINDMOD: ``${TPL_NAME}_FINDMOD`` - Gives the location for the TPL's find module. This is set using the + Relative path (w.r.t. ``_) 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 @@ -2196,45 +2309,49 @@ defined TPL ``TPL_NAME`` is assigned the following global non-cache variables: ``Repo2/TPLsList.cmake`` and the find module listed in ``Repo1/TPLsList.cmake`` is ignored. + .. __DEPENDENCIES_FILE: + .. _${TPL_NAME}_DEPENDENCIES_FILE: + + ``${TPL_NAME}_DEPENDENCIES_FILE`` + + Relative path (w.r.t. ``_) for the external package/TPL's + dependencies file (typically named `FindTPLDependencies.cmake`_) + .. _${TPL_NAME}_TESTGROUP: ``${TPL_NAME}_TESTGROUP`` - Gives the TPL's `SE Package Test Group`_. This is set using the - ``CLASSIFICATION`` field in the call to - `tribits_repository_define_tpls()`_. If multiple repos define a given - TPL, then the *first* `/TPLsList.cmake`_ file that is processed - that declares the TPL ``TPL_NAME`` specifies the test group. For example, - if ``Repo1/TPLsList.cmake`` and ``Repo2/TPLsList.cmake`` both list the TPL - ``SomeTpl``, then if ``Repo2`` is processed after ``Repo1``, then - ``SomeTpl_TESTGROUP`` is determined by ``Repo1/TPLsList.cmake`` and the - test group in ``Repo2/TPLsList.cmake`` is ignored. However, if - ``${TPL_NAME}_TESTGROUP`` is already set before the + TPL's `SE Package Test Group`_: This is set using the ``CLASSIFICATION`` + field in the call to `tribits_repository_define_tpls()`_. If multiple + repos define a given TPL, then the *first* `/TPLsList.cmake`_ + file that is processed that declares the TPL ``TPL_NAME`` specifies the + test group. For example, if ``Repo1/TPLsList.cmake`` and + ``Repo2/TPLsList.cmake`` both list the TPL ``SomeTpl``, then if ``Repo2`` + is processed after ``Repo1``, then ``SomeTpl_TESTGROUP`` is determined by + ``Repo1/TPLsList.cmake`` and the test group in ``Repo2/TPLsList.cmake`` is + ignored. However, if ``${TPL_NAME}_TESTGROUP`` is already set before the `/TPLsList.cmake`_ files are processed, then that test group will be used. Therefore, the project can override the test group for a given - TPL if desired. + TPL if desired by setting ``${TPL_NAME}_TESTGROUP`` before the first + `/TPLsList.cmake`_ file gets processed. + + .. _+${TPL_NAME}_TPLS_LIST_FILE: + + ``${TPL_NAME}_TPLS_LIST_FILE`` + + Absolute path of the (last) `/TPLsList.cmake`_ file that declared + this external package/TPL. As noted above, it is allowed for the same TPL to be listed in multiple `/TPLsList.cmake`_ files. In this case, the rules for overrides of -the find module and the test group as as described above. +the find module and the test group as described above. The specification given in `Enabling support for an optional Third-Party -Library (TPL)`_ and `tribits_tpl_find_include_dirs_and_libraries()`_ describes -how the a ``FindTPL${TPL_NAME}.cmake`` module should behave and allow users to -override and specialize how a TPL's include directories and libraries are -determined. However, note that the TriBITS system does not require the usage -of the function ``tribits_tpl_find_include_dirs_and_libraries()`` and does not -even care about the TPL module name ``FindTPL${TPL_NAME}.cmake``. All that is -required is that some CMake file fragment exist that once included, will -define the variables ``${TPL_NAME}_LIBRARIES`` and -``${TPL_NAME}_INCLUDE_DIRS``. However, to be user friendly, such a CMake file -should respond to the same variables as accepted by the standard -``tribits_tpl_find_include_dirs_and_libraries()`` function. - -The core variables related to an enabled TPL are ``${TPL_NAME}_LIBRARIES``, -``${TPL_NAME}_INCLUDE_DIRS``, and ``${TPL_NAME}_TESTGROUP`` as defined in -`tribits_tpl_find_include_dirs_and_libraries()`_ need to be defined. For more -details, see `tribits_repository_define_tpls()`_. +Library (TPL)`_ and `Creating the FindTPL.cmake file`_ describe how +to create a ``FindTPL.cmake`` module. However, all that is required +is that some CMake file fragment exist such that, once included, will define +the target ``::all_libs`` and create the ``Config.cmake`` +file in the correct location (see `Requirements for FindTPL.cmake modules`_). Processing of TriBITS Files: Ordering and Details @@ -2311,7 +2428,7 @@ proceeds through the call to `tribits_project()`_. | 5) ``include(`` `/Version.cmake`_ ``)`` | 6) Define primary TriBITS options and read in the list of extra repositories | (calls ``tribits_define_global_options_and_define_extra_repos()``) -| * ``include(`` `/cmake/ExtraRepositoriesList.cmake`_ ``)`` +| * ``include(`` `/cmake/ExtraRepositoriesList.cmake`_ ``)`` | 7) For each ```` in all defined TriBITS repositories: | * ``include(`` `/cmake/CallbackSetupExtraOptions.cmake`_ ``)`` | * Call macro ``tribits_repository_setup_extra_options()`` @@ -2355,7 +2472,7 @@ project, repository, package, and subpackage files should be clear. All of this information should also be clear when enabling `File Processing Tracing`_ and watching the output from the ``cmake`` configure STDOUT. -Reduced Package Dependency Processing +Reduced Package Dependency Processing ++++++++++++++++++++++++++++++++++++++ In addition to the full processing that occurs as part of the `Full TriBITS @@ -2641,7 +2758,7 @@ without having to define its own ``QT`` TPL in its repository's TriBITS, it can be difficult to know where the right place is to set a given set of variables. The primary considerations for where to set a variable depend on: - + .. ToDo: Describe considerations on where to set variables ... @@ -3150,7 +3267,7 @@ enable/disable cache variables (with the initial default values):: Trilinos_ENABLE_Teuchos="" Trilinos_ENABLE_RTOp"" - Trilinos_ENABLE_Epetra="" + Trilinos_ENABLE_Epetra="" Trilinos_ENABLE_Triutils="" Trilinos_ENABLE_EpetraExt="" Trilinos_ENABLE_ThyraCore="" @@ -3417,7 +3534,7 @@ In more detail, these rules/behaviors are: variable `${PROJECT_NAME}_DISABLE_ENABLED_FORWARD_DEP_PACKAGES`_: .. _${PROJECT_NAME}_DISABLE_ENABLED_FORWARD_DEP_PACKAGES=ON: - + * If ``${PROJECT_NAME}_DISABLE_ENABLED_FORWARD_DEP_PACKAGES=ON``, then TriBITS will disable the explicit enable and continue on. In the above example, TriBITS will override ``Trilinos_ENABLE_RTOp=ON`` and set @@ -3449,7 +3566,7 @@ In more detail, these rules/behaviors are: Trilinos_ENABLE_ThyraGoodStuff=ON # Only if enabling ST code! Trilinos_ENABLE_ThyraEpetra=ON Trilinos_ENABLE_ThyraEpetraExt=ON # Only if enabling ST code! - + (Note that ``Trilinos_ENABLE_ThyraCrazyStuff`` is **not** set to ``ON`` because it is already set to ``OFF`` by default, see `EX SE packages disabled by default`_.) Likewise, explicitly setting @@ -3471,8 +3588,16 @@ In more detail, these rules/behaviors are: `downstream`_ package declares a dependency on the SE package ``ThyraEpetra``, but not the parent package ``Thyra``, then the ``Thyra`` package (and its other subpackages and their dependencies) will not get - auto-enabled. This is a key aspect of the TriBITS SE package management - system. + auto-enabled. Also note that enabling a subset of the required + subpackages for a parent package does not require the enable of the other + required subpackages. For example, if both ``ThyraEpetra`` and + ``ThyraCore`` were both required subpackages of the parent package + ``Thyra``, then enabling ``ThyraCore`` does not require the enabling of + ``ThyraEpetra``. In these cases where one of a parent package's + subpackages is enabled for some reason, the final value of + ``${PROJECT_NAME}_ENABLE_${PACKAGE_NAME}`` will be set to ``ON`` (but this + does imply that all of the required subpackages will be enabled, only that + the parent package will be processed.) .. _Support for optional SE package/TPL is enabled by default: @@ -3809,12 +3934,12 @@ tests/examples and TPLs can be clearly seen when processing the TPLs and top-level packages in the lines:: Getting information for all enabled TPLs ... - + -- Processing enabled TPL: BLAS -- Processing enabled TPL: LAPACK - + Configuring individual enabled Trilinos packages ... - + Processing enabled package: Teuchos (Libs) Processing enabled package: RTOp (Libs) Processing enabled package: Epetra (Libs) @@ -4647,7 +4772,7 @@ the `checkin-test.py`_ tool in extended pre-push testing. .. _Performance Testing: -**Performance Testing** +**Performance Testing** *Performance Testing* builds are a special class of builds that have tests that are specifically designed to test the run-time performance of a particular @@ -5124,26 +5249,26 @@ the commands:: $ git clone git@someurl.com:MetaProject $ cd MetaProject/ - $ ./cmake/tribits/ci_support/clone_extra_repos.py + $ ./cmake/tribits/ci_support/clone_extra_repos.py which produces the output like:: - ... - + ... + *** *** Clone the selected extra repos: *** - + Cloning repo ExtraRepo1 ... - + Running: git clone git@someurl.com:ExtraRepo1 ExtraRepo1 - + Cloning repo ExtraRepo2 ... - + Running: git clone git@someurl.com:ExtraRepo2 ExtraRepo1/ExtraRepo2 - + Cloning repo ExtraRepo3 ... - + Running: git clone git@someurl.com:ExtraRepo3 ExtraRepo3 See `clone_extra_repos.py --help`_ for more details. @@ -5190,7 +5315,7 @@ Some of the aggregate commands that one would typically run under the base The tool ``gitdist`` is provided under TriBITS directory:: - cmake/tribits/python_utils/gitidst + cmake/tribits/python_utils/gitidst and can be installed by the `install_devtools.py`_ tool (see `TriBITS Development Toolset`_). See `gitdist documentation`_ for more details. @@ -5418,121 +5543,347 @@ subpackages, do the following: and tests run as new pieces are added. -How to add a new TriBITS TPL ----------------------------- +.. _How to add a new TriBITS TPL: + +How to add a new TriBITS external package/TPL +--------------------------------------------- -In order for an SE package to define a dependency on a new TPL (i.e. one that -has not already been declared in the current repo's or an upstream repo's -`/TPLsList.cmake`_ file), one must add and modify a few -repository-level files. +In order for a TriBITS package to define a dependency on a new `TriBITS +External Package/TPL`_ (i.e. a TPL that has not already been declared in the +current repo's or an upstream repo's `/TPLsList.cmake`_ file), one +must add and modify a few repository-level files in addition to modifying +files within the TriBITS packages that use the new external package/TPL. To add a new TriBITS TPL, do the following: -1) Chose a name ```` for the new TPL (must be globally unique across - all TriBITS repos, see `Globally unique TriBITS TPL names`_) and which - TriBITS repository (````) to define the new TPL in. The right - repo is usually the one where the package exists that needs the new TPL - dependency. +1) **Chose a name ** for the new TPL (must be globally unique across + all TriBITS repos. (See `Globally unique TriBITS TPL names`_.) -2) Create the TPL find module, e.g. ``/tpls/FindTPL.cmake`` - (see `TriBITS TPL`_ and `tribits_tpl_find_include_dirs_and_libraries()`_ - for details). List the default required header files and/or libraries that - must be provided by the TPL. NOTE: This find module can also (optionally) - use ``find_package( ...)`` for the default find operation. For - details, see `How to use find_package() for a TriBITS TPL`_. +2) **Choose the subdirectory for the new TPL files**. These + files are usually placed under the TriBITS repository directory + ``/`` (e.g. ``/cmake/tpls/``) where the first downstream + dependent package is defined or can be under a TriBITS package directory + ``/`` (e.g. ``/cmake/tpls/``) if only one package + is using that TPL. -3) Add a row for the new TPL to the `/TPLsList.cmake`_ file after any - TPLs that this new TPL may depend on. +3) **Create the FindTPL.cmake file** (or some other name, see + `_FINDMOD`_) under ``/``. (See `Creating the + FindTPL.cmake file`_.) -4) Configure the TriBITS project enabling the new TPL with - ``TPL_ENABLE_=ON`` and see that the new find module finds the TPL - correctly at configure time. +4) **[Optional] Create the FindTPLDependencies.cmake file** in the + same directory as the ``FindTPL.cmake`` file, ``/``. + (See `FindTPLDependencies.cmake`_.) -5) List the new TPL in the package(s) that need this dependency in the - package's `/cmake/Dependencies.cmake`_ file (or +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`_.) + +6) **Configure the TriBITS project enabling the new TPL with + TPL_ENABLE_=ON** and see that the TPL is found correctly at + configure time. + +7) **Add to the package Dependencies.cmake files** of downstream + dependent packages that will use this TPL (see + `/cmake/Dependencies.cmake`_ or `//cmake/Dependencies.cmake`_ for a subpackage). -6) If the TPL is an optional TPL for the package, then:: +8) **[Optional] Add #cmakedefine for an optional package library TPL + dependency in the package's _config.h.in file** using:: + + #cmakedefine HAVE__ + + so that the package's code build knows if the TPL is defined or not (see + `_config.h.in`_ and `tribits_configure_file()`_). (NOTE: Do + **not** add this for a optional test-only TPL dependency. We don't want + all of the libraries in a package to have to be rebuild when we enable or + disable tests for the package.) + +9) **Use the TPL functionality in the packages** that define the dependency on + the new TPL, configure, test, etc. + +.. _Creating the FindTPL.cmake file: + +**Creating the FindTPL.cmake file** + +The main axes of variation in defining ``FindTPL.cmake`` modules are: + +a) Use an inner ``find_package()`` call or just use a simple list + of header file names and library names? + +b) The call ``find_package()`` defines modern IMPORTED targets or + only provides variables for the list of include directories and libraries? + +c) Maintain backward compatibility with the legacy TriBITS TPL system that + allows the user to set cache variables for the include directories and link + libraries or force users to always call ``find_package()``? + +See the different variations in the below sections: - #cmakedefine HAVE__ +* `Creating FindTPL.cmake using find_package()`_ - should be added to the package's ``_config.h.in`` file (see - `tribits_configure_file()`_) so that the code knows if the TPL is defined - or not. + * `Creating FindTPL.cmake using find_package() with IMPORTED targets`_ -7) Use the TPL in the packages that define the dependency on the new TPL, - configure, test, etc. + * `Creating FindTPL.cmake using find_package() without IMPORTED targets`_ -.. ToDo: Provide more details on various things. +* `Creating a FindTPL.cmake module without find_package()`_ -.. ToDo: Add an example of an optional TPL to some TribitsExampleProject -.. package and refer to it here. +* `Requirements for FindTPL.cmake modules`_ -How to use find_package() for a TriBITS TPL -------------------------------------------- +Creating FindTPL.cmake using find_package() +++++++++++++++++++++++++++++++++++++++++++++++++++++ -When defining a ``FindTPL.cmake`` file, it is possible (and -encouraged) to utilize ``find_package( ...)`` to provide the default -find operation. In order for the resulting ``FindTPL.cmake`` to -behave consistently between all the various TriBITS TPLs (and allow the -standard TriBITS TPL find overrides) one must use the TriBITS function +When defining a ``FindTPL.cmake`` file, it encouraged to utilize +``find_package( ...)`` to provide the default find operation (and +also the definition of the IMPORTED targets needed to use the external package +when supported). (Here, typically ```` and ```` are the +same names, but there are cases where the names may be different or use +different capitalization.) However, the state of the current ecosystem of +``Find.cmake`` modules and ``Config.cmake`` package +config files is a bit uneven. While all find modules and package config files +should be defining modern CMake IMPORTED targets which contains all the needed +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 +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. + +The following subsections will describe how to create these TriBITS-compatible +``FindTPL.cmake`` modules for all of the various cases using an +internal call to ``find_package( ...)``: + +* `Creating FindTPL.cmake using find_package() with IMPORTED targets`_ +* `Creating FindTPL.cmake using find_package() without IMPORTED targets`_ + + +Creating FindTPL.cmake using find_package() with IMPORTED targets +.......................................................................... + +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 +``FindTPL.cmake`` module file is nothing more than:: + + find_package( REQUIRED) + tribits_extpkg_create_imported_all_libs_target_and_config_file( + + INNER_FIND_PACKAGE_NAME + 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 +``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. + +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. + +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()`_. The basic form of the -resulting TriBITS TPL module file ``FindTPL.cmake`` looks like:: - - # First, set up the variables for the (backward-compatible) TriBITS way of - # finding . These are used in case find_package( ...) is - # not called or does not find . Also, these variables need to be - # non-null in order to trigger the right behavior in the function - # tribits_tpl_find_include_dirs_and_libraries(). +`tribits_tpl_find_include_dirs_and_libraries()`_ function as follows:: + + set(REQUIRED_HEADERS ...) + set(REQUIRED_LIBS_NAMES ...) + set(IMPORTED_TARGETS_FOR_ALL_LIBS ...) + + tribits_tpl_allow_pre_find_package( _ALLOW_PREFIND) + + if (_ALLOW_PREFIND) + message("-- Using find_package( ...) ...") + find_package() + if (_FOUND) + message("-- Found _DIR='${_DIR}'") + message("-- Generating ::all_libs and Config.cmake") + tribits_extpkg_create_imported_all_libs_target_and_config_file( + INNER_FIND_PACKAGE_NAME + IMPORTED_TARGETS_FOR_ALL_LIBS ${IMPORTED_TARGETS_FOR_ALL_LIBS} ) + endif() + endif() + + if (NOT TARGET ::all_libs) + tribits_tpl_find_include_dirs_and_libraries( + REQUIRED_HEADERS ${REQUIRED_HEADERS} + REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} ) + endif() + +Above, if ``find_package()`` is called and returns +``_FOUND=FALSE``, then as fallback it will call +``tribits_tpl_find_include_dirs_and_libraries()`` to find the components of +the TPL. See the documentation for `tribits_tpl_allow_pre_find_package()`_ +for conditions where ``_ALLOW_PREFIND`` is set to ``FALSE`` (and +therefore ``find_package()`` is not called). + +Note that in the above ``FindTPL.cmake`` file that +``find_package()`` will be called even on reconfigures. That is +critical since ``find_package()`` defines IMPORTED targets that +must be available each time configure is called. Also, if +``find_package()`` is called and ``_FOUND=TRUE``, +then the function +`tribits_extpkg_create_imported_all_libs_target_and_config_file()`_ +is called which defines the targets ``::all_libs`` which means that +the function ``tribits_tpl_find_include_dirs_and_libraries()`` will **not** be +called. + +A concrete (and tested) example of the latter case can be found in the file +``TribitsExampleProject2/cmake/tpls/FindTPLTpl2.cmake``: + +.. include:: ../../examples/TribitsExampleProject2/cmake/tpls/FindTPLTpl2.cmake + :literal: + + +Creating FindTPL.cmake using find_package() without IMPORTED targets +............................................................................. + +There are cases where calling ``find_package()`` to find the +parts of an external package does not create proper IMPORTED targets that can +be directly used. For example, legacy ``Find.cmake`` modules +(even many standard ``Find*.cmake`` modules shipped with CMake as of CMake +3.23) do not provide IMPORTED targets and instead only provide variables for +the list of include directories ``_INCLUDE_DIRS``, a list of +library files ``_LIBRARIES``, and other information. In cases +such as this, one can implement the ``FindTPL.cmake`` module by +calling ``find_package()``, setting +``TPL__INCLUDE_DIRS`` and ``TPL__LIBRARIES``, and then +calling `tribits_tpl_find_include_dirs_and_libraries()`_ to create the +``::all_libs`` target and the ``Config.cmake`` wrapper +config file. + +The simplest way to implement ``FindTPL.cmake`` is to always call +``find_package()`` as:: + + message("-- Using find_package( ...) ...") + find_package( REQUIRED) + + # Tell TriBITS that we found and there no need to look any further + set(TPL__INCLUDE_DIRS ${_INCLUDE_DIRS} CACHE PATH "...") + set(TPL__LIBRARIES ${_LIBRARIES} CACHE FILEPATH "...") + set(TPL__LIBRARY_DIRS ${_LIBRARY_DIRS} CACHE PATH "...") + + tribits_tpl_find_include_dirs_and_libraries( + REQUIRED_HEADERS neverFindThisHeader + REQUIRED_LIBS_NAMES neverFindThisLib + ) + +The above will always call ``find_package( REQUIRED)``, and if it +can't find the package, it will error out and stop the configure process. + +While the above ``FindTPL.cmake`` file is pretty simple, it does not +allow for a fall-back using the legacy TriBITS TPL find system using +`tribits_tpl_find_include_dirs_and_libraries()`_. One can allow for a +fall-back find by passing a set of header files and library names for +``tribits_tpl_find_include_dirs_and_libraries()`` to find. This can be done +using the ``FindTPL.cmake`` module:: + + set(REQUIRED_HEADERS ...) + set(REQUIRED_LIBS_NAMES ...) + + message("-- Using find_package( ...) ...") + find_package() + if (_FOUND) + # Tell TriBITS that we found and there no need to look any further + set(TPL__INCLUDE_DIRS ${_INCLUDE_DIRS} CACHE PATH "...") + set(TPL__LIBRARIES ${_LIBRARIES} CACHE FILEPATH "...") + set(TPL__LIBRARY_DIRS ${_LIBRARY_DIRS} CACHE PATH "...") + endif() + + tribits_tpl_find_include_dirs_and_libraries( + REQUIRED_HEADERS ${REQUIRED_HEADERS} + REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} + MUST_FIND_ALL_LIBS ) + +Above, if ``find_package()`` can't find ````, then +the function ``tribits_tpl_find_include_dirs_and_libraries()`` will try to +find the listed required header files and libraries, using the legacy TriBITS +TPL find system. And if ``find_package()`` can find +````, then all the call to +`tribits_tpl_find_include_dirs_and_libraries()`_ will not look for anything +and will just take the information in the variables +``TPL__INCLUDE_DIRS`` and ``TPL__LIBRARIES`` and build +IMPORTED targets and the ``::all_libs`` target. + +Finally, if one is upgrading an existing ``FindTPL.cmake`` file to +use ``find_package()`` but needs to maintain backward +compatibility for existing configure scripts for the project that might be +using the legacy TriBITS TPL system, one can use the function +`tribits_tpl_allow_pre_find_package()`_ to determine if +``find_package()`` can be called or if the legacy TriBITS TPL +find must be used (to maintain backward compatibility). This +``FindTPL.cmake`` looks like:: + set(REQUIRED_HEADERS ...) set(REQUIRED_LIBS_NAMES ...) - - # Second, search for components (if allowed) using the standard - # find_package( ...). + tribits_tpl_allow_pre_find_package( _ALLOW_PREFIND) + if (_ALLOW_PREFIND) - message("-- Using find_package( ...) ...") - find_package() - if (_FOUND) - # Tell TriBITS that we found and there no need to look any further! - set(TPL__INCLUDE_DIRS ${_INCLUDE_DIRS} CACHE PATH "...") - set(TPL__LIBRARIES ${_LIBRARIES} CACHE FILEPATH "...") - set(TPL__LIBRARY_DIRS ${_LIBRARY_DIRS} CACHE PATH "...") + message("-- Using find_package ...) ...") + find_package() + if (_FOUND) + # Tell TriBITS that we found and there no need to look any further + set(TPL__INCLUDE_DIRS ${_INCLUDE_DIRS} CACHE PATH "...") + set(TPL__LIBRARIES ${_LIBRARIES} CACHE FILEPATH "...") + set(TPL__LIBRARY_DIRS ${_LIBRARY_DIRS} CACHE PATH "...") endif() endif() - - # Third, call tribits_tpl_find_include_dirs_and_libraries() + tribits_tpl_find_include_dirs_and_libraries( REQUIRED_HEADERS ${REQUIRED_HEADERS} REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} - ) - # NOTE: If find_package( ...) was called and successfully found - # , then tribits_tpl_find_include_dirs_and_libraries() will use the - # already-set variables and just print them out. This is the final "hook" - # into the TriBITS TPL system. - -With this approach, the ``FindTPL.cmake`` module preserves all of the -user behavior described in `Enabling support for an optional Third-Party -Library (TPL)`_ for overriding what TPL components to look for, where to look -and finally to override what is actually used. That is, if the user sets the -cache variables ``TPL__INCLUDE_DIRS``, ``TPL__LIBRARIES``, -or ``TPL__LIBRARY_DIRS``, then they should be used without question -(which is why the ``set( ... CACHE ...)`` calls in the above example do not -use ``FORCE``). + MUST_FIND_ALL_LIBS ) + +The above will result in skipping the call of ``find_package()`` +if any of the legacy TPL find variables are set. But if the legacy TPL find +variables are not set, then the default find will use +``find_package()`` and will only fall back on the legacy TriBITS +TPL find operation if ``find_package()`` sets +``_FOUND=FALSE``. + +With this last approach, the ``FindTPL.cmake`` module preserves all +of the user behavior described in `Enabling support for an optional +Third-Party Library (TPL)`_ for overriding what TPL components to look for, +where to look, and finally to override what is actually used. That is, if the +user sets the cache variables ``TPL__INCLUDE_DIRS``, +``TPL__LIBRARIES``, or ``TPL__LIBRARY_DIRS``, then they +should be used without question (which is why the ``set( ... CACHE ...)`` +calls in the above example do not use ``FORCE``). If one wants to skip and ignore the standard TriBITS TPL override variables ``_INCLUDE_DIRS``, ``_LIBRARY_NAMES``, or ``_LIBRARY_DIRS``, then one can set:: - set(_FORCE_PRE_FIND_PACKAGE TRUE CACHE BOOL + set(_FORCE_PRE_FIND_PACKAGE TRUE CACHE BOOL "Always first call find_package( ...) unless explicit override") -at the top of the ``FindTPL.cmake`` and it will ignore these -variables. This avoids name classes with the variables -``_INCLUDE_DIRS`` and ``_LIBRARY_DIRS`` which are often used -in the concrete CMake ``Find.cmake`` module files themselves. +at the top of the file ``FindTPL.cmake`` and +``tribits_tpl_allow_pre_find_package()`` will ignore these variables and +return ``TRUE``. This avoids name classes with the variables +``_INCLUDE_DIRS`` and ``_LIBRARY_DIRS`` with +``_INCLUDE_DIRS`` and ``_LIBRARY_DIRS`` (when `` == +``) which are often used in the concrete legacy CMake +``Find.cmake`` module files themselves. For a slightly more complex (but real-life) example, see ``FindTPLHDF5.cmake`` which is: @@ -5540,15 +5891,51 @@ which is: .. include:: ../../common_tpls/FindTPLHDF5.cmake :literal: -Note that some specialized ``Find.cmake`` modules do more than just -return a list of include directories and libraries. Some, like +Note that some specialized ``Find.cmake`` modules do more than +just return a list of include directories and libraries. Some, like ``FindQt4.cmake`` also return other variables that are used in downstream packages. therefore, in these cases, ``find_package(Qt4 ...)`` must be called -on every configure. In specialized cases such as this, one must write a more -specialized ``FindTPL.cmake`` file and can't use the -`tribits_tpl_allow_pre_find_package()`_ function like shown above. Such -find modules cannot completely adhere to the standard behavior described in -`Enabling support for an optional Third-Party Library (TPL)`_. +on every configure. Such find modules cannot completely adhere to the +standard legacy TriBITS behavior described in `Enabling support for an +optional Third-Party Library (TPL)`_. + + +Creating a FindTPL.cmake module without find_package() ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +For external packages that don't have a ``Find.cmake`` module or +``Config.cmake`` package config file, it may make sense to create +a simple ``FindTpl.cmake`` module that just calls +`tribits_tpl_find_include_dirs_and_libraries()`_ with the set of required +header files and libraries that must be found. A simple +``FindTPL.cmake`` module of this form is:: + + tribits_tpl_find_include_dirs_and_libraries( + REQUIRED_HEADERS ... + REQUIRED_LIBS_NAMES ... + MUST_FIND_ALL_LIBS + ) + + +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: + +* 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). + +* 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 +considerations for TriBITS-generated Config.cmake files`_. How to add a new TriBITS Repository @@ -5641,7 +6028,7 @@ as follows: #if HAVE__ # include "_" - #endif + #endif 4) **For an optional dependency, use CMake if() statements based on ${PACKAGE_NAME}_ENABLE_${OPTIONAL_DEP_PACKAGE_NAME}:** When a package @@ -5658,7 +6045,7 @@ as follows: endif() .. ToDo: Find an example to point to in TribitsExampleProject. - + NOTE: TriBITS will automatically add the include directories for the upstream package to the compile lines for the downstream package source builds and will add the libraries for the upstream package to the link lines to the downstream @@ -5721,7 +6108,7 @@ follows: #if HAVE__ # include "_" - #endif + #endif 4) **For an optional dependency, use CMake if() statements based on ${PACKAGE_NAME}_ENABLE_${OPTIONAL_DEP_TPL_NAME}:** When a package @@ -5738,7 +6125,7 @@ follows: endif() .. ToDo: Find an example to point to in TribitsExampleProject. - + NOTE: TriBITS will automatically add the include directories for the upstream TPL to the compile lines for the downstream package source builds and will add the libraries for the upstream TPL to the link lines to the downstream package @@ -6193,7 +6580,7 @@ The following steps describe how to submit results to a CDash site using the /TribitsExamplProject and then run ``make dashboard``. - + 4) Add custom CTest -S driver scripts. For driving different builds and tests, one needs to set up one or more @@ -6252,7 +6639,7 @@ The following steps describe how to submit results to a CDash site using the submit to CDash in a variety of ways: * Cron jobs can be set up to run them at the same time every day. - + * Jenkins jobs can be set up to run them based on various criteria. * Travis CI can run them to respond to GitHub pushes. @@ -6301,22 +6688,21 @@ given below. )`` in the CTest -S ``*.cmake`` driver script itself or can set it in the environment when running the ctest -S driver script. For example:: - + $ env _TRACK= ... \ ctest -V -S .cmake - + If the "build type" for the CDash group ```` was set to "Daily", then set `CTEST_TEST_TYPE`_ to ``Nightly``. Otherwise, ``CTEST_TEST_TYPE`` can be set to ``Continuous`` or ``Experimental``. -Additional Topics -================= +Miscellaneous Topics +==================== In this section, a number of miscellaneous topics and TriBITS features are discussed. These features and topics are either not considered primary -features of TriBITS (but can be very useful in many situations) or don't neatly -fit into one of the other sections. +features of TriBITS or don't neatly fit into one of the other sections. TriBITS Repository Contents @@ -6521,6 +6907,53 @@ ready to compile code. All of the major variables set as part of this process are printed to the ``cmake`` stdout when the project is configured. +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 be included by and 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:: + + /external_packages//Config.cmake + +and installed into the 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 +``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 +``ConfigVersion.cmake``, even if no version information is passed to +the command ``find_package()``. This allows special logic to be +placed in the file ``ConfigVersion.cmake`` to determine if +``find_package()`` will select a given ``Config.cmake`` file +that is in the search path based on a number of different criteria such as in +this case.) + + Installation considerations --------------------------- @@ -6788,12 +7221,12 @@ rebase by default) as shown in the following Trilinos commit:: commit 71ce56bd2d268922fda7b8eca74fad0ffbd7d807 Author: Roscoe A. Bartlett Date: Thu Feb 19 12:04:11 2015 -0500 - + Define HAVE_TEUCHOSCORE_CXX11 in TeuchosCore_config.h - + This makes TeuchosCore a good example for how Trilinos (or any TriBITS) subpackages should put in an optional dependency on C++11. - + Build/Test Cases Summary Enabled Packages: TeuchosCore Disabled Packages: [...] @@ -6942,16 +7375,16 @@ the commands:: $ cat ../git_bisect_log.log | grep "possible first bad commit" | \ sed "s/possible first bad commit://g" | sed "s/[a-z0-9]\{30\}\]/]/g" $ git bisect reset - + This set of commands yield the output:: Bisecting: 1128 revisions left to test after this (roughly 10 steps) [9634d462dba77704b598e89ba69ba3ffa5a71471] Revert "Trilinos: remove _def.hpp [...]" - + real 1m22.961s user 0m57.157s sys 3m40.376s - + # [165067ce53] MueLu: SemiCoarsenPFactory. Use strided maps to properly transfer [...] # [ada21a95a9] MueLu: refurbish LineDetectionFactory # [83f05e8970] MueLu: stop semi-coarsening if no z-layers are left. @@ -6965,7 +7398,7 @@ bounded in the set of commits ``8b79832..165067c``:: 165067c "MueLu: SemiCoarsenPFactory. Use strided maps to properly [...]." Author: Tobias Wiesner Date: Thu Jul 2 12:11:24 2015 -0600 - + 8b79832 "Ifpack2: RBILUK: adding additional ETI types" Author: Jonathan Hu Date: Thu Jul 2 14:17:40 2015 -0700 @@ -6992,7 +7425,7 @@ intermediate commits are in Trilinos. All that matters is the usage of the ``checkin-test.py`` tool (another motivation for the usage of the ``checkin-test.py`` tool, see `Pre-push Testing using checkin-test.py`_ for others as well). - + Note that above, we grep the output from ``git bisect log`` for the set of possible "bad" commits instead of just looking at the output from the ``git bisect run