From b6837af19768a7ce1d5641e4d4915413be741b27 Mon Sep 17 00:00:00 2001 From: "Roscoe A. Bartlett" Date: Fri, 29 Oct 2021 16:27:36 -0600 Subject: [PATCH 1/4] Sacado: Add TRIBITS_TESTONLY_LIB to non-TriBITS targets (TriBITSPub/TriBITS#299) The updated version of TriBITS using modern CMake for TriBITSPub/TriBITS#299 creates a ${PACKAGE_NAME}_all_libs library target (used to create an ALIAS ${PACKAGE_NAME}::all_libs library target) from all of the targets under a package's base CMakeLists.txt file that don't have the TRIBITS_TESTONLY_LIB property set to TRUE. The tribits_add_library( ... TESTONLY ... ) function call automatically sets this property but if a package uses raw CMake to create targets (like Sacado is doing here with GoogleTest), then one must set the TRIBITS_TESTONLY_LIB property or one must create the ${PACKAGE_NAME}_all_libs and ${PACKAGE_NAME}::all_libs targets manually. Small price to pay on the path to making TriBITS more flexible and allowing raw CMake target formation. --- packages/sacado/test/GTestSuite/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/sacado/test/GTestSuite/CMakeLists.txt b/packages/sacado/test/GTestSuite/CMakeLists.txt index 54ad77f993b8..4ff0be297cbe 100644 --- a/packages/sacado/test/GTestSuite/CMakeLists.txt +++ b/packages/sacado/test/GTestSuite/CMakeLists.txt @@ -5,6 +5,8 @@ SET(gtest_disable_pthreads ON CACHE BOOL "Disable uses of pthreads in gtest") # Configure googletest add_subdirectory(googletest) +set_target_properties(sacado-gtest gtest_main PROPERTIES + TRIBITS_TESTONLY_LIB TRUE) INCLUDE_DIRECTORIES(${PACKAGE_SOURCE_DIR}/Fad) INCLUDE_DIRECTORIES(${PACKAGE_SOURCE_DIR}/test/utils) From 23c2a5751fca2c2ce8eb9d81509a1e1abfcc286c Mon Sep 17 00:00:00 2001 From: "Roscoe A. Bartlett" Date: Tue, 2 Nov 2021 10:07:05 -0600 Subject: [PATCH 2/4] Automatic snapshot commit from tribits at 99d3869 Origin repo remote tracking branch: 'github/master' Origin repo remote repo URL: 'github = git@github.com:TriBITSPub/TriBITS.git' At commit: commit 99d3869645d0083cb499389659f1394f0b5e6a89 Author: Roscoe A. Bartlett Date: Mon Nov 1 09:48:44 2021 -0600 Summary: Call generate and include Config.cmake files (#299) --- cmake/tribits/ReleaseNotes.txt | 20 + cmake/tribits/TriBITS.cmake | 39 +- .../TribitsPackageConfigTemplate.cmake.in | 3 +- .../TribitsPackageConfigTemplate.export.in | 110 ---- .../TribitsProjectConfigTemplate.cmake.in | 32 +- .../TribitsProjectConfigTemplate.export.in | 90 --- .../CMakeLists.txt | 5 +- .../package_arch/TribitsAddAdvancedTest.cmake | 44 +- .../package_arch/TribitsAddExecutable.cmake | 5 +- .../core/package_arch/TribitsConstants.cmake | 8 +- .../TribitsCreateClientTemplateHeaders.cmake | 6 +- ...ribitsExternalPackageWriteConfigFile.cmake | 486 ++++++++++++++ .../package_arch/TribitsGlobalMacros.cmake | 24 +- .../package_arch/TribitsLibraryMacros.cmake | 49 +- .../package_arch/TribitsPackageMacros.cmake | 83 ++- .../TribitsProcessEnabledTpl.cmake | 6 +- .../TribitsReportInvalidTribitsUsage.cmake | 6 +- .../TribitsSubPackageMacros.cmake | 4 + ...itsSystemDataStructuresMacrosFunctions.rst | 18 +- ...ribitsTplFindIncludeDirsAndLibraries.cmake | 26 +- .../TribitsWriteClientExportFiles.cmake | 608 ++++++++---------- .../tribits/core/utils/AppendStringVar.cmake | 4 + .../core/utils/DriveAdvancedTest.cmake | 2 +- cmake/tribits/core/utils/MessageWrapper.cmake | 6 +- cmake/tribits/core/utils/PrintVar.cmake | 6 +- .../utils/TribitsGatherBuildTargets.cmake | 120 ++++ .../tribits/core/utils/UnitTestHelpers.cmake | 114 +++- .../ctest_driver/TribitsCTestDriverCore.cmake | 2 +- .../TribitsCTestDriverCoreHelpers.cmake | 2 +- .../build_ref/TribitsBuildReferenceBody.rst | 146 ++++- .../guides/TribitsCoreDetailedReference.rst | 27 +- .../TribitsMacroFunctionDocTemplate.rst | 2 +- .../TribitsSystemMacroFunctionDocTemplate.rst | 1 + .../src/TribitsTutorial_HelloWorld.rst | 2 - .../examples/InsertedPkg/test/CMakeLists.txt | 2 +- .../TribitsExampleApp/AppHelperFuncs.cmake | 171 +++++ .../examples/TribitsExampleApp/CMakeLists.txt | 41 ++ .../examples/TribitsExampleApp/README.md | 110 ++++ .../examples/TribitsExampleApp/app.cpp | 46 ++ .../TribitsExampleProject/ProjectName.cmake | 3 +- .../cmake/CallbackSetupExtraOptions.cmake | 4 +- .../simple_cxx/src/SimpleCxx_HelloWorld.cpp | 7 +- .../test/SimpleCxx_HelloWorld_Tests.cpp | 9 + .../with_subpackages/a/tests/CMakeLists.txt | 2 +- .../with_subpackages/b/tests/CMakeLists.txt | 6 +- .../with_subpackages/c/tests/CMakeLists.txt | 6 +- .../packages/wrap_external/CMakeLists.txt | 41 +- .../wrap_external/external_func/configure.py | 28 +- .../packages/addon1/tests/CMakeLists.txt | 2 +- .../TribitsSimpleExampleApp/CMakeLists.txt | 41 ++ .../TribitsSimpleExampleApp/README.md | 19 + .../examples/TribitsSimpleExampleApp/app.cpp | 33 + .../HeaderOnlyTpl/HeaderOnlyTpl_stuff.hpp | 7 + .../examples/tpls/SimpleTpl/CMakeLists.txt | 24 +- .../examples/tpls/SimpleTpl/SimpleTpl.cpp | 5 + .../examples/tpls/SimpleTpl/SimpleTpl.hpp | 5 + 56 files changed, 1970 insertions(+), 748 deletions(-) delete mode 100644 cmake/tribits/core/installation/TribitsPackageConfigTemplate.export.in delete mode 100644 cmake/tribits/core/installation/TribitsProjectConfigTemplate.export.in create mode 100644 cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake create mode 100644 cmake/tribits/core/utils/TribitsGatherBuildTargets.cmake create mode 100644 cmake/tribits/examples/TribitsExampleApp/AppHelperFuncs.cmake create mode 100644 cmake/tribits/examples/TribitsExampleApp/CMakeLists.txt create mode 100644 cmake/tribits/examples/TribitsExampleApp/README.md create mode 100644 cmake/tribits/examples/TribitsExampleApp/app.cpp create mode 100644 cmake/tribits/examples/TribitsSimpleExampleApp/CMakeLists.txt create mode 100644 cmake/tribits/examples/TribitsSimpleExampleApp/README.md create mode 100644 cmake/tribits/examples/TribitsSimpleExampleApp/app.cpp diff --git a/cmake/tribits/ReleaseNotes.txt b/cmake/tribits/ReleaseNotes.txt index 021bed044532..83103a2e4f02 100644 --- a/cmake/tribits/ReleaseNotes.txt +++ b/cmake/tribits/ReleaseNotes.txt @@ -2,6 +2,26 @@ Release Notes for TriBITS ---------------------------------------- +2021/10/11: + +(*) MAJOR: 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 fine 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. + +2021/09/13: + +(*) MAJOR: 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 inforamtion from TriBITS (see + TriBITSPub/TriBITS#63 and TriBITSPub/TriBITS#299). + 2021/06/17: (*) MINOR: Added tool tribits/python_utils/lower_case_cmake.py and driver 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/core/installation/TribitsPackageConfigTemplate.cmake.in b/cmake/tribits/core/installation/TribitsPackageConfigTemplate.cmake.in index 0ebe06a1651b..b85fd96ea97f 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() ## --------------------------------------------------------------------------- ## Compilers used by ${PROJECT_NAME}/${PACKAGE_NAME} build 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..0b6b5b50f16a 100644 --- a/cmake/tribits/core/installation/TribitsProjectConfigTemplate.cmake.in +++ b/cmake/tribits/core/installation/TribitsProjectConfigTemplate.cmake.in @@ -46,10 +46,7 @@ # ############################################################################## -# -# Ensure CMAKE_CURRENT_LIST_DIR is usable. -# -${DEFINE_CMAKE_CURRENT_LIST_DIR_CODE_SNIPPET} +include_guard() ## --------------------------------------------------------------------------- ## Compilers used by ${PROJECT_NAME} build @@ -106,7 +103,7 @@ 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}) +foreach (comp IN ITEMS ${PDOLLAR}{COMPONENTS_LIST}) set( INCLUDE_FILE ${PDOLLAR}{CMAKE_CURRENT_LIST_DIR}/../${PDOLLAR}{comp}/${PDOLLAR}{comp}Config.cmake @@ -198,5 +195,30 @@ 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}{COMPONENTS_LIST}") + ## 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) +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} ) + +# ${PROJECT_NAME}::all_selected_libs (Depend on COMPONENTS) +set(${PROJECT_NAME}_ALL_SELECTED_PACKAGES_TARGETS) +foreach (pkg IN ITEMS ${PDOLLAR}{COMPONENTS_LIST}) + 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} ) 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..be49149518ba 100644 --- a/cmake/tribits/core/package_arch/TribitsAddAdvancedTest.cmake +++ b/cmake/tribits/core/package_arch/TribitsAddAdvancedTest.cmake @@ -945,7 +945,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" @@ -1187,7 +1187,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 +1234,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 +1244,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" @@ -1263,7 +1263,7 @@ function(tribits_add_advanced_test TEST_NAME_IN) 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 +1275,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 +1285,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 +1312,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 +1451,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..aa0f100dec42 100644 --- a/cmake/tribits/core/package_arch/TribitsAddExecutable.cmake +++ b/cmake/tribits/core/package_arch/TribitsAddExecutable.cmake @@ -499,8 +499,9 @@ function(tribits_add_executable EXE_NAME) " 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}::${PREFIXED_LIB}" + FOUND_PREFIXED_LIB_IN_PKG_LIBRARIES_IDX) + if (NOT FOUND_PREFIXED_LIB_IN_PKG_LIBRARIES_IDX EQUAL -1) message(FATAL_ERROR "ERROR: Lib '${IMPORTEDLIB}' in IMPORTEDLIBS is in" " this SE package and is *not* an external lib!" diff --git a/cmake/tribits/core/package_arch/TribitsConstants.cmake b/cmake/tribits/core/package_arch/TribitsConstants.cmake index bdc63ef5d847..cb67118da50f 100644 --- a/cmake/tribits/core/package_arch/TribitsConstants.cmake +++ b/cmake/tribits/core/package_arch/TribitsConstants.cmake @@ -94,13 +94,15 @@ 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_CMAKE_PKGS_DIR "cmake_packages") + # Other stuff -if(WIN32) +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) -else(WIN32) +else() set(GIT_NAME git) -endif(WIN32) +endif() 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/TribitsExternalPackageWriteConfigFile.cmake b/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake new file mode 100644 index 000000000000..492a3b5fb464 --- /dev/null +++ b/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake @@ -0,0 +1,486 @@ +# @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(TribitsGeneralMacros) + +include(MessageWrapper) + + +# @FUNCTION: tribits_external_package_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_external_package_write_config_file_str()`` and writes that text to +# the file ```` so see that function for more details. +# +function(tribits_external_package_write_config_file tplName tplConfigFile) + tribits_external_package_write_config_file_str(${tplName} tplConfigFileStr) + file(WRITE "${tplConfigFile}" "${tplConfigFileStr}") +endfunction() + + +# @FUNCTION: tribits_external_package_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_external_package_install_config_file tplName tplConfigFile) + install( + FILES "${tplConfigFile}" + DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}/cmake/${tplName}" + ) +endfunction() + + +# @FUNCTION: tribits_external_package_write_config_file_str() +# +# Create the text strig for a ``Config.cmake`` file given the list of +# include directories and libraries for an external package/TPL. +# +# Usage:: +# +# tribits_external_package_write_config_file_str( +# ) +# +# The 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 varaibles ``TPL__INCLUDE_DIRS`` and +# ``TPL__LIBRARIES`` (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 the +# represent these libraries and include directories. +# +# ToDo: Flesh out more documentation for behavior as more features are added +# for handling: +# +# * ``TPL__LIBRARIES`` containing ``-l`` and ``-L`` arguments ... +# +# * ``TPL__LIBRARIES`` containing arguments other than library files +# * or ``-l`` and ``-L`` arguments and files. +# +function(tribits_external_package_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" + "include_guard()\n" + "\n" + ) + + # B) Create IMPORTED library targets from TPL_${tplName}_LIBRARIES + tribits_external_package_process_libraries_list( + ${tplName} + LIB_TARGETS_LIST_OUT libTargets + LIB_LINK_FLAGS_LIST_OUT libLinkFlags + CONFIG_FILE_STR_INOUT configFileStr + ) + + # C) Create the ::all_libs target + tribits_external_package_create_all_libs_target( + ${tplName} + LIB_TARGETS_LIST ${libTargets} + LIB_LINK_FLAGS_LIST ${libLinkFlags} + CONFIG_FILE_STR_INOUT configFileStr + ) + + # D) Set the output + set(${tplConfigFileStrOut} "${configFileStr}" PARENT_SCOPE) + +endfunction() + + +# @FUNCTION: tribits_external_package_process_libraries_list() +# +# Read the ``TPL__LIBRARIES` list variable and produce the string for +# the IMPORTED targets commands and return list of targets and left over +# linker flags.. +# +# Usage:: +# +# tribits_external_package_process_libraries_list( +# +# LIB_TARGETS_LIST_OUT +# LIB_LINK_FLAGS_LIST_OUT +# CONFIG_FILE_STR_INOUT +# ) +# +# The arguments are: +# +# ````: Name of the external package/TPL +# +# ````: Name of list variable that will be set with the +# list of IMPORTED library targets generated from this list. +# +# ````: Name of list variable that will be set with the +# list of ``-L`` library directoy paths. +# +# ````: A string variable that will be appended with +# the IMPORTED library commands for the list of targts given in +# ````. +# +function(tribits_external_package_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(lastLib "") + + # 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 "FULL_LIB_PATH") + tribits_external_package_process_libraries_list_full_lib_path( + ${tplName} "${libentry}" libTargets lastLib configFileStr ) + elseif (libEntryType STREQUAL "LIB_NAME_LINK_OPTION") + tribits_external_package_process_libraries_list_lib_name_link_option( + ${tplName} "${libentry}" libTargets lastLib configFileStr ) + elseif (libEntryType STREQUAL "LIB_DIR_LINK_OPTION") + list(APPEND libLinkFlagsList "${libentry}") + else() + message_wrapper(SEND_ERROR + "ERROR: Can't handle argument '${libentry}' in list TPL_${tplName}_LIBRARIES") + 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() + + +# Returns the type of the library entry in the list TPL__LIBRARIES +# +# Arguments: +# +# ``libentry`` [in]: Element of ``TPL__LIBRARIES`` +# +# ``libEntryTypeOut`` [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_DIR_LINK_OPTION``: A library directory search option of the form +# ``-L`` +# +# ``UNSUPPORTED_LIB_ENTRY``: An unsupported lib option +# +function(tribits_tpl_libraries_entry_type libentry libEntryTypeOut) + 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 (IS_ABSOLUTE "${libentry}") + set(libEntryType FULL_LIB_PATH) + else() + set(libEntryType UNSUPPORTED_LIB_ENTRY) + endif() + set(${libEntryTypeOut} ${libEntryType} PARENT_SCOPE) +endfunction() + + +# Function to process a full library path lib entry inside of loop over +# TPL__LIBRARIES in the function +# tribits_external_package_process_libraries_list() +# +function(tribits_external_package_process_libraries_list_full_lib_path + tplName libentry libTargetsInOut lastLibInOut configFileStrInOut + ) + # Set local vars for inout vars + set(libTargets ${${libTargetsInOut}}) + set(lastLib ${${lastLibInOut}}) + set(configFileStr ${${configFileStrInOut}}) + # Should be an absolute library path + get_filename_component(full_libname "${libentry}" NAME_WLE) + #print_var(full_libname) + # Assert is a valid lib name and get lib name + string(LENGTH "${full_libname}" full_libname_len) + if (full_libname_len LESS 0) + tribits_print_invalid_lib_name(${tplName} "${full_libname}") + endif() + string(SUBSTRING "${full_libname}" 0 3 libPart) + if (NOT libPart STREQUAL "lib") + tribits_print_invalid_lib_name(${tplName} "${full_libname}") + endif() + string(SUBSTRING "${full_libname}" 3 -1 libname) + #print_var(libname) + # Create IMPORTED library target + string(APPEND configFileStr + "add_library(${tplName}::${libname} IMPORTED UNKNOWN GLOBAL)\n" + "set_target_properties(${tplName}::${libname} PROPERTIES\n" + " IMPORTED_LOCATION \"${libentry}\")\n" + ) + # Set dependency on previous library + if (lastLib) + string(APPEND configFileStr + "target_link_libraries(${tplName}::${libname}\n" + " INTERFACE ${tplName}::${lastLib})\n" + ) + endif() + string(APPEND configFileStr + "\n") + # Update for next loop + set(lastLib ${libname}) + list(APPEND libTargets "${tplName}::${libname}") + # Set output vars + set(${libTargetsInOut} ${libTargets} PARENT_SCOPE) + set(${lastLibInOut} ${lastLib} PARENT_SCOPE) + set(${configFileStrInOut} ${configFileStr} PARENT_SCOPE) +endfunction() + + +# Function to process a ``-l`` entry inside of loop over +# TPL__LIBRARIES in the function +# ``tribits_external_package_process_libraries_list()`` +# +function(tribits_external_package_process_libraries_list_lib_name_link_option + tplName libentry libTargetsInOut lastLibInOut configFileStrInOut + ) + # Set local vars for inout vars + set(libTargets ${${libTargetsInOut}}) + set(lastLib ${${lastLibInOut}}) + set(configFileStr ${${configFileStrInOut}}) + # Assert begging part '-l' + string(SUBSTRING "${libentry}" 0 2 firstTwoCharsLibEntry) + if ( ) + tribits_print_invalid_lib_link_option(${tplName} "${libentry}") + endif() + # Get from -l + string(SUBSTRING "${libentry}" 2 -1 libname) + # Create IMPORTED library target + string(APPEND configFileStr + "add_library(${tplName}::${libname} IMPORTED INTERFACE GLOBAL)\n" + "set_target_properties(${tplName}::${libname} PROPERTIES\n" + " IMPORTED_LIBNAME \"${libname}\")\n" + ) + # Set dependency on previous library + if (lastLib) + string(APPEND configFileStr + "target_link_libraries(${tplName}::${libname}\n" + " INTERFACE ${tplName}::${lastLib})\n" + ) + endif() + string(APPEND configFileStr + "\n") + # Update for next loop + set(lastLib ${libname}) + list(APPEND libTargets "${tplName}::${libname}") + # Set output vars + set(${libTargetsInOut} ${libTargets} PARENT_SCOPE) + set(${lastLibInOut} ${lastLib} PARENT_SCOPE) + set(${configFileStrInOut} ${configFileStr} PARENT_SCOPE) +endfunction() + + +function(tribits_print_invalid_lib_name tplName full_libname) + message(SEND_ERROR + "ERROR: TPL_${tplName}_LIBRARIES entry '${full_libname}' not a valid lib 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_external_package_create_all_libs_target() +# +# Creates the ::all_libs target command text using input info and +# from ``TPL__INCLUDE_DIRS``. +# +# Usage:: +# +# tribits_external_package_create_all_libs_target( +# +# LIB_TARGETS_LIST +# LIB_LINK_FLAGS_LIST +# CONFIG_FILE_STR_INOUT +# ) +# +# The arguments are: +# +# ````: Name of the external package/TPL +# +# ````: List of targets created from processing +# ``TPL__LIBRARIES``. +# +# ````: List of of ``-L`` library directory paths +# entries found while processing ``TPL__LIBRARIES``. +# +# ````: A string variable that will be appended with +# the ``::all_libs`` target statements. +# +function(tribits_external_package_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/TribitsGlobalMacros.cmake b/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake index 567ce40546da..91c2a6cf4180 100644 --- a/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake @@ -84,7 +84,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/" @@ -572,20 +572,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 +587,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) @@ -1328,7 +1312,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 +1336,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" ) diff --git a/cmake/tribits/core/package_arch/TribitsLibraryMacros.cmake b/cmake/tribits/core/package_arch/TribitsLibraryMacros.cmake index cc97f07b5e0f..85cbe018437a 100644 --- a/cmake/tribits/core/package_arch/TribitsLibraryMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsLibraryMacros.cmake @@ -165,7 +165,7 @@ function(tribits_configure_file PACKAGE_NAME_CONFIG_FILE) endif() if (${PARENT_PACKAGE_NAME}_HIDE_DEPRECATED_CODE) - append_string_var(${PARENT_PACKAGE_NAME_UC}_DEPRECATED_DECLARATIONS + string(APPEND ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_DECLARATIONS "\n#define ${PARENT_PACKAGE_NAME_UC}_HIDE_DEPRECATED_CODE") endif() @@ -202,7 +202,9 @@ endfunction() # # @FUNCTION: tribits_add_library() # -# Function used to add a CMake library and target using ``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:: # @@ -333,7 +335,10 @@ endfunction() # 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. +# 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`` # @@ -575,7 +580,8 @@ function(tribits_add_library LIBRARY_NAME_IN) # Add whatever include directories have been defined so far - include_directories(AFTER ${${PACKAGE_NAME}_INCLUDE_DIRS}) + #include_directories(AFTER ${${PACKAGE_NAME}_INCLUDE_DIRS}) + # ToDo: #299: Remove the above once final cleanup is performed for #299. # Add whatever link directories have been added so far @@ -626,7 +632,7 @@ function(tribits_add_library LIBRARY_NAME_IN) set(PREFIXED_LIB "${LIBRARY_NAME_PREFIX}${LIB}") # LIB_IN_SE_PKG? - list(FIND ${PACKAGE_NAME}_LIBRARIES ${PREFIXED_LIB} FOUND_IDX) + list(FIND ${PACKAGE_NAME}_LIBRARIES "${PACKAGE_NAME}::${PREFIXED_LIB}" FOUND_IDX) if (FOUND_IDX GREATER -1) set(LIB_IN_SE_PKG TRUE) else() @@ -711,14 +717,15 @@ function(tribits_add_library LIBRARY_NAME_IN) foreach(IMPORTEDLIB ${PARSE_IMPORTEDLIBS}) set(PREFIXED_LIB "${LIBRARY_NAME_PREFIX}${IMPORTEDLIB}") - list(FIND ${PACKAGE_NAME}_LIBRARIES ${PREFIXED_LIB} FOUND_IDX) + list(FIND ${PACKAGE_NAME}_LIBRARIES "${PACKAGE_NAME}::${PREFIXED_LIB}" + FOUND_IMPORTEDLIB_IN_LIBRARIES_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) + elseif (FOUND_IMPORTEDLIB_IN_LIBRARIES_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" @@ -837,6 +844,11 @@ function(tribits_add_library LIBRARY_NAME_IN) set(${PARSE_ADDED_LIB_TARGET_NAME_OUT} ${LIBRARY_NAME} PARENT_SCOPE) endif() + if (PARSE_TESTONLY) + set_target_properties(${LIBRARY_NAME} PROPERTIES + TRIBITS_TESTONLY_LIB TRUE) + endif() + set_property( TARGET ${LIBRARY_NAME} APPEND PROPERTY @@ -912,6 +924,7 @@ function(tribits_add_library LIBRARY_NAME_IN) 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}" @@ -936,7 +949,7 @@ function(tribits_add_library LIBRARY_NAME_IN) 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}) + prepend_global_set(${PACKAGE_NAME}_LIBRARIES ${PACKAGE_NAME}::${LIBRARY_NAME}) remove_global_duplicates(${PACKAGE_NAME}_INCLUDE_DIRS) remove_global_duplicates(${PACKAGE_NAME}_LIBRARY_DIRS) @@ -961,6 +974,26 @@ function(tribits_add_library LIBRARY_NAME_IN) endif() endif() + + # Set INTERFACE_INCLUDE_DIRECTOIRES property for added library and must + # only do for the build interface (not the install interface). + set(buildInterfaceIncludeDirs) + foreach (includeDir IN LISTS ${PACKAGE_NAME}_INCLUDE_DIRS) + list(APPEND buildInterfaceIncludeDirs "$") + endforeach() + target_include_directories( ${LIBRARY_NAME} PUBLIC ${buildInterfaceIncludeDirs} ) + # ToDo: #299: In the final refactoring, the list of include directories + # for this library should be extracted from the directory property + # INCLUDE_DIRECTORIES and then set INTERFACE instead of PUBLIC above. The + # rest of the include directories from upstream packages should come from + # the targets that have their INTERFACE_INCLUDE_DIRECTORIES property set. + + # + # Add ALIAS library :: + # + + add_library(${PACKAGE_NAME}::${LIBRARY_NAME} ALIAS ${LIBRARY_NAME}) + endif() #if not in installation testing mode # diff --git a/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake b/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake index 615830b9b94b..419a09160924 100644 --- a/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake @@ -48,6 +48,7 @@ include(PrintVar) include(PrependSet) include(PrependGlobalSet) include(RemoveGlobalDuplicates) +include(TribitsGatherBuildTargets) include(TribitsAddOptionAndDefine) include(TribitsLibraryMacros) @@ -69,7 +70,6 @@ include(TribitsReportInvalidTribitsUsage) # -# # Macro that defines the package architecture system variables used to link # different SE packages together # @@ -84,7 +84,6 @@ macro(tribits_define_linkage_vars PACKAGE_NAME_IN) endmacro() -# # Macro that defines variables that create global targets # macro(tribits_define_target_vars PARENT_PACKAGE_NAME_IN) @@ -92,10 +91,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 +109,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 +274,6 @@ macro(tribits_package_decl PACKAGE_NAME_IN) endmacro() -# # @MACRO: tribits_package_def() # # Macro called in `/CMakeLists.txt`_ after subpackages are @@ -343,7 +339,6 @@ macro(tribits_package_def) endmacro() -# # @MACRO: tribits_package() # # Macro called at the very beginning of a package's top-level @@ -397,7 +392,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 +465,6 @@ endmacro() # -# # @MACRO: tribits_add_debug_option() # # Add the standard cache variable option ``${PACKAGE_NAME}_ENABLE_DEBUG`` for @@ -505,7 +498,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 +543,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 +610,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) @@ -694,7 +683,6 @@ function(tribits_package_finalize_dependency_vars) endfunction() -# # Helper macro for [SUB]tribits_package_postprocess() # macro(tribits_package_postprocess_common) @@ -706,12 +694,11 @@ macro(tribits_package_postprocess_common) 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 +708,60 @@ 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) + get_target_property(isTestOnlyLib ${libTarget} TRIBITS_TESTONLY_LIB) + #print_var(isTestOnlyLib) + if (NOT isTestOnlyLib) + list(APPEND packageLibsInAllLibsList ${libTarget}) + endif() + endforeach() + #print_var(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) + + # 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,6 +772,10 @@ endmacro() # # tribits_package_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 this macro must be called in a packages's # top-level ``CMakeLists.txt`` file but limitations of the CMake language make # it necessary to do so. @@ -828,7 +872,6 @@ macro(tribits_package_postprocess) endmacro() -# # @MACRO: tribits_process_subpackages() # # Macro that processes the `TriBITS Subpackages`_ for a parent `TriBITS diff --git a/cmake/tribits/core/package_arch/TribitsProcessEnabledTpl.cmake b/cmake/tribits/core/package_arch/TribitsProcessEnabledTpl.cmake index dd4eece4a5cf..ee5d6759834b 100644 --- a/cmake/tribits/core/package_arch/TribitsProcessEnabledTpl.cmake +++ b/cmake/tribits/core/package_arch/TribitsProcessEnabledTpl.cmake @@ -57,13 +57,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 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 1cbc9e8bb74d..ad270c9d7aed 100644 --- a/cmake/tribits/core/package_arch/TribitsSubPackageMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsSubPackageMacros.cmake @@ -142,6 +142,10 @@ endmacro() # # 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..11e1643c6ca0 100644 --- a/cmake/tribits/core/package_arch/TribitsSystemDataStructuresMacrosFunctions.rst +++ b/cmake/tribits/core/package_arch/TribitsSystemDataStructuresMacrosFunctions.rst @@ -318,8 +318,7 @@ a given package's capabilities: 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. + is also used to list out in ${PACKAGE_NAME}Config.cmake files. ToDo: Look to eliminate this variable and just add it to the package's library targets with target_include_directories(). @@ -332,8 +331,8 @@ a given package's capabilities: 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. + library directories is used when creating ${PACKAGE_NAME}Config.cmake + files. ``${PACKAGE_NAME}_LIBRARIES`` @@ -359,13 +358,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`` diff --git a/cmake/tribits/core/package_arch/TribitsTplFindIncludeDirsAndLibraries.cmake b/cmake/tribits/core/package_arch/TribitsTplFindIncludeDirsAndLibraries.cmake index dfcedc290a7a..b5db1ef454c5 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 @@ -146,7 +144,6 @@ 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 @@ -680,10 +677,19 @@ function(tribits_tpl_find_include_dirs_and_libraries TPL_NAME) global_set(TPL_${TPL_NAME}_NOT_FOUND FALSE) endif() + set(buildDirCMakePkgsDir + "${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_CMAKE_PKGS_DIR}") + set(tplConfigFile + "${buildDirCMakePkgsDir}/${TPL_NAME}/${TPL_NAME}Config.cmake") + tribits_external_package_write_config_file(${TPL_NAME} "${tplConfigFile}") + if (NOT ${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING) + include("${tplConfigFile}") + endif() + tribits_external_package_install_config_file(${TPL_NAME} "${tplConfigFile}") + endfunction() -# # @FUNCTION: tribits_tpl_tentatively_enable() # # Function that sets up for an optionally enabled TPL that is attempted to be @@ -728,10 +734,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/TribitsWriteClientExportFiles.cmake b/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake index 537ff85e9558..8405209c1ade 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 `` -# -# 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! -# -# ``WRITE_EXPORT_MAKEFILE `` -# -# 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! -# -# ``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. +# ``PACKAGE_CONFIG_FOR_BUILD_BASE_DIR `` # -# ``WRITE_INSTALL_EXPORT_MAKEFILE`` +# 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. # -# 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. +# ``PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR `` # -# 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. +# If specified, then the package's ``Config_install.cmake`` +# file and supporting files will be written under the directory +# ``/`` (and any subdirs that does exist +# will be created). The file ``${PACKAGE_NAME}Config_install.cmake`` is +# meant to be installed renamed as ``Config.cmake`` in the +# install tree and it points to installed include directories and +# libraries. # -# NOTE: This function does *not* contain 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 @@ -393,26 +340,50 @@ 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}) + # - # 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}) + +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() +# +# 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) + + set(BUILD_DIR_CMAKE_PKGS_DIR + "${${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(${packageName} + CONFIG_FILE_BASE_DIR "${BUILD_DIR_CMAKE_PKGS_DIR}" + CONFIG_FILE_STR_INOUT PACKAGE_CONFIG_CODE ) # Import build tree targets into applications. # @@ -423,13 +394,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 +410,36 @@ include(\"${${PROJECT_NAME}_BINARY_DIR}/${PROJECT_NAME}Targets.cmake\")" # Replace " by \". string(REGEX REPLACE "\"" "\\\\\"" CMAKE_CXX_FLAGS_ESCAPED ${CMAKE_CXX_FLAGS}) endif() + set(tribitsConfigFilesDir + "${${PROJECT_NAME}_TRIBITS_DIR}/${TRIBITS_CMAKE_INSTALLATION_FILES_DIR}") 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. - # - - if(PARSE_WRITE_EXPORT_MAKEFILE) - - 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) - - 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("${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) - - assert_defined(${PROJECT_NAME}_TRIBITS_DIR) - configure_file( - ${${PROJECT_NAME}_TRIBITS_DIR}/${TRIBITS_CMAKE_INSTALLATION_FILES_DIR}/TribitsPackageConfigTemplate.export.in - "${PARSE_WRITE_EXPORT_MAKEFILE}" + "${tribitsConfigFilesDir}/TribitsPackageConfigTemplate.cmake.in" + "${PARSE_PACKAGE_CONFIG_FOR_BUILD_BASE_DIR}/${packageName}Config.cmake" ) endif() - # - # H) Create the cmake Config.cmake file for the install tree. - # +endfunction() - # 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. - # 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() +# +# 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() +# +# 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) # Set the include and library directories relative to the location # at which the ${PROJECT_NAME}Config.cmake file is going to be @@ -501,9 +449,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 +460,227 @@ 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}") + 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(${packageName} + 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) - + 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() - # - # I) Write the export makefile for the install tree - # +endfunction() - if (PARSE_WRITE_INSTALL_EXPORT_MAKEFILE) - # 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}) +# @FUNCTION: tribits_append_dependent_package_config_file_includes() +# +# Append the includes for upstream internal packages and external packages +# (TPLs) to a `Config.cmake` file string. +# +# Usage:: +# +# tribits_append_dependent_package_config_file_includes( +# +# CONFIG_FILE_BASE_DIR +# CONFIG_FILE_STR_INOUT +# ) +# +function(tribits_append_dependent_package_config_file_includes packageName) - 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) + # Parse input - 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() + cmake_parse_arguments( + PARSE #prefix + "" #options + "CONFIG_FILE_BASE_DIR;CONFIG_FILE_STR_INOUT" #one_value_keywords + "" #multi_value_keywords + ${ARGN} + ) + tribits_check_for_unparsed_arguments() + + set(configFileBaseDir "${PARSE_CONFIG_FILE_BASE_DIR}") + set(configFileStr "${${PARSE_CONFIG_FILE_STR_INOUT}}") + + # Include configurations of dependent packages + string(APPEND configFileStr + "# Include configuration of dependent packages\n") + foreach(depPkg IN LISTS ${packageName}_FULL_ENABLED_DEP_PACKAGES) + set(cmakePkgDir "${configFileBaseDir}/${depPkg}") + string(APPEND configFileStr + "include(\"${cmakePkgDir}/${depPkg}Config.cmake\")\n") + endforeach() + + # Include configurations of dependent external packages/TPLs + string(APPEND configFileStr + "\n# Include configuration of dependent external packages/TPls\n") + foreach(depTpl IN LISTS ${packageName}_LIB_REQUIRED_DEP_TPLS) + if (TARGET ${depTpl}::all_libs) + set(cmakeTplDir "${configFileBaseDir}/${depTpl}") + string(APPEND configFileStr + "include(\"${cmakeTplDir}/${depTpl}Config.cmake\")\n") + endif() + endforeach() + foreach(depTpl IN LISTS ${packageName}_LIB_OPTIONAL_DEP_TPLS) + if (${packageName}_ENABLE_${depTpl} AND TARGET ${depTpl}::all_libs) + set(cmakeTplDir "${configFileBaseDir}/${depTpl}") + string(APPEND configFileStr + "include(\"${cmakeTplDir}/${depTpl}Config.cmake\")\n") + endif() + endforeach() + # NOTE: Above, every TPL does not have a Config.cmake file written + # for it. For example, special TPLs like "MPI" don't have this file created + # or have an MPI::all_libs target corrected. Therefore, we check for the + # defintion ::all_libs before we include the file above. + + # 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(BUILD_DIR_CMAKE_PKGS_DIR + "${${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 + "${BUILD_DIR_CMAKE_PKGS_DIR}/${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. @@ -736,19 +741,23 @@ function(tribits_write_project_client_export_files) 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 + # 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 +803,11 @@ 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}") 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 +835,35 @@ 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}") + 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}) - 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 + set(SHARED_LIB_RPATH_COMMAND + "${CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG}${CMAKE_INSTALL_PREFIX}/${${PROJECT_NAME}_INSTALL_LIB_DIR}" ) endif() - 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. - ###### + if (${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES) - # 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}) + tribits_set_compiler_vars_for_config_file(INSTALL_DIR) - 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) + # Custom code in configuration file. + set(PROJECT_CONFIG_CODE "") 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 +880,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/utils/AppendStringVar.cmake b/cmake/tribits/core/utils/AppendStringVar.cmake index 63d5cc7b4a7f..5735e56cdcb4 100644 --- a/cmake/tribits/core/utils/AppendStringVar.cmake +++ b/cmake/tribits/core/utils/AppendStringVar.cmake @@ -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} ) diff --git a/cmake/tribits/core/utils/DriveAdvancedTest.cmake b/cmake/tribits/core/utils/DriveAdvancedTest.cmake index 1950cac801b1..628b4ed574c5 100644 --- a/cmake/tribits/core/utils/DriveAdvancedTest.cmake +++ b/cmake/tribits/core/utils/DriveAdvancedTest.cmake @@ -387,7 +387,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/MessageWrapper.cmake b/cmake/tribits/core/utils/MessageWrapper.cmake index 59b17d13a15c..cf7a0723de18 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 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/TribitsGatherBuildTargets.cmake b/cmake/tribits/core/utils/TribitsGatherBuildTargets.cmake new file mode 100644 index 000000000000..021e11b3fabb --- /dev/null +++ b/cmake/tribits/core/utils/TribitsGatherBuildTargets.cmake @@ -0,0 +1,120 @@ +# @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 + ) + + #message("\ntribits_filter_only_build_targets:\n") + #print_var(targetListInVar) + #print_var(targetTypesList) + #print_var(targetListInVar) + #print_var(${targetListInVar}) + + set(targetListOut "") + + foreach (target IN LISTS ${targetListInVar}) + #message("") + #print_var(target) + get_property(targetType TARGET ${target} PROPERTY TYPE) + set(matchedDesiredTargetType FALSE) + #print_var(targetType) + foreach (desiredTargetType IN ITEMS ${targetTypesList}) + #print_var(desiredTargetType) + if (desiredTargetType STREQUAL targetType) + #message("-- " "${target} is a filtered-for build target!") + list(APPEND targetListOut ${target}) + set(matchedDesiredTargetType TRUE) + break() + endif() + endforeach() + #if (NOT matchedDesiredTargetType) + # message("-- " "${target} is **NOT** a filtered-for build target!") + #endif() + endforeach() + + set(${targetListOutVar} ${targetListOut} PARENT_SCOPE) + +endfunction() diff --git a/cmake/tribits/core/utils/UnitTestHelpers.cmake b/cmake/tribits/core/utils/UnitTestHelpers.cmake index 183d3d949f5b..ce163a35ca73 100644 --- a/cmake/tribits/core/utils/UnitTestHelpers.cmake +++ b/cmake/tribits/core/utils/UnitTestHelpers.cmake @@ -41,7 +41,22 @@ include(CMakeParseArguments) include(GlobalSet) +# @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,7 +98,102 @@ function(unittest_compare_const VAR_NAME CONST_VAL) 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) + + # Don't ignore empty elements in list() operations (they are very important + # here) + cmake_policy(PUSH) + cmake_policy(SET CMP0007 NEW) + + 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() + + cmake_policy(POP) + +endfunction() + + # @FUNCTION: unittest_string_regex() # # Perform a series regexes of given strings and update overall test statistics. @@ -140,7 +250,6 @@ function(unittest_string_regex INPUT_STRING) endfunction() -# # @FUNCTION: unittest_has_substr_const() # # Check that a given string var contains the given substring and update @@ -187,7 +296,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 +342,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 +363,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/TribitsCTestDriverCore.cmake b/cmake/tribits/ctest_driver/TribitsCTestDriverCore.cmake index 7449d172386d..e02d292c44df 100644 --- a/cmake/tribits/ctest_driver/TribitsCTestDriverCore.cmake +++ b/cmake/tribits/ctest_driver/TribitsCTestDriverCore.cmake @@ -325,7 +325,7 @@ include(TribitsCTestDriverCoreHelpers) # * `Specifying where the results go to 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())`_ diff --git a/cmake/tribits/ctest_driver/TribitsCTestDriverCoreHelpers.cmake b/cmake/tribits/ctest_driver/TribitsCTestDriverCoreHelpers.cmake index 350652e60164..ed329adf1b30 100644 --- a/cmake/tribits/ctest_driver/TribitsCTestDriverCoreHelpers.cmake +++ b/cmake/tribits/ctest_driver/TribitsCTestDriverCoreHelpers.cmake @@ -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}) diff --git a/cmake/tribits/doc/build_ref/TribitsBuildReferenceBody.rst b/cmake/tribits/doc/build_ref/TribitsBuildReferenceBody.rst index 6ee997bcf51f..9e0d74edd154 100644 --- a/cmake/tribits/doc/build_ref/TribitsBuildReferenceBody.rst +++ b/cmake/tribits/doc/build_ref/TribitsBuildReferenceBody.rst @@ -1484,13 +1484,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 @@ -1525,6 +1526,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:: @@ -1535,7 +1549,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:: @@ -1546,14 +1560,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 @@ -1621,7 +1635,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 @@ -2559,15 +2573,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:: @@ -3268,6 +3273,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 @@ -3640,6 +3647,103 @@ 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, 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. + + Installation Testing ==================== @@ -3651,7 +3755,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] \ @@ -3991,4 +4095,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/TribitsCoreDetailedReference.rst b/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst index eee58675ddc2..092ccb1abfb9 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`_ @@ -354,23 +353,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: @@ -455,13 +437,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:: diff --git a/cmake/tribits/doc/guides/TribitsMacroFunctionDocTemplate.rst b/cmake/tribits/doc/guides/TribitsMacroFunctionDocTemplate.rst index ab28bea04913..973a290746e0 100644 --- a/cmake/tribits/doc/guides/TribitsMacroFunctionDocTemplate.rst +++ b/cmake/tribits/doc/guides/TribitsMacroFunctionDocTemplate.rst @@ -43,5 +43,5 @@ @FUNCTION: tribits_tpl_allow_pre_find_package() + @FUNCTION: tribits_tpl_find_include_dirs_and_libraries() + @FUNCTION: tribits_tpl_tentatively_enable() + -@FUNCTION: tribits_verbose_print_var() + @FUNCTION: tribits_write_flexible_package_client_export_files() + +@FUNCTION: tribits_verbose_print_var() + diff --git a/cmake/tribits/doc/guides/TribitsSystemMacroFunctionDocTemplate.rst b/cmake/tribits/doc/guides/TribitsSystemMacroFunctionDocTemplate.rst index 0b20282c604d..bc2dc7b51b62 100644 --- a/cmake/tribits/doc/guides/TribitsSystemMacroFunctionDocTemplate.rst +++ b/cmake/tribits/doc/guides/TribitsSystemMacroFunctionDocTemplate.rst @@ -35,5 +35,6 @@ understand the internals of TriBITS. @MACRO: tribits_read_deps_files_create_deps_graph() + @MACRO: tribits_save_off_dependency_vars() + @FUNCTION: tribits_set_dep_packages() + +@FUNCTION: tribits_write_package_client_export_files_install_targets() + @MACRO: tribits_write_xml_dependency_files() + @FUNCTION: tribits_write_xml_dependency_files_if_supported() + diff --git a/cmake/tribits/doc/tutorial/src/TribitsTutorial_HelloWorld.rst b/cmake/tribits/doc/tutorial/src/TribitsTutorial_HelloWorld.rst index 86e33c473bbb..885c3b4faa56 100644 --- a/cmake/tribits/doc/tutorial/src/TribitsTutorial_HelloWorld.rst +++ b/cmake/tribits/doc/tutorial/src/TribitsTutorial_HelloWorld.rst @@ -425,8 +425,6 @@ project with contents:: |__ bin | |__ Hello-Executable-Name.exe |__ include - | |__ Makefile.export.HelloPackage - | |__ Makefile.export.TribitsGreetings | |__ hello_world_lib.hpp |__ lib |__ cmake diff --git a/cmake/tribits/examples/InsertedPkg/test/CMakeLists.txt b/cmake/tribits/examples/InsertedPkg/test/CMakeLists.txt index 7c06baf41ba7..72c47562180f 100644 --- a/cmake/tribits/examples/InsertedPkg/test/CMakeLists.txt +++ b/cmake/tribits/examples/InsertedPkg/test/CMakeLists.txt @@ -2,5 +2,5 @@ tribits_add_executable_and_test( test SOURCES InsertedPkg_test.cpp NUM_MPI_PROCS 1 PASS_REGULAR_EXPRESSION - "InsertedPkg deps are: no_deps" + "InsertedPkg deps are: headeronlytpl" ) diff --git a/cmake/tribits/examples/TribitsExampleApp/AppHelperFuncs.cmake b/cmake/tribits/examples/TribitsExampleApp/AppHelperFuncs.cmake new file mode 100644 index 000000000000..3ed976e7c654 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleApp/AppHelperFuncs.cmake @@ -0,0 +1,171 @@ +include(CMakePrintHelpers) + + +# Find TribitsExProj package(s), load compilers and compiler options, and get +# CMake lib targets (which have include dirs also) to link against. +# +# On return, sets the vars in the current scope: +# +# * TribitsExProj_SELECTED_PACKAGE_LIST: List of all of the packages pulled in +# * from the TribtsExProj. +# +# * APP_DEPS_LIB_TARGETS: List of all of the IMPORTED CMake targets that 'app' +# must link against +# +# * CMAKE__COMPILER and CMAKE__FLAGS pulled in from the +# TribitsExProjConfig.config or a Config.cmake file +# +macro(getTribitsExProjStuffForApp) + + set(${PROJECT_NAME}_FIND_INDIVIDUAL_PACKAGES OFF CACHE BOOL + "Set to TRUE to find individual packages and OFF to find project TribitsExProj") + + if (${PROJECT_NAME}_FIND_INDIVIDUAL_PACKAGES) + getTribitsExProjStuffForAppByPackage() + else() + getTribitsExProjStuffForAppByProject() + endif() + +endmacro() + + +# Get TribitsExProj stuff with find_package() for each +# package/component independently. +# +macro(getTribitsExProjStuffForAppByPackage) + + # Find each package and gather up all the ::all_libs targets + set(APP_DEPS_LIB_TARGETS "") + foreach (packageName IN LISTS ${PROJECT_NAME}_USE_COMPONENTS) + find_package(${packageName} REQUIRED) + message("Found ${packageName}!") + list(APPEND APP_DEPS_LIB_TARGETS ${packageName}::all_libs) + endforeach() + print_var(APP_DEPS_LIB_TARGETS) + + # Set TribitsExProj_SELECTED_PACKAGE_LIST + set(TribitsExProj_SELECTED_PACKAGE_LIST ${${PROJECT_NAME}_USE_COMPONENTS}) + # NOTE: We are setting his here since TribitsExProjConfig.cmake is not being + # read in in this case. + + # Get compilers from first package listed + list(GET ${PROJECT_NAME}_USE_COMPONENTS 0 firstPkg) + setCompilersForAppFromConfigFileCompilers(${firstPkg}) + +endmacro() + + +# Get TribitsExProj stuff from find_package(TribitsExProj) +# +macro(getTribitsExProjStuffForAppByProject) + + find_package(TribitsExProj REQUIRED COMPONENTS ${${PROJECT_NAME}_USE_COMPONENTS}) + + message("\nFound TribitsExProj! Here are the details: ") + message(" TribitsExProj_DIR = ${TribitsExProj_DIR}") + message(" TribitsExProj_VERSION = ${TribitsExProj_VERSION}") + message(" TribitsExProj_PACKAGE_LIST = ${TribitsExProj_PACKAGE_LIST}") + message(" TribitsExProj_TPL_LIST = ${TribitsExProj_TPL_LIST}") + message(" TribitsExProj_BUILD_SHARED_LIBS = ${TribitsExProj_BUILD_SHARED_LIBS}") + message("End of TribitsExProj details\n") + + # Make sure to use same compilers and flags as TribitsExProj + setCompilersForAppFromConfigFileCompilers(TribitsExProj) + + # Get the libraries for building and linking + if (${PROJECT_NAME}_USE_COMPONENTS) + set(APP_DEPS_LIB_TARGETS TribitsExProj::all_selected_libs) + else() + set(APP_DEPS_LIB_TARGETS TribitsExProj::all_libs) + endif() + +endmacro() + + +# Get compilers and compiler flags from the imported +# ``TribitsExProjConfig.cmake`` or ``Config.cmake`` file. +# +# Here ``prefix`` is the prefix for the variables read in from the +# *Config.cmake file. +# +macro(setCompilersForAppFromConfigFileCompilers prefix) + + message("-- Setting compilers and flags read in from '${prefix}Config.cmake' file:") + + set(CMAKE_CXX_COMPILER ${${prefix}_CXX_COMPILER} ) + set(CMAKE_C_COMPILER ${${prefix}_C_COMPILER} ) + set(CMAKE_Fortran_COMPILER ${${prefix}_Fortran_COMPILER} ) + + set(CMAKE_CXX_FLAGS "${${prefix}_CXX_COMPILER_FLAGS} ${CMAKE_CXX_FLAGS}") + set(CMAKE_C_FLAGS "${${prefix}_C_COMPILER_FLAGS} ${CMAKE_C_FLAGS}") + set(CMAKE_Fortran_FLAGS "${${prefix}_Fortran_COMPILER_FLAGS} ${CMAKE_Fortran_FLAGS}") + + cmake_print_variables(CMAKE_CXX_COMPILER) + cmake_print_variables(CMAKE_C_COMPILER) + cmake_print_variables(CMAKE_Fortran_COMPILER) + cmake_print_variables(CMAKE_CXX_FLAGS) + cmake_print_variables(CMAKE_C_FLAGS) + cmake_print_variables(CMAKE_Fortran_FLAGS) + +endmacro() + + +# Add compiler defines to the ``app`` target for optionally supported packages +# from upstream TribitExProj +# +function(addAppDepCompileDefines) + addAppDepCompileDefine("SimpleCxx") + addAppDepCompileDefine("MixedLang") + addAppDepCompileDefine("WithSubpackages") +endfunction() + + +function(addAppDepCompileDefine componentName) + if (${componentName} IN_LIST TribitsExProj_SELECTED_PACKAGE_LIST) + string(TOUPPER "${componentName}" componentNameUpper) + target_compile_definitions(app PRIVATE TRIBITSEXAPP_HAVE_${componentNameUpper}) + endif() +endfunction() + + +# Return the extended dependency string from the app at runtime given the +# enabled packages from TribitsExProj. +# +function(getExpectedAppDepsStr expectedDepsStrOut) + + if ("SimpleTpl" IN_LIST SimpleCxx_TPL_LIST) + set(simpleCxxDeps "simpletpl ") + else() + set(simpleCxxDeps "") + endif() + set(simpleCxxDeps "${simpleCxxDeps}headeronlytpl") + + set(depsStr "") + appendExpectedAppDepsStr("WithSubpackages" + "WithSubpackages:B A ${simpleCxxDeps} ${simpleCxxDeps}" + depsStr) + appendExpectedAppDepsStr("MixedLang" "MixedLang:Mixed Language" depsStr) + appendExpectedAppDepsStr("SimpleCxx" "SimpleCxx:${simpleCxxDeps}" depsStr) + + set(${expectedDepsStrOut} "${depsStr}" PARENT_SCOPE) + +endfunction() + + +function(appendExpectedAppDepsStr componentName str depsStrOut) + set(depsStr "${${depsStrOut}}") # Should be value of var in parent scope! + #message("-- depsStr (inner) = '${depsStr}'") + if (${componentName} IN_LIST TribitsExProj_SELECTED_PACKAGE_LIST) + if (depsStr) + set(depsStr "${depsStr}[;] ${str}") + else() + set(depsStr "${str}") + endif() + endif() + set(${depsStrOut} "${depsStr}" PARENT_SCOPE) +endfunction() + + +function(print_var varName) + message("-- ${varName} = '${${varName}}'") +endfunction() diff --git a/cmake/tribits/examples/TribitsExampleApp/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleApp/CMakeLists.txt new file mode 100644 index 000000000000..4de561d8acbb --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleApp/CMakeLists.txt @@ -0,0 +1,41 @@ +cmake_minimum_required(VERSION 3.17.1) + +project(TribitsExApp + DESCRIPTION + "Example raw CMake project using packages installed from TribitsExampleProject" + VERSION 0.0.0 + LANGUAGES NONE # Defined below after reading in compilers + ) + +set(${PROJECT_NAME}_USE_COMPONENTS "" CACHE STRING + "Components/Packages to use from TribitsExampleProject: ,,..." ) +string(REPLACE "," ";" ${PROJECT_NAME}_USE_COMPONENTS + "${${PROJECT_NAME}_USE_COMPONENTS}") + +list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") +include(AppHelperFuncs) + +getTribitsExProjStuffForApp() + +# Enable the compilers now that we have gotten them from the *Config.cmake file +enable_language(C) +enable_language(CXX) +if (CMAKE_Fortran_COMPILER) + enable_language(Fortran) +endif() + +# Build the APP and link to libraries from TribitsExProj packages +add_executable(app app.cpp) +target_link_libraries(app PRIVATE ${APP_DEPS_LIB_TARGETS}) +addAppDepCompileDefines() + +# Set up tests + +enable_testing() + +getExpectedAppDepsStr(expectedDepsStr) + +add_test(app_test app) +set_tests_properties(app_test PROPERTIES + PASS_REGULAR_EXPRESSION "Full Deps: ${expectedDepsStr}" + ) diff --git a/cmake/tribits/examples/TribitsExampleApp/README.md b/cmake/tribits/examples/TribitsExampleApp/README.md new file mode 100644 index 000000000000..e80b7ee8817b --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleApp/README.md @@ -0,0 +1,110 @@ +# TribitsExampleApp + +The example project `TribitsExampleApp` is a raw CMake project that pulls in +libraries from packages from `TribitsExampleProject`. To build against all of +the installed packages from an upstream `TribitsExampleProject`, configure, +build, and run the tests with: + +``` + cmake \ + -DCMAKE_PREFIX_PATH= \ + /TribitsExampleApp + + make + + ctest +``` + +That will call `find_package(TribitsExaProj)` and will set the compilers +pulled in from the found `TribitsExaProjConfig.cmake` file. + + +## Pulling in only a subset of packages + +To configure and build `TribitsExampleApp` against only a subset of the +installed `TribitsExampleProject` packages, configure `TribitsExampleApp` +using, for example: + +``` + cmake \ + -DCMAKE_PREFIX_PATH= \ + -DTribitsExApp_USE_COMPONENTS=SimpleCxx,WithSubpackages \ + /TribitsExampleApp +``` + +Internally, that that will call: + +``` + find_package(TribitsExApp REQUIRED COMPONENTS ${TribitsExApp_USE_COMPONENTS}) +``` + +(where `,` in `TribitsExApp_USE_COMPONENTS` is replaced with `;` internally to +create a proper CMake list internally before calling `find_package()`). + + +## Pulling in only a subset of packages by finding each package individually + +`TribitsExampleApp` is also set up to demonstrate finding the individual +packages using separate calls to `find_package()` by configuring +with, for example: + +``` + cmake \ + -DCMAKE_PREFIX_PATH= \ + -DTribitsExApp_USE_COMPONENTS=SimpleCxx,WithSubpackages \ + -DTribitsExApp_FIND_INDIVIDUAL_PACKAGES=ON \ + /TribitsExampleApp +``` + +That essentially results in calling: + +``` + find_package(SimpleCxx REQUIRED) + find_package(WithSubpackages REQUIRED) + ... + target_link_libraries(app + PRIVATE SimpleCxx::all_libs + PRIVATE WithSubpackages::all_libs + ) +``` + +(but does so with a loop and a list internally obviously). + + +## Pulling in packages from the build tree + +`TribitsExampleApp` is additionally set up to demonstrate finding the +individual packages from the build directory (where `` is +the build directory for `TribitsExampleProject`) instead of the install tree +using separate calls to `find_package()` by configuring with, for +example: + +``` + cmake \ + -DCMAKE_PREFIX_PATH=/cmake_packages \ + -DTribitsExApp_USE_COMPONENTS=SimpleCxx,WithSubpackages \ + -DTribitsExApp_FIND_INDIVIDUAL_PACKAGES=ON \ + /TribitsExampleApp +``` + +This is identical to the case to finding the individual packages under the +install tree except here the packages and libraries are found under the build +tree and the include directories point into the source tree. (There is no +need for an install directory in this case.) This is to simulate more +advanced use cases such as where `TribitsExampleApp` and +`TribitsExampleProject` may be part of a larger super-build that works out of +the build tree without needing to install. + +NOTE: There is no `TribitsExProjConfig.cmake` file generated in the build tree +to find so it is not possible to call `find_package(TribitsExProjConfig)` +pointing into the build tree. + + +## Tests demonstrating usage of TribitsExampleApp + +The TriBITS project contains automated tests that run the various use cases +described above and check their result. These tests are shown defined +[here](https://github.com/TriBITSPub/TriBITS/blob/master/test/core/ExamplesUnitTests/TribitsExampleApp_Tests.cmake) +and are run locally with CTest and are submitted to +[CDash](https://github.com/TriBITSPub/TriBITS/wiki/TriBITS-CDash-Dashboard) as +part of regular testing. diff --git a/cmake/tribits/examples/TribitsExampleApp/app.cpp b/cmake/tribits/examples/TribitsExampleApp/app.cpp new file mode 100644 index 000000000000..0b80b645af1a --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleApp/app.cpp @@ -0,0 +1,46 @@ +#ifdef TRIBITSEXAPP_HAVE_SIMPLECXX +# include "SimpleCxx_HelloWorld.hpp" +#endif +#ifdef TRIBITSEXAPP_HAVE_MIXEDLANG +# include "MixedLang.hpp" +#endif +#ifdef TRIBITSEXAPP_HAVE_WITHSUBPACKAGES +# include "wsp_c/C.hpp" +#endif + + +#include +#include + + +void appendDepsStr(std::string &depsStr, const std::string &str) +{ + if (depsStr.length()) { + depsStr += "; "+str; + } + else { + depsStr = str; + } +} + + +int main(int argc, char *argv[]) { + // Get deps down the deps graph + std::string depsStr; +#ifdef TRIBITSEXAPP_HAVE_WITHSUBPACKAGES + appendDepsStr(depsStr, "WithSubpackages:"+WithSubpackages::depsC()); +#endif +#ifdef TRIBITSEXAPP_HAVE_MIXEDLANG + appendDepsStr(depsStr, "MixedLang:"+tribits_mixed::mixedLang()); +#endif +#ifdef TRIBITSEXAPP_HAVE_SIMPLECXX + appendDepsStr(depsStr, "SimpleCxx:"+SimpleCxx::deps()); +#endif + // NOTE: The above all call functions from the libraries and requires that + // both the header files be found at compile time and the libraries be found + // at link time and runtime for this these function calls to work. + + std::cout << "Full Deps: " << depsStr << "\n"; + + return 0; +} diff --git a/cmake/tribits/examples/TribitsExampleProject/ProjectName.cmake b/cmake/tribits/examples/TribitsExampleProject/ProjectName.cmake index 0b64b67bd416..3333b577c231 100644 --- a/cmake/tribits/examples/TribitsExampleProject/ProjectName.cmake +++ b/cmake/tribits/examples/TribitsExampleProject/ProjectName.cmake @@ -4,6 +4,5 @@ set(PROJECT_NAME TribitsExProj) # Turn on export dependency generation for WrapExteranl package set(${PROJECT_NAME}_GENERATE_EXPORT_FILE_DEPENDENCIES_DEFAULT ON) -# Turn on by default the gneration of the export files +# Turn on by default the generation of the export files set(${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES_DEFAULT ON) -set(${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES_DEFAULT ON) diff --git a/cmake/tribits/examples/TribitsExampleProject/cmake/CallbackSetupExtraOptions.cmake b/cmake/tribits/examples/TribitsExampleProject/cmake/CallbackSetupExtraOptions.cmake index 65494bec8d59..7a66eb1f9969 100644 --- a/cmake/tribits/examples/TribitsExampleProject/cmake/CallbackSetupExtraOptions.cmake +++ b/cmake/tribits/examples/TribitsExampleProject/cmake/CallbackSetupExtraOptions.cmake @@ -1,14 +1,12 @@ macro(TRIBITS_REPOSITORY_SETUP_EXTRA_OPTIONS) - assert_defined(${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES) assert_defined(${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES) if (${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES) message( "\n***" "\n*** NOTE: Setting ${PROJECT_NAME}_ENABLE_WrapExternal=OFF" - " because ${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES or" - " ${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES is ON!" + " because ${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES='${${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES}'!" "\n***\n" ) set(${PROJECT_NAME}_ENABLE_WrapExternal OFF) diff --git a/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/src/SimpleCxx_HelloWorld.cpp b/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/src/SimpleCxx_HelloWorld.cpp index 68224ef96a76..103038204a53 100644 --- a/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/src/SimpleCxx_HelloWorld.cpp +++ b/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/src/SimpleCxx_HelloWorld.cpp @@ -8,7 +8,12 @@ std::string SimpleCxx::deps() { - return "no_deps"; + std::string deps; +#ifdef HAVE_SIMPLECXX_SIMPLETPL + deps = SimpleTpl::itsme(); +#endif + deps += (deps.length() ? " " : "") + HeaderOnlyTpl::itsme(); + return deps; } diff --git a/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/test/SimpleCxx_HelloWorld_Tests.cpp b/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/test/SimpleCxx_HelloWorld_Tests.cpp index 4f5832c36586..575555ffbe59 100644 --- a/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/test/SimpleCxx_HelloWorld_Tests.cpp +++ b/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/test/SimpleCxx_HelloWorld_Tests.cpp @@ -3,6 +3,7 @@ #include #include #include "SimpleCxx_HelloWorld.hpp" +#include "HeaderOnlyTpl_stuff.hpp" #define TEST_FIND_SUBSTR_IN_STR(SUBSTR, STR) \ @@ -42,6 +43,14 @@ int main() { TEST_FIND_SUBSTR_IN_STR("Cube(3) = 27", oss.str()); #endif + srand(time(NULL)); + std::cout + << "" + << HeaderOnlyTpl::sqr(rand() % 10) // Random number between 1 and 100 + << "\n"; + // NOTE: The above produces a numeric test measurement that change each time + // it calls and produce an interesting numeric plot on CDash. + if (success) { std::cout << "End Result: TEST PASSED\n"; } diff --git a/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/a/tests/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/a/tests/CMakeLists.txt index 56e719565384..6627657c232a 100644 --- a/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/a/tests/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/a/tests/CMakeLists.txt @@ -5,5 +5,5 @@ tribits_add_advanced_test( test_of_a TEST_0 EXEC a_test PASS_REGULAR_EXPRESSION_ALL "A label is: A" - "A deps are: no_deps" + "A deps are: headeronlytpl" ) diff --git a/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/b/tests/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/b/tests/CMakeLists.txt index cf7c3b5592a5..29695d02f28c 100644 --- a/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/b/tests/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/b/tests/CMakeLists.txt @@ -25,12 +25,12 @@ add_subdirectory(testlib) set(EXPECTED_B_DEPS) assert_defined(${PACKAGE_NAME}_ENABLE_WithSubpackagesA) if(${PACKAGE_NAME}_ENABLE_WithSubpackagesA) - set(EXPECTED_B_DEPS "${EXPECTED_B_DEPS} A no_deps") + set(EXPECTED_B_DEPS "${EXPECTED_B_DEPS} A headeronlytpl") endif() if(${PACKAGE_NAME}_ENABLE_InsertedPkg) - set(EXPECTED_B_DEPS "${EXPECTED_B_DEPS} InsertedPkg no_deps") + set(EXPECTED_B_DEPS "${EXPECTED_B_DEPS} InsertedPkg headeronlytpl") endif() -set(EXPECTED_B_DEPS "${EXPECTED_B_DEPS} no_deps") +set(EXPECTED_B_DEPS "${EXPECTED_B_DEPS} headeronlytpl") tribits_add_advanced_test( test_of_b OVERALL_NUM_MPI_PROCS 1 diff --git a/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/c/tests/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/c/tests/CMakeLists.txt index 204ed9b89dbb..724ccc130c13 100644 --- a/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/c/tests/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/c/tests/CMakeLists.txt @@ -1,5 +1,5 @@ if(WithSubpackagesB_ENABLE_InsertedPkg) - set(EXPECTED_EXTERNALPKG_DEPS "InsertedPkg no_deps ") + set(EXPECTED_EXTERNALPKG_DEPS "InsertedPkg headeronlytpl ") endif() tribits_add_test( c_util @@ -8,7 +8,7 @@ tribits_add_test( c_util NAME test_of_c_util NUM_MPI_PROCS 1 PASS_REGULAR_EXPRESSION - "Called c_util: A no_deps ${EXPECTED_EXTERNALPKG_DEPS}no_deps no_deps" + "Called c_util: A headeronlytpl ${EXPECTED_EXTERNALPKG_DEPS}headeronlytpl headeronlytpl" ADDED_TESTS_NAMES_OUT c_util_TEST_NAME ) @@ -59,7 +59,7 @@ if (WithSubpackagesB_ENABLE_MixedLang AND TESTONLYLIBS c_b_mixed_lang NUM_MPI_PROCS 1 PASS_REGULAR_EXPRESSION - "B A no_deps no_deps B Mixed Language" + "B A headeronlytpl headeronlytpl B Mixed Language" ADDED_EXE_TARGET_NAME_OUT test_of_c_b_mixed_lang_TARGET_NAME ADDED_TESTS_NAMES_OUT test_of_c_b_mixed_lang_TEST_NAME ) diff --git a/cmake/tribits/examples/TribitsExampleProject/packages/wrap_external/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject/packages/wrap_external/CMakeLists.txt index f9e6bb031095..68e76a335f04 100644 --- a/cmake/tribits/examples/TribitsExampleProject/packages/wrap_external/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleProject/packages/wrap_external/CMakeLists.txt @@ -62,15 +62,29 @@ endif() # start from scratch. # -# B) Write the export makefile that will be used by the external project +# B) Get the arguments for the configure of exteranl_func # -set(EXPORT_MAKKEFILE "${CMAKE_CURRENT_BINARY_DIR}/Makefile.export.TribExProj") -tribits_write_flexible_package_client_export_files( - PACKAGE_NAME ${PACKAGE_NAME} - EXPORT_FILE_VAR_PREFIX TribitsExProj - WRITE_EXPORT_MAKEFILE "${EXPORT_MAKKEFILE}" +string(TOUPPER "${CMAKE_BUILD_TYPE}" upperBuildType) + +set(includeDirsList + -I ${WithSubpackagesA_SOURCE_DIR} + -I ${SimpleCxx_SOURCE_DIR}/src + -I ${SimpleCxx_BINARY_DIR}/src ) +if (${PACKAGE_NAME}_ENABLE_MixedLang) + list(PREPEND includeDirsList + -I ${MixedLang_SOURCE_DIR}/src + -I ${MixedLang_BINARY_DIR}/src + ) +endif() +list(JOIN includeDirsList " " includeDirs) +# NOTE: TriBITS export Makefile support used to handle the above stuff +# automatically but that is what you give up when moving to modern CMake. + +# +# C) Do configuration of the external project +# set(EXTERNAL_FUNC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_func) set(EXTERNAL_FUNC_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/external_func) @@ -78,15 +92,14 @@ set(EXTERNAL_FUNC_LIB_FILE ${EXTERNAL_FUNC_BINARY_DIR}/libexternal_func.a) file(MAKE_DIRECTORY ${EXTERNAL_FUNC_BINARY_DIR}) -# -# C) Do configuration of the external project -# - execute_process( COMMAND ${PYTHON_EXECUTABLE} ${EXTERNAL_FUNC_SOURCE_DIR}/configure.py - --with-export-makefile=${EXPORT_MAKKEFILE} - --src-dir=${EXTERNAL_FUNC_SOURCE_DIR} - --build-dir=${EXTERNAL_FUNC_BINARY_DIR} + "--cxx=${CMAKE_CXX_COMPILER}" + "--cxx-flags=${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${upperBuildType}}" + "--ar=${CMAKE_AR}" + "--include-dirs=${includeDirs}" + "--src-dir=${EXTERNAL_FUNC_SOURCE_DIR}" + "--build-dir=${EXTERNAL_FUNC_BINARY_DIR}" ) # @@ -147,7 +160,7 @@ if (${PACKAGE_NAME}_ENABLE_TESTS) tribits_add_executable_and_test(run_external_func SOURCES run_external_func.cpp - PASS_REGULAR_EXPRESSION "external_func A no_deps" + PASS_REGULAR_EXPRESSION "external_func A headeronlytpl" NUM_MPI_PROCS 1 ) diff --git a/cmake/tribits/examples/TribitsExampleProject/packages/wrap_external/external_func/configure.py b/cmake/tribits/examples/TribitsExampleProject/packages/wrap_external/external_func/configure.py index 78f45b3e4b6a..9da2e1347217 100755 --- a/cmake/tribits/examples/TribitsExampleProject/packages/wrap_external/external_func/configure.py +++ b/cmake/tribits/examples/TribitsExampleProject/packages/wrap_external/external_func/configure.py @@ -12,9 +12,24 @@ # clp = OptionParser() - + clp.add_option( - "--with-export-makefile", dest="exportMakefile", type="string", + "--cxx", dest="cxx", type="string", + default="" + ) + +clp.add_option( + "--cxx-flags", dest="cxxFlags", type="string", + default="" + ) + +clp.add_option( + "--ar", dest="ar", type="string", + default="" + ) + +clp.add_option( + "--include-dirs", dest="includeDirs", type="string", default="" ) @@ -35,17 +50,14 @@ # generatedMakefile = \ -"include "+options.exportMakefile+"\n" \ -"\n" \ "all: libexternal_func.a\n" \ "\n" \ "external_func.o: "+options.srcDir+"/external_func.hpp "+options.srcDir+"/external_func.cpp\n" \ -"\t$(TribitsExProj_CXX_COMPILER) $(TribitsExProj_CXX_COMPILER_FLAGS) -I. $(TribitsExProj_INCLUDE_DIRS) -o external_func.o -c "+options.srcDir+"/external_func.cpp\n" \ +"\t"+options.cxx+" "+options.cxxFlags+"" \ + " -I. "+options.includeDirs+" -o external_func.o -c "+options.srcDir+"/external_func.cpp\n" \ "\n" \ "libexternal_func.a: external_func.o\n" \ -"\t$(TribitsExProj_AR) cr libexternal_func.a external_func.o\n" \ +"\t"+options.ar+" cr libexternal_func.a external_func.o\n" \ "\n" open(options.buildDir+"/Makefile", 'w').write(generatedMakefile) - - diff --git a/cmake/tribits/examples/TribitsExampleProjectAddons/packages/addon1/tests/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProjectAddons/packages/addon1/tests/CMakeLists.txt index 17587c9b4868..a862c08b3bb6 100644 --- a/cmake/tribits/examples/TribitsExampleProjectAddons/packages/addon1/tests/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleProjectAddons/packages/addon1/tests/CMakeLists.txt @@ -5,5 +5,5 @@ tribits_add_advanced_test( test TEST_0 EXEC test PASS_REGULAR_EXPRESSION_ALL "Addon1 label is: Addon1" - "Addon1 deps are: no_deps" + "Addon1 deps are: headeronlytpl" ) diff --git a/cmake/tribits/examples/TribitsSimpleExampleApp/CMakeLists.txt b/cmake/tribits/examples/TribitsSimpleExampleApp/CMakeLists.txt new file mode 100644 index 000000000000..45285967f003 --- /dev/null +++ b/cmake/tribits/examples/TribitsSimpleExampleApp/CMakeLists.txt @@ -0,0 +1,41 @@ +cmake_minimum_required(VERSION 3.17.1) + +project(TribitsSimpleExApp + DESCRIPTION + "Example raw CMake project using packages installed from TribitsExampleProject" + VERSION 0.0.0 + LANGUAGES NONE # Defined below after reading in compilers + ) + +find_package(TribitsExProj REQUIRED + COMPONENTS SimpleCxx MixedLang WithSubpackages) + +message("Setting compilers and flags read in from 'TribitsExProjConfig.cmake' file:") + +set(CMAKE_CXX_COMPILER ${TribitsExProj_CXX_COMPILER} ) +set(CMAKE_C_COMPILER ${TribitsExProj_C_COMPILER} ) +set(CMAKE_Fortran_COMPILER ${TribitsExProj_Fortran_COMPILER} ) + +set(CMAKE_CXX_FLAGS "${TribitsExProj_CXX_COMPILER_FLAGS} ${CMAKE_CXX_FLAGS}") +set(CMAKE_C_FLAGS "${TribitsExProj_C_COMPILER_FLAGS} ${CMAKE_C_FLAGS}") +set(CMAKE_Fortran_FLAGS "${TribitsExProj_Fortran_COMPILER_FLAGS} ${CMAKE_Fortran_FLAGS}") + +# Enable the compilers now that we have gotten them from TribitsExProjConfig.cmake +enable_language(C) +enable_language(CXX) +if (CMAKE_Fortran_COMPILER) + enable_language(Fortran) +endif() + +# Build the APP and link to libraries from TribitsExProj packages +add_executable(app app.cpp) +target_link_libraries(app PRIVATE TribitsExProj::all_selected_libs) + +# Set up tests + +enable_testing() + +add_test(app_test app) +set_tests_properties(app_test PROPERTIES + PASS_REGULAR_EXPRESSION "Full Deps: WithSubpackages:B A headeronlytpl headeronlytpl; MixedLang:Mixed Language; SimpleCxx:headeronlytpl" + ) diff --git a/cmake/tribits/examples/TribitsSimpleExampleApp/README.md b/cmake/tribits/examples/TribitsSimpleExampleApp/README.md new file mode 100644 index 000000000000..4ad96988dd9b --- /dev/null +++ b/cmake/tribits/examples/TribitsSimpleExampleApp/README.md @@ -0,0 +1,19 @@ +# TribitsSimpleExampleApp + +Simple example project `TribitsSimpleExampleApp` is a raw CMake project that +pulls in libraries from a few packages from `TribitsExampleProject` using just +`find_package(TribitsExProj REQUIRED COMPONENTS ...)`. + +After building and installing TribitsExampleProject under +``, then configure, build, and test +`TribitsSimpleExampleApp` with: + +``` + cmake \ + -DCMAKE_PREFIX_PATH= \ + /TribitsSimpleExampleApp + + make + + ctest +``` diff --git a/cmake/tribits/examples/TribitsSimpleExampleApp/app.cpp b/cmake/tribits/examples/TribitsSimpleExampleApp/app.cpp new file mode 100644 index 000000000000..3c0b31f55cf4 --- /dev/null +++ b/cmake/tribits/examples/TribitsSimpleExampleApp/app.cpp @@ -0,0 +1,33 @@ +#include "SimpleCxx_HelloWorld.hpp" +#include "MixedLang.hpp" +#include "wsp_c/C.hpp" + +#include +#include + + +void appendDepsStr(std::string &depsStr, const std::string &str) +{ + if (depsStr.length()) { + depsStr += "; "+str; + } + else { + depsStr = str; + } +} + + +int main(int argc, char *argv[]) { + // Get deps down the deps graph + std::string depsStr; + appendDepsStr(depsStr, "WithSubpackages:"+WithSubpackages::depsC()); + appendDepsStr(depsStr, "MixedLang:"+tribits_mixed::mixedLang()); + appendDepsStr(depsStr, "SimpleCxx:"+SimpleCxx::deps()); + // NOTE: The above all call functions from the libraries and requires that + // both the header files be found at compile time and the libraries be found + // at link time and runtime for this these function calls to work. + + std::cout << "Full Deps: " << depsStr << "\n"; + + return 0; +} diff --git a/cmake/tribits/examples/tpls/HeaderOnlyTpl/HeaderOnlyTpl_stuff.hpp b/cmake/tribits/examples/tpls/HeaderOnlyTpl/HeaderOnlyTpl_stuff.hpp index 8434c0d1d8eb..630beb8be780 100644 --- a/cmake/tribits/examples/tpls/HeaderOnlyTpl/HeaderOnlyTpl_stuff.hpp +++ b/cmake/tribits/examples/tpls/HeaderOnlyTpl/HeaderOnlyTpl_stuff.hpp @@ -1,6 +1,7 @@ #ifndef HEADER_ONLY_TPL_STUFF_HPP #define HEADER_ONLY_TPL_STUFF_HPP +#include namespace HeaderOnlyTpl { @@ -11,6 +12,12 @@ T sqr(const T &v) return v*v; } +/** \brief . */ +inline std::string itsme() +{ + return "headeronlytpl"; +} + } // namespace HeaderOnlyTpl diff --git a/cmake/tribits/examples/tpls/SimpleTpl/CMakeLists.txt b/cmake/tribits/examples/tpls/SimpleTpl/CMakeLists.txt index 83227be5bb07..b2909c6b096c 100644 --- a/cmake/tribits/examples/tpls/SimpleTpl/CMakeLists.txt +++ b/cmake/tribits/examples/tpls/SimpleTpl/CMakeLists.txt @@ -1,15 +1,31 @@ cmake_minimum_required(VERSION 3.17.0) +project(SimpleTpl + DESCRIPTION + "Simple TPL with a header file and a library" + LANGUAGES C CXX + ) + add_library(simpletpl SimpleTpl.hpp SimpleTpl.cpp) +target_include_directories(simpletpl + PUBLIC $ + ) + +include(GNUInstallDirs) install( TARGETS simpletpl - RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" - LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" - ARCHIVE DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" + EXPORT SimpleTpl + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) install( FILES SimpleTpl.hpp - DESTINATION "${CMAKE_INSTALL_PREFIX}/include" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + ) + +install(EXPORT SimpleTpl + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/SimpleTpl + NAMESPACE SimpleTpl:: + FILE SimplTplConfig.cmake ) diff --git a/cmake/tribits/examples/tpls/SimpleTpl/SimpleTpl.cpp b/cmake/tribits/examples/tpls/SimpleTpl/SimpleTpl.cpp index 0fc41970ffcb..646471fe9e40 100644 --- a/cmake/tribits/examples/tpls/SimpleTpl/SimpleTpl.cpp +++ b/cmake/tribits/examples/tpls/SimpleTpl/SimpleTpl.cpp @@ -4,3 +4,8 @@ double SimpleTpl::cube(const double &v) { return v*v*v; } + +std::string SimpleTpl::itsme() +{ + return "simpletpl"; +} diff --git a/cmake/tribits/examples/tpls/SimpleTpl/SimpleTpl.hpp b/cmake/tribits/examples/tpls/SimpleTpl/SimpleTpl.hpp index 83cf1242f02e..e922f5f386b2 100644 --- a/cmake/tribits/examples/tpls/SimpleTpl/SimpleTpl.hpp +++ b/cmake/tribits/examples/tpls/SimpleTpl/SimpleTpl.hpp @@ -1,11 +1,16 @@ #ifndef SIMPLE_TPL_HPP #define SIMPLE_TPL_HPP +#include + namespace SimpleTpl { /** \brief . */ double cube(const double &v); +/** \brief . */ +std::string itsme(); + } // namespace SimpleTpl #endif // SIMPLE_TPL_HPP From 157f4806af2c9a958a1f3972975082e7f6e9aef1 Mon Sep 17 00:00:00 2001 From: "Roscoe A. Bartlett" Date: Wed, 3 Nov 2021 10:15:31 -0600 Subject: [PATCH 3/4] Automatic snapshot commit from tribits at f8f2df0 Origin repo remote tracking branch: 'github/master' Origin repo remote repo URL: 'github = git@github.com:TriBITSPub/TriBITS.git' At commit: commit f8f2df0b5d884c9c2a1644ebf40cff25e515ff76 Author: Roscoe A. Bartlett Date: Wed Nov 3 09:51:04 2021 -0600 Summary: Create tribits_external_package_process_libraries_list_library_entry(), elim dup (#299) --- ...ribitsExternalPackageWriteConfigFile.cmake | 166 ++++++++++-------- 1 file changed, 92 insertions(+), 74 deletions(-) diff --git a/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake b/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake index 492a3b5fb464..554984ec1fc7 100644 --- a/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake +++ b/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake @@ -37,7 +37,6 @@ # ************************************************************************ # @HEADER - include(TribitsGeneralMacros) include(MessageWrapper) @@ -223,17 +222,14 @@ function(tribits_external_package_process_libraries_list tplName) foreach (libentry IN LISTS reverseLibraries) #print_var(libentry) tribits_tpl_libraries_entry_type(${libentry} libEntryType) - if (libEntryType STREQUAL "FULL_LIB_PATH") - tribits_external_package_process_libraries_list_full_lib_path( - ${tplName} "${libentry}" libTargets lastLib configFileStr ) - elseif (libEntryType STREQUAL "LIB_NAME_LINK_OPTION") - tribits_external_package_process_libraries_list_lib_name_link_option( - ${tplName} "${libentry}" libTargets lastLib configFileStr ) + 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}") else() - message_wrapper(SEND_ERROR - "ERROR: Can't handle argument '${libentry}' in list TPL_${tplName}_LIBRARIES") + tribits_external_package_process_libraries_list_library_entry( + ${tplName} "${libentry}" ${libEntryType} libTargets lastLib configFileStr ) endif() endforeach() @@ -283,20 +279,92 @@ function(tribits_tpl_libraries_entry_type libentry libEntryTypeOut) endfunction() -# Function to process a full library path lib entry inside of loop over -# TPL__LIBRARIES in the function -# tribits_external_package_process_libraries_list() +# Function to process a library inside of loop over TPL__LIBRARIES +# in the function tribits_external_package_process_libraries_list() # -function(tribits_external_package_process_libraries_list_full_lib_path - tplName libentry libTargetsInOut lastLibInOut configFileStrInOut +function(tribits_external_package_process_libraries_list_library_entry + tplName libentry libEntryType + libTargetsInOut lastLibInOut configFileStrInOut ) + cmake_policy(SET CMP0057 NEW) # Support if ( ... IN_LIST ... ) # Set local vars for inout vars set(libTargets ${${libTargetsInOut}}) set(lastLib ${${lastLibInOut}}) set(configFileStr ${${configFileStrInOut}}) + # Get libname + tribits_external_package_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_external_package_append_add_library_str (${libname} ${prefixed_libname} + ${libEntryType} "${libpath}" configFileStr) + # Set dependency on previous library + if (lastLib) + string(APPEND configFileStr + "target_link_libraries(${prefixed_libname}\n" + " INTERFACE ${tplName}::${lastLib})\n" + ) + endif() + string(APPEND configFileStr + "\n") + # Update for next loop + set(lastLib ${libname}) + list(APPEND libTargets ${prefixed_libname}) + endif() + # Set output vars + set(${libTargetsInOut} ${libTargets} PARENT_SCOPE) + set(${lastLibInOut} ${lastLib} PARENT_SCOPE) + set(${configFileStrInOut} ${configFileStr} PARENT_SCOPE) +endfunction() + + +function(tribits_external_package_get_libname_and_path_from_libentry + libentry libEntryType libnameOut libpathOut + ) + if (libEntryType STREQUAL "FULL_LIB_PATH") + tribits_external_package_get_libname_from_full_lib_path("${libentry}" libname) + set(libpath "${libentry}") + elseif (libEntryType STREQUAL "LIB_NAME_LINK_OPTION") + tribits_external_package_get_libname_from_lib_name_link_option("${libentry}" libname) + 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_external_package_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") + 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_external_package_get_libname_from_full_lib_path full_lib_path + libnameOut + ) # Should be an absolute library path - get_filename_component(full_libname "${libentry}" NAME_WLE) - #print_var(full_libname) + get_filename_component(full_libname "${full_lib_path}" NAME_WLE) # Assert is a valid lib name and get lib name string(LENGTH "${full_libname}" full_libname_len) if (full_libname_len LESS 0) @@ -307,72 +375,22 @@ function(tribits_external_package_process_libraries_list_full_lib_path tribits_print_invalid_lib_name(${tplName} "${full_libname}") endif() string(SUBSTRING "${full_libname}" 3 -1 libname) - #print_var(libname) - # Create IMPORTED library target - string(APPEND configFileStr - "add_library(${tplName}::${libname} IMPORTED UNKNOWN GLOBAL)\n" - "set_target_properties(${tplName}::${libname} PROPERTIES\n" - " IMPORTED_LOCATION \"${libentry}\")\n" - ) - # Set dependency on previous library - if (lastLib) - string(APPEND configFileStr - "target_link_libraries(${tplName}::${libname}\n" - " INTERFACE ${tplName}::${lastLib})\n" - ) - endif() - string(APPEND configFileStr - "\n") - # Update for next loop - set(lastLib ${libname}) - list(APPEND libTargets "${tplName}::${libname}") - # Set output vars - set(${libTargetsInOut} ${libTargets} PARENT_SCOPE) - set(${lastLibInOut} ${lastLib} PARENT_SCOPE) - set(${configFileStrInOut} ${configFileStr} PARENT_SCOPE) + set(${libnameOut} ${libname} PARENT_SCOPE) endfunction() -# Function to process a ``-l`` entry inside of loop over -# TPL__LIBRARIES in the function -# ``tribits_external_package_process_libraries_list()`` -# -function(tribits_external_package_process_libraries_list_lib_name_link_option - tplName libentry libTargetsInOut lastLibInOut configFileStrInOut +function(tribits_external_package_get_libname_from_lib_name_link_option + lib_name_link_option libnameOut ) - # Set local vars for inout vars - set(libTargets ${${libTargetsInOut}}) - set(lastLib ${${lastLibInOut}}) - set(configFileStr ${${configFileStrInOut}}) # Assert begging part '-l' - string(SUBSTRING "${libentry}" 0 2 firstTwoCharsLibEntry) + string(SUBSTRING "${lib_name_link_option}" 0 2 firstTwoCharsLibEntry) if ( ) - tribits_print_invalid_lib_link_option(${tplName} "${libentry}") + tribits_print_invalid_lib_link_option(${tplName} "${lib_name_link_option}") endif() # Get from -l - string(SUBSTRING "${libentry}" 2 -1 libname) - # Create IMPORTED library target - string(APPEND configFileStr - "add_library(${tplName}::${libname} IMPORTED INTERFACE GLOBAL)\n" - "set_target_properties(${tplName}::${libname} PROPERTIES\n" - " IMPORTED_LIBNAME \"${libname}\")\n" - ) - # Set dependency on previous library - if (lastLib) - string(APPEND configFileStr - "target_link_libraries(${tplName}::${libname}\n" - " INTERFACE ${tplName}::${lastLib})\n" - ) - endif() - string(APPEND configFileStr - "\n") - # Update for next loop - set(lastLib ${libname}) - list(APPEND libTargets "${tplName}::${libname}") - # Set output vars - set(${libTargetsInOut} ${libTargets} PARENT_SCOPE) - set(${lastLibInOut} ${lastLib} PARENT_SCOPE) - set(${configFileStrInOut} ${configFileStr} PARENT_SCOPE) + string(SUBSTRING "${lib_name_link_option}" 2 -1 libname) + # Set output + set(${libnameOut} ${libname} PARENT_SCOPE) endfunction() From 5ab3736f0ebbc8a2da3944e768ae359e8fc0284d Mon Sep 17 00:00:00 2001 From: "Roscoe A. Bartlett" Date: Fri, 19 Nov 2021 07:34:10 -0700 Subject: [PATCH 4/4] Automatic snapshot commit from tribits at 1241168 Origin repo remote tracking branch: 'github/master' Origin repo remote repo URL: 'github = git@github.com:TriBITSPub/TriBITS.git' At commit: commit 12411685da4b795fb4b980f7306e4aa441abe563 Author: Roscoe A. Bartlett Date: Thu Nov 18 17:52:30 2021 -0500 Summary: Override _GENERATE_REPO_VERSION_FILE_DEFAULT=OFF if no git (#299) --- cmake/tribits/ReleaseNotes.txt | 14 +- .../TribitsProjectConfigTemplate.cmake.in | 5 +- .../core/package_arch/TribitsConstants.cmake | 2 + ...ribitsExternalPackageWriteConfigFile.cmake | 83 ++++++++- .../package_arch/TribitsGlobalMacros.cmake | 11 +- .../TribitsProcessEnabledTpl.cmake | 28 +++ ...ribitsTplFindIncludeDirsAndLibraries.cmake | 10 +- .../TribitsWriteClientExportFiles.cmake | 34 ++-- .../core/utils/CMakeBuildTypesList.cmake | 3 + .../utils/TribitsGatherBuildTargets.cmake | 16 -- .../TribitsGetImportedLocationProperty.cmake | 62 +++++++ .../build_ref/TribitsBuildReferenceBody.rst | 7 + .../guides/TribitsCoreDetailedReference.rst | 10 ++ .../tribits/doc/guides/TribitsGuidesBody.rst | 109 ++++++++++-- .../examples/TribitsExampleApp/README.md | 6 +- .../TribitsExampleApp2/AppHelperFuncs.cmake | 163 ++++++++++++++++++ .../TribitsExampleApp2/CMakeLists.txt | 41 +++++ .../examples/TribitsExampleApp2/README.md | 110 ++++++++++++ .../examples/TribitsExampleApp2/app.cpp | 34 ++++ .../packages/wrap_external/CMakeLists.txt | 5 +- .../TribitsExampleProject2/CMakeLists.txt | 14 ++ .../TribitsExampleProject2/PackagesList.cmake | 3 + .../TribitsExampleProject2/ProjectName.cmake | 2 + .../TribitsExampleProject2/TPLsList.cmake | 3 + .../TribitsExampleProject2/Version.cmake | 5 + .../cmake/tpls/FindTPLTpl1.cmake | 69 ++++++++ .../packages/package1/CMakeLists.txt | 4 + .../package1/cmake/Dependencies.cmake | 3 + .../packages/package1/src/CMakeLists.txt | 22 +++ .../packages/package1/src/Package1.cpp | 9 + .../packages/package1/src/Package1.hpp | 16 ++ .../packages/package1/src/Package1_Prg.cpp | 9 + .../packages/package1/test/CMakeLists.txt | 6 + .../tribits/examples/tpls/Tpl1/CMakeLists.txt | 31 ++++ cmake/tribits/examples/tpls/Tpl1/Tpl1.cpp | 6 + cmake/tribits/examples/tpls/Tpl1/Tpl1.hpp | 13 ++ 36 files changed, 899 insertions(+), 69 deletions(-) create mode 100644 cmake/tribits/core/utils/TribitsGetImportedLocationProperty.cmake create mode 100644 cmake/tribits/examples/TribitsExampleApp2/AppHelperFuncs.cmake create mode 100644 cmake/tribits/examples/TribitsExampleApp2/CMakeLists.txt create mode 100644 cmake/tribits/examples/TribitsExampleApp2/README.md create mode 100644 cmake/tribits/examples/TribitsExampleApp2/app.cpp create mode 100644 cmake/tribits/examples/TribitsExampleProject2/CMakeLists.txt create mode 100644 cmake/tribits/examples/TribitsExampleProject2/PackagesList.cmake create mode 100644 cmake/tribits/examples/TribitsExampleProject2/ProjectName.cmake create mode 100644 cmake/tribits/examples/TribitsExampleProject2/TPLsList.cmake create mode 100644 cmake/tribits/examples/TribitsExampleProject2/Version.cmake create mode 100644 cmake/tribits/examples/TribitsExampleProject2/cmake/tpls/FindTPLTpl1.cmake create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package1/CMakeLists.txt create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/Dependencies.cmake create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/CMakeLists.txt create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1.cpp create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1.hpp create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1_Prg.cpp create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package1/test/CMakeLists.txt create mode 100644 cmake/tribits/examples/tpls/Tpl1/CMakeLists.txt create mode 100644 cmake/tribits/examples/tpls/Tpl1/Tpl1.cpp create mode 100644 cmake/tribits/examples/tpls/Tpl1/Tpl1.hpp diff --git a/cmake/tribits/ReleaseNotes.txt b/cmake/tribits/ReleaseNotes.txt index 83103a2e4f02..86e4ad4f14c9 100644 --- a/cmake/tribits/ReleaseNotes.txt +++ b/cmake/tribits/ReleaseNotes.txt @@ -2,13 +2,23 @@ Release Notes for TriBITS ---------------------------------------- +2021/11/18: + +(*) MAJOR: 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 Guilde documenation. + +(*) MAJOR: 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: (*) MAJOR: 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 fine these files by simply adding the + `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. @@ -19,7 +29,7 @@ Release Notes for TriBITS 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 inforamtion from TriBITS (see + removing complex dependency tracking information from TriBITS (see TriBITSPub/TriBITS#63 and TriBITSPub/TriBITS#299). 2021/06/17: diff --git a/cmake/tribits/core/installation/TribitsProjectConfigTemplate.cmake.in b/cmake/tribits/core/installation/TribitsProjectConfigTemplate.cmake.in index 0b6b5b50f16a..cdfc2e3fc145 100644 --- a/cmake/tribits/core/installation/TribitsProjectConfigTemplate.cmake.in +++ b/cmake/tribits/core/installation/TribitsProjectConfigTemplate.cmake.in @@ -103,6 +103,7 @@ 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) +set(${PROJECT_NAME}_NOT_FOUND_MESSAGE "") foreach (comp IN ITEMS ${PDOLLAR}{COMPONENTS_LIST}) set( INCLUDE_FILE @@ -121,10 +122,10 @@ foreach (comp IN ITEMS ${PDOLLAR}{COMPONENTS_LIST}) 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}) + string(APPEND ${PROJECT_NAME}_NOT_FOUND_MESSAGE + "ERROR: Could not find component '${PDOLLAR}{comp}'!\n") set(${PROJECT_NAME}_FOUND FALSE) endif() endif() diff --git a/cmake/tribits/core/package_arch/TribitsConstants.cmake b/cmake/tribits/core/package_arch/TribitsConstants.cmake index cb67118da50f..efda842730a2 100644 --- a/cmake/tribits/core/package_arch/TribitsConstants.cmake +++ b/cmake/tribits/core/package_arch/TribitsConstants.cmake @@ -94,6 +94,8 @@ 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 diff --git a/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake b/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake index 554984ec1fc7..69b513e88e3d 100644 --- a/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake +++ b/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake @@ -69,6 +69,46 @@ function(tribits_external_package_write_config_file tplName tplConfigFile) endfunction() +# @FUNCTION: tribits_external_package_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_external_package_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_external_package_install_config_file() # # Install an already-generated ``Config.cmake`` file. @@ -88,7 +128,34 @@ endfunction() function(tribits_external_package_install_config_file tplName tplConfigFile) install( FILES "${tplConfigFile}" - DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}/cmake/${tplName}" + DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}/external_packages/${tplName}" + ) +endfunction() + + +# @FUNCTION: tribits_external_package_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. +# +function(tribits_external_package_install_config_version_file tplName + tplConfigVersionFile + ) + install( + FILES "${tplConfigVersionFile}" + DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}/external_packages/${tplName}" ) endfunction() @@ -370,11 +437,17 @@ function(tribits_external_package_get_libname_from_full_lib_path full_lib_path if (full_libname_len LESS 0) tribits_print_invalid_lib_name(${tplName} "${full_libname}") endif() - string(SUBSTRING "${full_libname}" 0 3 libPart) - if (NOT libPart STREQUAL "lib") - tribits_print_invalid_lib_name(${tplName} "${full_libname}") + if (WIN32) + # Native windows compilers does not prepend library names with 'lib' + set(libname "${full_libname}") + else() + # Every other system prepends the library name with 'lib' + string(SUBSTRING "${full_libname}" 0 3 libPart) + if (NOT libPart STREQUAL "lib") + tribits_print_invalid_lib_name(${tplName} "${full_libname}") + endif() + string(SUBSTRING "${full_libname}" 3 -1 libname) endif() - string(SUBSTRING "${full_libname}" 3 -1 libname) set(${libnameOut} ${libname} PARENT_SCOPE) endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake b/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake index 91c2a6cf4180..5ae79c5fc18d 100644 --- a/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake @@ -291,7 +291,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 @@ -649,7 +653,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( @@ -1387,6 +1393,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 diff --git a/cmake/tribits/core/package_arch/TribitsProcessEnabledTpl.cmake b/cmake/tribits/core/package_arch/TribitsProcessEnabledTpl.cmake index ee5d6759834b..71429910b65d 100644 --- a/cmake/tribits/core/package_arch/TribitsProcessEnabledTpl.cmake +++ b/cmake/tribits/core/package_arch/TribitsProcessEnabledTpl.cmake @@ -39,6 +39,7 @@ # Standard TriBITS Includes +include(TribitsExternalPackageWriteConfigFile) include(TribitsTplFindIncludeDirsAndLibraries) include(TribitsGeneralMacros) @@ -103,7 +104,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) @@ -152,6 +164,22 @@ function(tribits_process_enabled_tpl TPL_NAME) # 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 + if (TARGET ${TPL_NAME}::all_libs) + 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_external_package_write_config_version_file(${TPL_NAME} + "${tplConfigVersionFile}") + tribits_external_package_install_config_file(${TPL_NAME} "${tplConfigFile}") + tribits_external_package_install_config_version_file(${TPL_NAME} + "${tplConfigVersionFile}") + endif() + endif() endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsTplFindIncludeDirsAndLibraries.cmake b/cmake/tribits/core/package_arch/TribitsTplFindIncludeDirsAndLibraries.cmake index b5db1ef454c5..acc851e31c7d 100644 --- a/cmake/tribits/core/package_arch/TribitsTplFindIncludeDirsAndLibraries.cmake +++ b/cmake/tribits/core/package_arch/TribitsTplFindIncludeDirsAndLibraries.cmake @@ -677,15 +677,17 @@ function(tribits_tpl_find_include_dirs_and_libraries TPL_NAME) global_set(TPL_${TPL_NAME}_NOT_FOUND FALSE) endif() - set(buildDirCMakePkgsDir - "${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_CMAKE_PKGS_DIR}") + set(buildDirExternalPkgsDir + "${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR}") set(tplConfigFile - "${buildDirCMakePkgsDir}/${TPL_NAME}/${TPL_NAME}Config.cmake") + "${buildDirExternalPkgsDir}/${TPL_NAME}/${TPL_NAME}Config.cmake") tribits_external_package_write_config_file(${TPL_NAME} "${tplConfigFile}") if (NOT ${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING) include("${tplConfigFile}") endif() - tribits_external_package_install_config_file(${TPL_NAME} "${tplConfigFile}") + # NOTE: The file ConfigVersion.cmake will get created elsewhere as + # will the install targets for the files Config and + # ConfigVersion.cmake. endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake b/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake index 8405209c1ade..767cc62e8a22 100644 --- a/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake +++ b/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake @@ -371,7 +371,9 @@ endfunction() # function(tribits_generate_package_config_file_for_build_tree packageName) - set(BUILD_DIR_CMAKE_PKGS_DIR + 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 @@ -382,7 +384,8 @@ function(tribits_generate_package_config_file_for_build_tree packageName) set(PACKAGE_CONFIG_CODE "") tribits_append_dependent_package_config_file_includes(${packageName} - CONFIG_FILE_BASE_DIR "${BUILD_DIR_CMAKE_PKGS_DIR}" + 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. @@ -469,7 +472,9 @@ function(tribits_generate_package_config_file_for_install_tree packageName) set(PACKAGE_CONFIG_CODE "") tribits_append_dependent_package_config_file_includes(${packageName} - CONFIG_FILE_BASE_DIR "\${CMAKE_CURRENT_LIST_DIR}/.." + 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 targets @@ -499,14 +504,15 @@ endfunction() # @FUNCTION: tribits_append_dependent_package_config_file_includes() # -# Append the includes for upstream internal packages and external packages -# (TPLs) to a `Config.cmake` file string. +# Append the includes for upstream external packages (TPLs) and internal +# packages to a `Config.cmake` file string. # # Usage:: # # tribits_append_dependent_package_config_file_includes( # -# CONFIG_FILE_BASE_DIR +# EXT_PKG_CONFIG_FILE_BASE_DIR +# PKG_CONFIG_FILE_BASE_DIR # CONFIG_FILE_STR_INOUT # ) # @@ -517,20 +523,22 @@ function(tribits_append_dependent_package_config_file_includes packageName) cmake_parse_arguments( PARSE #prefix "" #options - "CONFIG_FILE_BASE_DIR;CONFIG_FILE_STR_INOUT" #one_value_keywords + #one_value_keywords + "EXT_PKG_CONFIG_FILE_BASE_DIR;PKG_CONFIG_FILE_BASE_DIR;CONFIG_FILE_STR_INOUT" "" #multi_value_keywords ${ARGN} ) tribits_check_for_unparsed_arguments() - set(configFileBaseDir "${PARSE_CONFIG_FILE_BASE_DIR}") + set(extPkgConfigFileBaseDir "${PARSE_EXT_PKG_CONFIG_FILE_BASE_DIR}") + set(pkgConfigFileBaseDir "${PARSE_PKG_CONFIG_FILE_BASE_DIR}") set(configFileStr "${${PARSE_CONFIG_FILE_STR_INOUT}}") # Include configurations of dependent packages string(APPEND configFileStr "# Include configuration of dependent packages\n") foreach(depPkg IN LISTS ${packageName}_FULL_ENABLED_DEP_PACKAGES) - set(cmakePkgDir "${configFileBaseDir}/${depPkg}") + set(cmakePkgDir "${pkgConfigFileBaseDir}/${depPkg}") string(APPEND configFileStr "include(\"${cmakePkgDir}/${depPkg}Config.cmake\")\n") endforeach() @@ -540,14 +548,14 @@ function(tribits_append_dependent_package_config_file_includes packageName) "\n# Include configuration of dependent external packages/TPls\n") foreach(depTpl IN LISTS ${packageName}_LIB_REQUIRED_DEP_TPLS) if (TARGET ${depTpl}::all_libs) - set(cmakeTplDir "${configFileBaseDir}/${depTpl}") + set(cmakeTplDir "${extPkgConfigFileBaseDir}/${depTpl}") string(APPEND configFileStr "include(\"${cmakeTplDir}/${depTpl}Config.cmake\")\n") endif() endforeach() foreach(depTpl IN LISTS ${packageName}_LIB_OPTIONAL_DEP_TPLS) if (${packageName}_ENABLE_${depTpl} AND TARGET ${depTpl}::all_libs) - set(cmakeTplDir "${configFileBaseDir}/${depTpl}") + set(cmakeTplDir "${extPkgConfigFileBaseDir}/${depTpl}") string(APPEND configFileStr "include(\"${cmakeTplDir}/${depTpl}Config.cmake\")\n") endif() @@ -645,7 +653,7 @@ function(tribits_write_package_client_export_files PACKAGE_NAME) message("\nTRIBITS_WRITE_PACKAGE_CLIENT_EXPORT_FILES: ${PACKAGE_NAME}") endif() - set(BUILD_DIR_CMAKE_PKGS_DIR + set(buildDirCMakePkgsDir "${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_CMAKE_PKGS_DIR}") set(EXPORT_FILES_ARGS PACKAGE_NAME ${PACKAGE_NAME}) @@ -655,7 +663,7 @@ function(tribits_write_package_client_export_files PACKAGE_NAME) message("For package ${PACKAGE_NAME} creating ${PACKAGE_NAME}Config.cmake") endif() set(PACKAGE_CONFIG_FOR_BUILD_BASE_DIR - "${BUILD_DIR_CMAKE_PKGS_DIR}/${PACKAGE_NAME}" ) + "${buildDirCMakePkgsDir}/${PACKAGE_NAME}" ) set(PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles" ) append_set(EXPORT_FILES_ARGS 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/TribitsGatherBuildTargets.cmake b/cmake/tribits/core/utils/TribitsGatherBuildTargets.cmake index 021e11b3fabb..6056d777f5d8 100644 --- a/cmake/tribits/core/utils/TribitsGatherBuildTargets.cmake +++ b/cmake/tribits/core/utils/TribitsGatherBuildTargets.cmake @@ -87,32 +87,16 @@ function(tribits_filter_only_build_targets targetListInVar targetTypesList targetListOutVar ) - #message("\ntribits_filter_only_build_targets:\n") - #print_var(targetListInVar) - #print_var(targetTypesList) - #print_var(targetListInVar) - #print_var(${targetListInVar}) - set(targetListOut "") foreach (target IN LISTS ${targetListInVar}) - #message("") - #print_var(target) get_property(targetType TARGET ${target} PROPERTY TYPE) - set(matchedDesiredTargetType FALSE) - #print_var(targetType) foreach (desiredTargetType IN ITEMS ${targetTypesList}) - #print_var(desiredTargetType) if (desiredTargetType STREQUAL targetType) - #message("-- " "${target} is a filtered-for build target!") list(APPEND targetListOut ${target}) - set(matchedDesiredTargetType TRUE) break() endif() endforeach() - #if (NOT matchedDesiredTargetType) - # message("-- " "${target} is **NOT** a filtered-for build target!") - #endif() endforeach() set(${targetListOutVar} ${targetListOut} PARENT_SCOPE) diff --git a/cmake/tribits/core/utils/TribitsGetImportedLocationProperty.cmake b/cmake/tribits/core/utils/TribitsGetImportedLocationProperty.cmake new file mode 100644 index 000000000000..a4b4d7599a26 --- /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 proeprty 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/doc/build_ref/TribitsBuildReferenceBody.rst b/cmake/tribits/doc/build_ref/TribitsBuildReferenceBody.rst index 9e0d74edd154..46e0d59b5283 100644 --- a/cmake/tribits/doc/build_ref/TribitsBuildReferenceBody.rst +++ b/cmake/tribits/doc/build_ref/TribitsBuildReferenceBody.rst @@ -3743,6 +3743,13 @@ 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 seprate directory to avoid being found by accident. + Installation Testing ==================== diff --git a/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst b/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst index 092ccb1abfb9..38d58b4192f8 100644 --- a/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst +++ b/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst @@ -368,6 +368,10 @@ These options are described below. This default can be set in `/ProjectName.cmake`_ or `/CMakeLists.txt`_. + On WIN32 sytems, 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:: @@ -479,6 +483,12 @@ 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}_INSTALL_LIBRARIES_AND_HEADERS: diff --git a/cmake/tribits/doc/guides/TribitsGuidesBody.rst b/cmake/tribits/doc/guides/TribitsGuidesBody.rst index 190d97e286d1..d8c947dd1660 100644 --- a/cmake/tribits/doc/guides/TribitsGuidesBody.rst +++ b/cmake/tribits/doc/guides/TribitsGuidesBody.rst @@ -2150,11 +2150,12 @@ 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 -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`_). +multiple packages that uses the TPL. 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 @@ -2171,11 +2172,12 @@ module which is currently: 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`_. +the wrapping ``FindTPL${TPL_NAME}.cmake`` file is to ensure the definition of +the complete target ``${TPL_NAME}::all_libs`` which contains all usage +requirements for the external package/TPL (i.e. all of the libraries, include +directories, etc.). 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`_. Once the `/TPLsList.cmake`_ files are all processed, then each defined TPL ``TPL_NAME`` is assigned the following global non-cache variables: @@ -5472,14 +5474,22 @@ To add a new TriBITS TPL, do the following: How to use find_package() for a TriBITS TPL ------------------------------------------- -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 is possible and encouraged +to utilize ``find_package( ...)`` to provide the default find +operation. However, most ``Find.cmake`` modules and even some +``Config.cmake`` config files don't provide all of the required +features needed by downstream TriBITS packages. Specifically, these modules +and config files usually don't provide a complete ``::all_libs`` +target that contains all usage requirements (such as the +``INTERFACE_INCLUDE_DIRECTORIES`` and ``INTERFACE_LINK_LIBRARIES`` target +properties) for the external package/TPL libraries. Also, in order for the +resulting ``FindTPL.cmake`` module to behave consistently between all +the various TriBITS TPLs (and allow the standard TriBITS TPL find overrides) +and maintain backwards compatibility, one must use the TriBITS function `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:: +`tribits_tpl_find_include_dirs_and_libraries()`_. One basic form of the +resulting TriBITS TPL module file ``FindTPL.cmake`` that uses a list +of include directories and library files locations looks like:: # First, set up the variables for the (backward-compatible) TriBITS way of # finding . These are used in case find_package( ...) is @@ -5529,8 +5539,9 @@ If one wants to skip and ignore the standard TriBITS TPL override variables 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 +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`` which are often used in the concrete CMake ``Find.cmake`` module files themselves. @@ -5550,6 +5561,66 @@ specialized ``FindTPL.cmake`` file and can't use the find modules cannot completely adhere to the standard behavior described in `Enabling support for an optional Third-Party Library (TPL)`_. +One issue to be made aware of is that code in ``FindTPL.cmake`` must +generate the file:: + + /external_packages//Config.cmake + +where ``Config.cmake`` defines the ``::all_libs`` target. +The function `tribits_tpl_find_include_dirs_and_libraries()`_ creates these +files automatically when working with the lists ``TPL__INCLUDE_DIRS`` +and ``TPL__LIBRARIES`` as shown in the examples above. But in cases +where the inner ``find_package( ...)`` call actually generates a set +of modern CMake IMPORTED targets, the code in ``Find.cmake`` will +need to skip calling ``tribits_tpl_find_include_dirs_and_libraries()`` and +will instead need to build the target ``::all_libs`` itself and will +need to build the and write the wrapper file ``Config.cmake`` +manually into ``/external_packages//`` that does the right +thing when they are included by downstream ``Config.cmake`` files. + +An example of a custom ``FindTPL.cmake`` file that calls +``find_package( ...)`` which produces modern CMake targets that +manually creates the ``::all_libs`` target is given in +``TribitsExampleProject2/cmake/tpls/FindTPLTpl1.cmake`` which is: + +.. include:: ../../examples/TribitsExampleProject2/cmake/tpls/FindTPLTpl1.cmake + :literal: + +Another issue that comes up with external packages/TPLs like HDF5 that needs +to be discussed here is the fact that TriBITS generates and installs files of +the name ``HDF5Config.cmake`` that can be found by calls to +``find_package(HDF5)``. These TriBITS-generated ``HDF5Config.cmake`` files +are primarily meant to be included by and provide targets for downstream +TriBITS package ``Config.cmake`` files. These TriBITS-generated +``HDF5Config.cmake`` files may not behave the same way that a more general +``FindHDF5.config`` modules or ``HDF5Config.camke`` configure files would +behave as expected when found by ``find_package(HDF5)`` 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 ``/external_packages/`` and +installed into the directory ``/lib/external_packages/`` so they +will not be found 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. through ``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 ``Config.cmake``. (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.) + How to add a new TriBITS Repository ----------------------------------- diff --git a/cmake/tribits/examples/TribitsExampleApp/README.md b/cmake/tribits/examples/TribitsExampleApp/README.md index e80b7ee8817b..9d9b99bb0b29 100644 --- a/cmake/tribits/examples/TribitsExampleApp/README.md +++ b/cmake/tribits/examples/TribitsExampleApp/README.md @@ -15,8 +15,8 @@ build, and run the tests with: ctest ``` -That will call `find_package(TribitsExaProj)` and will set the compilers -pulled in from the found `TribitsExaProjConfig.cmake` file. +That will call `find_package(TribitsExProj)` and will set the compilers +pulled in from the found `TribitsExProjConfig.cmake` file. ## Pulling in only a subset of packages @@ -68,7 +68,7 @@ That essentially results in calling: ) ``` -(but does so with a loop and a list internally obviously). +(but does so with a loop and a list internally). ## Pulling in packages from the build tree diff --git a/cmake/tribits/examples/TribitsExampleApp2/AppHelperFuncs.cmake b/cmake/tribits/examples/TribitsExampleApp2/AppHelperFuncs.cmake new file mode 100644 index 000000000000..0317c489ce41 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleApp2/AppHelperFuncs.cmake @@ -0,0 +1,163 @@ +include(CMakePrintHelpers) + + +# Find TribitsExProj2 package(s), load compilers and compiler options, and get +# CMake lib targets (which have include dirs also) to link against. +# +# On return, sets the vars in the current scope: +# +# * TribitsExProj2_SELECTED_PACKAGE_LIST: List of all of the packages pulled in +# * from the TribitsExProj2. +# +# * APP_DEPS_LIB_TARGETS: List of all of the IMPORTED CMake targets that 'app' +# must link against +# +# * CMAKE__COMPILER and CMAKE__FLAGS pulled in from the +# TribitsExProj2Config.config or a Config.cmake file +# +macro(getTribitsExProj2StuffForApp) + + set(${PROJECT_NAME}_FIND_INDIVIDUAL_PACKAGES OFF CACHE BOOL + "Set to TRUE to find individual packages and OFF to find project TribitsExProj2") + + if (${PROJECT_NAME}_FIND_INDIVIDUAL_PACKAGES) + getTribitsExProj2StuffForAppByPackage() + else() + getTribitsExProj2StuffForAppByProject() + endif() + +endmacro() + + +# Get TribitsExProj2 stuff with find_package() for each +# package/component independently. +# +macro(getTribitsExProj2StuffForAppByPackage) + + # Find each package and gather up all the ::all_libs targets + set(APP_DEPS_LIB_TARGETS "") + foreach (packageName IN LISTS ${PROJECT_NAME}_USE_COMPONENTS) + find_package(${packageName} REQUIRED) + message("Found ${packageName}!") + list(APPEND APP_DEPS_LIB_TARGETS ${packageName}::all_libs) + endforeach() + print_var(APP_DEPS_LIB_TARGETS) + + # Set TribitsExProj2_SELECTED_PACKAGE_LIST + set(TribitsExProj2_SELECTED_PACKAGE_LIST ${${PROJECT_NAME}_USE_COMPONENTS}) + # NOTE: We are setting his here since TribitsExProj2Config.cmake is not being + # read in in this case. + + # Get compilers from first package listed + list(GET ${PROJECT_NAME}_USE_COMPONENTS 0 firstPkg) + setCompilersForAppFromConfigFileCompilers(${firstPkg}) + +endmacro() + + +# Get TribitsExProj2 stuff from find_package(TribitsExProj2) +# +macro(getTribitsExProj2StuffForAppByProject) + + find_package(TribitsExProj2 REQUIRED COMPONENTS ${${PROJECT_NAME}_USE_COMPONENTS}) + + message("\nFound TribitsExProj2! Here are the details: ") + message(" TribitsExProj2_DIR = ${TribitsExProj2_DIR}") + message(" TribitsExProj2_VERSION = ${TribitsExProj2_VERSION}") + message(" TribitsExProj2_PACKAGE_LIST = ${TribitsExProj2_PACKAGE_LIST}") + message(" TribitsExProj2_TPL_LIST = ${TribitsExProj2_TPL_LIST}") + message(" TribitsExProj2_BUILD_SHARED_LIBS = ${TribitsExProj2_BUILD_SHARED_LIBS}") + message("End of TribitsExProj2 details\n") + + # Make sure to use same compilers and flags as TribitsExProj2 + setCompilersForAppFromConfigFileCompilers(TribitsExProj2) + + # Get the libraries for building and linking + if (${PROJECT_NAME}_USE_COMPONENTS) + set(APP_DEPS_LIB_TARGETS TribitsExProj2::all_selected_libs) + else() + set(APP_DEPS_LIB_TARGETS TribitsExProj2::all_libs) + endif() + +endmacro() + + +# Get compilers and compiler flags from the imported +# ``TribitsExProj2Config.cmake`` or ``Config.cmake`` file. +# +# Here ``prefix`` is the prefix for the variables read in from the +# *Config.cmake file. +# +macro(setCompilersForAppFromConfigFileCompilers prefix) + + message("-- Setting compilers and flags read in from '${prefix}Config.cmake' file:") + + set(CMAKE_CXX_COMPILER ${${prefix}_CXX_COMPILER} ) + set(CMAKE_C_COMPILER ${${prefix}_C_COMPILER} ) + set(CMAKE_Fortran_COMPILER ${${prefix}_Fortran_COMPILER} ) + + set(CMAKE_CXX_FLAGS "${${prefix}_CXX_COMPILER_FLAGS} ${CMAKE_CXX_FLAGS}") + set(CMAKE_C_FLAGS "${${prefix}_C_COMPILER_FLAGS} ${CMAKE_C_FLAGS}") + set(CMAKE_Fortran_FLAGS "${${prefix}_Fortran_COMPILER_FLAGS} ${CMAKE_Fortran_FLAGS}") + + cmake_print_variables(CMAKE_CXX_COMPILER) + cmake_print_variables(CMAKE_C_COMPILER) + cmake_print_variables(CMAKE_Fortran_COMPILER) + cmake_print_variables(CMAKE_CXX_FLAGS) + cmake_print_variables(CMAKE_C_FLAGS) + cmake_print_variables(CMAKE_Fortran_FLAGS) + +endmacro() + + +# Add compiler defines to the ``app`` target for optionally supported packages +# from upstream TribitExProj +# +function(addAppDepCompileDefines) + addAppDepCompileDefine("Package1") + #addAppDepCompileDefine("Package2") + #addAppDepCompileDefine("Package3") +endfunction() + + +function(addAppDepCompileDefine componentName) + if (${componentName} IN_LIST TribitsExProj2_SELECTED_PACKAGE_LIST) + string(TOUPPER "${componentName}" componentNameUpper) + message("target_compile_definitions(app PRIVATE TRIBITSEXAPP2_HAVE_${componentNameUpper}) +") + target_compile_definitions(app PRIVATE TRIBITSEXAPP2_HAVE_${componentNameUpper}) + endif() +endfunction() + + +# Return the extended dependency string from the app at runtime given the +# enabled packages from TribitsExProj2. +# +function(getExpectedAppDepsStr expectedDepsStrOut) + + set(package1Deps "tpl1") + + set(depsStr "Package1: ${package1Deps}") + + set(${expectedDepsStrOut} "${depsStr}" PARENT_SCOPE) + +endfunction() + + +function(appendExpectedAppDepsStr componentName str depsStrOut) + set(depsStr "${${depsStrOut}}") # Should be value of var in parent scope! + #message("-- depsStr (inner) = '${depsStr}'") + if (${componentName} IN_LIST TribitsExProj2_SELECTED_PACKAGE_LIST) + if (depsStr) + set(depsStr "${depsStr}[;] ${str}") + else() + set(depsStr "${str}") + endif() + endif() + set(${depsStrOut} "${depsStr}" PARENT_SCOPE) +endfunction() + + +function(print_var varName) + message("-- ${varName} = '${${varName}}'") +endfunction() diff --git a/cmake/tribits/examples/TribitsExampleApp2/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleApp2/CMakeLists.txt new file mode 100644 index 000000000000..306b0d61b6ed --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleApp2/CMakeLists.txt @@ -0,0 +1,41 @@ +cmake_minimum_required(VERSION 3.17.1) + +project(TribitsExApp2 + DESCRIPTION + "Example raw CMake project using packages installed from TribitsExampleProject2" + VERSION 0.0.0 + LANGUAGES NONE # Defined below after reading in compilers + ) + +set(${PROJECT_NAME}_USE_COMPONENTS "" CACHE STRING + "Components/Packages to use from TribitsExampleProject2: ,,..." ) +string(REPLACE "," ";" ${PROJECT_NAME}_USE_COMPONENTS + "${${PROJECT_NAME}_USE_COMPONENTS}") + +list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") +include(AppHelperFuncs) + +getTribitsExProj2StuffForApp() + +# Enable the compilers now that we have gotten them from the *Config.cmake file +enable_language(C) +enable_language(CXX) +if (CMAKE_Fortran_COMPILER) + enable_language(Fortran) +endif() + +# Build the APP and link to libraries from TribitsExProj packages +add_executable(app app.cpp) +target_link_libraries(app PRIVATE ${APP_DEPS_LIB_TARGETS}) +addAppDepCompileDefines() + +# Set up tests + +enable_testing() + +getExpectedAppDepsStr(expectedDepsStr) + +add_test(app_test app) +set_tests_properties(app_test PROPERTIES + PASS_REGULAR_EXPRESSION "Full Deps: ${expectedDepsStr}" + ) diff --git a/cmake/tribits/examples/TribitsExampleApp2/README.md b/cmake/tribits/examples/TribitsExampleApp2/README.md new file mode 100644 index 000000000000..01555a00dc62 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleApp2/README.md @@ -0,0 +1,110 @@ +# TribitsExampleApp2 + +The example project `TribitsExampleApp2` is a raw CMake project that pulls in +libraries from packages from `TribitsExampleProject2`. To build against all of +the installed packages from an upstream `TribitsExampleProject2`, configure, +build, and run the tests with: + +``` + cmake \ + -DCMAKE_PREFIX_PATH= \ + /TribitsExampleApp2 + + make + + ctest +``` + +That will call `find_package(TribitsExProj2)` and will set the compilers +pulled in from the found `TribitsExProj2Config.cmake` file. + + +## Pulling in only a subset of packages + +To configure and build `TribitsExampleApp2` against only a subset of the +installed `TribitsExampleProject2` packages, configure `TribitsExampleApp2` +using, for example: + +``` + cmake \ + -DCMAKE_PREFIX_PATH= \ + -DTribitsExApp_USE_COMPONENTS=Package1,Package2 \ + /TribitsExampleApp2 +``` + +Internally, that that will call: + +``` + find_package(TribitsExApp REQUIRED COMPONENTS ${TribitsExApp_USE_COMPONENTS}) +``` + +(where `,` in `TribitsExApp_USE_COMPONENTS` is replaced with `;` internally to +create a proper CMake list internally before calling `find_package()`). + + +## Pulling in only a subset of packages by finding each package individually + +`TribitsExampleApp2` is also set up to demonstrate finding the individual +packages using separate calls to `find_package()` by configuring +with, for example: + +``` + cmake \ + -DCMAKE_PREFIX_PATH= \ + -DTribitsExApp_USE_COMPONENTS=Package1,Package2 \ + -DTribitsExApp_FIND_INDIVIDUAL_PACKAGES=ON \ + /TribitsExampleApp2 +``` + +That essentially results in calling: + +``` + find_package(Package1 REQUIRED) + find_package(Package2 REQUIRED) + ... + target_link_libraries(app + PRIVATE Package1::all_libs + PRIVATE Package2::all_libs + ) +``` + +(but does so with a loop and a list internally). + + +## Pulling in packages from the build tree + +`TribitsExampleApp2` is additionally set up to demonstrate finding the +individual packages from the build directory (where `` is +the build directory for `TribitsExampleProject2`) instead of the install tree +using separate calls to `find_package()` by configuring with, for +example: + +``` + cmake \ + -DCMAKE_PREFIX_PATH=/cmake_packages \ + -DTribitsExApp_USE_COMPONENTS=Package1,Package2 \ + -DTribitsExApp_FIND_INDIVIDUAL_PACKAGES=ON \ + /TribitsExampleApp2 +``` + +This is identical to the case to finding the individual packages under the +install tree except here the packages and libraries are found under the build +tree and the include directories point into the source tree. (There is no +need for an install directory in this case.) This is to simulate more +advanced use cases such as where `TribitsExampleApp2` and +`TribitsExampleProject2` may be part of a larger super-build that works out of +the build tree without needing to install. + +NOTE: There is no `TribitsExProj2Config.cmake` file generated in the build tree +to find so it is not possible to call `find_package(TribitsExProj2Config)` +pointing into the build tree. + + +## Tests demonstrating usage of TribitsExampleApp2 + +The TriBITS project contains automated tests that run the various use cases +described above and check their result. These tests are shown defined +[here](https://github.com/TriBITSPub/TriBITS/blob/master/test/core/ExamplesUnitTests/TribitsExampleApp2_Tests.cmake) +and are run locally with CTest and are submitted to +[CDash](https://github.com/TriBITSPub/TriBITS/wiki/TriBITS-CDash-Dashboard) as +part of regular testing. diff --git a/cmake/tribits/examples/TribitsExampleApp2/app.cpp b/cmake/tribits/examples/TribitsExampleApp2/app.cpp new file mode 100644 index 000000000000..9ac07aad12eb --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleApp2/app.cpp @@ -0,0 +1,34 @@ +#ifdef TRIBITSEXAPP2_HAVE_PACKAGE1 +# include "Package1.hpp" +#endif + + +#include +#include + + +void appendDepsStr(std::string &depsStr, const std::string &str) +{ + if (depsStr.length()) { + depsStr += "; "+str; + } + else { + depsStr = str; + } +} + + +int main(int argc, char *argv[]) { + // Get deps down the deps graph + std::string depsStr; +#ifdef TRIBITSEXAPP2_HAVE_PACKAGE1 + appendDepsStr(depsStr, "Package1: "+Package1::deps()); +#endif + // NOTE: The above all call functions from the libraries and requires that + // both the header files be found at compile time and the libraries be found + // at link time and runtime for this these function calls to work. + + std::cout << "Full Deps: " << depsStr << "\n"; + + return 0; +} diff --git a/cmake/tribits/examples/TribitsExampleProject/packages/wrap_external/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject/packages/wrap_external/CMakeLists.txt index 68e76a335f04..c92492464ec7 100644 --- a/cmake/tribits/examples/TribitsExampleProject/packages/wrap_external/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleProject/packages/wrap_external/CMakeLists.txt @@ -6,8 +6,7 @@ # configured and built piece of software. The external software once built # provides libraries that need to be cast as TriBITS CMake libraries. To # make this even more interesting, the external software has dependencies on -# upstream TriBITS packages that it pulls in through a TriBITS export -# makefile. +# upstream TriBITS packages. # # An overview of the basic tasks required are: # @@ -62,7 +61,7 @@ endif() # start from scratch. # -# B) Get the arguments for the configure of exteranl_func +# B) Get the arguments for the configure of external_func # string(TOUPPER "${CMAKE_BUILD_TYPE}" upperBuildType) diff --git a/cmake/tribits/examples/TribitsExampleProject2/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject2/CMakeLists.txt new file mode 100644 index 000000000000..661cb556e0a0 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/CMakeLists.txt @@ -0,0 +1,14 @@ +################################################################################ +# # +# TribitsExampleProject2 # +# # +################################################################################ + +cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR) +include("${CMAKE_CURRENT_SOURCE_DIR}/ProjectName.cmake") +project(${PROJECT_NAME} LANGUAGES NONE) +set(${PROJECT_NAME}_TRIBITS_DIR + "${CMAKE_CURRENT_LIST_DIR}/../.." CACHE STRING + "TriBITS base directory (default assumes in TriBITS source tree)") +include("${${PROJECT_NAME}_TRIBITS_DIR}/TriBITS.cmake") +tribits_project() diff --git a/cmake/tribits/examples/TribitsExampleProject2/PackagesList.cmake b/cmake/tribits/examples/TribitsExampleProject2/PackagesList.cmake new file mode 100644 index 000000000000..104684961749 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/PackagesList.cmake @@ -0,0 +1,3 @@ +tribits_repository_define_packages( + Package1 packages/package1 PT + ) diff --git a/cmake/tribits/examples/TribitsExampleProject2/ProjectName.cmake b/cmake/tribits/examples/TribitsExampleProject2/ProjectName.cmake new file mode 100644 index 000000000000..c80b2c0653df --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/ProjectName.cmake @@ -0,0 +1,2 @@ +set(PROJECT_NAME TribitsExProj2) +set(${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES_DEFAULT ON) diff --git a/cmake/tribits/examples/TribitsExampleProject2/TPLsList.cmake b/cmake/tribits/examples/TribitsExampleProject2/TPLsList.cmake new file mode 100644 index 000000000000..eca542bfdffb --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/TPLsList.cmake @@ -0,0 +1,3 @@ +tribits_repository_define_tpls( + Tpl1 "cmake/tpls/" PT + ) diff --git a/cmake/tribits/examples/TribitsExampleProject2/Version.cmake b/cmake/tribits/examples/TribitsExampleProject2/Version.cmake new file mode 100644 index 000000000000..beeb4f4429dd --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/Version.cmake @@ -0,0 +1,5 @@ +set(${REPOSITORY_NAME}_VERSION 1.1) +set(${REPOSITORY_NAME}_MAJOR_VERSION 01) +set(${REPOSITORY_NAME}_MAJOR_MINOR_VERSION 010100) +set(${REPOSITORY_NAME}_VERSION_STRING "1.1 (Dev)") +set(${REPOSITORY_NAME}_ENABLE_DEVELOPMENT_MODE_DEFAULT ON) # Change to 'OFF' for a release diff --git a/cmake/tribits/examples/TribitsExampleProject2/cmake/tpls/FindTPLTpl1.cmake b/cmake/tribits/examples/TribitsExampleProject2/cmake/tpls/FindTPLTpl1.cmake new file mode 100644 index 000000000000..b96e80e076b4 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/cmake/tpls/FindTPLTpl1.cmake @@ -0,0 +1,69 @@ +include(TribitsGetImportedLocationProperty) + + +# +# Functions +# + +function(tpl1_write_config_file tpl1Dir) + set(configFileStr "") + string(APPEND configFileStr + "include(CMakeFindDependencyMacro)\n" + "set(Tpl1_DIR \"${tpl1Dir}\")\n" + "find_dependency(Tpl1)\n" + "add_library(Tpl1::all_libs INTERFACE IMPORTED GLOBAL)\n" + "target_link_libraries(Tpl1::all_libs INTERFACE tpl1::tpl1)\n" + ) + set(buildDirExternalPkgsDir + "${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR}") + set(tplConfigFile + "${buildDirExternalPkgsDir}/${TPL_NAME}/${TPL_NAME}Config.cmake") + file(WRITE "${tplConfigFile}" "${configFileStr}") + +endfunction() + + +# +# Executable Code +# + +set(REQUIRED_HEADERS Tpl1.hpp) +set(REQUIRED_LIBS_NAMES tpl1) + +tribits_tpl_allow_pre_find_package(Tpl1 Tpl1_ALLOW_PREFIND) + +if (Tpl1_ALLOW_PREFIND) + message("-- Using find_package(Tpl1 ...) ...") + find_package(Tpl1) + if (Tpl1_FOUND) + message("-- Found Tpl1_DIR='${Tpl1_DIR}'") + if (Tpl1_EXTRACT_INFO_AFTER_FIND_PACKAGE) + message("-- Extracting include dirs and libraries from target tpl1::tpl1") + get_target_property(inclDirs tpl1::tpl1 INTERFACE_INCLUDE_DIRECTORIES) + tribits_get_imported_location_property(tpl1::tpl1 libfile) + set(TPL_Tpl1_INCLUDE_DIRS "${inclDirs}" CACHE PATH "Include dirs for Tpl1") + set(TPL_Tpl1_LIBRARIES "${libfile}" CACHE PATH "Libraries for Tpl1") + else() + # Create imported target Tpl1::all_libs + add_library(Tpl1::all_libs INTERFACE IMPORTED GLOBAL) + target_link_libraries(Tpl1::all_libs INTERFACE tpl1::tpl1) + set(TPL_Tpl1_LIBRARIES Tpl1::all_libs CACHE STRING + "Set in ${CMAKE_CURRENT_LIST_FILE}") + set(TPL_Tpl1_INCLUDE_DIRS "" CACHE STRING + "Set in ${CMAKE_CURRENT_LIST_FILE}") + set(TPL_Tpl1_LIBRARY_DIRS "" CACHE STRING + "Set in ${CMAKE_CURRENT_LIST_FILE}") + print_var(TPL_Tpl1_LIBRARIES) + print_var(TPL_Tpl1_INCLUDE_DIRS) + # Write a specialized Tpl1Config.cmake file + tpl1_write_config_file("${Tpl1_DIR}") + endif() + endif() +endif() + +if (NOT TARGET Tpl1::all_libs) + tribits_tpl_find_include_dirs_and_libraries( Tpl1 + REQUIRED_HEADERS ${REQUIRED_HEADERS} + REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} + ) +endif() diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/CMakeLists.txt new file mode 100644 index 000000000000..bf2638c61fe9 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/CMakeLists.txt @@ -0,0 +1,4 @@ +tribits_package(Package1) +add_subdirectory(src) +tribits_add_test_directories(test) +tribits_package_postprocess() diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/Dependencies.cmake b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/Dependencies.cmake new file mode 100644 index 000000000000..64ccf196ee88 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/Dependencies.cmake @@ -0,0 +1,3 @@ +tribits_package_define_dependencies( + LIB_REQUIRED_TPLS Tpl1 + ) diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/CMakeLists.txt new file mode 100644 index 000000000000..a0d23199e246 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/CMakeLists.txt @@ -0,0 +1,22 @@ +set(HEADERS "") +set(SOURCES "") + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +append_set(HEADERS + Package1.hpp + ) +append_set(SOURCES + Package1.cpp + ) + +tribits_add_library( + package1 + HEADERS ${HEADERS} + SOURCES ${SOURCES} + ) + +tribits_add_executable(package1-prg NOEXEPREFIX NOEXESUFFIX + SOURCES Package1_Prg.cpp + INSTALLABLE + ) diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1.cpp b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1.cpp new file mode 100644 index 000000000000..b414fbd97b98 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1.cpp @@ -0,0 +1,9 @@ +#include "Package1.hpp" +#include "Tpl1.hpp" + +std::string Package1::deps() +{ + std::string deps; + deps = Tpl1::itsme(); + return deps; +} diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1.hpp b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1.hpp new file mode 100644 index 000000000000..2ba04aa4e985 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1.hpp @@ -0,0 +1,16 @@ +#ifndef PACKAGE1_HPP +#define PACKAGE1_HPP + + +#include + + +namespace Package1 { + +/** \brief . */ +std::string deps(); + +} // namespace Package1 + + +#endif // PACKAGE1_HPP diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1_Prg.cpp b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1_Prg.cpp new file mode 100644 index 000000000000..2ce91f102a79 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1_Prg.cpp @@ -0,0 +1,9 @@ +#include + +#include "Package1.hpp" + +int main() +{ + std::cout << "Package1 Deps: " << Package1::deps() << "\n"; + return 0; +} diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/test/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/test/CMakeLists.txt new file mode 100644 index 000000000000..afef4e708adf --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/test/CMakeLists.txt @@ -0,0 +1,6 @@ +tribits_add_test(package1-prg NOEXEPREFIX NOEXESUFFIX + NAME Prg + DIRECTORY ${PACKAGE_BINARY_DIR}/src + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "Package1 Deps: tpl1" + ) diff --git a/cmake/tribits/examples/tpls/Tpl1/CMakeLists.txt b/cmake/tribits/examples/tpls/Tpl1/CMakeLists.txt new file mode 100644 index 000000000000..681cefc9ca31 --- /dev/null +++ b/cmake/tribits/examples/tpls/Tpl1/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.17.0) + +project(Tpl1 + DESCRIPTION + "Simple TPL with one header file, one library, and no deps" + LANGUAGES C CXX + ) + +add_library(tpl1 Tpl1.hpp Tpl1.cpp) +target_include_directories(tpl1 + PUBLIC $ + ) + +include(GNUInstallDirs) + +install( + TARGETS tpl1 + EXPORT ${PROJECT_NAME} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ) + +install( + FILES Tpl1.hpp + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + ) + +install(EXPORT ${PROJECT_NAME} + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} + NAMESPACE tpl1:: + FILE ${PROJECT_NAME}Config.cmake + ) diff --git a/cmake/tribits/examples/tpls/Tpl1/Tpl1.cpp b/cmake/tribits/examples/tpls/Tpl1/Tpl1.cpp new file mode 100644 index 000000000000..d22e73e75e34 --- /dev/null +++ b/cmake/tribits/examples/tpls/Tpl1/Tpl1.cpp @@ -0,0 +1,6 @@ +#include "Tpl1.hpp" + +std::string Tpl1::itsme() +{ + return "tpl1"; +} diff --git a/cmake/tribits/examples/tpls/Tpl1/Tpl1.hpp b/cmake/tribits/examples/tpls/Tpl1/Tpl1.hpp new file mode 100644 index 000000000000..e263feab7c26 --- /dev/null +++ b/cmake/tribits/examples/tpls/Tpl1/Tpl1.hpp @@ -0,0 +1,13 @@ +#ifndef TPL1_HPP +#define TPL1_HPP + +#include + +namespace Tpl1 { + +/** \brief . */ +std::string itsme(); + +} // namespace tpl1 + +#endif // TPL1_HPP