From e9e2860883c2aeb9bb7843515d7db6983c377c0b Mon Sep 17 00:00:00 2001 From: "Roscoe A. Bartlett" Date: Wed, 15 Dec 2021 09:56:54 -0700 Subject: [PATCH 01/37] Automatic snapshot commit from tribits at 35d82aa Origin repo remote tracking branch: 'github/master' Origin repo remote repo URL: 'github = git@github.com:TriBITSPub/TriBITS.git' At commit: commit 35d82aaa31fe81ca30a619320bb71fe481e9d4c7 Author: Roscoe A. Bartlett Date: Tue Dec 14 15:48:02 2021 -0700 Summary: Interpret a raw identifer in TPL__LIBRARIES as a lib name (#299, #433) --- .../TribitsAdjustPackageEnables.cmake | 25 ++++++++++- ...ribitsExternalPackageWriteConfigFile.cmake | 42 ++++++++++++++----- .../TribitsWriteClientExportFiles.cmake | 20 +++++++-- .../examples/InsertedPkg/InsertedPkg.cpp | 2 +- .../examples/InsertedPkg/test/CMakeLists.txt | 2 +- .../TribitsExampleApp/AppHelperFuncs.cmake | 26 +++++++++--- .../examples/TribitsExampleApp/app.cpp | 20 +++++++-- .../packages/simple_cxx/CMakeLists.txt | 12 +++++- .../packages/with_subpackages/a/A.cpp | 2 +- .../with_subpackages/a/tests/CMakeLists.txt | 2 +- .../with_subpackages/b/CMakeLists.txt | 21 ++++++++++ .../packages/with_subpackages/b/src/B.cpp | 2 +- .../with_subpackages/b/tests/CMakeLists.txt | 12 +----- .../packages/with_subpackages/c/C.cpp | 2 +- .../packages/with_subpackages/c/c_util.cpp | 4 +- .../with_subpackages/c/tests/CMakeLists.txt | 8 +--- .../packages/wrap_external/CMakeLists.txt | 2 +- 17 files changed, 152 insertions(+), 52 deletions(-) diff --git a/cmake/tribits/core/package_arch/TribitsAdjustPackageEnables.cmake b/cmake/tribits/core/package_arch/TribitsAdjustPackageEnables.cmake index a08508730ff1..7db948b66fa6 100644 --- a/cmake/tribits/core/package_arch/TribitsAdjustPackageEnables.cmake +++ b/cmake/tribits/core/package_arch/TribitsAdjustPackageEnables.cmake @@ -57,6 +57,7 @@ include(MessageWrapper) include(DualScopeSet) include(CMakeParseArguments) + # # Private helper macros # @@ -314,7 +315,6 @@ macro(tribits_disable_parents_subpackages PARENT_PACKAGE_NAME) endmacro() -# # Macro that enables all of the subpackages of a parent package. # macro(tribits_enable_parents_subpackages PARENT_PACKAGE_NAME) @@ -698,6 +698,8 @@ macro(tribits_postprocess_package_with_subpackages_enables PACKAGE_NAME) "Setting ${PROJECT_NAME}_ENABLE_${PACKAGE_NAME}=ON" " because ${PROJECT_NAME}_ENABLE_${SUBPACKAGE_FULLNAME}=ON") set(${PROJECT_NAME}_ENABLE_${PACKAGE_NAME} ON) + tribits_postprocess_package_with_subpackages_optional_subpackage_enables( + ${PACKAGE_NAME}) tribits_postprocess_package_with_subpackages_test_example_enables( ${PACKAGE_NAME} TESTS) tribits_postprocess_package_with_subpackages_test_example_enables( @@ -711,6 +713,27 @@ macro(tribits_postprocess_package_with_subpackages_enables PACKAGE_NAME) endmacro() +# Set _ENABLE_=ON if not already enabled for all +# subpackages of a parent package. +# +macro(tribits_postprocess_package_with_subpackages_optional_subpackage_enables + PACKAGE_NAME + ) + #message("TRIBITS_POSTPROCESS_PACKAGE_WITH_SUBPACKAGES_TEST_EXAMPLE_ENABLES '${PACKAGE_NAME}'") + foreach(TRIBITS_SUBPACKAGE ${${PACKAGE_NAME}_SUBPACKAGES}) + set(SUBPACKAGE_FULLNAME ${PACKAGE_NAME}${TRIBITS_SUBPACKAGE}) + if (${PROJECT_NAME}_ENABLE_${SUBPACKAGE_FULLNAME} + AND "${${PACKAGE_NAME}_ENABLE_${SUBPACKAGE_FULLNAME}}" STREQUAL "" + ) + message("-- " + "Setting ${PACKAGE_NAME}_ENABLE_${SUBPACKAGE_FULLNAME}=ON" + " because ${PROJECT_NAME}_ENABLE_${SUBPACKAGE_FULLNAME}=ON") + set(${PACKAGE_NAME}_ENABLE_${SUBPACKAGE_FULLNAME} ON) + endif() + endforeach() +endmacro() + + # Set the parent package tests/examples enables if one subpackage is enabled # and has its tests/examples # diff --git a/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake b/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake index 69b513e88e3d..3de401327c94 100644 --- a/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake +++ b/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake @@ -230,7 +230,7 @@ endfunction() # # 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.. +# linker flags. # # Usage:: # @@ -243,17 +243,17 @@ endfunction() # # The arguments are: # -# ````: Name of the external package/TPL +# ````: [In] 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. +# ````: [Out] 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. +# ````: [Out] 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 -# ````. +# ````: [Inout] 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) @@ -294,6 +294,9 @@ function(tribits_external_package_process_libraries_list tplName) "ERROR: Can't handle argument '${libentry}' in list TPL_${tplName}_LIBRARIES") elseif (libEntryType STREQUAL "LIB_DIR_LINK_OPTION") list(APPEND libLinkFlagsList "${libentry}") + elseif (libEntryType STREQUAL "GENERAL_LINK_OPTION") + message_wrapper("NOTE: Moving the general link argument '${libentry}' in TPL_${tplName}_LIBRARIES forward on the link line which may change the link and break the link!") + list(APPEND libLinkFlagsList "${libentry}") else() tribits_external_package_process_libraries_list_library_entry( ${tplName} "${libentry}" ${libEntryType} libTargets lastLib configFileStr ) @@ -326,25 +329,36 @@ endfunction() # ``LIB_NAME_LINK_OPTION``: A library name link option of the form # ``-l`` # +# ``LIB_NAME``: A library name of the form ```` +# # ``LIB_DIR_LINK_OPTION``: A library directory search option of the form # ``-L`` # +# ``GENERAL_LINK_OPTION``: Some other general link option that starts with +# ``-`` but is not ``-l`` or ``-L``. +# # ``UNSUPPORTED_LIB_ENTRY``: An unsupported lib option # function(tribits_tpl_libraries_entry_type libentry libEntryTypeOut) + string(SUBSTRING "${libentry}" 0 1 firstCharLibEntry) string(SUBSTRING "${libentry}" 0 2 firstTwoCharsLibEntry) if (firstTwoCharsLibEntry STREQUAL "-l") set(libEntryType LIB_NAME_LINK_OPTION) elseif (firstTwoCharsLibEntry STREQUAL "-L") set(libEntryType LIB_DIR_LINK_OPTION) + elseif (firstCharLibEntry STREQUAL "-") + set(libEntryType GENERAL_LINK_OPTION) elseif (IS_ABSOLUTE "${libentry}") set(libEntryType FULL_LIB_PATH) + elseif (libentry MATCHES "^[a-zA-Z_][a-zA-Z0-9_-]*$") + set(libEntryType LIB_NAME) else() set(libEntryType UNSUPPORTED_LIB_ENTRY) endif() set(${libEntryTypeOut} ${libEntryType} PARENT_SCOPE) endfunction() - +# NOTE: Above, if libentry is only 1 char long, then firstTwoCharsLibEntry is +# also 1 char long and the above logic still works. # Function to process a library inside of loop over TPL__LIBRARIES # in the function tribits_external_package_process_libraries_list() @@ -395,6 +409,9 @@ function(tribits_external_package_get_libname_and_path_from_libentry elseif (libEntryType STREQUAL "LIB_NAME_LINK_OPTION") tribits_external_package_get_libname_from_lib_name_link_option("${libentry}" libname) set(libpath "") + elseif (libEntryType STREQUAL "LIB_NAME") + set(libname "${libentry}") + set(libpath "") else() message(FATAL_ERROR "Error libEntryType='${libEntryType}' not supported here!") endif() @@ -414,7 +431,10 @@ function(tribits_external_package_append_add_library_str "set_target_properties(${prefixed_libname} PROPERTIES\n" " IMPORTED_LOCATION \"${libpath}\")\n" ) - elseif (libEntryType STREQUAL "LIB_NAME_LINK_OPTION") + elseif ( + (libEntryType STREQUAL "LIB_NAME_LINK_OPTION") + OR (libEntryType STREQUAL "LIB_NAME") + ) string(APPEND configFileStr "add_library(${prefixed_libname} IMPORTED INTERFACE GLOBAL)\n" "set_target_properties(${prefixed_libname} PROPERTIES\n" diff --git a/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake b/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake index 767cc62e8a22..89703bb3dbf9 100644 --- a/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake +++ b/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake @@ -537,10 +537,22 @@ function(tribits_append_dependent_package_config_file_includes packageName) # 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 "${pkgConfigFileBaseDir}/${depPkg}") - string(APPEND configFileStr - "include(\"${cmakePkgDir}/${depPkg}Config.cmake\")\n") + foreach(depPkg IN LISTS ${packageName}_LIB_REQUIRED_DEP_PACKAGES) + if (${PROJECT_NAME}_ENABLE_${depPkg}) + set(cmakeTplDir "${pkgConfigFileBaseDir}/${depPkg}") + string(APPEND configFileStr + "include(\"${cmakeTplDir}/${depPkg}Config.cmake\")\n") + endif() + # NOTE: Above, a required dependent package may not actaully be enabled if + # it is a required subpackage of a parent package and the parent package + # itself is not actaully enabled (very tricky). + endforeach() + foreach(depPkg IN LISTS ${packageName}_LIB_OPTIONAL_DEP_PACKAGES) + if (${packageName}_ENABLE_${depPkg} AND ${PROJECT_NAME}_ENABLE_${depPkg}) + set(cmakeTplDir "${pkgConfigFileBaseDir}/${depPkg}") + string(APPEND configFileStr + "include(\"${cmakeTplDir}/${depPkg}Config.cmake\")\n") + endif() endforeach() # Include configurations of dependent external packages/TPLs diff --git a/cmake/tribits/examples/InsertedPkg/InsertedPkg.cpp b/cmake/tribits/examples/InsertedPkg/InsertedPkg.cpp index b645688010d5..29afe432b324 100644 --- a/cmake/tribits/examples/InsertedPkg/InsertedPkg.cpp +++ b/cmake/tribits/examples/InsertedPkg/InsertedPkg.cpp @@ -3,5 +3,5 @@ #include "SimpleCxx_HelloWorld.hpp" std::string InsertedPkg::deps() { - return SimpleCxx::deps(); + return (std::string("SimpleCxx ") + SimpleCxx::deps()); } diff --git a/cmake/tribits/examples/InsertedPkg/test/CMakeLists.txt b/cmake/tribits/examples/InsertedPkg/test/CMakeLists.txt index 72c47562180f..b01f653d617c 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: headeronlytpl" + "InsertedPkg deps are: ${EXPECTED_SIMPLECXX_AND_DEPS}" ) diff --git a/cmake/tribits/examples/TribitsExampleApp/AppHelperFuncs.cmake b/cmake/tribits/examples/TribitsExampleApp/AppHelperFuncs.cmake index 3ed976e7c654..471f33eb2d20 100644 --- a/cmake/tribits/examples/TribitsExampleApp/AppHelperFuncs.cmake +++ b/cmake/tribits/examples/TribitsExampleApp/AppHelperFuncs.cmake @@ -116,16 +116,22 @@ endmacro() function(addAppDepCompileDefines) addAppDepCompileDefine("SimpleCxx") addAppDepCompileDefine("MixedLang") - addAppDepCompileDefine("WithSubpackages") + addAppDepCompileDefine("WithSubpackagesA") + addAppDepCompileDefine("WithSubpackagesB") + addAppDepCompileDefine("WithSubpackagesC") endfunction() function(addAppDepCompileDefine componentName) - if (${componentName} IN_LIST TribitsExProj_SELECTED_PACKAGE_LIST) + if (TARGET ${componentName}::all_libs) string(TOUPPER "${componentName}" componentNameUpper) target_compile_definitions(app PRIVATE TRIBITSEXAPP_HAVE_${componentNameUpper}) endif() endfunction() +# NOTE: Above, we look to see if the 'all_libs' target for a package is +# defined as a way to know if that package is enabled. That will determine if +# the package is enabled even if it is just implicitly enabled and therefore +# is not listed in the list of COMPONENTS passed to find_package(). # Return the extended dependency string from the app at runtime given the @@ -140,9 +146,19 @@ function(getExpectedAppDepsStr expectedDepsStrOut) endif() set(simpleCxxDeps "${simpleCxxDeps}headeronlytpl") + set(withSubpackagesADeps "SimpleCxx ${simpleCxxDeps}") + set(withSubpackagesBDeps "A ${withSubpackagesADeps} SimpleCxx ${simpleCxxDeps}") + set(withSubpackagesCDeps "B ${withSubpackagesBDeps} A ${withSubpackagesADeps}") + set(depsStr "") - appendExpectedAppDepsStr("WithSubpackages" - "WithSubpackages:B A ${simpleCxxDeps} ${simpleCxxDeps}" + appendExpectedAppDepsStr("WithSubpackagesC" + "WithSubpackagesC:${withSubpackagesCDeps}" + depsStr) + appendExpectedAppDepsStr("WithSubpackagesB" + "WithSubpackagesB:${withSubpackagesBDeps}" + depsStr) + appendExpectedAppDepsStr("WithSubpackagesA" + "WithSubpackagesA:${withSubpackagesADeps}" depsStr) appendExpectedAppDepsStr("MixedLang" "MixedLang:Mixed Language" depsStr) appendExpectedAppDepsStr("SimpleCxx" "SimpleCxx:${simpleCxxDeps}" depsStr) @@ -155,7 +171,7 @@ 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 (TARGET ${componentName}::all_libs) if (depsStr) set(depsStr "${depsStr}[;] ${str}") else() diff --git a/cmake/tribits/examples/TribitsExampleApp/app.cpp b/cmake/tribits/examples/TribitsExampleApp/app.cpp index 0b80b645af1a..95ffc43b0629 100644 --- a/cmake/tribits/examples/TribitsExampleApp/app.cpp +++ b/cmake/tribits/examples/TribitsExampleApp/app.cpp @@ -4,7 +4,13 @@ #ifdef TRIBITSEXAPP_HAVE_MIXEDLANG # include "MixedLang.hpp" #endif -#ifdef TRIBITSEXAPP_HAVE_WITHSUBPACKAGES +#ifdef TRIBITSEXAPP_HAVE_WITHSUBPACKAGESA +# include "A.hpp" +#endif +#ifdef TRIBITSEXAPP_HAVE_WITHSUBPACKAGESB +# include "B.hpp" +#endif +#ifdef TRIBITSEXAPP_HAVE_WITHSUBPACKAGESC # include "wsp_c/C.hpp" #endif @@ -27,11 +33,17 @@ void appendDepsStr(std::string &depsStr, const std::string &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()); +#ifdef TRIBITSEXAPP_HAVE_WITHSUBPACKAGESC + appendDepsStr(depsStr, "WithSubpackagesC:"+WithSubpackages::depsC()); +#endif +#ifdef TRIBITSEXAPP_HAVE_WITHSUBPACKAGESB + appendDepsStr(depsStr, "WithSubpackagesB:"+WithSubpackages::depsB()); +#endif +#ifdef TRIBITSEXAPP_HAVE_WITHSUBPACKAGESA + appendDepsStr(depsStr, "WithSubpackagesA:"+WithSubpackages::depsA()); #endif #ifdef TRIBITSEXAPP_HAVE_MIXEDLANG - appendDepsStr(depsStr, "MixedLang:"+tribits_mixed::mixedLang()); + appendDepsStr(depsStr, "MixedLang:"+tribits_mixed::mixedLang()); // Just print something #endif #ifdef TRIBITSEXAPP_HAVE_SIMPLECXX appendDepsStr(depsStr, "SimpleCxx:"+SimpleCxx::deps()); diff --git a/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/CMakeLists.txt index e2fee0772254..d9e5c1c2bd1a 100644 --- a/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/CMakeLists.txt @@ -20,7 +20,17 @@ tribits_add_show_deprecated_warnings_option() # add_subdirectory(src) tribits_add_test_directories(test) -#tribits_add_example_directories(example) + +# Set a variable that will be used in downstream packages + +if (SimpleCxx_ENABLE_SimpleTpl) + set(simpletplText "simpletpl ") +else() + set(simpletplText) +endif() + +global_set(EXPECTED_SIMPLECXX_AND_DEPS + "SimpleCxx ${simpletplText}headeronlytpl") # # E) Do standard post processing diff --git a/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/a/A.cpp b/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/a/A.cpp index 0b877fee7aeb..f9db8c90a125 100644 --- a/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/a/A.cpp +++ b/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/a/A.cpp @@ -7,5 +7,5 @@ std::string WithSubpackages::getA() { } std::string WithSubpackages::depsA() { - return SimpleCxx::deps(); + return "SimpleCxx "+SimpleCxx::deps(); } 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 6627657c232a..788b93eac65d 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: headeronlytpl" + "A deps are: ${EXPECTED_SIMPLECXX_AND_DEPS}" ) diff --git a/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/b/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/b/CMakeLists.txt index 97cd22ded39d..e5d729ca07c1 100644 --- a/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/b/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/b/CMakeLists.txt @@ -2,6 +2,27 @@ tribits_subpackage(B) add_subdirectory(src) +# Set variables that will be used in this package and downstream packages + +if (${PROJECT_NAME}_ENABLE_InsertedPkg) + global_set(EXPECTED_INSERTEDPKG_AND_DEPS "InsertedPkg ${EXPECTED_SIMPLECXX_AND_DEPS}") + global_set(EXPECTED_INSERTEDPKG_AND_DEPS_STR "${EXPECTED_INSERTEDPKG_AND_DEPS} ") +else() + global_set(EXPECTED_INSERTEDPKG_DEPS "") + global_set(EXPECTED_INSERTEDPKG_DEPS_STR "") +endif() + +if (${PROJECT_NAME}_ENABLE_WithSubpackagesA) + global_set(EXPECTED_A_AND_DEPS "A ${EXPECTED_SIMPLECXX_AND_DEPS}") + global_set(EXPECTED_A_AND_DEPS_STR "${EXPECTED_A_AND_DEPS} ") +else() + global_set(EXPECTED_A_AND_DEPS "") + global_set(EXPECTED_A_AND_DEPS_STR "") +endif() + +global_set(EXPECTED_B_DEPS + "${EXPECTED_A_AND_DEPS_STR}${EXPECTED_INSERTEDPKG_AND_DEPS_STR}${EXPECTED_SIMPLECXX_AND_DEPS}") + tribits_add_test_directories(tests) install( DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/stuff" diff --git a/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/b/src/B.cpp b/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/b/src/B.cpp index 31e39859f4ab..5b5f7f8b3473 100644 --- a/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/b/src/B.cpp +++ b/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/b/src/B.cpp @@ -24,6 +24,6 @@ std::string WithSubpackages::depsB() { #ifdef HAVE_WITHSUBPACKAGESB_INSERTEDPKG B_deps += (std::string("InsertedPkg ") + InsertedPkg::deps() + std::string(" ")); #endif - B_deps += SimpleCxx::deps(); + B_deps += (std::string("SimpleCxx ") + SimpleCxx::deps()); return B_deps; } 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 29695d02f28c..ddf51a21cd49 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 @@ -22,22 +22,12 @@ add_subdirectory(testlib) # Test b_test # -set(EXPECTED_B_DEPS) -assert_defined(${PACKAGE_NAME}_ENABLE_WithSubpackagesA) -if(${PACKAGE_NAME}_ENABLE_WithSubpackagesA) - set(EXPECTED_B_DEPS "${EXPECTED_B_DEPS} A headeronlytpl") -endif() -if(${PACKAGE_NAME}_ENABLE_InsertedPkg) - set(EXPECTED_B_DEPS "${EXPECTED_B_DEPS} InsertedPkg headeronlytpl") -endif() -set(EXPECTED_B_DEPS "${EXPECTED_B_DEPS} headeronlytpl") - tribits_add_advanced_test( test_of_b OVERALL_NUM_MPI_PROCS 1 TEST_0 EXEC b_test PASS_REGULAR_EXPRESSION_ALL "B label is: B" - "B deps are:${EXPECTED_B_DEPS}" + "B deps are: ${EXPECTED_B_DEPS}" ADDED_TEST_NAME_OUT test_of_b_TEST_NAME ) diff --git a/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/c/C.cpp b/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/c/C.cpp index 2267f691fe58..524e976093ee 100644 --- a/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/c/C.cpp +++ b/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/c/C.cpp @@ -9,5 +9,5 @@ std::string WithSubpackages::getC() std::string WithSubpackages::depsC() { - return std::string("B ") + depsB(); + return std::string("B ") + depsB() + std::string(" A ") + depsA(); } diff --git a/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/c/c_util.cpp b/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/c/c_util.cpp index 739e6f787698..5c8f4a47a996 100644 --- a/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/c/c_util.cpp +++ b/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/c/c_util.cpp @@ -6,8 +6,8 @@ int main() { std::cout - << "Called c_util: " - << WithSubpackages::depsB() << " " + << "Called c_util: B " + << WithSubpackages::depsB() << " A " << WithSubpackages::depsA() << "\n"; return 0; 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 724ccc130c13..2e6c2634aa5a 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,14 +1,10 @@ -if(WithSubpackagesB_ENABLE_InsertedPkg) - set(EXPECTED_EXTERNALPKG_DEPS "InsertedPkg headeronlytpl ") -endif() - tribits_add_test( c_util NOEXEPREFIX NOEXESUFFIX DIRECTORY ../ NAME test_of_c_util NUM_MPI_PROCS 1 PASS_REGULAR_EXPRESSION - "Called c_util: A headeronlytpl ${EXPECTED_EXTERNALPKG_DEPS}headeronlytpl headeronlytpl" + "Called c_util: B ${EXPECTED_B_DEPS} ${EXPECTED_A_AND_DEPS}" ADDED_TESTS_NAMES_OUT c_util_TEST_NAME ) @@ -59,7 +55,7 @@ if (WithSubpackagesB_ENABLE_MixedLang AND TESTONLYLIBS c_b_mixed_lang NUM_MPI_PROCS 1 PASS_REGULAR_EXPRESSION - "B A headeronlytpl headeronlytpl B Mixed Language" + "B ${EXPECTED_B_DEPS} ${EXPECTED_A_AND_DEPS} 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 c92492464ec7..c24397019d36 100644 --- a/cmake/tribits/examples/TribitsExampleProject/packages/wrap_external/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleProject/packages/wrap_external/CMakeLists.txt @@ -159,7 +159,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 headeronlytpl" + PASS_REGULAR_EXPRESSION "external_func A ${EXPECTED_SIMPLECXX_AND_DEPS}" NUM_MPI_PROCS 1 ) From ab5f8fb7d9f5045528d594fdf93b9be66654a8e6 Mon Sep 17 00:00:00 2001 From: "Roscoe A. Bartlett" Date: Thu, 20 Jan 2022 08:23:50 -0700 Subject: [PATCH 02/37] Automatic snapshot commit from tribits at b2f309b Origin repo remote tracking branch: 'github/master' Origin repo remote repo URL: 'github = git@github.com:TriBITSPub/TriBITS.git' At commit: commit b2f309b5f8422c737c2f06542582986a7a833beb Author: Roscoe A. Bartlett Date: Wed Jan 19 10:51:16 2022 -0700 Summary: Add back deprecated non-namespaced library targets (#299) --- .../TribitsPackageConfigTemplate.cmake.in | 26 +++++++ ...ribitsExternalPackageWriteConfigFile.cmake | 2 +- .../package_arch/TribitsPackageMacros.cmake | 2 + .../TribitsWriteClientExportFiles.cmake | 12 ++++ .../TribitsOldSimpleExampleApp/CMakeLists.txt | 69 +++++++++++++++++++ .../TribitsOldSimpleExampleApp/README.md | 31 +++++++++ .../TribitsOldSimpleExampleApp/app.cpp | 33 +++++++++ .../TribitsOldSimpleExampleApp/util.cpp | 10 +++ .../TribitsSimpleExampleApp/CMakeLists.txt | 10 ++- 9 files changed, 193 insertions(+), 2 deletions(-) create mode 100644 cmake/tribits/examples/TribitsOldSimpleExampleApp/CMakeLists.txt create mode 100644 cmake/tribits/examples/TribitsOldSimpleExampleApp/README.md create mode 100644 cmake/tribits/examples/TribitsOldSimpleExampleApp/app.cpp create mode 100644 cmake/tribits/examples/TribitsOldSimpleExampleApp/util.cpp diff --git a/cmake/tribits/core/installation/TribitsPackageConfigTemplate.cmake.in b/cmake/tribits/core/installation/TribitsPackageConfigTemplate.cmake.in index b85fd96ea97f..396f904628e8 100644 --- a/cmake/tribits/core/installation/TribitsPackageConfigTemplate.cmake.in +++ b/cmake/tribits/core/installation/TribitsPackageConfigTemplate.cmake.in @@ -136,3 +136,29 @@ set(${EXPORT_FILE_VAR_PREFIX}_PACKAGE_LIST "${FULL_PACKAGE_SET}") set(${EXPORT_FILE_VAR_PREFIX}_TPL_LIST "${ORDERED_FULL_TPL_SET}") ${PACKAGE_CONFIG_CODE} + +## ---------------------------------------------------------------------------- +## Create deprecated non-namespaced library targets for backwards compatibility +## ---------------------------------------------------------------------------- + +set(${EXPORT_FILE_VAR_PREFIX}_EXPORTED_PACKAGE_LIBS_NAMES "${EXPORTED_PACKAGE_LIBS_NAMES}") + +foreach(libname IN LISTS ${EXPORT_FILE_VAR_PREFIX}_EXPORTED_PACKAGE_LIBS_NAMES) + if (NOT TARGET ${PDOLLAR}{libname}) + add_library(${PDOLLAR}{libname} INTERFACE IMPORTED) + target_link_libraries(${PDOLLAR}{libname} + INTERFACE ${PACKAGE_NAME}::${PDOLLAR}{libname}) + set(deprecationMessage + "WARNING: The non-namespaced target '${PDOLLAR}{libname}' is deprecated!" + " If always using newer versions of the project '${PROJECT_NAME}', then use the" + " new namespaced target '${PACKAGE_NAME}::${PDOLLAR}{libname}', or better yet," + " '${PACKAGE_NAME}::all_libs' to be less sensitive to changes in the definition" + " of targets in the package '${PACKAGE_NAME}'. Or, to maintain compatibility with" + " older or newer versions the project '${PROJECT_NAME}', instead link against the" + " libraries specified by the variable '${PACKAGE_NAME}_LIBRARIES'." + ) + string(REPLACE ";" "" deprecationMessage "${PDOLLAR}{deprecationMessage}") + set_target_properties(${PDOLLAR}{libname} + PROPERTIES DEPRECATION "${PDOLLAR}{deprecationMessage}" ) + endif() +endforeach() diff --git a/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake b/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake index 3de401327c94..0d4114d37a05 100644 --- a/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake +++ b/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake @@ -295,7 +295,7 @@ function(tribits_external_package_process_libraries_list tplName) elseif (libEntryType STREQUAL "LIB_DIR_LINK_OPTION") list(APPEND libLinkFlagsList "${libentry}") elseif (libEntryType STREQUAL "GENERAL_LINK_OPTION") - message_wrapper("NOTE: Moving the general link argument '${libentry}' in TPL_${tplName}_LIBRARIES forward on the link line which may change the link and break the link!") + message_wrapper("-- NOTE: Moving the general link argument '${libentry}' in TPL_${tplName}_LIBRARIES forward on the link line which may change the link and break the link!") list(APPEND libLinkFlagsList "${libentry}") else() tribits_external_package_process_libraries_list_library_entry( diff --git a/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake b/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake index 419a09160924..49398672fe71 100644 --- a/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake @@ -728,6 +728,8 @@ macro(tribits_package_create_all_libs_interface_library) endif() endforeach() #print_var(packageLibsInAllLibsList) + global_set(${PACKAGE_NAME}_EXPORTED_PACKAGE_LIBS_NAMES + ${packageLibsInAllLibsList}) # Create the ${PACKAGE_NAME}_all_libs INTERFACE interface target add_library(${PACKAGE_NAME}_all_libs INTERFACE) diff --git a/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake b/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake index 89703bb3dbf9..eaf01fa739de 100644 --- a/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake +++ b/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake @@ -413,12 +413,18 @@ function(tribits_generate_package_config_file_for_build_tree packageName) # Replace " by \". string(REGEX REPLACE "\"" "\\\\\"" CMAKE_CXX_FLAGS_ESCAPED ${CMAKE_CXX_FLAGS}) endif() + + # Used in configured file below + set(EXPORTED_PACKAGE_LIBS_NAMES ${${packageName}_EXPORTED_PACKAGE_LIBS_NAMES}) + set(PDOLLAR "$") + set(tribitsConfigFilesDir "${${PROJECT_NAME}_TRIBITS_DIR}/${TRIBITS_CMAKE_INSTALLATION_FILES_DIR}") configure_file( "${tribitsConfigFilesDir}/TribitsPackageConfigTemplate.cmake.in" "${PARSE_PACKAGE_CONFIG_FOR_BUILD_BASE_DIR}/${packageName}Config.cmake" ) + endif() endfunction() @@ -492,6 +498,10 @@ function(tribits_generate_package_config_file_for_install_tree packageName) tribits_set_compiler_vars_for_config_file(INSTALL_DIR) + # Used in configure file below + set(EXPORTED_PACKAGE_LIBS_NAMES ${${packageName}_EXPORTED_PACKAGE_LIBS_NAMES}) + set(PDOLLAR "$") + if (PARSE_PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR) configure_file( "${${PROJECT_NAME}_TRIBITS_DIR}/${TRIBITS_CMAKE_INSTALLATION_FILES_DIR}/TribitsPackageConfigTemplate.cmake.in" @@ -875,6 +885,8 @@ include(\"${${TRIBITS_PACKAGE}_BINARY_DIR}/${TRIBITS_PACKAGE}Config.cmake\")") # Custom code in configuration file. set(PROJECT_CONFIG_CODE "") + set(PDOLLAR "$") # Hack used in configure file below + configure_file( "${${PROJECT_NAME}_TRIBITS_DIR}/${TRIBITS_CMAKE_INSTALLATION_FILES_DIR}/TribitsProjectConfigTemplate.cmake.in" "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config_install.cmake" diff --git a/cmake/tribits/examples/TribitsOldSimpleExampleApp/CMakeLists.txt b/cmake/tribits/examples/TribitsOldSimpleExampleApp/CMakeLists.txt new file mode 100644 index 000000000000..466f812d597f --- /dev/null +++ b/cmake/tribits/examples/TribitsOldSimpleExampleApp/CMakeLists.txt @@ -0,0 +1,69 @@ +cmake_minimum_required(VERSION 3.17.1) + +project(TribitsOldSimpleExApp + DESCRIPTION + "Example raw CMake project using packages installed from new or old 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 a utility and link to libraries from SimpleCxx package +add_executable(util util.cpp) +if (${PROJECT_NAME}_USE_DEPRECATED_TARGETS) + target_link_libraries(util PRIVATE pws_b) + # NOTE: Above will generate a DEPRECATION warning for newer TriBITS + # versions! +else() + target_link_libraries(util PRIVATE ${WithSubpackagesB_LIBRARIES}) + # NOTE: Above is the correct way to link against libraries from an + # individual package for old and new TriBITS! +endif() +target_include_directories(util + PRIVATE ${SimpleCxx_INCLUDE_DIRS} ${SimpleCxx_TPL_INCLUDE_DIRS}) + +# Build the APP and link to libraries from TribitsExProj packages +add_executable(app app.cpp) +target_link_libraries(app + PRIVATE ${TribitsExProj_LIBRARIES}) +target_include_directories(app + PRIVATE ${TribitsExProj_INCLUDE_DIRS} ${TribitsExProj_TPL_INCLUDE_DIRS}) + +# Set up tests + +enable_testing() + +if ("SimpleTpl" IN_LIST TribitsExProj_TPL_LIST) + set(simpleCxxDeps "simpletpl headeronlytpl") +else() + set(simpleCxxDeps "headeronlytpl") +endif() + +add_test(util_test util) +set_tests_properties(util_test PROPERTIES + PASS_REGULAR_EXPRESSION "Util Deps: B A SimpleCxx ${simpleCxxDeps} SimpleCxx ${simpleCxxDeps}" + ) + +add_test(app_test app) +set_tests_properties(app_test PROPERTIES + PASS_REGULAR_EXPRESSION "Full Deps: WithSubpackages:B A SimpleCxx ${simpleCxxDeps} SimpleCxx ${simpleCxxDeps} A SimpleCxx ${simpleCxxDeps}[;] MixedLang:Mixed Language[;] SimpleCxx:${simpleCxxDeps}" + ) diff --git a/cmake/tribits/examples/TribitsOldSimpleExampleApp/README.md b/cmake/tribits/examples/TribitsOldSimpleExampleApp/README.md new file mode 100644 index 000000000000..f728c497ba13 --- /dev/null +++ b/cmake/tribits/examples/TribitsOldSimpleExampleApp/README.md @@ -0,0 +1,31 @@ +# TribitsOldSimpleExampleApp + +Simple example project `TribitsOldSimpleExampleApp` is a raw CMake project +that pulls in libraries from a few packages from `TribitsExampleProject` using +just `find_package(TribitsExProj REQUIRED COMPONENTS ...)` but uses the old +specification for using an installed TriBITS project (i.e. through CMake +variables `_LIBRARIES`, `_INCLUDE_DIRS`, and +`_TPL_INCLUDE_DIRS`). + +After building and installing TribitsExampleProject under +``, then configure, build, and test +`TribitsSimpleExampleApp` with: + +``` + cmake \ + -DCMAKE_PREFIX_PATH= \ + /TribitsOldSimpleExampleApp + + make + + ctest +``` + +This project can be instructed to use the old deprecated targets by adding the +CMake cache var: + +``` + -D TribitsOldSimpleExApp_USE_DEPRECATED_TARGETS=ON +``` + +This will generated deprecated warnings with newer versions of TriBITS. diff --git a/cmake/tribits/examples/TribitsOldSimpleExampleApp/app.cpp b/cmake/tribits/examples/TribitsOldSimpleExampleApp/app.cpp new file mode 100644 index 000000000000..3c0b31f55cf4 --- /dev/null +++ b/cmake/tribits/examples/TribitsOldSimpleExampleApp/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/TribitsOldSimpleExampleApp/util.cpp b/cmake/tribits/examples/TribitsOldSimpleExampleApp/util.cpp new file mode 100644 index 000000000000..98cc11feb698 --- /dev/null +++ b/cmake/tribits/examples/TribitsOldSimpleExampleApp/util.cpp @@ -0,0 +1,10 @@ +#include "B.hpp" + +#include +#include + +int main(int argc, char *argv[]) { + std::string depsStr = WithSubpackages::getB()+" "+WithSubpackages::depsB(); + std::cout << "Util Deps: " << depsStr << "\n"; + return 0; +} diff --git a/cmake/tribits/examples/TribitsSimpleExampleApp/CMakeLists.txt b/cmake/tribits/examples/TribitsSimpleExampleApp/CMakeLists.txt index 45285967f003..a7ee999501ef 100644 --- a/cmake/tribits/examples/TribitsSimpleExampleApp/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsSimpleExampleApp/CMakeLists.txt @@ -35,7 +35,15 @@ target_link_libraries(app PRIVATE TribitsExProj::all_selected_libs) enable_testing() +if ("SimpleTpl" IN_LIST TribitsExProj_TPL_LIST) + set(simpleCxxDeps "simpletpl headeronlytpl") +else() + set(simpleCxxDeps "headeronlytpl") +endif() + +add_test(app_test app) + 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" + PASS_REGULAR_EXPRESSION "Full Deps: WithSubpackages:B A SimpleCxx ${simpleCxxDeps} SimpleCxx ${simpleCxxDeps} A SimpleCxx ${simpleCxxDeps}[;] MixedLang:Mixed Language[;] SimpleCxx:${simpleCxxDeps}" ) From a4254081c5647d2d5eb6ed640901d333f730ded9 Mon Sep 17 00:00:00 2001 From: "Roscoe A. Bartlett" Date: Mon, 7 Mar 2022 08:28:33 -0700 Subject: [PATCH 03/37] Automatic snapshot commit from tribits at 10d02daa Origin repo remote tracking branch: 'github/master' Origin repo remote repo URL: 'github = git@github.com:TriBITSPub/TriBITS.git' Git describe: Vera4.0-RC1-start-1031-ga72c0d52 At commit: commit 10d02daafd114235864cd25c594a6cd93d13d39b Author: Roscoe A. Bartlett Date: Fri Mar 4 15:12:12 2022 -0700 Summary: Fix typos and other improvements (#443) --- cmake/tribits/CHANGELOG.md | 341 +++++++++++++++ cmake/tribits/ReleaseNotes.txt | 318 -------------- ...ribitsExternalPackageWriteConfigFile.cmake | 10 +- .../package_arch/TribitsGlobalMacros.cmake | 12 + .../package_arch/TribitsLibraryMacros.cmake | 8 +- .../package_arch/TribitsPackageMacros.cmake | 3 + .../TribitsPackageSetupCompilerFlags.cmake | 78 ++-- .../TribitsSubPackageMacros.cmake | 52 ++- .../tribits/devtools_install/install-cmake.py | 19 +- .../build_ref/TribitsBuildReferenceBody.rst | 160 +++++-- .../guides/Makefile.common_generated_files | 1 + .../guides/TribitsCoreDetailedReference.rst | 36 +- .../examples/TribitsExampleApp/README.md | 6 +- .../examples/TribitsExampleProject/README.md | 45 +- .../with_subpackages/b/CMakeLists.txt | 2 +- .../TribitsOldSimpleExampleApp/CMakeLists.txt | 6 +- .../TribitsOldSimpleExampleApp/README.md | 25 +- .../TribitsSimpleExampleApp/CMakeLists.txt | 11 +- .../TribitsSimpleExampleApp/README.md | 15 +- .../examples/TribitsSimpleExampleApp/util.cpp | 10 + cmake/tribits/python_utils/SnapshotDir.py | 408 ++++++++++++------ 21 files changed, 974 insertions(+), 592 deletions(-) create mode 100644 cmake/tribits/CHANGELOG.md delete mode 100644 cmake/tribits/ReleaseNotes.txt create mode 100644 cmake/tribits/examples/TribitsSimpleExampleApp/util.cpp diff --git a/cmake/tribits/CHANGELOG.md b/cmake/tribits/CHANGELOG.md new file mode 100644 index 000000000000..4ba2a69d3c8a --- /dev/null +++ b/cmake/tribits/CHANGELOG.md @@ -0,0 +1,341 @@ +---------------------------------------- +ChangeLog for TriBITS +---------------------------------------- + +## 2022-03-02: + +* **Added:** The project-level cache variable `_IMPORTED_NO_SYSTEM` + was added to set the `IMPORTED_NO_SYSTEM` property (CMake versions 3.23+ + only) on the IMPORTED library targets in the installed + `Config.cmake` files (see updated TriBITS users guide and build + reference documentation for `_IMPORTED_NO_SYSTEM`). Setting this + to `ON` results in the include directories for this project's IMPORTED + library targets to be listed on the compile lines in downstream CMake + projects using `-I` instead of the default `-isystem` for IMPORTED library + targets. Setting this option to `ON` returns backward compatibility for the + move to modern CMake targets which involved setting the include directories + on the IMPORTED library targets using `target_include_directories()` + described below (which changed the include directories from being listed as + `-I` to `-isystem` by default).
**Workaround:** As a workaround for + CMake versions less than 3.23, downstream CMake projects can set + `CMAKE_NO_SYSTEM_FROM_IMPORTED=TRUE` in their CMake configure as described + below.
For more details, see + [TriBITSPub/TriBITS#443](https://github.com/TriBITSPub/TriBITS/issues/443). + +## 2021-11-18: + +* **Changed:** The default `_GENERATE_REPO_VERSION_FILE_DEFAULT` will + be overridden to `OFF` if the 'git' executable cannot be found at configure + time. See updated TriBITS Developer's Guide documentation. + +* **Changed:** The default value for `_ENABLE_Fortran` is set to + `OFF` on WIN32 systems. (Getting a Fortran compiler for native Windows is + not typically very easy.) + +## 2021-10-11 + +* **Changed:** The `Config.cmake` for each enabled package generated + in the build directory tree have been moved from + `/packages//` to + `/cmake_packages//`. (This makes it easy for + `find_package()` to find these files by simply adding the + directory `/cmake_packages` to `CMAKE_PREFIX_PATH` and then + `Config.cmake` for any enabled package will be found automatically + found by CMake.) + +* **Added/Changed:** Added the include directories for each library target + with `target_include_directories()`. This makes the usage of the variables + `_INCLUDE_DIRS`, `_TPL_INCLUDE_DIRS`, + `_INCLUDE_DIRS`, and `_TPL_INCLUDE_DIRS` unnecessary by + downstream CMake projects. (See the changes to the + `TribitsExampleApp/CmakeLists.txt` file that removed calls to + `include_directories()` involving these variables.) However, this change + will also cause downstream CMake projects to pull in include directories as + `SYSTEM` includes (e.g. using `-isystem` instead of `-I`) from IMPORTED + library targets. This changes how these include directories are searched + and could break some fragile build environments that have the same header + file names in multiple include directories searched by the compiler. + Changing to `-isystem` will also silence any regular compiler warnings from + headers found under these include directories.
***Workarounds:*** One + workaround for this is for the downstream CMake project to set the cache + variable `CMAKE_NO_SYSTEM_FROM_IMPORTED=TRUE` which will restore the include + directories for the IMPORTED library targets for the TriBITS project as + non-SYSTEM include directories (i.e. `-I`) but it will also cause all + include directories for all IMPORTED library targets to be non-SYSTEM + (i.e. `-I`) even if they were being handled as SYSTEM include directories + using `-isystem` before. Therefore, that could still break the downstream + project as it might change what header files are found for these other + IMPORTED library targets and may expose many new warnings (which may have + been silenced by their include directories being pulled in using + `-isystem`). The other workaround would be to clean up the list of include + directories or delete some header files in those include directories so that + only the correct header files can be found (regardless of the include + directory search order). For more details, see + [TriBITSPub/TriBITS#443](https://github.com/TriBITSPub/TriBITS/issues/443). + +## 2021-09-13 + +* **Removed:** Support for generation and installation of `Makefile.export.*` + files has been removed along with the cache variable + `_ENABLE_EXPORT_MAKEFILES`. This is to allow the refactoring of + TriBITS to use modern CMake targets that propagate all information and + removing complex dependency tracking information from TriBITS (see + TriBITSPub/TriBITS#63 and TriBITSPub/TriBITS#299). + +## 2021-06-17 + +* **Added:** Added tool `tribits/python_utils/lower_case_cmake.py` and driver + `tribits/refactoring/lower-case-cmake-tree.sh` that can make CMake command + calls lower-case and make macro and function definition names lower case. + This was applied to the entire TriBITS repository (and then minor + modifications to fix a few issues). This should not impact users of TriBITS + but it does change the case of commands in the TriBITS error messages. (See + TriBITSPub/TriBITS#274) + +## 2021-05-15 + +* **Changed/Fixed:** Changed so that all arguments passed to `ctest -S` + command in 'dashboard' target are passed if their value is non-empty instead + of `TRUE`. Also, `CTEST_BUILD_NAME`, `TRIBITS_2ND_CTEST_DROP_SITE` and + `TRIBITS_2ND_CTEST_DROP_LOCATION` can now be set and overridden in the CMake + configure and will get passed to the `ctest -S` command by the 'dashboard' + target. This now allows setting these latter vars to `OFF` or `FALSE` which + allows skipping a submit to a secondary CDash site if the underlying project + is set up to submit to a secondary CDash site by default (see + trilinos/Trilinos#9079). These changes technically break backward + compatibility because now setting some vars in the CMake configure will now + get passed on to `ctest -S` command in the 'dashboard' target and some vars + set in the env when calling 'make dashboard' will now be ignored if they + were set in the CMake cache. But many of these vars are only forwarded to + the ctest -S command in the env if they are set to non-empty in the + configure. So existing processes that set `CTEST_BUILD_NAME` in the env + when running `make dashboard` but not in the CMake configure will still + behave the same (which is why no existing TriBITS tests had to change). For + these reasons, the chance of these changes causing a problem for most users + should be very small and in fact it restores what most people would consider + to be logical and useful behavior. + +## 2021-03-12 + +* **Changed:** Upgrade minimum required CMake version from 3.10 to 3.17. Existing + TriBITS projects that have already upgraded to require CMake 3.17+ should not + notice any major changes due to this change. + +## 2020-11-12 + +* **Changed:** The default for `_ENABLE_EXPLICIT_INSTANTIATION` (ETI) + was changed from `OFF` to `ON`. This was turned on in practice for almost + all users of Trilinos so while this change technically breaks backward + compatibility of TriBITS, in practice, this will likely not impact any + important customers. (And new customers of Trilinos and related TriBITS + projects will enjoy the benefits of ETI by default. See + trilinos/Trilinos#8130.) + +## 2020-10-08 + +* **Changed:** Tests defined with `TRIBITS_ADD_TEST()` and + `TRIBITS_ADD_ADVANCED_TEST()` with `NUM_MPI_PROCS > 1` will now not be + added for non-MPI (`TPL_ENABLE_MPI=OFF`) configurations. Before, the test + would get added and basically ignore the value of `NUM_MPI_PROCS`. This + change together with the change to move to using `add_test(NAME + COMMAND )` mostly restores backward compatibility for projects + using TriBITS. For more details, see trilinos/Trilinos#8110. + +## 2020-09-28 + +* **Changed/Fixed:** Tests defined with `TRIBITS_ADD_TEST()` and + `TRIBITS_ADD_ADVANCED_TEST()` have been updated from using + `add_test( )` to using `add_test(NAME COMMAND + )`. This now causes CMake to error-out if there is more than one + test with the same name in the same directory. Before, CMake would allow + it (but the behavior in that case was undocumented and undefined). For + more details, see trilinos/Trilinos#8110. + +## 2020-06-16 + +* **Added/Deprecated:** The variables `_FORTRAN_COMPILER` and + `_FORTRAN_FLAGS` in the `Config.cmake` files (in the build + dir and the install dir) are deprecated. Please use the new variables + `_Fortran_COMPILER` and `_Fortran_FLAGS`. (Justification: + In raw CMake, the compiler is called 'Fortran', not 'FORTRAN'. Also, the + name 'Fortran' is already used in the `Config.cmake` file.) + +## 2020-04-16 + +* **Changed/Removed:** TriBITS Core: `CMAKE_CXX_STANDARD` is now always set to + at least `11` to enable C++11 support. The `${PROJECT_NAME}_ENABLE_CXX11` + option has been removed, but a variable of the same name is hard-coded to ON + for compatibility. + +* **Changed/Removed:** TriBITS Core: `CMAKE_CXX_FLAGS` will no longer contain + an explicit C++ standard option like `-std=c++11`. TriBITS clients' + dependents using CMake will still compile with support for C++11 language + constructs because libraries come with `INTERFACE_COMPILE_FEATURES` + including `cxx_std_11`. However, those using `Makefile.export.` + files will no longer get a `-std=c++11` flag. + +## 2018-10-10 + +* **Changed:** TriBITS Core: Changed minimum CMake version from 2.8.11 to + 3.10.0. + +## 2017-09-25 + +* **Added:** TriBITS CTest Driver: Added cache and env vars + `CTEST_SUBMIT_RETRY_COUNT` and `CTEST_SUBMIT_RETRY_DELAY` to allow the + number of `ctest_submit()` submit attempts to retry and how long to pause + between retries. Before, these were hard-coded to 25 and 120 respectively, + which means that something like a MySQL insertion error could consume as + much as 50 minutes before moving on! The new defaults are set at 5 retries + with a 3 sec delay (which appear to be the CTest defaults). + +## 2017-09-30 + +* **Added:** TriBITS Core: Added `TEST_ COPY_FILES_TO_TEST_DIR` block for + `TRIBITS_ADD_ADVANCED_TEST()`. This was added in such a way so to avoid + clashing with existing usages of the script (since the new arguments + `SOURCE_DIR` and `DEST_DIR` are only parsed if `COPY_FILES_TO_TEST_DIR` is + listed in the `TEST_ block`. + +## 2017-09-05 + +* **Changed:** TriBITS Core: Un-parsed and otherwise ignored arguments to many + TriBITS functions and macros are now flagged (see developers guide + documentation for `${PROJECT_NAME}_CHECK_FOR_UNPARSED_ARGUMENTS`). The + default value is `WARNING` which results in simply printing a warning but + allow configure to complete. This allows one to see the warnings but for + the project to continue to work as before. But this can be changed to + `SEND_ERROR` or `FATAL_ERROR` that will fail the configure. + +## 2017-06-24 + +* **Added:** TriBITS CTest Driver: Add new all-at-once mode for `ctest -S` + driver scripts using `TRIBITS_CTEST_DRIVER()` by setting the variable + `${PROJECT_NAME}_CTEST_DO_ALL_AT_ONCE=TRUE`. This works with older versions + of CMake/CTest and CDash but, by default, will just return a single glob of + results, not breaking-out results on a package-by-package basis. Therefore, + this is disabled by default and package-by-package mode is used by default. + But if `${PROJECT_NAME}_CTEST_USE_NEW_AAO_FEATURES=TRUE` is set, then + TriBITS will take advantage of new CMake, CTest, and CDash features + (currently on a branch) to display the results on CDash broken down + package-by-package. Once these changes are merged to the CMake/CTest and + CDash 'master' branches, then the default for + `${PROJECT_NAME}_CTEST_USE_NEW_AAO_FEATURES` will be set to `TRUE` + automatically when it detects an updated version of CMake/CTest is present. + In the future, at some point, the TriBITS default for + `${PROJECT_NAME}_CTEST_DO_ALL_AT_ONCE` will change from `FALSE` to `TRUE` + since that is a much more efficient way to drive automated testing. + +## 2017-05-25 + +* **Added/Deprecated:** TriBITS Core: The usage of `PARSE_ARGUMENTS()` has + been deprecated and replaced by `CMAKE_PARSE_ARGUMENTS()` everywhere in + TriBITS. Any call to `PARSE_ARGUMENTS()` will warn users and tell them to + use `CMAKE_PARSE_ARGUMENTS()` instead. + +## 2017-05-17 + +* **Changed:** TriBITS Core: TriBITS now unconditionally sets + `${PROJECT_NAME}_ENABLE_Fortran_DEFAULT` to `ON`. Projects will now need to + put in special logic to set to `OFF` or `ON` for certain platforms. + +## 2017-01-11 + +* **Changed/Fixed:** TriBITS Core: TriBITS now correctly sets the default + value for DART_TESTING_TIMEOUT to 1500 seconds and will scale it by + `_SCALE_TEST_TIMEOUT` even if `DART_TESTING_TIMEOUT` is not + explicitly set. + +## 2016-12-07 + +* **Removed:** TriBITS Core: The long deprecated variable + `${PROJECT_NAME}_ENABLE_SECONDARY_STABLE_CODE` has been removed. Upgrading + existing TriBITS projects just requires a simple string replacement of + `_ENABLE_SECONDARY_STABLE_CODE` with `_ENABLE_SECONDARY_TESTED_CODE` in all + files. Since Trilinos has turned on ST code by default and many other + TriBITS projects don't differentiate between PT and ST code, this change + should not even break those projects, even if they don't update. + +## 2016-11-02 + +* **Added/Changed/Removed:** TriBITS Python Utils: gitdist now accepts + `--dist-repos` and `--dist-not-repos` arguments and requires that the base + repo '.' be explicitly listed in the `.gitdist[.default]` files and in + `--dist-repos`. The arguments `--dist-extra-repos`, + `--dist-not-extra-repos` and `--dist-not-base-repo` are not longer + supported. See `gitdist --help` for more details. + +* **Changed:** TriBITS projects now install with full RPATH set by default + (see "Setting install RPATH" in build reference guide). + +## 2016-10-22 + +* **Changed:** TriBITS Core: `TRIBITS_ADD_TEST()` argument for + `FAIL_REGULAR_EXPRESSION` now works when circular RCP detection is enabled. + This is technically a break in backward compatibility since now that + argument will not be ignored and any tests that specified this may change + behavior. + +* **Changed:** TriBITS Core: `TRIBITS_ADD_ADVANCED_TEST()` block `TEST_` + argument `FAIL_REGULAR_EXPRESSION` now works. Before, it was just being + ignored. This is technically a break in backward compatibility since now + that argument will not be ignored and any tests that specified this may + change behavior. + +* **Added/Changed:** TriBITS Core: Added `TRIBITS_ADD_ADVANCED_TEST()` block + `TEST_` option `WILL_FAIL` that has the same behavior as the built-in + CTest option `WILL_FAIL`. Note that this technically can break backward + compatibility since `WILL_FAIL` may have been interpreted to be a value from + another argument and now will not. + +## 2016-01-22 + +* **Added/Deprecated:** TriBITS Core: Change test category `WEEKLY` to `HEAVY` + and depreciate `WEEKLY`. You can still use `WEEKLY` but it will result in a + lot of warnings. + +## 2015-12-03 + +* **Added:** TriBITS CI Support: `checkin-test.py`: Added support for tracking + branches for each repo independently and not assume 'origin' and not assume + that all of the repos are on the same branch or will be pulling and pushing + to the same remote branch. This will make it easier to use the + `checkin-test.py` script to set up various integration scenarios. See + TriBITSPub/TriBITS#15 for details. + +## 2015-04-14 + +* MAJOR: TriBITS Core: When configuring with + ${PROJECT_NAME}_ENABLE_CXX11=ON, if C++11 support cannot be verified, then + the configure will fail hard right away. Before, TriBITS would disable + C++11 support and continue. + +## 2014-11-22 + +* **Added:** TriBITS Core: Added `${PROJECT_NAME}_TRACE_ADD_TEST`: Now you can + print a single line to STDOUT if a test got added (and its important + properties) or not and if not then why the test did not get added. + +## 2014-09-22 + +* **Changed:** TriBITS Core: Changed minimum version of CMake from 2.7 to + 2.8.11. + +## 2014-09-21 + +* **Added:** TriBITS Dashboard Driver: Added support for the env var + `TRIBITS_TDD_USE_SYSTEM_CTEST` so that if equal to `1`, then the TriBITS + Dashboard Driver (TDD) system will use the CTest (and CMake) in the env will + be used instead of being downloaded using `download-cmake.py`. This not + only speeds up the automated builds, but it also ensures that the automated + testing uses exactly the install of CMake/CTest that is used by the + developers on the system. Also, it has been found that `download-cmake.py` + will download and install a 32bit version even on 64bit machines. + + diff --git a/cmake/tribits/ReleaseNotes.txt b/cmake/tribits/ReleaseNotes.txt deleted file mode 100644 index 86e4ad4f14c9..000000000000 --- a/cmake/tribits/ReleaseNotes.txt +++ /dev/null @@ -1,318 +0,0 @@ ----------------------------------------- -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 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. - -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 information 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 - tribits/refactoring/lower-case-cmake-tree.sh that can make CMake command - calls lower-case and make macro and function definition names lowe case. - This was applied to the entire TriBITS repository (and then minor - modifications for fix a few issues). This should not impact users of - TriBITS but it does change the case of commands in the TriBITS error - messages. (See TriBITSPub/TriBITS#274) - -2021/05/15: - -(*) MAJOR: Changed so that all arguments passed to ctest -S command in - 'dashboard' target are passed if their value is non-empty instead of TRUE. - Also, CTEST_BUILD_NAME, TRIBITS_2ND_CTEST_DROP_SITE and - TRIBITS_2ND_CTEST_DROP_LOCATION can now be set and overridden in the CMake - configure and will get passed to the ctest -S command by the 'dashboard' - target. This now allows setting these latter vars to 'OFF' or 'FALSE' - which allows skipping a submit to a secondary CDash site if the underlying - project is set up to submit to a secondary CDash site by default (see - trilinos/Trilinos#9079). These changes technically break backward - compatibility because now setting some vars in the CMake configure will - now get passed on to ctest -S command in the 'dashboard' target and some - vars set in the env when calling 'make dashboard' will now be ignored if - they were set in the CMake cache. But many of these vars are only - forwarded to the ctest -S command in the env if they are set to non-empty - in the configure. So existing processes that set CTEST_BUILD_NAME in the - env when running 'make dashboard' but not in the CMake configure will - still behave the same (which is why no existing TriBITS tests had to - change). For these reasons, the chance of these changes causing a problem - for most users should be very small and in fact it restores what most - people would consider to be logical and useful behavior. - -2021/03/12: - -(*) MAJOR: Upgrade minimum required CMake version from 3.10 to 3.17. Existing - TriBITS projects that have already upgraded to require CMake 3.17+ should not - notice any major changes due to this change. - -2020/11/12: - -(*) MAJOR: The default for `_ENABLE_EXPLICIT_INSTANTIATION` (ETI) was - changed from `OFF` to `ON`. This was turned on in practice for almost all - users of Trilinos so while this change technically breaks backward - compatibility of TriBITS, in practice, this will likely not impact any - important customers. (And new customers of Trilinos and related TriBITS - projects will enjoy the benefits of ETI by default. See - trilinos/Trilinos#8130.) - -2020/10/08: - -(*) MAJOR: Tests defined with `TRIBITS_ADD_TEST()` and - `TRIBITS_ADD_ADVANCED_TEST()` with `NUM_MPI_PROCS > 1` will now not be - added for non-MPI TPL_ENABLE_MPI=OFF configurations. Before, the test - would get added and basically ignore the value of `NUM_MPI_PROCS`. This - change together with the change to move to using `add_test(NAME - COMMAND )` mostly restores backward compatibility for projects - using TriBITS. For more details, see trilinos/Trilinos#8110. - -2020/09/28: - -(*) MAJOR: Tests defined with `TRIBITS_ADD_TEST()` and - `TRIBITS_ADD_ADVANCED_TEST()` have been updated from using - `add_test( )` to using `add_test(NAME COMMAND - )`. This now causes CMake to error out if there is more than one - test with the same name in the same directory. Before, CMake would allow - it (but the behavior in that case was undocumented and undefined). For - more details, see trilinos/Trilinos#8110. - -2020/06/16: - -(*) MINOR: The variables _FORTRAN_COMPILER and - _FORTRAN_FLAGS in the Config.cmake files (in the build - dir and the install dir) are deprecated. Please use the new variables - _Fortran_COMPILER and _Fortran_FLAGS. (Justification: - In raw CMake, the compiler is called 'Fortran', not 'FORTRAN'. Also, the - name 'Fortran' is already used in the Config.cmake file.) - -2020/04/16: - -(*) MAJOR: TriBITS Core: CMAKE_CXX_STANDARD is now always set to at least 11 - to enable C++11 support. The ${PROJECT_NAME}_ENABLE_CXX11 option has been - removed, but a variable of the same name is hard-coded to ON for - compatibility. - -(*) MAJOR: TriBITS Core: CMAKE_CXX_FLAGS will no longer contain an explicit - C++ standard option like '-std=c++11'. TriBITS clients' dependents - using CMake will still compile with support for C++11 language constructs - because libraries come with INTERFACE_COMPILE_FEATURES including cxx_std_11. - However, those using Makefile.export. files will no longer get - a '-std=c++11` flag from TriBITS. - -2018/10/10: - -(*) MAJOR: TriBITS Core: Changed minimum CMake version from 2.8.11 to 3.10.0. - -2017/09/25: - -(*) MINOR: TriBITS CTest Driver: Added cache and env vars - CTEST_SUBMIT_RETRY_COUNT and CTEST_SUBMIT_RETRY_DELAY to allow the number - of ctest_submit() submit attempts to retry and how how log to pause - between retries. Before, these were hard-coded to 25 and 120 - respectively, which means that something like a MySQL insertion error - could consume as much as 50 minutes before moving on! The new defaults are - set at 5 retries with a 3 sec delay (which appear to be the CTest - defaults). - -2017/09/30: - -(*) MINOR: TriBITS Core: Added TEST_ COPY_FILES_TO_TEST_DIR block for - TRIBITS_ADD_ADVANCED_TEST(). This was added in such a way so to avoid - clashing with existing usages of the script (since the new arguments - SOURCE_DIR and DEST_DIR are only parsed if COPY_FILES_TO_TEST_DIR is - listed in the TEST_ block. - -2017/09/05: - -(*) MINOR: TriBITS Core: Un-parsed and otherwise ignored arguments are now - flagged (see developers guide documentation for - ${PROJECT_NAME}_CHECK_FOR_UNPARSED_ARGUMENTS). The default value is - 'WARNING' which results in simply printing a warning but allow configure - to complete. This allows one to see the warnings but for the project to - continue to work as before. But this can be changed to 'SEND_ERROR' or - 'FATAL_ERROR' that will fail the configure. - -2017/06/24: - -(*) MINOR: TriBITS CTest Driver: Add new all-at-once more for CTest -S driver - scripts using TRIBITS_CTEST_DRIVER() by setting the variable - ${PROJECT_NAME}_CTEST_DO_ALL_AT_ONCE=TRUE. This works with older versions - of CMake/CTest and CDash but, by default, will just return a single glob - of results, not breaking results out package-by-package. Therefore, this - is disabled by default and package-by-package mode is used by default. - But if ${PROJECT_NAME}_CTEST_USE_NEW_AAO_FEATURES=TRUE is set, then - TriBITS will take advantage of new CMake, CTest, and CDash features - (currently on a branch) to display the results on CDash broken down - package-by-package. Once these changes are merged to the CMake/CTest and - CDash 'master' branches, then the default for - ${PROJECT_NAME}_CTEST_USE_NEW_AAO_FEATURES will be set to TRUE - automatically when it detects an updated version of CMake/CTest is - present. In the future, at some point, the TriBITS default for - ${PROJECT_NAME}_CTEST_DO_ALL_AT_ONCE will change from FALSE to TRUE since - that is a much more efficient way to drive automated testing. - -2017/05/25: - -(*) MINOR: TriBITS Core: PARSE_ARGUMENTS() has been deprecated and replaced by - CMAKE_PARSE_ARGUMENTS() everywhere in TriBITS. Any call to - PARSE_ARGUMENTS() will warn users and tell them to use - CMAKE_PARSE_ARGUMENTS() instead. - -2017/05/17: - -(*) MAJOR: TriBITS Core: TriBITS now unconditionally sets - ${PROJECT_NAME}_ENABLE_Fortran_DEFAULT to ON. Projects will now need to - put in special logic to set to OFF or ON for certain platforms. - -2017/01/11: - -(*) MINOR: TriBITS Core: TriBITS now correctly sets the default value for - DART_TESTING_TIMEOUT to 1500 seconds and will scale it by - _SCALE_TEST_TIMEOUT even if DART_TESTING_TIMEOUT is not - explicitly set. - -2016/12/07: - -(*) MAJOR: TriBITS Core: The long deprecated variable - ${PROJECT_NAME}_ENABLE_SECONDARY_STABLE_CODE has been removed. Upgrading - existing TriBITS projects just requires a simple string replacement of - _ENABLE_SECONDARY_STABLE_CODE with _ENABLE_SECONDARY_TESTED_CODE in all - files. Since Trilinos has turned on ST code by default and many other - TriBITS projects don't differentiate between PT and ST code, this change - should not even break those projects, even if they don't update. - -2016/11/02: - -(*) MAJOR: TriBITS Python Utils: gitdist now accepts --dist-repos and - --dist-not-repos arguments and requires that the base repo '.' be - explicitly listed in the .gitdist[.default] files and in --dist-repos. - The arguments --dist-extra-repos, --dist-not-extra-repos and - --dist-not-base-repo are not longer supported. See gitdist --help for - more details. - -(*) MINOR: TriBITS projects now install with full RPATH set by default (see - "Setting install RPATH" in build reference guide). - -2016/10/22: - -(*) MAJOR: TriBITS Core: TRIBITS_ADD_TEST() argument FAIL_REGULAR_EXPRESSION - now works when circular RCP detection is enabled. This is technically a - break in backward compatibility since now that argument will not be - ignored and any tests that specified this may change behavior. - -(*) MAJOR: TriBITS Core: TRIBITS_ADD_ADVANCED_TEST() TEST_ argument - FAIL_REGULAR_EXPRESSION now works. Before, it was just being ignored. - This is technically a break in backward compatibility since now that - argument will not be ignored and any tests that specified this may change - behavior. - -(*) MINOR: TriBITS Core: Added TRIBITS_ADD_ADVANCED_TEST() TEST_ option - WILL_FAIL that has the same behavior as the built-in CTest option - WILL_FAIL. - -2016/01/22: - -(*) MINOR: TriBITS Core: Change test category WEEKLY to HEAVY and depreciate - WEEKLY. You can still use WEEKLY but it will result in a lot of warnings. - -2015/12/03: - -(*) MINOR: TriBITS CI Support: checkin-test.py: Added support for tracking - branches for each repo independently and not assume 'origin' and not - assume that all of the repos are on the same branch or will be pulling and - pushing to the same remote branch. This will make it easier to use the - checkin-test.py script to set up various integration scenarios. See - TriBITS GitHub Issue #15 for details. - -2015/04/14: - -(*) MAJOR: TriBITS Core: When configuring with - ${PROJECT_NAME}_ENABLE_CXX11=ON, if C++11 support cannot be verified, then - the configure will fail hard right away. Before, TriBITS would disable - C++11 support and continue. - -2014/11/22: - -(*) MINOR: TriBITS Core: Added ${PROJECT_NAME}_TRACE_ADD_TEST: Now you can a - single line print if a test got added (and its important properties if it - did) or not and if not then why the test did not get added. - -2014/09/22: - -(*) MAJOR: TriBITS Core: Changed minimum version of CMake from 2.7 to 2.8.11. - -2014/09/21: - -(*) MINOR: TriBITS Dashboard Driver: Added support for the env var - TRIBITS_TDD_USE_SYSTEM_CTEST so that if equal to 1, then the TriBITS - Dashboard Driver (TDD) system will use the CTest (and CMake) in the env - will be used instead of being downloaded using download-cmake.py. This - not only speeds up the automated builds, but it also ensures that the - automated testing uses exactly the install of CMake/CTest that is used by - the developers on the system. Also, it has been found that - download-cmake.py will download and install a 32bit version even on 64bit - machines. - -Trilinos 11.7: --------------- - -(*) MINOR: TriBITS Core: Switched from the terms Primary Stable (PS) and - Secondary Stable (SS) code to Primary Tested (PT) and Secondary Tested - (ST) according to the plan in the TriBITS Life-cycle model. Using 'PS' and - 'SS' is still allowed but is deprecated. This also included deprecating - the variable _ENABLE_SECONDARY_STABLE_CODE and replacing it with - _ENABLE_SECONDARY_TEST_CODE. Again, backward compatibility is - preserved. Also, the checkin-test.py arg --ss-extra-builds is deprecated - and replaced with --st-extra-builds. - - -Trilinos 11.6: --------------- - -(*) MAJOR: TriBITS Core: Changed behavior of _ENABLE_=ON to - enable all subpackages for that package including in propagating forward - dependencies. See updated BuildQuickRef.* document. - - -Trilinos 11.3: --------------- - -(*) MINOR: TriBITS Core: Added ENVIRONMENT env1=val1 env2=val2 ... argument to - TRIBITS_ADD_TEST(), TRIBITS_ADD_ADVANCED_TEST(), and - TRIBITS_ADD_EXECUTABLE_AND_TEST(). - -(*) MINOR: TriBITS Core: Fixed the generation of headers for explicit - instantiation system for subpackages: Now subpackages that use the macro - TRIBITS_CREATE_CLIENT_TEMPLATE_HEADERS() to generate XXX.hpp header files - with or without explicit instantiation will key off of the parent package's - explicit instantiation setting. In addition, packages that use the macro - TRIBITS_CREATE_CLIENT_TEMPLATE_HEADERS() will also need to add a call to - TRIBITS_ADD_EXPLICIT_INSTANTIATION_OPTION() in their top-level - CMakeLists.txt file. - - diff --git a/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake b/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake index 0d4114d37a05..8d9270b0f61a 100644 --- a/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake +++ b/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake @@ -162,7 +162,7 @@ endfunction() # @FUNCTION: tribits_external_package_write_config_file_str() # -# Create the text strig for a ``Config.cmake`` file given the list of +# Create the text string for a ``Config.cmake`` file given the list of # include directories and libraries for an external package/TPL. # # Usage:: @@ -177,10 +177,10 @@ endfunction() # ````: Name of variable that will contain the string # for the config file on output. # -# This function reads from the varaibles ``TPL__INCLUDE_DIRS`` and +# This function reads from the variables ``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 +# is returned as a string variable that contains IMPORTED targets to # represent these libraries and include directories. # # ToDo: Flesh out more documentation for behavior as more features are added @@ -249,10 +249,10 @@ endfunction() # the list of IMPORTED library targets generated from this list. # # ````: [Out] Name of list variable that will be set -# with the list of ``-L`` library directoy paths. +# with the list of ``-L`` library directory paths. # # ````: [Inout] A string variable that will be -# appended with the IMPORTED library commands for the list of targts given +# appended with the IMPORTED library commands for the list of targets given # in ````. # function(tribits_external_package_process_libraries_list tplName) diff --git a/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake b/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake index 5ae79c5fc18d..019dfd15fb0d 100644 --- a/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake @@ -535,6 +535,18 @@ macro(tribits_define_global_options_and_define_extra_repos) CACHE BOOL "If set TRUE, then 'SYSTEM' will be passed into include_directories() for TPL includes.") + if ("${${PROJECT_NAME}_IMPORTED_NO_SYSTEM_DEFAULT}" STREQUAL "") + set(${PROJECT_NAME}_IMPORTED_NO_SYSTEM_DEFAULT FALSE) + endif() + advanced_set(${PROJECT_NAME}_IMPORTED_NO_SYSTEM + ${${PROJECT_NAME}_IMPORTED_NO_SYSTEM_DEFAULT} + CACHE BOOL + "If set TRUE, then set IMPORTED_NO_SYSTEM proeprty on all exported libraries.") + + if (CMAKE_VERSION VERSION_LESS 3.23 AND ${PROJECT_NAME}_IMPORTED_NO_SYSTEM) + message(FATAL_ERROR "Error, setting ${PROJECT_NAME}_IMPORTED_NO_SYSTEM='${${PROJECT_NAME}_IMPORTED_NO_SYSTEM}' for CMake version '${CMAKE_VERSION}' < 3.23 is not allowed!") + endif() + advanced_set(TPL_FIND_SHARED_LIBS ON CACHE BOOL "If ON, then the TPL system will find shared libs if they exist, otherwise will only find static libs." ) diff --git a/cmake/tribits/core/package_arch/TribitsLibraryMacros.cmake b/cmake/tribits/core/package_arch/TribitsLibraryMacros.cmake index 85cbe018437a..360c879b0b57 100644 --- a/cmake/tribits/core/package_arch/TribitsLibraryMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsLibraryMacros.cmake @@ -988,12 +988,14 @@ function(tribits_add_library LIBRARY_NAME_IN) # 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}) + # Optionally Set IMPORTED_NO_SYSTEM + if (${PROJECT_NAME}_IMPORTED_NO_SYSTEM) + set_target_properties(${LIBRARY_NAME} PROPERTIES IMPORTED_NO_SYSTEM TRUE) + endif() + endif() #if not in installation testing mode # diff --git a/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake b/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake index 49398672fe71..481a7a87be5d 100644 --- a/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake @@ -737,6 +737,9 @@ macro(tribits_package_create_all_libs_interface_library) INTERFACE ${packageLibsInAllLibsList} ) set_target_properties(${PACKAGE_NAME}_all_libs PROPERTIES EXPORT_NAME all_libs) + if (${PROJECT_NAME}_IMPORTED_NO_SYSTEM) + set_target_properties(${PACKAGE_NAME}_all_libs PROPERTIES IMPORTED_NO_SYSTEM TRUE) + endif() # Install the interface target (makes sure it gets put in # Targets.cmake file) diff --git a/cmake/tribits/core/package_arch/TribitsPackageSetupCompilerFlags.cmake b/cmake/tribits/core/package_arch/TribitsPackageSetupCompilerFlags.cmake index 8646b83e04cf..18a9d6e17124 100644 --- a/cmake/tribits/core/package_arch/TribitsPackageSetupCompilerFlags.cmake +++ b/cmake/tribits/core/package_arch/TribitsPackageSetupCompilerFlags.cmake @@ -58,9 +58,9 @@ macro(tribits_apply_warnings_as_error_flags_lang LANG) endmacro() -macro(tribits_set_package_language_flags LANG) +macro(tribits_set_package_compiler_lang_flags LANG) - #message("Entering tribits_set_package_language_flags(${LANG})") + #message("Entering tribits_set_package_compiler_lang_flags(${LANG})") #print_var(${PROJECT_NAME}_ENABLE_STRONG_${LANG}_COMPILE_WARNINGS) if (${PACKAGE_NAME}_${LANG}_FLAGS) @@ -68,65 +68,77 @@ macro(tribits_set_package_language_flags LANG) "${${PACKAGE_NAME}_${LANG}_FLAGS}") endif() - if(${PROJECT_NAME}_VERBOSE_CONFIGURE) - message(STATUS "Adding strong ${LANG} warning flags \"${${LANG}_STRONG_COMPILE_WARNING_FLAGS}\"") - print_var(CMAKE_${LANG}_FLAGS) - endif() - endmacro() -function(tribits_setup_add_package_compile_flags) +function(tribits_print_package_compiler_lang_flags LANG SUFFIX) + message("-- " "${PACKAGE_NAME}: CMAKE_${LANG}_FLAGS${SUFFIX}=\"${CMAKE_${LANG}_FLAGS${SUFFIX}}\"") +endfunction() + - #message("Entering tribits_setup_add_package_compile_flags()") +# Function that appends package-specific compiler flags for each language +# +function(tribits_append_package_specific_compiler_flags) - # - # C compiler options - # + #message("Entering tribits_append_package_specific_compiler_flags() for ${PACKAGE_NAME}") + # C compiler options assert_defined(${PROJECT_NAME}_ENABLE_C CMAKE_C_COMPILER_ID) if (${PROJECT_NAME}_ENABLE_C) - tribits_set_package_language_flags(C) + tribits_set_package_compiler_lang_flags(C) endif() - # # C++ compiler options - # - assert_defined(${PROJECT_NAME}_ENABLE_CXX CMAKE_CXX_COMPILER_ID) if (${PROJECT_NAME}_ENABLE_CXX) - tribits_set_package_language_flags(CXX) + tribits_set_package_compiler_lang_flags(CXX) endif() - # # Fortran compiler options - # - assert_defined(${PROJECT_NAME}_ENABLE_Fortran) if (${PROJECT_NAME}_ENABLE_Fortran) - tribits_set_package_language_flags(Fortran) + tribits_set_package_compiler_lang_flags(Fortran) endif() endfunction() +# Function that prints out all of the compiler flags for a package +# +function(tribits_print_package_compiler_flags) + if(${PROJECT_NAME}_VERBOSE_CONFIGURE OR ${PROJECT_NAME}_PRINT_PACKAGE_COMPILER_FLAGS) + string(TOUPPER "${CMAKE_BUILD_TYPE}" upperBuildType) + set(buildNameSuffix "_${upperBuildType}") + # C compiler options + if (${PROJECT_NAME}_ENABLE_C) + tribits_print_package_compiler_lang_flags(C "") + tribits_print_package_compiler_lang_flags(C ${buildNameSuffix}) + endif() + # C++ compiler options + if (${PROJECT_NAME}_ENABLE_CXX) + tribits_print_package_compiler_lang_flags(CXX "") + tribits_print_package_compiler_lang_flags(CXX ${buildNameSuffix}) + endif() + # Fortran compiler options + if (${PROJECT_NAME}_ENABLE_Fortran) + tribits_print_package_compiler_lang_flags(Fortran "") + tribits_print_package_compiler_lang_flags(Fortran ${buildNameSuffix}) + endif() + endif() +endfunction() - - -# -# Macro that sets up compiler flags for a package +# Macro that sets up compiler flags for a top-level package (not subpackage) # # This CMake code is broken out in order to allow it to be unit tested. # - macro(tribits_setup_compiler_flags PACKAGE_NAME_IN) # Set up strong warning flags @@ -149,17 +161,11 @@ macro(tribits_setup_compiler_flags PACKAGE_NAME_IN) tribits_apply_warnings_as_error_flags_lang(CXX) endif() - # Append package specific options - tribits_setup_add_package_compile_flags() + tribits_append_package_specific_compiler_flags() - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("Final compiler flags:") - print_var(CMAKE_CXX_FLAGS) - print_var(CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}) - print_var(CMAKE_C_FLAGS) - print_var(CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE}) - print_var(CMAKE_Fortran_FLAGS) - print_var(CMAKE_Fortran_FLAGS_${CMAKE_BUILD_TYPE}) + if(${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("Final package compiler flags:") endif() + tribits_print_package_compiler_flags() endmacro() diff --git a/cmake/tribits/core/package_arch/TribitsSubPackageMacros.cmake b/cmake/tribits/core/package_arch/TribitsSubPackageMacros.cmake index ad270c9d7aed..60a7c668e9a5 100644 --- a/cmake/tribits/core/package_arch/TribitsSubPackageMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsSubPackageMacros.cmake @@ -41,7 +41,6 @@ include(TribitsPackageMacros) include(TribitsReportInvalidTribitsUsage) -# # @MACRO: tribits_subpackage() # # Forward declare a `TriBITS Subpackage`_ called at the top of the @@ -78,18 +77,42 @@ macro(tribits_subpackage SUBPACKAGE_NAME_IN) message("\nSUBPACKAGE: ${SUBPACKAGE_NAME_IN}") endif() + tribits_subpackage_assert_call_context() + + # To provide context for various macros + set(PACKAGE_NAME ${SUBPACKAGE_FULLNAME}) + + set(PARENT_PACKAGE_SOURCE_DIR "${PACKAGE_SOURCE_DIR}") + set(PARENT_PACKAGE_BINARY_DIR "${PACKAGE_BINARY_DIR}") + + # Now override the package-like variables + tribits_set_common_vars(${SUBPACKAGE_FULLNAME}) + tribits_define_linkage_vars(${SUBPACKAGE_FULLNAME}) + + tribits_append_package_specific_compiler_flags() + if(${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("Final subpackage compiler flags:") + endif() + tribits_print_package_compiler_flags() + + # Set flags that are used to check that macros are called in the correct order + set(${SUBPACKAGE_FULLNAME}_TRIBITS_SUBPACKAGE_CALLED TRUE) + set(${SUBPACKAGE_FULLNAME}_TRIBITS_SUBPACKAGE_POSTPROCESS_CALLED FALSE) + +endmacro() + + +function(tribits_subpackage_assert_call_context) + # check that this is not being called from a package if (NOT CURRENTLY_PROCESSING_SUBPACKAGE) - # we are in a package - + # we are in a package tribits_report_invalid_tribits_usage( "Cannot call tribits_subpackage() from a package." " Use tribits_package() instead" " ${CURRENT_PACKAGE_CMAKELIST_FILE}") - else() - # We are in a subpackage - + # We are in a subpackage # check to see if postprocess is called before subpackage if(${SUBPACKAGE_FULLNAME}_TRIBITS_SUBPACKAGE_POSTPROCESS_CALLED) tribits_report_invalid_tribits_usage( @@ -113,25 +136,10 @@ macro(tribits_subpackage SUBPACKAGE_NAME_IN) endif() endif() +endfunction() - # To provide context for various macros - set(PACKAGE_NAME ${SUBPACKAGE_FULLNAME}) - - set(PARENT_PACKAGE_SOURCE_DIR "${PACKAGE_SOURCE_DIR}") - set(PARENT_PACKAGE_BINARY_DIR "${PACKAGE_BINARY_DIR}") - - # Now override the package-like variables - tribits_set_common_vars(${SUBPACKAGE_FULLNAME}) - tribits_define_linkage_vars(${SUBPACKAGE_FULLNAME}) - - # Set flags that are used to check that macros are called in the correct order - set(${SUBPACKAGE_FULLNAME}_TRIBITS_SUBPACKAGE_CALLED TRUE) - set(${SUBPACKAGE_FULLNAME}_TRIBITS_SUBPACKAGE_POSTPROCESS_CALLED FALSE) - -endmacro() -# # @MACRO: tribits_subpackage_postprocess() # # Macro that performs standard post-processing after defining a `TriBITS diff --git a/cmake/tribits/devtools_install/install-cmake.py b/cmake/tribits/devtools_install/install-cmake.py index b9240c20cc68..5b5b48ea76bf 100755 --- a/cmake/tribits/devtools_install/install-cmake.py +++ b/cmake/tribits/devtools_install/install-cmake.py @@ -108,7 +108,24 @@ def getExtraHelpStr(self, version): If CMake 3.17 is selected, a patch is applied which adds the CTEST_RESOURCE_SPEC_FILE variable. (For versions 3.18+ this is not needed.) -""" + +NOTE: To install CMake from the tip of a branch such as 'master', one must +override the 'download' command and eliminate the 'untar' command. One must +stick with the directory structure that is assumed by the underlying code +which creates temp directories based in the CMake version. For example, to +cone and install the tip of the CMake 'master' branch one can run: + + install-cmake.py \\ + --install-dir=__FLAGS="" + -D __FLAGS="" -The package-specific options get appended to those already in +The package-specific options get appended **after** those already in ``CMAKE__FLAGS`` and therefore override (but not replace) those set -globally in ``CMAKE__FLAGS`` (either internally or by the user in the -cache). +globally in ``CMAKE__FLAGS`` (either internally in the CMakeLists.txt +files or by the user in the cache). + +In addition, flags can be targeted to a specific TriBITS subpackage using the +same syntax:: + + -D __FLAGS="" + +If top-level package-specific flags and subpackage-specific flags are both set +for the same parent package such as with:: + + -D SomePackage__FLAGS="" \ + -D SomePackageSpkgA__FLAGS="" \ + +then the flags for the subpackage ``SomePackageSpkgA`` will be listed after +those for its parent package ``SomePackage`` on the compiler command-line as:: + + + +That way, compiler options for a subpackage override flags set for the parent +package. NOTES: -1) Setting ``CMAKE__FLAGS`` will override but will not replace any -other internally set flags in ``CMAKE__FLAGS`` defined by the - CMake system because these flags will come after those set -internally. To get rid of these project/TriBITS default flags, see below. +1) Setting ``CMAKE__FLAGS`` as a cache varible by the user on input be +listed after and therefore override, but will not replace, any internally set +flags in ``CMAKE__FLAGS`` defined by the CMake system. To get +rid of these project/TriBITS set compiler flags/options, see the below items. 2) Given that CMake passes in flags in ``CMAKE__FLAGS_`` after those in @@ -830,30 +849,6 @@ internally by CMake and the new variable is needed to make the override explicit. -Appending arbitrary libraries and link flags every executable -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -In order to append any set of arbitrary libraries and link flags to your -executables use:: - - -D_EXTRA_LINK_FLAGS="" \ - -DCMAKE_EXE_LINKER_FLAGS="" - -Above, you can pass any type of library and they will always be the last -libraries listed, even after all of the TPLs. - -NOTE: This is how you must set extra libraries like Fortran libraries and -MPI libraries (when using raw compilers). Please only use this variable -as a last resort. - -NOTE: You must only pass in libraries in ``_EXTRA_LINK_FLAGS`` and -*not* arbitrary linker flags. To pass in extra linker flags that are not -libraries, use the built-in CMake variable ``CMAKE_EXE_LINKER_FLAGS`` -instead. The TriBITS variable ``_EXTRA_LINK_FLAGS`` is badly named -in this respect but the name remains due to backward compatibility -requirements. - - Turning off strong warnings for individual packages +++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -934,8 +929,51 @@ To get the compiler to add debug symbols to the build, configure with:: -D _ENABLE_DEBUG_SYMBOLS=ON -This will add ``-g`` on most compilers. NOTE: One does **not** generally -need to create a fully debug build to get debug symbols on most compilers. +This will add ``-g`` on most compilers. NOTE: One does **not** generally need +to create a full debug build to get debug symbols on most compilers. + + +Printing out compiler flags for each package +++++++++++++++++++++++++++++++++++++++++++++ + +To print out the exact ``CMAKE__FLAGS`` that will be used for each +package, set:: + + -D _PRINT_PACKAGE_COMPILER_FLAGS=ON + +That will print lines in STDOUT that are formatted as:: + + : CMAKE__FLAGS="" + : CMAKE__FLAGS_="" + +This will print the value of the ``CMAKE__FLAGS`` and +``CMAKE__FLAGS_`` variables that are used as each package is +being processed and will contain the flags in the exact order they are applied +by CMake + + +Appending arbitrary libraries and link flags every executable ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +In order to append any set of arbitrary libraries and link flags to your +executables use:: + + -D_EXTRA_LINK_FLAGS="" \ + -DCMAKE_EXE_LINKER_FLAGS="" + +Above, you can pass any type of library and they will always be the last +libraries listed, even after all of the TPLs. + +NOTE: This is how you must set extra libraries like Fortran libraries and +MPI libraries (when using raw compilers). Please only use this variable +as a last resort. + +NOTE: You must only pass in libraries in ``_EXTRA_LINK_FLAGS`` and +*not* arbitrary linker flags. To pass in extra linker flags that are not +libraries, use the built-in CMake variable ``CMAKE_EXE_LINKER_FLAGS`` +instead. The TriBITS variable ``_EXTRA_LINK_FLAGS`` is badly named +in this respect but the name remains due to backward compatibility +requirements. Enabling support for Ninja @@ -1363,6 +1401,52 @@ search for extra required libraries (such as the mpi library and the gfortran library for gnu compilers) to locate static versions. +Changing include directories in downstream CMake projects to non-system +----------------------------------------------------------------------- + +By default, include directories from IMPORTED library targets from the + project's installed ``Config.cmake`` files will be +considered ``SYSTEM`` headers and therefore will be included on the compile +lines of downstream CMake projects with ``-isystem`` with most compilers. +However, when using CMake 3.23+, by configuring with:: + + -D _IMPORTED_NO_SYSTEM=ON + +then all of the IMPORTED library targets in the set of installed +``Config.cmake`` files will have the ``IMPORTED_NO_SYSTEM`` target +property set. This will cause downstream customer CMake projects to apply the +include directories from these IMPORTED library targets as non-SYSTEM include +directories. On most compilers, that means that the include directories will +be listed on the compile lines with ``-I`` instead of with ``-isystem`` (for +compilers that support the ``-isystem`` option). (Changing from ``-isystem +`` to ``-I `` moves ```` forward in the +compiler's include directory search order and could also result in the found +header files emitting compiler warnings that would other otherwise be silenced +when the headers were found in include directories pulled in with +``-isystem``.) + +**NOTE:** Setting ``_IMPORTED_NO_SYSTEM=ON`` when using a CMake +version less than 3.23 will result in a fatal configure error (so don't do +that). + +**A workaround for CMake versions less than 3.23** is for **downstream +customer CMake projects** to set the native CMake cache variable:: + + -D CMAKE_NO_SYSTEM_FROM_IMPORTED=TRUE + +This will result in **all** include directories from **all** IMPORTED library +targets used in the downstream customer CMake project to be listed on the +compile lines using ``-I`` instead of ``-isystem``, and not just for the +IMPORTED library targets from this project's installed +``Config.cmake`` files! + +**NOTE:** Setting ``CMAKE_NO_SYSTEM_FROM_IMPORTED=TRUE`` in the +CMake configure will **not** result in changing how include directories from +'s IMPORTED targets are handled in a downstream customer CMake +project! It will only change how include directories from upstream package's +IMPORTED targets are handled in the CMake project build itself. + + Enabling the usage of resource files to reduce length of build lines -------------------------------------------------------------------- @@ -3738,10 +3822,10 @@ CMake project's ``CMakeLists.txt`` file as usual using, for example:: 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. +Note that in this case, ``target_link_libraries()`` ensures that the include +directories and other imported compiler options from the source tree and the +build tree are automatically injected into the build targets associated with +the ```` object compile lines and link lines. Also note that package config files for all of the enabled external packages/TPLs will also be written into the build tree under diff --git a/cmake/tribits/doc/guides/Makefile.common_generated_files b/cmake/tribits/doc/guides/Makefile.common_generated_files index 25bcf0b69277..c6a352d1228f 100644 --- a/cmake/tribits/doc/guides/Makefile.common_generated_files +++ b/cmake/tribits/doc/guides/Makefile.common_generated_files @@ -1,6 +1,7 @@ COMMON_DEPENDENT_FILES = \ Makefile \ ../generate-guide.sh \ + ../TribitsCoreDetailedReference.rst \ ../TribitsGuidesBody.rst \ ../TribitsGuidesReferences.rst \ ../TribitsFAQ.rst \ diff --git a/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst b/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst index 38d58b4192f8..3acfef8dcfe2 100644 --- a/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst +++ b/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst @@ -79,6 +79,7 @@ a given TriBITS project are: * `${PROJECT_NAME}_GENERATE_EXPORT_FILE_DEPENDENCIES`_ * `${PROJECT_NAME}_GENERATE_VERSION_DATE_FILES`_ * `${PROJECT_NAME}_GENERATE_REPO_VERSION_FILE`_ +* `${PROJECT_NAME}_IMPORTED_NO_SYSTEM`_ * `${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS`_ * `${PROJECT_NAME}_MAKE_INSTALL_GROUP_READABLE`_ * `${PROJECT_NAME}_MAKE_INSTALL_GROUP_WRITABLE`_ @@ -489,7 +490,40 @@ These options are described below. overridden to ``OFF``. But if the user sets ``${PROJECT_NAME}_GENERATE_REPO_VERSION_FILE=ON`` in the cache and ``git`` can't be found, then an configure-time error will occur. - + + +.. _${PROJECT_NAME}_IMPORTED_NO_SYSTEM: + +**${PROJECT_NAME}_IMPORTED_NO_SYSTEM** + + By default, include directories from IMPORTED library targets from the + TriBITS project's installed ``Config.cmake`` files will be + considered ``SYSTEM`` headers and therefore be included on the compile lines + of downstream CMake projects with ``-isystem`` with most compilers. + However, if ``${PROJECT_NAME}_IMPORTED_NO_SYSTEM`` is set to ``ON`` (only + supported for CMake versions 3.23 or greater), then all of the IMPORTED + library targets exported into the set of installed ``Config.cmake`` + files will have the ``IMPORTED_NO_SYSTEM`` property set. This will cause + downstream customer CMake projects to apply the include directories from + these IMPORTED library targets as non-system include directories. On most + compilers, that means that the include directories will be listed on the + compile lines with ``-I`` instead of with ``-isystem``. (See more details + in the TriBITS Build Reference for ``_IMPORTED_NO_SYSTEM``.) + + The default value set by TriBITS itself is ``OFF`` but a TriBITS project can + change the default value to ``ON`` by adding:: + + if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.23) + set(${PROJECT_NAME}_IMPORTED_NO_SYSTEM_DEFAULT ON) + endif() + + in the `/ProjectName.cmake`_ file. (NOTE: The above ``if()`` + statement ensures that a configure error will not occur if a version of + CMake less than 3.23 is used. But if the TriBITS project minimum CMake + version is 3.23 or greater, then the above ``if()`` statement guard can be + removed.) + + .. _${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS: **${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS** diff --git a/cmake/tribits/examples/TribitsExampleApp/README.md b/cmake/tribits/examples/TribitsExampleApp/README.md index 9d9b99bb0b29..8711450ac960 100644 --- a/cmake/tribits/examples/TribitsExampleApp/README.md +++ b/cmake/tribits/examples/TribitsExampleApp/README.md @@ -1,8 +1,10 @@ # 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, +libraries from packages from `TribitsExampleProject`. If `WithSubpackageC` +subpackage or the `MixedLang` packages are built, then a Fortran compiler +is required to build `TribitsExampleApp`. To build against all of the +installed packages from an upstream `TribitsExampleProject`, configure, build, and run the tests with: ``` diff --git a/cmake/tribits/examples/TribitsExampleProject/README.md b/cmake/tribits/examples/TribitsExampleProject/README.md index 291700dbfb05..ab0b5b42b14f 100644 --- a/cmake/tribits/examples/TribitsExampleProject/README.md +++ b/cmake/tribits/examples/TribitsExampleProject/README.md @@ -1,39 +1,48 @@ # TribitsExampleProject Documentation -The project TribitsExampleProject defines a TriBITS CMake project designed to +The project `TribitsExampleProject` defines a TriBITS CMake project designed to provide a simple example to demonstrate how to use the TriBITS system to create a CMake build, test, and deployment system using a package-based -architecture. +architecture. To build all of the packages from `TribitsExampleProject`, +a Fortran compiler is needed. -To get started building you can create a directory structure like: +To build and test the project, one must first create a build directory and +configure by pointing to the TriBITS source dir `` +(i.e. `TriBITS/tribits`) and the `TribitsExampleProject` project source dir +with: ``` - ~/TribitsExampleProject.base/ - TribitsExampleProject/ # This directory - BUILDS/ - SERIAL/ -``` - -After that configure pointing to some value TriBITS source dir -(i.e. TriBITS/tribits) with: - -``` - cd BUILDS/SERIAL/ - - cmake -D \ + mkdir + + cd + + cmake \ -DTribitsExProj_TRIBITS_DIR= \ + -DCMAKE_INSTALL_PREFIX= -DTribitsExProj_ENABLE_TESTS=ON \ -DTribitsExProj_ENABLE_ALL_PACKAGES=ON + -DTribitsExProj_ENABLE_SECONDARY_TESTED_CODE=ON \ -DCMAKE_CXX_COMPILER=g++ \ - ../../examples/TribitsExampleProject + ``` -and then build and test with: +then build and test with: ``` make -j4 && ctest -j4 ``` +and then install: + +``` + make install +``` + +`TribitsExampleProject` will be installed to +`` and this path should be then used +to point `-DCMAKE_PREFIX_PATH=` when +building e.g. `TribitsExampleApp` + The layout of a TriBITS project is described in: * https://tribits.org/doc/TribitsUsersGuide.html#tribits-project-structure diff --git a/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/b/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/b/CMakeLists.txt index e5d729ca07c1..200d869b1f43 100644 --- a/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/b/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleProject/packages/with_subpackages/b/CMakeLists.txt @@ -26,7 +26,7 @@ global_set(EXPECTED_B_DEPS tribits_add_test_directories(tests) install( DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/stuff" - DESTINATION "${CMAKE_INSTALL_PREFIX}/share/${PACKAGE_NAME}" + DESTINATION "share/${PACKAGE_NAME}" USE_SOURCE_PERMISSIONS PATTERN "*~" EXCLUDE ) # Above, we must use 'USE_SOURCE_PERMISSIONS' to preserve the executable # permission on the scripts in that directory. (TriBITS will add commands to diff --git a/cmake/tribits/examples/TribitsOldSimpleExampleApp/CMakeLists.txt b/cmake/tribits/examples/TribitsOldSimpleExampleApp/CMakeLists.txt index 466f812d597f..0b8d334d5ecb 100644 --- a/cmake/tribits/examples/TribitsOldSimpleExampleApp/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsOldSimpleExampleApp/CMakeLists.txt @@ -27,7 +27,7 @@ if (CMAKE_Fortran_COMPILER) enable_language(Fortran) endif() -# Build a utility and link to libraries from SimpleCxx package +# Build a utility and link to libraries from WithSubpackagesB add_executable(util util.cpp) if (${PROJECT_NAME}_USE_DEPRECATED_TARGETS) target_link_libraries(util PRIVATE pws_b) @@ -58,12 +58,12 @@ else() set(simpleCxxDeps "headeronlytpl") endif() -add_test(util_test util) +add_test(NAME util_test COMMAND util) set_tests_properties(util_test PROPERTIES PASS_REGULAR_EXPRESSION "Util Deps: B A SimpleCxx ${simpleCxxDeps} SimpleCxx ${simpleCxxDeps}" ) -add_test(app_test app) +add_test(NAME app_test COMMAND app) set_tests_properties(app_test PROPERTIES PASS_REGULAR_EXPRESSION "Full Deps: WithSubpackages:B A SimpleCxx ${simpleCxxDeps} SimpleCxx ${simpleCxxDeps} A SimpleCxx ${simpleCxxDeps}[;] MixedLang:Mixed Language[;] SimpleCxx:${simpleCxxDeps}" ) diff --git a/cmake/tribits/examples/TribitsOldSimpleExampleApp/README.md b/cmake/tribits/examples/TribitsOldSimpleExampleApp/README.md index f728c497ba13..7fa355be8f5d 100644 --- a/cmake/tribits/examples/TribitsOldSimpleExampleApp/README.md +++ b/cmake/tribits/examples/TribitsOldSimpleExampleApp/README.md @@ -1,15 +1,16 @@ # TribitsOldSimpleExampleApp -Simple example project `TribitsOldSimpleExampleApp` is a raw CMake project -that pulls in libraries from a few packages from `TribitsExampleProject` using -just `find_package(TribitsExProj REQUIRED COMPONENTS ...)` but uses the old +This simple example project `TribitsOldSimpleExampleApp` is a raw CMake +project that pulls in libraries from a few packages from +[`TribitsExampleProject`](../TribitsExampleProject/README.md) using just +`find_package(TribitsExProj REQUIRED COMPONENTS ...)` but uses the old specification for using an installed TriBITS project (i.e. through CMake variables `_LIBRARIES`, `_INCLUDE_DIRS`, and `_TPL_INCLUDE_DIRS`). After building and installing TribitsExampleProject under ``, then configure, build, and test -`TribitsSimpleExampleApp` with: +`TribitsOldSimpleExampleApp` with: ``` cmake \ @@ -21,11 +22,21 @@ After building and installing TribitsExampleProject under ctest ``` -This project can be instructed to use the old deprecated targets by adding the -CMake cache var: +This project can be instructed to use the non-namespaced old deprecated +targets by adding the CMake cache var: ``` -D TribitsOldSimpleExApp_USE_DEPRECATED_TARGETS=ON ``` -This will generated deprecated warnings with newer versions of TriBITS. +This will generated deprecated warnings with newer versions of TriBITS. (This +is to demonstrate and test these deprecated non-namespaced targets and to +demonstrate how to remove the deprecated warnings in a downstream customer +CMake project.) + +NOTE: The modern version of this project using the modern CMake targets +produced by `TribitsExampleProject` is +[`TribitsSimpleExampleApp`](../TribitsSimpleExampleApp/README.md). Comparing +the `CMakeLists.txt` files in these two projects (e.g. [here](CMakeLists.txt) +and [here](../TribitsSimpleExampleApp/CMakeLists.txt)) demonstrates the +simplifications afforded by the namespaced modern CMake targets. diff --git a/cmake/tribits/examples/TribitsSimpleExampleApp/CMakeLists.txt b/cmake/tribits/examples/TribitsSimpleExampleApp/CMakeLists.txt index a7ee999501ef..425e0717cdde 100644 --- a/cmake/tribits/examples/TribitsSimpleExampleApp/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsSimpleExampleApp/CMakeLists.txt @@ -27,6 +27,10 @@ if (CMAKE_Fortran_COMPILER) enable_language(Fortran) endif() +# Build a utility and link to libraries from WithSubpackagesB +add_executable(util util.cpp) +target_link_libraries(util PRIVATE WithSubpackagesB::all_libs) + # Build the APP and link to libraries from TribitsExProj packages add_executable(app app.cpp) target_link_libraries(app PRIVATE TribitsExProj::all_selected_libs) @@ -41,9 +45,12 @@ else() set(simpleCxxDeps "headeronlytpl") endif() -add_test(app_test app) +add_test(NAME util_test COMMAND util) +set_tests_properties(util_test PROPERTIES + PASS_REGULAR_EXPRESSION "Util Deps: B A SimpleCxx ${simpleCxxDeps} SimpleCxx ${simpleCxxDeps}" + ) -add_test(app_test app) +add_test(NAME app_test COMMAND app) set_tests_properties(app_test PROPERTIES PASS_REGULAR_EXPRESSION "Full Deps: WithSubpackages:B A SimpleCxx ${simpleCxxDeps} SimpleCxx ${simpleCxxDeps} A SimpleCxx ${simpleCxxDeps}[;] MixedLang:Mixed Language[;] SimpleCxx:${simpleCxxDeps}" ) diff --git a/cmake/tribits/examples/TribitsSimpleExampleApp/README.md b/cmake/tribits/examples/TribitsSimpleExampleApp/README.md index 4ad96988dd9b..a79255b47b23 100644 --- a/cmake/tribits/examples/TribitsSimpleExampleApp/README.md +++ b/cmake/tribits/examples/TribitsSimpleExampleApp/README.md @@ -1,10 +1,13 @@ # 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 ...)`. +This simple example project `TribitsSimpleExampleApp` is a raw CMake project +that pulls in libraries from a few packages from +[`TribitsExampleProject`](../TribitsExampleProject/README.md) using just +`find_package(TribitsExProj REQUIRED COMPONENTS ...)` and also links a smaller +program using a subset of the libraries from one of the packages from +`TribitsExampleProject`. -After building and installing TribitsExampleProject under +After building and installing `TribitsExampleProject` under ``, then configure, build, and test `TribitsSimpleExampleApp` with: @@ -17,3 +20,7 @@ After building and installing TribitsExampleProject under ctest ``` + +NOTE: The version of this project that demonstrates using the old interface +using variables that works with much older versions of TriBITS is given in +[`TribitsOldSimpleExampleApp`](../TribitsOldSimpleExampleApp/README.md). diff --git a/cmake/tribits/examples/TribitsSimpleExampleApp/util.cpp b/cmake/tribits/examples/TribitsSimpleExampleApp/util.cpp new file mode 100644 index 000000000000..98cc11feb698 --- /dev/null +++ b/cmake/tribits/examples/TribitsSimpleExampleApp/util.cpp @@ -0,0 +1,10 @@ +#include "B.hpp" + +#include +#include + +int main(int argc, char *argv[]) { + std::string depsStr = WithSubpackages::getB()+" "+WithSubpackages::depsB(); + std::cout << "Util Deps: " << depsStr << "\n"; + return 0; +} diff --git a/cmake/tribits/python_utils/SnapshotDir.py b/cmake/tribits/python_utils/SnapshotDir.py index 1bc84fae1ee0..458adcde460d 100644 --- a/cmake/tribits/python_utils/SnapshotDir.py +++ b/cmake/tribits/python_utils/SnapshotDir.py @@ -64,8 +64,8 @@ def __init__(self): self.destDir = "" def setDefaultDefaults(self): - self.origDir = os.path.abspath(os.path.dirname(sys.argv[0])) + "/" - self.destDir = os.getcwd() + "/" + self.origDir = addTrailingSlashToPath(os.path.abspath(os.path.dirname(sys.argv[0]))) + self.destDir = addTrailingSlashToPath(os.getcwd()) def setDefaultOrigDir(self, origDirIn): self.origDir = origDirIn @@ -85,37 +85,47 @@ def getDefaultDestDir(self): # usageHelp = r""" -This tool snapshots the contents of an origin directory ('orig-dir') to -destination directory ('dest-dir') and creates linkages between the two git -repos in the commit message in the 'dest-dir' git branch. The command 'git' -must be in the path for this script to be used. -To sync between any two arbitrary directories invoking this script from any -directory location, one can do: +This tool uses rsync and some git commands to snapshot the contents of an +origin directory ('orig-dir') in one Git repo to destination directory +('dest-dir') in another Git repo and logs version information in a new Git +commit message. + +WARNING: Because this tool uses 'rsync --delete', it can be quite destructive +to the contents of dest-dir if one is not careful and selects the wrong +orig-dir or wrong dest-dir! Therefore, please carefully read this entire help +message and especially the warnings given below and always start by running +with --no-op! + +To sync between any two arbitrary directories between two different git repos +invoking this script from any directory location, one can do: $ /snapshot-dir.py \ - --orig-dir=/ \ - --dest-dir=/ + --orig-dir= \ + --dest-dir= \ + [--no-op] + +(where --no-op should be used on the initial trial run to check that the +correct rsync and other commands will be run, see below). To describe how this script is used, consider the desire to snapshot the -directory tree: +directory tree from one git repo: /orig-dir/ -and duplicate it in the directory tree +and exactly duplicate it in another git repo under: /dest-dir/ Here, the directories can be any two directories from local git repos with any -names as long as they are given a final '/' at the end. Otherwise, if you are -missing the final '/', then rsync will copy the contents from 'orig-dir' into -a subdir of 'dest-dir' which is usually not what you want. +names. (Note if the paths don't end with '/', then '/' will be added. +Otherwise, rsync will copy the contents from 'orig-dir' into a subdir of +'dest-dir' which is usually not what you want.) A typical case is to have snapshot-dir.py soft linked into orig-dir/ to allow -a simple sync process. This is the case, for example, with the 'tribits' -source tree. The linked-in location of snapshot-dir.py gives the default -'orig-dir' directory automatically (but can be overridden with --orig-dir -option). +a simple sync process. The linked-in location of snapshot-dir.py gives the +default 'orig-dir' directory automatically (but can be overridden with +--orig-dir= option). When snapshot-dir.py is soft-linked into the 'orig-dir' directory base, the way to run this script would be: @@ -128,55 +138,74 @@ def getDefaultDestDir(self): 'orig-dir' is recorded in the commit message of the 'dest-dir' git repo to provide tractability for the versions (see below). -Note the trailing '/' is critical for the correct functioning of rsync. - By default, this script does the following: -1) Assert that the git repo for 'orig-dir' is clean (i.e. no uncommitted - files, no unknown files, etc.). (Can be disabled by passing in - --allow-dirty-orig-dir.) +1) Assert that 'orig-dir' in its git repo is clean (i.e. no uncommitted + files). (Can be disabled by passing in --allow-dirty-orig-dir.) -2) Assert that the git repo for / is clean (see above). (Can -be disabled by passing in --allow-dirty-dest-dir.) +2) Assert that / in its git repo is clean (same checks as for + 'orig-dir' above). (Can be disabled by passing in --allow-dirty-dest-dir. + Also, this must be skipped on the initial snapshot where / + does not exist yet.) 3) Clean out the ignored files from /orig-dir using 'git clean -xdf' run in that directory. (Only if --clean-ignored-files-orig-dir - is specified.) - -4) Run 'rsync -cav --delete' to copy the contents from 'orig-dir' to - 'dest-dir', excluding the '.git/' directory if it exists in either git repo - dir. After this runs, / should be an exact duplicate of - / (except for otherwise noted excluded files). This rsync - will delete any files in 'dest-dir' that are not in 'orig-dir'. Note that - if there are ignored untracked files, then the copied .gitignore files - should avoid showing them as tracked or unknown files in the 'dest-dir' git - repo as well. - -5) Run 'git add .' in / to stage any new files. Note that git - will automatically stage deletes for any files removed by the 'rsync -cav - --delete' command! + is passed.) + +4) Run 'rsync -cav --delete [other options] / /' to copy + the contents from 'orig-dir' to 'dest-dir', excluding the '.git/' directory + if it exists in either git repo dir. After this runs, / should + be an exact duplicate of / (except for otherwise noted excluded + files). This rsync will delete any files in 'dest-dir' that are not in + 'orig-dir'. Note that if there are any ignored untracked files in + 'orig-dir' that get copied over, then the copied .gitignore files should + avoid treating them as tracked files in the 'dest-dir' git repo. (The + rsync command is skipped if the argument --no-op is passed.) + +5) Run 'git add .' in / to stage any files copied over. (Note that + git will automatically stage deletes for any files removed by the 'rsync + -cav --delete' command. Also note that any untracked, unknown or ignored + files in 'orig-dir' that get copied over and are not ignored in 'dist-dir' + in the copied-over '.gitignore' files, or other git ignore files in + 'dist-dir', then they will be added to the new commit in 'dist-dir'.) 6) Get the git remote URL from the orig-dir git repo, and the git log for the - last commit for the directory from orig-dir. This information is used to - define perfect tracing of the version info when doing the snapshot. + last commit for the directory orig-dir from its git repo. (If the orig-dir + repo is on a tracking branch, then this remote will be guaranteed to be + correct. However, if the orig-dir repo not on a tracking branch, then the + first remote returned from 'git remote -v' will be used. This information + is used to provide tractability of the version info back to the originating + git repo in the commit created in the dest-dir repo.) 7) Commit the updated dest-dir directory using a commit message with the - orig-dir repo URL and log info. This will only commit files in 'dest-dir' - and not in other directories in the destination git repo! + orig-dir snapshot version info. (This will only commit files in 'dest-dir' + and not in other directories in the destination git repo!) (The 'git + commit' will be skipped if the options --skip-commit or --no-op are + passed.) NOTES: +* When first running this tool, use the --no-op option to see what commands + would be run without actually performing any mutable operations. Especially + pay attention to the rsync command that would be run and make sure it is + operating on the desired directories. + +* On the first creation of /, one must pass in + --allow-dirty-dest-dir to avoid checks of / (because it does not yet + exist). + * This script allows the syncing between base git repos or subdirs within git repos. This is allowed because the rsync command is told to ignore the .git/ directory when syncing. -* The cleaning of the orig-dir/ using 'git clean -xdf' may be somewhat - dangerous but it is recommended that it be performed by passing in - --clean-ignored-files-orig-dir to avoid copying locally-ignored files in - orig-dir/ (e.g. ignored in .git/info/excludes but not in a committed - .gitignore file) that get copied to and then committed in the dest-dir/ - repo. Therefore, be sure you don't have any ignored files in orig-dir/ that - you want to keep before you run this script! +* The cleaning of orig-dir/ using 'git clean -xdf' may be somewhat dangerous + but it is recommended by passing in --clean-ignored-files-orig-dir to avoid + copying locally-ignored files in orig-dir/ (e.g. ignored in + .git/info/excludes and not ignored in a committed .gitignore file in + orig-dir/) that get copied to and then committed in the dest-dir/ repo. + Therefore, be sure you don't have any of these type of ignored files in + orig-dir/ that you want to keep before you run this tool with the option + --clean-ignored-files-orig-dir! * Snapshotting with this script will create an exact duplicate of 'orig-dir' in 'dest-dir' and therefore if there are any local changes to the files or @@ -185,14 +214,52 @@ def getDefaultDestDir(self): branch into the main branch (e.g. 'master') in 'dest-dir' repo. As long as there are no merge conflicts, this will preserve local changes for the mirrored directories and files. This strategy can work well as a way to - allow for local modifications but still do the snapshotting.. + allow for local modifications but still do snapshotting. + +WARNINGS: + +* Make sure that orig-dir is a non-ignored subdir of the origin git repo and + that it does not contain any ignored subdirs and files that are ignored by + listing them in the .git/info/exclude file instead of .gitignore files that + would get copied over to dist-dir. (If ignored files are ignored using + .gitignore files within orig-dir, then those files will be copied by the + rsync command along with the rest of the files from orig-dir and those files + will also be ignored after being copied to dest-dir. However, if these + files and dirs are ignored because of being listed in the .git/info/exclude + file in orig-dir, then those files will not be ignored when copied over to + dest-dir and will therefore be added to the git commit in the dist-dir git + repo. That is why it is recommended to run with + --clean-ignored-files-orig-dir to ensure that all ignore files are removed + from orig-dir before doing the rsync.) + +* Make sure that the top commit in orig-dir has been pushed (or will be + pushed) to the listed remote git repo showed in the output line 'origin + remote name' or 'origin remote URL'. Otherwise, others will not be able to + trace that exact version by cloning that repo and traceability is lost. + +* Make sure that dest-dir is a non-ignored subdir of the destination git repo + and does not contain any ignored subdirs or files that you don't care if + they are deleted. (Otherwise, the 'rsync --delete' command will delete any + files in dest-dir that are not also in orig-dir and since these non-ignored + files in dest-dir are not under version control, they will not be + recoverable.) + +* As a corollary to the above warnings about ignored files and directories, do + not snapshot from an orig-dir or to a dest-dir that contain build + directories or other generated files that you want to keep! Even if those + files and directories are ignored in copied-over .gitignore files, the copy + of those ignored files will still occur. (Just another reason to keep your + build directories completely outside of the source tree!) + """ -# # Direct script driver (taking in command-line arguments) # - +# This runs given a set of command-line arguments and a stream to do +# outputting to. This allows running an a unit testing environment very +# efficiently. +# def snapshotDirMainDriver(cmndLineArgs, defaultOptionsIn = None, stdout = None): oldstdout = sys.stdout @@ -229,7 +296,7 @@ def snapshotDirMainDriver(cmndLineArgs, defaultOptionsIn = None, stdout = None): "--orig-dir", dest="origDir", default=defaultOptions.getDefaultOrigDir(), help="Original directory that is the source for the snapshotted directory." \ - +" Note that it is important to add a final /' to the directory name." \ + +" If a trailing '/' is missing then it will be added." \ +" The default is the directory where this script lives (or is soft-linked)." \ +" [default: '"+defaultOptions.getDefaultOrigDir()+"']") @@ -237,7 +304,7 @@ def snapshotDirMainDriver(cmndLineArgs, defaultOptionsIn = None, stdout = None): "--dest-dir", dest="destDir", default=defaultOptions.getDefaultDestDir(), help="Destination directory that is the target for the snapshoted directory." \ - +" Note that a final '/' just be added or the origin will be added as subdir." \ + +" If a trailing '/' is missing then it will be added." \ +" The default dest-dir is current working directory." \ +" [default: '"+defaultOptions.getDefaultDestDir()+"']" \ ) @@ -271,14 +338,6 @@ def snapshotDirMainDriver(cmndLineArgs, defaultOptionsIn = None, stdout = None): "--no-clean-ignored-files-orig-dir", dest="cleanIgnoredFilesOrigDir", action="store_false", help="Do not clean out orig-dir/ ignored files before snapshotting. [default]" ) - clp.add_argument( - "--do-rsync", dest="doRsync", action="store_true", - default=True, - help="Actually do the rsync. [default]" ) - clp.add_argument( - "--skip-rsync", dest="doRsync", action="store_false", - help="Skip the rsync (testing only?)." ) - clp.add_argument( "--do-commit", dest="doCommit", action="store_true", default=True, @@ -286,7 +345,21 @@ def snapshotDirMainDriver(cmndLineArgs, defaultOptionsIn = None, stdout = None): clp.add_argument( "--skip-commit", dest="doCommit", action="store_false", help="Skip the commit." ) - + + clp.add_argument( + "--verify-commit", dest="noVerifyCommit", action="store_false", + default=False, + help="Do not pass --no-verify to git commit. [default]" ) + clp.add_argument( + "--no-verify-commit", dest="noVerifyCommit", action="store_true", + help="Pass --no-verify to git commit." ) + + clp.add_argument( + "--no-op", dest="noOp", action="store_true", + default=False, + help="Don't actaully run any commands that would change the state other" + +" (other than the natural side-effects of running git query commands)" ) + options = clp.parse_args(cmndLineArgs) # @@ -313,14 +386,16 @@ def snapshotDirMainDriver(cmndLineArgs, defaultOptionsIn = None, stdout = None): print(" --clean-ignored-files-orig-dir \\") else: print(" --no-clean-ignored-files-orig-dir \\") - if options.doRsync: - print(" --do-rsync \\") - else: - print(" --skip-rsync \\") if options.doCommit: print(" --do-commit \\") else: print(" --skip-commit \\") + if options.noVerifyCommit: + print(" --no-verify-commit \\") + else: + print(" --verify-commit \\") + if options.noOp: + print(" --no-op \\") if options.showDefaults: return # All done! @@ -342,6 +417,8 @@ def snapshotDirMainDriver(cmndLineArgs, defaultOptionsIn = None, stdout = None): def snapshotDir(inOptions): + addTrailingSlashToPaths(inOptions) + # print("\nA) Assert that orig-dir is 100% clean with all changes committed\n") # @@ -367,59 +444,59 @@ def snapshotDir(inOptions): # if inOptions.cleanIgnoredFilesOrigDir: - cleanIgnoredFilesFromGitDir(inOptions.origDir, "origin") + cleanIgnoredFilesFromGitDir(inOptions.origDir, inOptions.noOp, "origin") else: print("Skipping on request!") # - print("\nD) Get info from git commit from origDir [optional]\n") + print("\nD) Get info for git commit from orig-dir [optional]\n") # # Get the repo for origin (remoteRepoName, remoteBranch, remoteRepoUrl) = \ - getGitRepoUrl(inOptions.origDir) + getGitRepoRemoteNameBranchAndUrl(inOptions.origDir) print("origin remote name = '" + remoteRepoName + "'") print("origin remote branch = '" + remoteBranch + "'") print("origin remote URL = '" + remoteRepoUrl + "'") + gitDescribe = getGitDescribe(inOptions.origDir) + print("Git describe = '" + gitDescribe + "'") # Get the last commit message originLastCommitMsg = getLastCommitMsg(inOptions.origDir) - print("\norigin commit message:\n\n" + originLastCommitMsg + "\n") + print("\norigin commit message:") + print("---------------------------------------") + print(originLastCommitMsg) + print("---------------------------------------") # print("\nE) Run rsync to add and remove files and dirs between two directories\n") # - if inOptions.doRsync: + excludes = r"""--exclude=\.git""" + if inOptions.exclude: + excludes += " " + " ".join(map(lambda ex: "--exclude="+ex, + inOptions.exclude)) + print("Excluding files/directories/globs: " + + " ".join(inOptions.exclude)) + # Note that when syncing one git repo to another, we want to sync the + # .gitingore and other hidden files as well. - excludes = r"""--exclude=\.git""" - if inOptions.exclude: - excludes += " " + " ".join(map(lambda ex: "--exclude="+ex, - inOptions.exclude)) - print("Excluding files/directories/globs: " + - " ".join(inOptions.exclude)) - # Note that when syncing one git repo to another, we want to sync the - # .gitingore and other hidden files as well. - - # When we support syncing from hg repos, add these excludes as well: - # --exclude=\.hg --exclude=.hgignore --exclude=.hgtags - - rtn = echoRunSysCmnd( - r"rsync -cav --delete "+excludes+" "+inOptions.origDir+" "+inOptions.destDir, - throwExcept=False, - timeCmnd=True - ) - + # When we support syncing from hg repos, add these excludes as well: + # --exclude=\.hg --exclude=.hgignore --exclude=.hgtags + + rsyncCmnd = \ + r"rsync -cav --delete "+excludes+" "+inOptions.origDir+" "+inOptions.destDir + + if not inOptions.noOp: + rtn = echoRunSysCmnd(rsyncCmnd, throwExcept=False, timeCmnd=True) if rtn != 0: print("Rsync failed, aborting!") return False - else: - - print("\nSkipping rsync on request!") + print("Would be running: "+rsyncCmnd) # - print("\nE) Create a new commit in destination directory [optional]") + print("\nE) Create a new commit in dest-dir [optional]") # origDirLast = inOptions.origDir.split("/")[-2] @@ -427,35 +504,75 @@ def snapshotDir(inOptions): commitMessage = \ "Automatic snapshot commit from "+origDirLast+" at "+origSha1+"\n"+\ - "\n"+\ - "Origin repo remote tracking branch: '"+remoteRepoName+"/"+remoteBranch+"'\n"+\ - "Origin repo remote repo URL: '"+remoteRepoName+" = "+remoteRepoUrl+"'\n"+\ + "\n" + + if remoteBranch: + commitMessage += \ + "Origin repo remote tracking branch: '"+remoteRepoName+"/"+remoteBranch+"'\n"+\ + "Origin repo remote repo URL: '"+remoteRepoName+" = "+remoteRepoUrl+"'\n" + else: + commitMessage += \ + "Origin repo remote repo URL: '"+remoteRepoName+" = "+remoteRepoUrl+"'\n" + + commitMessage += \ + "Git describe: "+gitDescribe+"\n" +\ "\n"+\ "At commit:\n"+\ "\n"+\ originLastCommitMsg - print("\nGeneratting commit with commit message:\n") - print("---------------------------------------" ) - print(commitMessage ) - print("---------------------------------------" ) + print("\nGenerating commit in dest-dir with commit message:\n") + print("---------------------------------------") + print(commitMessage) + print("---------------------------------------") if inOptions.doCommit: - echoRunSysCmnd( - "git add .", - workingDir=inOptions.destDir - ) - - echoRunSysCmnd( - "git commit -m \""+commitMessage+"\" -- .", - workingDir=inOptions.destDir - ) + gitAddCmnd = "git add ." + if not inOptions.noOp: + echoRunSysCmnd(gitAddCmnd, workingDir=inOptions.destDir) + else: + print("\nWould be running: "+gitAddCmnd+"\n" \ + +"\n in directory '"+inOptions.destDir+"'" ) + + if inOptions.noVerifyCommit: + noVerifyCommitArgStr = " --no-verify" + else: + noVerifyCommitArgStr = "" + + gitCommitCmndBegin = "git commit"+noVerifyCommitArgStr+" -m " + if not inOptions.noOp: + echoRunSysCmnd(gitCommitCmndBegin+"\""+commitMessage+"\"", + workingDir=inOptions.destDir) + else: + print("\nWould be running: "+gitCommitCmndBegin+"\"\"\n" + +"\n in directory '"+inOptions.destDir+"'" ) else: print("\nSkipping commit on request!\n") + if inOptions.noOp: + + print( + "\n***\n" + "*** NOTE: No modifying operations were performed!\n" + "***\n" + "*** Run again removing the option --no-op to make modifying\n" + "*** changes.\n" + "***\n" + "*** But first, carefully look at the orig-dir, dest-dir and the\n" + "*** various operations performed above to make sure that\n" + "*** everything is as it should be before removing the option --no-op.\n" + "***\n" + "*** In particular, look carefully at the 'git clean' and 'rsync' commands\n" + "*** on the lines that begin with 'Would be running:'\n" + "***\n" + "***\n" + "***\n" + "***\n" + ) + # # F) Success! (if you get this far) # @@ -468,6 +585,17 @@ def snapshotDir(inOptions): # +def addTrailingSlashToPath(path): + if path[-1] != "/": + return path + "/" + return path + + +def addTrailingSlashToPaths(options): + options.origDir = addTrailingSlashToPath(options.origDir) + options.destDir = addTrailingSlashToPath(options.destDir) + + def assertCleanGitDir(dirPath, dirName, explanation): changedFiles = getCmndOutput( @@ -489,36 +617,39 @@ def assertCleanGitDir(dirPath, dirName, explanation): # not a huge risk for the use cases that I am concerned with. -def cleanIgnoredFilesFromGitDir(dirPath, dirName): - - rtn = echoRunSysCmnd( - r"git clean -xdf", - workingDir=dirPath, - throwExcept=False, - timeCmnd=True - ) - - if rtn != 0: - raise Exception( - "Error, cleaning of origin `"+dirPath+"` failed!" - ) +def cleanIgnoredFilesFromGitDir(dirPath, noOp, dirName): + gitCleanCmnd = r"git clean -xdf" + if not noOp: + rtn = echoRunSysCmnd(gitCleanCmnd, workingDir=dirPath, + throwExcept=False, timeCmnd=True) + if rtn != 0: + raise Exception( + "Error, cleaning of origin `"+dirPath+"` failed!") + else: + print("Would be running: "+gitCleanCmnd+"\n" \ + +"\n in directory '"+dirPath+"'" ) def getCommitSha1(gitDir): return getCmndOutput("git log -1 --pretty=format:'%h' -- .", workingDir=gitDir).strip() -def getGitRepoUrl(gitDir): +def getGitRepoRemoteNameBranchAndUrl(gitDir): remoteRepoName = "" remoteBranch = "" remoteRepoUrl = "" # Get the remote tracking branch - trackingBranchStr = getCmndOutput( - "git rev-parse --abbrev-ref --symbolic-full-name @{u}", workingDir=gitDir) + (trackingBranchStr, trackingBranchErrCode) = getCmndOutput( + "git rev-parse --abbrev-ref --symbolic-full-name @{u}", workingDir=gitDir, + throwOnError=False, rtnCode=True) - (remoteRepoName, remoteBranch) = trackingBranchStr.strip().split("/") + if trackingBranchErrCode == 0: + (remoteRepoName, remoteBranch) = trackingBranchStr.strip().split("/") + else: + remoteRepoName = "" + remoteBranch = "" # Get the list of remote repos remoteReposListStr = getCmndOutput("git remote -v", workingDir=gitDir) @@ -547,8 +678,14 @@ def getGitRepoUrl(gitDir): #print("repoName = '" + repoName + "'") #print("repoUrl = '" + repoUrl + "'") - # Grab the URL if the remote name matches - if repoName == remoteRepoName: + if remoteRepoName: + # Grab the URL if the remote name matches + if repoName == remoteRepoName: + remoteRepoUrl = repoUrl + break + else: + # Just grab the first remote name you find if there is no tracking branch + remoteRepoName = repoName remoteRepoUrl = repoUrl break @@ -557,6 +694,13 @@ def getGitRepoUrl(gitDir): return (remoteRepoName, remoteBranch, remoteRepoUrl) +def getGitDescribe(gitDir): + + gitDescribe = getCmndOutput( "git describe", workingDir=gitDir, stripTrailingSpaces=True) + + return gitDescribe + + def getLastCommitMsg(gitDir): return getCmndOutput( "git log " \ @@ -564,3 +708,5 @@ def getLastCommitMsg(gitDir): +" -1 -- .", workingDir=gitDir ) + +# LocalWords: traceability TriBITS Snapshotting snapshotting From ed4e7bdf57afd0137da591e464d709bc9ff734b8 Mon Sep 17 00:00:00 2001 From: "Roscoe A. Bartlett" Date: Mon, 29 Nov 2021 13:33:16 -0700 Subject: [PATCH 04/37] Revert "Revert "Merge Pull Request #9894 from bartlettroscoe/Trilinos/tribits-299-modern-cmake-targets-1"" This reverts commit fd27a2010a0b05349c0d3dd415d8c6841b37bb1a. This gets us back to the state of the 'develop' branch after the PR #9894 that merged the branch 'tribits-299-modern-cmake-targets-1' was merged (as well as other PRs in the days after that). Now I can try to reproduce the errors in issues #9972 and #9973. --- cmake/tribits/ReleaseNotes.txt | 30 + cmake/tribits/TriBITS.cmake | 39 +- .../TribitsPackageConfigTemplate.cmake.in | 3 +- .../TribitsPackageConfigTemplate.export.in | 110 ---- .../TribitsProjectConfigTemplate.cmake.in | 37 +- .../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 | 577 ++++++++++++++++ .../package_arch/TribitsGlobalMacros.cmake | 35 +- .../package_arch/TribitsLibraryMacros.cmake | 49 +- .../package_arch/TribitsPackageMacros.cmake | 83 ++- .../TribitsProcessEnabledTpl.cmake | 34 +- .../TribitsReportInvalidTribitsUsage.cmake | 6 +- .../TribitsSubPackageMacros.cmake | 4 + ...itsSystemDataStructuresMacrosFunctions.rst | 18 +- ...ribitsTplFindIncludeDirsAndLibraries.cmake | 28 +- .../TribitsWriteClientExportFiles.cmake | 616 ++++++++---------- .../tribits/core/utils/AppendStringVar.cmake | 4 + .../core/utils/CMakeBuildTypesList.cmake | 3 + .../core/utils/DriveAdvancedTest.cmake | 2 +- cmake/tribits/core/utils/MessageWrapper.cmake | 6 +- cmake/tribits/core/utils/PrintVar.cmake | 6 +- .../utils/TribitsGatherBuildTargets.cmake | 104 +++ .../TribitsGetImportedLocationProperty.cmake | 62 ++ .../tribits/core/utils/UnitTestHelpers.cmake | 114 +++- .../ctest_driver/TribitsCTestDriverCore.cmake | 2 +- .../TribitsCTestDriverCoreHelpers.cmake | 2 +- .../build_ref/TribitsBuildReferenceBody.rst | 153 ++++- .../guides/TribitsCoreDetailedReference.rst | 37 +- .../tribits/doc/guides/TribitsGuidesBody.rst | 109 +++- .../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 ++ .../TribitsExampleApp2/AppHelperFuncs.cmake | 163 +++++ .../TribitsExampleApp2/CMakeLists.txt | 41 ++ .../examples/TribitsExampleApp2/README.md | 110 ++++ .../examples/TribitsExampleApp2/app.cpp | 34 + .../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 | 44 +- .../wrap_external/external_func/configure.py | 28 +- .../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 + .../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 + .../tribits/examples/tpls/Tpl1/CMakeLists.txt | 31 + cmake/tribits/examples/tpls/Tpl1/Tpl1.cpp | 6 + cmake/tribits/examples/tpls/Tpl1/Tpl1.hpp | 13 + 79 files changed, 2842 insertions(+), 772 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/core/utils/TribitsGetImportedLocationProperty.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/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/TribitsSimpleExampleApp/CMakeLists.txt create mode 100644 cmake/tribits/examples/TribitsSimpleExampleApp/README.md create mode 100644 cmake/tribits/examples/TribitsSimpleExampleApp/app.cpp 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 021bed044532..86e4ad4f14c9 100644 --- a/cmake/tribits/ReleaseNotes.txt +++ b/cmake/tribits/ReleaseNotes.txt @@ -2,6 +2,36 @@ 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 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. + +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 information 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..cdfc2e3fc145 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,8 @@ endif() # Initialize ${PROJECT_NAME}_FOUND with true, and set it to FALSE if any of # the required components wasn't found. set(${PROJECT_NAME}_FOUND TRUE) -foreach(comp ${PDOLLAR}{COMPONENTS_LIST}) +set(${PROJECT_NAME}_NOT_FOUND_MESSAGE "") +foreach (comp IN ITEMS ${PDOLLAR}{COMPONENTS_LIST}) set( INCLUDE_FILE ${PDOLLAR}{CMAKE_CURRENT_LIST_DIR}/../${PDOLLAR}{comp}/${PDOLLAR}{comp}Config.cmake @@ -124,10 +122,10 @@ foreach(comp ${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() @@ -198,5 +196,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 b13675fc14bc..efda842730a2 100644 --- a/cmake/tribits/core/package_arch/TribitsConstants.cmake +++ b/cmake/tribits/core/package_arch/TribitsConstants.cmake @@ -94,13 +94,17 @@ set(${PROJECT_NAME}_PACKAGE_DEPS_TABLE_HTML_FILE_NAME ${PROJECT_NAME}PackageDepe set(${PROJECT_NAME}_PACKAGE_DEPS_FILES_DIR "cmake/dependencies") +set(${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR "external_packages") + +set(${PROJECT_NAME}_BUILD_DIR_CMAKE_PKGS_DIR "cmake_packages") + # Other stuff if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Windows") #Apparently FIND_PROGRAM looks for an exact match of the file name. #So even though "git clone ..." is valid to use on windows we need to give the #full name of the command we want to run. - SET(GIT_NAME git.cmd) + set(GIT_NAME git.cmd) else() - SET(GIT_NAME git) + set(GIT_NAME git) endif() diff --git a/cmake/tribits/core/package_arch/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..69b513e88e3d --- /dev/null +++ b/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake @@ -0,0 +1,577 @@ +# @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_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. +# +# 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}/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() + + +# @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 "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() + tribits_external_package_process_libraries_list_library_entry( + ${tplName} "${libentry}" ${libEntryType} libTargets lastLib configFileStr ) + endif() + endforeach() + + list(REVERSE libLinkFlagsList) # Put back in original order + + # C) Set output arguments: + set(${PARSE_LIB_TARGETS_LIST_OUT} "${libTargets}" PARENT_SCOPE) + set(${PARSE_LIB_LINK_FLAGS_LIST_OUT} "${libLinkFlagsList}" PARENT_SCOPE) + set(${PARSE_CONFIG_FILE_STR_INOUT} "${configFileStrInit}${configFileStr}" + PARENT_SCOPE) + +endfunction() + + +# 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 library inside of loop over TPL__LIBRARIES +# in the function tribits_external_package_process_libraries_list() +# +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 "${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) + tribits_print_invalid_lib_name(${tplName} "${full_libname}") + endif() + 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() + set(${libnameOut} ${libname} PARENT_SCOPE) +endfunction() + + +function(tribits_external_package_get_libname_from_lib_name_link_option + lib_name_link_option libnameOut + ) + # Assert begging part '-l' + string(SUBSTRING "${lib_name_link_option}" 0 2 firstTwoCharsLibEntry) + if ( ) + tribits_print_invalid_lib_link_option(${tplName} "${lib_name_link_option}") + endif() + # Get from -l + string(SUBSTRING "${lib_name_link_option}" 2 -1 libname) + # Set output + set(${libnameOut} ${libname} PARENT_SCOPE) +endfunction() + + +function(tribits_print_invalid_lib_name tplName full_libname) + message(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..5ae79c5fc18d 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/" @@ -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 @@ -572,20 +576,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 +591,7 @@ macro(tribits_define_global_options_and_define_extra_repos) if (NOT ${PROJECT_NAME}_GENERATE_EXPORT_FILE_DEPENDENCIES_DEFAULT) # We need to generate the dependency logic for export dependency files if # asked. - if (${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES OR - ${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES - ) + if (${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES) set(${PROJECT_NAME}_GENERATE_EXPORT_FILE_DEPENDENCIES_DEFAULT ON) else() set(${PROJECT_NAME}_GENERATE_EXPORT_FILE_DEPENDENCIES_DEFAULT OFF) @@ -665,7 +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( @@ -1328,7 +1318,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 +1342,7 @@ function(tribits_generate_repo_version_file_string PROJECT_REPO_VERSION_FILE_ST tribits_generate_single_repo_version_string( "${CMAKE_CURRENT_SOURCE_DIR}/${EXTRAREPO_DIR}" SINGLE_REPO_VERSION) - append_string_var(REPO_VERSION_FILE_STR + string(APPEND REPO_VERSION_FILE_STR "*** Git Repo: ${EXTRAREPO_DIR}\n" "${SINGLE_REPO_VERSION}\n" ) @@ -1403,6 +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/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..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) @@ -57,13 +58,13 @@ function(tribits_process_enabled_tpl TPL_NAME) # Setup the processing string set(PROCESSING_MSG_STRING "Processing enabled TPL: ${TPL_NAME} (") if (TPL_${TPL_NAME}_ENABLING_PKG) - append_string_var(PROCESSING_MSG_STRING + string(APPEND PROCESSING_MSG_STRING "enabled by ${TPL_${TPL_NAME}_ENABLING_PKG}," ) else() - append_string_var(PROCESSING_MSG_STRING + string(APPEND PROCESSING_MSG_STRING "enabled explicitly," ) endif() - append_string_var(PROCESSING_MSG_STRING + string(APPEND PROCESSING_MSG_STRING " disable with -DTPL_ENABLE_${TPL_NAME}=OFF)" ) # Print the processing header @@ -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/TribitsReportInvalidTribitsUsage.cmake b/cmake/tribits/core/package_arch/TribitsReportInvalidTribitsUsage.cmake index 4db279fd387e..442a4928fbcd 100644 --- a/cmake/tribits/core/package_arch/TribitsReportInvalidTribitsUsage.cmake +++ b/cmake/tribits/core/package_arch/TribitsReportInvalidTribitsUsage.cmake @@ -37,11 +37,7 @@ # ************************************************************************ # @HEADER -if (__TribitsReportInvalidTribitsUsage_INCLUDED__) - return() -else() - set(__TribitsReportInvalidTribitsUsage_INCLUDED__ TRUE) -endif() +include_guard() include(MessageWrapper) diff --git a/cmake/tribits/core/package_arch/TribitsSubPackageMacros.cmake b/cmake/tribits/core/package_arch/TribitsSubPackageMacros.cmake index 19afd7ddd3bf..60a7c668e9a5 100644 --- a/cmake/tribits/core/package_arch/TribitsSubPackageMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsSubPackageMacros.cmake @@ -150,6 +150,10 @@ endfunction() # # tribits_subpackage_postprocess() # +# NOTE: This creates the aliased target ``${PACKAGE_NAME}::all_libs`` for all +# libraries in all subdirectories that don't have the TRIBITS_TESTONLY_LIB +# target property set on them. +# # NOTE: It is unfortunate that a Subpackages's CMakeLists.txt file must call # this macro but limitations of the CMake language make it necessary to do so. # diff --git a/cmake/tribits/core/package_arch/TribitsSystemDataStructuresMacrosFunctions.rst b/cmake/tribits/core/package_arch/TribitsSystemDataStructuresMacrosFunctions.rst index 00cdb56c7ee7..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..acc851e31c7d 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,21 @@ function(tribits_tpl_find_include_dirs_and_libraries TPL_NAME) global_set(TPL_${TPL_NAME}_NOT_FOUND FALSE) endif() + set(buildDirExternalPkgsDir + "${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR}") + set(tplConfigFile + "${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() + # NOTE: The file ConfigVersion.cmake will get created elsewhere as + # will the install targets for the files Config and + # ConfigVersion.cmake. + endfunction() -# # @FUNCTION: tribits_tpl_tentatively_enable() # # Function that sets up for an optionally enabled TPL that is attempted to be @@ -728,10 +736,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..767cc62e8a22 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,53 @@ 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(buildDirExtPkgsDir + "${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR}") + set(buildDirCMakePkgsDir + "${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_CMAKE_PKGS_DIR}") + + if (PARSE_PACKAGE_CONFIG_FOR_BUILD_BASE_DIR + OR PARSE_PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR + ) + # Custom code in configuration file (gets pulled from by configure_file() + # below) set(PACKAGE_CONFIG_CODE "") - # Include configurations of dependent packages - foreach(DEP_PACKAGE ${${PACKAGE_NAME}_FULL_ENABLED_DEP_PACKAGES}) - # Could use file(RELATIVE_PATH ...), but probably not necessary - # since unlike install trees, build trees need not be relocatable - set(PACKAGE_CONFIG_CODE "${PACKAGE_CONFIG_CODE} -include(\"${${DEP_PACKAGE}_BINARY_DIR}/${DEP_PACKAGE}Config.cmake\")" - ) - endforeach() + tribits_append_dependent_package_config_file_includes(${packageName} + EXT_PKG_CONFIG_FILE_BASE_DIR "${buildDirExtPkgsDir}" + PKG_CONFIG_FILE_BASE_DIR "${buildDirCMakePkgsDir}" + CONFIG_FILE_STR_INOUT PACKAGE_CONFIG_CODE ) # Import build tree targets into applications. # @@ -423,13 +397,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 +413,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 +452,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 +463,232 @@ 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} + EXT_PKG_CONFIG_FILE_BASE_DIR + "\${CMAKE_CURRENT_LIST_DIR}/../../${${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR}" + PKG_CONFIG_FILE_BASE_DIR "\${CMAKE_CURRENT_LIST_DIR}/.." + CONFIG_FILE_STR_INOUT PACKAGE_CONFIG_CODE ) - # Import install tree targets into applications. - get_property(HAS_INSTALL_TARGETS GLOBAL PROPERTY ${PACKAGE_NAME}_HAS_INSTALL_TARGETS) - if(HAS_INSTALL_TARGETS) - set(PACKAGE_CONFIG_CODE "${PACKAGE_CONFIG_CODE} -# Import ${PACKAGE_NAME} targets -include(\"\${CMAKE_CURRENT_LIST_DIR}/${PACKAGE_NAME}Targets.cmake\")" -) - endif() + # Import install targets + string(APPEND PACKAGE_CONFIG_CODE + "\n# Import ${packageName} targets\n" + "include(\"\${CMAKE_CURRENT_LIST_DIR}/${packageName}Targets.cmake\")") - # Write the specification of the rpath if necessary. This is only needed if we're building shared libraries. - if(BUILD_SHARED_LIBS) - set(SHARED_LIB_RPATH_COMMAND ${CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG}${CMAKE_INSTALL_PREFIX}/${${PROJECT_NAME}_INSTALL_LIB_DIR}) + # Write the specification of the rpath if necessary. This is only needed if + # we're building shared libraries. + if (BUILD_SHARED_LIBS) + set(SHARED_LIB_RPATH_COMMAND + ${CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG}${CMAKE_INSTALL_PREFIX}/${${PROJECT_NAME}_INSTALL_LIB_DIR} + ) endif() tribits_set_compiler_vars_for_config_file(INSTALL_DIR) - if (PARSE_WRITE_INSTALL_CMAKE_CONFIG_FILE) - + 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 external packages (TPLs) and internal +# packages to a `Config.cmake` file string. +# +# Usage:: +# +# tribits_append_dependent_package_config_file_includes( +# +# EXT_PKG_CONFIG_FILE_BASE_DIR +# PKG_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 + #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(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 "${pkgConfigFileBaseDir}/${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 "${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 "${extPkgConfigFileBaseDir}/${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(buildDirCMakePkgsDir + "${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_CMAKE_PKGS_DIR}") + set(EXPORT_FILES_ARGS PACKAGE_NAME ${PACKAGE_NAME}) if (${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES) - set(WRITE_CMAKE_CONFIG_FILE - ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME}Config.cmake) - if(${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("For package ${PACKAGE_NAME} creating ${WRITE_CMAKE_CONFIG_FILE}") - endif() - append_set(EXPORT_FILES_ARGS - WRITE_CMAKE_CONFIG_FILE "${WRITE_CMAKE_CONFIG_FILE}" - WRITE_INSTALL_CMAKE_CONFIG_FILE) - endif() - - if(${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES) - set(WRITE_EXPORT_MAKEFILE - ${CMAKE_CURRENT_BINARY_DIR}/Makefile.export.${PACKAGE_NAME}) if(${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("For package ${PACKAGE_NAME} creating ${WRITE_EXPORT_MAKEFILE}") + message("For package ${PACKAGE_NAME} creating ${PACKAGE_NAME}Config.cmake") endif() + set(PACKAGE_CONFIG_FOR_BUILD_BASE_DIR + "${buildDirCMakePkgsDir}/${PACKAGE_NAME}" ) + set(PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR + "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles" ) append_set(EXPORT_FILES_ARGS - WRITE_EXPORT_MAKEFILE "${WRITE_EXPORT_MAKEFILE}" - WRITE_INSTALL_EXPORT_MAKEFILE) + PACKAGE_CONFIG_FOR_BUILD_BASE_DIR "${PACKAGE_CONFIG_FOR_BUILD_BASE_DIR}" + PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR "${PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR}" + ) endif() tribits_write_flexible_package_client_export_files(${EXPORT_FILES_ARGS}) - tribits_write_project_client_export_files_install_targets(${PACKAGE_NAME}) + tribits_write_package_client_export_files_install_targets(${EXPORT_FILES_ARGS}) endfunction() -# -# Write the outer TriBITS project configure and/or export makefiles +# Write the outer TriBITS Config.cmake file # # If ${PROJECT_NAME}_VERSION is not set or is '' on input, then it will be set # to 0.0.0 in order to create the ${PROJECT_NAME}ConfigVersion.cmake file. # # ToDo: Finish documentation! # - function(tribits_write_project_client_export_files) set(EXPORT_FILE_VAR_PREFIX ${PROJECT_NAME}) - tribits_set_define_cmake_current_list_dir_code_snippet() # Reversing the package list so that libraries will be produced in order of # most dependent to least dependent. @@ -736,19 +749,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 +811,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 +843,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 +888,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/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/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..6056d777f5d8 --- /dev/null +++ b/cmake/tribits/core/utils/TribitsGatherBuildTargets.cmake @@ -0,0 +1,104 @@ +# @HEADER +# ************************************************************************ +# +# TriBITS: Tribal Build, Integrate, and Test System +# Copyright 2013 Sandia Corporation +# +# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +# the U.S. Government retains certain rights in this software. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Corporation nor the names of the +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# ************************************************************************ +# @HEADER + + +# Function to get a list all of buildsystem targets of the type matching the +# given list starting in a subdir and in below subdirs. +# +# Usage:: +# +# tribits_get_all_build_targets_including_in_subdirs( +# ) +# +# On output the variable ```` will contain a list of all of +# the build targets match match the targets types listed in +# ```` which is a quoted list of the form +# ``";;..."``. For example, to get all of the +# real library and executable targets, run:: +# +# tribits_get_all_build_targets_including_in_subdirs( +# +# "STATIC_LIBRARY;SHARED_LIBRARY;EXECUTABLE" +# ) +# +function(tribits_get_all_build_targets_including_in_subdirs srcdir targetTypesList + targetsListVarOut + ) + + set(targetsList "") + + # Recurse into subdirectories. + get_property(dirs DIRECTORY "${srcdir}" PROPERTY SUBDIRECTORIES) + foreach(d IN LISTS dirs) + tribits_get_all_build_targets_including_in_subdirs(${d} "${targetTypesList}" + targetsSubdirList) + list(APPEND targetsList ${targetsSubdirList}) + endforeach() + + # Get the targets from this directory. + get_property(allTargetsThisDir DIRECTORY "${srcdir}" PROPERTY BUILDSYSTEM_TARGETS) + tribits_filter_only_build_targets(allTargetsThisDir "${targetTypesList}" + buildTargetsThisDir) + list(APPEND targetsList ${buildTargetsThisDir}) + + # Return + set(${targetsListVarOut} ${targetsList} PARENT_SCOPE) + +endfunction() + + +function(tribits_filter_only_build_targets targetListInVar targetTypesList + targetListOutVar + ) + + set(targetListOut "") + + foreach (target IN LISTS ${targetListInVar}) + get_property(targetType TARGET ${target} PROPERTY TYPE) + foreach (desiredTargetType IN ITEMS ${targetTypesList}) + if (desiredTargetType STREQUAL targetType) + list(APPEND targetListOut ${target}) + break() + endif() + endforeach() + endforeach() + + set(${targetListOutVar} ${targetListOut} PARENT_SCOPE) + +endfunction() diff --git a/cmake/tribits/core/utils/TribitsGetImportedLocationProperty.cmake b/cmake/tribits/core/utils/TribitsGetImportedLocationProperty.cmake new file mode 100644 index 000000000000..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/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 025e04ae2898..f8950715051e 100644 --- a/cmake/tribits/doc/build_ref/TribitsBuildReferenceBody.rst +++ b/cmake/tribits/doc/build_ref/TribitsBuildReferenceBody.rst @@ -1522,13 +1522,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 @@ -1563,6 +1564,19 @@ Most ``FindTPL.cmake`` modules will define a default set of libraries to look for and therefore ``_LIBRARY_NAMES`` can typically be left off. +Therefore, to find the same set of libraries for ``SimpleTPL`` shown +above, one would specify:: + + -D SomeTPL_LIBRARY_DIRS="${LIB_BASE}/lib" + +and if the set of libraries to be found is different than the default, one can +override that using:: + + -D SomeTPL_LIBRARY_NAMES="lib1;lib2" + +Therefore, this is in fact the preferred way to specify the libraries for a +TPL. + In order to allow a TPL that normally requires one or more libraries to ignore the libraries, one can set ``_LIBRARY_NAMES`` to empty, for example:: @@ -1573,7 +1587,7 @@ Optional package-specific support for a TPL can be turned off by setting:: -D _ENABLE_=OFF This gives the user full control over what TPLs are supported by which package -independently. +independent of whether the TPL is enabled or not. Support for an optional TPL can also be turned on implicitly by setting:: @@ -1584,14 +1598,14 @@ dependency on ````. That will result in setting ``TPL_ENABLE_=ON`` internally (but not set in the cache) if ``TPL_ENABLE_=OFF`` is not already set. -If all the parts of a TPL are not found on an initial configure the configure +If all the parts of a TPL are not found on an initial configure, the configure will error out with a helpful error message. In that case, one can change the variables ``_INCLUDE_DIRS``, ``_LIBRARY_NAMES``, and/or ``_LIBRARY_DIRS`` in order to help fund the parts of the TPL. One -can do this over and over until the TPL is found. By reconfiguring, one avoid +can do this over and over until the TPL is found. By reconfiguring, one avoids a complete configure from scratch which saves time. Or, one can avoid the find operations by directly setting ``TPL__INCLUDE_DIRS`` and -``TPL__LIBRARIES``. +``TPL__LIBRARIES`` as described above. **WARNING:** The cmake cache variable ``TPL__LIBRARY_DIRS`` does **not** control where libraries are found. Instead, this variable is set @@ -1659,7 +1673,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 @@ -2597,15 +2611,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:: @@ -3306,6 +3311,8 @@ For more details, see the following subsections: * `Setting install RPATH`_ * `Avoiding installing libraries and headers`_ * `Installing the software`_ +* `Using the installed software in downstream CMake projects`_ +* `Using packages from the build tree in downstream CMake projects`_ Setting the install prefix @@ -3678,6 +3685,110 @@ This will ensure that every package that builds correctly will get installed. (The default 'install' target aborts on the first file install failure.) +Using the installed software in downstream CMake projects +--------------------------------------------------------- + +As described in `Generating export files`_, when ``-D +_ENABLE_INSTALL_CMAKE_CONFIG_FILES=ON`` is set at configure time, a +``Config.cmake`` file and a different ``Config.cmake`` file +for each enabled package is installed into the install tree under ``-D +CMAKE_INSTALL_PREFIX=``. A downstream CMake project can +then pull in CMake targets for the installed libraries using +``find_package()`` in the downstream project's ``CMakeLists.txt`` file. All +of the built and installed libraries can be pulled in and built against at the +project level by configuring the downstream CMake project with:: + + -D CMAKE_PREFIX_PATH= + +and having the downstream project's ``CMakeLists.txt`` file call, for +example:: + + find_package( REQUIRED) + ... + target_link_libraries( + PRIVATE ::all_libs ) + +This will put the needed include directories and other imported compiler +options on the downstream compile lines as specified through the IMPORTED +library targets and will put the needed libraries on the link line. + +To pull in libraries from only a subset of the installed packages `` + ...``, use, for example:: + + find_package( REQUIRED COMPONENTS ...) + ... + target_link_libraries( + PRIVATE ::all_selected_libs ) + +The target ``::all_selected_libs`` only contains the library targets +for the selected packages (through their ``::all_libs`` targets) for +the packages requested in the ``COMPONENTS ...`` argument. +(NOTE, the target ``::all_libs`` is unaffected by the ``COMPONENTS`` +argument and always links to all of the enabled package's libraries.) + +Downstream projects can also pull in and use installed libraries by finding +individual packages by calling ``find_package( REQUIRED)`` for each +package ```` and then linking against the defined IMPORTED CMake +target ``::all_libs`` such as:: + + find_package( REQUIRED) + find_package( REQUIRED) + ... + target_link_libraries( + PUBLIC ::all_libs + PRIVATE ::all_libs + ) + +Finding and using libraries for packages at the package-level provides better +fine-grained control over internal linking and provides greater flexibility in +case these packages are not all installed in the same upstream CMake project +in the future. + +To see an example of all of these use cases being demonstrated, see +`TribitsExampleApp`_ and the `TriBITS TribitsExampleApp Tests`_. + + +Using packages from the build tree in downstream CMake projects +------------------------------------------------------------------ + +Note that libraries from enabled and built packages can also be used from the +```` build tree without needing to install. Being able to build +against pre-built packages in the build tree can be very useful such as when +the project is part of a CMake super-build where one does not want to install +the intermediate packages. + +Let ```` be the build directory for ```` that has +already been configured and built (but not necessarily installed). A +downstream CMake project can pull in and link against any of the enabled +libraries in the upstream ```` configuring the downstream CMake +project with:: + + -D CMAKE_PREFIX_PATH=/cmake_packages + +and then finding the individual packages and linking to them in the downstream +CMake project's ``CMakeLists.txt`` file as usual using, for example:: + + find_package( REQUIRED) + find_package( REQUIRED) + ... + target_link_libraries( + PUBLIC ::all_libs + PRIVATE ::all_libs + ) + +Note that in this case, the include directories and other imported compiler +options from the source tree and the build tree are automatically injected +into the build targets associated with the ```` object +compile lines and link lines. + +Also note that package config files for all of the enabled external +packages/TPLs will also be written into the build tree under +``/external_packages``. These contain modern CMake targets +that are pulled in by the downstream ``Config.cmake`` files under +``/external_packages``. These external package/TPL config +files are placed in a seprate directory to avoid being found by accident. + + Installation Testing ==================== @@ -3689,7 +3800,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] \ @@ -4029,4 +4140,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..38d58b4192f8 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: @@ -386,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:: @@ -455,13 +441,12 @@ These options are described below. **${PROJECT_NAME}_GENERATE_EXPORT_FILE_DEPENDENCIES** If ``${PROJECT_NAME}_GENERATE_EXPORT_FILE_DEPENDENCIES`` is ``ON``, then the - data-structures needed to generate ``Makefile.export.`` and - ``Config.cmake`` are created. These data structures are also - needed in order to generate export makefiles on demand using the function + data-structures needed to generate ``Config.cmake`` files are + created. These data structures are also needed in order to generate export + makefiles on demand using the function `tribits_write_flexible_package_client_export_files()`_. The default in TriBITS is to turn this ``ON`` automatically by default if - ``${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES`` or - ``${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES`` are ``ON``. Else, by + ``${PROJECT_NAME}_ENABLE_INSTALL_CMAKE_CONFIG_FILES`` is ``ON``. Else, by default, TriBITS sets this to ``OFF``. The only reason for the project to override the default is to set it to ``ON`` as with:: @@ -498,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/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..9d9b99bb0b29 --- /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(TribitsExProj)` and will set the compilers +pulled in from the found `TribitsExProjConfig.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). + + +## 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/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/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..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,15 +61,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 external_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 +91,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 +159,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/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/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 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 From fb578c9143f5489488b7adc0ddbb253eee9eed66 Mon Sep 17 00:00:00 2001 From: "Roscoe A. Bartlett" Date: Fri, 10 Jun 2022 13:40:24 -0600 Subject: [PATCH 05/37] Automatic snapshot commit from tribits at e82c4544 Origin repo remote tracking branch: 'github/master' Origin repo remote repo URL: 'github = git@github.com:TriBITSPub/TriBITS.git' Git describe: Vera4.0-RC1-start-1173-g332f7a44 At commit: commit e82c4544fbd50769b85bab45cb98ef009ca4643c Author: Roscoe A. Bartlett Date: Fri Jun 10 11:08:38 2022 -0600 Summary: Remove internal quotes for git log --pretty=format: strings (#485) --- cmake/tribits/CHANGELOG.md | 76 ++ cmake/tribits/common_tpls/FindTPLNetcdf.cmake | 50 +- .../common_tpls/FindTPLProjectLastLib.cmake | 9 + .../TribitsPackageConfigTemplate.cmake.in | 10 +- .../TribitsProjectConfigTemplate.cmake.in | 69 +- .../package_arch/TribitsAddAdvancedTest.cmake | 239 ++-- .../package_arch/TribitsAddExecutable.cmake | 497 ++++---- .../TribitsAddExecutableAndTest.cmake | 10 +- .../TribitsAddExecutableTestHelpers.cmake | 10 +- .../core/package_arch/TribitsAddLibrary.cmake | 802 +++++++++++++ .../TribitsAddOptionAndDefine.cmake | 1 - .../core/package_arch/TribitsAddTest.cmake | 81 +- .../package_arch/TribitsAddTestHelpers.cmake | 53 +- .../TribitsAdjustPackageEnables.cmake | 182 ++- .../TribitsCommonArgsHelpers.cmake | 5 +- .../package_arch/TribitsConfigureFile.cmake | 180 +++ .../TribitsCopyFilesToBinaryDir.cmake | 1 - ...ribitsExternalPackageWriteConfigFile.cmake | 227 +++- .../TribitsFindMostRecentFileTimestamp.cmake | 4 - .../package_arch/TribitsGeneralMacros.cmake | 188 +--- .../package_arch/TribitsGetVersionDate.cmake | 2 - .../TribitsGitRepoVersionInfo.cmake | 164 +++ .../package_arch/TribitsGlobalMacros.cmake | 258 +---- .../TribitsIncludeDirectories.cmake | 1 - .../package_arch/TribitsInstallHeaders.cmake | 1 - .../package_arch/TribitsLibIsTestOnly.cmake | 77 ++ .../package_arch/TribitsLibraryMacros.cmake | 1002 +---------------- .../package_arch/TribitsListHelpers.cmake | 1 - .../package_arch/TribitsPackageMacros.cmake | 88 +- .../TribitsPrintEnabledPackagesLists.cmake | 172 +++ .../TribitsProcessEnabledTpl.cmake | 37 +- .../TribitsProcessExtraRepositoriesList.cmake | 1 - .../TribitsProcessPackagesAndDirsLists.cmake | 1 + .../TribitsProcessTplsLists.cmake | 11 +- .../core/package_arch/TribitsProject.cmake | 1 - .../package_arch/TribitsProjectImpl.cmake | 1 - .../TribitsReadDepsFilesCreateDepsGraph.cmake | 2 + ...itsSystemDataStructuresMacrosFunctions.rst | 119 +- ...ribitsTplFindIncludeDirsAndLibraries.cmake | 66 +- .../package_arch/TribitsVerbosePrintVar.cmake | 2 +- .../TribitsWriteClientExportFiles.cmake | 205 ++-- cmake/tribits/core/std_tpls/FindTPLMPI.cmake | 4 + .../core/utils/AddSubdirectories.cmake | 2 +- cmake/tribits/core/utils/AdvancedOption.cmake | 2 +- cmake/tribits/core/utils/AdvancedSet.cmake | 1 - .../core/utils/AppendCmndlineArgs.cmake | 2 +- cmake/tribits/core/utils/AppendGlob.cmake | 2 +- .../tribits/core/utils/AppendGlobalSet.cmake | 2 +- cmake/tribits/core/utils/AppendSet.cmake | 2 +- .../tribits/core/utils/AppendStringVar.cmake | 3 +- .../core/utils/AppendStringVarWithSep.cmake | 2 +- cmake/tribits/core/utils/AssertDefined.cmake | 4 +- cmake/tribits/core/utils/CombinedOption.cmake | 1 - cmake/tribits/core/utils/ConcatStrings.cmake | 1 - .../core/utils/DriveAdvancedTest.cmake | 67 +- .../utils/DualScopeAppendCmndlineArgs.cmake | 2 +- .../utils/DualScopePrependCmndlineArgs.cmake | 2 +- cmake/tribits/core/utils/DualScopeSet.cmake | 1 - cmake/tribits/core/utils/GlobalNullSet.cmake | 2 +- cmake/tribits/core/utils/GlobalSet.cmake | 1 - cmake/tribits/core/utils/Join.cmake | 1 - cmake/tribits/core/utils/MessageWrapper.cmake | 8 +- cmake/tribits/core/utils/MultilineSet.cmake | 1 - .../core/utils/ParseVariableArguments.cmake | 10 +- .../core/utils/PrependCmndlineArgs.cmake | 2 +- .../tribits/core/utils/PrependGlobalSet.cmake | 2 +- cmake/tribits/core/utils/PrependSet.cmake | 2 +- .../tribits/core/utils/PrintNonemptyVar.cmake | 1 - .../utils/PrintNonemptyVarWithSpaces.cmake | 2 +- .../core/utils/PrintVarWithSpaces.cmake | 66 ++ .../core/utils/RemoveGlobalDuplicates.cmake | 2 +- cmake/tribits/core/utils/SetAndIncDirs.cmake | 2 +- .../core/utils/SetCacheOnOffEmpty.cmake | 1 - cmake/tribits/core/utils/SetDefault.cmake | 2 +- .../core/utils/SetDefaultAndFromEnv.cmake | 3 +- cmake/tribits/core/utils/Split.cmake | 2 +- cmake/tribits/core/utils/TimingUtils.cmake | 4 +- .../core/utils/TribitsFilepathHelpers.cmake | 3 +- .../utils/TribitsParseArgumentsHelpers.cmake | 156 +++ .../tribits/core/utils/TribitsPrintList.cmake | 73 ++ .../core/utils/TribitsStandardizePaths.cmake | 2 +- .../utils/TribitsStripQuotesFromStr.cmake | 3 +- .../tribits/core/utils/UnitTestHelpers.cmake | 117 +- .../TribitsAddDashboardTarget.cmake | 10 + .../ctest_driver/TribitsCTestDriverCore.cmake | 77 +- .../TribitsCTestDriverCoreHelpers.cmake | 2 +- .../TribitsGetCDashUrlFromTagFile.cmake | 194 ---- .../TribitsGetCDashUrlsInsideCTestS.cmake | 527 +++++++++ .../ctest_driver/TribitsReadTagFile.cmake | 3 + .../experimental_build_test.cmake | 2 +- .../build_ref/TribitsBuildReferenceBody.rst | 22 +- .../ExpectedDependencies.txt | 29 + .../guides/TribitsCoreDetailedReference.rst | 2 +- .../tribits/doc/guides/TribitsGuidesBody.rst | 116 +- .../guides/UtilsMacroFunctionDocTemplate.rst | 2 + .../doc/guides/maintainers_guide/Makefile | 3 +- cmake/tribits/doc/sphinx/build_sphinx_docs.sh | 2 +- .../doc/sphinx/combined_docs/index.html | 2 +- .../doc/sphinx/sphinx_rst_generator.py | 472 ++++---- .../package2/cmake/Dependencies.cmake | 13 + .../TribitsExampleApp2/AppHelperFuncs.cmake | 57 +- .../examples/TribitsExampleApp2/app.cpp | 38 +- .../simple_cxx/cmake/Dependencies.cmake | 2 +- .../simple_cxx/cmake/SimpleCxx_config.h.in | 5 + .../packages/wrap_external/CMakeLists.txt | 1 - .../TribitsExampleProject2/PackagesList.cmake | 2 + .../TribitsExampleProject2/TPLsList.cmake | 8 + .../cmake/tpls/FindTPLTpl2.cmake | 4 + .../cmake/tpls/FindTPLTpl3.cmake | 4 + .../cmake/tpls/FindTPLTpl4.cmake | 3 + .../packages/package1/src/Package1.cpp | 5 + .../packages/package1/src/Package1.hpp | 3 + .../packages/package2/CMakeLists.txt | 4 + .../package2/cmake/Dependencies.cmake | 4 + .../package2/cmake/Package2_config.h.in | 6 + .../packages/package2/src/CMakeLists.txt | 26 + .../packages/package2/src/Package2.cpp | 26 + .../packages/package2/src/Package2.hpp | 19 + .../packages/package2/src/Package2_Prg.cpp | 9 + .../packages/package2/test/CMakeLists.txt | 13 + .../packages/package3/CMakeLists.txt | 4 + .../package3/cmake/Dependencies.cmake | 6 + .../package3/cmake/Package3_config.h.in | 7 + .../packages/package3/src/CMakeLists.txt | 26 + .../packages/package3/src/Package3.cpp | 40 + .../packages/package3/src/Package3.hpp | 21 + .../packages/package3/src/Package3_Prg.cpp | 9 + .../packages/package3/test/CMakeLists.txt | 20 + .../TribitsOldSimpleExampleApp/CMakeLists.txt | 2 +- .../TribitsSimpleExampleApp/README.md | 4 +- .../tribits/examples/tpls/Tpl2/CMakeLists.txt | 53 + .../examples/tpls/Tpl2/Tpl2Config.cmake.in | 2 + cmake/tribits/examples/tpls/Tpl2/Tpl2a.cpp | 13 + cmake/tribits/examples/tpls/Tpl2/Tpl2a.hpp | 16 + cmake/tribits/examples/tpls/Tpl2/Tpl2b.cpp | 11 + cmake/tribits/examples/tpls/Tpl2/Tpl2b.hpp | 16 + .../tribits/examples/tpls/Tpl3/CMakeLists.txt | 46 + cmake/tribits/examples/tpls/Tpl3/Tpl3.cpp | 20 + cmake/tribits/examples/tpls/Tpl3/Tpl3.hpp | 16 + .../examples/tpls/Tpl3/Tpl3Config.cmake.in | 2 + .../tribits/examples/tpls/Tpl4/CMakeLists.txt | 50 + cmake/tribits/examples/tpls/Tpl4/Tpl4.hpp | 33 + .../examples/tpls/Tpl4/Tpl4Config.cmake.in | 3 + 143 files changed, 4848 insertions(+), 2763 deletions(-) create mode 100644 cmake/tribits/common_tpls/FindTPLProjectLastLib.cmake create mode 100644 cmake/tribits/core/package_arch/TribitsAddLibrary.cmake create mode 100644 cmake/tribits/core/package_arch/TribitsConfigureFile.cmake create mode 100644 cmake/tribits/core/package_arch/TribitsGitRepoVersionInfo.cmake create mode 100644 cmake/tribits/core/package_arch/TribitsLibIsTestOnly.cmake create mode 100644 cmake/tribits/core/package_arch/TribitsPrintEnabledPackagesLists.cmake create mode 100644 cmake/tribits/core/utils/PrintVarWithSpaces.cmake create mode 100644 cmake/tribits/core/utils/TribitsParseArgumentsHelpers.cmake create mode 100644 cmake/tribits/core/utils/TribitsPrintList.cmake delete mode 100644 cmake/tribits/ctest_driver/TribitsGetCDashUrlFromTagFile.cmake create mode 100644 cmake/tribits/ctest_driver/TribitsGetCDashUrlsInsideCTestS.cmake create mode 100644 cmake/tribits/examples/TribitsExampleProject2/cmake/tpls/FindTPLTpl2.cmake create mode 100644 cmake/tribits/examples/TribitsExampleProject2/cmake/tpls/FindTPLTpl3.cmake create mode 100644 cmake/tribits/examples/TribitsExampleProject2/cmake/tpls/FindTPLTpl4.cmake create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package2/CMakeLists.txt create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package2/cmake/Dependencies.cmake create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package2/cmake/Package2_config.h.in create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package2/src/CMakeLists.txt create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package2/src/Package2.cpp create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package2/src/Package2.hpp create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package2/src/Package2_Prg.cpp create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package2/test/CMakeLists.txt create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package3/CMakeLists.txt create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package3/cmake/Dependencies.cmake create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package3/cmake/Package3_config.h.in create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package3/src/CMakeLists.txt create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package3/src/Package3.cpp create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package3/src/Package3.hpp create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package3/src/Package3_Prg.cpp create mode 100644 cmake/tribits/examples/TribitsExampleProject2/packages/package3/test/CMakeLists.txt create mode 100644 cmake/tribits/examples/tpls/Tpl2/CMakeLists.txt create mode 100644 cmake/tribits/examples/tpls/Tpl2/Tpl2Config.cmake.in create mode 100644 cmake/tribits/examples/tpls/Tpl2/Tpl2a.cpp create mode 100644 cmake/tribits/examples/tpls/Tpl2/Tpl2a.hpp create mode 100644 cmake/tribits/examples/tpls/Tpl2/Tpl2b.cpp create mode 100644 cmake/tribits/examples/tpls/Tpl2/Tpl2b.hpp create mode 100644 cmake/tribits/examples/tpls/Tpl3/CMakeLists.txt create mode 100644 cmake/tribits/examples/tpls/Tpl3/Tpl3.cpp create mode 100644 cmake/tribits/examples/tpls/Tpl3/Tpl3.hpp create mode 100644 cmake/tribits/examples/tpls/Tpl3/Tpl3Config.cmake.in create mode 100644 cmake/tribits/examples/tpls/Tpl4/CMakeLists.txt create mode 100644 cmake/tribits/examples/tpls/Tpl4/Tpl4.hpp create mode 100644 cmake/tribits/examples/tpls/Tpl4/Tpl4Config.cmake.in diff --git a/cmake/tribits/CHANGELOG.md b/cmake/tribits/CHANGELOG.md index 4ba2a69d3c8a..63761777b5f4 100644 --- a/cmake/tribits/CHANGELOG.md +++ b/cmake/tribits/CHANGELOG.md @@ -2,6 +2,82 @@ ChangeLog for TriBITS ---------------------------------------- +## 2022-05-16: + +* **Changed:** All compliant external packages (TPLs) must now set the + imported target `::all_libs` in their `FindTPL.cmake` + files instead of the variables `TPL__INCLUDE` and + `TPL__LIBRARIES`. + +* **Changed:** The project-level variables `_INCLUDE_DIRS`, + `_TPL_INCLUDE_DIRS`, `_LIBRARY_DIRS` and + `_TPL_LIBRARY_DIRS` from the file `Config.cmake` and + package-level variables `_INCLUDE_DIRS`, + `_TPL_INCLUDE_DIRS`, `_LIBRARY_DIRS` and + `_TPL_LIBRARY_DIRS` from the installed files + `Config.cmake` are now set to empty. Downstream CMake projects + will need to link against the exported project-level target + `::all_libs` or `::all_selected_libs` or the package-level + targets `::all_libs` in order to get the list of include + directories that are propagated through those targets by CMake. + +* **Changed:** The function `tribits_add_library()` no longer sets the + directory property `INCLUDE_DIRECTORIES` and instead passes include + directory information between targets directly using the + `INTERFACE_INCLUDE_DIRECTORIES` target property. This may result in + situations where include directories were getting set through the directory + property `INCLUDE_DIRECTORIES` and getting picked up in the builds of + targets that lacked the proper library dependencies. Therefore, this is + technically a break in backward compatibility, but not for well-formed + TriBITS projects. + +* **Changed:** Variables `${PACKAGE_NAME}_ENABLE_` are now set to + `TRUE` for required upstream internal and external packages/TPLs `` + (in order to simplify internal TriBITS logic). However, a side-effect of + this change is that CMake code that was ifed out with an `if + (${PACKAGE_NAME}_ENABLE_)` statement (because that variable was not + defined and therefore defaults to `FLASE`) for a required upstream + dependency `` will now be enabled. (This mistake can happen when an + optional dependency `` is changed to a required dependency but the + `if()` statements based on `${PACKAGE_NAME}_ENABLE_` are not + removed. Well-formed TriBITS projects and packages should not experience + this problem or notice any change.) + +## 2022-05-16: + +* **Added:** The function `tribits_add_advanced_test(`) now correctly accepts + a list of regexes for `PASS_REGULAR_EXPRESSION` and + `FAIL_REGULAR_EXPRESSION` and behave the same as the raw CTest properties of + the same names. + +## 2022-03-10: + +* **Changed:** The `tribits_add_advanced_test()` command now correctly reports + unparsed/unrecognized arguments. This will break some sloppy usages. (One + TriBITS test had to be fixed.) + +* **Changed:** The `tribits_add_test()` and `tribits_add_advanced_test()` + behave differently with data passed in with explicit colon arguments. For + example, before `PASS_REGULAR_EXPRESSION ";"` could be used + to pass in a list of regular expressions but with the new handling of + function arguments, this now gets set as a single regex + `"\\;"` which is not the same. The fix (that also works + with older versions of TriBITS) is to pass in multiple regexes as separate + arguments as `PASS_REGULAR_EXPRESSION "" ""`. + +* **Added:** The `tribits_add_test()`, `tribits_add_advanced_test()`, and + `tribits_add_executable_and_test()` functions now allow handling semi-colons + ';' in the quoted arguments to CMND/EXEC `ARGS` and `ENVIRONMENT` variable + values by adding a `LIST_SEPARATOR ` argument (same as for + `ExternalProject_Add()`). + +* **Changed:** The `tribits_add_test()` and `tribits_add_advanced_test()` + functions switched over from using `cmake_parse_arguments(... ${ARGN})` to + using `cmake_parse_arguments(PARSE_ARGV ...)` and, therefore, now will no + longer ignore empty arguments. This will break backward compatibility for + cases where empty quoted arguments like `"${SomeVar}"` are passed in where + the variable `SomeVar` is empty. + ## 2022-03-02: * **Added:** The project-level cache variable `_IMPORTED_NO_SYSTEM` diff --git a/cmake/tribits/common_tpls/FindTPLNetcdf.cmake b/cmake/tribits/common_tpls/FindTPLNetcdf.cmake index a5a98ce2c3fb..9ffd66c06a63 100644 --- a/cmake/tribits/common_tpls/FindTPLNetcdf.cmake +++ b/cmake/tribits/common_tpls/FindTPLNetcdf.cmake @@ -48,6 +48,10 @@ set(REQUIRED_HEADERS netcdf.h) set(REQUIRED_LIBS_NAMES netcdf) +if (TPL_ENABLE_MPI) + set(REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} pnetcdf) +endif() + # # Second, search for Netcdf components (if allowed) using the standard # find_package(NetCDF ...). @@ -62,7 +66,7 @@ if (Netcdf_ALLOW_PREFIND) "${CMAKE_CURRENT_LIST_DIR}/find_modules" "${CMAKE_CURRENT_LIST_DIR}/utils" ) - + find_package(NetCDF) if (NetCDF_FOUND) @@ -71,7 +75,7 @@ if (Netcdf_ALLOW_PREFIND) "True if netcdf enables netcdf-4") set(TPL_Netcdf_Enables_PNetcdf ${NetCDF_NEEDS_PNetCDF} CACHE BOOL "True if netcdf enables pnetcdf") - set(TPL_Netcdf_PARALLEL ${NetCDF_PARALLEL} CACHE BOOL + set(TPL_Netcdf_PARALLEL ${NetCDF_PARALLEL} CACHE INTERNAL "True if netcdf compiled with parallel enabled") set(TPL_Netcdf_LIBRARY_DIRS ${_hdf5_LIBRARY_SEARCH_DIRS} CACHE PATH "${DOCSTR} library files") @@ -80,7 +84,20 @@ if (Netcdf_ALLOW_PREFIND) set(TPL_Netcdf_INCLUDE_DIRS ${NetCDF_INCLUDE_DIRS} CACHE PATH "${DOCSTR} header files.") endif() - +else() + # Curl library is only required if DAP is enabled; should detect inside + # FindNetCDF.cmake, but that is not being called... SEMS has DAP enabled; + # many HPC systems don't, but they override these settings... + find_program(NC_CONFIG "nc-config") + if (NC_CONFIG) + execute_process(COMMAND "nc-config --has-dap2" + OUTPUT_VARIABLE NETCDF_HAS_DAP2) + execute_process(COMMAND "nc-config --has-dap4" + OUTPUT_VARIABLE NETCDF_HAS_DAP4) + endif() + if ((NOT NC_CONFIG) OR NETCDF_HAS_DAP2 OR NETCDF_HAS_DAP4) + set(REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} curl) + endif() endif() # @@ -95,3 +112,30 @@ tribits_tpl_find_include_dirs_and_libraries( Netcdf # variables TPL_Netcdf_INCLUDE_DIRS and TPL_Netcdf_LIBRARIES and then print # them out (and set some other standard variables as well). This is the final # "hook" into the TriBITS TPL system. + +# If the `find_package(NetCDF)` is not run, then this may not be set +# Need to determine how this is set in the library that is being used... + +if ("${TPL_Netcdf_PARALLEL}" STREQUAL "") + assert_defined(TPL_Netcdf_INCLUDE_DIRS) + find_path(meta_path + NAMES "netcdf_meta.h" + HINTS ${TPL_Netcdf_INCLUDE_DIRS} + NO_DEFAULT_PATH) + + if (meta_path) + # Search meta for NC_HAS_PARALLEL setting... + # Note that there is both NC_HAS_PARALLEL and NC_HAS_PARALLEL4, only want first... + file(STRINGS "${meta_path}/netcdf_meta.h" netcdf_par_string REGEX "NC_HAS_PARALLEL ") + string(REGEX MATCH "[01]" netcdf_par_val "${netcdf_par_string}") + if (netcdf_par_val EQUAL 1) + set(TPL_Netcdf_PARALLEL True CACHE INTERNAL + "True if netcdf compiled with parallel enabled") + endif() + endif() + if ("${TPL_Netcdf_PARALLEL}" STREQUAL "") + set(TPL_Netcdf_PARALLEL False CACHE INTERNAL + "True if netcdf compiled with parallel enabled") + endif() +endif() +message(STATUS "TPL_Netcdf_PARALLEL is ${TPL_Netcdf_PARALLEL}") diff --git a/cmake/tribits/common_tpls/FindTPLProjectLastLib.cmake b/cmake/tribits/common_tpls/FindTPLProjectLastLib.cmake new file mode 100644 index 000000000000..97d052978c84 --- /dev/null +++ b/cmake/tribits/common_tpls/FindTPLProjectLastLib.cmake @@ -0,0 +1,9 @@ +# This is a hack to handle the ${PROJECT_NAME}_EXTRA_LINK_FLAGS options as a +# TPL that every downstream TPL and package will depend on. + +separate_arguments(TPL_${PROJECT_NAME}TribitsLastLib_LIBRARIES NATIVE_COMMAND + "${${PROJECT_NAME}_EXTRA_LINK_FLAGS}") + +tribits_tpl_find_include_dirs_and_libraries( ${PROJECT_NAME}TribitsLastLib + REQUIRED_LIBS_NAMES NEVER_USED + ) diff --git a/cmake/tribits/core/installation/TribitsPackageConfigTemplate.cmake.in b/cmake/tribits/core/installation/TribitsPackageConfigTemplate.cmake.in index 396f904628e8..1b11675c7d76 100644 --- a/cmake/tribits/core/installation/TribitsPackageConfigTemplate.cmake.in +++ b/cmake/tribits/core/installation/TribitsPackageConfigTemplate.cmake.in @@ -45,7 +45,7 @@ # ############################################################################## -include_guard() +include_guard(GLOBAL) ## --------------------------------------------------------------------------- ## Compilers used by ${PROJECT_NAME}/${PACKAGE_NAME} build @@ -95,19 +95,19 @@ set(${EXPORT_FILE_VAR_PREFIX}_AR ${CMAKE_AR}) set(${EXPORT_FILE_VAR_PREFIX}_INSTALL_DIR "@CMAKE_INSTALL_PREFIX@") ## List of package include dirs -set(${EXPORT_FILE_VAR_PREFIX}_INCLUDE_DIRS "${FULL_INCLUDE_DIRS_SET}") +set(${EXPORT_FILE_VAR_PREFIX}_INCLUDE_DIRS "") ## List of package library paths -set(${EXPORT_FILE_VAR_PREFIX}_LIBRARY_DIRS "${FULL_LIBRARY_DIRS_SET}") +set(${EXPORT_FILE_VAR_PREFIX}_LIBRARY_DIRS "") ## List of package libraries set(${EXPORT_FILE_VAR_PREFIX}_LIBRARIES "${FULL_LIBRARY_SET}") ## Specification of directories for TPL headers -set(${EXPORT_FILE_VAR_PREFIX}_TPL_INCLUDE_DIRS "${${PACKAGE_NAME}_TPL_INCLUDE_DIRS}") +set(${EXPORT_FILE_VAR_PREFIX}_TPL_INCLUDE_DIRS "") ## Specification of directories for TPL libraries -set(${EXPORT_FILE_VAR_PREFIX}_TPL_LIBRARY_DIRS "${${PACKAGE_NAME}_TPL_LIBRARY_DIRS}") +set(${EXPORT_FILE_VAR_PREFIX}_TPL_LIBRARY_DIRS "") ## List of required TPLs set(${EXPORT_FILE_VAR_PREFIX}_TPL_LIBRARIES "${${PACKAGE_NAME}_TPL_LIBRARIES}") diff --git a/cmake/tribits/core/installation/TribitsProjectConfigTemplate.cmake.in b/cmake/tribits/core/installation/TribitsProjectConfigTemplate.cmake.in index cdfc2e3fc145..38a27dedf4ce 100644 --- a/cmake/tribits/core/installation/TribitsProjectConfigTemplate.cmake.in +++ b/cmake/tribits/core/installation/TribitsProjectConfigTemplate.cmake.in @@ -46,8 +46,6 @@ # ############################################################################## -include_guard() - ## --------------------------------------------------------------------------- ## Compilers used by ${PROJECT_NAME} build ## --------------------------------------------------------------------------- @@ -115,11 +113,7 @@ foreach (comp IN ITEMS ${PDOLLAR}{COMPONENTS_LIST}) # Include the package file. include(${PDOLLAR}{INCLUDE_FILE}) # Add variables to lists. - list(APPEND ${PROJECT_NAME}_INCLUDE_DIRS ${PDOLLAR}{${PDOLLAR}{comp}_INCLUDE_DIRS}) - list(APPEND ${PROJECT_NAME}_LIBRARY_DIRS ${PDOLLAR}{${PDOLLAR}{comp}_LIBRARY_DIRS}) list(APPEND ${PROJECT_NAME}_LIBRARIES ${PDOLLAR}{${PDOLLAR}{comp}_LIBRARIES}) - list(APPEND ${PROJECT_NAME}_TPL_INCLUDE_DIRS ${PDOLLAR}{${PDOLLAR}{comp}_TPL_INCLUDE_DIRS}) - list(APPEND ${PROJECT_NAME}_TPL_LIBRARY_DIRS ${PDOLLAR}{${PDOLLAR}{comp}_TPL_LIBRARY_DIRS}) list(APPEND ${PROJECT_NAME}_TPL_LIBRARIES ${PDOLLAR}{${PDOLLAR}{comp}_TPL_LIBRARIES}) else() set(${PROJECT_NAME}_${PDOLLAR}{comp}_FOUND FALSE) @@ -131,38 +125,21 @@ foreach (comp IN ITEMS ${PDOLLAR}{COMPONENTS_LIST}) endif() endforeach() -# Resolve absolute paths and remove duplicate paths -# for LIBRARY_DIRS and INCLUDE_DIRS -# This reduces stress on regular expressions later -set(short_dirs) -foreach(dir ${PDOLLAR}{${PROJECT_NAME}_INCLUDE_DIRS}) - get_filename_component(dir_abs ${PDOLLAR}{dir} ABSOLUTE) - list(APPEND short_dirs ${PDOLLAR}{dir_abs}) -endforeach() -list(REMOVE_DUPLICATES short_dirs) -set(${PROJECT_NAME}_INCLUDE_DIRS ${PDOLLAR}{short_dirs}) +# Deprecated (see #299)! +set(${PROJECT_NAME}_INCLUDE_DIRS "${TRIBITS_PROJECT_INSTALL_INCLUDE_DIR}") -set(short_dirs) -foreach(dir ${PDOLLAR}{${PROJECT_NAME}_LIBRARY_DIRS}) - get_filename_component(dir_abs ${PDOLLAR}{dir} ABSOLUTE) - list(APPEND short_dirs ${PDOLLAR}{dir_abs}) -endforeach() -list(REMOVE_DUPLICATES short_dirs) -set(${PROJECT_NAME}_LIBRARY_DIRS ${PDOLLAR}{short_dirs}) +# Deprecated (see #299)! +set(${PROJECT_NAME}_LIBRARY_DIRS "") # Remove duplicates in ${PROJECT_NAME}_LIBRARIES list(REVERSE ${PROJECT_NAME}_LIBRARIES) list(REMOVE_DUPLICATES ${PROJECT_NAME}_LIBRARIES) list(REVERSE ${PROJECT_NAME}_LIBRARIES) -# Remove duplicates in ${PROJECT_NAME}_TPL_INCLUDE_DIRS -if (${PROJECT_NAME}_TPL_INCLUDE_DIRS) - list(REMOVE_DUPLICATES ${PROJECT_NAME}_TPL_INCLUDE_DIRS) -endif() - -# NOTE: It is *NOT* safe to try to remove duplicate in -# ${PROJECT_NAME}_TPL_LIBRARIES because these can be specified as -L, -l, etc. -# Actually, we should think about that. +# Remove duplicates in ${PROJECT_NAME}_TPL_LIBRARIES +list(REVERSE ${PROJECT_NAME}_TPL_LIBRARIES) +list(REMOVE_DUPLICATES ${PROJECT_NAME}_TPL_LIBRARIES) +list(REVERSE ${PROJECT_NAME}_TPL_LIBRARIES) ## --------------------------------------------------------------------------- ## MPI specific variables @@ -207,19 +184,23 @@ set(${PROJECT_NAME}_TPL_LIST "${FULL_TPL_SET}") ## --------------------------------------------------------------------------- # ${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 +if (NOT TARGET ${PROJECT_NAME}::all_libs) + set(${PROJECT_NAME}_ALL_PACKAGES_TARGETS) + foreach (pkg IN ITEMS ${FULL_PACKAGE_SET}) + list(APPEND ${PROJECT_NAME}_ALL_PACKAGES_TARGETS ${PDOLLAR}{pkg}::all_libs) + endforeach() + add_library(${PROJECT_NAME}::all_libs IMPORTED INTERFACE GLOBAL) + target_link_libraries(${PROJECT_NAME}::all_libs INTERFACE ${PDOLLAR}{${PROJECT_NAME}_ALL_PACKAGES_TARGETS} ) +endif() # ${PROJECT_NAME}::all_selected_libs (Depend on COMPONENTS) -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} ) +if (NOT TARGET ${PROJECT_NAME}::all_selected_libs) + 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} ) +endif() diff --git a/cmake/tribits/core/package_arch/TribitsAddAdvancedTest.cmake b/cmake/tribits/core/package_arch/TribitsAddAdvancedTest.cmake index be49149518ba..98500ecde101 100644 --- a/cmake/tribits/core/package_arch/TribitsAddAdvancedTest.cmake +++ b/cmake/tribits/core/package_arch/TribitsAddAdvancedTest.cmake @@ -41,11 +41,18 @@ include(TribitsAddAdvancedTestHelpers) include(TribitsConstants) +include(TribitsPrintList) include(AppendStringVar) include(PrintVar) -# +# Avoid quoted strings lookup variables +cmake_policy(SET CMP0054 NEW) +# NOTE: For some reason, setting this policy at the top level with TriBITS +# in TribitsCMakePolices.cmake does not affect this function. Therefore, I +# have to set it again here. + + # @FUNCTION: tribits_add_advanced_test() # # Function that creates an advanced test defined by stringing together one or @@ -75,10 +82,11 @@ include(PrintVar) # [XHOSTTYPE ...] # [EXCLUDE_IF_NOT_TRUE ...] # [DISABLED ] -# [FINAL_PASS_REGULAR_EXPRESSION | -# FINAL_FAIL_REGULAR_EXPRESSION ] +# [FINAL_PASS_REGULAR_EXPRESSION "" | +# FINAL_FAIL_REGULAR_EXPRESSION ""] # [ENVIRONMENT = = ...] # [TIMEOUT ] +# [LIST_SEPARATOR ] # [ADDED_TEST_NAME_OUT ] # ) # @@ -102,7 +110,7 @@ include(PrintVar) # (EXEC [NOEXEPREFIX] [NOEXESUFFIX] [ADD_DIR_TO_NAME] # [DIRECTORY ] # | CMND ) -# [ARGS ... ] +# [ARGS "" "" ... ""] # [MESSAGE ""] # [WORKING_DIRECTORY ] # [SKIP_CLEAN_WORKING_DIRECTORY] @@ -111,10 +119,10 @@ include(PrintVar) # [OUTPUT_FILE ] # [NO_ECHO_OUTPUT]] # [PASS_ANY -# | PASS_REGULAR_EXPRESSION "" -# | PASS_REGULAR_EXPRESSION_ALL "" "" ... "" +# | PASS_REGULAR_EXPRESSION "" "" ... +# | PASS_REGULAR_EXPRESSION_ALL "" "" ... # | STANDARD_PASS_OUTPUT ] -# [FAIL_REGULAR_EXPRESSION ""] +# [FAIL_REGULAR_EXPRESSION "" "" ...] # [ALWAYS_FAIL_ON_NONZERO_RETURN | ALWAYS_FAIL_ON_ZERO_RETURN] # [WILL_FAIL] # @@ -295,11 +303,18 @@ include(PrintVar) # by CMake, then the test will be added by ctest but the ``DISABLED`` test # property will be set (see `tribits_add_test()`_). # -# ``ENVIRONMENT = = ..``. +# ``ENVIRONMENT "=" "=" ...``. # -# If passed in, the listed environment variables will be set before -# calling the test. This is set using the built-in CTest test property -# ``ENVIRONMENT``. +# If passed in, the listed environment variables will be set by CTest +# before calling the test. This is set using the built-in CTest test +# property ``ENVIRONMENT``. Note, if the env var values contain +# semi-colons ``';'``, then replace the semi-colons ``';'`` with another +# separator ``''`` and pass in ``LIST_SEPARATOR `` so ```` +# will be replaced with ``';'`` at point of usage. If the env var values +# contain any spaces, also quote the entire variable/value pair as +# ``"="``. For example, the env var and value +# ``my_env_var="arg1 b;arg2;I have spaces"`` would need to be passed as +# ``"my_env_var=arg1 barg2I have spaces"``. # # ``TIMEOUT `` # @@ -308,6 +323,18 @@ include(PrintVar) # tests (tribits_add_test())`_). This is for the full CTest test, not # individual ``TEST_`` commands! # +# ``LIST_SEPARATOR `` +# +# String used as placeholder for the semi-colon char ``';'`` in order to +# allow pass-through. For example, if arguments to the ``ARGS`` or +# ``ENVIRONMENT`` need to use semi-colons, then replace ``';'`` with +# ``''`` (for example) such as with +# ``"somearg=arg1arg2"``, then at the point of usage, +# ``''`` will be replaced with ``';'`` and it will be passed to +# the final command as ``"somearg=arg1;arg2"`` (with as many preceding +# escape backslashes ``'\'`` in front of ``';'`` as is needed for the +# given usage context). +# # ``ADDED_TEST_NAME_OUT `` # # If specified, then on output the variable ```` will be set @@ -358,7 +385,7 @@ include(PrintVar) # ``my_python_test.py`` with ``/usr/bin/env pyhton`` at the top, you can't # just use:: # -# CMND /my_python_test.py ARGS ... +# CMND /my_python_test.py ARGS "" "" ... # # The same goes for Perl or any other scripting language. # @@ -366,6 +393,15 @@ include(PrintVar) # # CMND ${PYTHON_EXECUTABLE} ARGS /my_python_test.py ... # +# ``ARGS "" "" ... ""`` +# +# The list of command-line arguments to pass to the ``CMND`` command or +# ``EXEC`` executable. Put each argument ```` in quotes ``""`` +# if it contains any spaces. Also, of any of the individual arguments need +# to contain semi-colons ``';'`` such as ``--my-arg=a;b a;c;d``, then pass +# that quoted as ``"--my-arg=ab acd"`` where ```` +# matches the ```` argument to the input ``LIST_SEPARATOR ``. +# # By default, the output (stdout/stderr) for each test command is captured and # is then echoed to stdout for the overall test. This is done in order to be # able to grep the result to determine pass/fail. @@ -463,17 +499,17 @@ include(PrintVar) # that is to follow will determine pass or fail based on output from this # command in some way. # -# ``PASS_REGULAR_EXPRESSION ""`` +# ``PASS_REGULAR_EXPRESSION "" "" ...`` # -# If specified, the test command will be assumed to pass if it matches the -# given regular expression. Otherwise, it is assumed to fail. TIPS: -# Replace ';' with '[;]' or CMake will interpret this as an array element -# boundary. To match '.', use '[.]'. +# If specified, the test command will be assumed to pass if it matches +# **any** of the given regular expressions. Otherwise, it is assumed to +# fail. TIPS: Replace ';' with '[;]' or CMake will interpret this as an +# array element boundary. To match '.', use '[.]'. # -# ``PASS_REGULAR_EXPRESSION_ALL "" "" ... ""`` +# ``PASS_REGULAR_EXPRESSION_ALL "" "" ...`` # # If specified, the test command will be assumed to pass if the output -# matches all of the provided regular expressions. Note that this is not +# matches **all** of the provided regular expressions. Note that this is not # a capability of raw ctest and represents an extension provided by # TriBITS. NOTE: It is critical that you replace ';' with '[;]' or CMake # will interpret this as an array element boundary. @@ -485,14 +521,14 @@ include(PrintVar) # This as the result of directly passing in ``PASS_REGULAR_EXPRESSION # "End Result: TEST PASSED"``. # -# ``FAIL_REGULAR_EXPRESSION ""`` +# ``FAIL_REGULAR_EXPRESSION "" "" ...`` # -# If specified, the test command will be assumed to fail if it matches the -# given regular expression. Otherwise, it is assumed to pass. This will -# be applied and take precedence over other above pass criteria. For -# example, if even if ``PASS_REGULAR_EXPRESSION`` or -# ``PASS_REGULAR_EXPRESSION_ALL`` match, then the test will be marked as -# failed if this fail regex matches the output. +# If specified, the test command will be assumed to fail if it matches +# **any** of the given regular expressions. This will be applied and take +# precedence over other above pass criteria. For example, if even if +# ``PASS_REGULAR_EXPRESSION`` or ``PASS_REGULAR_EXPRESSION_ALL`` match, +# then the test will be marked as failed if this fail regex matches the +# output. # # ``ALWAYS_FAIL_ON_NONZERO_RETURN`` # @@ -572,6 +608,15 @@ include(PrintVar) # # **Test case Pass/Fail (tribits_add_advanced_test())** # +# The logic given below can be used to determine pass/fail criteria for a test +# case both based on what is printed in the test output **and** the return +# code for the test block command. Raw CTest, as of version 3.23, does not +# allow that. With raw CTest, one can only set determine pass/fail based the +# test output **or** the return code, but not both. This make +# `tribits_add_advanced_test()`_ more attractive to use than +# `tribits_add_test()`_ or raw ``add_test()`` in cases where it is important +# to check both. +# # The logic for how pass/fail for a ``TEST_`` ``EXEC`` or ``CMND`` case # is applied is given by:: # @@ -579,13 +624,19 @@ include(PrintVar) # TEST_CASE_PASSED = FALSE # If PASS_ANY specified: # TEST_CASE_PASSED = TRUE -# Else If PASS_REGULAR_EXPRESSION specified and "" matches: -# TEST_CASE_PASSED = TRUE +# Else If PASS_REGULAR_EXPRESSION is specified: +# For each "" in PASS_REGULAR_EXPRESSION: +# If "" matches STDOUT: +# TEST_CASE_PASSED = TRUE +# Endif +# Endforeach # Else if PASS_REGULAR_EXPRESSION_ALL specified: # TEST_CASE_PASSED = TRUE -# For each "": -# If "" does not match: +# For each "" in PASS_REGULAR_EXPRESSION_ALL: +# If "" does not match STDOUT: # TEST_CASE_PASSED = FALSE +# Endif +# Endforeach # Else # If command return code == 0: # TEST_CASE_PASSED = TRUE @@ -593,14 +644,18 @@ include(PrintVar) # Endif # # # B) Check for failing regex matching? -# If FAIL_REGULAR_EXPRESSION specified and "" matches: -# TEST_CASE_PASSED = FALSE +# If FAIL_REGULAR_EXPRESSION specified: +# For each "" in FAIL_REGULAR_EXPRESSION: +# If "" matches STDOUT: +# TEST_CASE_PASSED = FALSE +# Endif +# Endforeach # Endif # # # C) Check for return code always 0 or !=0? # If ALWAYS_FAIL_ON_NONZERO_RETURN specified and return code != 0: # TEST_CASE_PASSED = FALSE -# ElseIf ALWAYS_FAIL_ON_ZERO_RETURN specified and return code == 0: +# Else If ALWAYS_FAIL_ON_ZERO_RETURN specified and return code == 0: # TEST_CASE_PASSED = FALSE # Endif # @@ -613,6 +668,13 @@ include(PrintVar) # Endif # Endif # +# Note that the above is the exact same logic that CTest uses to determine +# pass/fail w.r.t. to the CTest properties ``PASS_REGULAR_EXPRESSION``, +# ``FAIL_REGULAR_EXPRESSION`` and ``WILL_FAIL``. (It is just that raw +# CMake/CTest, as of version 3.23, does not support any pass/fail criteria +# like ``PASS_REGULAR_EXPRESSION_ALL`` or +# ``ALWAYS_FAIL_ON_NONZERO_RETURN``/``ALWAYS_FAIL_ON_ZERO_RETURN``.) +# # .. _Overall Pass/Fail (tribits_add_advanced_test()): # # **Overall Pass/Fail (tribits_add_advanced_test())** @@ -623,26 +685,37 @@ include(PrintVar) # # However, this can be changed by setting one of the following optional arguments: # -# ``FINAL_PASS_REGULAR_EXPRESSION `` +# ``FINAL_PASS_REGULAR_EXPRESSION "" "" ...`` # # If specified, the test will be assumed to pass if the output matches -# ````. Otherwise, it will be assumed to fail. +# **any** of the provided regular expressions ````. Otherwise, it +# will be assumed to fail. (Sets the CTest property +# ``PASS_REGULAR_EXPRESSION`` for the overall test.) # -# ``FINAL_FAIL_REGULAR_EXPRESSION `` +# ``FINAL_FAIL_REGULAR_EXPRESSION "" "" ...`` # # If specified, the test will be assumed to fail if the output matches -# ````. Otherwise, it will be assumed to fail. +# **any** of the provided regular expressions ```` regardless if +# other criteria would have the test passing. (Sets the CTest property +# ``FAIL_REGULAR_EXPRESSION`` for the overall test.) +# +# **NOTE:** It is **not** recommended to set ``FINAL_PASS_REGULAR_EXPRESSION`` +# or ``FINAL_FAIL_REGULAR_EXPRESSION`` directly, but instead to determine +# pass/fail for each test case individually as described in `TEST_ +# EXEC/CMND Test Blocks and Arguments (tribits_add_advanced_test())`_ and +# `Test case Pass/Fail (tribits_add_advanced_test())`_. Otherwise, the test +# will confuse most people and the output behavior will seem very strange. # # .. _Argument Parsing and Ordering (tribits_add_advanced_test()): # # **Argument Parsing and Ordering (tribits_add_advanced_test())** # -# The basic tool used for parsing the arguments to this function is the macro -# ``cmake_parse_arguments()`` which has a certain set of behaviors. The -# parsing using ``cmake_parse_arguments()`` is actually done in two phases. -# There is a top-level parsing of the "overall" arguments listed in `Overall -# Arguments (tribits_add_advanced_test())`_ that also pulls out the test -# blocks. Then there is a second level of parsing using +# The basic tool used for parsing the arguments to this function is the +# command ``cmake_parse_arguments()`` which has a certain set of behaviors. +# The parsing using ``cmake_parse_arguments()`` is actually done in two +# phases. There is a top-level parsing of the "overall" arguments listed in +# `Overall Arguments (tribits_add_advanced_test())`_ that also pulls out the +# test blocks. Then there is a second level of parsing using # ``cmake_parse_arguments()`` for each of the ``TEST_`` blocks. Because # of this usage, there are a few restrictions that one needs to be aware of # when using ``tribits_add_advanced_test()``. This short sections tries to @@ -833,11 +906,6 @@ function(tribits_add_advanced_test TEST_NAME_IN) set(TEST_NAME ${TEST_NAME_IN}) endif() - # Avoid quoted strings lookup variables - cmake_policy(SET CMP0054 NEW) - # NOTE: For some reason, setting this policy at the top level with TriBITS - # in TribitsCMakePolices.cmake does not affect this function. Therefore, I - # have to set it again here. # # A) Parse the overall arguments and figure out how many tests @@ -852,20 +920,30 @@ function(tribits_add_advanced_test TEST_NAME_IN) foreach( TEST_CMND_IDX RANGE ${MAX_NUM_TEST_CMND_IDX}) list( APPEND TEST_IDX_LIST TEST_${TEST_CMND_IDX} ) endforeach() - #print_var(TEST_IDX_LIST) + + set(optionsList FAIL_FAST RUN_SERIAL SKIP_CLEAN_OVERALL_WORKING_DIRECTORY) + + set(oneValueKeywordsList DISABLED) + + set(multiValueKeywordsList + ${TEST_IDX_LIST} OVERALL_WORKING_DIRECTORY + LIST_SEPARATOR + OVERALL_NUM_MPI_PROCS OVERALL_NUM_TOTAL_CORES_USED + CATEGORIES COMM HOST XHOST HOSTTYPE XHOSTTYPE EXCLUDE_IF_NOT_TRUE + FINAL_PASS_REGULAR_EXPRESSION FINAL_FAIL_REGULAR_EXPRESSION + TIMEOUT ENVIRONMENT KEYWORDS + ADDED_TEST_NAME_OUT + ) cmake_parse_arguments( - #prefix - PARSE - #options - "FAIL_FAST;RUN_SERIAL;SKIP_CLEAN_OVERALL_WORKING_DIRECTORY" - # one_value_keywords - "DISABLED" - # multi_value_keywords - "${TEST_IDX_LIST};OVERALL_WORKING_DIRECTORY;KEYWORDS;COMM;OVERALL_NUM_MPI_PROCS;OVERALL_NUM_TOTAL_CORES_USED;FINAL_PASS_REGULAR_EXPRESSION;CATEGORIES;HOST;XHOST;HOSTTYPE;XHOSTTYPE;EXCLUDE_IF_NOT_TRUE;FINAL_FAIL_REGULAR_EXPRESSION;TIMEOUT;ENVIRONMENT;ADDED_TEST_NAME_OUT" - ${ARGN} - ) + PARSE_ARGV 1 # NOTE: One named argument to skip over + PARSE # prefix + "${optionsList}" + "${oneValueKeywordsList}" + "${multiValueKeywordsList}" + ) + tribits_check_for_unparsed_arguments() tribits_add_advanced_test_check_exceed_max_num_test_blocks() if(PARSE_ADDED_TEST_NAME_OUT) @@ -960,6 +1038,7 @@ function(tribits_add_advanced_test TEST_NAME_IN) "#\n" "\n" "set( TEST_NAME ${TEST_NAME} )\n" + "set( LIST_SEPARATOR \"${PARSE_LIST_SEPARATOR}\" )\n" ) # Loop through each test case @@ -1001,8 +1080,6 @@ function(tribits_add_advanced_test TEST_NAME_IN) # Parse the test command case - #print_var(PARSE_TEST_${TEST_CMND_IDX}) - # Search to see if we are copying files or not for this TEST_ block ... set(PARSE_COPY_FILES_TO_TEST_DIR) @@ -1035,26 +1112,32 @@ function(tribits_add_advanced_test TEST_NAME_IN) tribits_assert_parse_arg_zero_or_one_value(PARSE SOURCE_DIR) tribits_assert_parse_arg_zero_or_one_value(PARSE DEST_DIR) - set(PARSE_EXEC) - set(PARSE_CMND) + set(PARSE_EXEC "") + set(PARSE_CMND "") else() # Parse TEST_ block args for types EXEC and CMND + set(testBlockOptionsList NOEXEPREFIX NOEXESUFFIX NO_ECHO_OUTPUT PASS_ANY + STANDARD_PASS_OUTPUT ALWAYS_FAIL_ON_NONZERO_RETURN ALWAYS_FAIL_ON_ZERO_RETURN + WILL_FAIL ADD_DIR_TO_NAME SKIP_CLEAN_WORKING_DIRECTORY + ) + + set(testBlockMultiValueKeywordsList EXEC CMND ARGS DIRECTORY MESSAGE + WORKING_DIRECTORY OUTPUT_FILE NUM_MPI_PROCS NUM_TOTAL_CORES_USED + PASS_REGULAR_EXPRESSION_ALL FAIL_REGULAR_EXPRESSION PASS_REGULAR_EXPRESSION + ) + cmake_parse_arguments( - #prefix - PARSE - #options - "NOEXEPREFIX;NOEXESUFFIX;NO_ECHO_OUTPUT;PASS_ANY;STANDARD_PASS_OUTPUT;ALWAYS_FAIL_ON_NONZERO_RETURN;ALWAYS_FAIL_ON_ZERO_RETURN;WILL_FAIL;ADD_DIR_TO_NAME;SKIP_CLEAN_WORKING_DIRECTORY" - # one_value_keywords - "" - # multi_value_keywords - "EXEC;CMND;ARGS;DIRECTORY;MESSAGE;WORKING_DIRECTORY;OUTPUT_FILE;NUM_MPI_PROCS;NUM_TOTAL_CORES_USED;PASS_REGULAR_EXPRESSION_ALL;FAIL_REGULAR_EXPRESSION;PASS_REGULAR_EXPRESSION" + PARSE #prefix + "${testBlockOptionsList}" + "" # one_value_keywords + "${testBlockMultiValueKeywordsList}" ${PARSE_TEST_${TEST_CMND_IDX}} ) - - tribits_check_for_unparsed_arguments() + + tribits_check_for_unparsed_arguments(PARSE) # ToDo: Use a different prefix! endif() @@ -1062,11 +1145,7 @@ function(tribits_add_advanced_test TEST_NAME_IN) # Set up the command that will be written into the cmake -P *.cmake file # - set(ARGS_STR ${PARSE_ARGS}) - #print_var(ARGS_STR) - #if (PARSE_ARGS) - # tribits_join_exec_process_set_args( ARGS_STR ${PARSE_ARGS} ) - #endif() + set(ARGS_STR "${PARSE_ARGS}") if (PARSE_EXEC) @@ -1131,7 +1210,6 @@ function(tribits_add_advanced_test TEST_NAME_IN) tribits_add_test_get_test_cmnd_array( TEST_CMND_ARRAY "${EXECUTABLE_PATH}" "${NUM_PROCS_USED}" ${ARGS_STR} ) - #print_var(TEST_CMND_ARRAY) elseif (PARSE_CMND) @@ -1261,8 +1339,7 @@ function(tribits_add_advanced_test TEST_NAME_IN) # Write the command to be run for EXEC and CMND blocks ... tribits_join_exec_process_set_args( TEST_CMND_STR "${TEST_CMND_ARRAY}" ) - #print_var(TEST_CMND_STR) - + string(APPEND TEST_SCRIPT_STR "\n" "set( TEST_${TEST_CMND_IDX}_CMND ${TEST_CMND_STR} )\n" diff --git a/cmake/tribits/core/package_arch/TribitsAddExecutable.cmake b/cmake/tribits/core/package_arch/TribitsAddExecutable.cmake index aa0f100dec42..285afc90825d 100644 --- a/cmake/tribits/core/package_arch/TribitsAddExecutable.cmake +++ b/cmake/tribits/core/package_arch/TribitsAddExecutable.cmake @@ -42,19 +42,14 @@ include(TribitsAddExecutableTestHelpers) include(TribitsCommonArgsHelpers) include(TribitsAddTestHelpers) include(TribitsGeneralMacros) +include(TribitsLibIsTestOnly) include(TribitsReportInvalidTribitsUsage) include(PrintVar) include(AppendSet) include(CMakeParseArguments) -### -### WARNING: See "NOTES TO DEVELOPERS" at the bottom of the file -### TribitsPackageMacros.cmake before trying to change anything in this file! -### - -# # @FUNCTION: tribits_add_executable() # # Function used to create an executable (typically for a test or example), @@ -180,19 +175,7 @@ include(CMakeParseArguments) # package or any upstream SE packages can *NOT* be listed! TriBITS # automatically links non ``TESTONLY`` libraries in this package and # upstream packages to the executable. The only libraries that should be -# listed in this argument are either ``TESTONLY`` libraries. The include -# directories for each test-only library will automatically be added -# using:: -# -# include_directories(${_INCLUDE_DIRS}) -# -# where ``_INCLUDE_DIRS`` was set by:: -# -# tribits_add_library( ... TESTONLY ...) -# -# Therefore, to link to a defined ``TESTONLY`` library in any upstream -# enabled package, one just needs to pass in the library name through -# ``TESTONLYLIBS ... ...`` and that is it! +# listed in this argument are either ``TESTONLY`` libraries. # # ``IMPORTEDLIBS ...`` # @@ -334,11 +317,138 @@ function(tribits_add_executable EXE_NAME) message("") message("TRIBITS_ADD_EXECUTABLE: ${EXE_NAME} ${ARGN}") endif() - + + tribits_add_executable_assert_correct_call_context() + + # + # A) Parse the input arguments + # + + cmake_parse_arguments( + #prefix + PARSE + #options + "NOEXEPREFIX;NOEXESUFFIX;ADD_DIR_TO_NAME;INSTALLABLE" + #one_value_keywords + "" + #multi_value_keywords + "SOURCES;CATEGORIES;HOST;XHOST;HOSTTYPE;XHOSTTYPE;EXCLUDE_IF_NOT_TRUE;DIRECTORY;TESTONLYLIBS;IMPORTEDLIBS;DEPLIBS;COMM;LINKER_LANGUAGE;TARGET_DEFINES;DEFINES;ADDED_EXE_TARGET_NAME_OUT" + ${ARGN} + ) + + tribits_check_for_unparsed_arguments() + + # Executable not added by default! + if(PARSE_ADDED_EXE_TARGET_NAME_OUT) + set(${PARSE_ADDED_EXE_TARGET_NAME_OUT} "" PARENT_SCOPE) + endif() + + set(EXE_BINARY_NAME ${EXE_NAME}) + tribits_add_executable_adjust_exe_name(EXE_BINARY_NAME) + + tribits_add_executable_is_skipped(skipAddExecutable) + if (skipAddExecutable) + return() + endif() + + tribits_add_executable_get_adjusted_sources_list(EXE_SOURCES) + + tribits_add_executable_assert_testonlylibs() + + tribits_add_executable_assert_importedlibs() + + tribits_add_executable_convert_from_deplibs() + + # + # B) Add the executable and set its properties + # + + if(${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("TRIBITS_ADD_EXECUTABLE: add_executable(${EXE_BINARY_NAME} ${EXE_SOURCES})") + endif() + add_executable(${EXE_BINARY_NAME} ${EXE_SOURCES}) + append_global_set(${PARENT_PACKAGE_NAME}_ALL_TARGETS ${EXE_BINARY_NAME}) + + if(PARSE_ADDED_EXE_TARGET_NAME_OUT) + set(${PARSE_ADDED_EXE_TARGET_NAME_OUT} ${EXE_BINARY_NAME} PARENT_SCOPE) + endif() + + if (PARSE_DEFINES) + message(WARNING "WARNING: Passing extra defines through 'DEFINES' ${PARSE_DEFINES}" + " is deprecated. Instead, pass them through 'TARGET_DEFINES'. The 'DEFINES'" + " argument was incorrectly implemented by calling add_definitions() which has" + " directory scope and not function scope as was documented. This resulted in" + " confusing behavior. If one wishes to set defines at the directly level," + " just call add_definitions() directly.") + add_definitions(${PARSE_DEFINES}) + endif() + + if (PARSE_TARGET_DEFINES) + target_compile_definitions(${EXE_BINARY_NAME} PUBLIC ${PARSE_TARGET_DEFINES}) + endif() + + if(PARSE_NOEXESUFFIX AND NOT WIN32) + set_target_properties(${EXE_BINARY_NAME} PROPERTIES SUFFIX "") + else() + set_target_properties(${EXE_BINARY_NAME} PROPERTIES SUFFIX + ${${PROJECT_NAME}_CMAKE_EXECUTABLE_SUFFIX}) + endif() + + tribits_set_linker_language_from_arg( ${EXE_BINARY_NAME} + "${PARSE_LINKER_LANGUAGE}" ) + + assert_defined(${PROJECT_NAME}_LINK_SEARCH_START_STATIC) + if (${PROJECT_NAME}_LINK_SEARCH_START_STATIC) + #message("${EXE_BINARY_NAME}: Adding property LINK_SEARCH_START_STATIC") + set_property(TARGET ${EXE_BINARY_NAME} PROPERTY LINK_SEARCH_START_STATIC 1) + endif() + + if(PARSE_DIRECTORY) + set_target_properties( ${EXE_BINARY_NAME} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${PARSE_DIRECTORY} ) + endif() + + set_property(TARGET ${EXE_BINARY_NAME} APPEND PROPERTY + LABELS ${PACKAGE_NAME}Exes ${PARENT_PACKAGE_NAME}Exes) + # - # Confirm that package and subpackage macros/functions have been called inteh correct order + # C) Link ${EXE_BINARY_NAME} to direct upstream libraries # - + + target_link_libraries(${EXE_BINARY_NAME} PUBLIC ${${PACKAGE_NAME}_LIBRARIES}) + foreach(depPkg IN LISTS ${PACKAGE_NAME}_LIB_ENABLED_DEPENDENCIES + ${PACKAGE_NAME}_TEST_ENABLED_DEPENDENCIES + ) + target_link_libraries(${EXE_BINARY_NAME} PUBLIC ${depPkg}::all_libs) + endforeach() + foreach(testOnlyLib ${PARSE_TESTONLYLIBS}) + target_link_libraries(${EXE_BINARY_NAME} PUBLIC + "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}${testOnlyLib}") + endforeach() + + # + # D) Install if asked + # + + if(${PROJECT_NAME}_INSTALL_EXECUTABLES AND PARSE_INSTALLABLE) + install( + TARGETS ${EXE_BINARY_NAME} + EXPORT ${PROJECT_NAME} + DESTINATION ${${PROJECT_NAME}_INSTALL_RUNTIME_DIR} + COMPONENT ${PACKAGE_NAME} + ) + endif() + +endfunction() + + +# Assert tribits_add_executable() is called in the correct context +# +# NOTE: This read the variables from the enclosing tribits_add_executable() +# function call scope. +# +function(tribits_add_executable_assert_correct_call_context) + if (CURRENTLY_PROCESSING_SUBPACKAGE) # This is a subpackage being processed @@ -373,143 +483,155 @@ function(tribits_add_executable EXE_NAME) endif() +endfunction() - # - # A) Parse the input arguments - # - cmake_parse_arguments( - #prefix - PARSE - #options - "NOEXEPREFIX;NOEXESUFFIX;ADD_DIR_TO_NAME;INSTALLABLE" - #one_value_keywords - "" - #multi_value_keywords - "SOURCES;CATEGORIES;HOST;XHOST;HOSTTYPE;XHOSTTYPE;EXCLUDE_IF_NOT_TRUE;DIRECTORY;TESTONLYLIBS;IMPORTEDLIBS;DEPLIBS;COMM;LINKER_LANGUAGE;TARGET_DEFINES;DEFINES;ADDED_EXE_TARGET_NAME_OUT" - ${ARGN} - ) +# Modify EXE_BINARY_NAME based in passed-in args +# +# NOTE: This read the variables from the enclosing tribits_add_executable() +# function call scope. +# +function(tribits_add_executable_adjust_exe_name exeBinaryNameInOut) - tribits_check_for_unparsed_arguments() + set(exeBinaryName ${${exeBinaryNameInOut}}) + if (PARSE_ADD_DIR_TO_NAME) + set(dirName "") + tribits_create_name_from_current_source_directory(dirName) + set(exeBinaryName ${dirName}_${exeBinaryName}) + endif() - if(PARSE_ADDED_EXE_TARGET_NAME_OUT) - set(${PARSE_ADDED_EXE_TARGET_NAME_OUT} PARENT_SCOPE) + if (DEFINED PACKAGE_NAME AND NOT PARSE_NOEXEPREFIX) + set(exeBinaryName ${PACKAGE_NAME}_${exeBinaryName}) endif() + set(${exeBinaryNameInOut} ${exeBinaryName} PARENT_SCOPE) - # - # B) Exclude building the test executable based on some criteria - # +endfunction() + + +# Check if to skip adding the executable based on different criteria +# +# NOTE: This read the variables from the enclosing tribits_add_executable() +# function call scope. +# +function(tribits_add_executable_is_skipped skipAddExecutableOut) + + set(skipAddExecutable FALSE) set(ADD_THE_TEST FALSE) set(TEST_NAME ${EXE_NAME}) # For error message tribits_add_test_process_categories(ADD_THE_TEST) if (NOT ADD_THE_TEST) - return() + set(skipAddExecutable TRUE) endif() - set(TEST_NAME) + set(TEST_NAME "") set(ADD_THE_TEST FALSE) tribits_add_test_process_host_hosttype(ADD_THE_TEST) if (NOT ADD_THE_TEST) - return() + set(skipAddExecutable TRUE) endif() tribits_process_comm_args(ADD_SERIAL_EXE ADD_MPI_EXE ${PARSE_COMM}) if (NOT ADD_SERIAL_EXE AND NOT ADD_MPI_EXE) - return() - endif() - - # - # C) Add the executable - # - - set(LIBRARY_NAME_PREFIX "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}") - - if (NOT TRIBITS_ADD_EXECUTABLE_UNIT_TESTING) - tribits_include_directories(REQUIRED_DURING_INSTALLATION_TESTING - ${${PACKAGE_NAME}_INCLUDE_DIRS}) -# set_property(DIRECTORY APPEND PROPERTY PACKAGE_LIBRARY_DIRS -# ${${PACKAGE_NAME}_LIBRARY_DIRS}) - endif() - - set (EXE_SOURCES) - set(EXE_BINARY_NAME ${EXE_NAME}) - - # If requested create a modifier for the name that will be inserted between - # the package name and the given name or exe_name for the test - if(PARSE_ADD_DIR_TO_NAME) - set(DIRECTORY_NAME "") - tribits_create_name_from_current_source_directory(DIRECTORY_NAME) - set(EXE_BINARY_NAME ${DIRECTORY_NAME}_${EXE_BINARY_NAME}) + set(skipAddExecutable TRUE) endif() - if(DEFINED PACKAGE_NAME AND NOT PARSE_NOEXEPREFIX) - set(EXE_BINARY_NAME ${PACKAGE_NAME}_${EXE_BINARY_NAME}) - endif() - - # Exclude the build if requested if (${EXE_BINARY_NAME}_EXE_DISABLE) message("-- " "${EXE_BINARY_NAME} EXE NOT being built due to ${EXE_BINARY_NAME}_EXE_DISABLE=" "'${${EXE_BINARY_NAME}_EXE_DISABLE}'") - return() + set(skipAddExecutable TRUE) endif() - # If exe is in subdirectory prepend that dir name to the source files + set(${skipAddExecutableOut} ${skipAddExecutable} PARENT_SCOPE) + +endfunction() + + +# Get adjusted list of source files +# +# NOTE: This read the variables from the enclosing tribits_add_executable() +# function call scope. +# +function(tribits_add_executable_get_adjusted_sources_list exeSourcesOut) + + set(exeSources "") if(PARSE_DIRECTORY ) - foreach( SOURCE_FILE ${PARSE_SOURCES} ) - if(IS_ABSOLUTE ${SOURCE_FILE}) - set (EXE_SOURCES ${EXE_SOURCES} ${SOURCE_FILE}) + foreach( srcFile ${PARSE_SOURCES} ) + if(IS_ABSOLUTE ${srcFile}) + list(APPEND exeSources "${srcFile}") else() - set (EXE_SOURCES ${EXE_SOURCES} ${PARSE_DIRECTORY}/${SOURCE_FILE}) + list(APPEND exeSources "${PARSE_DIRECTORY}/${srcFile}") endif() endforeach( ) else() - foreach( SOURCE_FILE ${PARSE_SOURCES} ) - set (EXE_SOURCES ${EXE_SOURCES} ${SOURCE_FILE}) + foreach( srcFile ${PARSE_SOURCES} ) + list(APPEND exeSources "${srcFile}") endforeach( ) endif() + set(${exeSourcesOut} ${exeSources} PARENT_SCOPE) + +endfunction() + + +# Assert tribits_add_executable() TESTONLYLIBS +# +# NOTE: This read the variables from the enclosing tribits_add_executable() +# function call scope. +# +function(tribits_add_executable_assert_testonlylibs) # Assert that TESTONLYLIBS only contains TESTONLY libs! - foreach(TESTONLYLIB ${PARSE_TESTONLYLIBS}) - set(PREFIXED_LIB "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}${TESTONLYLIB}") - if (NOT ${PREFIXED_LIB}_INCLUDE_DIRS) - message(FATAL_ERROR "ERROR: '${TESTONLYLIB}' in TESTONLYLIBS not a TESTONLY lib!" + foreach(testOnlyLib ${PARSE_TESTONLYLIBS}) + set(prefixedTestOnlyLib "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}${testOnlyLib}") + tribits_lib_is_testonly(${prefixedTestOnlyLib} libIsTestOnlyLib) + if (NOT libIsTestOnlyLib) + message(FATAL_ERROR "ERROR: '${testOnlyLib}' in TESTONLYLIBS not a TESTONLY lib!" " If this a regular library in this SE package or in an dependent upstream SE" " package then TriBITS will link automatically to it. If you remove this and it" " does not link, then you need to add a new SE package dependency to" " this SE package's dependencies file" " ${${PACKAGE_NAME}_SOURCE_DIR}/cmake/Dependencies.cmake") elseif(PARSE_INSTALLABLE) - message(FATAL_ERROR "ERROR: TESTONLY lib '${TESTONLYLIB}' not allowed with" + message(FATAL_ERROR "ERROR: TESTONLY lib '${testOnlyLib}' not allowed with" " INSTALLABLE executable! An INSTALLABLE executable can only depend on" " non-TESTONLY libraries! Otherwise, when shared libs are used, and" " TESTONLY library would not be installed and the installed executable" " would be unusable!" ) endif() endforeach() +endfunction() + + +# Assert tribits_add_executable() IMPORTEDLIBS +# +# NOTE: This read the variables from the enclosing tribits_add_executable() +# function call scope. +# +function(tribits_add_executable_assert_importedlibs) # Assert that IMPORTEDLIBS are not TESTONLY libs are not regular package # libs! - foreach(IMPORTEDLIB ${PARSE_IMPORTEDLIBS}) - set(PREFIXED_LIB "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}${IMPORTEDLIB}") - if (${PREFIXED_LIB}_INCLUDE_DIRS) + foreach(importedLib ${PARSE_IMPORTEDLIBS}) + set(prefixedImportedLib "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}${importedLib}") + tribits_lib_is_testonly(${prefixedImportedLib} importedLibIsTestOnlyLib) + if (libIsTestOnly) message(FATAL_ERROR - "ERROR: Lib '${IMPORTEDLIB}' being passed through" + "ERROR: Lib '${importedLib}' being passed through" " IMPORTEDLIBS is not allowed to be a TESTONLY lib!" " Use TESTONLYLIBS instead!" ) endif() - list(FIND ${PACKAGE_NAME}_LIBRARIES "${PACKAGE_NAME}::${PREFIXED_LIB}" - FOUND_PREFIXED_LIB_IN_PKG_LIBRARIES_IDX) - if (NOT FOUND_PREFIXED_LIB_IN_PKG_LIBRARIES_IDX EQUAL -1) + list(FIND ${PACKAGE_NAME}_LIBRARIES "${PACKAGE_NAME}::${prefixedImportedLib}" + foundPrefixedImportedLibInPkgLibs_idx) + if (NOT foundPrefixedImportedLibInPkgLibs_idx EQUAL -1) message(FATAL_ERROR - "ERROR: Lib '${IMPORTEDLIB}' in IMPORTEDLIBS is in" + "ERROR: Lib '${importedLib}' in IMPORTEDLIBS is in" " this SE package and is *not* an external lib!" " TriBITS takes care of linking against libs the current" - " SE package automatically. Please remove '${IMPORTEDLIB}' from IMPORTEDLIBS!") - elseif (TARGET ${PREFIXED_LIB}) + " SE package automatically. Please remove '${importedLib}' from IMPORTEDLIBS!") + elseif (TARGET ${prefixedImportedLib}) message(FATAL_ERROR - "ERROR: Lib '${IMPORTEDLIB}' being passed through" + "ERROR: Lib '${importedLib}' being passed through" " IMPORTEDLIBS is *not* an external library but instead is a library" " defined in this CMake project!" " TriBITS takes care of linking against libraries in dependent upstream" @@ -520,173 +642,44 @@ function(tribits_add_executable EXE_NAME) endif() endforeach() +endfunction() + + +# Convert from tribits_add_executable() DEPLIBS to IMPORTEDLIBS and TESTONLYLIBS +# +# NOTE: This is a macro as it updates local variables in the +# tribits_add_executable() scope! +# +macro(tribits_add_executable_convert_from_deplibs) + # Convert from old DEPLIBS to TESTONLYLIBS and IMPORTEDLIBS - foreach(DEPLIB ${PARSE_DEPLIBS}) - set(PREFIXED_LIB "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}${DEPLIB}") - if (${PREFIXED_LIB}_INCLUDE_DIRS) - message(WARNING "WARNING: Passing TESTONLY lib '${DEPLIB}' through DEPLIBS" + foreach(depLib ${PARSE_DEPLIBS}) + set(prefixedDepLib "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}${depLib}") + tribits_lib_is_testonly(${prefixedDepLib} depLibIsTestOnlyLib) + if (depLibIsTestOnlyLib) + message(WARNING "WARNING: Passing TESTONLY lib '${depLib}' through DEPLIBS" " is deprecated! Instead, please pass through TESTONLYLIBS instead!" " DEPLIBS is deprecated!") - list(APPEND PARSE_TESTONLYLIBS ${DEPLIB}) - elseif (TARGET ${PREFIXED_LIB}) - message(WARNING "WARNING: Passing non-TESTONLY lib '${DEPLIB}' through DEPLIBS" - " is deprecated! The library '${DEPLIB}' appears to be a" + list(APPEND PARSE_TESTONLYLIBS ${depLib}) + elseif (TARGET ${prefixedDepLib}) + message(WARNING "WARNING: Passing non-TESTONLY lib '${depLib}' through DEPLIBS" + " is deprecated! The library '${depLib}' appears to be a" " library defined in this CMake project." " TriBITS takes care of linking against libraries in dependent upstream" - " SE packages. Therefore, please remove '${DEPLIB}' from this list." + " SE packages. Therefore, please remove '${depLib}' from this list." " If you want to link to a library from an upstream SE" " package, then add the SE package name to the appropriate category" " in this SE package's dependencies file: " " ${${PACKAGE_NAME}_SOURCE_DIR}/cmake/Dependencies.cmake") + # ToDo: Convert the above 'WARNING' to 'SEND_ERROR' else() - message(WARNING "WARNING: Passing external lib '${DEPLIB}' through" + message(WARNING "WARNING: Passing external lib '${depLib}' through" " DEPLIBS is deprecated! Instead, pass through IMPORTEDLIBS!" " DEPLIBS is deprecated!" " Please note that only external libs are allowed to be passed through" " IMPORTEDLIBS.") - list(APPEND PARSE_IMPORTEDLIBS ${DEPLIB}) - endif() - endforeach() - - foreach(TESTONLYLIB_IN ${PARSE_TESTONLYLIBS}) - set(TESTONLYLIB "${LIBRARY_NAME_PREFIX}${TESTONLYLIB_IN}") - if (${TESTONLYLIB}_INCLUDE_DIRS) - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message(STATUS "Adding include directories ${TESTONLYLIB}_INCLUDE_DIRS ...") - endif() - include_directories(${${TESTONLYLIB}_INCLUDE_DIRS}) + list(APPEND PARSE_IMPORTEDLIBS ${depLib}) endif() endforeach() - if (PARSE_DEFINES) - message(WARNING "WARNING: Passing extra defines through 'DEFINES' ${PARSE_DEFINES}" - " is deprecated. Instead, pass them through 'TARGET_DEFINES'. The 'DEFINES'" - " argument was incorrectly implemented by calling add_definitions() which has" - " directory scope and not function scope as was documented. This resulted in" - " confusing behavior. If one wishes to set defines at the directly level," - " just call add_definitions() directly.") - add_definitions(${PARSE_DEFINES}) - endif() - - if(${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("TRIBITS_ADD_EXECUTABLE: add_executable(${EXE_BINARY_NAME} ${EXE_SOURCES})") - endif() - add_executable(${EXE_BINARY_NAME} ${EXE_SOURCES}) - append_global_set(${PARENT_PACKAGE_NAME}_ALL_TARGETS ${EXE_BINARY_NAME}) - - if(PARSE_ADDED_EXE_TARGET_NAME_OUT) - set(${PARSE_ADDED_EXE_TARGET_NAME_OUT} ${EXE_BINARY_NAME} PARENT_SCOPE) - endif() - - if (PARSE_TARGET_DEFINES) - target_compile_definitions(${EXE_BINARY_NAME} PUBLIC ${PARSE_TARGET_DEFINES}) - endif() - - if(PARSE_NOEXESUFFIX AND NOT WIN32) - set_target_properties(${EXE_BINARY_NAME} PROPERTIES SUFFIX "") - else() - set_target_properties(${EXE_BINARY_NAME} PROPERTIES SUFFIX - ${${PROJECT_NAME}_CMAKE_EXECUTABLE_SUFFIX}) - endif() - - tribits_set_linker_language_from_arg( ${EXE_BINARY_NAME} - "${PARSE_LINKER_LANGUAGE}" ) - - set(LINK_LIBS) - - # First, add in the passed in TESTONLY dependent libraries - if (PARSE_TESTONLYLIBS) - foreach(LIB ${PARSE_TESTONLYLIBS}) - list(APPEND LINK_LIBS "${LIBRARY_NAME_PREFIX}${LIB}") - endforeach() - endif() - - # Second, add the package's own regular libraries - if(NOT ${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING) - list(APPEND LINK_LIBS ${${PACKAGE_NAME}_LIBRARIES}) - else() - list(APPEND LINK_LIBS ${${PACKAGE_NAME}_INSTALLATION_LIBRARIES}) - endif() - - # Third, add the IMPORTEDLIBS - if (PARSE_IMPORTEDLIBS) - list(APPEND LINK_LIBS ${PARSE_IMPORTEDLIBS}) - endif() - - # Call include_directories() and link_directories(...) for upstream - # dependent Packages and TPLs and accumulate the list of libraries that will - # need to be linked to. - - if(NOT ${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING - AND NOT ${PACKAGE_NAME}_INCLUDE_DIRS - ) - # No libraries have been added for this package so - # add the upstream package and TPL includes and libraries - tribits_sort_and_append_package_include_and_link_dirs_and_libs( - ${PACKAGE_NAME} LIB LINK_LIBS) - tribits_sort_and_append_tpl_include_and_link_dirs_and_libs( - ${PACKAGE_NAME} LIB LINK_LIBS) - endif() - - tribits_sort_and_append_package_include_and_link_dirs_and_libs( - ${PACKAGE_NAME} TEST LINK_LIBS) - - if(NOT ${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING) - tribits_sort_and_append_tpl_include_and_link_dirs_and_libs( - ${PACKAGE_NAME} TEST LINK_LIBS) - else() - list(APPEND LINK_LIBS ${${PACKAGE_NAME}_INSTALLATION_TPL_LIBRARIES}) - endif() - - # Last, add last_lib to get extra link options on the link line - if (${PROJECT_NAME}_EXTRA_LINK_FLAGS) - list(APPEND LINK_LIBS last_lib) - endif() - - if (${PROJECT_NAME}_DUMP_LINK_LIBS) - message("-- ${EXE_NAME}:LINK_LIBS='${LINK_LIBS}'") - endif() - - target_link_libraries(${EXE_BINARY_NAME} PUBLIC ${LINK_LIBS}) - - assert_defined(${PROJECT_NAME}_LINK_SEARCH_START_STATIC) - if (${PROJECT_NAME}_LINK_SEARCH_START_STATIC) - #message("${EXE_BINARY_NAME}: Adding property LINK_SEARCH_START_STATIC") - set_property(TARGET ${EXE_BINARY_NAME} PROPERTY LINK_SEARCH_START_STATIC 1) - endif() - - if(PARSE_DIRECTORY) - set_target_properties( ${EXE_BINARY_NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${PARSE_DIRECTORY} ) - endif() - - set_property(TARGET ${EXE_BINARY_NAME} APPEND PROPERTY - LABELS ${PACKAGE_NAME}Exes ${PARENT_PACKAGE_NAME}Exes) - - if(${PROJECT_NAME}_INSTALL_EXECUTABLES AND PARSE_INSTALLABLE) - install( - TARGETS ${EXE_BINARY_NAME} - EXPORT ${PROJECT_NAME} - DESTINATION ${${PROJECT_NAME}_INSTALL_RUNTIME_DIR} - COMPONENT ${PACKAGE_NAME} - ) - endif() -endfunction() - - -# -# Setup include directories and library dependencies -# - -#if (${PROJECT_NAME}_VERBOSE_CONFIGURE) -# message("TribitsAddExecutable.cmake") -# print_var(${PACKAGE_NAME}_INCLUDE_DIRS) -# print_var(${PACKAGE_NAME}_LIBRARY_DIRS) -#endif() -# -#if (NOT TRIBITS_ADD_EXECUTABLE_UNIT_TESTING) -# include_directories(REQUIRED_DURING_INSTALLATION_TESTING -# ${${PACKAGE_NAME}_INCLUDE_DIRS}) -# set_property(DIRECTORY APPEND PROPERTY PACKAGE_LIBRARY_DIRS -# ${${PACKAGE_NAME}_LIBRARY_DIRS}) -#endif() +endmacro() diff --git a/cmake/tribits/core/package_arch/TribitsAddExecutableAndTest.cmake b/cmake/tribits/core/package_arch/TribitsAddExecutableAndTest.cmake index 46b2b13a088d..298f64ac75c7 100644 --- a/cmake/tribits/core/package_arch/TribitsAddExecutableAndTest.cmake +++ b/cmake/tribits/core/package_arch/TribitsAddExecutableAndTest.cmake @@ -78,7 +78,7 @@ macro(tribits_add_test_wrapper) endif() endmacro() -# + # @FUNCTION: tribits_add_executable_and_test() # # Add an executable and a test (or several tests) all in one shot (just calls @@ -113,6 +113,7 @@ endmacro() # [ENVIRONMENT = = ...] # [INSTALLABLE] # [TIMEOUT ] +# [LIST_SEPARATOR ] # [ADDED_EXE_TARGET_NAME_OUT ] # [ADDED_TESTS_NAMES_OUT ] # ) @@ -159,7 +160,7 @@ function(tribits_add_executable_and_test EXE_NAME) #one_value_keywords "DISABLED" #mulit_value_keywords - "SOURCES;DEPLIBS;TESTONLYLIBS;IMPORTEDLIBS;NAME;NAME_POSTFIX;NUM_MPI_PROCS;DIRECTORY;KEYWORDS;COMM;ARGS;PASS_REGULAR_EXPRESSION;FAIL_REGULAR_EXPRESSION;ENVIRONMENT;TIMEOUT;CATEGORIES;HOST;XHOST;XHOST_TEST;HOSTTYPE;XHOSTTYPE;EXCLUDE_IF_NOT_TRUE;XHOSTTYPE_TEST;LINKER_LANGUAGE;TARGET_DEFINES;DEFINES;ADDED_EXE_TARGET_NAME_OUT;ADDED_TESTS_NAMES_OUT" + "SOURCES;DEPLIBS;TESTONLYLIBS;IMPORTEDLIBS;NAME;NAME_POSTFIX;NUM_MPI_PROCS;DIRECTORY;KEYWORDS;COMM;ARGS;PASS_REGULAR_EXPRESSION;FAIL_REGULAR_EXPRESSION;ENVIRONMENT;TIMEOUT;LIST_SEPARATOR;CATEGORIES;HOST;XHOST;XHOST_TEST;HOSTTYPE;XHOSTTYPE;EXCLUDE_IF_NOT_TRUE;XHOSTTYPE_TEST;LINKER_LANGUAGE;TARGET_DEFINES;DEFINES;ADDED_EXE_TARGET_NAME_OUT;ADDED_TESTS_NAMES_OUT" ${ARGN} ) @@ -193,7 +194,7 @@ function(tribits_add_executable_and_test EXE_NAME) tribits_fwd_parse_opt(COMMON_CALL_ARGS NOEXESUFFIX) # - # C) tribitsaddexecutable(...) + # C) tribits_add_executable(...) # set(CALL_ARGS "") @@ -219,7 +220,7 @@ function(tribits_add_executable_and_test EXE_NAME) endif() # - # D) tribitsaddtest(...) + # D) tribits_add_test(...) # set(CALL_ARGS "") @@ -236,6 +237,7 @@ function(tribits_add_executable_and_test EXE_NAME) tribits_fwd_parse_opt(CALL_ARGS STANDARD_PASS_OUTPUT) tribits_fwd_parse_opt(CALL_ARGS WILL_FAIL) tribits_fwd_parse_arg(CALL_ARGS TIMEOUT) + tribits_fwd_parse_arg(CALL_ARGS LIST_SEPARATOR) tribits_fwd_parse_opt(CALL_ARGS ADD_DIR_TO_NAME) tribits_fwd_parse_opt(CALL_ARGS ADDED_TESTS_NAMES_OUT) if (PARSE_XHOST_TEST) diff --git a/cmake/tribits/core/package_arch/TribitsAddExecutableTestHelpers.cmake b/cmake/tribits/core/package_arch/TribitsAddExecutableTestHelpers.cmake index 1121de2f3eb1..81cfec436a34 100644 --- a/cmake/tribits/core/package_arch/TribitsAddExecutableTestHelpers.cmake +++ b/cmake/tribits/core/package_arch/TribitsAddExecutableTestHelpers.cmake @@ -96,8 +96,9 @@ function( tribits_process_comm_args ADD_SERIAL_FEATURE_OUT ADD_MPI_FEATURE_OUT endfunction() -function( tribits_create_name_from_current_source_directory DIRECTORY_NAME ) - set(DIRECTORY_NAME "") +function(tribits_create_name_from_current_source_directory directoryNameOut) + set(directoryName "") + #Get the unique part of the path for this test directory string(REGEX REPLACE ${PACKAGE_SOURCE_DIR} "" unique_dir_path ${CMAKE_CURRENT_SOURCE_DIR}) @@ -111,8 +112,7 @@ function( tribits_create_name_from_current_source_directory DIRECTORY_NAME ) # compatible with windows since they use a "\" instead of a "/" for # directory delimiters. I'm not sure how this will react if we encounter a # directory name with a space in it. - string(REGEX REPLACE "/" "_" DIRECTORY_NAME ${unique_dir_path}) + string(REGEX REPLACE "/" "_" directoryName "${unique_dir_path}") - #print_var(DIRECTORY_NAME) - set(DIRECTORY_NAME ${DIRECTORY_NAME} PARENT_SCOPE) + set(${directoryNameOut} "${directoryName}" PARENT_SCOPE) endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsAddLibrary.cmake b/cmake/tribits/core/package_arch/TribitsAddLibrary.cmake new file mode 100644 index 000000000000..26bddd91931e --- /dev/null +++ b/cmake/tribits/core/package_arch/TribitsAddLibrary.cmake @@ -0,0 +1,802 @@ +# @HEADER +# ************************************************************************ +# +# TriBITS: Tribal Build, Integrate, and Test System +# Copyright 2013 Sandia Corporation +# +# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +# the U.S. Government retains certain rights in this software. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Corporation nor the names of the +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# ************************************************************************ +# @HEADER + +include(TribitsLibIsTestOnly) +include(CMakeParseArguments) +include(GlobalSet) +include(AppendSet) +include(AppendGlob) +include(AppendGlobalSet) +include(AppendStringVar) +include(PrependGlobalSet) +include(RemoveGlobalDuplicates) +include(TribitsGeneralMacros) +include(TribitsReportInvalidTribitsUsage) +include(SetAndIncDirs) + + +# @FUNCTION: tribits_add_library() +# +# Function used to add a CMake library and target using ``add_library()`` and +# also the ALIAS target ``${PACKAGE_NAME}::`` (where ```` is +# the full CMake target name as returned from ``${}``). +# +# Usage:: +# +# tribits_add_library( +# +# [HEADERS

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

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

...)``, but only if ``TESTONLY`` and +# ``NO_INSTALL_LIB_OR_HEADERS`` are not passed in as well. Also, the install +# target for the headers will not get added if +# `${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS`_ is ``FASLE``. If this +# install target is added, then the headers get installed into the flat +# directory ``${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}/`` (default is +# ``${CMAKE_INSTALL_PREFIX}/include/``, see `Setting the install prefix`_). +# If ``HEADERS_INSTALL_SUBDIR`` is set, then the headers will be installed +# under ``${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}//``. +# +# Note that an install target will *not* get created for the headers listed in +# ``NOINSTALLHEADERS``. +# +# .. _Additional Library and Source File Properties (tribits_add_library()): +# +# **Additional Library and Source File Properties (tribits_add_library())** +# +# Once ``add_library( ... ...)`` is called, one +# can set and change properties on the ```` library target +# using the built-in CMake command ``set_target_properties()`` as well as set +# and change properties on any of the source files listed in ``SOURCES`` using +# the built-in CMake command ``set_source_file_properties()`` just like in any +# CMake project. For example:: +# +# tribits_add_library( somelib ... +# ADDED_LIB_TARGET_NAME_OUT somelib_TARGET_NAME ) +# +# set_target_properties( ${somelib_TARGET_NAME} +# PROPERTIES LINKER_LANGUAGE CXX ) +# +# .. _Miscellaneous Notes (tribits_add_library()): +# +# **Miscellaneous Notes (tribits_add_library())** +# +# When the file ``Version.cmake`` exists and the CMake variables +# ``${PROJECT_NAME}_VERSION`` and ``${PROJECT_NAME}_MAJOR_VERSION`` are +# defined, then produced shared libraries will be given the standard SOVERSION +# symlinks (see `/Version.cmake`_). +# +# **WARNING:** Do **NOT** use the built-in CMake command ``add_definitions()`` +# to add defines ``-D`` to the compile command line that will +# affect any of the header files in the package! These CMake-added defines +# are only set locally in this directory and child directories. These defines +# will **NOT** be set when code in peer directories (e.g. a downstream TriBITS +# packages) compiles that may include these header files. To add defines that +# affect header files, please use a configured header file (see +# `tribits_configure_file()`_). +# +function(tribits_add_library LIBRARY_NAME_IN) + + tribits_add_library_assert_correct_call_context() + + # Set library prefix and name + + set(LIBRARY_NAME_PREFIX "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}") + set(LIBRARY_NAME ${LIBRARY_NAME_PREFIX}${LIBRARY_NAME_IN}) + + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("\nTRIBITS_ADD_LIBRARY: ${LIBRARY_NAME}") + if(${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING) + message("\n${PACKAGE_NAME}_LIBRARIES In installation testing mode," + " libraries will be found instead of created.") + endif() + print_var(${PACKAGE_NAME}_LIBRARIES) + endif() + + # Parse input args + + cmake_parse_arguments( + #prefix + PARSE + #Options + "STATIC;SHARED;TESTONLY;NO_INSTALL_LIB_OR_HEADERS;CUDALIBRARY" + #one_value_keywords + "" + #mulit_value_keywords + "HEADERS;HEADERS_INSTALL_SUBDIR;NOINSTALLHEADERS;SOURCES;DEPLIBS;IMPORTEDLIBS;DEFINES;ADDED_LIB_TARGET_NAME_OUT" + ${ARGN} + ) + + tribits_check_for_unparsed_arguments() + + # ToDo: Assert that HEADERS_INSTALL_SUBDIR has 0 or 1 entries! + # ToDo: Assert that ADDED_LIB_TARGET_NAME_OUT as 0 or 1 entries! + + if(PARSE_HEADERS) + list(REMOVE_DUPLICATES PARSE_HEADERS) + endif() + if(PARSE_SOURCES) + list(REMOVE_DUPLICATES PARSE_SOURCES) + endif() + + # Library not added by default + if(PARSE_ADDED_LIB_TARGET_NAME_OUT) + set(${PARSE_ADDED_LIB_TARGET_NAME_OUT} "" PARENT_SCOPE) + endif() + + # + # Create library target if not doing installation testing or if this is a + # TESTONLY library. + # + + if (NOT ${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING OR PARSE_TESTONLY) + + if (PARSE_DEPLIBS AND ${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("-- " "DEPLIBS = ${PARSE_DEPLIBS}") + endif() + if (PARSE_IMPORTEDLIBS AND ${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("-- " "IMPORTEDLIBS = ${PARSE_IMPORTEDLIBS}") + endif() + + # Assert DEPLIBS and IMPORTEDLIBS + + tribits_add_library_assert_deplibs() + tribits_add_library_assert_importedlibs() + + # Add the library and all the dependencies + + if (PARSE_DEFINES) + add_definitions(${PARSE_DEFINES}) + endif() + + if (PARSE_STATIC) + set(STATIC_KEYWORD "STATIC") + else() + set(STATIC_KEYWORD "") + endif() + + if (PARSE_SHARED) + set(SHARED_KEYWORD "SHARED") + else() + set(SHARED_KEYWORD "") + endif() + + if (NOT PARSE_CUDALIBRARY) + add_library( + ${LIBRARY_NAME} + ${STATIC_KEYWORD} + ${SHARED_KEYWORD} + ${PARSE_HEADERS} + ${PARSE_NOINSTALLHEADERS} + ${PARSE_SOURCES} + ) + else() + cuda_add_library( + ${LIBRARY_NAME} + ${PARSE_HEADERS} + ${PARSE_NOINSTALLHEADERS} + ${PARSE_SOURCES} + ) + endif() + + if(PARSE_ADDED_LIB_TARGET_NAME_OUT) + set(${PARSE_ADDED_LIB_TARGET_NAME_OUT} ${LIBRARY_NAME} PARENT_SCOPE) + endif() + + if (PARSE_TESTONLY) + tribits_set_lib_is_testonly(${LIBRARY_NAME}) + endif() + + set_property( + TARGET ${LIBRARY_NAME} + APPEND PROPERTY + LABELS ${PACKAGE_NAME}Libs ${PARENT_PACKAGE_NAME}Libs + ) + + if (NOT "${${PROJECT_NAME}_VERSION}" STREQUAL "" AND + NOT "${${PROJECT_NAME}_MAJOR_VERSION}" STREQUAL "" + ) + set_target_properties( + ${LIBRARY_NAME} + PROPERTIES + VERSION ${${PROJECT_NAME}_VERSION} + SOVERSION ${${PROJECT_NAME}_MAJOR_VERSION} + ) + endif() + + prepend_global_set(${PARENT_PACKAGE_NAME}_LIB_TARGETS ${LIBRARY_NAME}) + prepend_global_set(${PARENT_PACKAGE_NAME}_ALL_TARGETS ${LIBRARY_NAME}) + + # + # Link ${LIBRARY_NAME} to direct upstream libraries + # + + # DEPLIBS + foreach(depLib ${PARSE_DEPLIBS}) + target_link_libraries(${LIBRARY_NAME} PUBLIC "${LIBRARY_NAME_PREFIX}${depLib}") + endforeach() + # ${PACKAGE_NAME}_LIBRARIES + target_link_libraries(${LIBRARY_NAME} PUBLIC ${${PACKAGE_NAME}_LIBRARIES}) + # ${PACKAGE_NAME}_LIB_ENABLED_DEPENDENCIES + foreach(depPkg IN LISTS ${PACKAGE_NAME}_LIB_ENABLED_DEPENDENCIES) + target_link_libraries(${LIBRARY_NAME} PUBLIC ${depPkg}::all_libs) + endforeach() + # ${PACKAGE_NAME}_TEST_ENABLED_DEPENDENCIES (TESTONLY lib) + if (PARSE_TESTONLY) + foreach(depPkg IN LISTS ${PACKAGE_NAME}_TEST_ENABLED_DEPENDENCIES) + target_link_libraries(${LIBRARY_NAME} PUBLIC ${depPkg}::all_libs) + endforeach() + endif() + # IMPORTEDLIBS + foreach(importedLib ${PARSE_IMPORTEDLIBS}) + target_link_libraries(${LIBRARY_NAME} PUBLIC "${importedLib}") + endforeach() + + # ToDo: #63: Above, allow for other link visibilities other than 'PUBLIC'! + + if (${PROJECT_NAME}_CXX_STANDARD_FEATURE) + target_compile_features(${LIBRARY_NAME} PUBLIC + "${${PROJECT_NAME}_CXX_STANDARD_FEATURE}") + endif() + + # Add to the install target + + tribits_add_library_determine_install_lib_and_or_headers( + installLib installHeaders appendLibAndHeadersToPackageVars) + + if (installLib OR installHeaders) + set_property(GLOBAL PROPERTY ${PROJECT_NAME}_HAS_INSTALL_TARGETS ON) + set_property(GLOBAL PROPERTY ${PACKAGE_NAME}_HAS_INSTALL_TARGETS ON) + endif() + + if (installLib) + install( + TARGETS ${LIBRARY_NAME} + EXPORT ${PACKAGE_NAME} + INCLUDES DESTINATION "${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}" + RUNTIME DESTINATION "${${PROJECT_NAME}_INSTALL_RUNTIME_DIR}" + LIBRARY DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}" + ARCHIVE DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}" + COMPONENT ${PACKAGE_NAME} + ) + endif() + + if (installHeaders) + tribits_install_headers( + HEADERS ${PARSE_HEADERS} + INSTALL_SUBDIR ${PARSE_HEADERS_INSTALL_SUBDIR} + COMPONENT ${PACKAGE_NAME} + ) + endif() + + # Append the new libraries to this package's lists + + if (appendLibAndHeadersToPackageVars) + prepend_global_set(${PACKAGE_NAME}_LIBRARIES ${PACKAGE_NAME}::${LIBRARY_NAME}) + remove_global_duplicates(${PACKAGE_NAME}_LIBRARIES) + if (installLib) + global_set(${PACKAGE_NAME}_HAS_NATIVE_LIBRARIES_TO_INSTALL TRUE) + endif() + else() + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("-- " "Skipping augmentation of package's lists of libraries! ...") + endif() + endif() + + # Set INTERFACE_INCLUDE_DIRECTORIES property for added library and must + # only do for the build interface (not the install interface). + get_directory_property(INCLUDE_DIRS_CURRENT INCLUDE_DIRECTORIES) + set(buildInterfaceIncludeDirs) + foreach (includeDir IN LISTS INCLUDE_DIRS_CURRENT) + list(APPEND buildInterfaceIncludeDirs "$") + endforeach() + target_include_directories( ${LIBRARY_NAME} PUBLIC ${buildInterfaceIncludeDirs} ) + + # Add ALIAS library :: + add_library(${PACKAGE_NAME}::${LIBRARY_NAME} ALIAS ${LIBRARY_NAME}) + + # Optionally Set IMPORTED_NO_SYSTEM + if (${PROJECT_NAME}_IMPORTED_NO_SYSTEM) + set_target_properties(${LIBRARY_NAME} PROPERTIES IMPORTED_NO_SYSTEM TRUE) + endif() + + endif() #if not in installation testing mode + + # Adjust for installation testing + + if (${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING) + list(FIND ${PROJECT_NAME}_INSTALLATION_PACKAGE_LIST ${PACKAGE_NAME} + ${PACKAGE_NAME}_WAS_INSTALLED) + if(${${PACKAGE_NAME}_WAS_INSTALLED} EQUAL -1) + message(FATAL_ERROR + "The package ${PACKAGE_NAME} was not installed with ${PROJECT_NAME}!" + " Please disable package ${PACKAGE_NAME} or install it.") + endif() + global_set(${PACKAGE_NAME}_LIBRARIES ${${PACKAGE_NAME}_INSTALLATION_LIBRARIES}) + endif() + + # Print the updates to the linkage variables + + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + print_var(${PACKAGE_NAME}_LIBRARIES) + endif() + +endfunction() +# +# ToDo:, above Deprecate and remove the usage of DEFINES! People should be +# putting defines into configured header files, not adding -D to +# the compile lines! + + +# Function that asserts that tribits_add_library() is called in the correct +# context +# +function(tribits_add_library_assert_correct_call_context) + + if (CURRENTLY_PROCESSING_SUBPACKAGE) + + # This is a subpackage being processed + + if(NOT ${SUBPACKAGE_FULLNAME}_TRIBITS_SUBPACKAGE_CALLED) + tribits_report_invalid_tribits_usage( + "Must call tribits_subpackage() before tribits_add_library()" + " in ${CURRENT_SUBPACKAGE_CMAKELIST_FILE}") + endif() + + if(${SUBPACKAGE_FULLNAME}_TRIBITS_SUBPACKAGE_POSTPROCESS_CALLED) + tribits_report_invalid_tribits_usage( + "Must call tribits_add_library() before " + " tribits_subpackage_postprocess() in ${CURRENT_SUBPACKAGE_CMAKELIST_FILE}") + endif() + + else() + + # This is a package being processed + + if(NOT ${PACKAGE_NAME}_TRIBITS_PACKAGE_DECL_CALLED) + tribits_report_invalid_tribits_usage( + "Must call tribits_package() or tribits_package_decl() before" + " tribits_add_library() in ${TRIBITS_PACKAGE_CMAKELIST_FILE}") + endif() + + if(${PACKAGE_NAME}_TRIBITS_PACKAGE_POSTPROCESS_CALLED) + tribits_report_invalid_tribits_usage( + "Must call tribits_add_library() before " + " tribits_package_postprocess() in ${TRIBITS_PACKAGE_CMAKELIST_FILE}") + endif() + + endif() + +endfunction() + + +# Assert correct DEPSLIB passed to tribits_add_library() +# +# NOTE: This accesses vars from the enclosed calling function +# tribits_add_library() but does not set any variables in that scope! +# +# We also need to make special considerations for test libraries since +# things need to be handled a little bit differently (but not much). In the +# case of test libraries, we need to also pull the test-only dependencies. +# In this case, we will always assume that we will add in the test +# libraries. +# +# ToDo: Turn the below deprecated WARNING messages to FATAL_ERROR once we +# give enough time for people to clean up their codes. +# +function(tribits_add_library_assert_deplibs) + + foreach(depLib ${PARSE_DEPLIBS}) + + set(prefixedDepLib "${LIBRARY_NAME_PREFIX}${depLib}") + + # Is this lib already listed in ${PACKAGE_NAME}_LIBS? + list(FIND ${PACKAGE_NAME}_LIBRARIES "${PACKAGE_NAME}::${prefixedDepLib}" FOUND_IDX) + if (FOUND_IDX GREATER -1) + set(depLibAlreadyInPkgLibs TRUE) + else() + set(depLibAlreadyInPkgLibs FALSE) + endif() + + # ${PREFIXED_LIB" is TESTONLY? + tribits_lib_is_testonly(${prefixedDepLib} depLibIsTestOnlyLib) + + # Check for valid usage (sorted by most common to least common) + if (depLibAlreadyInPkgLibs AND NOT depLibIsTestOnlyLib) # PARSE_TESTONLY=any + # The library being created here is a (regular or testonly) library + # dependent on a regular (non-TESTONLY) lib in this package. This is + # valid usage of DEPLIBS. There is no need to link this new lib to + # the package's upstream dependent package and TPL libraries because + # these are already linked into one of the of the package's own + # upstream libs. + elseif (PARSE_TESTONLY AND depLibAlreadyInPkgLibs AND NOT depLibIsTestOnlyLib) + # The library being created here is TESTONLY library and is + # dependent on a regular (non-TESTONLY) lib. This is valid usage of + # DEPLIBS. In the case of test-only libraries, we always link in + # the upstream libs. + elseif (PARSE_TESTONLY AND depLibIsTestOnlyLib) # any depLibAlreadyInPkgLibs + # The library being created here is TESTONLY library and is dependent + # on another TESTONLY library. This is valid usage of DEPLIBS. In + # this case we just hope that this package correctly specified a TEST + # dependency on the upstream package that owns this upstream TESTONLY + # library if it comes from an upstream package. + elseif (NOT PARSE_TESTONLY AND depLibIsTestOnlyLib) # any depLibAlreadyInPkgLibs + message(WARNING "WARNING: '${depLib}' in DEPLIBS is a TESTONLY lib" + " and it is illegal to link to this non-TESTONLY library '${LIBRARY_NAME}'." + " Such usage is deprecated (and this warning will soon become an error)!" + " If this is a regular library in this package or in an dependent upstream" + " package then TriBITS will link automatically to it. If you remove this and it" + " does not link, then you need to add a new package dependency to" + " this package's dependencies file" + " ${${PACKAGE_NAME}_SOURCE_DIR}/cmake/Dependencies.cmake") + # ToDo: Turn the above to FATAL_ERROR after dropping deprecated code + elseif (NOT depLibAlreadyInPkgLibs AND TARGET ${prefixedDepLib}) # any PARSE_TESTONLY + message(WARNING "WARNING: '${depLib}' in DEPLIBS is not" + " a lib in this package but is a library defined in the current" + " cmake project! Such usage is deprecated (and" + " will result in a configure error soon). If this is a library in" + " a dependent upstream package, then simply remove '${depLib}' from this list." + " TriBITS automatically links in libraries in upstream packages." + " If you remove '${depLib}' from DEPLIBS and your code does" + " not link, then you need to add a new package dependency to" + " this package's dependencies file" + " ${${PACKAGE_NAME}_SOURCE_DIR}/cmake/Dependencies.cmake.") + elseif (NOT depLibAlreadyInPkgLibs AND NOT TARGET ${prefixedDepLib} ) + message(WARNING "WARNING: '${depLib}' in DEPLIBS is not" + " a lib defined in the current cmake project! Such usage is deprecated (and" + " will result in a configure error soon). If this is an external" + " lib you are trying to link in, it should likely be handled as a TriBITS" + " TPL. Otherwise, it should be passed in through IMPORTEDLIBS. However," + " the only case we have found where IMPORTEDLIBS had to be used instead of" + " through a proper TriBITS TPL is the C math library 'm'.") + else() + message(WARNING "WARNING: The case PARSE_TESTONLY=${PARSE_TESTONLY}," + " depLibAlreadyInPkgLibs=${depLibAlreadyInPkgLibs}," + " depLibIsTestOnlyLib=${depLibIsTestOnlyLib}, has" + " not yet been handled!") + endif() + + endforeach() + +endfunction() + + +# Assert correct IMPORTEDLIBS passed to tribits_add_library() +# +# NOTE: This accesses vars from the enclosed calling function +# tribits_add_library() but does not set any variables in that scope! +# +# ToDo: Turn the below deprecated WARNING messages to FATAL_ERROR once we +# give enough time for people to clean up their codes. +# +function(tribits_add_library_assert_importedlibs) + foreach(importedLib ${PARSE_IMPORTEDLIBS}) + set(prefixedImportedLib "${LIBRARY_NAME_PREFIX}${importedLib}") + list(FIND ${PACKAGE_NAME}_LIBRARIES "${PACKAGE_NAME}::${prefixedImportedLib}" + FOUND_IMPORTEDLIB_IN_LIBRARIES_IDX) + tribits_lib_is_testonly(${prefixedImportedLib} importedLibIsTestOnlyLib) + if (importedLibIsTestOnlyLib) + message(WARNING "WARNING: '${importedLib}' in IMPORTEDLIBS is a TESTONLY lib" + " and it is illegal to pass in through IMPORTEDLIBS!" + " Such usage is deprecated (and this warning will soon become an error)!" + " Should '${importedLib}' instead be passed through DEPLIBS?") + # ToDo: Turn the above to FATAL_ERROR after dropping deprecated code + elseif (FOUND_IMPORTEDLIB_IN_LIBRARIES_IDX GREATER -1) + message(WARNING "WARNING: Lib '${importedLib}' in IMPORTEDLIBS is in" + " this package and is *not* an external lib!" + " Please move '${importedLib}' from the list IMPORTEDLIBS to DEPLIBS.") + elseif (TARGET ${prefixedImportedLib}) + message(WARNING "WARNING: Lib '${importedLib}' being passed through" + " IMPORTEDLIBS is *not* an external library but instead is a library" + " defined in this CMake project!" + " TriBITS takes care of linking against libraries in dependent upstream" + " packages. If you want to link to a library in an upstream" + " package then add the package name to the appropriate category" + " in this package's dependencies file: " + " ${${PACKAGE_NAME}_SOURCE_DIR}/cmake/Dependencies.cmake.") + endif() + endforeach() +endfunction() + + +# Determine lib and/or headers should be installed and if the package vars +# should be updated +# +# NOTE: This reads the parsed arguments (prefixed with ``PARSE_``) from the +# calling tribits_add_library() function from the enclosing scope. +# +function(tribits_add_library_determine_install_lib_and_or_headers + installLibOut installHeadersOut appendLibAndHeadersToPackageVarsOut + ) + + set(installLib ON) + set(installHeaders ON) + set(appendLibAndHeadersToPackageVars ON) + + if (PARSE_TESTONLY) + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("-- " "Skipping installation hooks for this library" + " because 'TESTONLY' was passed in ...") + endif() + set(installLib OFF) + set(installHeaders OFF) + set(appendLibAndHeadersToPackageVars OFF) + elseif (PARSE_NO_INSTALL_LIB_OR_HEADERS) + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("-- " "Skipping installation hooks for this library" + " because 'NO_INSTALL_LIB_OR_HEADERS' was passed in ...") + endif() + set(installLib OFF) + set(installHeaders OFF) + elseif (NOT ${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS AND NOT BUILD_SHARED_LIBS) + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("-- " "Skipping installation of headers and libraries" + " because ${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS=FALSE and" + " BUILD_SHARED_LIBS=FALSE ...") + endif() + set(installLib OFF) + set(installHeaders OFF) + elseif (NOT ${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS AND BUILD_SHARED_LIBS) + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("-- " "Skipping installation of headers but installing libraries" + " because ${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS=FALSE and" + " BUILD_SHARED_LIBS=TRUE ...") + endif() + set(installHeaders OFF) + endif() + + set(${installLibOut} ${installLib} PARENT_SCOPE) + set(${installHeadersOut} ${installHeaders} PARENT_SCOPE) + set(${appendLibAndHeadersToPackageVarsOut} ${appendLibAndHeadersToPackageVars} + PARENT_SCOPE) + +endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsAddOptionAndDefine.cmake b/cmake/tribits/core/package_arch/TribitsAddOptionAndDefine.cmake index 534ef9e75d55..8c98b1717d74 100644 --- a/cmake/tribits/core/package_arch/TribitsAddOptionAndDefine.cmake +++ b/cmake/tribits/core/package_arch/TribitsAddOptionAndDefine.cmake @@ -40,7 +40,6 @@ include(GlobalSet) -# # @MACRO: tribits_add_option_and_define() # # Add an option and a define variable in one shot. diff --git a/cmake/tribits/core/package_arch/TribitsAddTest.cmake b/cmake/tribits/core/package_arch/TribitsAddTest.cmake index 9d98021f8729..3be4c329d9ba 100644 --- a/cmake/tribits/core/package_arch/TribitsAddTest.cmake +++ b/cmake/tribits/core/package_arch/TribitsAddTest.cmake @@ -39,8 +39,9 @@ include(TribitsAddTestHelpers) +cmake_policy(SET CMP0007 NEW) # Don't ignore empty list elements + -# # @FUNCTION: tribits_add_test() # # Add a test or a set of tests for a single executable or command using CTest @@ -68,11 +69,12 @@ include(TribitsAddTestHelpers) # [EXCLUDE_IF_NOT_TRUE ...] # [DISABLED ] # [STANDARD_PASS_OUTPUT -# | PASS_REGULAR_EXPRESSION ";;..."] -# [FAIL_REGULAR_EXPRESSION ";;..."] +# | PASS_REGULAR_EXPRESSION "" "" ...] +# [FAIL_REGULAR_EXPRESSION "" "" ...] # [WILL_FAIL] # [ENVIRONMENT = = ...] # [TIMEOUT ] +# [LIST_SEPARATOR ] # [ADDED_TESTS_NAMES_OUT ] # ) # @@ -189,9 +191,9 @@ include(TribitsAddTestHelpers) # For example, a set of three different tests with argument lists can be # specified as:: # -# POSTIFX_AND_ARGS_0 postfix0 --arg1 --arg2="dummy" -# POSTIFX_AND_ARGS_1 postfix1 --arg2="fly" -# POSTIFX_AND_ARGS_2 postfix2 --arg2="bags" +# POSTIFX_AND_ARGS_0 postfix0 --arg1 --arg2=dummy +# POSTIFX_AND_ARGS_1 postfix1 --arg2=fly +# POSTIFX_AND_ARGS_2 postfix2 --arg2=bags # # This will create three different test cases with the postfix names # ``postfix0``, ``postfix1``, and ``postfix2``. The indexes must be @@ -202,6 +204,13 @@ include(TribitsAddTestHelpers) # allow long argument lists to span multiple lines. See `Adding Multiple # Tests (tribits_add_test())`_ for more details and examples. # +# Note that one of the `` arguments can be empty, in which case +# the base test name is not appended so:: +# +# POSTIFX_AND_ARGS_0 "" --arg1 --arg2=dummy +# +# would create one test without appending the test name. +# # ``COMM [serial] [mpi]`` # # If specified, determines if the test will be added in serial and/or MPI @@ -329,7 +338,7 @@ include(TribitsAddTestHelpers) # MPI executables is unreliable. This is set using the built-in CTest # property ``PASS_REGULAR_EXPRESSION``. # -# ``PASS_REGULAR_EXPRESSION ";;..."`` +# ``PASS_REGULAR_EXPRESSION "" "" ...`` # # If specified, then the test will be assumed to pass only if one of the # regular expressions ````, ```` etc. match the output @@ -339,7 +348,7 @@ include(TribitsAddTestHelpers) # CMake will interpret this as an array element boundary. To match '.', # use '[.]'. # -# ``FAIL_REGULAR_EXPRESSION ";;..."`` +# ``FAIL_REGULAR_EXPRESSION "" "" ...`` # # If specified, then a test will be assumed to fail if one of the regular # expressions ````, ```` etc. match the output send to @@ -354,11 +363,18 @@ include(TribitsAddTestHelpers) # using the built-in CTest property ``WILL_FAIL``. Consult standard CMake # documentation for full behavior. # -# ``ENVIRONMENT = = ...`` +# ``ENVIRONMENT "=" "=" ...``. # -# If passed in, the listed environment variables will be set before -# calling the test. This is set using the built-in CTest property -# ``ENVIRONMENT``. +# If passed in, the listed environment variables will be set by CTest +# before calling the test. This is set using the built-in CTest test +# property ``ENVIRONMENT``. Note, if the env var values contain +# semi-colons ``';'``, then replace the semi-colons ``';'`` with another +# separator ``''`` and pass in ``LIST_SEPARATOR `` so ```` +# will be replaced with ``';'`` at point of usage. If the env var values +# contain any spaces, also quote the entire variable/value pair as +# ``"="``. For example, the env var and value +# ``my_env_var="arg1 b;arg2;I have spaces"`` would need to be passed as +# ``"my_env_var=arg1 barg2I have spaces"``. # # ``TIMEOUT `` # @@ -374,6 +390,18 @@ include(TribitsAddTestHelpers) # ``HEAVY`` for extremely expensive tests). Expensive tests are one of # the worse forms of technical debt that a project can have! # +# ``LIST_SEPARATOR `` +# +# String used as placeholder for the semi-colon char ``';'`` in order to +# allow pass-through. For example, if arguments to the ``ARGS`` or +# ``ENVIRONMENT`` need to use semi-colons, then replace ``';'`` with +# ``''`` (for example) such as with +# ``"somearg=arg1arg2"``, then at the point of usage, +# ``''`` will be replaced with ``';'`` and it will be passed to +# the final command as ``"somearg=arg1;arg2"`` (with as many preceding +# escape backslashes ``'\'`` in front of ``';'`` as is needed for the +# given usage context). +# # ``ADDED_TESTS_NAMES_OUT `` # # If specified, then on output the variable ```` will be set @@ -807,15 +835,15 @@ function(tribits_add_test EXE_NAME) #print_var(POSTFIX_AND_ARGS_LIST) cmake_parse_arguments( + PARSE_ARGV 1 # One named argument #prefix PARSE # options "NOEXEPREFIX;NOEXESUFFIX;STANDARD_PASS_OUTPUT;WILL_FAIL;ADD_DIR_TO_NAME;RUN_SERIAL" #one_value_keywords - "DISABLED" + "DISABLED;LIST_SEPARATOR" #multi_value_keywords "DIRECTORY;KEYWORDS;COMM;NUM_MPI_PROCS;NUM_TOTAL_CORES_USED;ARGS;${POSTFIX_AND_ARGS_LIST};NAME;NAME_POSTFIX;CATEGORIES;HOST;XHOST;HOSTTYPE;XHOSTTYPE;EXCLUDE_IF_NOT_TRUE;PASS_REGULAR_EXPRESSION;FAIL_REGULAR_EXPRESSION;TIMEOUT;ENVIRONMENT;ADDED_TESTS_NAMES_OUT" - ${ARGN} ) tribits_check_for_unparsed_arguments() @@ -848,20 +876,20 @@ function(tribits_add_test EXE_NAME) # If requested create a modifier for the name that will be inserted between # the package name and the given name or exe_name for the test - set(DIRECTORY_NAME "") - if(PARSE_ADD_DIR_TO_NAME) - tribits_create_name_from_current_source_directory(DIRECTORY_NAME) - set(DIRECTORY_NAME "${DIRECTORY_NAME}_") + set(directoryName "") + if (PARSE_ADD_DIR_TO_NAME) + tribits_create_name_from_current_source_directory(directoryName) + set(directoryName "${directoryName}_") endif() #message("TRIBITS_ADD_TEST: ${EXE_NAME}: EXE_BINARY_NAME = ${EXE_BINARY_NAME}") if (PARSE_NAME) - set(TEST_NAME "${DIRECTORY_NAME}${PARSE_NAME}") + set(TEST_NAME "${directoryName}${PARSE_NAME}") elseif (PARSE_NAME_POSTFIX) - set(TEST_NAME "${DIRECTORY_NAME}${EXE_NAME}_${PARSE_NAME_POSTFIX}") + set(TEST_NAME "${directoryName}${EXE_NAME}_${PARSE_NAME_POSTFIX}") else() - set(TEST_NAME "${DIRECTORY_NAME}${EXE_NAME}") + set(TEST_NAME "${directoryName}${EXE_NAME}") endif() set(TEST_NAME "${PACKAGE_NAME}_${TEST_NAME}") @@ -1005,13 +1033,17 @@ function(tribits_add_test EXE_NAME) break() endif() - set( POSTFIX_AND_ARGS ${PARSE_POSTFIX_AND_ARGS_${POSTFIX_AND_ARGS_IDX}} ) + set( POSTFIX_AND_ARGS "${PARSE_POSTFIX_AND_ARGS_${POSTFIX_AND_ARGS_IDX}}" ) list( GET POSTFIX_AND_ARGS 0 POSTFIX ) - set( INARGS ${POSTFIX_AND_ARGS} ) # Initially contains postfix as ele 0 + set( INARGS "${POSTFIX_AND_ARGS}" ) # Initially contains postfix as ele 0 list( REMOVE_AT INARGS 0 ) # Strip off the postfix name - set(TEST_NAME_INSTANCE "${TEST_NAME}_${POSTFIX}${MPI_NAME_POSTFIX}") + if (NOT "${POSTFIX}" STREQUAL "") + set(TEST_NAME_INSTANCE "${TEST_NAME}_${POSTFIX}${MPI_NAME_POSTFIX}") + else() + set(TEST_NAME_INSTANCE "${TEST_NAME}${MPI_NAME_POSTFIX}") + endif() tribits_set_run_serial(${TEST_NAME_INSTANCE} "${PARSE_RUN_SERIAL}" SET_RUN_SERIAL) @@ -1022,7 +1054,6 @@ function(tribits_add_test EXE_NAME) tribits_add_test_add_test_all( ${TEST_NAME_INSTANCE} "${EXECUTABLE_PATH}" "${PARSE_CATEGORIES}" "${NUM_PROCS_USED}" "${NUM_TOTAL_CORES_USED}" - ${PARSE_CREATE_WORKING_DIR} "${SET_RUN_SERIAL}" "${SET_DISABLED_AND_MSG}" ADDED_TEST_NAME ${INARGS} "${${TEST_NAME_INSTANCE}_EXTRA_ARGS}" ) diff --git a/cmake/tribits/core/package_arch/TribitsAddTestHelpers.cmake b/cmake/tribits/core/package_arch/TribitsAddTestHelpers.cmake index f6f82ea09396..b5fe642c17e6 100644 --- a/cmake/tribits/core/package_arch/TribitsAddTestHelpers.cmake +++ b/cmake/tribits/core/package_arch/TribitsAddTestHelpers.cmake @@ -52,7 +52,6 @@ include(MessageWrapper) include(TribitsGetCategoriesString) -# # Do initialization for test helpers # # This must be run just before the packages define their tests and this macro @@ -66,34 +65,32 @@ macro(tribits_add_test_helpers_init) endmacro() -# # Wrapper function for set_tests_properties() to be used in unit testing. # - function(tribits_set_tests_properties) + cmake_parse_arguments(PARSE_ARGV 0 FWD "" "" "") if (NOT TRIBITS_ADD_TEST_ADD_TEST_UNITTEST) - set_tests_properties(${ARGN}) + set_tests_properties(${FWD_UNPARSED_ARGUMENTS}) endif() if (TRIBITS_SET_TEST_PROPERTIES_CAPTURE_INPUT) - append_global_set(TRIBITS_SET_TEST_PROPERTIES_INPUT ${ARGN}) + append_global_set(TRIBITS_SET_TEST_PROPERTIES_INPUT ${FWD_UNPARSED_ARGUMENTS}) endif() endfunction() -# + # Wrapper function for set_property(TEST ...) to be used in unit testing # - function(tribits_set_test_property) + cmake_parse_arguments(PARSE_ARGV 0 FWD "" "" "") if (NOT TRIBITS_ADD_TEST_ADD_TEST_UNITTEST) - set_property(TEST ${ARGN}) + set_property(TEST ${FWD_UNPARSED_ARGUMENTS}) endif() if (TRIBITS_SET_TEST_PROPERTIES_CAPTURE_INPUT) - append_global_set(TRIBITS_SET_TEST_PROPERTIES_INPUT ${ARGN}) + append_global_set(TRIBITS_SET_TEST_PROPERTIES_INPUT ${FWD_UNPARSED_ARGUMENTS}) endif() endfunction() -# # Scale a timeout by ${PROJECT_NAME}_SCALE_TEST_TIMEOUT # # This function will truncate input TIMEOUT_IN but will allow for a simple @@ -148,7 +145,6 @@ function(tribits_scale_timeout TIMEOUT_IN SCALED_TIMEOUT_OUT) endfunction() -# # Function that converts a complete string of command-line arguments # into a form that add_test(...) can correctly deal with. # @@ -159,7 +155,6 @@ endfunction() # active. This allows you to pass in quoted arguments and have them # treated as a single argument. # - function(tribits_convert_cmnd_arg_string_to_add_test_arg_array CMND_ARG_STRING ARG_ARRAY_VARNAME) #message("TRIBITS_CONVERT_CMND_ARG_STRING_TO_ADD_TEST_ARG_ARRAY") @@ -208,11 +203,9 @@ function(tribits_convert_cmnd_arg_string_to_add_test_arg_array CMND_ARG_STRING A endfunction() -# # Determine if to add the test based on if testing is enabled for the current # package or subpackage. # - function(tribits_add_test_process_enable_tests ADD_THE_TEST_OUT) if(${PACKAGE_NAME}_ENABLE_TESTS OR ${PARENT_PACKAGE_NAME}_ENABLE_TESTS) set(ADD_THE_TEST TRUE) @@ -233,13 +226,11 @@ function(tribits_add_test_process_enable_tests ADD_THE_TEST_OUT) endfunction() -# # Determine if to add the test or not based on [X]HOST and [X]HOSTTYPE arguments # # Warning: Arguments for [X]HOST and [X]HOSTTYPE arguments are passed in # implicitly due to scoping of CMake. # - function(tribits_add_test_process_host_hosttype ADD_THE_TEST_OUT) if ("${${PROJECT_NAME}_HOSTNAME}" STREQUAL "") @@ -318,7 +309,6 @@ function(tribits_add_test_process_host_hosttype ADD_THE_TEST_OUT) endfunction() -# # Determine if to add the test or not based on CATEGORIES arguments # # Warning: Argument PARSE_CATEGORIES is passed in implicitly due to scoping of @@ -390,7 +380,6 @@ function(tribits_add_test_process_categories ADD_THE_TEST_OUT) endfunction() -# # FUNCTION: tribits_add_test_get_exe_binary_name() # # Get the full name of a package executable given its root name and other @@ -432,7 +421,6 @@ function(tribits_add_test_get_exe_binary_name EXE_NAME_IN endfunction() -# # Adjust the directory path to an executable for a test # function(tribits_add_test_adjust_directory EXE_BINARY_NAME DIRECTORY @@ -462,7 +450,6 @@ function(tribits_add_test_adjust_directory EXE_BINARY_NAME DIRECTORY endfunction() -# # Get the number of MPI processes to use # function(tribits_add_test_get_num_procs_used NUM_MPI_PROCS_IN @@ -523,7 +510,6 @@ function(tribits_add_test_get_num_procs_used NUM_MPI_PROCS_IN endfunction() -# # Generate the array of arguments for an MPI run # # NOTE: The extra test program arguments are passed through ${ARGN}. @@ -551,7 +537,6 @@ function( tribits_add_test_get_test_cmnd_array CMND_ARRAY_OUT endfunction() -# # Get the number of cores used by process # function(tribits_add_test_get_num_total_cores_used TEST_NAME_IN @@ -595,7 +580,6 @@ function(tribits_add_test_get_num_total_cores_used TEST_NAME_IN endfunction() -# # Read ${TEST_NAME_IN}_SET_DISABLED_AND_MSG and set output var # as used by the TRIBITS_ADD[_ADVANCED]_test() # functions. @@ -622,7 +606,6 @@ function(tribits_set_disabled_and_msg TEST_NAME_IN PARSE_DISABLED endfunction() -# # Read ${TEST_NAME_IN}_SET_RUN_SERIAL and set output var SET_RUN_SERIAL_OUT as # used by the TRIBITS_ADD[_ADVANCED]_test() functions. # @@ -648,7 +631,6 @@ function(tribits_set_run_serial TEST_NAME_IN PARSE_RUN_SERIAL endfunction() -# # Determine if the test should be skipped due to a disable var set # # Usage: @@ -703,12 +685,14 @@ endfunction() # function(tribits_add_test_add_test TEST_NAME EXE_NAME) + string(REPLACE "${PARSE_LIST_SEPARATOR}" "\\;" args "${ARGN}") + if (TRIBITS_ADD_TEST_ADD_TEST_CAPTURE) - append_global_set(TRIBITS_ADD_TEST_ADD_TEST_INPUT NAME ${TEST_NAME} COMMAND ${ARGN}) + append_global_set(TRIBITS_ADD_TEST_ADD_TEST_INPUT NAME ${TEST_NAME} COMMAND ${args}) endif() if (NOT TRIBITS_ADD_TEST_ADD_TEST_UNITTEST) - add_test(NAME ${TEST_NAME} COMMAND ${ARGN}) + add_test(NAME ${TEST_NAME} COMMAND ${args}) endif() tribits_set_tests_properties(${TEST_NAME} PROPERTIES REQUIRED_FILES ${EXE_NAME}) @@ -731,7 +715,7 @@ function(tribits_private_add_test_set_passfail_properties TEST_NAME_IN) if (PARSE_PASS_REGULAR_EXPRESSION) tribits_set_tests_properties(${TEST_NAME_IN} PROPERTIES PASS_REGULAR_EXPRESSION - ${PARSE_PASS_REGULAR_EXPRESSION}) + "${PARSE_PASS_REGULAR_EXPRESSION}") endif() if (PARSE_WILL_FAIL) @@ -781,7 +765,10 @@ endfunction() function(tribits_private_add_test_set_environment TEST_NAME_IN) if (PARSE_ENVIRONMENT) - tribits_set_test_property(${TEST_NAME_IN} PROPERTY ENVIRONMENT ${PARSE_ENVIRONMENT}) + string(REPLACE "${PARSE_LIST_SEPARATOR}" "\\;" PARSE_ENVIRONMENT + "${PARSE_ENVIRONMENT}") + tribits_set_test_property(${TEST_NAME_IN} PROPERTY ENVIRONMENT + "${PARSE_ENVIRONMENT}") endif() endfunction() @@ -804,7 +791,6 @@ function(tribits_private_add_test_set_processors TEST_NAME_IN endfunction() -# # Print test added message! # function(tribits_private_add_test_print_added TEST_NAME_IN CATEGORIES_IN @@ -852,7 +838,6 @@ function(tribits_private_add_test_print_added TEST_NAME_IN CATEGORIES_IN endfunction() -# # Overall add test command # # NOTE: Pass the command arguments on the end in ARGSN. @@ -886,10 +871,8 @@ function(tribits_add_test_add_test_all TEST_NAME_IN endfunction() -# # Set the label and keywords # - function(tribits_private_add_test_add_label_and_keywords TEST_NAME_IN) tribits_set_test_property(${TEST_NAME_IN} APPEND PROPERTY @@ -903,10 +886,8 @@ function(tribits_private_add_test_add_label_and_keywords TEST_NAME_IN) endfunction() -# # Postprocess a test that was added # - function(tribits_private_add_test_post_process_added_test TEST_NAME_IN CATEGORIES_IN NUM_PROCS_USED_IN NUM_TOTAL_CORES_USED_IN RUN_SERIAL_IN DISABLED_MSG_IN @@ -938,10 +919,8 @@ function(tribits_private_add_test_post_process_added_test TEST_NAME_IN endfunction() -# # Add environment and resource properties to a test # - function(tribits_private_add_test_add_environment_and_resource TEST_NAME_IN NUM_PROCS_USED_IN ) diff --git a/cmake/tribits/core/package_arch/TribitsAdjustPackageEnables.cmake b/cmake/tribits/core/package_arch/TribitsAdjustPackageEnables.cmake index 7db948b66fa6..cd179089da79 100644 --- a/cmake/tribits/core/package_arch/TribitsAdjustPackageEnables.cmake +++ b/cmake/tribits/core/package_arch/TribitsAdjustPackageEnables.cmake @@ -41,6 +41,7 @@ include(TribitsProcessPackagesAndDirsLists) include(TribitsAddOptionAndDefine) include(TribitsGeneralMacros) +include(TribitsPrintEnabledPackagesLists) include(AdvancedOption) include(AdvancedSet) @@ -49,6 +50,7 @@ include(CMakeBuildTypesList) include(FindListElement) include(GlobalNullSet) include(PrintNonemptyVar) +include(PrintVarWithSpaces) include(PrintNonemptyVarWithSpaces) include(PrintVar) include(RemoveGlobalDuplicates) @@ -150,8 +152,8 @@ macro(tribits_private_disable_tpl_required_package_enable # NOTE: We can't assert that ${PACKAGE_NAME}_ENABLE_TESTS or # ${PACKAGE_NAME}_ENABLE_EXAMPLES exists yet because - # tribits_add_optional_package_enables() which defines them is not - # called until after the final package enables are set. + # tribits_set_up_optional_package_enables_and_cache_vars() which defines + # them is not called until after the final package enables are set. endif() @@ -396,7 +398,7 @@ endmacro() # macro(tribits_print_package_dependencies PACKAGE_NAME) - set(PRINTED_VAR) + set(PRINTED_VAR "") print_nonempty_var_with_spaces(${PACKAGE_NAME}_LIB_REQUIRED_DEP_PACKAGES PRINTED_VAR) print_nonempty_var_with_spaces(${PACKAGE_NAME}_LIB_OPTIONAL_DEP_PACKAGES PRINTED_VAR) @@ -486,9 +488,12 @@ macro(tribits_private_add_optional_tpl_enable PACKAGE_NAME OPTIONAL_DEP_TPL endmacro() -# Macro that enables optional package interdependencies +# Macro that sets cache vars for optional package interdependencies # -macro(tribits_add_optional_package_enables PACKAGE_NAME) +# This also will set ${PACKAGE_NAME}_ENABLE_TESTS and +# ${PACKAGE_NAME}_ENABLE_EXAMPLES to empty non-cache vars +# +macro(tribits_set_up_optional_package_enables_and_cache_vars PACKAGE_NAME) #message("\nPACKAGE_ARCH_ADD_OPTIONAL_PACKAGE_ENABLES: ${PACKAGE_NAME}") @@ -550,6 +555,140 @@ macro(tribits_add_optional_package_enables PACKAGE_NAME) endmacro() +# Macro that sets up the flat list of direct package dependencies and enabled +# package dependencies and sets ${packageName}_ENABLE_${depPkg} for LIB +# dependencies +# +# This makes it easy to just loop over all of the direct upstream dependencies +# for a package or just the enabled dependencies. +# +# NOTES: +# +# * ${packageName}_LIB_ALL_DEPENDENCIES will be set regardless if +# ${packageName} is enabled or not. +# +# * ${packageName}_LIB_ENABLED_DEPENDENCIES is only set if ${packageName} is +# enabled and will only contain the names of direct library upstream +# internal and external packages ${depPkg} that are required or are +# optional and ${packageName}_ENABLE_${depPkg} is set to ON. +# +# * ${packageName}_TEST_ALL_DEPENDENCIES will be set regardless if +# ${packageName} is enabled or not. +# +# * ${packageName}_TEST_ENABLED_DEPENDENCIES is only set if ${packageName} is +# enabled and will only contain the names of direct test/example upstream +# internal and external packages ${depPkg} that are required or are +# optional and ${packageName}_ENABLE_${depPkg} is set to ON. +# +# * Sets ${packageName}_ENABLE_${depPkg}=ON for every required dep package +# for LIB dependencies (but not TEST dependencies). This allows looping +# over just ${packageName}_LIB_ALL_DEPENDENCIES looking at +# ${packageName}_ENABLE_${depPkg} to see if the package is enable or not. +# This also includes special logic for required subpackages for parent +# packages where only the shell of the parent package is enabled and not +# all of its required subpackages are enabled. +# +macro(tribits_setup_direct_package_dependencies_lists_and_lib_required_enable_vars packageName) + + # LIB dependencies + + set(${packageName}_LIB_ALL_DEPENDENCIES "") + set(${packageName}_LIB_ENABLED_DEPENDENCIES "") + + foreach(depPkg ${${packageName}_LIB_REQUIRED_DEP_PACKAGES}) + list(APPEND ${packageName}_LIB_ALL_DEPENDENCIES ${depPkg}) + if (${PROJECT_NAME}_ENABLE_${packageName} AND ${PROJECT_NAME}_ENABLE_${depPkg}) + set(${packageName}_ENABLE_${depPkg} ON) + list(APPEND ${packageName}_LIB_ENABLED_DEPENDENCIES ${depPkg}) + endif() + endforeach() + # See below NOTE about required subpackage dependencies not being enabled in + # some cases! + + foreach(depPkg ${${packageName}_LIB_OPTIONAL_DEP_PACKAGES}) + list(APPEND ${packageName}_LIB_ALL_DEPENDENCIES ${depPkg}) + if (${PROJECT_NAME}_ENABLE_${packageName} AND ${packageName}_ENABLE_${depPkg}) + list(APPEND ${packageName}_LIB_ENABLED_DEPENDENCIES ${depPkg}) + endif() + endforeach() + + foreach(depPkg ${${packageName}_LIB_REQUIRED_DEP_TPLS}) + list(APPEND ${packageName}_LIB_ALL_DEPENDENCIES ${depPkg}) + if (${PROJECT_NAME}_ENABLE_${packageName}) + set(${packageName}_ENABLE_${depPkg} ON) + list(APPEND ${packageName}_LIB_ENABLED_DEPENDENCIES ${depPkg}) + endif() + endforeach() + + foreach(depPkg ${${packageName}_LIB_OPTIONAL_DEP_TPLS}) + list(APPEND ${packageName}_LIB_ALL_DEPENDENCIES ${depPkg}) + if (${PROJECT_NAME}_ENABLE_${packageName} AND ${packageName}_ENABLE_${depPkg}) + list(APPEND ${packageName}_LIB_ENABLED_DEPENDENCIES ${depPkg}) + endif() + endforeach() + + # TEST dependencies + + set(${packageName}_TEST_ALL_DEPENDENCIES "") + set(${packageName}_TEST_ENABLED_DEPENDENCIES "") + + if (${PROJECT_NAME}_ENABLE_${packageName} + AND + (${packageName}_ENABLE_TESTS OR ${packageName}_ENABLE_EXAMPLES) + ) + set(enablePkgAndTestsOrExamples ON) + else() + set(enablePkgAndTestsOrExamples OFF) + endif() + + foreach(depPkg ${${packageName}_TEST_REQUIRED_DEP_PACKAGES}) + list(APPEND ${packageName}_TEST_ALL_DEPENDENCIES ${depPkg}) + if (enablePkgAndTestsOrExamples) + list(APPEND ${packageName}_TEST_ENABLED_DEPENDENCIES ${depPkg}) + endif() + endforeach() + + foreach(depPkg ${${packageName}_TEST_OPTIONAL_DEP_PACKAGES}) + list(APPEND ${packageName}_TEST_ALL_DEPENDENCIES ${depPkg}) + if (enablePkgAndTestsOrExamples AND ${packageName}_ENABLE_${depPkg}) + list(APPEND ${packageName}_TEST_ENABLED_DEPENDENCIES ${depPkg}) + endif() + endforeach() + + foreach(depPkg ${${packageName}_TEST_REQUIRED_DEP_TPLS}) + list(APPEND ${packageName}_TEST_ALL_DEPENDENCIES ${depPkg}) + if (enablePkgAndTestsOrExamples) + list(APPEND ${packageName}_TEST_ENABLED_DEPENDENCIES ${depPkg}) + endif() + endforeach() + + foreach(depPkg ${${packageName}_TEST_OPTIONAL_DEP_TPLS}) + list(APPEND ${packageName}_TEST_ALL_DEPENDENCIES ${depPkg}) + if (enablePkgAndTestsOrExamples AND ${packageName}_ENABLE_${depPkg}) + list(APPEND ${packageName}_TEST_ENABLED_DEPENDENCIES ${depPkg}) + endif() + endforeach() + +endmacro() +# NOTE: Above, a required dependency of an enabled package may not actually be +# enabled if it is a required subpackage of a parent package and the parent +# package was not actually enabled due to a dependency but the shell of the +# parent package was only enabled at the very end. This is one of the more +# confusing aspects of the TriBITS dependency system. + + +# Function to print the direct package dependency lists +# +function(tribits_print_direct_package_dependencies_lists packageName) + set(PRINTED_VAR "") + message("") + print_nonempty_var_with_spaces(${packageName}_LIB_ENABLED_DEPENDENCIES PRINTED_VAR) + print_var_with_spaces(${packageName}_LIB_ALL_DEPENDENCIES PRINTED_VAR) + print_nonempty_var_with_spaces(${packageName}_TEST_ENABLED_DEPENDENCIES PRINTED_VAR) + print_nonempty_var_with_spaces(${packageName}_TEST_ALL_DEPENDENCIES PRINTED_VAR) +endfunction() + + # # Private helper macros # @@ -1311,7 +1450,7 @@ macro(tribits_adjust_package_enables) message("Set cache entries for optional packages/TPLs and tests/examples for packages actually enabled ...") message("") foreach(TRIBITS_PACKAGE ${${PROJECT_NAME}_ENABLED_SE_PACKAGES}) - tribits_add_optional_package_enables(${TRIBITS_PACKAGE}) + tribits_set_up_optional_package_enables_and_cache_vars(${TRIBITS_PACKAGE}) endforeach() # @@ -1330,16 +1469,38 @@ macro(tribits_adjust_package_enables) tribits_set_up_enabled_lists_and_se_pkg_idx() + # + # H) Set up flat list of direct package dependencies (even for non-enabled + # packages) and enabled package dependencies for enabled packages + # + + foreach(TRIBITS_PACKAGE ${${PROJECT_NAME}_SE_PACKAGES}) + tribits_setup_direct_package_dependencies_lists_and_lib_required_enable_vars( + ${TRIBITS_PACKAGE}) + endforeach() + + if (${PROJECT_NAME}_DUMP_PACKAGE_DEPENDENCIES) + message("\nDumping direct dependencies for each SE package ...") + foreach(TRIBITS_PACKAGE ${${PROJECT_NAME}_SE_PACKAGES}) + tribits_print_direct_package_dependencies_lists(${TRIBITS_PACKAGE}) + endforeach() + endif() + endmacro() -# Function that sets up the full package dependencies for each enabled -# package. +# Function that sets up the full package dependencies for each enabled package +# including all of its indirect upstream package dependencies. # # This is needed in several different parts of the TriBITS implementation. # +# ToDo: #63: Remove this function since we should not need a full list of +# direct and indirect package dependencies! +# function(tribits_package_set_full_enabled_dep_packages PACKAGE_NAME) + set(PACKAGE_FULL_DEPS_LIST "") + foreach(DEP_PKG ${${PACKAGE_NAME}_LIB_REQUIRED_DEP_PACKAGES}) if (${PROJECT_NAME}_ENABLE_${DEP_PKG}) list(APPEND PACKAGE_FULL_DEPS_LIST ${DEP_PKG}) @@ -1363,7 +1524,7 @@ function(tribits_package_set_full_enabled_dep_packages PACKAGE_NAME) list(REMOVE_DUPLICATES PACKAGE_FULL_DEPS_LIST) endif() - set(ORDERED_PACKAGE_FULL_DEPS_LIST) + set(ORDERED_PACKAGE_FULL_DEPS_LIST "") foreach(DEP_PACKAGE ${PACKAGE_FULL_DEPS_LIST}) @@ -1406,6 +1567,9 @@ endfunction() # Function that creates enable-only dependency data-structures # +# ToDo: #63: Remove this function since we should not need a full list of +# direct and indirect package dependencies! +# function(tribits_set_up_enabled_only_dependencies) set(GENERATE_EXPORT_DEPENDENCIES ${${PROJECT_NAME}_GENERATE_EXPORT_FILE_DEPENDENCIES}) diff --git a/cmake/tribits/core/package_arch/TribitsCommonArgsHelpers.cmake b/cmake/tribits/core/package_arch/TribitsCommonArgsHelpers.cmake index a6370f153723..9aaffca9828d 100644 --- a/cmake/tribits/core/package_arch/TribitsCommonArgsHelpers.cmake +++ b/cmake/tribits/core/package_arch/TribitsCommonArgsHelpers.cmake @@ -55,7 +55,9 @@ function(tribits_set_linker_language_from_arg TARGET_NAME_IN LINKER_LANGUAGE_I if (LINKER_LANGUAGE) - if (${PROJECT_NAME}_VERBOSE_CONFIGURE OR TRIBITS_SET_LINKER_LANGUAGE_FROM_ARG_DEBUG_DUMP) + if (${PROJECT_NAME}_VERBOSE_CONFIGURE + OR TRIBITS_SET_LINKER_LANGUAGE_FROM_ARG_DEBUG_DUMP + ) message("-- Setting linker language for target '${TARGET_NAME_IN}' to '${LINKER_LANGUAGE}'") endif() @@ -63,6 +65,7 @@ function(tribits_set_linker_language_from_arg TARGET_NAME_IN LINKER_LANGUAGE_I TARGET ${TARGET_NAME_IN} APPEND PROPERTY LINKER_LANGUAGE ${LINKER_LANGUAGE} ) + endif() endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsConfigureFile.cmake b/cmake/tribits/core/package_arch/TribitsConfigureFile.cmake new file mode 100644 index 000000000000..55ac9123cd38 --- /dev/null +++ b/cmake/tribits/core/package_arch/TribitsConfigureFile.cmake @@ -0,0 +1,180 @@ +# @HEADER +# ************************************************************************ +# +# TriBITS: Tribal Build, Integrate, and Test System +# Copyright 2013 Sandia Corporation +# +# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +# the U.S. Government retains certain rights in this software. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Corporation nor the names of the +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# ************************************************************************ +# @HEADER + + + +# Macro that configures the package's main config.h file +# +function(tribits_add_config_define DEFINE) + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("-- " "Package ${PARENT_PACKAGE_NAME}: adding compiler" + " define to config file: ${DEFINE}") + endif() + global_set(${PARENT_PACKAGE_NAME}_CONFIG_DEFINES + "${${PARENT_PACKAGE_NAME}_CONFIG_DEFINES}\n#define ${DEFINE}") + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("-- ${${PARENT_PACKAGE_NAME}_CONFIG_DEFINES}") + endif() +endfunction() + + +# @FUNCTION: tribits_configure_file() +# +# Macro that configures the package's main configured header file (typically +# called ``${PACKAGE_NAME}_config.h`` but any name can be used). +# +# Usage:: +# +# tribits_configure_file() +# +# This function requires the file:: +# +# ${PACKAGE_SOURCE_DIR}/cmake/.in +# +# exists and it creates the file:: +# +# ${CMAKE_CURRENT_BINARY_DIR}/ +# +# by calling the built-in ``configure_file()`` command:: +# +# configure_file( +# ${PACKAGE_SOURCE_DIR}/cmake/.in +# ${CMAKE_CURRENT_BINARY_DIR}/ +# ) +# +# which does basic substitution of CMake variables (see documentation for +# built-in CMake `configure_file()`_ command for rules on how it performs +# substitutions). This command is typically used to configure the package's +# main `/cmake/_config.h.in`_ file. +# +# In addition to just calling ``configure_file()``, this function also aids in +# creating configured header files adding macros for deprecating code as +# described below. +# +# **Deprecated Code Macros** +# +# If ``${PARENT_PACKAGE_NAME}_SHOW_DEPRECATED_WARNINGS`` is ``TRUE`` (see +# `tribits_add_show_deprecated_warnings_option()`_), then the local CMake +# variable ``${PARENT_PACKAGE_NAME_UC}_DEPRECATED_DECLARATIONS`` is set which +# adds a define ``_DEPRECATED`` (where +# ```` is the package name in all upper-case letters) +# which adds a compiler-specific deprecated warning for an entity. To take +# advantage of this, just add the line:: +# +# @_DEPRECATED_DECLARATIONS@ +# +# to the ``.in`` file and it will be expanded at configure +# time. +# +# Then C/C++ code can use this macro to deprecate functions, variables, +# classes, etc., for example, using:: +# +# _DEPRECATED class SomeDepreatedClass { ... }. +# +# If the particular compiler does not support deprecated warnings, then this +# macro is defined to be empty. See `Regulated Backward Compatibility and +# Deprecated Code`_ for more details. +# +function(tribits_configure_file PACKAGE_NAME_CONFIG_FILE) + + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("\nPACKAGE_CONFIGURE_FILE: ${PACKAGE_NAME_CONFIG_FILE}") + endif() + + # Set up the deprecated attribute if showing deprecated warnings + if (${PARENT_PACKAGE_NAME}_SHOW_DEPRECATED_WARNINGS) + multiline_set(${PARENT_PACKAGE_NAME_UC}_DEPRECATED_DECLARATIONS + "#ifndef ${PARENT_PACKAGE_NAME_UC}_DEPRECATED\n" + "# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))\n" + "# define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED __attribute__((__deprecated__))\n" + "# else\n" + "# define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED\n" + "# endif\n" + "#endif\n" + "\n" + "#ifndef ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_MSG\n" + "# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))\n" + "# define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_MSG(MSG) __attribute__((__deprecated__ (#MSG) ))\n" + "# elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))\n" + "# define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_MSG(MSG) __attribute__((__deprecated__))\n" + "# else\n" + "# define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_MSG(MSG)\n" + "# endif\n" + "#endif\n" + ) + else() + multiline_set(${PARENT_PACKAGE_NAME_UC}_DEPRECATED_DECLARATIONS + "#define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED\n" + "#define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_MSG(MSG)\n" + ) + endif() + + if (${PARENT_PACKAGE_NAME}_HIDE_DEPRECATED_CODE) + string(APPEND ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_DECLARATIONS + "\n#define ${PARENT_PACKAGE_NAME_UC}_HIDE_DEPRECATED_CODE") + endif() + + # Set up the macro to create the define for time monitor + set(TIME_MONITOR_DEFINE_NAME ${PARENT_PACKAGE_NAME_UC}_TEUCHOS_TIME_MONITOR) + set(FUNC_TIME_MONITOR_MACRO_NAME ${PARENT_PACKAGE_NAME_UC}_FUNC_TIME_MONITOR) + set(FUNC_TIME_MONITOR_DIFF_MACRO_NAME ${PARENT_PACKAGE_NAME_UC}_FUNC_TIME_MONITOR_DIFF) + if (${PARENT_PACKAGE_NAME}_ENABLE_TEUCHOS_TIME_MONITOR) + multiline_set(${PARENT_PACKAGE_NAME_UC}_TEUCHOS_TIME_MONITOR_DECLARATIONS + "#ifndef ${FUNC_TIME_MONITOR_MACRO_NAME}\n" + "# define ${TIME_MONITOR_DEFINE_NAME}\n" + "# define ${FUNC_TIME_MONITOR_MACRO_NAME}(FUNCNAME) \\\n" + " TEUCHOS_FUNC_TIME_MONITOR_DIFF(FUNCNAME, ${PARENT_PACKAGE_NAME_UC})\n" + "# define ${FUNC_TIME_MONITOR_DIFF_MACRO_NAME}(FUNCNAME, DIFF) \\\n" + " TEUCHOS_FUNC_TIME_MONITOR_DIFF(FUNCNAME, DIFF)\n" + "#endif\n" + ) + else() + multiline_set(${PARENT_PACKAGE_NAME_UC}_TEUCHOS_TIME_MONITOR_DECLARATIONS + "#define ${FUNC_TIME_MONITOR_MACRO_NAME}(FUNCNAME)\n" + "#define ${FUNC_TIME_MONITOR_DIFF_MACRO_NAME}(FUNCNAME, DIFF)\n" + ) + endif() + + # Configure the file + configure_file( + ${PACKAGE_SOURCE_DIR}/cmake/${PACKAGE_NAME_CONFIG_FILE}.in + ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME_CONFIG_FILE} + ) + +endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsCopyFilesToBinaryDir.cmake b/cmake/tribits/core/package_arch/TribitsCopyFilesToBinaryDir.cmake index b2f29290f503..514092c19af3 100644 --- a/cmake/tribits/core/package_arch/TribitsCopyFilesToBinaryDir.cmake +++ b/cmake/tribits/core/package_arch/TribitsCopyFilesToBinaryDir.cmake @@ -42,7 +42,6 @@ include(TribitsAddTestHelpers) include(CMakeParseArguments) -# # @FUNCTION: tribits_copy_files_to_binary_dir() # # Function that copies a list of files from a source directory to a diff --git a/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake b/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake index 8d9270b0f61a..0ab3cc48b73e 100644 --- a/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake +++ b/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake @@ -41,6 +41,8 @@ include(TribitsGeneralMacros) include(MessageWrapper) +cmake_policy(SET CMP0057 NEW) # Support if ( ... IN_LIST ... ) + # @FUNCTION: tribits_external_package_write_config_file() # @@ -177,11 +179,13 @@ endfunction() # ````: Name of variable that will contain the string # for the config file on output. # -# This function reads from the variables ``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 to -# represent these libraries and include directories. +# This function reads from the variables ``TPL__INCLUDE_DIRS`` +# ``TPL__LIBRARIES``, and ``_LIB_ENABLED_DEPENDENCIES`` +# (which must already be set) and uses that information to produce the +# contents of the ``Config.cmake`` which is returned as a string +# variable that contains IMPORTED targets to represent these libraries and +# include directories as well as ``find_dependency()`` calls for upstream +# packages listed in ``_LIB_ENABLED_DEPENDENCIES`` # # ToDo: Flesh out more documentation for behavior as more features are added # for handling: @@ -200,11 +204,18 @@ function(tribits_external_package_write_config_file_str tplName tplConfigFileStr "#\n" "# Generated by CMake, do not edit!\n" "\n" - "include_guard()\n" + "# Guard against multiple inclusion\n" + "if (TARGET ${tplName}::all_libs)\n" + " return()\n" + "endif()\n" "\n" ) - # B) Create IMPORTED library targets from TPL_${tplName}_LIBRARIES + # B) Call find_dependency() for all direct dependent upstream TPLs + tribits_external_package_add_find_upstream_dependencies_str(${tplName} + configFileStr) + + # C) Create IMPORTED library targets from TPL_${tplName}_LIBRARIES tribits_external_package_process_libraries_list( ${tplName} LIB_TARGETS_LIST_OUT libTargets @@ -212,7 +223,7 @@ function(tribits_external_package_write_config_file_str tplName tplConfigFileStr CONFIG_FILE_STR_INOUT configFileStr ) - # C) Create the ::all_libs target + # D) Create the ::all_libs target tribits_external_package_create_all_libs_target( ${tplName} LIB_TARGETS_LIST ${libTargets} @@ -220,17 +231,93 @@ function(tribits_external_package_write_config_file_str tplName tplConfigFileStr CONFIG_FILE_STR_INOUT configFileStr ) - # D) Set the output + # E) Set the output set(${tplConfigFileStrOut} "${configFileStr}" PARENT_SCOPE) endfunction() +# @FUNCTION: tribits_external_package_add_find_upstream_dependencies_str() +# +# Add code to call find_dependency() for all upstream external packages/TPLs +# listed in ``_LIB_ENABLED_DEPENDENCIES``. +# +# Usage:: +# +# tribits_external_package_add_find_upstream_dependencies_str(tplName +# configFileFragStrInOut) +# +# NOTE: This also requires that `_DIR` be set for each +# external package/TPL listed in ``_LIB_ENABLED_DEPENDENCIES``. +# +function(tribits_external_package_add_find_upstream_dependencies_str + tplName configFileFragStrInOut + ) + if (NOT "${${tplName}_LIB_ENABLED_DEPENDENCIES}" STREQUAL "") + set(configFileFragStr "${${configFileFragStrInOut}}") + string(APPEND configFileFragStr + "include(CMakeFindDependencyMacro)\n" + "\n" + "# Don't allow find_dependency() to search anything other than _DIR\n" + "set(${tplName}_SearchNoOtherPathsArgs\n" + " NO_DEFAULT_PATH\n" + " NO_PACKAGE_ROOT_PATH NO_CMAKE_PATH\n" + " NO_CMAKE_ENVIRONMENT_PATH\n" + " NO_SYSTEM_ENVIRONMENT_PATH\n" + " NO_CMAKE_PACKAGE_REGISTRY\n" + " NO_CMAKE_SYSTEM_PATH\n" + " NO_CMAKE_SYSTEM_PACKAGE_REGISTRY\n" + " CMAKE_FIND_ROOT_PATH_BOTH\n" + " ONLY_CMAKE_FIND_ROOT_PATH\n" + " NO_CMAKE_FIND_ROOT_PATH\n" + " )\n" + "\n" + ) + foreach (upstreamTplDepEntry IN LISTS ${tplName}_LIB_ENABLED_DEPENDENCIES) + tribits_external_package_append_upstream_target_link_libraries_get_name_and_vis( + "${upstreamTplDepEntry}" upstreamTplDepName upstreamTplDepVis) + if ("${${upstreamTplDepName}_DIR}" STREQUAL "") + message(FATAL_ERROR "ERROR: ${upstreamTplDepName}_DIR is empty!") + endif() + string(APPEND configFileFragStr + "set(${upstreamTplDepName}_DIR \"${${upstreamTplDepName}_DIR}\")\n" + "find_dependency(${upstreamTplDepName} REQUIRED CONFIG \${${tplName}_SearchNoOtherPathsArgs})\n" + "unset(${upstreamTplDepName}_DIR)\n" + "\n" + ) + endforeach() + string(APPEND configFileFragStr + "unset(${tplName}_SearchNoOtherPathsArgs)\n" + "\n" + ) + set(${configFileFragStrInOut} "${configFileFragStr}" PARENT_SCOPE) + endif() +endfunction() +# +# NOTE: Above, to be the most flexible, we have to set +# `_DIR` and then call `find_dependency()` instead of just +# including the file: +# +# include("${_DIR}/Config.cmake") +# +# This is to allow finding and depending on external packages/TPLs that may +# have different names than Config.cmake. The CMake +# command find_package() only returns _DIR, not the full +# path to the config file or even the config file name. It is a little bit +# dangerous to use find_dependency() in case the config fire is not found in +# the directory `_DIR` but I am not sure how else to do +# this. +# +# ToDo: It would be great to make the above find_dependency() call **only ** +# search the directory _DIR and no others. That would make + + # @FUNCTION: tribits_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. +# Read the ``TPL__LIBRARIES`` and +# ``_LIB_ENABLED_DEPENDENCIES`` list variables and produce the string +# for the IMPORTED targets commands with upstream linkages and return list of +# targets and left over linker flags. # # Usage:: # @@ -276,7 +363,7 @@ function(tribits_external_package_process_libraries_list tplName) set(configFileStr "") set(libTargets "") - set(lastLib "") + set(lastLibProcessed "") # Iterate through libs in reverse order setting dependencies on the libs # that came before them so CMake will put in right order on the link line. @@ -299,7 +386,8 @@ function(tribits_external_package_process_libraries_list tplName) list(APPEND libLinkFlagsList "${libentry}") else() tribits_external_package_process_libraries_list_library_entry( - ${tplName} "${libentry}" ${libEntryType} libTargets lastLib configFileStr ) + ${tplName} "${libentry}" ${libEntryType} libTargets lastLibProcessed + configFileStr ) endif() endforeach() @@ -360,17 +448,21 @@ endfunction() # NOTE: Above, if libentry is only 1 char long, then firstTwoCharsLibEntry is # also 1 char long and the above logic still works. -# Function to process a library inside of loop over TPL__LIBRARIES -# in the function tribits_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(). +# +# This also puts in linkages to upstream TPLs ``::all_libs`` listed +# in ``_LIB_ENABLED_DEPENDENCIES``. # function(tribits_external_package_process_libraries_list_library_entry tplName libentry libEntryType - libTargetsInOut lastLibInOut configFileStrInOut + libTargetsInOut lastLibProcessedInOut configFileStrInOut ) - cmake_policy(SET CMP0057 NEW) # Support if ( ... IN_LIST ... ) # Set local vars for inout vars set(libTargets ${${libTargetsInOut}}) - set(lastLib ${${lastLibInOut}}) + set(lastLibProcessed ${${lastLibProcessedInOut}}) set(configFileStr ${${configFileStrInOut}}) # Get libname tribits_external_package_get_libname_and_path_from_libentry( @@ -380,25 +472,30 @@ function(tribits_external_package_process_libraries_list_library_entry 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) + if (lastLibProcessed) string(APPEND configFileStr "target_link_libraries(${prefixed_libname}\n" - " INTERFACE ${tplName}::${lastLib})\n" + " INTERFACE ${tplName}::${lastLibProcessed})\n" ) + else() + tribits_external_package_append_upstream_target_link_libraries_str( ${tplName} + ${prefixed_libname} configFileStr ) endif() string(APPEND configFileStr "\n") # Update for next loop - set(lastLib ${libname}) + set(lastLibProcessed ${libname}) list(APPEND libTargets ${prefixed_libname}) endif() # Set output vars set(${libTargetsInOut} ${libTargets} PARENT_SCOPE) - set(${lastLibInOut} ${lastLib} PARENT_SCOPE) + set(${lastLibProcessedInOut} ${lastLibProcessed} PARENT_SCOPE) set(${configFileStrInOut} ${configFileStr} PARENT_SCOPE) endfunction() - +# NOTE: Above, we only need to link the first library :: +# against the upstream TPL libraries ::all_libs. The other +# imported targets :: for this TPL are linked to this first +# :: which has the needed dependencies. function(tribits_external_package_get_libname_and_path_from_libentry libentry libEntryType libnameOut libpathOut @@ -499,6 +596,86 @@ function(tribits_print_invalid_lib_link_option tplName liblinkoption) endfunction() +function(tribits_external_package_append_upstream_target_link_libraries_str + tplName prefix_libname configFileStrInOut + ) + set(configFileStr "${${configFileStrInOut}}") + if (${tplName}_LIB_ENABLED_DEPENDENCIES) + string(APPEND configFileStr + "target_link_libraries(${prefix_libname}\n") + foreach (upstreamTplDepEntry IN LISTS ${tplName}_LIB_ENABLED_DEPENDENCIES) + tribits_external_package_append_upstream_target_link_libraries_get_name_and_vis( + "${upstreamTplDepEntry}" upstreamTplDepName upstreamTplDepVis) + if (upstreamTplDepVis STREQUAL "PUBLIC") + string(APPEND configFileStr + " INTERFACE ${upstreamTplDepName}::all_libs # i.e. PUBLIC\n") + elseif(upstreamTplDepVis STREQUAL "PRIVATE") + string(APPEND configFileStr + " INTERFACE $ # i.e. PRIVATE\n") + else() + message(FATAL_ERROR "ERROR: Invalid visibility in entry '${upstreamTplDepEntry}'") + endif() + endforeach() + string(APPEND configFileStr + " )\n") + endif() + set(${configFileStrInOut} "${configFileStr}" PARENT_SCOPE) +endfunction() +# +# NOTE: Above, the syntax for a private dependency is: +# +# INTERFACE $ +# +# This has the effect of not bringing along the INTERFACE_INCLUDE_DIRECTORIES +# for upstreamLib so the include dirs for upstreamLib will not be listed on +# the compile lines of downstream object builds. But it will result in the +# libraries being listed on link lines for downstsream library and exec links. + + +# @FUNCTION: tribits_external_package_append_upstream_target_link_libraries_get_name_and_vis() +# +# Extract ```` and ```` from ``[:]`` input with +# default ```` of `PRIVATE`. +# +# Usage:: +# +# tribits_external_package_append_upstream_target_link_libraries_get_name_and_vis( +# upstreamTplDepEntry upstreamTplDepNameOut upstreamTplDepVisOut) +# +function(tribits_external_package_append_upstream_target_link_libraries_get_name_and_vis + upstreamTplDepEntry upstreamTplDepNameOut upstreamTplDepVisOut + ) + # Split on ':' to get [:] + string(REPLACE ":" ";" upstreamTplAndVisList "${upstreamTplDepEntry}") + list(LENGTH upstreamTplAndVisList upstreamTplAndVisListLen) + # Validate one or two entries only + if (upstreamTplAndVisListLen GREATER 2) + math(EXPR numColons "${upstreamTplAndVisListLen}-1") + message_wrapper(FATAL_ERROR + "ERROR: '${upstreamTplDepEntry}' has ${numColons} ':' but only 1 is allowed!") + endif() + # Set + list(GET upstreamTplAndVisList 0 upstreamTplDepName) + # Set + if (upstreamTplAndVisListLen EQUAL 2) + list(GET upstreamTplAndVisList 1 upstreamTplDepVis) + else() + set(upstreamTplDepVis PRIVATE) + endif() + # Assert valid + set(validVisValues "PUBLIC" "PRIVATE") + if (NOT upstreamTplDepVis IN_LIST validVisValues) + message_wrapper(FATAL_ERROR + "ERROR: '${upstreamTplDepEntry}' has invalid visibility '${upstreamTplDepVis}'." + " Only 'PUBLIC' or 'PRIVATE' allowed!") + return() # Only executed in unit-test mode! + endif() + # Set outputs + set(${upstreamTplDepNameOut} ${upstreamTplDepName} PARENT_SCOPE) + set(${upstreamTplDepVisOut} ${upstreamTplDepVis} PARENT_SCOPE) +endfunction() + + # @FUNCTION: tribits_external_package_create_all_libs_target() # # Creates the ::all_libs target command text using input info and diff --git a/cmake/tribits/core/package_arch/TribitsFindMostRecentFileTimestamp.cmake b/cmake/tribits/core/package_arch/TribitsFindMostRecentFileTimestamp.cmake index be6881ab1623..c6f70cef0664 100644 --- a/cmake/tribits/core/package_arch/TribitsFindMostRecentFileTimestamp.cmake +++ b/cmake/tribits/core/package_arch/TribitsFindMostRecentFileTimestamp.cmake @@ -40,7 +40,6 @@ include(CMakeParseArguments) -# # @FUNCTION: tribits_find_most_recent_file_timestamp() # # Find the most modified file in a set of base directories and return its @@ -294,7 +293,6 @@ function(tribits_find_most_recent_file_timestamp) endfunction() -# # @FUNCTION: tribits_find_most_recent_source_file_timestamp() # # Find the most modified source file in a set of base directories and return @@ -381,7 +379,6 @@ function(tribits_find_most_recent_source_file_timestamp) endfunction() -# # @FUNCTION: tribits_find_most_recent_binary_file_timestamp() # # Find the most modified binary file in a set of base directories and return @@ -471,7 +468,6 @@ function(tribits_find_most_recent_binary_file_timestamp) endfunction() -# # @FUNCTION: tribits_determine_if_current_package_needs_rebuilt() # # Determine at configure time if any of the upstream dependencies for a diff --git a/cmake/tribits/core/package_arch/TribitsGeneralMacros.cmake b/cmake/tribits/core/package_arch/TribitsGeneralMacros.cmake index 3c83d5d108c9..bd05810ae904 100644 --- a/cmake/tribits/core/package_arch/TribitsGeneralMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsGeneralMacros.cmake @@ -40,6 +40,7 @@ include(AppendSet) include(AssertDefined) include(MessageWrapper) +include(TribitsParseArgumentsHelpers) include(TribitsSortListAccordingToMasterList) @@ -372,150 +373,6 @@ function( tribits_gather_enabled_items PACKAGE_NAME LISTTYPE_PREFIX endfunction() -# Function that appends the Package/TPL include and library paths for given -# list of enabled Packages/TPLs -# -# As a side effect of calling this function, include_directories(...) to set -# all of the include directories for a given set of enabled Packages/TPLs. -# -# NOTE: The Packages/TPLs should be sorted in descending dependency order -# before calling this function. -# -# NOTE: Because this function may be called in cases where a package's -# required subpackages are not actually enabled (e.g. SEACAS subpackages) -# -function( tribits_append_include_and_link_dirs TPL_OR_PACKAGE PREFIX - LIST EXTRA_DEP_LIBS_INOUT - ) - if (TRIBITS_APPEND_INCLUDE_AND_LINK_DIRS_DEBUG_DUMP) - message("\nTRIBITS_APPEND_INCLUDE_AND_LINK_DIRS: '${TPL_OR_PACKAGE}'" - " '${PREFIX}' '${LIST}' '${EXTRA_DEP_LIBS_INOUT}'") - endif() - set(EXTRA_DEP_LIBS_INOUT_TMP ${${EXTRA_DEP_LIBS_INOUT}}) - cmake_policy(SET CMP0054 NEW) - if ( - "${TPL_OR_PACKAGE}" STREQUAL "TPL" - AND - ( - ${PROJECT_NAME}_TPL_SYSTEM_INCLUDE_DIRS - AND NOT - (${PARENT_PACKAGE_NAME}_SKIP_TPL_SYSTEM_INCLUDE_DIRS - OR ${PACKAGE_NAME}_SKIP_TPL_SYSTEM_INCLUDE_DIRS) - ) - ) - set(SYSTEM_ARG "SYSTEM") - else() - set(SYSTEM_ARG) - endif() - foreach(ITEM ${LIST}) - if (${PREFIX}${ITEM}_LIBRARIES) - append_set(EXTRA_DEP_LIBS_ARG_TMP ${${PREFIX}${ITEM}_LIBRARIES}) - endif() - if (${PREFIX}${ITEM}_INCLUDE_DIRS) - if (TRIBITS_APPEND_INCLUDE_AND_LINK_DIRS_DEBUG_DUMP) - message("-- " "include_directories(${SYSTEM_ARG} ${${PREFIX}${ITEM}_INCLUDE_DIRS})") - endif() - include_directories(${SYSTEM_ARG} ${${PREFIX}${ITEM}_INCLUDE_DIRS}) - endif() - if (${PREFIX}${ITEM}_LIBRARY_DIRS) - if (PREFIX) - # TODO: Is there a better way to know if we need this? - # We want LINK_DIRECTORIES for TPLs but not packages. - link_directories(${${PREFIX}${ITEM}_LIBRARY_DIRS}) - endif() - set_property(DIRECTORY APPEND PROPERTY PACKAGE_LIBRARY_DIRS - ${${PREFIX}${ITEM}_LIBRARY_DIRS}) - endif() - if (TRIBITS_APPEND_INCLUDE_AND_LINK_DIRS_DEBUG_DUMP) - print_var(${PREFIX}${ITEM}_LIBRARIES) - print_var(${PREFIX}${ITEM}_INCLUDE_DIRS) - print_var(${PREFIX}${ITEM}_LIBRARY_DIRS) - endif() - endforeach() - set(${EXTRA_DEP_LIBS_INOUT} ${EXTRA_DEP_LIBS_ARG_TMP} PARENT_SCOPE) -endfunction() - - -# Function that sorts and appends all the items in a dependency list for -# packages or TPLs. -# -function( tribits_sort_and_append_include_and_link_dirs_and_libs - TPL_OR_PACKAGE MASTER_SORT_LIST LIST PREFIX - EXTRA_DEP_LIBS_INOUT - ) - - if (TRIBITS_SORT_AND_APPEND_INCLUDE_AND_LINK_DIRS_AND_LIBS_DEBUG_DUMP) - message("TRIBITS_SORT_AND_APPEND_INCLUDE_AND_LINK_DIRS_AND_LIBS:") - print_var(MASTER_SORT_LIST) - print_var(LIST) - print_var(PREFIX) - print_var(EXTRA_DEP_LIBS_INOUT) - endif() - - set(LOCAL_LIST ${LIST}) - if (TRIBITS_SORT_AND_APPEND_INCLUDE_AND_LINK_DIRS_AND_LIBS_DEBUG_DUMP) - print_var(LOCAL_LIST) - endif() - - if (LOCAL_LIST) - - tribits_sort_list_according_to_master_list("${MASTER_SORT_LIST}" LOCAL_LIST) - if (TRIBITS_SORT_AND_APPEND_INCLUDE_AND_LINK_DIRS_AND_LIBS_DEBUG_DUMP) - print_var(LOCAL_LIST) - endif() - - set(EXTRA_DEP_LIBS_ARG_TMP ${${EXTRA_DEP_LIBS_INOUT}}) - tribits_append_include_and_link_dirs("${TPL_OR_PACKAGE}" "${PREFIX}" - "${LOCAL_LIST}" EXTRA_DEP_LIBS_ARG_TMP) - set(${EXTRA_DEP_LIBS_INOUT} ${EXTRA_DEP_LIBS_ARG_TMP} PARENT_SCOPE) - - endif() - -endfunction() - - -# Fully process the include and link directories and list of libraries for a -# package's list of dependent packages for use in creating a library or an -# executable -# -function( tribits_sort_and_append_package_include_and_link_dirs_and_libs - PACKAGE_NAME LIB_OR_TEST_ARG EXTRA_DEP_LIBS_INOUT - ) - - tribits_gather_enabled_items(${PACKAGE_NAME} ${LIB_OR_TEST_ARG} - PACKAGES ALL_DEP_PACKAGES) - - set(EXTRA_DEP_LIBS_TMP ${${EXTRA_DEP_LIBS_INOUT}}) - tribits_sort_and_append_include_and_link_dirs_and_libs( - "PACKAGE" - "${${PROJECT_NAME}_REVERSE_ENABLED_SE_PACKAGES}" - "${ALL_DEP_PACKAGES}" "" EXTRA_DEP_LIBS_TMP) - set(${EXTRA_DEP_LIBS_INOUT} ${EXTRA_DEP_LIBS_TMP} PARENT_SCOPE) - -endfunction() - - -# Fully process the include and link directories and list of libraries for a -# package's list of dependent TPLs for use in creating a library or an -# executable -# -function( tribits_sort_and_append_tpl_include_and_link_dirs_and_libs - PACKAGE_NAME LIB_OR_TEST_ARG EXTRA_DEP_LIBS_INOUT - ) - - tribits_gather_enabled_items(${PACKAGE_NAME} ${LIB_OR_TEST_ARG} - TPLS ALL_TPLS) - - set(EXTRA_DEP_LIBS_TMP ${${EXTRA_DEP_LIBS_INOUT}}) - tribits_sort_and_append_include_and_link_dirs_and_libs( - "TPL" - "${${PROJECT_NAME}_REVERSE_ENABLED_TPLS}" - "${ALL_TPLS}" TPL_ EXTRA_DEP_LIBS_TMP) - set(${EXTRA_DEP_LIBS_INOUT} ${EXTRA_DEP_LIBS_TMP} PARENT_SCOPE) - -endfunction() - - # Print trace of file processing # function(tribits_trace_file_processing TYPE_IN PROCESSING_TYPE_IN FILE_PATH) @@ -555,46 +412,3 @@ function(tribits_trace_file_processing TYPE_IN PROCESSING_TYPE_IN FILE_PATH) endfunction() -# Check to see if there are unparsed arguments after calling CMAKE_PARSE_ARGUMENTS -# -macro(tribits_check_for_unparsed_arguments) - - if( NOT "${PARSE_UNPARSED_ARGUMENTS}" STREQUAL "") - message( - ${${PROJECT_NAME}_CHECK_FOR_UNPARSED_ARGUMENTS} - "Arguments are being passed in but not used. UNPARSED_ARGUMENTS =" - " ${PARSE_UNPARSED_ARGUMENTS}" - ) - endif() - -endmacro() - - -# Check that a parase argument has at least one value -# -macro(tribits_assert_parse_arg_one_or_more_values PREFIX ARGNAME) - set(PREFIX_ARGNAME "${PREFIX}_${ARGNAME}") - list( LENGTH ${PREFIX_ARGNAME} ARG_NUM_VALS ) - if (ARG_NUM_VALS LESS 1) - message_wrapper(FATAL_ERROR - "ERROR: ${ARGNAME} must have at least one value!" ) - return() - # NOTE: The return is needed in unit testing mode - endif() -endmacro() - - -# Check that a parase argument has zero or one value -# -macro(tribits_assert_parse_arg_zero_or_one_value PREFIX ARGNAME) - set(PREFIX_ARGNAME "${PREFIX}_${ARGNAME}") - if (NOT "${${PREFIX_ARGNAME}}" STREQUAL "") - list( LENGTH ${PREFIX_ARGNAME} ARG_NUM_VALS ) - if (ARG_NUM_VALS GREATER 1) - message_wrapper(FATAL_ERROR - "ERROR: ${ARGNAME}='${${PREFIX_ARGNAME}}' can not have more than one value!" ) - return() - # NOTE: The return is needed in unit testing mode - endif() - endif() -endmacro() diff --git a/cmake/tribits/core/package_arch/TribitsGetVersionDate.cmake b/cmake/tribits/core/package_arch/TribitsGetVersionDate.cmake index 32a40b3eadf3..aa09836d628f 100644 --- a/cmake/tribits/core/package_arch/TribitsGetVersionDate.cmake +++ b/cmake/tribits/core/package_arch/TribitsGetVersionDate.cmake @@ -2,7 +2,6 @@ include("${${PROJECT_NAME}_TRIBITS_DIR}/core/utils/MessageWrapper.cmake") include("${${PROJECT_NAME}_TRIBITS_DIR}/core/utils/TribitsStripQuotesFromStr.cmake") -# # @FUNCTION: tribits_get_raw_git_commit_utc_time() # # Get the git commit date of a repo at a given commit in UTC in the format @@ -58,7 +57,6 @@ function(tribits_get_raw_git_commit_utc_time repo_base_dir commit_ref endfunction() -# # @FUNCTION: tribits_get_version_date_from_raw_git_commit_utc_time() # # Takes input of the form "YYYY-MM-DD hh:mm:ss +0000" from the git command:: diff --git a/cmake/tribits/core/package_arch/TribitsGitRepoVersionInfo.cmake b/cmake/tribits/core/package_arch/TribitsGitRepoVersionInfo.cmake new file mode 100644 index 000000000000..8dbe8f519c97 --- /dev/null +++ b/cmake/tribits/core/package_arch/TribitsGitRepoVersionInfo.cmake @@ -0,0 +1,164 @@ +# @HEADER +# ************************************************************************ +# +# TriBITS: Tribal Build, Integrate, and Test System +# Copyright 2013 Sandia Corporation +# +# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +# the U.S. Government retains certain rights in this software. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Corporation nor the names of the +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# ************************************************************************ +# @HEADER + +################################################################################ +# +# Module containing functions for getting Git repo information +# +################################################################################ + + +# @FUNCTION: tribits_git_repo_sha1() +# +# Get the Git repo version SHA1. +# +# Usage:: +# +# tribits_git_repo_sha1( +# FAILURE_MESSAGE_OUT ) +# +# If ```` is non-empty on input, then the variable +# ```` will be set to a non-empty value on output with the +# error message if an error occurs and the SHA1 for ```` can not +# be computed. If ```` is empty in input, and there is an +# error, a ``FATAL_ERROR`` will be raised. +# +# NOTE: To get the SHA1 for the Git repo ````, it must contain the +# ``.git/`` directory and the ``git`` executable var ``GIT_EXECUTABLE`` must +# be set. Otherwise, it is an error. +# +function(tribits_git_repo_sha1 gitRepoDir gitRepoSha1Out) + + cmake_parse_arguments( PARSE_ARGV 2 + PARSE "" "" # prefix, options, one_value_keywords + "FAILURE_MESSAGE_OUT" # multi_value_keywords + ) + tribits_check_for_unparsed_arguments() + tribits_assert_parse_arg_zero_or_one_value(PARSE FAILURE_MESSAGE_OUT) + + set(failureMsg "") + + if (NOT GIT_EXECUTABLE) + set(failureMsg "ERROR: The program '${GIT_NAME}' could not be found!") + elseif (NOT IS_DIRECTORY "${gitRepoDir}/.git") + set(failureMsg "ERROR: The directory ${gitRepoDir}/.git does not exist!") + endif() + + set(gitRepoSha1 "") + if (failureMsg STREQUAL "") + execute_process( + COMMAND ${GIT_EXECUTABLE} log -1 "--pretty=format:%H" + WORKING_DIRECTORY ${gitRepoDir} + RESULT_VARIABLE gitCmndRtn OUTPUT_VARIABLE gitCmndOutput + ) + + if (NOT gitCmndRtn STREQUAL 0) + set(failureMsg "ERROR: ${GIT_EXECUTABLE} command returned ${gitCmndRtn}!=0 for repo ${gitRepoDir}!") + else() + set(gitRepoSha1 "${gitCmndOutput}") + endif() + endif() + + if (NOT failureMsg STREQUAL "" AND PARSE_FAILURE_MESSAGE_OUT STREQUAL "") + message(FATAL_ERROR "${failureMsg}") + elseif (PARSE_FAILURE_MESSAGE_OUT) + set(${PARSE_FAILURE_MESSAGE_OUT} "${failureMsg}" PARENT_SCOPE) + endif() + set(${gitRepoSha1Out} "${gitRepoSha1}" PARENT_SCOPE) + +endfunction() + + +# Run the git log command to get the version info for a git repo +# +function(tribits_generate_single_repo_version_string gitRepoDir + repoVersionStringOut + ) + + tribits_assert_git_executable() + + # A) Get the basic version info. + + execute_process( + COMMAND ${GIT_EXECUTABLE} log -1 "--pretty=format:%h [%ad] <%ae>" + WORKING_DIRECTORY ${gitRepoDir} + RESULT_VARIABLE gitCmndRtn + OUTPUT_VARIABLE gitCmndOutput + ) + + if (NOT gitCmndRtn STREQUAL 0) + message(FATAL_ERROR "ERROR, ${GIT_EXECUTABLE} command returned ${gitCmndRtn}!=0" + " for repo ${gitRepoDir}!") + set(gitVersionLine "Error, could not get version info!") + else() + set(gitVersionLine "${gitCmndOutput}") + endif() + + # B) Get the first 80 chars of the summary message for more info + + execute_process( + COMMAND ${GIT_EXECUTABLE} log -1 --pretty=format:%s + WORKING_DIRECTORY ${gitRepoDir} + RESULT_VARIABLE gitCmndRtn + OUTPUT_VARIABLE gitCmndOutput + ) + + if (NOT gitCmndRtn STREQUAL 0) + message(FATAL_ERROR "ERROR, ${GIT_EXECUTABLE} command returned ${gitCmndRtn}!=0" + " for extra repo ${gitRepoDir}!") + set(gitSummaryStr "Error, could not get version summary!") + else() + set(maxSummaryLen 80) + string(SUBSTRING "${gitCmndOutput}" 0 ${maxSummaryLen} gitSummaryStr) + endif() + + set(${repoVersionStringOut} + "${gitVersionLine}\n${gitSummaryStr}" PARENT_SCOPE) + +endfunction() +# NOTE: Above, it is fine if ${maxSummaryLen} > len(${gitCmndOutput}) as +# string(SUBSTRING ...) will just shorten this to the lenght of the string. + + +function(tribits_assert_git_executable) + if (NOT GIT_EXECUTABLE) + message(SEND_ERROR "ERROR, the program '${GIT_NAME}' could not be found!" + " We can not generate the repo version file!") + endif() +endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake b/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake index 019dfd15fb0d..50340fb5afbd 100644 --- a/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake @@ -50,6 +50,7 @@ include(TribitsGetVersionDate) include(TribitsReportInvalidTribitsUsage) include(TribitsReadAllProjectDepsFilesCreateDepsGraph) include(TribitsAdjustPackageEnables) +include(TribitsGitRepoVersionInfo) # Standard TriBITS utilities includes include(TribitsAddOptionAndDefine) @@ -1251,75 +1252,6 @@ macro(tribits_copy_installer_resource _varname _source _destination) COPYONLY) endmacro() -# Run the git log command to get the version info for a git repo -# -function(tribits_generate_single_repo_version_string GIT_REPO_DIR - SINGLE_REPO_VERSION_STRING_OUT - ) - - if (NOT GIT_EXECUTABLE) - message(SEND_ERROR "ERROR, the program '${GIT_NAME}' could not be found!" - " We can not generate the repo version file!") - endif() - - # A) Get the basic version info. - - execute_process( - COMMAND ${GIT_EXECUTABLE} log -1 --pretty=format:"%h [%ad] <%ae>" - WORKING_DIRECTORY ${GIT_REPO_DIR} - RESULT_VARIABLE GIT_RETURN - OUTPUT_VARIABLE GIT_OUTPUT - ) - # NOTE: Above we have to add quotes '"' or CMake will not accept the - # command. However, git will put those quotes in the output so we have to - # strip them out later :-( - - if (NOT GIT_RETURN STREQUAL 0) - message(FATAL_ERROR "ERROR, ${GIT_EXECUTABLE} command returned ${GIT_RETURN}!=0" - " for extra repo ${GIT_REPO_DIR}!") - set(GIT_VERSION_INFO "Error, could not get version info!") - else() - # Strip the quotes off :-( - string(LENGTH "${GIT_OUTPUT}" GIT_OUTPUT_LEN) - math(EXPR OUTPUT_NUM_CHARS_TO_KEEP "${GIT_OUTPUT_LEN}-2") - string(SUBSTRING "${GIT_OUTPUT}" 1 ${OUTPUT_NUM_CHARS_TO_KEEP} - GIT_VERSION_INFO) - endif() - - # B) Get the first 80 chars of the summary message for more info - - execute_process( - COMMAND ${GIT_EXECUTABLE} log -1 --pretty=format:"%s" - WORKING_DIRECTORY ${GIT_REPO_DIR} - RESULT_VARIABLE GIT_RETURN - OUTPUT_VARIABLE GIT_OUTPUT - ) - - if (NOT GIT_RETURN STREQUAL 0) - message(FATAL_ERROR "ERROR, ${GIT_EXECUTABLE} command returned ${GIT_RETURN}!=0" - " for extra repo ${GIT_REPO_DIR}!") - set(GIT_VERSION_SUMMARY "Error, could not get version summary!") - else() - # Strip ouf quotes and quote the 80 char string - set(MAX_SUMMARY_LEN 80) - math(EXPR MAX_SUMMARY_LEN_PLUS_2 "${MAX_SUMMARY_LEN}+2") - string(LENGTH "${GIT_OUTPUT}" GIT_OUTPUT_LEN) - math(EXPR OUTPUT_NUM_CHARS_TO_KEEP "${GIT_OUTPUT_LEN}-2") - string(SUBSTRING "${GIT_OUTPUT}" 1 ${OUTPUT_NUM_CHARS_TO_KEEP} - GIT_OUTPUT_STRIPPED) - if (GIT_OUTPUT_LEN GREATER ${MAX_SUMMARY_LEN_PLUS_2}) - string(SUBSTRING "${GIT_OUTPUT_STRIPPED}" 0 ${MAX_SUMMARY_LEN} - GIT_SUMMARY_STR) - else() - set(GIT_SUMMARY_STR "${GIT_OUTPUT_STRIPPED}") - endif() - endif() - - set(${SINGLE_REPO_VERSION_STRING_OUT} - "${GIT_VERSION_INFO}\n${GIT_SUMMARY_STR}" PARENT_SCOPE) - -endfunction() - # Get the versions of all the git repos # @@ -1441,134 +1373,63 @@ function(tribits_generate_repo_version_output_and_file_and_install) endfunction() -# Print out a list with white-space separators with an initial doc string -# -function(tribits_print_prefix_string_and_list DOCSTRING LIST_TO_PRINT) - string(REPLACE ";" " " LIST_TO_PRINT_STR "${LIST_TO_PRINT}") - list(LENGTH LIST_TO_PRINT NUM_ELEMENTS) - if (NUM_ELEMENTS GREATER "0") - message("${DOCSTRING}: ${LIST_TO_PRINT_STR} ${NUM_ELEMENTS}") - else() - message("${DOCSTRING}: ${NUM_ELEMENTS}") - endif() -endfunction() - - -# Print the current set of enabled/disabled packages given input list of -# packages -# -function(tribits_print_enabled_packages_list_from_var PACKAGES_LIST_VAR - DOCSTRING ENABLED_FLAG INCLUDE_EMPTY - ) - if (ENABLED_FLAG AND NOT INCLUDE_EMPTY) - tribits_get_enabled_list(${PACKAGES_LIST_VAR} ${PROJECT_NAME} - ENABLED_PACKAGES NUM_ENABLED) - elseif (ENABLED_FLAG AND INCLUDE_EMPTY) - tribits_get_nondisabled_list(${PACKAGES_LIST_VAR} ${PROJECT_NAME} - ENABLED_PACKAGES NUM_ENABLED) - elseif (NOT ENABLED_FLAG AND NOT INCLUDE_EMPTY) - tribits_get_disabled_list(${PACKAGES_LIST_VAR} ${PROJECT_NAME} - ENABLED_PACKAGES NUM_ENABLED) - else() # NOT ENABLED_FLAG AND INCLUDE_EMPTY - tribits_get_nonenabled_list(${PACKAGES_LIST_VAR} ${PROJECT_NAME} - ENABLED_PACKAGES NUM_ENABLED) - endif() - tribits_print_prefix_string_and_list("${DOCSTRING}" "${ENABLED_PACKAGES}") -endfunction() - - -# Prints the current set of enabled/disabled packages -# -function(tribits_print_enabled_package_list DOCSTRING ENABLED_FLAG INCLUDE_EMPTY) - tribits_print_enabled_packages_list_from_var( ${PROJECT_NAME}_PACKAGES - "${DOCSTRING}" ${ENABLED_FLAG} ${INCLUDE_EMPTY} ) -endfunction() - - -# Prints the current set of enabled/disabled SE packages -# -function(tribits_print_enabled_se_package_list DOCSTRING ENABLED_FLAG INCLUDE_EMPTY) - if (ENABLED_FLAG AND NOT INCLUDE_EMPTY) - tribits_get_enabled_list( ${PROJECT_NAME}_SE_PACKAGES ${PROJECT_NAME} - ENABLED_SE_PACKAGES NUM_ENABLED) - elseif (ENABLED_FLAG AND INCLUDE_EMPTY) - tribits_get_nondisabled_list( ${PROJECT_NAME}_SE_PACKAGES ${PROJECT_NAME} - ENABLED_SE_PACKAGES NUM_ENABLED) - elseif (NOT ENABLED_FLAG AND NOT INCLUDE_EMPTY) - tribits_get_disabled_list( ${PROJECT_NAME}_SE_PACKAGES ${PROJECT_NAME} - ENABLED_SE_PACKAGES NUM_ENABLED) - else() # NOT ENABLED_FLAG AND INCLUDE_EMPTY - tribits_get_nonenabled_list( ${PROJECT_NAME}_SE_PACKAGES ${PROJECT_NAME} - ENABLED_SE_PACKAGES NUM_ENABLED) - endif() - tribits_print_prefix_string_and_list("${DOCSTRING}" "${ENABLED_SE_PACKAGES}") -endfunction() - - -# Print the current set of enabled/disabled TPLs -# -function(tribits_print_enabled_tpl_list DOCSTRING ENABLED_FLAG INCLUDE_EMPTY) - if (ENABLED_FLAG AND NOT INCLUDE_EMPTY) - tribits_get_enabled_list( ${PROJECT_NAME}_TPLS TPL - ENABLED_TPLS NUM_ENABLED) - elseif (ENABLED_FLAG AND INCLUDE_EMPTY) - tribits_get_nondisabled_list( ${PROJECT_NAME}_TPLS TPL - ENABLED_TPLS NUM_ENABLED) - elseif (NOT ENABLED_FLAG AND NOT INCLUDE_EMPTY) - tribits_get_disabled_list( ${PROJECT_NAME}_TPLS TPL - ENABLED_TPLS NUM_ENABLED) - else() # NOT ENABLED_FLAG AND INCLUDE_EMPTY - tribits_get_nonenabled_list( ${PROJECT_NAME}_TPLS TPL - ENABLED_TPLS NUM_ENABLED) - endif() - tribits_print_prefix_string_and_list("${DOCSTRING}" "${ENABLED_TPLS}") -endfunction() - - # Adjust package enable logic and print out before and after state # # On output sets: # -# ${PROJECT_NAME}_NUM_ENABLED_PACKAGES: Number of enabled packages (local variable) -# ${PROJECT_NAME}_ENABLE_${PACKAGE_NAME}: Enable status of PACKAGE_NAME (local variable) +# * ${PROJECT_NAME}_NUM_ENABLED_PACKAGES: Number of enabled packages (local variable) +# * ${PROJECT_NAME}_ENABLE_${PACKAGE_NAME}: Enable status of PACKAGE_NAME (local variable) # ToDo: Fill in others as well! # macro(tribits_adjust_and_print_package_dependencies) - tribits_config_code_start_timer(ADJUST_PACKAGE_DEPS_TIME_START_SECONDS) + tribits_print_enables_before_adjust_package_enables() + tribits_adjust_package_enables() + tribits_print_enables_after_adjust_package_enables() + tribits_handle_project_extra_link_flags_as_a_tpl() + tribits_set_up_enabled_only_dependencies() + tribits_config_code_stop_timer(ADJUST_PACKAGE_DEPS_TIME_START_SECONDS + "\nTotal time to adjust package and TPL enables") +endmacro() - tribits_print_enabled_package_list( - "\nExplicitly enabled packages on input (by user)" ON FALSE) - tribits_print_enabled_se_package_list( - "\nExplicitly enabled SE packages on input (by user)" ON FALSE) - tribits_print_enabled_package_list( - "\nExplicitly disabled packages on input (by user or by default)" OFF FALSE) - tribits_print_enabled_se_package_list( - "\nExplicitly disabled SE packages on input (by user or by default)" OFF FALSE) - tribits_print_enabled_tpl_list( - "\nExplicitly enabled TPLs on input (by user)" ON FALSE) - tribits_print_enabled_tpl_list( - "\nExplicitly disabled TPLs on input (by user or by default)" OFF FALSE) - tribits_adjust_package_enables() +# Tack on ${PROJECT_NAME}_EXTRA_LINK_LIBS as a TPL that every downstream +# external and internal package depends on +# +macro(tribits_handle_project_extra_link_flags_as_a_tpl) + + if (${PROJECT_NAME}_EXTRA_LINK_FLAGS) - tribits_print_prefix_string_and_list( - "\nFinal set of enabled packages" "${${PROJECT_NAME}_ENABLED_PACKAGES}") - tribits_print_prefix_string_and_list( - "\nFinal set of enabled SE packages" "${${PROJECT_NAME}_ENABLED_SE_PACKAGES}") - tribits_print_enabled_package_list( - "\nFinal set of non-enabled packages" OFF TRUE) - tribits_print_enabled_se_package_list( - "\nFinal set of non-enabled SE packages" OFF TRUE) - tribits_print_enabled_tpl_list( - "\nFinal set of enabled TPLs" ON FALSE) - tribits_print_enabled_tpl_list( - "\nFinal set of non-enabled TPLs" OFF TRUE) + set(lastLibTplName ${PROJECT_NAME}TribitsLastLib) - tribits_set_up_enabled_only_dependencies() + # Define the TPL ${PROJECT_NAME}TribitsLastLib and its find module + set(${lastLibTplName}_FINDMOD + "${${PROJECT_NAME}_TRIBITS_DIR}/common_tpls/FindTPLProjectLastLib.cmake") - tribits_config_code_stop_timer(ADJUST_PACKAGE_DEPS_TIME_START_SECONDS - "\nTotal time to adjust package and TPL enables") + # Tack on ${PROJECT_NAME}TribitsLastLib as a dependency to all enabled + # external packages/TPLs + foreach(TPL_NAME ${${PROJECT_NAME}_TPLS}) + list(APPEND ${TPL_NAME}_LIB_ALL_DEPENDENCIES ${lastLibTplName}) + if (TPL_ENABLE_${TPL_NAME}) + list(APPEND ${TPL_NAME}_LIB_ENABLED_DEPENDENCIES ${lastLibTplName}) + endif() + endforeach() + + # Prepend ${PROJECT_NAME}TribitsLastLib to the list of external packages/TPLs + list(PREPEND ${PROJECT_NAME}_TPLS ${lastLibTplName}) + set(TPL_ENABLE_${lastLibTplName} ON) + set(${lastLibTplName}_PACKAGE_BUILD_STATUS EXTERNAL) + + # Tack on ${PROJECT_NAME}TribitsLastLib as a dependency to all enabled + # internal packages + foreach(PACKAGE_NAME ${${PROJECT_NAME}_PACKAGES}) + list(APPEND ${PACKAGE_NAME}_LIB_ALL_DEPENDENCIES ${lastLibTplName}) + if (${PROJECT_NAME}_ENABLE_${PACKAGE_NAME}) + list(APPEND ${PACKAGE_NAME}_LIB_ENABLED_DEPENDENCIES ${lastLibTplName}) + endif() + endforeach() + + endif() endmacro() @@ -1852,21 +1713,6 @@ macro(tribits_setup_env) # enable/disable the graphical dependency graphs in doxygen Doxyfiles. include(FindDoxygen) - # Set the hack library to get link options on - - if (${PROJECT_NAME}_EXTRA_LINK_FLAGS) - if (TRIBITS_SETUP_ENV_DEBUG) - message(STATUS "Creating dummy last_lib for appending the link flags: " - "${${PROJECT_NAME}_EXTRA_LINK_FLAGS}") - endif() - if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/last_lib_dummy.c) - file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/last_lib_dummy.c - "typedef int last_lib_dummy_t;\n") - endif() - add_library(last_lib STATIC ${CMAKE_CURRENT_BINARY_DIR}/last_lib_dummy.c) - target_link_libraries(last_lib ${${PROJECT_NAME}_EXTRA_LINK_FLAGS}) - endif() - # You have to override the configuration types for MSVS after the compiler # checks! set(CMAKE_CONFIGURATION_TYPES ${CMAKE_CONFIGURATION_TYPE} @@ -2200,10 +2046,8 @@ macro(tribits_configure_enabled_packages) # A) Global variable initialization # - global_null_set(${PROJECT_NAME}_INCLUDE_DIRS) - global_null_set(${PROJECT_NAME}_LIBRARY_DIRS) - global_null_set(${PROJECT_NAME}_LIBRARIES) - global_null_set(${PROJECT_NAME}_ETI_PACKAGES) + global_null_set(${PROJECT_NAME}_LIBRARIES "") + global_null_set(${PROJECT_NAME}_ETI_PACKAGES "") # # B) Define the source and binary directories for all of the packages that @@ -2305,8 +2149,6 @@ macro(tribits_configure_enabled_packages) endif() list(APPEND ENABLED_PACKAGE_LIBS_TARGETS ${TRIBITS_PACKAGE}_libs) - list(APPEND ${PROJECT_NAME}_INCLUDE_DIRS ${${TRIBITS_PACKAGE}_INCLUDE_DIRS}) - list(APPEND ${PROJECT_NAME}_LIBRARY_DIRS ${${TRIBITS_PACKAGE}_LIBRARY_DIRS}) list(APPEND ${PROJECT_NAME}_LIBRARIES ${${TRIBITS_PACKAGE}_LIBRARIES}) tribits_package_config_code_stop_timer(PROCESS_THIS_PACKAGE_TIME_START_SECONDS @@ -2385,18 +2227,12 @@ macro(tribits_configure_enabled_packages) if (NOT ${PROJECT_NAME}_TRACE_DEPENDENCY_HANDLING_ONLY) - remove_global_duplicates(${PROJECT_NAME}_INCLUDE_DIRS) - remove_global_duplicates(${PROJECT_NAME}_LIBRARY_DIRS) remove_global_duplicates(${PROJECT_NAME}_LIBRARIES) # Add global 'libs' target if(ENABLED_PACKAGE_LIBS_TARGETS) list(REVERSE ENABLED_PACKAGE_LIBS_TARGETS) # Make it so when no packages are enabled it is not a cmake error - if (${PROJECT_NAME}_EXTRA_LINK_FLAGS) - append_set(ENABLED_PACKAGE_LIBS_TARGETS last_lib) - endif() - #print_var(ENABLED_PACKAGE_LIBS_TARGETS) if (NOT TARGET ${PROJECT_NAME}_libs) add_custom_target(${PROJECT_NAME}_libs) add_dependencies(${PROJECT_NAME}_libs ${ENABLED_PACKAGE_LIBS_TARGETS}) diff --git a/cmake/tribits/core/package_arch/TribitsIncludeDirectories.cmake b/cmake/tribits/core/package_arch/TribitsIncludeDirectories.cmake index c1de80edcc9b..3f90fc873d69 100644 --- a/cmake/tribits/core/package_arch/TribitsIncludeDirectories.cmake +++ b/cmake/tribits/core/package_arch/TribitsIncludeDirectories.cmake @@ -40,7 +40,6 @@ include(CMakeParseArguments) -# # @MACRO: tribits_include_directories() # # This function is to override the standard behavior of the built-in CMake diff --git a/cmake/tribits/core/package_arch/TribitsInstallHeaders.cmake b/cmake/tribits/core/package_arch/TribitsInstallHeaders.cmake index 8f875dfd95d6..c1bf53039796 100644 --- a/cmake/tribits/core/package_arch/TribitsInstallHeaders.cmake +++ b/cmake/tribits/core/package_arch/TribitsInstallHeaders.cmake @@ -41,7 +41,6 @@ include(CMakeParseArguments) -# # @FUNCTION: tribits_install_headers() # # Function used to (optionally) install header files using ``install()`` diff --git a/cmake/tribits/core/package_arch/TribitsLibIsTestOnly.cmake b/cmake/tribits/core/package_arch/TribitsLibIsTestOnly.cmake new file mode 100644 index 000000000000..1120b27045fd --- /dev/null +++ b/cmake/tribits/core/package_arch/TribitsLibIsTestOnly.cmake @@ -0,0 +1,77 @@ +# @HEADER +# ************************************************************************ +# +# TriBITS: Tribal Build, Integrate, and Test System +# Copyright 2013 Sandia Corporation +# +# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +# the U.S. Government retains certain rights in this software. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Corporation nor the names of the +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# ************************************************************************ +# @HEADER + +include_guard() + + +# @FUNCTION: tribits_set_lib_is_testonly() +# +# See if a library is a TESTONLY library +# +# Usage:: +# +# tribits_set_lib_is_testonly() +# +# This sets the ``TRIBITS_TESTONLY_LIB`` on the library target ````. +# +function(tribits_set_lib_is_testonly libName) + set_target_properties(${libName} PROPERTIES TRIBITS_TESTONLY_LIB TRUE) +endfunction() + + +# @FUNCTION: tribits_lib_is_testonly() +# +# See if a library is a TESTONLY library +# +# Usage:: +# +# tribits_lib_is_testonly( ) +# +# This will only return ``TRUE`` in `` `` if ```` +# is a target and the target property ``TRIBITS_TESTONLY_LIB`` is set to +# ``TRUE``. +# +function(tribits_lib_is_testonly libName libIsTestOnlyOut) + if (TARGET ${libName}) + get_target_property(libIsTestOnly ${libName} TRIBITS_TESTONLY_LIB) + else() + set(libIsTestOnly FALSE) + endif() + set(${libIsTestOnlyOut} ${libIsTestOnly} PARENT_SCOPE) +endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsLibraryMacros.cmake b/cmake/tribits/core/package_arch/TribitsLibraryMacros.cmake index 360c879b0b57..27fdfc952501 100644 --- a/cmake/tribits/core/package_arch/TribitsLibraryMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsLibraryMacros.cmake @@ -38,1003 +38,5 @@ # @HEADER include(TribitsCreateClientTemplateHeaders) -include(CMakeParseArguments) -include(GlobalSet) -include(AppendSet) -include(AppendGlob) -include(AppendGlobalSet) -include(AppendStringVar) -include(PrependGlobalSet) -include(RemoveGlobalDuplicates) -include(TribitsGeneralMacros) -include(TribitsReportInvalidTribitsUsage) -include(SetAndIncDirs) - -### -### WARNING: See "NOTES TO DEVELOPERS" at the bottom of the file -### TribitsPackageMacros.cmake! -### - - -# -# Macro that configures the package's main config.h file -# -function(tribits_add_config_define DEFINE) - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- " "Package ${PARENT_PACKAGE_NAME}: adding compiler" - " define to config file: ${DEFINE}") - endif() - global_set(${PARENT_PACKAGE_NAME}_CONFIG_DEFINES - "${${PARENT_PACKAGE_NAME}_CONFIG_DEFINES}\n#define ${DEFINE}") - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- ${${PARENT_PACKAGE_NAME}_CONFIG_DEFINES}") - endif() -endfunction() - - -# -# @FUNCTION: tribits_configure_file() -# -# Macro that configures the package's main configured header file (typically -# called ``${PACKAGE_NAME}_config.h`` but any name can be used). -# -# Usage:: -# -# tribits_configure_file() -# -# This function requires the file:: -# -# ${PACKAGE_SOURCE_DIR}/cmake/.in -# -# exists and it creates the file:: -# -# ${CMAKE_CURRENT_BINARY_DIR}/ -# -# by calling the built-in ``configure_file()`` command:: -# -# configure_file( -# ${PACKAGE_SOURCE_DIR}/cmake/.in -# ${CMAKE_CURRENT_BINARY_DIR}/ -# ) -# -# which does basic substitution of CMake variables (see documentation for -# built-in CMake `configure_file()`_ command for rules on how it performs -# substitutions). This command is typically used to configure the package's -# main `/cmake/_config.h.in`_ file. -# -# In addition to just calling ``configure_file()``, this function also aids in -# creating configured header files adding macros for deprecating code as -# described below. -# -# **Deprecated Code Macros** -# -# If ``${PARENT_PACKAGE_NAME}_SHOW_DEPRECATED_WARNINGS`` is ``TRUE`` (see -# `tribits_add_show_deprecated_warnings_option()`_), then the local CMake -# variable ``${PARENT_PACKAGE_NAME_UC}_DEPRECATED_DECLARATIONS`` is set which -# adds a define ``_DEPRECATED`` (where -# ```` is the package name in all upper-case letters) -# which adds a compiler-specific deprecated warning for an entity. To take -# advantage of this, just add the line:: -# -# @_DEPRECATED_DECLARATIONS@ -# -# to the ``.in`` file and it will be expanded at configure -# time. -# -# Then C/C++ code can use this macro to deprecate functions, variables, -# classes, etc., for example, using:: -# -# _DEPRECATED class SomeDepreatedClass { ... }. -# -# If the particular compiler does not support deprecated warnings, then this -# macro is defined to be empty. See `Regulated Backward Compatibility and -# Deprecated Code`_ for more details. -# -function(tribits_configure_file PACKAGE_NAME_CONFIG_FILE) - - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("\nPACKAGE_CONFIGURE_FILE: ${PACKAGE_NAME_CONFIG_FILE}") - endif() - - # Set up the deprecated attribute if showing deprecated warnings - if (${PARENT_PACKAGE_NAME}_SHOW_DEPRECATED_WARNINGS) - multiline_set(${PARENT_PACKAGE_NAME_UC}_DEPRECATED_DECLARATIONS - "#ifndef ${PARENT_PACKAGE_NAME_UC}_DEPRECATED\n" - "# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))\n" - "# define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED __attribute__((__deprecated__))\n" - "# else\n" - "# define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED\n" - "# endif\n" - "#endif\n" - "\n" - "#ifndef ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_MSG\n" - "# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))\n" - "# define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_MSG(MSG) __attribute__((__deprecated__ (#MSG) ))\n" - "# elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))\n" - "# define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_MSG(MSG) __attribute__((__deprecated__))\n" - "# else\n" - "# define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_MSG(MSG)\n" - "# endif\n" - "#endif\n" - ) - else() - multiline_set(${PARENT_PACKAGE_NAME_UC}_DEPRECATED_DECLARATIONS - "#define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED\n" - "#define ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_MSG(MSG)\n" - ) - endif() - - if (${PARENT_PACKAGE_NAME}_HIDE_DEPRECATED_CODE) - string(APPEND ${PARENT_PACKAGE_NAME_UC}_DEPRECATED_DECLARATIONS - "\n#define ${PARENT_PACKAGE_NAME_UC}_HIDE_DEPRECATED_CODE") - endif() - - # Set up the macro to create the define for time monitor - set(TIME_MONITOR_DEFINE_NAME ${PARENT_PACKAGE_NAME_UC}_TEUCHOS_TIME_MONITOR) - set(FUNC_TIME_MONITOR_MACRO_NAME ${PARENT_PACKAGE_NAME_UC}_FUNC_TIME_MONITOR) - set(FUNC_TIME_MONITOR_DIFF_MACRO_NAME ${PARENT_PACKAGE_NAME_UC}_FUNC_TIME_MONITOR_DIFF) - if (${PARENT_PACKAGE_NAME}_ENABLE_TEUCHOS_TIME_MONITOR) - multiline_set(${PARENT_PACKAGE_NAME_UC}_TEUCHOS_TIME_MONITOR_DECLARATIONS - "#ifndef ${FUNC_TIME_MONITOR_MACRO_NAME}\n" - "# define ${TIME_MONITOR_DEFINE_NAME}\n" - "# define ${FUNC_TIME_MONITOR_MACRO_NAME}(FUNCNAME) \\\n" - " TEUCHOS_FUNC_TIME_MONITOR_DIFF(FUNCNAME, ${PARENT_PACKAGE_NAME_UC})\n" - "# define ${FUNC_TIME_MONITOR_DIFF_MACRO_NAME}(FUNCNAME, DIFF) \\\n" - " TEUCHOS_FUNC_TIME_MONITOR_DIFF(FUNCNAME, DIFF)\n" - "#endif\n" - ) - else() - multiline_set(${PARENT_PACKAGE_NAME_UC}_TEUCHOS_TIME_MONITOR_DECLARATIONS - "#define ${FUNC_TIME_MONITOR_MACRO_NAME}(FUNCNAME)\n" - "#define ${FUNC_TIME_MONITOR_DIFF_MACRO_NAME}(FUNCNAME, DIFF)\n" - ) - endif() - - # Configure the file - configure_file( - ${PACKAGE_SOURCE_DIR}/cmake/${PACKAGE_NAME_CONFIG_FILE}.in - ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME_CONFIG_FILE} - ) - -endfunction() - - -# -# @FUNCTION: tribits_add_library() -# -# Function used to add a CMake library and target using ``add_library()`` and -# also the ALIAS target ``${PACKAGE_NAME}::`` (where ```` is -# the full CMake target name as returned from ``${}``). -# -# Usage:: -# -# tribits_add_library( -# -# [HEADERS

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

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

...)``, but only if ``TESTONLY`` and -# ``NO_INSTALL_LIB_OR_HEADERS`` are not passed in as well. Also, the install -# target for the headers will not get added if -# `${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS`_ is ``FASLE``. If this -# install target is added, then the headers get installed into the flat -# directory ``${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}/`` (default is -# ``${CMAKE_INSTALL_PREFIX}/include/``, see `Setting the install prefix`_). -# If ``HEADERS_INSTALL_SUBDIR`` is set, then the headers will be installed -# under ``${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}//``. -# -# Note that an install target will *not* get created for the headers listed in -# ``NOINSTALLHEADERS``. -# -# .. _Additional Library and Source File Properties (tribits_add_library()): -# -# **Additional Library and Source File Properties (tribits_add_library())** -# -# Once ``add_library( ... ...)`` is called, one -# can set and change properties on the ```` library target -# using the built-in CMake command ``set_target_properties()`` as well as set -# and change properties on any of the source files listed in ``SOURCES`` using -# the built-in CMake command ``set_source_file_properties()`` just like in any -# CMake project. For example:: -# -# tribits_add_library( somelib ... -# ADDED_LIB_TARGET_NAME_OUT somelib_TARGET_NAME ) -# -# set_target_properties( ${somelib_TARGET_NAME} -# PROPERTIES LINKER_LANGUAGE CXX ) -# -# .. _Miscellaneous Notes (tribits_add_library()): -# -# **Miscellaneous Notes (tribits_add_library())** -# -# When the file ``Version.cmake`` exists and the CMake variables -# ``${PROJECT_NAME}_VERSION`` and ``${PROJECT_NAME}_MAJOR_VERSION`` are -# defined, then produced shared libraries will be given the standard SOVERSION -# symlinks (see `/Version.cmake`_). -# -# **WARNING:** Do **NOT** use the built-in CMake command ``add_definitions()`` -# to add defines ``-D`` to the compile command line that will -# affect any of the header files in the package! These CMake-added defines -# are only set locally in this directory and child directories. These defines -# will **NOT** be set when code in peer directories (e.g. a downstream TriBITS -# packages) compiles that may include these header files. To add defines that -# affect header files, please use a configured header file (see -# `tribits_configure_file()`_). -# -function(tribits_add_library LIBRARY_NAME_IN) - - # - # Confirm that package and subpackage macros/functions have been called in the correct order - # - - if (CURRENTLY_PROCESSING_SUBPACKAGE) - - # This is a subpackage being processed - - if(NOT ${SUBPACKAGE_FULLNAME}_TRIBITS_SUBPACKAGE_CALLED) - tribits_report_invalid_tribits_usage( - "Must call tribits_subpackage() before tribits_add_library()" - " in ${CURRENT_SUBPACKAGE_CMAKELIST_FILE}") - endif() - - if(${SUBPACKAGE_FULLNAME}_TRIBITS_SUBPACKAGE_POSTPROCESS_CALLED) - tribits_report_invalid_tribits_usage( - "Must call tribits_add_library() before " - " tribits_subpackage_postprocess() in ${CURRENT_SUBPACKAGE_CMAKELIST_FILE}") - endif() - - else() - - # This is a package being processed - - if(NOT ${PACKAGE_NAME}_TRIBITS_PACKAGE_DECL_CALLED) - tribits_report_invalid_tribits_usage( - "Must call tribits_package() or tribits_package_decl() before" - " tribits_add_library() in ${TRIBITS_PACKAGE_CMAKELIST_FILE}") - endif() - - if(${PACKAGE_NAME}_TRIBITS_PACKAGE_POSTPROCESS_CALLED) - tribits_report_invalid_tribits_usage( - "Must call tribits_add_library() before " - " tribits_package_postprocess() in ${TRIBITS_PACKAGE_CMAKELIST_FILE}") - endif() - - endif() - - set(LIBRARY_NAME_PREFIX "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}") - set(LIBRARY_NAME ${LIBRARY_NAME_PREFIX}${LIBRARY_NAME_IN}) - - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("\nTRIBITS_ADD_LIBRARY: ${LIBRARY_NAME}") - if(${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING) - message("\n${PACKAGE_NAME}_LIBRARIES In installation testing mode," - " libraries will be found instead of created.") - endif() - endif() - - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - print_var(${PACKAGE_NAME}_INCLUDE_DIRS) - print_var(${PACKAGE_NAME}_LIBRARY_DIRS) - print_var(${PACKAGE_NAME}_LIBRARIES) - endif() - - cmake_parse_arguments( - #prefix - PARSE - #Options - "STATIC;SHARED;TESTONLY;NO_INSTALL_LIB_OR_HEADERS;CUDALIBRARY" - #one_value_keywords - "" - #mulit_value_keywords - "HEADERS;HEADERS_INSTALL_SUBDIR;NOINSTALLHEADERS;SOURCES;DEPLIBS;IMPORTEDLIBS;DEFINES;ADDED_LIB_TARGET_NAME_OUT" - ${ARGN} - ) - - tribits_check_for_unparsed_arguments() - - # ToDo: Assert that HEADERS_INSTALL_SUBDIR has 0 or 1 entries! - # ToDo: Assert that ADDED_LIB_TARGET_NAME_OUT as 0 or 1 entries! - - if(PARSE_HEADERS) - list(REMOVE_DUPLICATES PARSE_HEADERS) - endif() - if(PARSE_SOURCES) - list(REMOVE_DUPLICATES PARSE_SOURCES) - endif() - - if(PARSE_ADDED_LIB_TARGET_NAME_OUT) - set(${PARSE_ADDED_LIB_TARGET_NAME_OUT} PARENT_SCOPE) - endif() - - # ToDo: Deprecate and remove the usage of DEFINES! People should be putting - # defines into configured header files, not adding -D to the - # compile lines! - - if (NOT ${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING OR PARSE_TESTONLY) - - # Add the link directory for this library. - - set_property(DIRECTORY APPEND PROPERTY PACKAGE_LIBRARY_DIRS - ${CMAKE_CURRENT_BINARY_DIR}) - - # NOTE: Above, this link path not really used here for anything. - # Instead it is just added to the other set link library directories - # that are already set. These link directories are then extracted - # and stored into stored in ${PACKAGE_NAME}_LIBRARY_DIRS. - - # Add whatever include directories have been defined so far - - #include_directories(AFTER ${${PACKAGE_NAME}_INCLUDE_DIRS}) - # ToDo: #299: Remove the above once final cleanup is performed for #299. - - # Add whatever link directories have been added so far - - set_property(DIRECTORY APPEND PROPERTY PACKAGE_LIBRARY_DIRS - ${${PACKAGE_NAME}_LIBRARY_DIRS}) - - # Local variable to hold all of the libraries that will be directly linked - # to this library. - set(LINK_LIBS) - - # Add dependent libraries passed directly in - - if (PARSE_DEPLIBS AND ${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- " "DEPLIBS = ${PARSE_DEPLIBS}") - endif() - if (PARSE_IMPORTEDLIBS AND ${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- " "IMPORTEDLIBS = ${PARSE_IMPORTEDLIBS}") - endif() - - # - # Add the DEPLIBS to the LINK_LIBS, assert correct usage of DEPLIBS, and - # see if we need to link in the upstream SE package and TPL libs. - # - # We only want to link to the upstream dependent SE package and TPL - # libraries if needed. We only need to link to these upstream dependent - # libraries when this is the first library being created for this SE - # package or if this library does not depend on other libraries created - # for this package. Otherwise, we don't need to add the include - # directories or link libraries because a dependent lib specified in - # PARSE_DEPLIBS already has everything that we need. - # - # We also need to make special considerations for test libraries since - # things need to be handled a little bit differently (but not much). In the - # case of test libraries, we need to also pull the test-only dependencies. - # In this case, we will always assume that we will add in the test - # libraries. - # - # ToDo: Turn the below deprecated WARNING messages to FATAL_ERROR once we - # give enough time for people to clean up their codes. - # - - set(ADD_DEP_PACKAGE_AND_TPL_LIBS TRUE) - - set(PREFIXED_DEPLIBS) - - foreach(LIB ${PARSE_DEPLIBS}) - - set(PREFIXED_LIB "${LIBRARY_NAME_PREFIX}${LIB}") - - # LIB_IN_SE_PKG? - list(FIND ${PACKAGE_NAME}_LIBRARIES "${PACKAGE_NAME}::${PREFIXED_LIB}" FOUND_IDX) - if (FOUND_IDX GREATER -1) - set(LIB_IN_SE_PKG TRUE) - else() - set(LIB_IN_SE_PKG FALSE) - endif() - - # PREFIXED_LIB_IS_TESTONLY? - if (${PREFIXED_LIB}_INCLUDE_DIRS) - set(LIB_TESTONLY TRUE) - else() - set(LIB_TESTONLY FALSE) - endif() - - # Check for valid usage (sorted by most common to least common) - if (LIB_IN_SE_PKG AND NOT LIB_TESTONLY) #PARSE_TESTONLY=TRUE/FASLE - # The library being created here is a library dependent on a regular - # (non-TESTONLY) lib in this SE package. This is valid usage of - # DEPLIBS. There is no need to link this new lib to the SE package's - # upstream dependent SE package and TPL libraries because thse are - # already linked into the lib ${LIB}. - set(ADD_DEP_PACKAGE_AND_TPL_LIBS FALSE) - elseif (PARSE_TESTONLY AND LIB_IN_SE_PKG AND NOT LIB_TESTONLY) - # The library being created here is TESTONLY library and is - # dependent on a regular (non-TESTONLY) lib. This is valid usage of - # DEPLIBS. In the case of test-only libraries, we always link in - # the upstream libs. - elseif (PARSE_TESTONLY AND LIB_TESTONLY) # LIB_IN_SE_PKG=TRUE/FASLE - # The library being created here is TESTONLY library and is dependent - # on another TESTONLY library. This is valid usage of DEPLIBS. In - # this case we just hope that this SE package correctly specified a - # TEST dependency on the upstream SE package that owns this upstream - # TESTONLY library. - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- " - "Adding include directories for TESTONLY ${PREFIXED_LIB}_INCLUDE_DIRS ...") - endif() - include_directories(${${PREFIXED_LIB}_INCLUDE_DIRS}) - elseif (NOT PARSE_TESTONLY AND LIB_TESTONLY) # LIB_IN_SE_PKG=TRUE/FASLE - message(WARNING "WARNING: '${LIB}' in DEPLIBS is a TESTONLY lib" - " and it is illegal to link to this non-TESTONLY library '${LIBRARY_NAME}'." - " Such usage is deprecated (and this warning will soon become an error)!" - " If this is a regular library in this SE package or in an dependent upstream SE" - " package then TriBITS will link automatically to it. If you remove this and it" - " does not link, then you need to add a new SE package dependency to" - " this SE package's dependencies file" - " ${${PACKAGE_NAME}_SOURCE_DIR}/cmake/Dependencies.cmake") - # ToDo: Turn the above to FATAL_ERROR after dropping deprecated code - elseif (NOT LIB_IN_SE_PKG AND TARGET ${PREFIXED_LIB} ) # PARSE_TESTONLY=TRUE/FALSE - message(WARNING "WARNING: '${LIB}' in DEPLIBS is not" - " a lib in this SE package but is a library defined in the current" - " cmake project! Such usage is deprecated (and" - " will result in a configure error soon). If this is a library in" - " a dependent upstream SE package, then simply remove it from this list." - " TriBITS automatically links in libraries in upstream SE packages." - " If you remove '${LIB}' from DEPLIBS and your code does" - " not link, then you need to add a new SE package dependency to" - " this SE package's dependencies file" - " ${${PACKAGE_NAME}_SOURCE_DIR}/cmake/Dependencies.cmake") - elseif (NOT LIB_IN_SE_PKG AND NOT TARGET ${PREFIXED_LIB} ) - message(WARNING "WARNING: '${LIB}' in DEPLIBS is not" - " a lib defined in the current cmake project! Such usage is deprecated (and" - " will result in a configure error soon). If this is an external" - " lib you are trying to link in, it should likely be handled as a TriBITS" - " TPL. Otherwise, it should be passed in through IMPORTEDLIBS. However," - " the only case we have found where IMPORTEDLIBS had to be used instead of" - " through a proper TriBITS TPL is the C math library 'm'.") - else() - message(WARNING "WARNING: The case PARSE_TESTONLY=${PARSE_TESTONLY}," - " LIB_IN_SE_PKG=${LIB_IN_SE_PKG}, LIB_TESTONLY=${LIB_TESTONLY}, has" - " not yet been handled!") - endif() - - list(APPEND PREFIXED_DEPLIBS "${LIBRARY_NAME_PREFIX}${LIB}") - - endforeach() - - append_set(LINK_LIBS ${PREFIXED_DEPLIBS}) - - # - # Check IMPORTEDLIBS - # - - foreach(IMPORTEDLIB ${PARSE_IMPORTEDLIBS}) - set(PREFIXED_LIB "${LIBRARY_NAME_PREFIX}${IMPORTEDLIB}") - list(FIND ${PACKAGE_NAME}_LIBRARIES "${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_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" - " SE package automatically. Please remove it from IMPORTEDLIBS!") - elseif (TARGET ${PREFIXED_LIB}) - message(WARNING "WARNING: Lib '${IMPORTEDLIB}' being passed through" - " IMPORTEDLIBS is *not* an external library but instead is a library" - " defined in this CMake project!" - " TriBITS takes care of linking against libraries in dependent upstream" - " SE packages. If you want to link to a library in an upstream SE" - " package then add the SE package name to the appropriate category" - " in this SE package's dependencies file: " - " ${${PACKAGE_NAME}_SOURCE_DIR}/cmake/Dependencies.cmake") - endif() - # ToDo: Assert that this is not a test-only lib - list(APPEND LINK_LIBS ${IMPORTEDLIB}) - endforeach() - - # - # Link in the upstream TEST SE package and TPL libs - # - # We link these before those in the LIB SE package and TPL libs because - # the TEST dependencies tend to be higher in the dependency tree. It - # should not really matter but it looks better on the link line. - # - - if (PARSE_TESTONLY) - - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- " "Pulling in header and libraries dependencies" - " for TEST dependencies ...") - endif() - - tribits_sort_and_append_package_include_and_link_dirs_and_libs( - ${PACKAGE_NAME} TEST LINK_LIBS) - - tribits_sort_and_append_tpl_include_and_link_dirs_and_libs( - ${PACKAGE_NAME} TEST LINK_LIBS) - - endif() - - # - # Add the dependent LIB SE package and TPL libs - # - - if (ADD_DEP_PACKAGE_AND_TPL_LIBS) - - # If there are no dependent libs passed in, then this library can not - # possibly depend on the package's other libraries so we must link to - # the dependent libraries in dependent libraries and TPLs. - - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- " "Pulling in header and libraries dependencies" - " for LIB dependencies ...") - endif() - - # - # Call include_directories() and link_directories(...) for all upstream - # dependent Packages and TPLs and accumulate the libraries to link against. - # - # NOTE: Adding these directories serves two purposes. First, so that the includes - # get added the the sources that get built for this library. Second, so - # that list full list of include directories can be extracted as a - # property and set on ${PACKAGE_NAME}_INCLUDE_DIRS - # - - tribits_sort_and_append_package_include_and_link_dirs_and_libs( - ${PACKAGE_NAME} LIB LINK_LIBS) - - tribits_sort_and_append_tpl_include_and_link_dirs_and_libs( - ${PACKAGE_NAME} LIB LINK_LIBS) - - endif() - - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - print_var(LINK_LIBS) - endif() - - # Add the library and all the dependencies - - if (PARSE_DEFINES) - add_definitions(${PARSE_DEFINES}) - endif() - - if (PARSE_STATIC) - set(STATIC_KEYWORD "STATIC") - else() - set(STATIC_KEYWORD) - endif() - - if (PARSE_SHARED) - set(SHARED_KEYWORD "SHARED") - else() - set(SHARED_KEYWORD) - endif() - - if (NOT PARSE_CUDALIBRARY) - add_library( - ${LIBRARY_NAME} - ${STATIC_KEYWORD} - ${SHARED_KEYWORD} - ${PARSE_HEADERS} - ${PARSE_NOINSTALLHEADERS} - ${PARSE_SOURCES} - ) - else() - cuda_add_library( - ${LIBRARY_NAME} - ${PARSE_HEADERS} - ${PARSE_NOINSTALLHEADERS} - ${PARSE_SOURCES} - ) - endif() - - if(PARSE_ADDED_LIB_TARGET_NAME_OUT) - set(${PARSE_ADDED_LIB_TARGET_NAME_OUT} ${LIBRARY_NAME} PARENT_SCOPE) - endif() - - if (PARSE_TESTONLY) - set_target_properties(${LIBRARY_NAME} PROPERTIES - TRIBITS_TESTONLY_LIB TRUE) - endif() - - set_property( - TARGET ${LIBRARY_NAME} - APPEND PROPERTY - LABELS ${PACKAGE_NAME}Libs ${PARENT_PACKAGE_NAME}Libs - ) - - if (NOT "${${PROJECT_NAME}_VERSION}" STREQUAL "" AND - NOT "${${PROJECT_NAME}_MAJOR_VERSION}" STREQUAL "" - ) - set_target_properties( - ${LIBRARY_NAME} - PROPERTIES - VERSION ${${PROJECT_NAME}_VERSION} - SOVERSION ${${PROJECT_NAME}_MAJOR_VERSION} - ) - endif() - - prepend_global_set(${PARENT_PACKAGE_NAME}_LIB_TARGETS ${LIBRARY_NAME}) - prepend_global_set(${PARENT_PACKAGE_NAME}_ALL_TARGETS ${LIBRARY_NAME}) - - if (${PROJECT_NAME}_DUMP_LINK_LIBS) - message("-- ${LIBRARY_NAME_IN}:LINK_LIBS='${LINK_LIBS}'") - endif() - - target_link_libraries(${LIBRARY_NAME} PUBLIC ${LINK_LIBS}) - - if (${PROJECT_NAME}_CXX_STANDARD_FEATURE) - target_compile_features(${LIBRARY_NAME} PUBLIC "${${PROJECT_NAME}_CXX_STANDARD_FEATURE}") - ENDIF () - - # Add to the install target - - set(INSTALL_LIB ON) - set(INSTALL_HEADERS ON) - set(APPEND_LIB_AND_HEADERS_TO_PACKAGE ON) - - if (PARSE_TESTONLY) - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- " "Skipping installation hooks for this library" - " because 'TESTONLY' was passed in ...") - endif() - set(INSTALL_LIB OFF) - set(INSTALL_HEADERS OFF) - set(APPEND_LIB_AND_HEADERS_TO_PACKAGE OFF) - elseif (PARSE_NO_INSTALL_LIB_OR_HEADERS) - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- " "Skipping installation hooks for this library" - " because 'NO_INSTALL_LIB_OR_HEADERS' was passed in ...") - endif() - set(INSTALL_LIB OFF) - set(INSTALL_HEADERS OFF) - elseif (NOT ${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS AND NOT BUILD_SHARED_LIBS) - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- " "Skipping installation of headers and libraries" - " because ${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS=FALSE and BUILD_SHARED_LIBS=FALSE ...") - endif() - set(INSTALL_LIB OFF) - set(INSTALL_HEADERS OFF) - elseif (NOT ${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS AND BUILD_SHARED_LIBS) - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- " "Skipping installation of headers but installing libraries" - " because ${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS=FALSE and BUILD_SHARED_LIBS=TRUE ...") - endif() - set(INSTALL_HEADERS OFF) - endif() - - if (INSTALL_LIB OR INSTALL_HEADERS) - set_property(GLOBAL PROPERTY ${PROJECT_NAME}_HAS_INSTALL_TARGETS ON) - set_property(GLOBAL PROPERTY ${PACKAGE_NAME}_HAS_INSTALL_TARGETS ON) - endif() - - if (INSTALL_LIB) - install( - TARGETS ${LIBRARY_NAME} - EXPORT ${PACKAGE_NAME} - INCLUDES DESTINATION "${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}" - RUNTIME DESTINATION "${${PROJECT_NAME}_INSTALL_RUNTIME_DIR}" - LIBRARY DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}" - ARCHIVE DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}" - COMPONENT ${PACKAGE_NAME} - ) - endif() - - if (INSTALL_HEADERS) - tribits_install_headers( - HEADERS ${PARSE_HEADERS} - INSTALL_SUBDIR ${PARSE_HEADERS_INSTALL_SUBDIR} - COMPONENT ${PACKAGE_NAME} - ) - endif() - - # Append the new include dirs, library dirs, and libraries to this package's lists - - get_directory_property(INCLUDE_DIRS_CURRENT INCLUDE_DIRECTORIES) - get_directory_property(LIBRARY_DIRS_CURRENT PACKAGE_LIBRARY_DIRS) - - if (APPEND_LIB_AND_HEADERS_TO_PACKAGE) - - prepend_global_set(${PACKAGE_NAME}_INCLUDE_DIRS ${INCLUDE_DIRS_CURRENT}) - prepend_global_set(${PACKAGE_NAME}_LIBRARY_DIRS ${LIBRARY_DIRS_CURRENT}) - prepend_global_set(${PACKAGE_NAME}_LIBRARIES ${PACKAGE_NAME}::${LIBRARY_NAME}) - - remove_global_duplicates(${PACKAGE_NAME}_INCLUDE_DIRS) - remove_global_duplicates(${PACKAGE_NAME}_LIBRARY_DIRS) - remove_global_duplicates(${PACKAGE_NAME}_LIBRARIES) - - if (INSTALL_LIB) - global_set(${PACKAGE_NAME}_HAS_NATIVE_LIBRARIES_TO_INSTALL TRUE) - endif() - - else() - - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("-- " "Skipping augmentation of package's lists of include" - " directories and libraries! ...") - endif() - - list(REMOVE_DUPLICATES INCLUDE_DIRS_CURRENT) - global_set(${LIBRARY_NAME}_INCLUDE_DIRS ${INCLUDE_DIRS_CURRENT}) - - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - print_var(${LIBRARY_NAME}_INCLUDE_DIRS) - endif() - - endif() - - # 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}) - - # Optionally Set IMPORTED_NO_SYSTEM - if (${PROJECT_NAME}_IMPORTED_NO_SYSTEM) - set_target_properties(${LIBRARY_NAME} PROPERTIES IMPORTED_NO_SYSTEM TRUE) - endif() - - endif() #if not in installation testing mode - - # - # Adjust for installation testing - # - - if (${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING) - - list(FIND ${PROJECT_NAME}_INSTALLATION_PACKAGE_LIST ${PACKAGE_NAME} - ${PACKAGE_NAME}_WAS_INSTALLED) - if(${${PACKAGE_NAME}_WAS_INSTALLED} EQUAL -1) - message(FATAL_ERROR - "The package ${PACKAGE_NAME} was not installed with ${PROJECT_NAME}!" - " Please disable package ${PACKAGE_NAME} or install it.") - endif() - - include_directories(REQUIRED_DURING_INSTALLATION_TESTING BEFORE - ${${PACKAGE_NAME}_INSTALLATION_INCLUDE_DIRS} - ${${TRIBITS_PACKAGE}_INSTALLATION_TPL_INCLUDE_DIRS}) - set_property(DIRECTORY APPEND PROPERTY PACKAGE_LIBRARY_DIRS - ${${PACKAGE_NAME}_INSTALLATION_LIBRARY_DIRS}) - - get_directory_property(INCLUDE_DIRS_CURRENT INCLUDE_DIRECTORIES) - get_directory_property(LIBRARY_DIRS_CURRENT PACKAGE_LIBRARY_DIRS) - - global_set(${PACKAGE_NAME}_INCLUDE_DIRS ${INCLUDE_DIRS_CURRENT}) - global_set(${PACKAGE_NAME}_LIBRARY_DIRS ${LIBRARY_DIRS_CURRENT}) - global_set(${PACKAGE_NAME}_LIBRARIES ${${PACKAGE_NAME}_INSTALLATION_LIBRARIES}) - - endif() #installation testing mode - - # - # Print the updates to the linkage variables - # - - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - print_var(${PACKAGE_NAME}_INCLUDE_DIRS) - print_var(${PACKAGE_NAME}_LIBRARY_DIRS) - print_var(${PACKAGE_NAME}_LIBRARIES) - endif() - -endfunction() +include(TribitsConfigureFile) +include(TribitsAddLibrary) diff --git a/cmake/tribits/core/package_arch/TribitsListHelpers.cmake b/cmake/tribits/core/package_arch/TribitsListHelpers.cmake index f500bf863364..ea94d8cb1e91 100644 --- a/cmake/tribits/core/package_arch/TribitsListHelpers.cmake +++ b/cmake/tribits/core/package_arch/TribitsListHelpers.cmake @@ -81,7 +81,6 @@ macro(tribits_set_package_to_ex PACKAGE_NAME) endmacro() -# # @MACRO: tribits_disable_package_on_platforms() # # Disable a package automatically for a list of platforms. diff --git a/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake b/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake index 481a7a87be5d..cee06a2d8e58 100644 --- a/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake @@ -40,6 +40,7 @@ include(TribitsPackageSetupCompilerFlags) include(TribitsWriteClientExportFiles) include(TribitsGeneralMacros) +include(TribitsLibIsTestOnly) include(CMakeParseArguments) include(GlobalNullSet) @@ -60,11 +61,6 @@ include(TribitsCopyFilesToBinaryDir) include(TribitsReportInvalidTribitsUsage) -### -### WARNING: See "NOTES TO DEVELOPERS" at the bottom of file! -### - - # # Utility macros # @@ -77,9 +73,7 @@ include(TribitsReportInvalidTribitsUsage) # they are used. # macro(tribits_define_linkage_vars PACKAGE_NAME_IN) - global_null_set(${PACKAGE_NAME_IN}_INCLUDE_DIRS) - global_null_set(${PACKAGE_NAME_IN}_LIBRARY_DIRS) - global_null_set(${PACKAGE_NAME_IN}_LIBRARIES) + global_null_set(${PACKAGE_NAME_IN}_LIBRARIES "") global_set(${PACKAGE_NAME_IN}_HAS_NATIVE_LIBRARIES_TO_INSTALL FALSE) endmacro() @@ -474,10 +468,12 @@ endmacro() # # tribits_add_debug_option() # -# This option is given the default ``${${PROJECT_NAME}_ENABLE_DEBUG}`` and if -# true, will set the variable ``HAVE_${PACKAGE_NAME_UC}_DEBUG`` (to be used in -# the package's configured header file). This macro is typically called in -# the package's `/CMakeLists.txt`_ file. +# This option is given the default value ``${${PROJECT_NAME}_ENABLE_DEBUG}``, +# and if true, this macro will set the variable +# ``HAVE_${PACKAGE_NAME_UC}_DEBUG`` (to be used in the package's configured +# header file `/cmake/_config.h.in`_). This macro is +# typically called in the package's `/CMakeLists.txt`_ file (see +# the example ``SimpleCxx/CMakeLists.txt``). # macro(tribits_add_debug_option) tribits_add_option_and_define( @@ -620,9 +616,7 @@ function(tribits_package_finalize_dependency_vars) # A package with subpackages should get all of its dependency vars from # its enabled subpackages. - set(PARENT_PACKAGE_INCLUDE_DIRS) - set(PARENT_PACKAGE_LIBRARY_DIRS) - set(PARENT_PACKAGE_LIBRARIES) + set(PARENT_PACKAGE_LIBRARIES "") set(SUBPACKAGE_IDX 0) foreach(TRIBITS_SUBPACKAGE ${${PARENT_PACKAGE_NAME}_SUBPACKAGES}) @@ -631,10 +625,6 @@ function(tribits_package_finalize_dependency_vars) set(SUBPACKAGE_FULLNAME ${PARENT_PACKAGE_NAME}${TRIBITS_SUBPACKAGE}) if (${PROJECT_NAME}_ENABLE_${SUBPACKAGE_FULLNAME}) - prepend_set(PARENT_PACKAGE_INCLUDE_DIRS - ${${SUBPACKAGE_FULLNAME}_INCLUDE_DIRS}) - prepend_set(PARENT_PACKAGE_LIBRARY_DIRS - ${${SUBPACKAGE_FULLNAME}_LIBRARY_DIRS}) prepend_set(PARENT_PACKAGE_LIBRARIES ${${SUBPACKAGE_FULLNAME}_LIBRARIES}) endif() @@ -643,41 +633,10 @@ function(tribits_package_finalize_dependency_vars) endforeach() - if (PARENT_PACKAGE_INCLUDE_DIRS) - list(REMOVE_DUPLICATES PARENT_PACKAGE_INCLUDE_DIRS) - endif() - if (PARENT_PACKAGE_LIBRARY_DIRS) - list(REMOVE_DUPLICATES PARENT_PACKAGE_LIBRARY_DIRS) - endif() - # NOTE: Above, in the rare case that none of the subpackages contain any - # libraries or any include directories, we need to not call - # list(REMOVE_DUPLICATES ...). - # NOTE: There can't be any duplicate libraries in PARENT_PACKAGE_LIBRARIES # so no need to remove them. - - global_set(${PACKAGE_NAME}_INCLUDE_DIRS "${PARENT_PACKAGE_INCLUDE_DIRS}") - global_set(${PACKAGE_NAME}_LIBRARY_DIRS "${PARENT_PACKAGE_LIBRARY_DIRS}") global_set(${PACKAGE_NAME}_LIBRARIES "${PARENT_PACKAGE_LIBRARIES}") - elseif(NOT ${PACKAGE_NAME}_INCLUDE_DIRS) - - # No libraries have been defined for this package so we are going to set - # them based on this package's dependencies. - - tribits_sort_and_append_package_include_and_link_dirs_and_libs( - ${PACKAGE_NAME} LIB LINK_LIBS) - - tribits_sort_and_append_tpl_include_and_link_dirs_and_libs( - ${PACKAGE_NAME} LIB LINK_LIBS) - - get_directory_property(INCLUDE_DIRS_CURRENT INCLUDE_DIRECTORIES) - get_directory_property(LIBRARY_DIRS_CURRENT PACKAGE_LIBRARY_DIRS) - - prepend_global_set(${PACKAGE_NAME}_INCLUDE_DIRS ${INCLUDE_DIRS_CURRENT}) - prepend_global_set(${PACKAGE_NAME}_LIBRARY_DIRS ${LIBRARY_DIRS_CURRENT}) - prepend_global_set(${PACKAGE_NAME}_LIBRARIES ${LINK_LIBS}) - endif() endfunction() @@ -689,8 +648,6 @@ macro(tribits_package_postprocess_common) if (${PROJECT_NAME}_VERBOSE_CONFIGURE) message("\nTRIBITS_PACKAGE_POSTPROCESS_COMMON: ${PACKAGE_NAME}") - print_var(${PACKAGE_NAME}_INCLUDE_DIRS) - print_var(${PACKAGE_NAME}_LIBRARY_DIRS) print_var(${PACKAGE_NAME}_LIBRARIES) endif() @@ -721,13 +678,12 @@ macro(tribits_package_create_all_libs_interface_library) #print_var(allPackageBuildableLibTargetsList) set(packageLibsInAllLibsList) foreach (libTarget IN LISTS allPackageBuildableLibTargetsList) - get_target_property(isTestOnlyLib ${libTarget} TRIBITS_TESTONLY_LIB) + tribits_lib_is_testonly(${libTarget} isTestOnlyLib) #print_var(isTestOnlyLib) if (NOT isTestOnlyLib) list(APPEND packageLibsInAllLibsList ${libTarget}) endif() endforeach() - #print_var(packageLibsInAllLibsList) global_set(${PACKAGE_NAME}_EXPORTED_PACKAGE_LIBS_NAMES ${packageLibsInAllLibsList}) @@ -781,7 +737,7 @@ endmacro() # 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 +# NOTE: It is unfortunate that this macro must be called in a package's # top-level ``CMakeLists.txt`` file but limitations of the CMake language make # it necessary to do so. # @@ -965,25 +921,3 @@ macro(tribits_process_subpackages) set(${PACKAGE_NAME}_TRIBITS_PROCESS_SUBPACKAGES_CALLED TRUE) endmacro() - - -################################################################## -# -# NOTES TO DEVELOPERS -# -# Don't even attempt to touch the logic that goes into setting up and -# modifying the variables: -# -# ${PACKAGE_NAME}_INCLUDE_DIRS -# ${PACKAGE_NAME}_LIBRARY_DIRS -# ${PACKAGE_NAME}_LIBRARIES -# ${PACKAGE_NAME}_HAS_NATIVE_LIBRARIES_TO_INSTALL -# ${PACKAGE_NAME}_FULL_ENABLED_DEP_PACKAGES -# ${PARENT_PACKAGE_NAME}_LIB_TARGETS -# ${PARENT_PACKAGE_NAME}_ALL_TARGETS -# -# without carefully studying the documentation in README.DEPENDENCIES and then -# carefully studying all of the code and issues that modify these variables! -# -# ToDo: Write some good unit tests that pin down the behavior of all of this! -# diff --git a/cmake/tribits/core/package_arch/TribitsPrintEnabledPackagesLists.cmake b/cmake/tribits/core/package_arch/TribitsPrintEnabledPackagesLists.cmake new file mode 100644 index 000000000000..c1fd99ba4c83 --- /dev/null +++ b/cmake/tribits/core/package_arch/TribitsPrintEnabledPackagesLists.cmake @@ -0,0 +1,172 @@ +# @HEADER +# ************************************************************************ +# +# TriBITS: Tribal Build, Integrate, and Test System +# Copyright 2013 Sandia Corporation +# +# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +# the U.S. Government retains certain rights in this software. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Corporation nor the names of the +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# ************************************************************************ +# @HEADER + + +# @FUNCTION: tribits_print_enables_before_adjust_package_enables() +# +# Call this to print the package enables before calling +# tribits_adjust_package_enables(). +# +# Usage:: +# +# tribits_print_enables_before_adjust_package_enables() +# +function(tribits_print_enables_before_adjust_package_enables) + tribits_print_enabled_package_list( + "\nExplicitly enabled packages on input (by user)" ON FALSE) + tribits_print_enabled_se_package_list( + "\nExplicitly enabled SE packages on input (by user)" ON FALSE) + tribits_print_enabled_package_list( + "\nExplicitly disabled packages on input (by user or by default)" OFF FALSE) + tribits_print_enabled_se_package_list( + "\nExplicitly disabled SE packages on input (by user or by default)" OFF FALSE) + tribits_print_enabled_tpl_list( + "\nExplicitly enabled TPLs on input (by user)" ON FALSE) + tribits_print_enabled_tpl_list( + "\nExplicitly disabled TPLs on input (by user or by default)" OFF FALSE) +endfunction() + + +# @FUNCTION: tribits_print_enables_after_adjust_package_enables() +# +# Call this to print the package enables before calling +# tribits_adjust_package_enables(). +# +# Usage:: +# +# tribits_print_enables_after_adjust_package_enables() +# +function(tribits_print_enables_after_adjust_package_enables) + tribits_print_prefix_string_and_list( + "\nFinal set of enabled packages" "${${PROJECT_NAME}_ENABLED_PACKAGES}") + tribits_print_prefix_string_and_list( + "\nFinal set of enabled SE packages" "${${PROJECT_NAME}_ENABLED_SE_PACKAGES}") + tribits_print_enabled_package_list( + "\nFinal set of non-enabled packages" OFF TRUE) + tribits_print_enabled_se_package_list( + "\nFinal set of non-enabled SE packages" OFF TRUE) + tribits_print_enabled_tpl_list( + "\nFinal set of enabled TPLs" ON FALSE) + tribits_print_enabled_tpl_list( + "\nFinal set of non-enabled TPLs" OFF TRUE) +endfunction() + + +# Function that prints the current set of enabled/disabled packages +# +function(tribits_print_enabled_package_list DOCSTRING ENABLED_FLAG INCLUDE_EMPTY) + tribits_print_enabled_packages_list_from_var( ${PROJECT_NAME}_PACKAGES + "${DOCSTRING}" ${ENABLED_FLAG} ${INCLUDE_EMPTY} ) +endfunction() + + +# Prints the current set of enabled/disabled SE packages +# +function(tribits_print_enabled_se_package_list DOCSTRING ENABLED_FLAG INCLUDE_EMPTY) + if (ENABLED_FLAG AND NOT INCLUDE_EMPTY) + tribits_get_enabled_list( ${PROJECT_NAME}_SE_PACKAGES ${PROJECT_NAME} + ENABLED_SE_PACKAGES NUM_ENABLED) + elseif (ENABLED_FLAG AND INCLUDE_EMPTY) + tribits_get_nondisabled_list( ${PROJECT_NAME}_SE_PACKAGES ${PROJECT_NAME} + ENABLED_SE_PACKAGES NUM_ENABLED) + elseif (NOT ENABLED_FLAG AND NOT INCLUDE_EMPTY) + tribits_get_disabled_list( ${PROJECT_NAME}_SE_PACKAGES ${PROJECT_NAME} + ENABLED_SE_PACKAGES NUM_ENABLED) + else() # NOT ENABLED_FLAG AND INCLUDE_EMPTY + tribits_get_nonenabled_list( ${PROJECT_NAME}_SE_PACKAGES ${PROJECT_NAME} + ENABLED_SE_PACKAGES NUM_ENABLED) + endif() + tribits_print_prefix_string_and_list("${DOCSTRING}" "${ENABLED_SE_PACKAGES}") +endfunction() + + +# Print the current set of enabled/disabled TPLs +# +function(tribits_print_enabled_tpl_list DOCSTRING ENABLED_FLAG INCLUDE_EMPTY) + if (ENABLED_FLAG AND NOT INCLUDE_EMPTY) + tribits_get_enabled_list( ${PROJECT_NAME}_TPLS TPL + ENABLED_TPLS NUM_ENABLED) + elseif (ENABLED_FLAG AND INCLUDE_EMPTY) + tribits_get_nondisabled_list( ${PROJECT_NAME}_TPLS TPL + ENABLED_TPLS NUM_ENABLED) + elseif (NOT ENABLED_FLAG AND NOT INCLUDE_EMPTY) + tribits_get_disabled_list( ${PROJECT_NAME}_TPLS TPL + ENABLED_TPLS NUM_ENABLED) + else() # NOT ENABLED_FLAG AND INCLUDE_EMPTY + tribits_get_nonenabled_list( ${PROJECT_NAME}_TPLS TPL + ENABLED_TPLS NUM_ENABLED) + endif() + tribits_print_prefix_string_and_list("${DOCSTRING}" "${ENABLED_TPLS}") +endfunction() + + +# Print the current set of enabled/disabled packages given input list of +# packages +# +function(tribits_print_enabled_packages_list_from_var PACKAGES_LIST_VAR + DOCSTRING ENABLED_FLAG INCLUDE_EMPTY + ) + if (ENABLED_FLAG AND NOT INCLUDE_EMPTY) + tribits_get_enabled_list(${PACKAGES_LIST_VAR} ${PROJECT_NAME} + ENABLED_PACKAGES NUM_ENABLED) + elseif (ENABLED_FLAG AND INCLUDE_EMPTY) + tribits_get_nondisabled_list(${PACKAGES_LIST_VAR} ${PROJECT_NAME} + ENABLED_PACKAGES NUM_ENABLED) + elseif (NOT ENABLED_FLAG AND NOT INCLUDE_EMPTY) + tribits_get_disabled_list(${PACKAGES_LIST_VAR} ${PROJECT_NAME} + ENABLED_PACKAGES NUM_ENABLED) + else() # NOT ENABLED_FLAG AND INCLUDE_EMPTY + tribits_get_nonenabled_list(${PACKAGES_LIST_VAR} ${PROJECT_NAME} + ENABLED_PACKAGES NUM_ENABLED) + endif() + tribits_print_prefix_string_and_list("${DOCSTRING}" "${ENABLED_PACKAGES}") +endfunction() + + +# Print out a list with white-space separators with an initial doc string +# +function(tribits_print_prefix_string_and_list DOCSTRING LIST_TO_PRINT) + string(REPLACE ";" " " LIST_TO_PRINT_STR "${LIST_TO_PRINT}") + list(LENGTH LIST_TO_PRINT NUM_ELEMENTS) + if (NUM_ELEMENTS GREATER "0") + message("${DOCSTRING}: ${LIST_TO_PRINT_STR} ${NUM_ELEMENTS}") + else() + message("${DOCSTRING}: ${NUM_ELEMENTS}") + endif() +endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsProcessEnabledTpl.cmake b/cmake/tribits/core/package_arch/TribitsProcessEnabledTpl.cmake index 71429910b65d..e112a8f9e66c 100644 --- a/cmake/tribits/core/package_arch/TribitsProcessEnabledTpl.cmake +++ b/cmake/tribits/core/package_arch/TribitsProcessEnabledTpl.cmake @@ -48,7 +48,6 @@ include(AppendStringVar) include(TribitsStandardizePaths) -# # @FUNCTION: tribits_process_enabled_tpl() # # Process an enabled TPL's FindTPL${TPL_NAME}.cmake module. @@ -76,22 +75,14 @@ function(tribits_process_enabled_tpl TPL_NAME) if (${PROJECT_NAME}_VERBOSE_CONFIGURE) print_var(${TPL_NAME}_FINDMOD) endif() - #print_var(${TPL_NAME}_FINDMOD) if (${TPL_NAME}_FINDMOD STREQUAL "TRIBITS_PKG") set(TPL_${TPL_NAME}_PARTS_ALREADY_SET FALSE) # ToDo: Take out? if (NOT TPL_${TPL_NAME}_PARTS_ALREADY_SET) find_package(${TPL_NAME} CONFIG REQUIRED) - #print_var(${TPL_NAME}_INCLUDE_DIRS) - #print_var(${TPL_NAME}_LIBRARIES) - tribits_standardize_abs_paths(THIS_TPL_INCLUDE_DIRS - ${${TPL_NAME}_INCLUDE_DIRS} ${${TPL_NAME}_TPL_INCLUDE_DIRS}) - global_set(TPL_${TPL_NAME}_INCLUDE_DIRS ${THIS_TPL_INCLUDE_DIRS}) global_set(TPL_${TPL_NAME}_LIBRARIES "${${TPL_NAME}_LIBRARIES}" "${${TPL_NAME}_TPL_LIBRARIES}") global_set(TPL_${TPL_NAME}_PARTS_ALREADY_SET TRUE) endif() - #print_var(TPL_${TPL_NAME}_INCLUDE_DIRS) - #print_var(TPL_${TPL_NAME}_LIBRARIES) return() elseif (IS_ABSOLUTE ${${TPL_NAME}_FINDMOD}) #message("${${TPL_NAME}_FINDMOD} is absolute!") @@ -158,27 +149,21 @@ function(tribits_process_enabled_tpl TPL_NAME) endif() # Assert that the TPL correctly defined all of these variables - assert_defined(TPL_${TPL_NAME}_INCLUDE_DIRS) assert_defined(TPL_${TPL_NAME}_LIBRARIES) - assert_defined(TPL_${TPL_NAME}_LIBRARY_DIRS) - # ToDo: Make TPL_${TPL_NAME}_LIBRARY_DIRS go away. It is not needed for - # anything. # Generate the ConfigVersion.cmake file if it has not been # created yet and add install targets for Config[Version].cmake - 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() + 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() diff --git a/cmake/tribits/core/package_arch/TribitsProcessExtraRepositoriesList.cmake b/cmake/tribits/core/package_arch/TribitsProcessExtraRepositoriesList.cmake index 01b7b5274cb1..d9bdf527f03b 100644 --- a/cmake/tribits/core/package_arch/TribitsProcessExtraRepositoriesList.cmake +++ b/cmake/tribits/core/package_arch/TribitsProcessExtraRepositoriesList.cmake @@ -47,7 +47,6 @@ include(MessageWrapper) include(TribitsSortListAccordingToMasterList) -# # @MACRO: tribits_project_define_extra_repositories() # # Declare a set of extra repositories for the `TriBITS Project`_ (i.e. in the diff --git a/cmake/tribits/core/package_arch/TribitsProcessPackagesAndDirsLists.cmake b/cmake/tribits/core/package_arch/TribitsProcessPackagesAndDirsLists.cmake index 0987844d45e8..92e5175e1b37 100644 --- a/cmake/tribits/core/package_arch/TribitsProcessPackagesAndDirsLists.cmake +++ b/cmake/tribits/core/package_arch/TribitsProcessPackagesAndDirsLists.cmake @@ -557,6 +557,7 @@ macro(tribits_process_packages_and_dirs_lists REPOSITORY_NAME REPOSITORY_DIR) list(APPEND ${PROJECT_NAME}_PACKAGES ${TRIBITS_PACKAGE}) tribits_insert_standard_package_options(${TRIBITS_PACKAGE} ${PACKAGE_TESTGROUP}) + set(${TRIBITS_PACKAGE}_PACKAGE_BUILD_STATUS INTERNAL) set(${TRIBITS_PACKAGE}_SOURCE_DIR "${PROJECT_SOURCE_DIR}/${REPOSITORY_AND_PACKAGE_DIR}") set(${TRIBITS_PACKAGE}_REL_SOURCE_DIR diff --git a/cmake/tribits/core/package_arch/TribitsProcessTplsLists.cmake b/cmake/tribits/core/package_arch/TribitsProcessTplsLists.cmake index 4009ac400928..f37f7bdbab50 100644 --- a/cmake/tribits/core/package_arch/TribitsProcessTplsLists.cmake +++ b/cmake/tribits/core/package_arch/TribitsProcessTplsLists.cmake @@ -44,7 +44,7 @@ include(TribitsListHelpers) include(PrintVar) include(Split) -# + # @MACRO: tribits_repository_define_tpls() # # Define the list of `TriBITS TPLs`_ for a given `TriBITS Repository`_ which @@ -215,6 +215,10 @@ macro(tribits_process_tpls_lists REPOSITORY_NAME REPOSITORY_DIR) list(APPEND ${PROJECT_NAME}_TPLS ${TPL_NAME}) endif() + # Set ${TPL_NAME}_PACKAGE_BUILD_STATUS + + SET(${TPL_NAME}_PACKAGE_BUILD_STATUS EXTERNAL) + # Set ${TPL_NAME}_TESTGROUP if (TPL_TESTGROUP STREQUAL PT @@ -233,23 +237,18 @@ macro(tribits_process_tpls_lists REPOSITORY_NAME REPOSITORY_DIR) # Set ${TPL_NAME}_FINDMOD - #print_var(REPOSITORY_DIR) - if ("${REPOSITORY_DIR}" STREQUAL "." OR IS_ABSOLUTE ${TPL_FINDMOD}) set(REPOSITORY_DIR_AND_SEP "") else() set(REPOSITORY_DIR_AND_SEP "${REPOSITORY_DIR}/") endif() - #print_var(REPOSITORY_DIR_AND_SEP) set(TPL_FINDMOD "${REPOSITORY_DIR_AND_SEP}${TPL_FINDMOD}") - #print_var(TPL_FINDMOD) set(TPL_FINDMOD_STD_NAME "FindTPL${TPL_NAME}.cmake") if (TPL_FINDMOD) string(REGEX MATCH ".+/$" FINDMOD_IS_DIR "${TPL_FINDMOD}") - #print_var(FINDMOD_IS_DIR) if (FINDMOD_IS_DIR) set(${TPL_NAME}_FINDMOD "${TPL_FINDMOD}${TPL_FINDMOD_STD_NAME}") else() diff --git a/cmake/tribits/core/package_arch/TribitsProject.cmake b/cmake/tribits/core/package_arch/TribitsProject.cmake index c1e3837aa639..d300356cb994 100644 --- a/cmake/tribits/core/package_arch/TribitsProject.cmake +++ b/cmake/tribits/core/package_arch/TribitsProject.cmake @@ -70,7 +70,6 @@ include(TribitsCMakePolicies) include(TribitsProjectImpl) -# # @MACRO: tribits_project() # # Processes a `TriBITS Project`_'s files and configures its software which is diff --git a/cmake/tribits/core/package_arch/TribitsProjectImpl.cmake b/cmake/tribits/core/package_arch/TribitsProjectImpl.cmake index 62ff4e883e0f..75c926eedb99 100644 --- a/cmake/tribits/core/package_arch/TribitsProjectImpl.cmake +++ b/cmake/tribits/core/package_arch/TribitsProjectImpl.cmake @@ -323,7 +323,6 @@ macro(tribits_project_impl) endmacro() -# # @MACRO: tribits_project_enable_all() # # Process a project where you enable all of the packages by default. diff --git a/cmake/tribits/core/package_arch/TribitsReadDepsFilesCreateDepsGraph.cmake b/cmake/tribits/core/package_arch/TribitsReadDepsFilesCreateDepsGraph.cmake index c344680041de..fce0e432586c 100644 --- a/cmake/tribits/core/package_arch/TribitsReadDepsFilesCreateDepsGraph.cmake +++ b/cmake/tribits/core/package_arch/TribitsReadDepsFilesCreateDepsGraph.cmake @@ -810,6 +810,8 @@ macro(tribits_parse_subpackages_append_se_packages_add_options print_var(${SUBPACKAGE_FULLNAME}_PARENT_REPOSITORY) endif() + set(${SUBPACKAGE_FULLNAME}_PACKAGE_BUILD_STATUS INTERNAL) + # Set up the input options for this subpackage tribits_insert_standard_package_options(${SUBPACKAGE_FULLNAME} ${SUBPACKAGE_TESTGROUP}) diff --git a/cmake/tribits/core/package_arch/TribitsSystemDataStructuresMacrosFunctions.rst b/cmake/tribits/core/package_arch/TribitsSystemDataStructuresMacrosFunctions.rst index 11e1643c6ca0..e3183fd22d9a 100644 --- a/cmake/tribits/core/package_arch/TribitsSystemDataStructuresMacrosFunctions.rst +++ b/cmake/tribits/core/package_arch/TribitsSystemDataStructuresMacrosFunctions.rst @@ -10,13 +10,19 @@ graph of external packages (i.e. TPLs) and internal packages (i.e. buildable CMake packages). This information is meant for maintainers of the TriBITS system itself and should not need to be known by TriBITS Project maintainers. -In addition to the variables listed below are the variables documented in: +Basic TriBITS Project, Repository, Package, and Subpackage Core Variables ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +The basic variables that define a TriBITS Project, Repository, Package and +Subpackage are listed at the below links: * `TriBITS Project Core Variables`_ * `TriBITS Repository Core Variables`_ * `TriBITS Package Core Variables`_ * `TriBITS Subpackage Core Variables`_ +These are variables that can be accessed by `TriBITS Project Developers`_ but +are also used in the internal implementation of TriBITS functionality. Lists of external and internal packages +++++++++++++++++++++++++++++++++++++++ @@ -66,7 +72,7 @@ out on the system as pre-built/pre-installed packages using ``find_package()``. The final decision for if a package is treated as an internal or external package is determined by the variable:: - ${PACKAGE_NAME}_PACKAGE_STATUS=[INTERNAL|EXTERNAL] + ${PACKAGE_NAME}_PACKAGE_BUILD_STATUS=[INTERNAL|EXTERNAL] which gets set various criteria as described in section `Determining if a package is internal or external`_. This variable determines what @@ -201,16 +207,22 @@ a package's `/cmake/Dependencies.cmake`_ file. (These lists should **not** contain any *indirect* dependencies as the dependency system already handles these automatically.) + .. _${PACKAGE_NAME}_LIB_REQUIRED_DEP_PACKAGES: + ``${PACKAGE_NAME}_LIB_REQUIRED_DEP_PACKAGES`` List of *direct* package dependencies that are required for the libraries and non-test executables built by ``${PACKAGE_NAME}``. + .. _${PACKAGE_NAME}_LIB_OPTIONAL_DEP_PACKAGES: + ``${PACKAGE_NAME}_LIB_OPTIONAL_DEP_PACKAGES`` List of *direct* package dependencies that are only optional for the libraries and non-test executables built by ``${PACKAGE_NAME}``. + .. _${PACKAGE_NAME}_TEST_REQUIRED_DEP_PACKAGES: + ``${PACKAGE_NAME}_TEST_REQUIRED_DEP_PACKAGES`` List of *direct* package dependencies that are required for the @@ -218,6 +230,8 @@ already handles these automatically.) contain any of the packages already listed in ``${PACKAGE_NAME}_LIB_REQUIRED_DEP_PACKAGES``. + .. _${PACKAGE_NAME}_TEST_OPTIONAL_DEP_PACKAGES: + ``${PACKAGE_NAME}_TEST_OPTIONAL_DEP_PACKAGES``` List of *direct* package dependencies that are optional for the @@ -274,20 +288,20 @@ or:: The final status of whether a listed package is an internal package or an external package is provided by the variable:: - ${PACKAGE_NAME}_PACKAGE_STATUS=[INTERNAL|EXTERNAL] + ${PACKAGE_NAME}_PACKAGE_BUILD_STATUS=[INTERNAL|EXTERNAL] As a result, every other package upstream from any of these ```` packages must therefore also be treated as external packages automatically. -The primary TriBITS file that processes and defines these variables is: +The primary TriBITS file that processes and defines these variables is:: TribitsAdjustPackageEnables.cmake There are pretty good unit and regression tests to demonstrate and protect -this functionality in the directory: +this functionality in the directory:: - tribits/package_arch/UntiTests/ + TriBITS/test/core/ External package dependencies @@ -300,6 +314,71 @@ in ``FindTPLDependencies.cmake`` files and overridden in the cache. +Flat lists of direct package dependencies ++++++++++++++++++++++++++++++++++++++++++ + +TriBITS sets up the following lists of dependencies for each internal and +external package/TPL: + + .. _${PACKAGE_NAME}_LIB_ALL_DEPENDENCIES: + + ``${PACKAGE_NAME}_LIB_ALL_DEPENDENCIES`` + + The list of all **direct** required and optional upstream internal and + external packages/TPL dependencies, regardless if they are enabled or not. + This is concatenation of lists + `${PACKAGE_NAME}_LIB_REQUIRED_DEP_PACKAGES`_, + `${PACKAGE_NAME}_LIB_OPTIONAL_DEP_PACKAGES`_, + ``${PACKAGE_NAME}_LIB_REQUIRED_DEP_TPLS``, and + ``${PACKAGE_NAME}_LIB_OPTIONAL_DEP_TPLS`` (with the latter two lists soon + to disappear as part of #63). To determine if a given direct upstream + package ```` in this list is enabled/supported or not for this + package ``${PACKAGE_NAME}``, check the value of + ``${PACKAGE_NAME}_ENABLE_``. NOTE: The variables + ``${PACKAGE_NAME}_ENABLE_`` will be set even for required upstream + internal and external packages/tpls to allow for uniform loops involving + required and optional upstream dependencies. (And for a parent package + with subpackages, it is possible for a required subpackage to **not** be + enabled and for ``${PACKAGE_NAME}_ENABLE_`` to be ``OFF`` as + explained in `Subpackage enable does not auto-enable the parent + package`_.) This list will be set regardless of if the package + ``${PACKAGE_NAME}`` is enabled or not. + + .. _${PACKAGE_NAME}_LIB_ENABLED_DEPENDENCIES: + + ``${PACKAGE_NAME}_LIB_ENABLED_DEPENDENCIES`` + + List of all **enabled** **direct** required and optional upstream internal + and external packages/TPL dependencies. This is strict subset + `${PACKAGE_NAME}_LIB_ALL_DEPENDENCIES`_ (i.e. all of the ```` + items in this list will have ``${PACKAGE_NAME}_ENABLE_`` set to + ``ON``). + + .. _${PACKAGE_NAME}_TEST_ALL_DEPENDENCIES: + + ``${PACKAGE_NAME}_TEST_ALL_DEPENDENCIES`` + + This list of all **direct** extra package test required and optional + upstream internal and external packages/TPLs. This list includes just the + extra dependencies not already listed in + `${PACKAGE_NAME}_LIB_ALL_DEPENDENCIES`_. This is a concatenation of the + lists `${PACKAGE_NAME}_TEST_REQUIRED_DEP_PACKAGES`_, + `${PACKAGE_NAME}_TEST_OPTIONAL_DEP_PACKAGES`_, + ``${PACKAGE_NAME}_TEST_REQUIRED_DEP_TPLS``, and + ``${PACKAGE_NAME}_TEST_OPTIONAL_DEP_TPLS`` (with the latter two lists soon + to disappear as part of #63). This list is set regardless if the package + ``${PACKAGE_NAME}`` is enabled or not. + + .. _${PACKAGE_NAME}_TEST_ENABLED_DEPENDENCIES: + + ``${PACKAGE_NAME}_TEST_ENABLED_DEPENDENCIES`` + + The list of all **enabled** **direct** extra required and optional + upstream internal and external packages/TPL dependencies. This is a + strict subset of `${PACKAGE_NAME}_TEST_ALL_DEPENDENCIES`_. This list + includes just the extra dependencies not already listed in + `${PACKAGE_NAME}_LIB_ENABLED_DEPENDENCIES`_. + List variables defining include directories and libraries +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -310,29 +389,6 @@ targets as part of #299. The following global internal cache variables are used to communicate the required header directory paths and libraries needed to build and link against a given package's capabilities: - - ``${PACKAGE_NAME}_INCLUDE_DIRS`` - - Defines a list of include paths needed to find all of the headers needed - to compile client code against this (sub)packages sources and it's - upstream packages and TPL sources. This variable is used whenever - building downstream code including downstream libraries or executables in - the same package, or libraries or executables in downstream packages. It - is also used to list out in ${PACKAGE_NAME}Config.cmake files. - - ToDo: Look to eliminate this variable and just add it to the package's - library targets with target_include_directories(). - - ToDo: Split off ${PACKAGE_NAME}_TPL_INCLUDE_DIRS - - ``${PACKAGE_NAME}_LIBRARY_DIRS`` - - Defines as list of the link directories needed to find all of the - libraries for this packages and it's upstream packages and TPLs. Adding - these library directories to the CMake link line is unnecessary and would - cause link-line too long errors on some systems. Instead, this list of - library directories is used when creating ${PACKAGE_NAME}Config.cmake - files. ``${PACKAGE_NAME}_LIBRARIES`` @@ -416,7 +472,7 @@ Logic`_. There are pretty good unit and regression tests to demonstrate and protect this functionality in the directory:: - tribits/package_arch/UntiTests/ + TriBITS/test/core/ Function call tree for constructing package dependency graph @@ -509,4 +565,5 @@ allow it to be efficiently tested outside of the actual build. But there are a number of example projects that are part of the automated TriBITS test suite that do test much of the logic used in these variables. -.. LocalWords: acyclic TriBITS SUBPACKAGES CTEST subpackages +.. LocalWords: acyclic TriBITS SUBPACKAGES CTEST subpackages buildable TPLs TPLS +.. LocalWords: Subpackage CMake CMakeLists diff --git a/cmake/tribits/core/package_arch/TribitsTplFindIncludeDirsAndLibraries.cmake b/cmake/tribits/core/package_arch/TribitsTplFindIncludeDirsAndLibraries.cmake index acc851e31c7d..d3ebe2795030 100644 --- a/cmake/tribits/core/package_arch/TribitsTplFindIncludeDirsAndLibraries.cmake +++ b/cmake/tribits/core/package_arch/TribitsTplFindIncludeDirsAndLibraries.cmake @@ -78,12 +78,13 @@ include(Split) # the search for the library components and just specify the absolute # locations. The function will also set ```` to # ``FALSE`` if ``_INCLUDE_DIRS``, ``_LIBRARY_NAMES``, or -# ``_LIBRARY_DIRS`` is set and ``_FORCE_PRE_FIND_PACKAGE`` is -# set to ``FALSE``. Otherwise, if ``_FORCE_PRE_FIND_PACKAGE`` is set -# to ``TRUE``, the function will not return ``FALSE`` for +# ``_LIBRARY_DIRS`` is set and ``_FORCE_PRE_FIND_PACKAGE`` +# is set to ``FALSE``. Otherwise, if ``_FORCE_PRE_FIND_PACKAGE`` is +# set to ``TRUE``, the function will not return ``FALSE`` for # ```` no matter what the values of # ``_INCLUDE_DIRS``, ``_LIBRARY_NAMES``, or -# ``_LIBRARY_DIRS``. +# ``_LIBRARY_DIRS``. Finally, ```` is set to +# ``FALSE`` if ``_ALLOW_PACKAGE_PREFIND=OFF`` is set in the cache. # # The variable ``_FORCE_PRE_FIND_PACKAGE`` is needed to allow users # (or the ``FindTPL.cmake`` module itself) to avoid name clashes with @@ -94,6 +95,10 @@ include(Split) # value ``FALSE`` to maintain backward compatibility with existing # ``FindTPL.cmake`` modules. # +# The cache variable ``_ALLOW_PACKAGE_PREFIND`` is to allow the user +# to disable the prefind call to ``find_package()`` even if it would be +# allowed otherwise. +# # See `How to use find_package() for a TriBITS TPL`_ for details in how to use # this function to create a ``FindTPL.cmake`` module file. # @@ -111,10 +116,16 @@ function(tribits_tpl_allow_pre_find_package TPL_NAME ALLOW_PACKAGE_PREFIND_OUT CACHE BOOL "Determines if the variables ${TPL_NAME}_[INCLUDE_DIRS,LIBRARY_NAMES,LIBRARY_DIRS] should be ignored and the pre-find find_package(${TPL_NAME} should be performed anyway. But this will *not* do the pre-find if any of the TPL_${TPL_NAME}_[INCLUDE_DIRS,LIBRARY_NAMES,LIBRARY_DIRS] vars are set." ) + # Start out with TRUE and set to FALSE in logic below + set(${TPL_NAME}_ALLOW_PACKAGE_PREFIND TRUE CACHE BOOL + "Set to FALSE to skip find_package() prefind for the TriBITS TPL '${TPL_NAME}'") + # Start out with TRUE and set to FALSE in logic below set(ALLOW_PACKAGE_PREFIND TRUE) - if ( + if (NOT ${TPL_NAME}_ALLOW_PACKAGE_PREFIND) + set(ALLOW_PACKAGE_PREFIND FALSE) + elseif ( (NOT "${TPL_${TPL_NAME}_INCLUDE_DIRS}" STREQUAL "") OR (NOT "${TPL_${TPL_NAME}_LIBRARIES}" STREQUAL "") OR (NOT "${TPL_${TPL_NAME}_LIBRARY_DIRS}" STREQUAL "") @@ -290,11 +301,30 @@ function(tribits_tpl_find_include_dirs_and_libraries TPL_NAME) set(ERROR_MSG_MODE SEND_ERROR) endif() + # Allow user override for finding libraries even if REQUIRED_LIBS_NAMES is + # empty on input + + multiline_set(DOCSTR + "List of semi-colon separated names of libraries needed to link to for" + " the TPL ${TPL_NAME}. This list of libraries will be search for in" + " find_library(...) calls along with the directories specified with" + " ${TPL_NAME}_LIBRARY_DIRS. NOTE: This is not the final list of libraries" + " used for linking. That is specified by TPL_${TPL_NAME}_LIBRARIES!" + ) + advanced_set(${TPL_NAME}_LIBRARY_NAMES ${PARSE_REQUIRED_LIBS_NAMES} + CACHE STRING ${DOCSTR}) + split("${${TPL_NAME}_LIBRARY_NAMES}" "," ${TPL_NAME}_LIBRARY_NAMES) + print_var(${TPL_NAME}_LIBRARY_NAMES) + + # Let the user override what the names of the libraries which might + # actually mean that no libraries are searched for. + set(REQUIRED_LIBS_NAMES ${${TPL_NAME}_LIBRARY_NAMES}) + # # User options # - if (PARSE_REQUIRED_LIBS_NAMES) + if (REQUIRED_LIBS_NAMES) # Library directories @@ -315,22 +345,6 @@ function(tribits_tpl_find_include_dirs_and_libraries TPL_NAME) # Libraries - multiline_set(DOCSTR - "List of semi-colon separated names of libraries needed to link to for" - " the TPL ${TPL_NAME}. This list of libraries will be search for in" - " find_library(...) calls along with the directories specified with" - " ${TPL_NAME}_LIBRARY_DIRS. NOTE: This is not the final list of libraries" - " used for linking. That is specified by TPL_${TPL_NAME}_LIBRARIES!" - ) - advanced_set(${TPL_NAME}_LIBRARY_NAMES ${PARSE_REQUIRED_LIBS_NAMES} - CACHE STRING ${DOCSTR}) - split("${${TPL_NAME}_LIBRARY_NAMES}" "," ${TPL_NAME}_LIBRARY_NAMES) - print_var(${TPL_NAME}_LIBRARY_NAMES) - - # Let the user override what the names of the libraries which might - # actually mean that no libraries are searched for. - set(REQUIRED_LIBS_NAMES ${${TPL_NAME}_LIBRARY_NAMES}) - if (${PROJECT_NAME}_MUST_FIND_ALL_TPL_LIBS) set(MUST_FIND_ALL_LIBS TRUE) else() @@ -420,7 +434,7 @@ function(tribits_tpl_find_include_dirs_and_libraries TPL_NAME) set(LIBRARIES_FOUND) - foreach(LIBNAME_SET ${${TPL_NAME}_LIBRARY_NAMES}) + foreach(LIBNAME_SET ${REQUIRED_LIBS_NAMES}) message("-- Searching for a lib in the set \"${LIBNAME_SET}\":") @@ -679,11 +693,13 @@ function(tribits_tpl_find_include_dirs_and_libraries TPL_NAME) set(buildDirExternalPkgsDir "${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR}") - set(tplConfigFile - "${buildDirExternalPkgsDir}/${TPL_NAME}/${TPL_NAME}Config.cmake") + set(tplConfigFileBaseDir "${buildDirExternalPkgsDir}/${TPL_NAME}") + set(tplConfigFile "${tplConfigFileBaseDir}/${TPL_NAME}Config.cmake") tribits_external_package_write_config_file(${TPL_NAME} "${tplConfigFile}") if (NOT ${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING) include("${tplConfigFile}") + set(${TPL_NAME}_DIR "${tplConfigFileBaseDir}" CACHE INTERNAL + "TriBITS-generated ${TPL_NAME}Config.cmake file used from this dir") endif() # NOTE: The file ConfigVersion.cmake will get created elsewhere as # will the install targets for the files Config and diff --git a/cmake/tribits/core/package_arch/TribitsVerbosePrintVar.cmake b/cmake/tribits/core/package_arch/TribitsVerbosePrintVar.cmake index ef4496c92d4b..e6021d60f479 100644 --- a/cmake/tribits/core/package_arch/TribitsVerbosePrintVar.cmake +++ b/cmake/tribits/core/package_arch/TribitsVerbosePrintVar.cmake @@ -40,7 +40,7 @@ if (${PROJECT_NAME}_VERBOSE_CONFIGURE) -# + # @FUNCTION: tribits_verbose_print_var() # # print a variable giving its name then value if diff --git a/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake b/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake index eaf01fa739de..6a91545524e6 100644 --- a/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake +++ b/cmake/tribits/core/package_arch/TribitsWriteClientExportFiles.cmake @@ -185,15 +185,6 @@ function(tribits_write_flexible_package_client_export_files) set(FULL_PACKAGE_SET "") set(FULL_LIBRARY_SET "") - set(SET_INCLUDE_LIBRARY_DIRS_FROM_UPSTREAM TRUE) - if (${PACKAGE_NAME}_INCLUDE_DIRS) - set(FULL_INCLUDE_DIRS_SET ${${PACKAGE_NAME}_INCLUDE_DIRS}) - set(FULL_LIBRARY_DIRS_SET ${${PACKAGE_NAME}_LIBRARY_DIRS}) - set(SET_INCLUDE_LIBRARY_DIRS_FROM_UPSTREAM FALSE) - else() - set(FULL_INCLUDE_DIRS_SET "") - set(FULL_LIBRARY_DIRS_SET "") - endif() if (TRIBITS_WRITE_FLEXIBLE_PACKAGE_CLIENT_EXPORT_FILES_DEBUG_DUMP) print_var(${PACKAGE_NAME}_FULL_ENABLED_DEP_PACKAGES) @@ -219,10 +210,6 @@ function(tribits_write_flexible_package_client_export_files) list(APPEND FULL_PACKAGE_SET ${TRIBITS_PACKAGE}) if (APPEND_THE_PACKAGE_LIBS) append_set(FULL_LIBRARY_SET ${${TRIBITS_PACKAGE}_LIBRARIES}) - if (SET_INCLUDE_LIBRARY_DIRS_FROM_UPSTREAM) - append_set(FULL_INCLUDE_DIRS_SET ${${TRIBITS_PACKAGE}_INCLUDE_DIRS}) - append_set(FULL_LIBRARY_DIRS_SET ${${TRIBITS_PACKAGE}_LIBRARY_DIRS}) - endif() else() if (TRIBITS_WRITE_FLEXIBLE_PACKAGE_CLIENT_EXPORT_FILES_DEBUG_DUMP) message("-- " "Skipping adding the package libs!") @@ -237,10 +224,6 @@ function(tribits_write_flexible_package_client_export_files) if (TRIBITS_WRITE_FLEXIBLE_PACKAGE_CLIENT_EXPORT_FILES_DEBUG_DUMP) print_var(FULL_PACKAGE_SET) print_var(FULL_LIBRARY_SET) - if (SET_INCLUDE_LIBRARY_DIRS_FROM_UPSTREAM) - print_var(FULL_INCLUDE_DIRS_SET) - print_var(FULL_LIBRARY_DIRS_SET) - endif() endif() endforeach() @@ -256,21 +239,10 @@ function(tribits_write_flexible_package_client_export_files) prepend_set(FULL_LIBRARY_SET ${${PACKAGE_NAME}_LIBRARIES}) endif() - if (SET_INCLUDE_LIBRARY_DIRS_FROM_UPSTREAM) - if (FULL_INCLUDE_DIRS_SET) - list(REMOVE_DUPLICATES FULL_INCLUDE_DIRS_SET) - endif() - if (FULL_LIBRARY_DIRS_SET) - list(REMOVE_DUPLICATES FULL_LIBRARY_DIRS_SET) - endif() - endif() - if (TRIBITS_WRITE_FLEXIBLE_PACKAGE_CLIENT_EXPORT_FILES_DEBUG_DUMP) message("-- " "*** Final sets of packages, libs, include dirs, and lib dirs:") print_var(FULL_PACKAGE_SET) print_var(FULL_LIBRARY_SET) - print_var(FULL_INCLUDE_DIRS_SET) - print_var(FULL_LIBRARY_DIRS_SET) endif() # @@ -315,12 +287,8 @@ function(tribits_write_flexible_package_client_export_files) # set(${PACKAGE_NAME}_TPL_LIBRARIES "") - set(${PACKAGE_NAME}_TPL_INCLUDE_DIRS "") - set(${PACKAGE_NAME}_TPL_LIBRARY_DIRS "") foreach(TPL ${ORDERED_FULL_TPL_SET}) - list(APPEND ${PACKAGE_NAME}_TPL_LIBRARIES ${TPL_${TPL}_LIBRARIES}) - list(APPEND ${PACKAGE_NAME}_TPL_INCLUDE_DIRS ${TPL_${TPL}_INCLUDE_DIRS}) - list(APPEND ${PACKAGE_NAME}_TPL_LIBRARY_DIRS ${TPL_${TPL}_LIBRARY_DIRS}) + list(APPEND ${PACKAGE_NAME}_TPL_LIBRARIES ${TPL}::all_libs) endforeach() # Generate a note discouraging editing of the Config.cmake file @@ -343,13 +311,15 @@ function(tribits_write_flexible_package_client_export_files) # F) Create the contents of the Config.cmake file for the build tree # - tribits_generate_package_config_file_for_build_tree(${PACKAGE_NAME}) + tribits_generate_package_config_file_for_build_tree(${PACKAGE_NAME} + EXPORT_FILE_VAR_PREFIX ${EXPORT_FILE_VAR_PREFIX}) # # G) Create Config_install.cmake file for the install tree # - tribits_generate_package_config_file_for_install_tree(${PACKAGE_NAME}) + tribits_generate_package_config_file_for_install_tree(${PACKAGE_NAME} + EXPORT_FILE_VAR_PREFIX ${EXPORT_FILE_VAR_PREFIX}) endfunction() @@ -362,7 +332,9 @@ endfunction() # # Usage:: # -# tribits_generate_package_config_file_for_build_tree() +# tribits_generate_package_config_file_for_build_tree( +# [EXPORT_FILE_VAR_PREFIX ] +# ) # # These files get placed under /cmake_packages// # @@ -371,6 +343,24 @@ endfunction() # function(tribits_generate_package_config_file_for_build_tree packageName) + if (TRIBITS_WRITE_FLEXIBLE_PACKAGE_CLIENT_EXPORT_FILES_DEBUG_DUMP) + message("tribits_generate_package_config_file_for_build_tree(${ARGV})") + endif() + + cmake_parse_arguments( + PARSE #prefix + "" #options + "EXPORT_FILE_VAR_PREFIX" #one_value_keywords + "" #multi_value_keywords + ${ARGN} + ) + + if (PARSE_EXPORT_FILE_VAR_PREFIX) + set(EXPORT_FILE_VAR_PREFIX ${PARSE_EXPORT_FILE_VAR_PREFIX}) + else() + set(EXPORT_FILE_VAR_PREFIX ${packageName}) + endif() + set(buildDirExtPkgsDir "${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR}") set(buildDirCMakePkgsDir @@ -383,7 +373,8 @@ function(tribits_generate_package_config_file_for_build_tree packageName) # below) set(PACKAGE_CONFIG_CODE "") - tribits_append_dependent_package_config_file_includes(${packageName} + tribits_append_dependent_package_config_file_includes_and_enables(${packageName} + EXPORT_FILE_VAR_PREFIX ${EXPORT_FILE_VAR_PREFIX} EXT_PKG_CONFIG_FILE_BASE_DIR "${buildDirExtPkgsDir}" PKG_CONFIG_FILE_BASE_DIR "${buildDirCMakePkgsDir}" CONFIG_FILE_STR_INOUT PACKAGE_CONFIG_CODE ) @@ -438,7 +429,9 @@ endfunction() # # Usage:: # -# tribits_generate_package_config_file_for_install_tree() +# tribits_generate_package_config_file_for_install_tree( +# [EXPORT_FILE_VAR_PREFIX ] +# ) # # The export files are typically installed in # //cmake//. @@ -450,6 +443,24 @@ endfunction() # function(tribits_generate_package_config_file_for_install_tree packageName) + if (TRIBITS_WRITE_FLEXIBLE_PACKAGE_CLIENT_EXPORT_FILES_DEBUG_DUMP) + message("tribits_generate_package_config_file_for_install_tree(${ARGV})") + endif() + + cmake_parse_arguments( + PARSE #prefix + "" #options + "EXPORT_FILE_VAR_PREFIX" #one_value_keywords + "" #multi_value_keywords + ${ARGN} + ) + + if (PARSE_EXPORT_FILE_VAR_PREFIX) + set(EXPORT_FILE_VAR_PREFIX ${PARSE_EXPORT_FILE_VAR_PREFIX}) + else() + set(EXPORT_FILE_VAR_PREFIX ${packageName}) + endif() + # Set the include and library directories relative to the location # at which the ${PROJECT_NAME}Config.cmake file is going to be # installed. Note the variable reference below is escaped so it @@ -469,15 +480,12 @@ function(tribits_generate_package_config_file_for_install_tree packageName) foreach(PATH ${PATH_LIST}) set(RELATIVE_PATH "${RELATIVE_PATH}/..") endforeach() - set(FULL_LIBRARY_DIRS_SET - "\${CMAKE_CURRENT_LIST_DIR}/${RELATIVE_PATH}/${${PROJECT_NAME}_INSTALL_LIB_DIR}") - set(FULL_INCLUDE_DIRS_SET - "\${CMAKE_CURRENT_LIST_DIR}/${RELATIVE_PATH}/${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}") # Custom code in configuration file. set(PACKAGE_CONFIG_CODE "") - tribits_append_dependent_package_config_file_includes(${packageName} + tribits_append_dependent_package_config_file_includes_and_enables(${packageName} + EXPORT_FILE_VAR_PREFIX ${EXPORT_FILE_VAR_PREFIX} EXT_PKG_CONFIG_FILE_BASE_DIR "\${CMAKE_CURRENT_LIST_DIR}/../../${${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR}" PKG_CONFIG_FILE_BASE_DIR "\${CMAKE_CURRENT_LIST_DIR}/.." @@ -512,21 +520,27 @@ function(tribits_generate_package_config_file_for_install_tree packageName) endfunction() -# @FUNCTION: tribits_append_dependent_package_config_file_includes() +# @FUNCTION: tribits_append_dependent_package_config_file_includes_and_enables() # # Append the includes for upstream external packages (TPLs) and internal -# packages to a `Config.cmake` file string. +# packages as well as the enables/disables for upstream dependencies to an +# output `Config.cmake` file string. # # Usage:: # -# tribits_append_dependent_package_config_file_includes( +# tribits_append_dependent_package_config_file_includes_and_enables( # +# EXPORT_FILE_VAR_PREFIX # EXT_PKG_CONFIG_FILE_BASE_DIR # PKG_CONFIG_FILE_BASE_DIR # CONFIG_FILE_STR_INOUT # ) # -function(tribits_append_dependent_package_config_file_includes packageName) +function(tribits_append_dependent_package_config_file_includes_and_enables packageName) + + if (TRIBITS_WRITE_FLEXIBLE_PACKAGE_CLIENT_EXPORT_FILES_DEBUG_DUMP) + message("tribits_append_dependent_package_config_file_includes_and_enables(${ARGV})") + endif() # Parse input @@ -534,58 +548,52 @@ function(tribits_append_dependent_package_config_file_includes packageName) PARSE #prefix "" #options #one_value_keywords - "EXT_PKG_CONFIG_FILE_BASE_DIR;PKG_CONFIG_FILE_BASE_DIR;CONFIG_FILE_STR_INOUT" + "EXPORT_FILE_VAR_PREFIX;EXT_PKG_CONFIG_FILE_BASE_DIR;PKG_CONFIG_FILE_BASE_DIR;CONFIG_FILE_STR_INOUT" "" #multi_value_keywords ${ARGN} ) tribits_check_for_unparsed_arguments() + if (PARSE_EXPORT_FILE_VAR_PREFIX) + set(EXPORT_FILE_VAR_PREFIX ${PARSE_EXPORT_FILE_VAR_PREFIX}) + else() + set(EXPORT_FILE_VAR_PREFIX ${packageName}) + endif() + set(extPkgConfigFileBaseDir "${PARSE_EXT_PKG_CONFIG_FILE_BASE_DIR}") set(pkgConfigFileBaseDir "${PARSE_PKG_CONFIG_FILE_BASE_DIR}") set(configFileStr "${${PARSE_CONFIG_FILE_STR_INOUT}}") - # Include configurations of dependent packages + # Add set of enables/disables for all upstream dependencies string(APPEND configFileStr - "# Include configuration of dependent packages\n") - foreach(depPkg IN LISTS ${packageName}_LIB_REQUIRED_DEP_PACKAGES) - if (${PROJECT_NAME}_ENABLE_${depPkg}) - set(cmakeTplDir "${pkgConfigFileBaseDir}/${depPkg}") - string(APPEND configFileStr - "include(\"${cmakeTplDir}/${depPkg}Config.cmake\")\n") - endif() - # NOTE: Above, a required dependent package may not actaully be enabled if - # it is a required subpackage of a parent package and the parent package - # itself is not actaully enabled (very tricky). - endforeach() - foreach(depPkg IN LISTS ${packageName}_LIB_OPTIONAL_DEP_PACKAGES) - if (${packageName}_ENABLE_${depPkg} AND ${PROJECT_NAME}_ENABLE_${depPkg}) - set(cmakeTplDir "${pkgConfigFileBaseDir}/${depPkg}") - string(APPEND configFileStr - "include(\"${cmakeTplDir}/${depPkg}Config.cmake\")\n") + "# Enables/Disables for upstream package dependencies\n") + foreach(depPkg IN LISTS ${packageName}_LIB_ALL_DEPENDENCIES) + if (${packageName}_ENABLE_${depPkg}) + set(enableVal ON) + else() + set(enableVal OFF) endif() + string(APPEND configFileStr + "set(${EXPORT_FILE_VAR_PREFIX}_ENABLE_${depPkg} ${enableVal})\n") endforeach() - # Include configurations of dependent external packages/TPLs + # Include configurations of dependent packages 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 "${extPkgConfigFileBaseDir}/${depTpl}") - string(APPEND configFileStr - "include(\"${cmakeTplDir}/${depTpl}Config.cmake\")\n") + "\n# Include configuration of dependent packages\n") + foreach(depPkg IN LISTS ${packageName}_LIB_ENABLED_DEPENDENCIES) + set(packageConfigBaseDir "") # Initially, no add include() + if (${depPkg}_PACKAGE_BUILD_STATUS STREQUAL "INTERNAL") + set(packageConfigBaseDir "${pkgConfigFileBaseDir}/${depPkg}") + elseif (${depPkg}_PACKAGE_BUILD_STATUS STREQUAL "EXTERNAL") + set(packageConfigBaseDir "${extPkgConfigFileBaseDir}/${depPkg}") + else() + message(FATAL_ERROR "ERROR: ${depPkg}_PACKAGE_BUILD_STATUS='${${depPkg}_PACKAGE_BUILD_STATUS}' invalid!") endif() - endforeach() - foreach(depTpl IN LISTS ${packageName}_LIB_OPTIONAL_DEP_TPLS) - if (${packageName}_ENABLE_${depTpl} AND TARGET ${depTpl}::all_libs) - set(cmakeTplDir "${extPkgConfigFileBaseDir}/${depTpl}") + if (packageConfigBaseDir) string(APPEND configFileStr - "include(\"${cmakeTplDir}/${depTpl}Config.cmake\")\n") + "include(\"${packageConfigBaseDir}/${depPkg}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) @@ -723,14 +731,10 @@ function(tribits_write_project_client_export_files) # of all their libraries/includes in the proper order for linking set(FULL_PACKAGE_SET "") set(FULL_LIBRARY_SET "") - set(FULL_INCLUDE_DIRS_SET "") - set(FULL_LIBRARY_DIRS_SET "") foreach(TRIBITS_PACKAGE ${PACKAGE_LIST}) if(${PROJECT_NAME}_ENABLE_${TRIBITS_PACKAGE}) list(APPEND FULL_PACKAGE_SET ${TRIBITS_PACKAGE}) list(APPEND FULL_LIBRARY_SET ${${TRIBITS_PACKAGE}_LIBRARIES}) - list(APPEND FULL_INCLUDE_DIRS_SET ${${TRIBITS_PACKAGE}_INCLUDE_DIRS}) - list(APPEND FULL_LIBRARY_DIRS_SET ${${TRIBITS_PACKAGE}_LIBRARY_DIRS}) endif() endforeach() @@ -747,27 +751,13 @@ function(tribits_write_project_client_export_files) # of all their libraries/includes in the proper order for linking set(FULL_TPL_SET "") set(FULL_TPL_LIBRARY_SET "") - set(FULL_TPL_INCLUDE_DIRS_SET "") - set(FULL_TPL_LIBRARY_DIRS_SET "") foreach(TPL ${TPL_LIST}) if(TPL_ENABLE_${TPL}) list(APPEND FULL_TPL_SET ${TPL}) list(APPEND FULL_TPL_LIBRARY_SET ${TPL_${TPL}_LIBRARIES}) - list(APPEND FULL_TPL_INCLUDE_DIRS_SET ${TPL_${TPL}_INCLUDE_DIRS}) - list(APPEND FULL_TPL_LIBRARY_DIRS_SET ${TPL_${TPL}_LIBRARY_DIRS}) endif() endforeach() - # it is possible that tpls are in the same directory, to keep from - # having a very long include path or library path we will strip out - # any duplicates. This shouldn't affect which include or library is - # found since the first instance of any path will be the one that is - # kept. - list(REMOVE_DUPLICATES FULL_TPL_INCLUDE_DIRS_SET) - list(REMOVE_DUPLICATES FULL_TPL_LIBRARY_DIRS_SET) - - set(${PROJECT_NAME}_CONFIG_TPL_INCLUDE_DIRS ${FULL_TPL_INCLUDE_DIRS_SET}) - set(${PROJECT_NAME}_CONFIG_TPL_LIBRARY_DIRS ${FULL_TPL_LIBRARY_DIRS_SET}) set(${PROJECT_NAME}_CONFIG_TPL_LIBRARIES ${FULL_TPL_LIBRARY_SET}) # @@ -778,11 +768,6 @@ function(tribits_write_project_client_export_files) # Generate a note discouraging editing of the Config.cmake file set(DISCOURAGE_EDITING "Do not edit: This file was generated automatically by CMake.") - # Config file for setting variables and finding include/library paths from - # the build directory - set(${PROJECT_NAME}_CONFIG_INCLUDE_DIRS ${FULL_INCLUDE_DIRS_SET}) - set(${PROJECT_NAME}_CONFIG_LIBRARY_DIRS ${FULL_LIBRARY_DIRS_SET}) - # Write the specification of the rpath if necessary. This is only needed if # we're building shared libraries. if(BUILD_SHARED_LIBS) @@ -835,6 +820,7 @@ include(\"${${TRIBITS_PACKAGE}_BINARY_DIR}/${TRIBITS_PACKAGE}Config.cmake\")") set(PDOLLAR "$") set(tribitsInstallationDir "${${PROJECT_NAME}_TRIBITS_DIR}/${TRIBITS_CMAKE_INSTALLATION_FILES_DIR}") + set(TRIBITS_PROJECT_INSTALL_INCLUDE_DIR "") configure_file( "${tribitsInstallationDir}/TribitsProjectConfigTemplate.cmake.in" "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" ) @@ -865,10 +851,6 @@ include(\"${${TRIBITS_PACKAGE}_BINARY_DIR}/${TRIBITS_PACKAGE}Config.cmake\")") foreach(PATH ${PATH_LIST}) set(RELATIVE_PATH "${RELATIVE_PATH}/..") endforeach() - set(${PROJECT_NAME}_CONFIG_INCLUDE_DIRS - "\${CMAKE_CURRENT_LIST_DIR}/${RELATIVE_PATH}/${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}") - set(${PROJECT_NAME}_CONFIG_LIBRARY_DIRS - "\${CMAKE_CURRENT_LIST_DIR}/${RELATIVE_PATH}/${${PROJECT_NAME}_INSTALL_LIB_DIR}") # Write the specification of the rpath if necessary. This is only needed if # we're building shared libraries. @@ -887,6 +869,13 @@ include(\"${${TRIBITS_PACKAGE}_BINARY_DIR}/${TRIBITS_PACKAGE}Config.cmake\")") set(PDOLLAR "$") # Hack used in configure file below + if (IS_ABSOLUTE "${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}") + set(TRIBITS_PROJECT_INSTALL_INCLUDE_DIR "${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}") + else() + set(TRIBITS_PROJECT_INSTALL_INCLUDE_DIR + "${CMAKE_INSTALL_PREFIX}/${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}") + endif() + configure_file( "${${PROJECT_NAME}_TRIBITS_DIR}/${TRIBITS_CMAKE_INSTALLATION_FILES_DIR}/TribitsProjectConfigTemplate.cmake.in" "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config_install.cmake" diff --git a/cmake/tribits/core/std_tpls/FindTPLMPI.cmake b/cmake/tribits/core/std_tpls/FindTPLMPI.cmake index b3a5bf4644c3..f4917fd6a050 100644 --- a/cmake/tribits/core/std_tpls/FindTPLMPI.cmake +++ b/cmake/tribits/core/std_tpls/FindTPLMPI.cmake @@ -50,3 +50,7 @@ if(WIN32 AND TPL_ENABLE_MPI) global_set(TPL_MPI_LIBRARIES ${MPI_LIBRARIES}) endif() +tribits_tpl_find_include_dirs_and_libraries(MPI) + +# NOTE: Above, we need to generate the MPI::all_libs target and the +# MPIConfig.cmake file that will also provide the MPI::all_libs target. diff --git a/cmake/tribits/core/utils/AddSubdirectories.cmake b/cmake/tribits/core/utils/AddSubdirectories.cmake index 5ce3615c5eb3..20ac8b164725 100644 --- a/cmake/tribits/core/utils/AddSubdirectories.cmake +++ b/cmake/tribits/core/utils/AddSubdirectories.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @MACRO: add_subdirectories() # # Macro that adds a list of subdirectories all at once (removes boiler-plate diff --git a/cmake/tribits/core/utils/AdvancedOption.cmake b/cmake/tribits/core/utils/AdvancedOption.cmake index 22eee54e1ebe..49eed3c915e2 100644 --- a/cmake/tribits/core/utils/AdvancedOption.cmake +++ b/cmake/tribits/core/utils/AdvancedOption.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @MACRO: advanced_option() # # Macro that sets an option and marks it as advanced (removes boiler-plate and diff --git a/cmake/tribits/core/utils/AdvancedSet.cmake b/cmake/tribits/core/utils/AdvancedSet.cmake index 1939e14e67b1..97cf6d2643c7 100644 --- a/cmake/tribits/core/utils/AdvancedSet.cmake +++ b/cmake/tribits/core/utils/AdvancedSet.cmake @@ -38,7 +38,6 @@ # @HEADER -# # @MACRO: advanced_set() # # Macro that sets a variable and marks it as advanced (removes boiler-plate diff --git a/cmake/tribits/core/utils/AppendCmndlineArgs.cmake b/cmake/tribits/core/utils/AppendCmndlineArgs.cmake index f444b3daecd6..f004a71c772a 100644 --- a/cmake/tribits/core/utils/AppendCmndlineArgs.cmake +++ b/cmake/tribits/core/utils/AppendCmndlineArgs.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @FUNCTION: append_cmndline_args() # # Utility function that appends command-line arguments to a variable of diff --git a/cmake/tribits/core/utils/AppendGlob.cmake b/cmake/tribits/core/utils/AppendGlob.cmake index 7576f2595cce..14eab3155da6 100644 --- a/cmake/tribits/core/utils/AppendGlob.cmake +++ b/cmake/tribits/core/utils/AppendGlob.cmake @@ -39,7 +39,7 @@ include(AppendSet) -# + # @MACRO: append_glob() # # Utility macro that does a ``file(GLOB ...)`` and appends to an existing list diff --git a/cmake/tribits/core/utils/AppendGlobalSet.cmake b/cmake/tribits/core/utils/AppendGlobalSet.cmake index 1280ffb2ae98..51251dc326e9 100644 --- a/cmake/tribits/core/utils/AppendGlobalSet.cmake +++ b/cmake/tribits/core/utils/AppendGlobalSet.cmake @@ -40,7 +40,7 @@ include(GlobalSet) include(AssertDefined) -# + # @FUNCTION: append_global_set() # # Utility macro that appends arguments to a global variable (reduces diff --git a/cmake/tribits/core/utils/AppendSet.cmake b/cmake/tribits/core/utils/AppendSet.cmake index 2ae8decbf560..592a6de189ab 100644 --- a/cmake/tribits/core/utils/AppendSet.cmake +++ b/cmake/tribits/core/utils/AppendSet.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @MACRO: append_set() # # Utility function to append elements to a variable (reduces boiler-plate diff --git a/cmake/tribits/core/utils/AppendStringVar.cmake b/cmake/tribits/core/utils/AppendStringVar.cmake index 5735e56cdcb4..9b4e553a1494 100644 --- a/cmake/tribits/core/utils/AppendStringVar.cmake +++ b/cmake/tribits/core/utils/AppendStringVar.cmake @@ -40,7 +40,7 @@ include(ConcatStrings) include(PrintVar) -# + # @FUNCTION: append_string_var() # # Append strings to an existing string variable (reduces boiler-place code and @@ -68,7 +68,6 @@ function(append_string_var STRING_VAR_OUT) endfunction() -# # @FUNCTION: append_string_var_ext() # # Append a single string to an existing string variable, ignoring ';' (reduces diff --git a/cmake/tribits/core/utils/AppendStringVarWithSep.cmake b/cmake/tribits/core/utils/AppendStringVarWithSep.cmake index b08a042e791e..c671ff582ea0 100644 --- a/cmake/tribits/core/utils/AppendStringVarWithSep.cmake +++ b/cmake/tribits/core/utils/AppendStringVarWithSep.cmake @@ -39,7 +39,7 @@ include(ConcatStrings) -# + # @FUNCTION: append_string_var_with_sep() # # Append strings to a given string variable, joining them using a separator diff --git a/cmake/tribits/core/utils/AssertDefined.cmake b/cmake/tribits/core/utils/AssertDefined.cmake index 6b60ed267ae9..a7918483ec32 100644 --- a/cmake/tribits/core/utils/AssertDefined.cmake +++ b/cmake/tribits/core/utils/AssertDefined.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @FUNCTION: assert_defined() # # Assert that a variable is defined and if not call ``message(SEND_ERROR @@ -81,6 +81,6 @@ function(assert_defined VARS) endforeach() endfunction() -# ToDo: The VARS arg This really needs to be repalced with ${ARGV}. I fear +# ToDo: The VARS arg This really needs to be replaced with ${ARGV}. I fear # that only the first arg passed in is asserted. However, to change this now # is breaking backward compatibility. diff --git a/cmake/tribits/core/utils/CombinedOption.cmake b/cmake/tribits/core/utils/CombinedOption.cmake index 6d5480931509..2cf0c8dd3d13 100644 --- a/cmake/tribits/core/utils/CombinedOption.cmake +++ b/cmake/tribits/core/utils/CombinedOption.cmake @@ -42,7 +42,6 @@ include(MultilineSet) include(ConcatStrings) -# # @FUNCTION: combined_option() # # Set up a ``BOOL`` cache variable (i.e. an option) based on a set of diff --git a/cmake/tribits/core/utils/ConcatStrings.cmake b/cmake/tribits/core/utils/ConcatStrings.cmake index 0f49ac1a15ca..a2fdc3c41ae7 100644 --- a/cmake/tribits/core/utils/ConcatStrings.cmake +++ b/cmake/tribits/core/utils/ConcatStrings.cmake @@ -40,7 +40,6 @@ include(PrintVar) -# # @FUNCTION: concat_strings() # # Concatenate a set of string arguments. diff --git a/cmake/tribits/core/utils/DriveAdvancedTest.cmake b/cmake/tribits/core/utils/DriveAdvancedTest.cmake index 628b4ed574c5..87a4a82308af 100644 --- a/cmake/tribits/core/utils/DriveAdvancedTest.cmake +++ b/cmake/tribits/core/utils/DriveAdvancedTest.cmake @@ -58,11 +58,29 @@ function(print_uptime PREFIX_STR) endfunction() -function(print_single_check_result MSG_BEGIN TEST_CASE_PASSED_IN) +function(print_single_check_result msgBegin TEST_CASE_PASSED_IN) if (TEST_CASE_PASSED_IN) - message("${MSG_BEGIN} [PASSED]") + message("${msgBegin} [PASSED]") else() - message("${MSG_BEGIN} [FAILED]") + message("${msgBegin} [FAILED]") + endif() +endfunction() + + +function(print_any_regex_pass_match msgBegin regexMatch) + if (regexMatch) + message("${msgBegin} [PASSED]") + else() + message("${msgBegin} [not matched]") + endif() +endfunction() + + +function(print_any_regex_fail_match msgBegin regexMatch) + if (regexMatch) + message("${msgBegin} [FAILED]") + else() + message("${msgBegin} [does not match]") endif() endfunction() @@ -160,10 +178,12 @@ macro(setup_and_run_test_idx_cmnd_block) # Set up the TEST_ command block join( TEST_CMND_STR " " TRUE ${TEST_${CMND_IDX}_CMND} ) + string(REPLACE "${LIST_SEPARATOR}" ";" TEST_CMND_STR "${TEST_CMND_STR}") message("Running: ${TEST_CMND_STR}\n") set(EXEC_CMND COMMAND ${TEST_${CMND_IDX}_CMND}) + string(REPLACE "${LIST_SEPARATOR}" "\\\;" EXEC_CMND "${EXEC_CMND}") - # Set up the workig directory that this TEST_ CMND block will run in + # Set up the working directory that this TEST_ CMND block will run in set(WORKING_DIR_SET) if (TEST_${CMND_IDX}_WORKING_DIRECTORY) @@ -247,16 +267,16 @@ macro(determine_test_idx_cmnd_block_pass_fail) "TEST_${CMND_IDX}: Pass criteria = Pass Any" ${TEST_CASE_PASSED} ) elseif (TEST_${CMND_IDX}_PASS_REGULAR_EXPRESSION) - string(REGEX MATCH "${TEST_${CMND_IDX}_PASS_REGULAR_EXPRESSION}" - MATCH_STR "${TEST_CMND_OUT}" ) - if (MATCH_STR) - set(TEST_CASE_PASSED TRUE) - else() - set(TEST_CASE_PASSED FALSE) - endif() - print_single_check_result( - "TEST_${CMND_IDX}: Pass criteria = Match REGEX {${TEST_${CMND_IDX}_PASS_REGULAR_EXPRESSION}}" - ${TEST_CASE_PASSED}) + set(TEST_CASE_PASSED FALSE) + foreach(REGEX_STR ${TEST_${CMND_IDX}_PASS_REGULAR_EXPRESSION}) + string(REGEX MATCH "${REGEX_STR}" MATCH_STR "${TEST_CMND_OUT}") + if (MATCH_STR) + set(TEST_CASE_PASSED TRUE) + endif() + print_any_regex_pass_match( + "TEST_${CMND_IDX}: Pass criteria = Match any REGEX {${REGEX_STR}}" + "${MATCH_STR}") + endforeach() elseif (TEST_${CMND_IDX}_PASS_REGULAR_EXPRESSION_ALL) set(TEST_CASE_PASSED TRUE) foreach(REGEX_STR ${TEST_${CMND_IDX}_PASS_REGULAR_EXPRESSION_ALL}) @@ -270,7 +290,7 @@ macro(determine_test_idx_cmnd_block_pass_fail) set(TEST_CASE_PASSED FALSE) endif() print_single_check_result( - "TEST_${CMND_IDX}: Pass criteria = Match REGEX {${REGEX_STR}}" + "TEST_${CMND_IDX}: Pass criteria = Match all REGEX {${REGEX_STR}}" ${THIS_REGEX_MATCHED} ) endforeach() else() @@ -286,14 +306,15 @@ macro(determine_test_idx_cmnd_block_pass_fail) # B) Check for failing regex matching? if (TEST_${CMND_IDX}_FAIL_REGULAR_EXPRESSION) - string(REGEX MATCH "${TEST_${CMND_IDX}_FAIL_REGULAR_EXPRESSION}" - MATCH_STR "${TEST_CMND_OUT}" ) - if (MATCH_STR) - set(TEST_CASE_PASSED FALSE) - endif() - print_single_check_result( - "TEST_${CMND_IDX}: Pass criteria = Not match REGEX {${TEST_${CMND_IDX}_FAIL_REGULAR_EXPRESSION}}" - ${TEST_CASE_PASSED} ) + foreach(REGEX_STR ${TEST_${CMND_IDX}_FAIL_REGULAR_EXPRESSION}) + string(REGEX MATCH "${REGEX_STR}" MATCH_STR "${TEST_CMND_OUT}") + if (MATCH_STR) + set(TEST_CASE_PASSED FALSE) + endif() + print_any_regex_fail_match( + "TEST_${CMND_IDX}: Pass criteria = Not match REGEX {${REGEX_STR}}" + "${MATCH_STR}") + endforeach() endif() # C) Check for return code always 0? diff --git a/cmake/tribits/core/utils/DualScopeAppendCmndlineArgs.cmake b/cmake/tribits/core/utils/DualScopeAppendCmndlineArgs.cmake index 65c6738d8b65..4dd32caaa9b0 100644 --- a/cmake/tribits/core/utils/DualScopeAppendCmndlineArgs.cmake +++ b/cmake/tribits/core/utils/DualScopeAppendCmndlineArgs.cmake @@ -40,7 +40,7 @@ include(AppendCmndlineArgs) include(DualScopeSet) -# + # @MACRO: dual_scope_append_cmndline_args() # # Utility function that appends command-line arguments to a variable of diff --git a/cmake/tribits/core/utils/DualScopePrependCmndlineArgs.cmake b/cmake/tribits/core/utils/DualScopePrependCmndlineArgs.cmake index a4a8a627cd47..432c27f72251 100644 --- a/cmake/tribits/core/utils/DualScopePrependCmndlineArgs.cmake +++ b/cmake/tribits/core/utils/DualScopePrependCmndlineArgs.cmake @@ -40,7 +40,7 @@ include(PrependCmndlineArgs) include(DualScopeSet) -# + # @MACRO: dual_scope_prepend_cmndline_args() # # Utility function that prepends command-line arguments to a variable of diff --git a/cmake/tribits/core/utils/DualScopeSet.cmake b/cmake/tribits/core/utils/DualScopeSet.cmake index 8ea8ecb5fa06..e17234628acb 100644 --- a/cmake/tribits/core/utils/DualScopeSet.cmake +++ b/cmake/tribits/core/utils/DualScopeSet.cmake @@ -38,7 +38,6 @@ # @HEADER -# # @MACRO: dual_scope_set() # # Macro that sets a variable name both in the current scope and the diff --git a/cmake/tribits/core/utils/GlobalNullSet.cmake b/cmake/tribits/core/utils/GlobalNullSet.cmake index 728d06f06c4e..ae1125bc3012 100644 --- a/cmake/tribits/core/utils/GlobalNullSet.cmake +++ b/cmake/tribits/core/utils/GlobalNullSet.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @MACRO: global_null_set() # # Set a variable as a null internal global (cache) variable (removes diff --git a/cmake/tribits/core/utils/GlobalSet.cmake b/cmake/tribits/core/utils/GlobalSet.cmake index 7eb1ba20a421..b3c04aae0b20 100644 --- a/cmake/tribits/core/utils/GlobalSet.cmake +++ b/cmake/tribits/core/utils/GlobalSet.cmake @@ -38,7 +38,6 @@ # @HEADER -# # @MACRO: global_set() # # Set a variable as an internal global (cache) variable (removes boiler-plate diff --git a/cmake/tribits/core/utils/Join.cmake b/cmake/tribits/core/utils/Join.cmake index 0f9fe323bce1..288999b8e67d 100644 --- a/cmake/tribits/core/utils/Join.cmake +++ b/cmake/tribits/core/utils/Join.cmake @@ -38,7 +38,6 @@ # @HEADER -# # @FUNCTION: join() # # Join a set of strings into a single string using a join string. diff --git a/cmake/tribits/core/utils/MessageWrapper.cmake b/cmake/tribits/core/utils/MessageWrapper.cmake index cf7a0723de18..bdcd9e5e2966 100644 --- a/cmake/tribits/core/utils/MessageWrapper.cmake +++ b/cmake/tribits/core/utils/MessageWrapper.cmake @@ -68,11 +68,13 @@ include(GlobalSet) # verify that they say the right thing. # function(message_wrapper) - #message("MESSAGE_WRAPPER: ${ARGN}") + cmake_parse_arguments(PARSE_ARGV 0 FWD "" "" "") + #message("MESSAGE_WRAPPER: ${FWD_UNPARSED_ARGUMENTS}") if (MESSAGE_WRAPPER_UNIT_TEST_MODE) - global_set(MESSAGE_WRAPPER_INPUT "${MESSAGE_WRAPPER_INPUT}" ${ARGN}) + global_set(MESSAGE_WRAPPER_INPUT "${MESSAGE_WRAPPER_INPUT}" + ${FWD_UNPARSED_ARGUMENTS}) else() - message(${ARGN}) + message(${FWD_UNPARSED_ARGUMENTS}) endif() endfunction() diff --git a/cmake/tribits/core/utils/MultilineSet.cmake b/cmake/tribits/core/utils/MultilineSet.cmake index 923d65c5d217..dde0b471e424 100644 --- a/cmake/tribits/core/utils/MultilineSet.cmake +++ b/cmake/tribits/core/utils/MultilineSet.cmake @@ -38,7 +38,6 @@ # @HEADER -# # @FUNCTION: multiline_set() # # Function to set a single string by concatenating a list of separate strings diff --git a/cmake/tribits/core/utils/ParseVariableArguments.cmake b/cmake/tribits/core/utils/ParseVariableArguments.cmake index a3c278a7b8c0..92e1b060fd15 100644 --- a/cmake/tribits/core/utils/ParseVariableArguments.cmake +++ b/cmake/tribits/core/utils/ParseVariableArguments.cmake @@ -43,7 +43,7 @@ include(CMakeParseArguments) # natively implemented function cmake_parse_arguments() will get used! macro(parse_arguments_deprecated_warning) - message(WARNING "parse_arguments() is deprecated and should not be used." + message(DEPRECATION "parse_arguments() is deprecated and should not be used." " Instead use cmake_parse_arguments()") endmacro() @@ -57,7 +57,7 @@ function(parse_arguments_dump_output OUTPUT_STR) endif() endfunction() -# + # @MACRO: parse_arguments() # # Parse a set of macro/function input arguments into different lists. This @@ -248,12 +248,12 @@ endmacro() # NOTE: If the above function turns out to be a performance bottle neck, there # are a few things that could be done to improve performance. One thing you -# could do is repalce the o(len(arg_names)) and o(len(option_names)) lookups +# could do is replace the o(len(arg_names)) and o(len(option_names)) lookup # with o(1) lookups by creating CMake variables of the name # ${OUTER_FUNC_NAME}_arg_ and then just look of that variable exists # or not. That should use a hash function. That might actually slow things # down for short lists however so we would have to measure, measure, -# measure. I would have to pass in the function/macro name to disabiguate -# the variable names. It would really be better if cmake would provide a +# measure. I would have to pass in the function/macro name to disambiguate +# the variable names. It would really be better if CMake would provide a # sorted list find operation. That would make this much faster for large # numbers of argument and option names. diff --git a/cmake/tribits/core/utils/PrependCmndlineArgs.cmake b/cmake/tribits/core/utils/PrependCmndlineArgs.cmake index 29ee4c4b9110..08425aa2dcf6 100644 --- a/cmake/tribits/core/utils/PrependCmndlineArgs.cmake +++ b/cmake/tribits/core/utils/PrependCmndlineArgs.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @FUNCTION: prepend_cmndline_args() # # Utility function that prepends command-line arguments to a variable of diff --git a/cmake/tribits/core/utils/PrependGlobalSet.cmake b/cmake/tribits/core/utils/PrependGlobalSet.cmake index edd27338675c..1c827783ea14 100644 --- a/cmake/tribits/core/utils/PrependGlobalSet.cmake +++ b/cmake/tribits/core/utils/PrependGlobalSet.cmake @@ -40,7 +40,7 @@ include(GlobalSet) include(AssertDefined) -# + # @MACRO: prepend_global_set() # # Utility macro that prepends arguments to a global variable (reduces diff --git a/cmake/tribits/core/utils/PrependSet.cmake b/cmake/tribits/core/utils/PrependSet.cmake index 3b20d40d1411..0f022c83c779 100644 --- a/cmake/tribits/core/utils/PrependSet.cmake +++ b/cmake/tribits/core/utils/PrependSet.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @MACRO: prepend_set() # # Utility macro to prepend elements to a variable (reduces boiler-plate code). diff --git a/cmake/tribits/core/utils/PrintNonemptyVar.cmake b/cmake/tribits/core/utils/PrintNonemptyVar.cmake index 7c2b17ee4f15..064357adda3f 100644 --- a/cmake/tribits/core/utils/PrintNonemptyVar.cmake +++ b/cmake/tribits/core/utils/PrintNonemptyVar.cmake @@ -41,7 +41,6 @@ include(AssertDefined) include(PrintVar) -# # @FUNCTION: print_nonempty_var() # # Print a defined variable giving its name then value only if it is not empty. diff --git a/cmake/tribits/core/utils/PrintNonemptyVarWithSpaces.cmake b/cmake/tribits/core/utils/PrintNonemptyVarWithSpaces.cmake index cfb1c7148e06..64ebe2a579f8 100644 --- a/cmake/tribits/core/utils/PrintNonemptyVarWithSpaces.cmake +++ b/cmake/tribits/core/utils/PrintNonemptyVarWithSpaces.cmake @@ -40,7 +40,7 @@ include(AssertDefined) include(AppendStringVarWithSep) -# + # @FUNCTION: print_nonempty_var_with_spaces() # # Print a defined variable giving its name then value printed with spaces diff --git a/cmake/tribits/core/utils/PrintVarWithSpaces.cmake b/cmake/tribits/core/utils/PrintVarWithSpaces.cmake new file mode 100644 index 000000000000..356826756a94 --- /dev/null +++ b/cmake/tribits/core/utils/PrintVarWithSpaces.cmake @@ -0,0 +1,66 @@ +# @HEADER +# ************************************************************************ +# +# TriBITS: Tribal Build, Integrate, and Test System +# Copyright 2013 Sandia Corporation +# +# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +# the U.S. Government retains certain rights in this software. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Corporation nor the names of the +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# ************************************************************************ +# @HEADER + +include(AssertDefined) +include(AppendStringVarWithSep) + + +# @FUNCTION: print_var_with_spaces() +# +# Print a defined variable giving its name then value printed with spaces +# instead of ``';'``. +# +# Usage:: +# +# print_var_with_spaces( ) +# +# Prints the variable as:: +# +# : ... +# +# If ``$`` is ``TRUE`` on input, then the variable is not +# touched. If however, the variable ``$`` is not ``TRUE`` on +# input, then it is set to ``TRUE`` on output. +# +function(print_var_with_spaces VARIBLE_NAME PRINTED_VAR_OUT) + assert_defined(VARIBLE_NAME) + string(REPLACE ";" " " OUTSTR "${${VARIBLE_NAME}}") + message("-- ${VARIBLE_NAME}: ${OUTSTR}") + set(${PRINTED_VAR_OUT} TRUE PARENT_SCOPE) +endfunction() diff --git a/cmake/tribits/core/utils/RemoveGlobalDuplicates.cmake b/cmake/tribits/core/utils/RemoveGlobalDuplicates.cmake index 69ee668c46e7..f43ca43c89d2 100644 --- a/cmake/tribits/core/utils/RemoveGlobalDuplicates.cmake +++ b/cmake/tribits/core/utils/RemoveGlobalDuplicates.cmake @@ -40,7 +40,7 @@ include(AssertDefined) include(GlobalSet) -# + # @FUNCTION: remove_global_duplicates() # # Remove duplicate elements from a global list variable (removes boiler-plate diff --git a/cmake/tribits/core/utils/SetAndIncDirs.cmake b/cmake/tribits/core/utils/SetAndIncDirs.cmake index a305b424debe..80d4f688c40b 100644 --- a/cmake/tribits/core/utils/SetAndIncDirs.cmake +++ b/cmake/tribits/core/utils/SetAndIncDirs.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @MACRO: set_and_inc_dirs() # # Set a variable to an include directory and call ``include_directories()`` diff --git a/cmake/tribits/core/utils/SetCacheOnOffEmpty.cmake b/cmake/tribits/core/utils/SetCacheOnOffEmpty.cmake index caa3b1d3b493..0d9970731f54 100644 --- a/cmake/tribits/core/utils/SetCacheOnOffEmpty.cmake +++ b/cmake/tribits/core/utils/SetCacheOnOffEmpty.cmake @@ -38,7 +38,6 @@ # @HEADER -# # @FUNCTION: set_cache_on_off_empty() # # Usage:: diff --git a/cmake/tribits/core/utils/SetDefault.cmake b/cmake/tribits/core/utils/SetDefault.cmake index 3e2cdae73d28..87a25e275a29 100644 --- a/cmake/tribits/core/utils/SetDefault.cmake +++ b/cmake/tribits/core/utils/SetDefault.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @MACRO: set_default() # # Give a local variable a default value if a non-empty value is not already diff --git a/cmake/tribits/core/utils/SetDefaultAndFromEnv.cmake b/cmake/tribits/core/utils/SetDefaultAndFromEnv.cmake index 7f604c378f04..b407b571052a 100644 --- a/cmake/tribits/core/utils/SetDefaultAndFromEnv.cmake +++ b/cmake/tribits/core/utils/SetDefaultAndFromEnv.cmake @@ -38,11 +38,10 @@ # @HEADER - include(SetDefault) include(PrintVar) -# + # @MACRO: set_default_and_from_env() # # Set a default value for a local variable and override from an environment diff --git a/cmake/tribits/core/utils/Split.cmake b/cmake/tribits/core/utils/Split.cmake index 0a5f1ceb2b82..e18250c4b990 100644 --- a/cmake/tribits/core/utils/Split.cmake +++ b/cmake/tribits/core/utils/Split.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @FUNCTION: split() # # Split a string variable into a string array/list variable. diff --git a/cmake/tribits/core/utils/TimingUtils.cmake b/cmake/tribits/core/utils/TimingUtils.cmake index 19d39b53ea85..a83445663f02 100644 --- a/cmake/tribits/core/utils/TimingUtils.cmake +++ b/cmake/tribits/core/utils/TimingUtils.cmake @@ -46,7 +46,7 @@ include(Split) -# + # @FUNCTION: timer_get_raw_seconds() # # Return the raw time in seconds (nano-second accuracy) since epoch, i.e., @@ -76,7 +76,6 @@ function(timer_get_raw_seconds SECONDS_DEC_OUT) endfunction() -# # @FUNCTION: timer_get_rel_seconds() # # Return the relative time between start and stop seconds. @@ -114,7 +113,6 @@ function(timer_get_rel_seconds ABS_SECONDS_DEC_START endfunction() -# # @FUNCTION: timer_print_rel_time() # # Print the relative time between start and stop timers in ``ms`` diff --git a/cmake/tribits/core/utils/TribitsFilepathHelpers.cmake b/cmake/tribits/core/utils/TribitsFilepathHelpers.cmake index a367ff966d9c..1ee0489445c9 100644 --- a/cmake/tribits/core/utils/TribitsFilepathHelpers.cmake +++ b/cmake/tribits/core/utils/TribitsFilepathHelpers.cmake @@ -1,7 +1,7 @@ include(MessageWrapper) include(Split) -# + # @FUNCTION: tribits_dir_is_basedir() # # Function to determine if a given path is a base dir of another path. @@ -49,7 +49,6 @@ function(tribits_dir_is_basedir absBaseDir absFullDir isBaseDirVarOut) endfunction() -# # @FUNCTION: tribits_get_dir_array_below_base_dir() # # Returns the array of directories below a base directory. diff --git a/cmake/tribits/core/utils/TribitsParseArgumentsHelpers.cmake b/cmake/tribits/core/utils/TribitsParseArgumentsHelpers.cmake new file mode 100644 index 000000000000..75327668f67f --- /dev/null +++ b/cmake/tribits/core/utils/TribitsParseArgumentsHelpers.cmake @@ -0,0 +1,156 @@ +# @HEADER +# ************************************************************************ +# +# TriBITS: Tribal Build, Integrate, and Test System +# Copyright 2013 Sandia Corporation +# +# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +# the U.S. Government retains certain rights in this software. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Corporation nor the names of the +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# ************************************************************************ +# @HEADER + + +################################################################################ +# +# This module contains function to aid with the usage of +# cmake_parse_arguments(). +# +################################################################################ + + +include(MessageWrapper) + + +# @FUNCTION: tribits_check_for_unparsed_arguments() +# +# Check to see if there are unparsed arguments after calling +# ``cmake_parse_arguments()`` or ``tribits_parse_arguments_from_list()`` +# +# Usage:: +# +# tribits_check_for_unparsed_arguments([]) +# +# If `` is not given, it is assumed to be `PARSE`. +# +function(tribits_check_for_unparsed_arguments) + + if ("${ARGC}" GREATER 1) + message(FATAL_ERROR + "ERROR tribits_check_for_unparsed_arguments() passed arguments '${ARGV}' but only accepts 0 or 1 arguments (for )") + endif() + + set(prefix "PARSE") + foreach(arg ${ARGV}) + set(prefix "${arg}") + endforeach() + + if( NOT "${${prefix}_UNPARSED_ARGUMENTS}" STREQUAL "") + message_wrapper( + ${${PROJECT_NAME}_CHECK_FOR_UNPARSED_ARGUMENTS} + "Arguments passed in unrecognized. ${prefix}_UNPARSED_ARGUMENTS = '${${prefix}_UNPARSED_ARGUMENTS}'" + ) + endif() + +endfunction() + + +# @MACRO: tribits_assert_parse_arg_one_or_more_values() +# +# Assert that a set of parse arguments have at least one value +# +# Usage:: +# +# tribits_assert_parse_arg_one_or_more_values( ...) +# +macro(tribits_assert_parse_arg_one_or_more_values PREFIX) + foreach(ARGNAME ${ARGN}) + set(PREFIX_ARGNAME "${PREFIX}_${ARGNAME}") + list( LENGTH ${PREFIX_ARGNAME} ARG_NUM_VALS ) + if (ARG_NUM_VALS LESS 1) + message_wrapper(FATAL_ERROR + "ERROR: ${ARGNAME} must have at least one value!" ) + return() + # NOTE: The return() is needed in unit testing mode + endif() + endforeach() +endmacro() + + +# @MACRO: tribits_assert_parse_arg_zero_or_one_value() +# +# Assert a set of parse arguments have zero or one value +# +# Usage:: +# +# tribits_assert_parse_arg_zero_or_one_value( ...) +# +macro(tribits_assert_parse_arg_zero_or_one_value PREFIX) + foreach(ARGNAME ${ARGN}) + set(PREFIX_ARGNAME "${PREFIX}_${ARGNAME}") + if (NOT "${${PREFIX_ARGNAME}}" STREQUAL "") + list( LENGTH ${PREFIX_ARGNAME} ARG_NUM_VALS ) + if (ARG_NUM_VALS GREATER 1) + message_wrapper(FATAL_ERROR + "ERROR: ${ARGNAME}='${${PREFIX_ARGNAME}}' can not have more than one value!" ) + return() + # NOTE: The macro return() is needed in unit testing mode + endif() + endif() + endforeach() +endmacro() + + +# @MACRO: tribits_assert_parse_arg_one_value() +# +# Assert that a set of parse arguments have exactly one value +# +# Usage:: +# +# tribits_assert_parse_arg_one_value( ...) +# +macro(tribits_assert_parse_arg_one_value PREFIX) + foreach(ARGNAME ${ARGN}) + set(PREFIX_ARGNAME "${PREFIX}_${ARGNAME}") + if (NOT "${${PREFIX_ARGNAME}}" STREQUAL "") + list( LENGTH ${PREFIX_ARGNAME} ARG_NUM_VALS ) + if (NOT ARG_NUM_VALS EQUAL 1) + message_wrapper(FATAL_ERROR + "ERROR: ${ARGNAME}='${${PREFIX_ARGNAME}}' Must have exactly one value!" ) + return() + # NOTE: The macro return() is needed in unit testing mode + endif() + endif() + endforeach() +endmacro() + + +# NOTE: Above, we use macros for the assert functions with returns in unit +# test mode so that it will abort the calling function these are called from! diff --git a/cmake/tribits/core/utils/TribitsPrintList.cmake b/cmake/tribits/core/utils/TribitsPrintList.cmake new file mode 100644 index 000000000000..227ab9fcfa36 --- /dev/null +++ b/cmake/tribits/core/utils/TribitsPrintList.cmake @@ -0,0 +1,73 @@ +# @HEADER +# ************************************************************************ +# +# TriBITS: Tribal Build, Integrate, and Test System +# Copyright 2013 Sandia Corporation +# +# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +# the U.S. Government retains certain rights in this software. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Corporation nor the names of the +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# ************************************************************************ +# @HEADER + +include_guard() + +# @FUNCTION: tribits_print_list() +# +# Unconditionally the name and values of a list var. +# +# Usage:: +# +# tribits_print_list() +# +# This prints:: +# +# -- (size=): +# -- +# -- +# ... +# -- +# +# The variable ```` can be defined or undefined or empty. This uses +# an explicit "-- " line prefix so that it prints nice even on Windows CMake. +# +function(tribits_print_list listName) + list(LENGTH ${listName} len) + message("-- " "${listName} (size=${len})") + foreach(ele IN LISTS ${listName}) + message("-- " " '${ele}'") + endforeach() +endfunction() + +# NOTE: Above, I was not able to call message_wrapper() directly because it +# was removing the ';' in array arguments. This broke a bunch of unit tests. +# Therefore, I have to duplicate code and call it in two separate places. I +# have to admit that CMake behavior surprises me many times. This is not a +# great programming language. diff --git a/cmake/tribits/core/utils/TribitsStandardizePaths.cmake b/cmake/tribits/core/utils/TribitsStandardizePaths.cmake index 0a4f78e56d39..b442ce36bc4e 100644 --- a/cmake/tribits/core/utils/TribitsStandardizePaths.cmake +++ b/cmake/tribits/core/utils/TribitsStandardizePaths.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -# + # @FUNCTION: tribits_standardize_abs_paths() # # Function uses get_filename_component() to standardize a list of paths to be diff --git a/cmake/tribits/core/utils/TribitsStripQuotesFromStr.cmake b/cmake/tribits/core/utils/TribitsStripQuotesFromStr.cmake index 86abcfc51dfd..ff7edc0f36e2 100644 --- a/cmake/tribits/core/utils/TribitsStripQuotesFromStr.cmake +++ b/cmake/tribits/core/utils/TribitsStripQuotesFromStr.cmake @@ -1,4 +1,3 @@ -# # @FUNCTION: tribits_strip_quotes_from_str() # # Remove one set of quotes from the outside of a string if they exist. @@ -38,4 +37,4 @@ function(tribits_strip_quotes_from_str str_in str_var_out) # If we get here, there were not \" chars as the first and last char so # return the entire input string! set(${str_var_out} "${str_in}" PARENT_SCOPE) -endfunction() \ No newline at end of file +endfunction() diff --git a/cmake/tribits/core/utils/UnitTestHelpers.cmake b/cmake/tribits/core/utils/UnitTestHelpers.cmake index ce163a35ca73..0fecf477043b 100644 --- a/cmake/tribits/core/utils/UnitTestHelpers.cmake +++ b/cmake/tribits/core/utils/UnitTestHelpers.cmake @@ -40,6 +40,8 @@ include(CMakeParseArguments) include(GlobalSet) +cmake_policy(SET CMP0007 NEW) + # @MACRO: unittest_initialize_vars() # @@ -98,6 +100,50 @@ function(unittest_compare_const VAR_NAME CONST_VAL) endfunction() +# @FUNCTION: unittest_compare_list_ele_const() +# +# Perform a single unit test equality check for a single list element +# +# Usage:: +# +# unittest_compare_list_ele_const( ) +# +# If ``${[]} == ``, then the check passes, otherwise it +# fails. This prints the variable name and values and shows the test result. +# +# This updates the global variables ``UNITTEST_OVERALL_NUMRUN``, +# ``UNITTEST_OVERALL_NUMPASSED``, and ``UNITTEST_OVERALL_PASS`` which are used +# by the unit test harness system to assess overall pass/fail. +# +function(unittest_compare_list_ele_const listName idx expectedConstValue) + + math( EXPR NUMRUN ${UNITTEST_OVERALL_NUMRUN}+1 ) + global_set(UNITTEST_OVERALL_NUMRUN ${NUMRUN}) + + list(GET "${listName}" ${idx} listEleIdx) + set(listNameAndIdx "${listName}[${idx}]") + + message( + "\nCheck:\n" + " ${listNameAndIdx} =\n" + " [${listEleIdx}]\n" + " EQUALS:\n" + " [${expectedConstValue}]" + ) + + if ("${listEleIdx}" STREQUAL "${expectedConstValue}") + message(" [PASSED]\n") + math( EXPR NUMPASSED ${UNITTEST_OVERALL_NUMPASSED}+1 ) + global_set(UNITTEST_OVERALL_NUMPASSED ${NUMPASSED}) + else() + message(" [FAILED]\n") + global_set(UNITTEST_OVERALL_PASS FALSE) + message(WARNING "Stack trace for failed unit test") + endif() + +endfunction() + + # @FUNCTION: unittest_string_block_compare() # # Compare two string blocks (with multiple newlines '\n') line-by-line and @@ -115,11 +161,6 @@ endfunction() # 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 ) @@ -167,7 +208,7 @@ function(unittest_string_block_compare stringVar stringExpected) 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" + " only ${stringExpectedLen} lines and the next extra line is:\n" " '${nextLine}'\n" " [FAILED]\n" ) @@ -189,19 +230,18 @@ function(unittest_string_block_compare stringVar stringExpected) 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. +# Perform a series of regexes on a given string and update overall test +# statistics. # # Usage:: # # unittest_string_regex( -# +# "" # REGEX_STRINGS "" "" ... # ) # @@ -235,12 +275,65 @@ function(unittest_string_regex INPUT_STRING) string(REGEX MATCH "${REGEX}" REGEX_MATCH_RESULT "${INPUT_STRING}") + message(" Searching string:") + message(" '${INPUT_STRING}'") + if (REGEX_MATCH_RESULT) + message(" for REGEX {${REGEX}}: [PASSED]\n") + math( EXPR NUMPASSED ${UNITTEST_OVERALL_NUMPASSED}+1 ) + global_set(UNITTEST_OVERALL_NUMPASSED ${NUMPASSED}) + else() + message(" for REGEX {${REGEX}}: [FAILED]\n") + global_set(UNITTEST_OVERALL_PASS FALSE) + message(WARNING "Stack trace for failed unit test") + endif() + + endforeach() + +endfunction() + + +# @FUNCTION: unittest_string_var_regex() +# +# Perform a series of regexes on a given string variable and update overall +# test statistics. +# +# Usage:: +# +# unittest_string_var_regex( +# +# REGEX_STRINGS "" "" ... +# ) +# +# If the ``"${}"`` matches all of the of the regexs +# ``""``, ``""``, ..., then the test passes. Otherwise it fails. +# +# This updates the global variables ``UNITTEST_OVERALL_NUMRUN``, +# ``UNITTEST_OVERALL_NUMPASSED``, and ``UNITTEST_OVERALL_PASS`` which are used +# by the unit test harness system to assess overall pass/fail. +# +function(unittest_string_var_regex inputStringVar) + + cmake_parse_arguments(PARSE_ARGV 1 + PARSE "" "" # prefix, options, one_value_keywords + "REGEX_STRINGS" #multi_value_keywords + ) + tribits_check_for_unparsed_arguments(PARSE) + + foreach(REGEX ${PARSE_REGEX_STRINGS}) + + math( EXPR NUMRUN ${UNITTEST_OVERALL_NUMRUN}+1 ) + global_set(UNITTEST_OVERALL_NUMRUN ${NUMRUN}) + + string(REGEX MATCH "${REGEX}" REGEX_MATCH_RESULT "${${inputStringVar}}") + + message("Searching string variable value '${inputStringVar}':") + message(" '${${inputStringVar}}'") if (REGEX_MATCH_RESULT) - message(" Searching for REGEX {${REGEX}}: [PASSED]\n") + message(" for REGEX {${REGEX}}: [PASSED]\n") math( EXPR NUMPASSED ${UNITTEST_OVERALL_NUMPASSED}+1 ) global_set(UNITTEST_OVERALL_NUMPASSED ${NUMPASSED}) else() - message(" Searching for REGEX {${REGEX}}: [FAILED]\n") + message(" for REGEX {${REGEX}}: [FAILED]\n") global_set(UNITTEST_OVERALL_PASS FALSE) message(WARNING "Stack trace for failed unit test") endif() diff --git a/cmake/tribits/ctest_driver/TribitsAddDashboardTarget.cmake b/cmake/tribits/ctest_driver/TribitsAddDashboardTarget.cmake index 3e7b85dcd1fe..a9a8b6992f21 100644 --- a/cmake/tribits/ctest_driver/TribitsAddDashboardTarget.cmake +++ b/cmake/tribits/ctest_driver/TribitsAddDashboardTarget.cmake @@ -38,11 +38,14 @@ # @HEADER +################################################################################ # # This file gets included in the main TriBITS framework. It is put here to # reduce the size of the tribits/core/ directory. # +################################################################################ +include(TribitsGitRepoVersionInfo) # # Macro that drives a experimental 'dashboard' target @@ -95,6 +98,13 @@ macro(tribits_add_dashboard_target) append_set(EXPR_CMND_ARGS "${PROJECT_NAME}_WARNINGS_AS_ERRORS_FLAGS='${${PROJECT_NAME}_WARNINGS_AS_ERRORS_FLAGS}'") append_set(EXPR_CMND_ARGS "${PROJECT_NAME}_ENABLE_SECONDARY_TESTED_CODE=${${PROJECT_NAME}_ENABLE_SECONDARY_TESTED_CODE}") + # Determine if base repo is a git repo (by seeing if SHA1 can be extracted) + tribits_git_repo_sha1("${PROJECT_SOURCE_DIR}" projectGitRepoSha1 + FAILURE_MESSAGE_OUT projectGitRepoSha1FailureMsg) + if (projectGitRepoSha1 STREQUAL "") + append_set(EXPR_CMND_ARGS "CTEST_DO_UPDATES=OFF") + endif() + # Conditionally override options used only for the 'dashboard' target. # These options have no use in a a basic build/test so we don't want to # interfere with options users might set on the env. diff --git a/cmake/tribits/ctest_driver/TribitsCTestDriverCore.cmake b/cmake/tribits/ctest_driver/TribitsCTestDriverCore.cmake index e02d292c44df..8e1ad4eb9bc2 100644 --- a/cmake/tribits/ctest_driver/TribitsCTestDriverCore.cmake +++ b/cmake/tribits/ctest_driver/TribitsCTestDriverCore.cmake @@ -210,7 +210,6 @@ site_name(CTEST_SITE_DEFAULT) include(TribitsCTestDriverCoreHelpers) -# # @FUNCTION: tribits_ctest_driver() # # Universal platform-independent CTest/CDash driver function for CTest -S @@ -323,6 +322,7 @@ include(TribitsCTestDriverCoreHelpers) # * `Determining what testing-related actions are performed (tribits_ctest_driver())`_ # * `Determining how the results are displayed on CDash (tribits_ctest_driver())`_ # * `Specifying where the results go to CDash (tribits_ctest_driver())`_ +# * `Links to results on CDash (tribits_ctest_driver())`_ # * `Determining what TriBITS repositories are included (tribits_ctest_driver())`_ # * `All-at-once versus package-by-package mode (tribits_ctest_driver())`_ # * `Multiple ctest -S invocations (tribits_ctest_driver())`_ @@ -1166,6 +1166,63 @@ include(TribitsCTestDriverCoreHelpers) # not be performed. For more details, see `TRIBITS_2ND_CTEST_DROP_SITE`_ and # `TRIBITS_2ND_CTEST_DROP_LOCATION`_. # +# .. _Links to results on CDash (tribits_ctest_driver()): +# +# **Links to results on CDash (tribits_ctest_driver()):** +# +# Links to where the results will be posted on CDash are printed to STDOUT +# before it performs any actions and at end after all of the actions and +# submits have been completed. +# +# The results are printed to STDOUT in a section that looks like:: +# +# Link to this build's results on CDash: +# +# +# +# Link to all builds for this repo version on CDash: +# +# +# +# Link to all nonpassing tests for all builds for this repo version on CDash: +# +# +# +# The URL ```` is created from the buildname, site, and +# buildstartime fields which is known from the TAG file created by CTest. +# This allows access the results for this particular build on CDash by just +# clicking that link. +# +# The URL ```` provides a link to a CDash +# ``index.php`` query that includes all of the builds with the same base Git +# repo SHA1. This allows comparing the results of this build for other builds +# for this same version of the base Git repository. +# +# The URL ```` gives a link to a CDash +# ``queryTests.php`` query for all of the nonpassing tests for all of the +# builds with this same base project Git repo SHA1. This allows comparing +# test failures across all of the builds for the same base project Git repo +# version. +# +# NOTE: The links ```` and +# ```` are only provided if the base +# project Git repo has the ``.git/`` subdirectory and if ``git log`` +# successfully returns the SHA1 for that base Git repo. +# +# NOTE: The links ```` and +# ```` only consider the Git SHA1 of the +# base project Git repo. For multi-repo projects (see `Multi-Repository +# Support`_), you may get results for builds with different subrepo versions +# and therefore may be comparing apples and oranges. (Projects that commit a +# ``SubRepoVersion.txt`` file to their base Git repo or use Git +# Submodules will have unique base project Git repo SHA1s for different +# versions of the project's repos.) +# +# In addition, a text file ``CDashResults.txt`` will be written in the build +# directory that contains this same CDash link information shown above. This +# allows a process to cat the file ``CDashResults.txt`` to get links to the +# results on CDash. +# # .. _Determining what TriBITS repositories are included (tribits_ctest_driver()): # # **Determining what TriBITS repositories are included (tribits_ctest_driver()):** @@ -2093,9 +2150,15 @@ function(tribits_ctest_driver) ctest_start(${CTEST_START_ARGS}) tribits_remember_if_configure_attempted() - tribits_get_build_url_and_write_to_file(CDASH_BUILD_URL - "${CTEST_BINARY_DIRECTORY}/CDashBuildUrl.txt") - tribits_print_build_url("Results will be submitted on CDash at:" "${CDASH_BUILD_URL}") + + tribits_get_cdash_results_string_and_write_to_file( + CDASH_RESULTS_STRING_OUT CDASH_RESULTS_STRING + CDASH_RESULTS_FILE_OUT "${CTEST_BINARY_DIRECTORY}/CDashResults.txt" ) + message("Results will be submitted on CDash at the following links:\n\n" + "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n" + "${CDASH_RESULTS_STRING}\n" + "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n" + ) message( "\n***" @@ -2369,7 +2432,11 @@ function(tribits_ctest_driver) report_queued_errors() - tribits_print_build_url("See results submitted on CDash at:" "${CDASH_BUILD_URL}") + message("\nSee results submitted on CDash at the following links:\n\n" + "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n" + "${CDASH_RESULTS_STRING}\n" + "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n" + ) if ((NOT UPDATE_FAILED) AND ("${${PROJECT_NAME}_FAILED_PACKAGES}" STREQUAL "")) message( diff --git a/cmake/tribits/ctest_driver/TribitsCTestDriverCoreHelpers.cmake b/cmake/tribits/ctest_driver/TribitsCTestDriverCoreHelpers.cmake index ed329adf1b30..58ffc6264ddf 100644 --- a/cmake/tribits/ctest_driver/TribitsCTestDriverCoreHelpers.cmake +++ b/cmake/tribits/ctest_driver/TribitsCTestDriverCoreHelpers.cmake @@ -38,7 +38,7 @@ # @HEADER -include(TribitsGetCDashUrlFromTagFile) +include(TribitsGetCDashUrlsInsideCTestS) # Wrapper used for unit testing purposes diff --git a/cmake/tribits/ctest_driver/TribitsGetCDashUrlFromTagFile.cmake b/cmake/tribits/ctest_driver/TribitsGetCDashUrlFromTagFile.cmake deleted file mode 100644 index 944a598d688c..000000000000 --- a/cmake/tribits/ctest_driver/TribitsGetCDashUrlFromTagFile.cmake +++ /dev/null @@ -1,194 +0,0 @@ -include(TribitsReadTagFile) - - -# @FUNCTION: tribits_get_build_url_and_write_to_file() -# -# Construct the build URL on CDash given the site name, buildname, and -# buildstamp (take from the TAG file) from inside of a running ctest -S -# program and optionally write it to a file as well. -# -# Usage:: -# -# tribits_get_build_url_and_write_to_file( -# [ ] ) -# -# Here, ```` returns the CDash Build URL constructed from -# the following CMake variables already set in a ``ctest -S`` process: -# -# * ``CTEST_DROP_SITE`` -# * ``CTEST_DROP_LOCATION`` (``submit.php`` is replaced with ``index.php``) -# * ``CTEST_PROJECT_NAME`` -# * ``CTEST_SITE`` -# * ``CTEST_BUILD_NAME`` -# -# and the buildstamp read in from the file -# ``${CTEST_BINARY_DIRECTORY}/Testing/TAG``. -# -# Note that ```` will have ``https://`` added to the -# beginning of it so that GitHub Actions and other systems will put in a link -# to them. -# -# If the file name argument ```` is non-empty, then that -# CDash URL will be written to the file as a single line. -# -function(tribits_get_build_url_and_write_to_file cdashBuildUrlOut cdashBuildUrlFile) - tribits_get_cdash_index_php_from_drop_site_and_location( - CTEST_DROP_SITE "${CTEST_DROP_SITE}" - CTEST_DROP_LOCATION "${CTEST_DROP_LOCATION}" - INDEX_PHP_URL_OUT indexPhpUrl - ) - tribits_get_cdash_build_url_from_tag_file( - INDEX_PHP_URL "${indexPhpUrl}" - PROJECT_NAME "${CTEST_PROJECT_NAME}" - SITE_NAME "${CTEST_SITE}" - BUILD_NAME "${CTEST_BUILD_NAME}" - TAG_FILE "${CTEST_BINARY_DIRECTORY}/Testing/TAG" - CDASH_BUILD_URL_OUT cdashBuildUrl - ) - set(cdashBuildUrl "https://${cdashBuildUrl}") - if (cdashBuildUrlFile) - file(WRITE "${cdashBuildUrlFile}" "${cdashBuildUrl}") - endif() - set(${cdashBuildUrlOut} "${cdashBuildUrl}" PARENT_SCOPE) -endfunction() - - -# @FUNCTION: tribits_print_build_url() -# -# Print the URL on CDash where build results can be found. -# -# Usage:: -# -# tribits_print_build_url( ) -# -function(tribits_print_build_url msg cdashBuildUrl) - message("\n${msg}\n") - message(" ${cdashBuildUrl}\n") -endfunction() - - -# @FUNCTION: tribits_get_cdash_build_url_from_tag_file() -# -# Create CDash index.php URL from the build parts. -# -# Usage:: -# -# tribits_get_cdash_build_url_from_tag_file( -# INDEX_PHP_URL -# PROJECT_NAME -# SITE_NAME -# BUILD_NAME -# TAG_FILE -# CDASH_BUILD_URL_OUT -# ) -# -# Note that spaces are allowed ```` or ```` and those -# will be handled correctly to produce a valid URL. -# -function(tribits_get_cdash_build_url_from_tag_file) - # Get arguments - cmake_parse_arguments( - PREFIX #prefix - "" #options - "INDEX_PHP_URL;PROJECT_NAME;SITE_NAME;BUILD_NAME;TAG_FILE;CDASH_BUILD_URL_OUT" #one_value_keywords - "" #multi_value_keywords - ${ARGN} - ) - # Read in the tag file and get the build stamp from that - tribits_read_ctest_tag_file(${PREFIX_TAG_FILE} buildStartTime cdashGroup - cdashModel # The model is not used here but we still need to include this arg - ) - set(buildstamp "${buildStartTime}-${cdashGroup}") - # Build the URL and return it - tribits_get_cdash_build_url_from_parts( - INDEX_PHP_URL "${PREFIX_INDEX_PHP_URL}" - PROJECT_NAME "${PREFIX_PROJECT_NAME}" - SITE_NAME "${PREFIX_SITE_NAME}" - BUILD_NAME "${PREFIX_BUILD_NAME}" - BUILD_STAMP "${buildstamp}" - CDASH_BUILD_URL_OUT cdashBuildUrl - ) - set(${PREFIX_CDASH_BUILD_URL_OUT} "${cdashBuildUrl}" PARENT_SCOPE) -endfunction() - - -# @FUNCTION: tribits_get_cdash_index_php_from_drop_site_and_location() -# -# Get the CDash index.php URL from the input CTEST_DROP_SITE and -# CTEST_DROP_LOCATION vars used in a ctest -S script. -# -function(tribits_get_cdash_index_php_from_drop_site_and_location) - cmake_parse_arguments( - PREFIX #prefix - "" #options - "CTEST_DROP_SITE;CTEST_DROP_LOCATION;INDEX_PHP_URL_OUT" #one_value_keywords - "" #multi_value_keywords - ${ARGN} - ) - string(FIND "${PREFIX_CTEST_DROP_LOCATION}" "?" endOfSubmitPhpIdx) - string(SUBSTRING "${PREFIX_CTEST_DROP_LOCATION}" 0 ${endOfSubmitPhpIdx} submitPhpPart) - string(REPLACE "submit.php" "index.php" indexPhpPart "${submitPhpPart}") - set(indexPhpUrl "${PREFIX_CTEST_DROP_SITE}${indexPhpPart}") - SET(${PREFIX_INDEX_PHP_URL_OUT} "${indexPhpUrl}" PARENT_SCOPE) -endfunction() - - -# @FUNCTION: tribits_get_cdash_build_url_from_parts() -# -# Create CDash index.php URL from the build parts. -# -# Usage:: -# -# tribits_get_cdash_build_url_from_parts( -# INDEX_PHP_URL -# PROJECT_NAME -# SITE_NAME -# BUILD_NAME -# BUILD_STAMP -# CDASH_BUILD_URL_OUT -# ) -# -# Note that spaces are allowed ````, ```` or -# ```` and those will be handled correctly to produce a valid URL. -# -function(tribits_get_cdash_build_url_from_parts) - # Get arguments - cmake_parse_arguments( - PREFIX #prefix - "" #options - "INDEX_PHP_URL;PROJECT_NAME;SITE_NAME;BUILD_NAME;BUILD_STAMP;CDASH_BUILD_URL_OUT" #one_value_keywords - "" #multi_value_keywords - ${ARGN} - ) - # Do replacements for spaces and special chars in data - tribits_replace_chars_for_url("${PREFIX_PROJECT_NAME}" project) - tribits_replace_chars_for_url("${PREFIX_SITE_NAME}" site) - tribits_replace_chars_for_url("${PREFIX_BUILD_NAME}" buildname) - tribits_replace_chars_for_url("${PREFIX_BUILD_STAMP}" buildstamp) - # Build the URL - set(cdashIndexProj "${PREFIX_INDEX_PHP_URL}?project=${project}") - set(filtersPreTxt "filtercount=3&showfilters=1&filtercombine=and") - set(siteFlt "field1=site&compare1=61&value1=${site}") - set(buildnameFlt "field2=buildname&compare2=61&value2=${buildname}") - set(buildStampFlt "field3=buildstamp&compare3=61&value3=${buildstamp}") - set(cdashBuildUrl - "${cdashIndexProj}&${filtersPreTxt}&${siteFlt}&${buildnameFlt}&${buildStampFlt}") - set(${PREFIX_CDASH_BUILD_URL_OUT} "${cdashBuildUrl}" PARENT_SCOPE) -endfunction() - - -# Replace chars in a regular string for usage in a URL with CDash -# -function(tribits_replace_chars_for_url inputStr outputStrForUrlOutVar) - set(outputStrForUrl "${inputStr}") - string(REPLACE " " "%20" outputStrForUrl "${outputStrForUrl}") - string(REPLACE "+" "%2B" outputStrForUrl "${outputStrForUrl}") - set(${outputStrForUrlOutVar} "${outputStrForUrl}" PARENT_SCOPE) -endfunction() - -# LocalWords: GitHub tribits url buildname buildstamp -# LocalWords: tribits TRIBITS -# LocalWords: cmake CMake CMAKE -# LocalWords: ctest CTEST cdash CDash CDASH -# LocalWords: SUBSTRING -# LocalWords: endif endfunction diff --git a/cmake/tribits/ctest_driver/TribitsGetCDashUrlsInsideCTestS.cmake b/cmake/tribits/ctest_driver/TribitsGetCDashUrlsInsideCTestS.cmake new file mode 100644 index 000000000000..c6904f1195c9 --- /dev/null +++ b/cmake/tribits/ctest_driver/TribitsGetCDashUrlsInsideCTestS.cmake @@ -0,0 +1,527 @@ +# @HEADER +# ************************************************************************ +# +# TriBITS: Tribal Build, Integrate, and Test System +# Copyright 2013 Sandia Corporation +# +# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +# the U.S. Government retains certain rights in this software. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Corporation nor the names of the +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# ************************************************************************ +# @HEADER + + +include(PrintVar) +include(TribitsParseArgumentsHelpers) +include(TribitsReadTagFile) + + +################################################################################ +# +# This module contains functions for constructing CDash URLs to build and test +# results from inside of a CTest -S script. +# +################################################################################ + + +# @FUNCTION: tribits_get_cdash_results_string_and_write_to_file() +# +# Calls `tribits_get_cdash_results_urls_string()`_ and then writes the CDash +# URLs to a file. +# +# Usage:: +# +# tribits_get_cdash_results_string_and_write_to_file( +# [CDASH_RESULTS_STRING_OUT ] +# [CDASH_RESULTS_FILE_OUT ] +# ) +# +function(tribits_get_cdash_results_string_and_write_to_file) + # Parse args + cmake_parse_arguments( PARSE_ARGV 0 + PARSE "" "" # prefix, options, one_value_keywords + "CDASH_RESULTS_STRING_OUT;CDASH_RESULTS_FILE_OUT" # multi_value_keywords + ) + tribits_check_for_unparsed_arguments(PARSE) + tribits_assert_parse_arg_zero_or_one_value(PARSE CDASH_RESULTS_STRING_OUT + CDASH_RESULTS_FILE_OUT ) + # Get and set CDash results URL + tribits_get_cdash_results_urls_string(cdashResultsString) + if (PARSE_CDASH_RESULTS_STRING_OUT) + set(${PARSE_CDASH_RESULTS_STRING_OUT} "${cdashResultsString}" PARENT_SCOPE) + endif() + if (PARSE_CDASH_RESULTS_FILE_OUT) + file(WRITE "${PARSE_CDASH_RESULTS_FILE_OUT}" "${cdashResultsString}") + endif() +endfunction() + + +# @FUNCTION: tribits_get_cdash_results_urls_string() +# +# Call `tribits_get_cdash_results_urls()`_ and then construct a CDash URLs +# string fit for printing. +# +# Usage:: +# +# tribits_get_cdash_results_urls_string( +# +# ) +# +# Construct the build and test URLs on CDash given the site name, buildname, +# and buildstamp (taken from the TAG file) from inside of a running ctest -S +# program and optionally write it to a file as well. +# +function(tribits_get_cdash_results_urls_string cdashResultsUrlsStringOut) + tribits_get_cdash_results_urls( + CDASH_BUILD_URL_OUT cdashBuildUrl + CDASH_REVISION_BUILDS_URL_OUT cdashRevisionBuildsUrl + CDASH_REVISION_NONPASSING_TESTS_URL_OUT cdashRevisionNonpassingTestsUrl + ) + tribits_generate_cdash_results_string_from_urls( + CDASH_BUILD_URL "${cdashBuildUrl}" + CDASH_REVISION_BUILDS_URL "${cdashRevisionBuildsUrl}" + CDASH_REVISION_NONPASSING_TESTS_URL "${cdashRevisionNonpassingTestsUrl}" + CDASH_RESULTS_STRING_OUT cdashResultsUrlsString + ) + set(${cdashResultsUrlsStringOut} "${cdashResultsUrlsString}" PARENT_SCOPE) +endfunction() + + +# @FUNCTION: tribits_generate_cdash_results_string_from_urls() +# +# Generate the CDash results URL string given the individual URLs. +# +# Usage:: +# +# tribits_generate_cdash_results_string_from_urls( +# CDASH_BUILD_URL "" +# [CDASH_REVISION_BUILDS_URL ""] +# [CDASH_REVISION_NONPASSING_TESTS_URL ""] +# CDASH_RESULTS_STRING_OUT +# ) +# +# Takes the URLs returned from `tribits_get_cdash_results_urls()`_ and +# generates a string out of them which is set in the return var +# ````. +# +function(tribits_generate_cdash_results_string_from_urls) + # Parse args + cmake_parse_arguments(PARSE_ARGV 0 + PARSE "" "" # prefix, options, one_value_keywords + # multi_value_keywords + "CDASH_BUILD_URL;CDASH_REVISION_BUILDS_URL;CDASH_REVISION_NONPASSING_TESTS_URL;CDASH_RESULTS_STRING_OUT" + ) + tribits_check_for_unparsed_arguments() + tribits_assert_parse_arg_one_value(PARSE CDASH_BUILD_URL + CDASH_RESULTS_STRING_OUT) + tribits_assert_parse_arg_zero_or_one_value(PARSE CDASH_REVISION_BUILDS_URL + CDASH_REVISION_NONPASSING_TESTS_URL) + # Construct CDash results URLs string + set(cdashResultsString "") + string(APPEND cdashResultsString + "Link to this build's results on CDash:\n" + "\n" + " ${PARSE_CDASH_BUILD_URL}\n") + if (PARSE_CDASH_REVISION_BUILDS_URL) + string(APPEND cdashResultsString + "\nLink to all builds for this repo version on CDash:\n" + "\n" + " ${PARSE_CDASH_REVISION_BUILDS_URL}\n") + endif() + if (PARSE_CDASH_REVISION_NONPASSING_TESTS_URL) + string(APPEND cdashResultsString + "\nLink to all nonpassing tests for all builds for this repo version on CDash:\n" + "\n" + " ${PARSE_CDASH_REVISION_NONPASSING_TESTS_URL}\n") + endif() + # Set output + set(${PARSE_CDASH_RESULTS_STRING_OUT} ${cdashResultsString} PARENT_SCOPE) +endfunction() + + +# @FUNCTION: tribits_get_cdash_results_urls() +# +# Construct the build and test URLs on CDash given the site name, buildname, +# and buildstamp (taken from the TAG file) from inside of a running ctest -S +# program and optionally write it to a file as well. +# +# Usage:: +# +# tribits_get_cdash_results_urls( +# CDASH_BUILD_URL_OUT +# [CDASH_REVISION_BUILDS_URL_OUT ] +# [CDASH_REVISION_NONPASSING_TESTS_URL_OUT ] +# ) +# +# Here, the CDash URLs are constructed the following CMake variables already +# set in a ``ctest -S`` process: +# +# * ``CTEST_DROP_SITE`` +# * ``CTEST_DROP_LOCATION`` (``submit.php`` is replaced with ``index.php``) +# * ``CTEST_PROJECT_NAME`` +# * ``CTEST_SITE`` +# * ``CTEST_BUILD_NAME`` +# * ``CTEST_BINARY_DIRECTORY`` +# * ``CTEST_SOURCE_DIRECTORY`` +# +# and other information derived from that. +# +# The buildstamp is read in from the file +# ``${CTEST_BINARY_DIRECTORY}/Testing/TAG``. +# +# If available, the revision SHA1 is obtained from the git repo at +# ``CTEST_SOURCE_DIRECTORY`` if the directory +# ``${CTEST_SOURCE_DIRECTORY}/.git`` exists. If the base project source +# directory is not a git reposistory, then ```` and +# ````, if requested, will be set to +# empty. +# +# Note that the CDash URLs will have ``https://`` added to the beginning so +# that GitHub Actions and other systems will put in a hyperlink to them. +# +function(tribits_get_cdash_results_urls) + # Parse args + cmake_parse_arguments(PARSE_ARGV 0 + PARSE "" "" # prefix, options, one_value_keywords + # multi_value_keywords + "CDASH_BUILD_URL_OUT;CDASH_REVISION_BUILDS_URL_OUT;CDASH_REVISION_NONPASSING_TESTS_URL_OUT" + ) + tribits_check_for_unparsed_arguments(PARSE) + tribits_assert_parse_arg_one_value(PARSE CDASH_BUILD_URL_OUT) + tribits_assert_parse_arg_zero_or_one_value(PARSE CDASH_REVISION_BUILDS_URL_OUT + CDASH_REVISION_NONPASSING_TESTS_URL_OUT) + # Get the info + tribits_get_cdash_build_url(cdashBuildUrl) + tribits_git_repo_sha1("${CTEST_SOURCE_DIRECTORY}" gitRepoSha1 + FAILURE_MESSAGE_OUT gitRepoSha1FailureMsg) + if (gitRepoSha1) + tribits_get_cdash_site_from_drop_site_and_location( + CTEST_DROP_SITE "${CTEST_DROP_SITE}" + CTEST_DROP_LOCATION "${CTEST_DROP_LOCATION}" + CDASH_SITE_URL_OUT cdashSiteUrl + ) + tribits_get_cdash_revision_builds_url( + CDASH_SITE_URL "${cdashSiteUrl}" + PROJECT_NAME "${CTEST_PROJECT_NAME}" + GIT_REPO_SHA1 "${gitRepoSha1}" + CDASH_REVISION_BUILDS_URL_OUT cdashRevisionBuildsUrl + ) + tribits_get_cdash_revision_nonpassing_tests_url( + CDASH_SITE_URL "${cdashSiteUrl}" + PROJECT_NAME "${CTEST_PROJECT_NAME}" + GIT_REPO_SHA1 "${gitRepoSha1}" + CDASH_REVISION_NONPASSING_TESTS_URL_OUT cdashRevisionNonpassingTestsUrl + ) + else() + set(cdashRevisionBuildsUrl "") + set(cdashRevisionNonpassingTestsUrl "") + endif() + # Set the outputs + set(${PARSE_CDASH_BUILD_URL_OUT} "${cdashBuildUrl}" PARENT_SCOPE) + set(${PARSE_CDASH_REVISION_BUILDS_URL_OUT} "${cdashRevisionBuildsUrl}" + PARENT_SCOPE) + set(${PARSE_CDASH_REVISION_NONPASSING_TESTS_URL_OUT} "${cdashRevisionNonpassingTestsUrl}" + PARENT_SCOPE) +endfunction() + + +# @FUNCTION: tribits_get_cdash_revision_builds_url() +# +# Get the CDash URL for all builds with the same repo version SHA1 +# +# Usage:: +# +# tribits_get_cdash_revision_builds_url( +# CDASH_SITE_URL +# PROJECT_NAME +# GIT_REPO_SHA1 +# CDASH_REVISION_BUILDS_URL_OUT +# ) +# +function(tribits_get_cdash_revision_builds_url) + cmake_parse_arguments(PARSE_ARGV 0 + PARSE "" "" # prefix, options, one_value_keywords + # multi_value_keywords + "CDASH_SITE_URL;PROJECT_NAME;GIT_REPO_SHA1;CDASH_REVISION_BUILDS_URL_OUT" + ) + tribits_check_for_unparsed_arguments() + tribits_assert_parse_arg_one_value(PARSE CDASH_SITE_URL PROJECT_NAME + GIT_REPO_SHA1 CDASH_REVISION_BUILDS_URL_OUT) + set(${PARSE_CDASH_REVISION_BUILDS_URL_OUT} + "${PARSE_CDASH_SITE_URL}/index.php?project=${PARSE_PROJECT_NAME}&filtercount=1&showfilters=1&field1=revision&compare1=61&value1=${PARSE_GIT_REPO_SHA1}" + PARENT_SCOPE) +endfunction() + + +# @FUNCTION: tribits_get_cdash_revision_nonpassing_tests_url() +# +# Get the CDash URL for all non-passing tests with the same repo version SHA1 +# +# Usage:: +# +# tribits_get_cdash_revision_nonpassing_tests_url( +# CDASH_SITE_URL +# PROJECT_NAME +# GIT_REPO_SHA1 +# CDASH_REVISION_NONPASSING_TESTS_URL_OUT +# ) +# +function(tribits_get_cdash_revision_nonpassing_tests_url) + cmake_parse_arguments( PARSE_ARGV 0 + PARSE "" "" # prefix, options, one_value_keywords + # multi_value_keywords + "CDASH_SITE_URL;PROJECT_NAME;GIT_REPO_SHA1;CDASH_REVISION_NONPASSING_TESTS_URL_OUT" + ) + tribits_check_for_unparsed_arguments() + tribits_assert_parse_arg_one_value(PARSE CDASH_SITE_URL PROJECT_NAME + GIT_REPO_SHA1 CDASH_REVISION_NONPASSING_TESTS_URL_OUT) + set(${PARSE_CDASH_REVISION_NONPASSING_TESTS_URL_OUT} + "${PARSE_CDASH_SITE_URL}/queryTests.php?project=${PARSE_PROJECT_NAME}&filtercount=2&showfilters=1&filtercombine=and&field1=revision&compare1=61&value1=${PARSE_GIT_REPO_SHA1}&field2=status&compare2=62&value2=passed" + PARENT_SCOPE) +endfunction() + + +# @FUNCTION: tribits_get_cdash_build_url() +# +# Construct the build URL on CDash given the site name, buildname, and +# buildstamp (taken from the TAG file) from inside of a running ctest -S +# program. +# +# Usage:: +# +# tribits_get_cdash_build_url() +# +# Here, ```` returns the CDash Build URL constructed from +# the following CMake variables already set in a ``ctest -S`` process: +# +# * ``CTEST_DROP_SITE`` +# * ``CTEST_DROP_LOCATION`` (``submit.php`` is replaced with ``index.php``) +# * ``CTEST_PROJECT_NAME`` +# * ``CTEST_SITE`` +# * ``CTEST_BUILD_NAME`` +# +# and the buildstamp read in from the file +# ``${CTEST_BINARY_DIRECTORY}/Testing/TAG``. +# +# Note that ```` will have ``https://`` added to the +# beginning of it so that GitHub Actions and other systems will put in a link +# to them. +# +function(tribits_get_cdash_build_url cdashBuildUrlOut) + tribits_get_cdash_index_php_from_drop_site_and_location( + CTEST_DROP_SITE "${CTEST_DROP_SITE}" + CTEST_DROP_LOCATION "${CTEST_DROP_LOCATION}" + INDEX_PHP_URL_OUT indexPhpUrl + ) + tribits_get_cdash_build_url_from_tag_file( + INDEX_PHP_URL "${indexPhpUrl}" + PROJECT_NAME "${CTEST_PROJECT_NAME}" + SITE_NAME "${CTEST_SITE}" + BUILD_NAME "${CTEST_BUILD_NAME}" + TAG_FILE "${CTEST_BINARY_DIRECTORY}/Testing/TAG" + CDASH_BUILD_URL_OUT cdashBuildUrl + ) + set(${cdashBuildUrlOut} "${cdashBuildUrl}" PARENT_SCOPE) +endfunction() + + +# @FUNCTION: tribits_print_cdash_url() +# +# Print the URL on CDash where build results can be found. +# +# Usage:: +# +# tribits_print_cdash_url( ) +# +function(tribits_print_cdash_url msg cdashUrl) + message("\n${msg}\n") + message(" ${cdashUrl}\n") +endfunction() + + +# @FUNCTION: tribits_get_cdash_build_url_from_tag_file() +# +# Create CDash index.php URL from the build parts. +# +# Usage:: +# +# tribits_get_cdash_build_url_from_tag_file( +# INDEX_PHP_URL +# PROJECT_NAME +# SITE_NAME +# BUILD_NAME +# TAG_FILE +# CDASH_BUILD_URL_OUT +# ) +# +# Note that spaces are allowed ```` or ```` and those +# will be handled correctly to produce a valid URL. +# +function(tribits_get_cdash_build_url_from_tag_file) + # Get arguments + cmake_parse_arguments( + PREFIX #prefix + "" #options + "INDEX_PHP_URL;PROJECT_NAME;SITE_NAME;BUILD_NAME;TAG_FILE;CDASH_BUILD_URL_OUT" #one_value_keywords + "" #multi_value_keywords + ${ARGN} + ) + # Read in the tag file and get the build stamp from that + tribits_read_ctest_tag_file(${PREFIX_TAG_FILE} buildStartTime cdashGroup + cdashModel # The model is not used here but we still need to include this arg + ) + set(buildstamp "${buildStartTime}-${cdashGroup}") + # Build the URL and return it + tribits_get_cdash_build_url_from_parts( + INDEX_PHP_URL "${PREFIX_INDEX_PHP_URL}" + PROJECT_NAME "${PREFIX_PROJECT_NAME}" + SITE_NAME "${PREFIX_SITE_NAME}" + BUILD_NAME "${PREFIX_BUILD_NAME}" + BUILD_STAMP "${buildstamp}" + CDASH_BUILD_URL_OUT cdashBuildUrl + ) + set(${PREFIX_CDASH_BUILD_URL_OUT} "${cdashBuildUrl}" PARENT_SCOPE) +endfunction() + + +# @FUNCTION: tribits_get_cdash_index_php_from_drop_site_and_location() +# +# Get the CDash index.php URL from the input CTEST_DROP_SITE and +# CTEST_DROP_LOCATION vars used in a ctest -S script. +# +function(tribits_get_cdash_index_php_from_drop_site_and_location) + cmake_parse_arguments( + PREFIX #prefix + "" #options + "CTEST_DROP_SITE;CTEST_DROP_LOCATION;INDEX_PHP_URL_OUT" #one_value_keywords + "" #multi_value_keywords + ${ARGN} + ) + tribits_get_cdash_site_from_drop_site_and_location( + CTEST_DROP_SITE ${PREFIX_CTEST_DROP_SITE} + CTEST_DROP_LOCATION ${PREFIX_CTEST_DROP_LOCATION} + CDASH_SITE_URL_OUT cdashSiteUrl ) + SET(${PREFIX_INDEX_PHP_URL_OUT} "${cdashSiteUrl}/index.php" PARENT_SCOPE) +endfunction() + + +# @FUNCTION: tribits_get_cdash_site_from_drop_site_and_location() +# +# Get the full CDash site base URL from the input CTEST_DROP_SITE and +# CTEST_DROP_LOCATION vars used in a ctest -S script. +# +# Usage:: +# +# tribits_get_cdash_site_from_drop_site_and_location( +# CTEST_DROP_SITE +# CTEST_DROP_LOCATION +# CDASH_SITE_URL_OUT +# ) +# +function(tribits_get_cdash_site_from_drop_site_and_location) + # Parse args + cmake_parse_arguments(PARSE_ARGV 0 + PREFIX #prefix + "" #options + "CTEST_DROP_SITE;CTEST_DROP_LOCATION;CDASH_SITE_URL_OUT" #one_value_keywords + "" #multi_value_keywords + ) + tribits_check_for_unparsed_arguments(PREFIX) + tribits_assert_parse_arg_one_value(PREFIX CTEST_DROP_SITE) + tribits_assert_parse_arg_one_value(PREFIX CTEST_DROP_LOCATION) + tribits_assert_parse_arg_one_value(PREFIX CDASH_SITE_URL_OUT) + # Get the full CDash site from parts + string(FIND "${PREFIX_CTEST_DROP_LOCATION}" "?" beginningOfQueryString) + string(SUBSTRING "${PREFIX_CTEST_DROP_LOCATION}" 0 ${beginningOfQueryString} submitPhpPart) + string(REPLACE "/submit.php" "" endCDashUrl "${submitPhpPart}") + set(cdashSiteUrl "${PREFIX_CTEST_DROP_SITE}${endCDashUrl}") + set(${PREFIX_CDASH_SITE_URL_OUT} "https://${cdashSiteUrl}" PARENT_SCOPE) +endfunction() + + +# @FUNCTION: tribits_get_cdash_build_url_from_parts() +# +# Create CDash index.php URL from the build parts. +# +# Usage:: +# +# tribits_get_cdash_build_url_from_parts( +# INDEX_PHP_URL +# PROJECT_NAME +# SITE_NAME +# BUILD_NAME +# BUILD_STAMP +# CDASH_BUILD_URL_OUT +# ) +# +# Note that spaces are allowed ````, ```` or +# ```` and those will be handled correctly to produce a valid URL. +# +function(tribits_get_cdash_build_url_from_parts) + # Get arguments + cmake_parse_arguments( + PREFIX #prefix + "" #options + "INDEX_PHP_URL;PROJECT_NAME;SITE_NAME;BUILD_NAME;BUILD_STAMP;CDASH_BUILD_URL_OUT" #one_value_keywords + "" #multi_value_keywords + ${ARGN} + ) + # Do replacements for spaces and special chars in data + tribits_replace_chars_for_url("${PREFIX_PROJECT_NAME}" project) + tribits_replace_chars_for_url("${PREFIX_SITE_NAME}" site) + tribits_replace_chars_for_url("${PREFIX_BUILD_NAME}" buildname) + tribits_replace_chars_for_url("${PREFIX_BUILD_STAMP}" buildstamp) + # Build the URL + set(cdashIndexProj "${PREFIX_INDEX_PHP_URL}?project=${project}") + set(filtersPreTxt "filtercount=3&showfilters=1&filtercombine=and") + set(siteFlt "field1=site&compare1=61&value1=${site}") + set(buildnameFlt "field2=buildname&compare2=61&value2=${buildname}") + set(buildStampFlt "field3=buildstamp&compare3=61&value3=${buildstamp}") + set(cdashBuildUrl + "${cdashIndexProj}&${filtersPreTxt}&${siteFlt}&${buildnameFlt}&${buildStampFlt}") + set(${PREFIX_CDASH_BUILD_URL_OUT} "${cdashBuildUrl}" PARENT_SCOPE) +endfunction() + + +# Replace chars in a regular string for usage in a URL with CDash +# +function(tribits_replace_chars_for_url inputStr outputStrForUrlOutVar) + set(outputStrForUrl "${inputStr}") + string(REPLACE " " "%20" outputStrForUrl "${outputStrForUrl}") + string(REPLACE "+" "%2B" outputStrForUrl "${outputStrForUrl}") + set(${outputStrForUrlOutVar} "${outputStrForUrl}" PARENT_SCOPE) +endfunction() + +# LocalWords: GitHub tribits url buildname buildstamp +# LocalWords: tribits TRIBITS +# LocalWords: cmake CMake CMAKE +# LocalWords: ctest CTEST cdash CDash CDASH +# LocalWords: SUBSTRING +# LocalWords: endif endfunction diff --git a/cmake/tribits/ctest_driver/TribitsReadTagFile.cmake b/cmake/tribits/ctest_driver/TribitsReadTagFile.cmake index 6fac636d75cc..3073fb5200ba 100644 --- a/cmake/tribits/ctest_driver/TribitsReadTagFile.cmake +++ b/cmake/tribits/ctest_driver/TribitsReadTagFile.cmake @@ -1,3 +1,6 @@ +cmake_policy(SET CMP0007 NEW) + + # @FUNCTION: tribits_read_ctest_tag_file() # # Read in the /Testing/TAG file contents diff --git a/cmake/tribits/ctest_driver/experimental_build_test.cmake b/cmake/tribits/ctest_driver/experimental_build_test.cmake index 0b36b05e8f67..0c70ab4a7004 100644 --- a/cmake/tribits/ctest_driver/experimental_build_test.cmake +++ b/cmake/tribits/ctest_driver/experimental_build_test.cmake @@ -100,7 +100,7 @@ include(SetDefaultAndFromEnv) # All these can be changed by env vars set(CTEST_TEST_TYPE Experimental) -set(CTEST_DO_UPDATES FALSE) +set(CTEST_UPDATE_VERSION_ONLY TRUE) set(${PROJECT_NAME}_WARNINGS_AS_ERRORS_FLAGS "-Werror") # Don't change these in the env! diff --git a/cmake/tribits/doc/build_ref/TribitsBuildReferenceBody.rst b/cmake/tribits/doc/build_ref/TribitsBuildReferenceBody.rst index b5bcdc8f7f22..e1ec3a106799 100644 --- a/cmake/tribits/doc/build_ref/TribitsBuildReferenceBody.rst +++ b/cmake/tribits/doc/build_ref/TribitsBuildReferenceBody.rst @@ -218,7 +218,7 @@ b) Create a ``*.cmake`` file and point to it [Most Recommended]. MyConfigureOptions.cmake"`` makes it easy see where that variable got set when looking an the generated ``CMakeCache.txt`` file. Also, when this ``*.cmake`` fragment file changes, CMake will automatically trigger a - reconfgure during a make (because it knows about the file and will check its + reconfigure during a make (because it knows about the file and will check its time stamp, unlike when using ``-C .cmake``, see below). One can use the ``FORCE`` option in the ``set()`` commands shown above and @@ -277,7 +277,7 @@ b) Create a ``*.cmake`` file and point to it [Most Recommended]. contents of the ``*.cmake`` file reread on reconfigures, then one would want to use ``-C``. - 3) One can create and use parametrized ``*.cmake`` files that can be used + 3) One can create and use parameterized ``*.cmake`` files that can be used with multiple TriBITS projects. For example, one can have set statements like ``set(${PROJECT_NAME}_ENABLE_Fortran OFF ...)`` since ``PROJECT_NAME`` is known before the file is included. One can't do that with ``cmake -C`` @@ -506,7 +506,7 @@ pre-push testing. Enable all packages (and optionally all tests) ++++++++++++++++++++++++++++++++++++++++++++++ -To enable all defined packages and subpakages add the configure option:: +To enable all defined packages and subpackages add the configure option:: -D _ENABLE_ALL_PACKAGES=ON \ @@ -797,7 +797,7 @@ package. NOTES: -1) Setting ``CMAKE__FLAGS`` as a cache varible by the user on input be +1) Setting ``CMAKE__FLAGS`` as a cache variable by the user on input be listed after and therefore override, but will not replace, any internally set flags in ``CMAKE__FLAGS`` defined by the CMake system. To get rid of these project/TriBITS set compiler flags/options, see the below items. @@ -1583,7 +1583,11 @@ When the variables ``TPL__INCLUDE_DIRS`` and call ``find_package()`` internally by default and some may implement the default find in some other way. To know for sure, see the documentation for the specific TPL (e.g. looking in the ``FindTPL.cmake`` file to -be sure). +be sure). NOTE: if a given ``FindTPL.cmake`` would use +``find_package()`` by default, this can be disabled by configuring +with:: + + -D_ALLOW_PACKAGE_PREFIND=OFF Most TPLs, however, use a standard system for finding include directories and/or libraries based on the function @@ -2605,7 +2609,7 @@ To add timers to various configure steps, configure with:: -D _ENABLE_CONFIGURE_TIMING=ON -This will do baulk timing for the major configure steps which is independent +This will do bulk timing for the major configure steps which is independent of the number of packages in the project. To additionally add timing for the configure of individual packages, configure @@ -2803,7 +2807,7 @@ trigger warnings in CDash) about missing inserted/external packages will print regardless of the setting for ``_ASSERT_MISSING_PACKAGES``. Finally, ``_ENABLE_DEVELOPMENT_MODE=ON`` results in a number of -checks for invalid usage of TriBITS in the project's ``CMakeList.txt`` files +checks for invalid usage of TriBITS in the project's ``CMakeLists.txt`` files and will abort configure with a fatal error on the first check failure. This is appropriate for development mode when a project is clean of all such invalid usage patterns but there are times when it makes sense to report these @@ -3832,7 +3836,7 @@ 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. +files are placed in a separate directory to avoid being found by accident. Installation Testing @@ -3953,7 +3957,7 @@ Dashboard submissions ===================== All TriBITS projects have built-in support for submitting configure, build, -and test results to CDash using the custom ``dashbaord`` target. This uses +and test results to CDash using the custom ``dashboard`` target. This uses the `tribits_ctest_driver()`_ function internally set up to work correctly from an existing binary directory with a valid initial configure. The few of the advantages of using the custom TriBITS-enabled ``dashboard`` target over diff --git a/cmake/tribits/doc/guides/ReducedMockTrilinosOutput/ExpectedDependencies.txt b/cmake/tribits/doc/guides/ReducedMockTrilinosOutput/ExpectedDependencies.txt index 389c30f20245..64677aa6dbc4 100644 --- a/cmake/tribits/doc/guides/ReducedMockTrilinosOutput/ExpectedDependencies.txt +++ b/cmake/tribits/doc/guides/ReducedMockTrilinosOutput/ExpectedDependencies.txt @@ -27,3 +27,32 @@ Printing package dependencies ... -- Thyra_LIB_REQUIRED_DEP_PACKAGES: ThyraCoreLibs -- Thyra_LIB_OPTIONAL_DEP_PACKAGES: ThyraGoodStuff ThyraCrazyStuff ThyraEpetra ThyraEpetraExt +Dumping direct dependencies for each SE package ... + +-- Teuchos_LIB_ENABLED_DEPENDENCIES: BLAS LAPACK +-- Teuchos_LIB_ALL_DEPENDENCIES: BLAS LAPACK Boost MPI + +-- RTOp_LIB_ENABLED_DEPENDENCIES: Teuchos +-- RTOp_LIB_ALL_DEPENDENCIES: Teuchos + +-- Epetra_LIB_ENABLED_DEPENDENCIES: BLAS LAPACK +-- Epetra_LIB_ALL_DEPENDENCIES: BLAS LAPACK MPI + +-- Triutils_LIB_ALL_DEPENDENCIES: Epetra + +-- EpetraExt_LIB_ALL_DEPENDENCIES: Teuchos Epetra Triutils UMFPACK AMD PETSC + +-- ThyraCoreLibs_LIB_ENABLED_DEPENDENCIES: Teuchos RTOp +-- ThyraCoreLibs_LIB_ALL_DEPENDENCIES: Teuchos RTOp + +-- ThyraGoodStuff_LIB_ALL_DEPENDENCIES: ThyraCoreLibs + +-- ThyraCrazyStuff_LIB_ALL_DEPENDENCIES: ThyraGoodStuff + +-- ThyraEpetra_LIB_ENABLED_DEPENDENCIES: Epetra ThyraCoreLibs +-- ThyraEpetra_LIB_ALL_DEPENDENCIES: Epetra ThyraCoreLibs + +-- ThyraEpetraExt_LIB_ALL_DEPENDENCIES: ThyraEpetra EpetraExt + +-- Thyra_LIB_ENABLED_DEPENDENCIES: ThyraCoreLibs ThyraEpetra +-- Thyra_LIB_ALL_DEPENDENCIES: ThyraCoreLibs ThyraGoodStuff ThyraCrazyStuff ThyraEpetra ThyraEpetraExt diff --git a/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst b/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst index 3acfef8dcfe2..62a35e6f5543 100644 --- a/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst +++ b/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst @@ -760,7 +760,7 @@ These options are described below. A project can use the paths given the cmake module ``GNUInstallDirs`` by default by setting:: - set(${PROJECT_NAME}_USE_GNUINSTALLDIRS_DEFAULT FALSE) + set(${PROJECT_NAME}_USE_GNUINSTALLDIRS_DEFAULT TRUE) in the project's top-level `/CMakeLists.txt`_ file or its `/ProjectName.cmake`_ file. The default is ``FALSE``. diff --git a/cmake/tribits/doc/guides/TribitsGuidesBody.rst b/cmake/tribits/doc/guides/TribitsGuidesBody.rst index d8c947dd1660..fd4094662ae6 100644 --- a/cmake/tribits/doc/guides/TribitsGuidesBody.rst +++ b/cmake/tribits/doc/guides/TribitsGuidesBody.rst @@ -91,7 +91,7 @@ entire TriBITS system, the design philosophy that provides the foundation for TriBITS and be an expert in CMake, CTest, and CDash. Much of what needs to be known by a TriBITS System Developer and a TriBITS System Architect is contained in the document `TriBITS Maintainers Guide and Reference`_. The -rest of the the primary documentation for these roles will be in the TriBITS +rest of the primary documentation for these roles will be in the TriBITS CMake source code and various unit tests itself defined in `The TriBITS Test Package`_. At the time of this writing, there is currently there is only one TriBITS System Architect (who also happens to be the primary author of this @@ -315,21 +315,20 @@ CMake language behavior with respect to case sensitivity is also strange: * Calls of built-in and user-defined macros and functions is *case insensitive*! That is ``set(...)``, ``set(...)``, ``set()``, and all other combinations of upper and lower case characters for 'S', 'E', 'T' all call - the built-in ``set()`` function. The convention in TriBITS is to use all - caps for functions and macros (which was adopted by following the - conventions used in the early versions of TriBITS, see the `History of - TriBITS`_). The convention in CMake literature from Kitware seems to use - lower-case letters for functions and macros. + the built-in ``set()`` function. The convention in TriBITS is to use + ``lower_case_with_underscores()`` for functions and macros. * However, the names of CMake (local or cache/global) variables are *case sensitive*! That is, ``SOME_VAR`` and ``some_var`` are *different* variables. Built-in CMake variables tend use all caps with underscores (e.g. ``CMAKE_CURRENT_SOURCE_DIR``) but other built-in CMake variables tend to use mixed case with underscores (e.g. ``CMAKE_Fortran_FLAGS``). TriBITS - tends to use a similar naming convention where variables have mostly - upper-case letters except for parts that are proper nouns like the project, - package or TPL name (e.g. ``TribitsProj_TRIBITS_DIR``, - ``TriBITS_SOURCE_DIR``, ``Boost_INCLUDE_DIRS``). + tends to use a similar naming convention where project-level and cache + variables have mostly upper-case letters except for parts that are proper + nouns like the project, package or TPL name + (e.g. ``TribitsExProj_TRIBITS_DIR``, ``TriBITS_SOURCE_DIR``, + ``Boost_INCLUDE_DIRS``). Local variables and function/macro parameters can + use camelCase or lower_case_with_underscores. I don't know of any other programming language that uses different case sensitivity rules for variables and functions. However, because we must parse @@ -341,7 +340,7 @@ keyword-based arguments. Other mistakes that people make result from not understanding how CMake scopes variables and other entities. CMake defines a global scope (i.e. "cache" variables) and several nested local scopes that are created by -``add_subdirectory()`` and entering FUNCTIONS. See `dual_scope_set()`_ for a +``add_subdirectory()`` and entering functions. See `dual_scope_set()`_ for a short discussion of these scoping rules. And it is not just variables that can have local and global scoping rules. Other entities, like defines set with the built-in command ``add_definitions()`` only apply to the local scope @@ -700,7 +699,7 @@ The minimum CMake version must also be declared in the top-level version avoids strange errors that can occur when someone tries to build the project using a version of CMake that is too old. The project should set the minimum CMake version based on the CMake features used in that project's own -CMake files. The minimum CMake version required by TriBITS is defined in in +CMake files. The minimum CMake version required by TriBITS is defined in the variable ``TRIBITS_CMAKE_MINIMUM_REQUIRED`` (the current minimum version of CMake required by TriBITS is given at in `Getting set up to use CMake`_) . For example, the ``VERA/CMakeLists.txt`` file lists as its first line:: @@ -1578,7 +1577,24 @@ Other TriBITS macros/functions that can be called in this file include configured header file. This file will contain placeholders for variables that will be substitute at configure time with `tribits_configure_file()`_. This includes usage of ``#cmakedefine `` and other standard CMake -file configuration features. +file configuration features used by CMake's ``configure_file()`` command. + +An example of this file is shown in: + + `TribitsExampleProject`_/``packages/simple_cxx/cmake/SimpleCxx_config.h.in`` + +which is: + +.. include:: ../../examples/TribitsExampleProject/packages/simple_cxx/cmake/SimpleCxx_config.h.in + :literal: + +The variable ``HAVE_SIMPLECXX___INT64`` is set up in the base file +``SimpleCxx/CMakeLists.txt`` (see `/CMakeLists.txt`_ below). For +an explanation of ``HAVE_SIMPLECXX_DEBUG``, see `tribits_add_debug_option()`_. +For an explanation of ``HAVE_SIMPLECXX_SIMPLETPL``, see `How to add a new +TriBITS TPL dependency`_. For an explanation of +``@SIMPLECXX_DEPRECATED_DECLARATIONS@``, see `Setting up support for +deprecated code handling`_. **NOTE:** The file name ``_config.h.in`` is not at all fixed and the package can call this file anything it wants. Also, a package can @@ -1765,7 +1781,13 @@ defined before a (SE) Package's ``CMakeLists.txt`` file is processed: ``${PROJECT_NAME}_ENABLE_${PACKAGE_NAME}`` - Set to ``ON`` if the package is enabled and is to be processed. + Set to ``ON`` if the package is enabled and is to be processed or will be + set to ``ON`` or ``OFF`` automatically during enable/disable logic. For a + parent package that is not directly enabled but were one of its + subpackages is enabled, this will get set to ``ON`` (but that is not the + same as the parent package being directly enabled and therefore does not + imply that all of the required subpackages will be enabled, only that the + parent package will be processed). .. _${PACKAGE_NAME}_ENABLE_${OPTIONAL_DEP_PACKAGE_NAME}: @@ -1788,6 +1810,10 @@ defined before a (SE) Package's ``CMakeLists.txt`` file is processed: ``${OPTIONAL_DEP_PACKAGE_NAME}`` are both enabled at the project level! See `Support for optional SE package/TPL can be explicitly disabled`_. + **NOTE:** This variable will also be set for required dependencies as well + to allow for uniform processing such as when looping over the items in + `${PACKAGE_NAME}_LIB_ALL_DEPENDENCIES`_. + .. _${PACKAGE_NAME}_ENABLE_${OPTIONAL_DEP_TPL_NAME}: ``${PACKAGE_NAME}_ENABLE_${OPTIONAL_DEP_TPL_NAME}`` @@ -2159,12 +2185,11 @@ downstream dependencies`_). For each TPL referenced in a `/TPLsList.cmake`_ file using the macro `tribits_repository_define_tpls()`_, there must exist a file, typically called -``FindTPL${TPL_NAME}.cmake``, that once processed, produces the variables -``TPL_${TPL_NAME}_LIBRARIES`` and ``TPL_${TPL_NAME}_INCLUDE_DIRS``. Most -``FindTPL${TPL_NAME}.cmake`` files just use the function -`tribits_tpl_find_include_dirs_and_libraries()`_ the define the TriBITS TPL. -A simple example of such a file is the common TriBITS ``FindTPLPETSC.cmake`` -module which is currently: +``FindTPL${TPL_NAME}.cmake``, that once processed, produces the target +```${TPL_NAME}::all_libs``. Most ``FindTPL${TPL_NAME}.cmake`` files just use +the function `tribits_tpl_find_include_dirs_and_libraries()`_ to define the +TriBITS TPL. A simple example of such a file is the common TriBITS +``FindTPLPETSC.cmake`` module which is currently: .. include:: ../../common_tpls/FindTPLPETSC.cmake :literal: @@ -2227,11 +2252,10 @@ override and specialize how a TPL's include directories and libraries are determined. However, note that the TriBITS system does not require the usage of the function ``tribits_tpl_find_include_dirs_and_libraries()`` and does not even care about the TPL module name ``FindTPL${TPL_NAME}.cmake``. All that is -required is that some CMake file fragment exist that once included, will -define the variables ``${TPL_NAME}_LIBRARIES`` and -``${TPL_NAME}_INCLUDE_DIRS``. However, to be user friendly, such a CMake file -should respond to the same variables as accepted by the standard -``tribits_tpl_find_include_dirs_and_libraries()`` function. +required is that some CMake file fragment exist such that, once included, will +define the target ``${TPL_NAME}::all_libs``. However, to be user friendly, +such a CMake file should respond to the same variables as accepted by the +standard ``tribits_tpl_find_include_dirs_and_libraries()`` function. The core variables related to an enabled TPL are ``${TPL_NAME}_LIBRARIES``, ``${TPL_NAME}_INCLUDE_DIRS``, and ``${TPL_NAME}_TESTGROUP`` as defined in @@ -3473,8 +3497,16 @@ In more detail, these rules/behaviors are: `downstream`_ package declares a dependency on the SE package ``ThyraEpetra``, but not the parent package ``Thyra``, then the ``Thyra`` package (and its other subpackages and their dependencies) will not get - auto-enabled. This is a key aspect of the TriBITS SE package management - system. + auto-enabled. Also note that enabling a subset of the required + subpackages for a parent package does not require the enable of the other + required subpackages. For example, if both ``ThyraEpetra`` and + ``ThyraCore`` were both required subpackages of the parent package + ``Thyra``, then enabling ``ThyraCore`` does not require the enabling of + ``ThyraEpetra``. In these cases where one of a parent package's + subpackages is enabled for some reason, the final value of + ``${PROJECT_NAME}_ENABLE_${PACKAGE_NAME}`` will be set to ``ON`` (but this + does imply that all of the required subpackages will be enabled, only that + the parent package will be processed.) .. _Support for optional SE package/TPL is enabled by default: @@ -8140,3 +8172,33 @@ and then the installed versions of GCC, MPICH, CMake, and `gitdist`_ are placed in one's path. See `install_devtools.py --help`_ for more details. + + +.. Words specific to this documentation collection: + +.. LocalWords: projectDir packageDir + +.. TriBITS words: + +.. LocalWords: TRIBITS TriBITS tribits TPL TPLs +.. LocalWords: Subpackages subpackages Subpackage subpackage +.. LocalWords: PackagesList TPLsList +.. LocalWords: NativeRepositoriesList ExtraRepositoriesList +.. LocalWords: TribitsCTestDriverCore +.. LocalWords: TribitsExampleProject TribitsExProj DTribitsExProj SimpleCXX MixedLang +.. LocalWords: MockTrilinos +.. LocalWords: WithSubpackages WithSubpackagesA WithSubpackagesB WithSubpackagesC + +.. General CMake words: + +.. LocalWords: CMAKE CMake cmake CTEST CTest ctest CDash +.. LocalWords: CMakeLists CMakeCache CTestConfig +.. LocalWords: Kitware +.. LocalWords: endif foreach endforeach endmacro subdirectory +.. LocalWords: Fortran + + +.. Other general words: + +.. LocalWords: Trilinos executables Versioning versioning +.. LocalWords: Namespaced namespaced symlinks initializations diff --git a/cmake/tribits/doc/guides/UtilsMacroFunctionDocTemplate.rst b/cmake/tribits/doc/guides/UtilsMacroFunctionDocTemplate.rst index 72ff0b86d399..f5c4cf3970d2 100644 --- a/cmake/tribits/doc/guides/UtilsMacroFunctionDocTemplate.rst +++ b/cmake/tribits/doc/guides/UtilsMacroFunctionDocTemplate.rst @@ -29,6 +29,7 @@ @FUNCTION: print_nonempty_var() + @FUNCTION: print_nonempty_var_with_spaces() + @FUNCTION: print_var() + +@FUNCTION: print_var_with_spaces() + @FUNCTION: remove_global_duplicates() + @MACRO: set_and_inc_dirs() + @FUNCTION: set_cache_on_off_empty() + @@ -43,5 +44,6 @@ @FUNCTION: unittest_has_substr_const() + @FUNCTION: unittest_not_has_substr_const() + @FUNCTION: unittest_string_regex() + +@FUNCTION: unittest_string_var_regex() + @FUNCTION: unittest_file_regex() + @FUNCTION: unittest_final_result() + diff --git a/cmake/tribits/doc/guides/maintainers_guide/Makefile b/cmake/tribits/doc/guides/maintainers_guide/Makefile index 34d047b67a7c..161972de0c7e 100644 --- a/cmake/tribits/doc/guides/maintainers_guide/Makefile +++ b/cmake/tribits/doc/guides/maintainers_guide/Makefile @@ -13,7 +13,8 @@ include ../Makefile.common_generated_files EXTRA_FILES = \ Makefile \ $(BASE_NAME).rst \ - TribitsSystemMacroFunctionDoc.rst + TribitsSystemMacroFunctionDoc.rst \ + ../../../core/package_arch/TribitsSystemDataStructuresMacrosFunctions.rst all: $(BASE_NAME).html diff --git a/cmake/tribits/doc/sphinx/build_sphinx_docs.sh b/cmake/tribits/doc/sphinx/build_sphinx_docs.sh index 44e7749c1179..cb7fa74cb318 100755 --- a/cmake/tribits/doc/sphinx/build_sphinx_docs.sh +++ b/cmake/tribits/doc/sphinx/build_sphinx_docs.sh @@ -19,4 +19,4 @@ cd $SPHINX_DOC_BASE_DIR git clean -xdf -- . -python3 sphinx_rst_generator.py +python3 sphinx_rst_generator.py --copy-base-dir=../../.. diff --git a/cmake/tribits/doc/sphinx/combined_docs/index.html b/cmake/tribits/doc/sphinx/combined_docs/index.html index 1b4e4c97f0de..294ced08818b 100644 --- a/cmake/tribits/doc/sphinx/combined_docs/index.html +++ b/cmake/tribits/doc/sphinx/combined_docs/index.html @@ -122,7 +122,7 @@

TriBITS Documentation

diff --git a/cmake/tribits/doc/sphinx/sphinx_rst_generator.py b/cmake/tribits/doc/sphinx/sphinx_rst_generator.py index 7c5b05b5fd8e..d0dd375cc48e 100644 --- a/cmake/tribits/doc/sphinx/sphinx_rst_generator.py +++ b/cmake/tribits/doc/sphinx/sphinx_rst_generator.py @@ -1,3 +1,4 @@ +import argparse import os import re from shutil import copyfile, copytree @@ -5,250 +6,267 @@ import sys try: - doc_path = f"{os.sep}".join(os.path.abspath(__file__).split(os.sep)[:-2]) - sys.path.append(doc_path) - project_path = f"{os.sep}".join(os.path.abspath(__file__).split(os.sep)[:-4]) - sys.path.append(project_path) + doc_path = f"{os.sep}".join(os.path.abspath(__file__).split(os.sep)[:-2]) + sys.path.append(doc_path) + project_path = f"{os.sep}".join(os.path.abspath(__file__).split(os.sep)[:-4]) + sys.path.append(project_path) except Exception as e: - print(f"Can not add project path to system path! Exiting!\nERROR: {e}") - exit(1) + print(f"Can not add project path to system path! Exiting!\nERROR: {e}") + exit(1) def is_rst_file(file_path: str) -> bool: - """ Checks if file_path has .rst extension and if file_path is a file. - """ - if os.path.splitext(file_path)[-1] == '.rst' and os.path.isfile(file_path): - return True - return False - - -def change_paths_and_get_includes(source_file: str, src_file_path: str, - start_path: str, rst_dir: str, copy_file: bool = True) -> tuple: - """ Changes paths in source file, to be relative to sphinx_path or parent .rst - document. - Returns a tuple with .rst file content and includes(absolute_path, relative_to) - """ - with open(source_file, 'r') as src_file: - source_file_str = src_file.read() - source_file_list = list() - include_file_list = set() - for line in source_file_str.split('\n'): - splitted_line = line.split() - if 'include::' in splitted_line: - incl_index = splitted_line.index('include::') - path_index = incl_index + 1 - if len(splitted_line) > path_index: - new_line = [] - spaces_indented = line.find('.') # Below 'join()' statement adds a space! - if spaces_indented > 0: - new_line.append(' '*(spaces_indented-1)) - new_line.extend(splitted_line[:path_index]) - abs_path = os.path.abspath(os.path.join(src_file_path, - splitted_line[path_index])) - file_name = os.path.split(abs_path)[-1] - new_path = os.path.join(rst_dir, file_name) - if not os.path.isfile(new_path) and copy_file: - copyfile(src=abs_path, dst=new_path, follow_symlinks=True) - if is_rst_file(file_path=new_path): - include_file_list.add(abs_path) - rel_path_from_sphinx_dir = os.path.relpath(path=new_path, start=start_path) - new_line.append(rel_path_from_sphinx_dir) - new_line = ' '.join(new_line) - source_file_list.append(new_line) - else: - source_file_list.append(line) - else: - source_file_list.append(line) - abs_path_str = '\n'.join(source_file_list) + """ Checks if file_path has .rst extension and if file_path is a file. + """ + if os.path.splitext(file_path)[-1] == '.rst' and os.path.isfile(file_path): + return True + return False + + +def change_paths_and_get_includes(source_file: str, src_file_path: str, start_path: str, rst_dir: str, + tribits_base_dir: str, copy_file: bool = True) -> tuple: + """ Changes paths in source file, to be relative to sphinx_path or parent .rst document. + Returns a tuple with .rst file content and includes(absolute_path, relative_to). + """ + with open(source_file, 'r') as src_file: + source_file_str = src_file.read() + source_file_list = list() + include_file_list = set() + for line in source_file_str.split('\n'): + splitted_line = line.split() + if 'include::' in splitted_line: + incl_index = splitted_line.index('include::') + path_index = incl_index + 1 + if len(splitted_line) > path_index: + new_line = [] + spaces_indented = line.find('.') # Below 'join()' statement adds a space! + if spaces_indented > 0: + new_line.append(' ' * (spaces_indented - 1)) + new_line.extend(splitted_line[:path_index]) + abs_path = os.path.abspath(os.path.join(src_file_path, + splitted_line[path_index])) + tbd = tribits_base_dir.split(os.sep)[1:] + path_elem = abs_path.split(os.sep)[len(tbd) + 1:] + new_path = os.path.join(rst_dir, *path_elem) + os.makedirs(os.path.dirname(new_path), exist_ok=True) + if not os.path.isfile(new_path) and copy_file: + copyfile(src=abs_path, dst=new_path, follow_symlinks=True) + if is_rst_file(file_path=new_path): + include_file_list.add(abs_path) + rel_path_from_sphinx_dir = os.path.relpath(path=new_path, start=start_path) + new_line.append(rel_path_from_sphinx_dir) + new_line = ' '.join(new_line) + # Make sure version is formatted correctly: + if ':Version:' in new_line: + new_line = f":Version:\n {new_line.split(':Version:')[-1]}" + source_file_list.append(new_line) + else: + source_file_list.append(line) + else: + source_file_list.append(line) + abs_path_str = '\n'.join(source_file_list) - return abs_path_str, include_file_list + return abs_path_str, include_file_list class SphinxRstGenerator: - """ Changes include paths to relative to Sphinx build dir. Saves three main .rst docs - files inside Sphinx dir. - """ - - def __init__(self): - self.paths = { - 'maintainers_guide': { - 'src': os.path.join(doc_path, 'guides', 'maintainers_guide', - 'TribitsMaintainersGuide.rst'), - 'src_path': os.path.join(doc_path, 'guides', 'maintainers_guide'), - 'final_path': os.path.join(doc_path, 'sphinx', 'maintainers_guide', 'index.rst'), - 'sphinx_path': os.path.join(doc_path, 'sphinx', 'maintainers_guide'), - 'title': 'TriBITS Maintainers Guide and Reference'}, - 'users_guide': { - 'src': os.path.join(doc_path, 'guides', 'users_guide', 'TribitsUsersGuide.rst'), - 'src_path': os.path.join(doc_path, 'guides', 'users_guide'), - 'final_path': os.path.join(doc_path, 'sphinx', 'users_guide', 'index.rst'), - 'sphinx_path': os.path.join(doc_path, 'sphinx', 'users_guide'), - 'title': 'TriBITS Users Guide and Reference'}, - 'build_ref': { - 'src': os.path.join(doc_path, 'build_ref', 'TribitsBuildReference.rst'), - 'src_path': os.path.join(doc_path, 'build_ref'), - 'final_path': os.path.join(doc_path, 'sphinx', 'build_ref', 'index.rst'), - 'sphinx_path': os.path.join(doc_path, 'sphinx', 'build_ref'), - 'title': 'Generic TriBITS Project, Build, Test, and Install Reference Guide'}} - self.rst_dir = os.path.join(doc_path, 'sphinx', 'copied_files') - self.already_modified_files = set() - self.create_rst_dir() - self.build_docs() - - def create_rst_dir(self) -> None: - """ Creates copied_files directory in Sphinx directory. All include files will be copy - there. + """ Changes include paths to relative to Sphinx build dir. Saves three main .rst docs files inside Sphinx dir. """ - if self.rst_dir is not None: - if not os.path.exists(self.rst_dir): - os.makedirs(self.rst_dir) - @staticmethod - def build_docs() -> None: - """ Builds TriBITS documentation based on shell scripts. - """ - build_script_path = os.path.join(doc_path, 'build_docs.sh') - subprocess.call([build_script_path, '--skip-final-generation']) + def __init__(self): + self.paths = { + 'maintainers_guide': { + 'src': os.path.join(doc_path, 'guides', 'maintainers_guide', 'TribitsMaintainersGuide.rst'), + 'src_path': os.path.join(doc_path, 'guides', 'maintainers_guide'), + 'final_path': os.path.join(doc_path, 'sphinx', 'maintainers_guide', 'index.rst'), + 'sphinx_path': os.path.join(doc_path, 'sphinx', 'maintainers_guide'), + 'title': 'TriBITS Maintainers Guide and Reference'}, + 'users_guide': { + 'src': os.path.join(doc_path, 'guides', 'users_guide', 'TribitsUsersGuide.rst'), + 'src_path': os.path.join(doc_path, 'guides', 'users_guide'), + 'final_path': os.path.join(doc_path, 'sphinx', 'users_guide', 'index.rst'), + 'sphinx_path': os.path.join(doc_path, 'sphinx', 'users_guide'), + 'title': 'TriBITS Users Guide and Reference'}, + 'build_ref': { + 'src': os.path.join(doc_path, 'build_ref', 'TribitsBuildReference.rst'), + 'src_path': os.path.join(doc_path, 'build_ref'), + 'final_path': os.path.join(doc_path, 'sphinx', 'build_ref', 'index.rst'), + 'sphinx_path': os.path.join(doc_path, 'sphinx', 'build_ref'), + 'title': 'Generic TriBITS Project, Build, Test, and Install Reference Guide'}} + self.rst_dir = os.path.join(doc_path, 'sphinx', 'copied_files') + self.tribits_base_dir = self._cli() + self.already_modified_files = set() + self.create_rst_dir() + self.build_docs() - @staticmethod - def run_sphinx(cwd: str) -> None: - """ Runs Sphinx for each documentation. - """ - sphinx_command = ["make", "html"] - subprocess.call(sphinx_command, cwd=cwd) + @staticmethod + def _cli() -> str: + """ Support for common line arguments. """ + parser = argparse.ArgumentParser() + parser.add_argument("--copy-base-dir", help="Path to TriBITS base directory") + args = parser.parse_args() + abs_path = os.path.abspath(args.copy_base_dir) + if not abs_path or not os.path.exists(abs_path): + print(f"\n==> Path: `{abs_path}` is not correct!") + sys.exit(1) + print(f"Provided TriBITS base dir: {abs_path}") + return abs_path - def combine_documentation(self, docs_dir: str, change_url_to_landing_page: bool = True, - change_title_of_docs_main_page: bool = True, title: str = '' \ - ) -> None: - """ Renames and moves directory of generated static pages into combined directory - """ - new_name = os.path.split(docs_dir)[-1] - dir_to_rename = os.path.join(docs_dir, '_build', 'html') - new_name_path = os.path.join(docs_dir, '_build', new_name) - os.rename(src=dir_to_rename, dst=new_name_path) - static_dir = os.path.join(doc_path, 'sphinx', 'combined_docs', new_name) - copytree(src=new_name_path, dst=static_dir) - if change_url_to_landing_page: - self.change_url_to_landing_page(docs_static_dir=static_dir) - if change_title_of_docs_main_page: - self.change_title_of_docs_main_page(docs_static_dir=static_dir, new_title=title) - - @staticmethod - def change_url_to_landing_page(docs_static_dir: str) -> None: - """ Changes home url of documentation page, so it points to landing page. - """ - index_html = os.path.join(docs_static_dir, 'index.html') - with open(index_html, 'r') as index_read: - index_str = index_read.read() - repl_url = index_str.replace(' TriBITS', - ' TriBITS') - with open(index_html, 'w') as index_write: - index_write.write(repl_url) - - @staticmethod - def change_title_of_docs_main_page(docs_static_dir: str, new_title: str) -> None: - """ Changes home url of documentation page, so it points to landing page. - """ - index_html = os.path.join(docs_static_dir, 'index.html') - with open(index_html, 'r') as index_read: - index_str = index_read.read() - repl_url = re.sub('(1 Introduction —).+(documentation)', - f'{new_title}', index_str) - with open(index_html, 'w') as index_write: - index_write.write(repl_url) - - @staticmethod - def save_rst(file_path: str, file_content: str) -> None: - """ Saves .rst file with given pathh and content - """ - with open(file_path, 'w') as dest_file: - dest_file.write(file_content) + def create_rst_dir(self) -> None: + """ Creates copied_files directory in Sphinx directory. All include files will be copy + there. + """ + if self.rst_dir is not None: + if not os.path.exists(self.rst_dir): + os.makedirs(self.rst_dir) - def generate_rst(self, source_file: str, final_path: str = None, src_path: str = None, - start_path: str = None) -> set: - """ Generate correct links in .rst files, so Sphinx can find them - """ - if final_path is None: - overwrite_source = True - else: - overwrite_source = False + @staticmethod + def build_docs() -> None: + """ Builds TriBITS documentation based on shell scripts. + """ + build_script_path = os.path.join(doc_path, 'build_docs.sh') + subprocess.call([build_script_path, '--skip-final-generation']) - file_content, includes = change_paths_and_get_includes(source_file=source_file, - src_file_path=src_path, start_path=start_path, rst_dir=self.rst_dir) + @staticmethod + def run_sphinx(cwd: str) -> None: + """ Runs Sphinx for each documentation. + """ + sphinx_command = ["make", "html"] + subprocess.call(sphinx_command, cwd=cwd) - if overwrite_source: - self.save_rst(file_path=source_file, file_content=file_content) - else: - self.save_rst(file_path=final_path, file_content=file_content) + def combine_documentation(self, docs_dir: str, change_url_to_landing_page: bool = True, + change_title_of_docs_main_page: bool = True, title: str = '') -> None: + """ Renames and moves directory of generated static pages into combined directory + """ + new_name = os.path.split(docs_dir)[-1] + dir_to_rename = os.path.join(docs_dir, '_build', 'html') + new_name_path = os.path.join(docs_dir, '_build', new_name) + os.rename(src=dir_to_rename, dst=new_name_path) + static_dir = os.path.join(doc_path, 'sphinx', 'combined_docs', new_name) + copytree(src=new_name_path, dst=static_dir) + if change_url_to_landing_page: + self.change_url_to_landing_page(docs_static_dir=static_dir) + if change_title_of_docs_main_page: + self.change_title_of_docs_main_page(docs_static_dir=static_dir, new_title=title) - return includes + @staticmethod + def change_url_to_landing_page(docs_static_dir: str) -> None: + """ Changes home url of documentation page, so it points to landing page. + """ + index_html = os.path.join(docs_static_dir, 'index.html') + with open(index_html, 'r') as index_read: + index_str = index_read.read() + repl_url = index_str.replace(' TriBITS', + ' TriBITS') + with open(index_html, 'w') as index_write: + index_write.write(repl_url) - def remove_title_numbering(self) -> None: - """ Removes numbering from docs. - """ - for doc_name, sources in self.paths.items(): - - str_to_replace = '.. rubric::' - with open(sources.get('final_path'), 'r') as src_file: - org_str = src_file.read() - org_list = org_str.split('\n') - if org_list[0].startswith('====='): - del org_list[0] - if org_list[1].startswith('====='): - del org_list[1] - org_list[0] = f'{str_to_replace} {org_list[0]}' - mod_str = '\n'.join(org_list) - - with open(sources.get('final_path'), 'w') as dst_file: - dst_file.write(mod_str) - - def main(self): - """ Main routine goes for nested .rst docs - """ - child_rst = set() - for doc_name, sources in self.paths.items(): - includes = self.generate_rst(source_file=sources.get('src'), - src_path=sources.get('src_path'), - final_path=sources.get('final_path'), start_path=sources.get('sphinx_path')) - child_rst.update(includes) - self.already_modified_files.update(child_rst) - child_rst_lst = list(child_rst) - - sphinx_rel_path = self.paths.get('maintainers_guide').get('sphinx_path') - grand_child_rst = set() - for child in child_rst_lst: - file_name = os.path.split(child)[-1] - final_path = os.path.join(self.rst_dir, file_name) - src_path = os.path.split(child)[0] - includes_grand = self.generate_rst(source_file=child, src_path=src_path, - final_path=final_path, start_path=sphinx_rel_path) - grand_child_rst.update(includes_grand) - grand_child_rst_lst = \ - [gc_rst for gc_rst in grand_child_rst if gc_rst not in self.already_modified_files] - - grand_grand_child_rst = set() - for grand_child in grand_child_rst_lst: - file_name = os.path.split(grand_child)[-1] - final_path = os.path.join(self.rst_dir, file_name) - src_path = os.path.split(grand_child)[0] - includes_grand_grand = self.generate_rst(source_file=grand_child, src_path=src_path, - final_path=final_path, start_path=sphinx_rel_path) - grand_grand_child_rst.update(includes_grand_grand) - - if not grand_grand_child_rst: - print('DONE! ALL GOOD!\n') - else: - print('NOT DONE!\n') - - self.remove_title_numbering() - - print('===> Generating Sphinx documentation:\n') - for doc_name, sources in self.paths.items(): - cwd = sources.get('sphinx_path') - print(f'===> Generating {doc_name}\n') - self.run_sphinx(cwd=cwd) - self.combine_documentation(docs_dir=cwd, title=sources.get('title')) + @staticmethod + def change_title_of_docs_main_page(docs_static_dir: str, new_title: str) -> None: + """ Changes home url of documentation page, so it points to landing page. + """ + index_html = os.path.join(docs_static_dir, 'index.html') + with open(index_html, 'r') as index_read: + index_str = index_read.read() + repl_url = re.sub('(1 Introduction —).+(documentation)', + f'{new_title}', index_str) + with open(index_html, 'w') as index_write: + index_write.write(repl_url) + + @staticmethod + def save_rst(file_path: str, file_content: str) -> None: + """ Saves .rst file with given pathh and content + """ + with open(file_path, 'w') as dest_file: + dest_file.write(file_content) + + def generate_rst(self, source_file: str, final_path: str = None, src_path: str = None, + start_path: str = None) -> set: + """ Generate correct links in .rst files, so Sphinx can find them + """ + if final_path is None: + overwrite_source = True + else: + overwrite_source = False + + file_content, includes = change_paths_and_get_includes(source_file=source_file, src_file_path=src_path, + start_path=start_path, rst_dir=self.rst_dir, + tribits_base_dir=self.tribits_base_dir) + + if overwrite_source: + self.save_rst(file_path=source_file, file_content=file_content) + else: + self.save_rst(file_path=final_path, file_content=file_content) + + return includes + + def remove_title_numbering(self) -> None: + """ Removes numbering from docs. + """ + for doc_name, sources in self.paths.items(): + + str_to_replace = '.. rubric::' + with open(sources.get('final_path'), 'r') as src_file: + org_str = src_file.read() + org_list = org_str.split('\n') + if org_list[0].startswith('====='): + del org_list[0] + if org_list[1].startswith('====='): + del org_list[1] + org_list[0] = f'{str_to_replace} {org_list[0]}' + mod_str = '\n'.join(org_list) + + with open(sources.get('final_path'), 'w') as dst_file: + dst_file.write(mod_str) + + def main(self): + """ Main routine goes for nested .rst docs + """ + child_rst = set() + for doc_name, sources in self.paths.items(): + includes = self.generate_rst(source_file=sources.get('src'), src_path=sources.get('src_path'), + final_path=sources.get('final_path'), start_path=sources.get('sphinx_path')) + child_rst.update(includes) + self.already_modified_files.update(child_rst) + tbd = self.tribits_base_dir.split(os.sep)[1:] + child_rst_lst = list(child_rst) + + sphinx_rel_path = self.paths.get('maintainers_guide').get('sphinx_path') + grand_child_rst = set() + for child in child_rst_lst: + path_elem = child.split(os.sep)[len(tbd) + 1:] + final_path = os.path.join(self.rst_dir, *path_elem) + os.makedirs(os.path.dirname(final_path), exist_ok=True) + src_path = os.path.split(child)[0] + includes_grand = self.generate_rst(source_file=child, src_path=src_path, + final_path=final_path, start_path=sphinx_rel_path) + grand_child_rst.update(includes_grand) + grand_child_rst_lst = [gc_rst for gc_rst in grand_child_rst if gc_rst not in self.already_modified_files] + + grand_grand_child_rst = set() + for grand_child in grand_child_rst_lst: + path_elem = grand_child.split(os.sep)[len(tbd) + 1:] + final_path = os.path.join(self.rst_dir, *path_elem) + os.makedirs(os.path.dirname(final_path), exist_ok=True) + src_path = os.path.split(grand_child)[0] + includes_grand_grand = self.generate_rst(source_file=grand_child, src_path=src_path, + final_path=final_path, start_path=sphinx_rel_path) + grand_grand_child_rst.update(includes_grand_grand) + + if not grand_grand_child_rst: + print('DONE! ALL GOOD!\n') + else: + print('NOT DONE!\n') + + self.remove_title_numbering() + + print('===> Generating Sphinx documentation:\n') + for doc_name, sources in self.paths.items(): + cwd = sources.get('sphinx_path') + print(f'===> Generating {doc_name}\n') + self.run_sphinx(cwd=cwd) + self.combine_documentation(docs_dir=cwd, title=sources.get('title')) if __name__ == '__main__': - SphinxRstGenerator().main() + SphinxRstGenerator().main() diff --git a/cmake/tribits/examples/MockTrilinos/extraRepoTwoPackages/package2/cmake/Dependencies.cmake b/cmake/tribits/examples/MockTrilinos/extraRepoTwoPackages/package2/cmake/Dependencies.cmake index a3377de93729..66036414b250 100644 --- a/cmake/tribits/examples/MockTrilinos/extraRepoTwoPackages/package2/cmake/Dependencies.cmake +++ b/cmake/tribits/examples/MockTrilinos/extraRepoTwoPackages/package2/cmake/Dependencies.cmake @@ -37,7 +37,20 @@ # ************************************************************************ # @HEADER +if (EXTRA_REPO_PACKAGE2_ADD_TEST_DEPS) + set(ExRepo2Package2_TEST_DEPS + TEST_REQUIRED_PACKAGES Teuchos + TEST_OPTIONAL_PACKAGES RTOp Ex2Package1 + TEST_REQUIRED_TPLS Boost + TEST_OPTIONAL_TPLS MPI Boost + ) + # NOTE: Include duplicates above so that we can test removing them as well! +else() + set(ExRepo2Package2_TEST_DEPS "") +endif() + tribits_package_define_dependencies( LIB_REQUIRED_PACKAGES Teuchos LIB_OPTIONAL_PACKAGES Ex2Package1 + ${ExRepo2Package2_TEST_DEPS} ) diff --git a/cmake/tribits/examples/TribitsExampleApp2/AppHelperFuncs.cmake b/cmake/tribits/examples/TribitsExampleApp2/AppHelperFuncs.cmake index 0317c489ce41..cbed66bcd7e2 100644 --- a/cmake/tribits/examples/TribitsExampleApp2/AppHelperFuncs.cmake +++ b/cmake/tribits/examples/TribitsExampleApp2/AppHelperFuncs.cmake @@ -115,16 +115,14 @@ endmacro() # function(addAppDepCompileDefines) addAppDepCompileDefine("Package1") - #addAppDepCompileDefine("Package2") - #addAppDepCompileDefine("Package3") + 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() @@ -135,26 +133,47 @@ endfunction() # function(getExpectedAppDepsStr expectedDepsStrOut) - set(package1Deps "tpl1") + set(tpl1 "tpl1") # ToDo: Change to Tpl1{no deps}? + set(tpl2a "Tpl2a{${tpl1}}") + set(tpl2b "Tpl2b{no deps}") + set(tpl3 "Tpl3{${tpl2a}, ${tpl2b}}") + set(tpl4 "Tpl4{${tpl3}, ${tpl2a}, ${tpl2b}}") - set(depsStr "Package1: ${package1Deps}") + set(package1 "Package1{${tpl1}}") - set(${expectedDepsStrOut} "${depsStr}" PARENT_SCOPE) + if (Package2_ENABLE_Tpl3) + set(package2_tpl3_deps_str ", ${tpl3}") + else() + set(package2_tpl3_deps_str "") + endif() + set(package2 "Package2{${package1}${package2_tpl3_deps_str}}") -endfunction() + if (Package3_ENABLE_Package2) + set(package3_package2_deps_str "${package2}, ") + else() + set(package3_package2_deps_str "") + endif() + if (Package3_ENABLE_Tpl4) + set(package3_tpl4_deps_str "${tpl4}, ") + else() + set(package3_tpl4_deps_str "") + endif() + set(package3 + "Package3{${package3_package2_deps_str}${package1}, ${package3_tpl4_deps_str}${tpl2a}, ${tpl2b}}") + + if (TARGET Package3::all_libs) + set(depsStr "${package3}") + elseif (TARGET Package2::all_libs) + set(depsStr "${package2}") + elseif (TARGET Package1::all_libs) + set(depsStr "${package1}") + else() + message("No package targets exist!") + set(depsStr "no deps") + endif() + set(${expectedDepsStrOut} "${depsStr}" PARENT_SCOPE) -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() diff --git a/cmake/tribits/examples/TribitsExampleApp2/app.cpp b/cmake/tribits/examples/TribitsExampleApp2/app.cpp index 9ac07aad12eb..8c40077d2534 100644 --- a/cmake/tribits/examples/TribitsExampleApp2/app.cpp +++ b/cmake/tribits/examples/TribitsExampleApp2/app.cpp @@ -1,28 +1,35 @@ #ifdef TRIBITSEXAPP2_HAVE_PACKAGE1 # include "Package1.hpp" #endif +#ifdef TRIBITSEXAPP2_HAVE_PACKAGE2 +# include "Package2.hpp" +#endif +#ifdef TRIBITSEXAPP2_HAVE_PACKAGE3 +# include "Package3.hpp" +#endif #include #include -void appendDepsStr(std::string &depsStr, const std::string &str) -{ - if (depsStr.length()) { - depsStr += "; "+str; - } - else { - depsStr = str; - } +namespace Impl { +void appendDepsStr(std::string &depsStr, const std::string &str); } int main(int argc, char *argv[]) { + using Impl::appendDepsStr; // Get deps down the deps graph std::string depsStr; -#ifdef TRIBITSEXAPP2_HAVE_PACKAGE1 - appendDepsStr(depsStr, "Package1: "+Package1::deps()); +#ifdef TRIBITSEXAPP2_HAVE_PACKAGE3 + appendDepsStr(depsStr, "Package3{"+Package3::deps()+"}"); +#elif TRIBITSEXAPP2_HAVE_PACKAGE2 + appendDepsStr(depsStr, "Package2{"+Package2::deps()+"}"); +#elif TRIBITSEXAPP2_HAVE_PACKAGE1 + appendDepsStr(depsStr, "Package1{"+Package1::deps()+"}"); +#else + depsStr = "no 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 @@ -32,3 +39,14 @@ int main(int argc, char *argv[]) { return 0; } + + +void Impl::appendDepsStr(std::string &depsStr, const std::string &str) +{ + if (depsStr.length()) { + depsStr += ", "+str; + } + else { + depsStr = str; + } +} diff --git a/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/cmake/Dependencies.cmake b/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/cmake/Dependencies.cmake index 957707d9b5b3..13461825aff0 100644 --- a/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/cmake/Dependencies.cmake +++ b/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/cmake/Dependencies.cmake @@ -1,5 +1,5 @@ tribits_package_define_dependencies( LIB_REQUIRED_TPLS HeaderOnlyTpl - LIB_OPTIONAL_TPLS SimpleTpl + LIB_OPTIONAL_TPLS SimpleTpl MPI REGRESSION_EMAIL_LIST simplecxx-regressions@someurl.none ) diff --git a/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/cmake/SimpleCxx_config.h.in b/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/cmake/SimpleCxx_config.h.in index 0685e8ce34f7..cb782e7ae898 100644 --- a/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/cmake/SimpleCxx_config.h.in +++ b/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/cmake/SimpleCxx_config.h.in @@ -1,6 +1,11 @@ +#ifndef SIMPLECXX_CONFIG_H +#define SIMPLECXX_CONFIG_H + #cmakedefine HAVE_SIMPLECXX___INT64 #cmakedefine HAVE_SIMPLECXX_DEBUG #cmakedefine HAVE_SIMPLECXX_SIMPLETPL @SIMPLECXX_DEPRECATED_DECLARATIONS@ + +#endif /** SIMPLECXX_CONFIG_H **/ diff --git a/cmake/tribits/examples/TribitsExampleProject/packages/wrap_external/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject/packages/wrap_external/CMakeLists.txt index c24397019d36..3adfc2cdb90b 100644 --- a/cmake/tribits/examples/TribitsExampleProject/packages/wrap_external/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleProject/packages/wrap_external/CMakeLists.txt @@ -144,7 +144,6 @@ add_dependencies(build_external_func pws_a) # E.3) Update the TriBITS variables append_set(${PACKAGE_NAME}_LIB_TARGETS external_func) global_set(${PACKAGE_NAME}_LIBRARIES external_func pws_a) -global_set(${PACKAGE_NAME}_INCLUDE_DIRS ${EXTERNAL_FUNC_SOURCE_DIR}) global_set(${PACKAGE_NAME}_HAS_NATIVE_LIBRARIES ON) include_directories(${EXTERNAL_FUNC_SOURCE_DIR}) # NOTE: Above, you have to add the upstream dependent libraries to the current diff --git a/cmake/tribits/examples/TribitsExampleProject2/PackagesList.cmake b/cmake/tribits/examples/TribitsExampleProject2/PackagesList.cmake index 104684961749..9f7fdcf665c5 100644 --- a/cmake/tribits/examples/TribitsExampleProject2/PackagesList.cmake +++ b/cmake/tribits/examples/TribitsExampleProject2/PackagesList.cmake @@ -1,3 +1,5 @@ tribits_repository_define_packages( Package1 packages/package1 PT + Package2 packages/package2 PT + Package3 packages/package3 PT ) diff --git a/cmake/tribits/examples/TribitsExampleProject2/TPLsList.cmake b/cmake/tribits/examples/TribitsExampleProject2/TPLsList.cmake index eca542bfdffb..9c9412503208 100644 --- a/cmake/tribits/examples/TribitsExampleProject2/TPLsList.cmake +++ b/cmake/tribits/examples/TribitsExampleProject2/TPLsList.cmake @@ -1,3 +1,11 @@ tribits_repository_define_tpls( Tpl1 "cmake/tpls/" PT + Tpl2 "cmake/tpls/" PT + Tpl3 "cmake/tpls/" PT + Tpl4 "cmake/tpls/" PT ) + +# Temp hack for setting up TPL dependencies +set(Tpl2_LIB_ENABLED_DEPENDENCIES Tpl1 CACHE STRING "Tpl2 upstream dependencies") +set(Tpl3_LIB_ENABLED_DEPENDENCIES Tpl2 CACHE STRING "Tpl3 upstream dependencies") +set(Tpl4_LIB_ENABLED_DEPENDENCIES "Tpl2;Tpl3" CACHE STRING "Tpl4 upstream dependencies") diff --git a/cmake/tribits/examples/TribitsExampleProject2/cmake/tpls/FindTPLTpl2.cmake b/cmake/tribits/examples/TribitsExampleProject2/cmake/tpls/FindTPLTpl2.cmake new file mode 100644 index 000000000000..b7b9df380faf --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/cmake/tpls/FindTPLTpl2.cmake @@ -0,0 +1,4 @@ +tribits_tpl_find_include_dirs_and_libraries( Tpl2 + REQUIRED_HEADERS Tpl2a.hpp # Only look for one header file to find include dir + REQUIRED_LIBS_NAMES tpl2b tpl2a + ) diff --git a/cmake/tribits/examples/TribitsExampleProject2/cmake/tpls/FindTPLTpl3.cmake b/cmake/tribits/examples/TribitsExampleProject2/cmake/tpls/FindTPLTpl3.cmake new file mode 100644 index 000000000000..7967e10a45a3 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/cmake/tpls/FindTPLTpl3.cmake @@ -0,0 +1,4 @@ +tribits_tpl_find_include_dirs_and_libraries( Tpl3 + REQUIRED_HEADERS Tpl3.hpp + REQUIRED_LIBS_NAMES tpl3 + ) diff --git a/cmake/tribits/examples/TribitsExampleProject2/cmake/tpls/FindTPLTpl4.cmake b/cmake/tribits/examples/TribitsExampleProject2/cmake/tpls/FindTPLTpl4.cmake new file mode 100644 index 000000000000..f862727fd007 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/cmake/tpls/FindTPLTpl4.cmake @@ -0,0 +1,3 @@ +tribits_tpl_find_include_dirs_and_libraries( Tpl4 + REQUIRED_HEADERS Tpl4.hpp + ) diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1.cpp b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1.cpp index b414fbd97b98..894e35d28d7b 100644 --- a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1.cpp +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1.cpp @@ -1,6 +1,11 @@ #include "Package1.hpp" #include "Tpl1.hpp" +std::string Package1::itsme() +{ + return "Package1"; +} + std::string Package1::deps() { std::string deps; diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1.hpp b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1.hpp index 2ba04aa4e985..e89df0d34539 100644 --- a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1.hpp +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1.hpp @@ -7,6 +7,9 @@ namespace Package1 { +/** \brief . */ +std::string itsme(); + /** \brief . */ std::string deps(); diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package2/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject2/packages/package2/CMakeLists.txt new file mode 100644 index 000000000000..9decbb876043 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package2/CMakeLists.txt @@ -0,0 +1,4 @@ +tribits_package(Package2) +add_subdirectory(src) +tribits_add_test_directories(test) +tribits_package_postprocess() diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package2/cmake/Dependencies.cmake b/cmake/tribits/examples/TribitsExampleProject2/packages/package2/cmake/Dependencies.cmake new file mode 100644 index 000000000000..46c260a2642a --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package2/cmake/Dependencies.cmake @@ -0,0 +1,4 @@ +tribits_package_define_dependencies( + LIB_REQUIRED_PACKAGES Package1 + LIB_OPTIONAL_TPLS Tpl3 + ) diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package2/cmake/Package2_config.h.in b/cmake/tribits/examples/TribitsExampleProject2/packages/package2/cmake/Package2_config.h.in new file mode 100644 index 000000000000..e9156083aa19 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package2/cmake/Package2_config.h.in @@ -0,0 +1,6 @@ +#ifndef PACAKGE2_CONFIG_H +#define PACAKGE2_CONFIG_H + +#cmakedefine HAVE_PACKAGE2_TPL3 + +#endif /** PACAKGE2_CONFIG **/ diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package2/src/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject2/packages/package2/src/CMakeLists.txt new file mode 100644 index 000000000000..1de2194cb03a --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package2/src/CMakeLists.txt @@ -0,0 +1,26 @@ +set(HEADERS "") +set(SOURCES "") + +tribits_configure_file(${PACKAGE_NAME}_config.h) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +append_set(HEADERS + ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME}_config.h + Package2.hpp + ) +append_set(SOURCES + Package2.cpp + ) + +tribits_add_library( + package2 + HEADERS ${HEADERS} + SOURCES ${SOURCES} + ) + +tribits_add_executable(package2-prg NOEXEPREFIX NOEXESUFFIX + SOURCES Package2_Prg.cpp + INSTALLABLE + ) diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package2/src/Package2.cpp b/cmake/tribits/examples/TribitsExampleProject2/packages/package2/src/Package2.cpp new file mode 100644 index 000000000000..d29a7acb00c9 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package2/src/Package2.cpp @@ -0,0 +1,26 @@ +#include "Package2.hpp" + +#include + +#ifdef HAVE_PACKAGE2_TPL3 +# include "Tpl3.hpp" +#endif +#include "Package1.hpp" + +std::string Package2::itsme() +{ + return "Package2"; +} + +std::string Package2::deps() +{ + std::ostringstream oss_deps; + oss_deps + << Package1::itsme() << "{" << Package1::deps() << "}" +#ifdef HAVE_PACKAGE2_TPL3 + << ", " + << Tpl3::itsme() << "{" << Tpl3::deps() << "}" +#endif + ; + return oss_deps.str(); +} diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package2/src/Package2.hpp b/cmake/tribits/examples/TribitsExampleProject2/packages/package2/src/Package2.hpp new file mode 100644 index 000000000000..8d1753229701 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package2/src/Package2.hpp @@ -0,0 +1,19 @@ +#ifndef PACKAGE2_HPP +#define PACKAGE2_HPP + + +#include "Package2_config.h" +#include + +namespace Package2 { + +/** \brief . */ +std::string itsme(); + +/** \brief . */ +std::string deps(); + +} // namespace Package2 + + +#endif // PACKAGE2_HPP diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package2/src/Package2_Prg.cpp b/cmake/tribits/examples/TribitsExampleProject2/packages/package2/src/Package2_Prg.cpp new file mode 100644 index 000000000000..f642a49bd750 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package2/src/Package2_Prg.cpp @@ -0,0 +1,9 @@ +#include + +#include "Package2.hpp" + +int main() +{ + std::cout << "Package2 Deps: " << Package2::deps() << "\n"; + return 0; +} diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package2/test/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject2/packages/package2/test/CMakeLists.txt new file mode 100644 index 000000000000..0775b3d3c79b --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package2/test/CMakeLists.txt @@ -0,0 +1,13 @@ +if (${PACAKGE_NAME}_ENABLE_Tpl3) + set(tpl3_deps_string ", Tpl3{Tpl2a{tpl1}, Tpl2b{no deps}}") +else() + set(tpl3_deps_string "") +endif() + + +tribits_add_test(package2-prg NOEXEPREFIX NOEXESUFFIX + NAME Prg + DIRECTORY ${PACKAGE_BINARY_DIR}/src + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "Package2 Deps: Package1{tpl1}${tpl3_deps_string}" + ) diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package3/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject2/packages/package3/CMakeLists.txt new file mode 100644 index 000000000000..c21d8c7bcf46 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package3/CMakeLists.txt @@ -0,0 +1,4 @@ +tribits_package(Package3) +add_subdirectory(src) +tribits_add_test_directories(test) +tribits_package_postprocess() diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package3/cmake/Dependencies.cmake b/cmake/tribits/examples/TribitsExampleProject2/packages/package3/cmake/Dependencies.cmake new file mode 100644 index 000000000000..6e9a0e1e47b5 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package3/cmake/Dependencies.cmake @@ -0,0 +1,6 @@ +tribits_package_define_dependencies( + LIB_REQUIRED_PACKAGES Package1 + LIB_OPTIONAL_PACKAGES Package2 + LIB_REQUIRED_TPLS Tpl2 + LIB_OPTIONAL_TPLS Tpl4 + ) diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package3/cmake/Package3_config.h.in b/cmake/tribits/examples/TribitsExampleProject2/packages/package3/cmake/Package3_config.h.in new file mode 100644 index 000000000000..dfa5a47b6809 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package3/cmake/Package3_config.h.in @@ -0,0 +1,7 @@ +#ifndef PACAKGE3_CONFIG_H +#define PACAKGE3_CONFIG_H + +#cmakedefine HAVE_PACKAGE3_TPL4 +#cmakedefine HAVE_PACKAGE3_PACKAGE2 + +#endif /** PACAKGE3_CONFIG_H **/ diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package3/src/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject2/packages/package3/src/CMakeLists.txt new file mode 100644 index 000000000000..ffe0ecc60d12 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package3/src/CMakeLists.txt @@ -0,0 +1,26 @@ +set(HEADERS "") +set(SOURCES "") + +tribits_configure_file(${PACKAGE_NAME}_config.h) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +append_set(HEADERS + ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME}_config.h + Package3.hpp + ) +append_set(SOURCES + Package3.cpp + ) + +tribits_add_library( + package3 + HEADERS ${HEADERS} + SOURCES ${SOURCES} + ) + +tribits_add_executable(package3-prg NOEXEPREFIX NOEXESUFFIX + SOURCES Package3_Prg.cpp + INSTALLABLE + ) diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package3/src/Package3.cpp b/cmake/tribits/examples/TribitsExampleProject2/packages/package3/src/Package3.cpp new file mode 100644 index 000000000000..7ef34f28d39d --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package3/src/Package3.cpp @@ -0,0 +1,40 @@ +#include "Package3.hpp" + +#include + +#include "Package1.hpp" +#ifdef HAVE_PACKAGE3_PACKAGE2 +# include "Package2.hpp" +#endif + +#include "Tpl2a.hpp" +#include "Tpl2b.hpp" +#ifdef HAVE_PACKAGE3_TPL4 +# include "Tpl4.hpp" +#endif + +std::string Package3::itsme() +{ + return "Package3"; +} + +std::string Package3::deps() +{ + std::ostringstream oss_deps; + oss_deps +#ifdef HAVE_PACKAGE3_PACKAGE2 + << Package2::itsme() << "{" << Package2::deps() << "}" + << ", " +#endif + << Package1::itsme() << "{" << Package1::deps() << "}" + << ", " +#ifdef HAVE_PACKAGE3_TPL4 + << Tpl4::itsme() << "{" << Tpl4::deps() << "}" + << ", " +#endif + << Tpl2::a_itsme() << "{" << Tpl2::a_deps() << "}" + << ", " + << Tpl2::b_itsme() << "{" << Tpl2::b_deps() << "}" + ; + return oss_deps.str(); +} diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package3/src/Package3.hpp b/cmake/tribits/examples/TribitsExampleProject2/packages/package3/src/Package3.hpp new file mode 100644 index 000000000000..e5bc76c83a26 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package3/src/Package3.hpp @@ -0,0 +1,21 @@ +#ifndef PACKAGE3_HPP +#define PACKAGE3_HPP + + +#include "Package3_config.h" + +#include + + +namespace Package3 { + +/** \brief . */ +std::string itsme(); + +/** \brief . */ +std::string deps(); + +} // namespace Package3 + + +#endif // PACKAGE3_HPP diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package3/src/Package3_Prg.cpp b/cmake/tribits/examples/TribitsExampleProject2/packages/package3/src/Package3_Prg.cpp new file mode 100644 index 000000000000..26671da228dd --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package3/src/Package3_Prg.cpp @@ -0,0 +1,9 @@ +#include + +#include "Package3.hpp" + +int main() +{ + std::cout << "Package3 Deps: " << Package3::deps() << "\n"; + return 0; +} diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package3/test/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject2/packages/package3/test/CMakeLists.txt new file mode 100644 index 000000000000..a9087b8c5bfd --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package3/test/CMakeLists.txt @@ -0,0 +1,20 @@ +if (${PACKAGE_NAME}_ENABLE_Package2) + set(package2_deps_str + "Package2{Package1{tpl1}, Tpl3{Tpl2a{tpl1}, Tpl2b{no deps}}}, ") +else() + set(package2_deps_str "") +endif() + +if (${PACKAGE_NAME}_ENABLE_Tpl4) + set(tpl4_deps_str + "Tpl4{Tpl3{Tpl2a{tpl1}, Tpl2b{no deps}}, Tpl2a{tpl1}, Tpl2b{no deps}}, ") +else() + set(tpl4_deps_str "") +endif() + +tribits_add_test(package3-prg NOEXEPREFIX NOEXESUFFIX + NAME Prg + DIRECTORY ${PACKAGE_BINARY_DIR}/src + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "Package3 Deps: ${package2_deps_str}Package1{tpl1}, ${tpl4_deps_str}Tpl2a{tpl1}, Tpl2b{no deps}" + ) diff --git a/cmake/tribits/examples/TribitsOldSimpleExampleApp/CMakeLists.txt b/cmake/tribits/examples/TribitsOldSimpleExampleApp/CMakeLists.txt index 0b8d334d5ecb..34302ee7b669 100644 --- a/cmake/tribits/examples/TribitsOldSimpleExampleApp/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsOldSimpleExampleApp/CMakeLists.txt @@ -44,7 +44,7 @@ target_include_directories(util # Build the APP and link to libraries from TribitsExProj packages add_executable(app app.cpp) target_link_libraries(app - PRIVATE ${TribitsExProj_LIBRARIES}) + PRIVATE ${TribitsExProj_LIBRARIES} ${TribitsExProj_TPL_LIBRARIES}) target_include_directories(app PRIVATE ${TribitsExProj_INCLUDE_DIRS} ${TribitsExProj_TPL_INCLUDE_DIRS}) diff --git a/cmake/tribits/examples/TribitsSimpleExampleApp/README.md b/cmake/tribits/examples/TribitsSimpleExampleApp/README.md index a79255b47b23..85bb57165fea 100644 --- a/cmake/tribits/examples/TribitsSimpleExampleApp/README.md +++ b/cmake/tribits/examples/TribitsSimpleExampleApp/README.md @@ -21,6 +21,6 @@ After building and installing `TribitsExampleProject` under ctest ``` -NOTE: The version of this project that demonstrates using the old interface -using variables that works with much older versions of TriBITS is given in +NOTE: The version of this project that demonstrates how to use the old interface, +with variables that work with much older versions of TriBITS, is given in [`TribitsOldSimpleExampleApp`](../TribitsOldSimpleExampleApp/README.md). diff --git a/cmake/tribits/examples/tpls/Tpl2/CMakeLists.txt b/cmake/tribits/examples/tpls/Tpl2/CMakeLists.txt new file mode 100644 index 000000000000..36f9a747f4f8 --- /dev/null +++ b/cmake/tribits/examples/tpls/Tpl2/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.17.0) + +project(Tpl2 + DESCRIPTION + "Simple TPL with two header file, two libraries, and depends on Tpl1" + LANGUAGES C CXX + ) + +find_package(Tpl1 REQUIRED) + + +add_library(tpl2a Tpl2a.hpp Tpl2a.cpp) +target_include_directories(tpl2a + PUBLIC $) +target_link_libraries(tpl2a PRIVATE tpl1::tpl1) + +add_library(tpl2b Tpl2b.hpp Tpl2b.cpp) +target_include_directories(tpl2b + PUBLIC $) + +# NOTE: The above libs tpl2a and tpl2b do not depend on each other. They just +# depend on tpl1::tpl1. + +include(GNUInstallDirs) + +install( + TARGETS tpl2a tpl2b + EXPORT ${PROJECT_NAME} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ) + +install( + FILES Tpl2a.hpp Tpl2b.hpp + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + ) + +install(EXPORT ${PROJECT_NAME} + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} + NAMESPACE tpl2:: + FILE ${PROJECT_NAME}ConfigTargets.cmake + ) + +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/Tpl2Config.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Tpl2Config.install.cmake" + @ONLY + ) + +install( + FILES "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Tpl2Config.install.cmake" + RENAME "Tpl2Config.cmake" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} + ) diff --git a/cmake/tribits/examples/tpls/Tpl2/Tpl2Config.cmake.in b/cmake/tribits/examples/tpls/Tpl2/Tpl2Config.cmake.in new file mode 100644 index 000000000000..d78801ad8871 --- /dev/null +++ b/cmake/tribits/examples/tpls/Tpl2/Tpl2Config.cmake.in @@ -0,0 +1,2 @@ +include("@Tpl1_DIR@/Tpl1Config.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/Tpl2ConfigTargets.cmake") diff --git a/cmake/tribits/examples/tpls/Tpl2/Tpl2a.cpp b/cmake/tribits/examples/tpls/Tpl2/Tpl2a.cpp new file mode 100644 index 000000000000..63e2dea39655 --- /dev/null +++ b/cmake/tribits/examples/tpls/Tpl2/Tpl2a.cpp @@ -0,0 +1,13 @@ +#include "Tpl2a.hpp" + +#include "Tpl1.hpp" + +std::string Tpl2::a_itsme() +{ + return "Tpl2a"; +} + +std::string Tpl2::a_deps() +{ + return Tpl1::itsme(); +} diff --git a/cmake/tribits/examples/tpls/Tpl2/Tpl2a.hpp b/cmake/tribits/examples/tpls/Tpl2/Tpl2a.hpp new file mode 100644 index 000000000000..f1e4fa0bb126 --- /dev/null +++ b/cmake/tribits/examples/tpls/Tpl2/Tpl2a.hpp @@ -0,0 +1,16 @@ +#ifndef TPL2A_HPP +#define TPL2A_HPP + +#include + +namespace Tpl2 { + +/** \brief . */ +std::string a_itsme(); + +/** \brief . */ +std::string a_deps(); + +} // namespace tpl2 + +#endif // TPL2A_HPP diff --git a/cmake/tribits/examples/tpls/Tpl2/Tpl2b.cpp b/cmake/tribits/examples/tpls/Tpl2/Tpl2b.cpp new file mode 100644 index 000000000000..7fe13693f5fc --- /dev/null +++ b/cmake/tribits/examples/tpls/Tpl2/Tpl2b.cpp @@ -0,0 +1,11 @@ +#include "Tpl2b.hpp" + +std::string Tpl2::b_itsme() +{ + return "Tpl2b"; +} + +std::string Tpl2::b_deps() +{ + return "no deps"; +} diff --git a/cmake/tribits/examples/tpls/Tpl2/Tpl2b.hpp b/cmake/tribits/examples/tpls/Tpl2/Tpl2b.hpp new file mode 100644 index 000000000000..dbc597933470 --- /dev/null +++ b/cmake/tribits/examples/tpls/Tpl2/Tpl2b.hpp @@ -0,0 +1,16 @@ +#ifndef TPL2B_HPP +#define TPL2B_HPP + +#include + +namespace Tpl2 { + +/** \brief . */ +std::string b_itsme(); + +/** \brief . */ +std::string b_deps(); + +} // namespace tpl2 + +#endif // TPL2B_HPP diff --git a/cmake/tribits/examples/tpls/Tpl3/CMakeLists.txt b/cmake/tribits/examples/tpls/Tpl3/CMakeLists.txt new file mode 100644 index 000000000000..a10cb463ceef --- /dev/null +++ b/cmake/tribits/examples/tpls/Tpl3/CMakeLists.txt @@ -0,0 +1,46 @@ +cmake_minimum_required(VERSION 3.17.0) + +project(Tpl3 + DESCRIPTION + "Simple TPL with one header file, one library, and depends on Tpl2" + LANGUAGES C CXX + ) + +find_package(Tpl2 REQUIRED) + +add_library(tpl3 Tpl3.hpp Tpl3.cpp) +target_include_directories(tpl3 + PUBLIC $) +target_link_libraries(tpl3 PRIVATE tpl2::tpl2a tpl2::tpl2b) +# Does CMake maintain the above order? + +include(GNUInstallDirs) + +install( + TARGETS tpl3 + EXPORT ${PROJECT_NAME} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ) + +install( + FILES Tpl3.hpp + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + ) + +install(EXPORT ${PROJECT_NAME} + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} + NAMESPACE tpl3:: + FILE ${PROJECT_NAME}ConfigTargets.cmake + ) + +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/Tpl3Config.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Tpl3Config.install.cmake" + @ONLY + ) + +install( + FILES "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Tpl3Config.install.cmake" + RENAME "Tpl3Config.cmake" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} + ) diff --git a/cmake/tribits/examples/tpls/Tpl3/Tpl3.cpp b/cmake/tribits/examples/tpls/Tpl3/Tpl3.cpp new file mode 100644 index 000000000000..2bde0f7d0990 --- /dev/null +++ b/cmake/tribits/examples/tpls/Tpl3/Tpl3.cpp @@ -0,0 +1,20 @@ +#include + +#include "Tpl2a.hpp" +#include "Tpl2b.hpp" +#include "Tpl3.hpp" + +std::string Tpl3::itsme() +{ + return "Tpl3"; +} + +std::string Tpl3::deps() +{ + std::ostringstream oss; + oss + << Tpl2::a_itsme() << "{" << Tpl2::a_deps() << "}" + << ", " + << Tpl2::b_itsme() << "{" << Tpl2::b_deps() << "}"; + return oss.str(); +} diff --git a/cmake/tribits/examples/tpls/Tpl3/Tpl3.hpp b/cmake/tribits/examples/tpls/Tpl3/Tpl3.hpp new file mode 100644 index 000000000000..c1dfd4ea0acd --- /dev/null +++ b/cmake/tribits/examples/tpls/Tpl3/Tpl3.hpp @@ -0,0 +1,16 @@ +#ifndef TPL3_HPP +#define TPL3_HPP + +#include + +namespace Tpl3 { + +/** \brief . */ +std::string itsme(); + +/** \brief . */ +std::string deps(); + +} // namespace tpl3 + +#endif // TPL3_HPP diff --git a/cmake/tribits/examples/tpls/Tpl3/Tpl3Config.cmake.in b/cmake/tribits/examples/tpls/Tpl3/Tpl3Config.cmake.in new file mode 100644 index 000000000000..16b490c4cf3f --- /dev/null +++ b/cmake/tribits/examples/tpls/Tpl3/Tpl3Config.cmake.in @@ -0,0 +1,2 @@ +include("@Tpl2_DIR@/Tpl2Config.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/Tpl3ConfigTargets.cmake") diff --git a/cmake/tribits/examples/tpls/Tpl4/CMakeLists.txt b/cmake/tribits/examples/tpls/Tpl4/CMakeLists.txt new file mode 100644 index 000000000000..cbbe3f2acf6b --- /dev/null +++ b/cmake/tribits/examples/tpls/Tpl4/CMakeLists.txt @@ -0,0 +1,50 @@ +cmake_minimum_required(VERSION 3.17.0) + +project(Tpl4 + DESCRIPTION + "Simple TPL with one header file, no libraries, and depends on Tpl2 and Tpl3" + LANGUAGES C CXX + ) + +find_package(Tpl2 REQUIRED) +find_package(Tpl3 REQUIRED) + +add_library(tpl4 INTERFACE) +target_include_directories(tpl4 + INTERFACE $) +target_link_libraries(tpl4 + INTERFACE tpl3::tpl3 + INTERFACE tpl2::tpl2a tpl2::tpl2b + ) +# Does CMake maintain the above order? + +include(GNUInstallDirs) + +install( + TARGETS tpl4 + EXPORT ${PROJECT_NAME} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ) + +install( + FILES Tpl4.hpp + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + ) + +install(EXPORT ${PROJECT_NAME} + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} + NAMESPACE tpl4:: + FILE ${PROJECT_NAME}ConfigTargets.cmake + ) + +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/Tpl4Config.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Tpl4Config.install.cmake" + @ONLY + ) + +install( + FILES "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Tpl4Config.install.cmake" + RENAME "Tpl4Config.cmake" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} + ) diff --git a/cmake/tribits/examples/tpls/Tpl4/Tpl4.hpp b/cmake/tribits/examples/tpls/Tpl4/Tpl4.hpp new file mode 100644 index 000000000000..4f754d6c6f40 --- /dev/null +++ b/cmake/tribits/examples/tpls/Tpl4/Tpl4.hpp @@ -0,0 +1,33 @@ +#ifndef TPL4_HPP +#define TPL4_HPP + +#include "Tpl2a.hpp" +#include "Tpl2b.hpp" +#include "Tpl3.hpp" + +#include + +namespace Tpl4 { + +/** \brief . */ +inline std::string itsme() +{ + return "Tpl4"; +} + +/** \brief . */ +inline std::string deps() +{ + std::ostringstream oss; + oss + << Tpl3::itsme() << "{" << Tpl3::deps() << "}" + << ", " + << Tpl2::a_itsme() << "{" << Tpl2::a_deps() << "}" + << ", " + << Tpl2::b_itsme() << "{" << Tpl2::b_deps() << "}"; + return oss.str(); +} + +} // namespace Tpl4 + +#endif // TPL4_HPP diff --git a/cmake/tribits/examples/tpls/Tpl4/Tpl4Config.cmake.in b/cmake/tribits/examples/tpls/Tpl4/Tpl4Config.cmake.in new file mode 100644 index 000000000000..6d3bf5f8fd7c --- /dev/null +++ b/cmake/tribits/examples/tpls/Tpl4/Tpl4Config.cmake.in @@ -0,0 +1,3 @@ +include("@Tpl2_DIR@/Tpl2Config.cmake") +include("@Tpl3_DIR@/Tpl3Config.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/Tpl4ConfigTargets.cmake") From 54b2e8f6b3bb9e5def537c4d789e1ad73cda7138 Mon Sep 17 00:00:00 2001 From: "Roscoe A. Bartlett" Date: Thu, 3 Mar 2022 20:45:15 -0700 Subject: [PATCH 06/37] Add release notes for Trilinos 14.0 and break in backward compatibility with -isystem include dirs Hopefully this will be enough for Trilinos users to work through problems with changes in the handling of include directories. For more details, see TriBITSPub/TriBITS#443 --- RELEASE_NOTES | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index ad931b671a2d..7b2fe3f256ac 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -1,3 +1,78 @@ +############################################################################### +# # +# Trilinos Release 14.0 Release Notes # +# # +############################################################################### + +CMake + + - Switch to modern CMake targets in IMPORTED library targets in installed + Config.cmake files which breaks backward compatibility + + With the switch to modern CMake IMPORTED targets, now include directories + (along with critical compiler options and other modern CMake usage + requirements) are propagated through linking to the IMPORTED library + targets in downstream customer CMake projects. This makes the usage of + the variables `_INCLUDE_DIRS` and `Trilinos_TPL_INCLUDE_DIRS` + unnecessary in downstream CMake projects. However, this change will also + cause downstream CMake projects to pull in include directories as `SYSTEM` + includes (e.g. using `-isystem` instead of `-I`) from IMPORTED library + targets. This changes how these include directories are searched and + could break some fragile build environments that have the same header file + names in multiple include directories searched by the compiler. Also, + this will silence any regular compiler warnings from headers found under + these include directories. This constitutes a **break in backward + compatibility** that will break some customer CMake project builds that + use Trilinos on fragile environments where the search order of the include + directories is important. + + There are several different approaches for addressing this change from + `-I` to `-isystem` for the Trilinos include directories described below. + + **Approach-1:** Update to CMake 3.23 and set the Trilinos configure + variable: + + -D Trilinos_IMPORTED_NO_SYSTEM=ON + + This will change back the listing of Trilinos include directories in + downstream customer CMake projects from `-isystem` and `-I` and will + therefore restore about perfect backward compatibility. + + **Approach-2:** Set the cache variable + `CMAKE_NO_SYSTEM_FROM_IMPORTED=TRUE` in a downstream CMake project to set + which will restore the include directories for the IMPORTED library + targets for the TriBITS project as non-SYSTEM include directories + (i.e. `-I`) but it will also cause all include directories for all + IMPORTED library targets to be non-SYSTEM (i.e. `-I`) even if they were + being handled as SYSTEM include directories before. Therefore, that could + still break the downstream project as it might change what header files + are found for these other IMPORTED library targets and may expose many new + warnings (which may have been silenced by their include directories being + pulled in using `-isystem`). + + **Approach-3:** Clean up the list of include directories that is searched + by the compiler so that only the correct header files can be found + (regardless of the search order). + + **Approach-4:** Delete some header files in the set of searched include + directories so that only the correct header files can be found (regardless + of the search order). + + **Approach-5:** Use other approaches more specific to the given customer + project. For example, if multiple different versions of the googletest + (gtest) library header files can be found in the list of include + directories, then a customer project can build its own version of + googletest and put it's include directories first on the compile line and + list them with `-I` to ensure that only that version will be found, no + matter how many other versions of gtest are installed on the system. For + an example of how this was done for one customer CMake project, see + https://github.com/trilinos/Trilinos/issues/8001#issuecomment-1032827124. + + For more details on this change in the handling of include directories + with the switch to modern CMake, see + https://github.com/TriBITSPub/TriBITS/issues/443. + + ############################################################################### # # # Trilinos Release 12.12 Release Notes # From ece947513bd4eb81997f46ca2b89241ab5f6bb24 Mon Sep 17 00:00:00 2001 From: "Roscoe A. Bartlett" Date: Mon, 13 Jun 2022 18:33:11 -0600 Subject: [PATCH 07/37] Explain more about change in handling of include directories (TriBITSPub/TriBITS#299) This covers the issue encountered in testing with SPARC that required small additions to their CMakeLists.txt files. --- RELEASE_NOTES | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 7b2fe3f256ac..0b70b33efd1c 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -7,21 +7,39 @@ CMake - Switch to modern CMake targets in IMPORTED library targets in installed - Config.cmake files which breaks backward compatibility + `Config.cmake` files which **breaks backward compatibility** for + some downstream CMake projects: With the switch to modern CMake IMPORTED targets, now include directories (along with critical compiler options and other modern CMake usage requirements) are propagated through linking to the IMPORTED library targets in downstream customer CMake projects. This makes the usage of - the variables `_INCLUDE_DIRS` and `Trilinos_TPL_INCLUDE_DIRS` - unnecessary in downstream CMake projects. However, this change will also - cause downstream CMake projects to pull in include directories as `SYSTEM` - includes (e.g. using `-isystem` instead of `-I`) from IMPORTED library - targets. This changes how these include directories are searched and - could break some fragile build environments that have the same header file - names in multiple include directories searched by the compiler. Also, - this will silence any regular compiler warnings from headers found under - these include directories. This constitutes a **break in backward + the variables `Trilinos_INCLUDE_DIRS` and `Trilinos_TPL_INCLUDE_DIRS` + unnecessary in downstream CMake projects. The variable + `Trilinos_INCLUDE_DIRS` is still set but the variable + `Trilinos_TPL_INCLUDE_DIRS` is empty in this change to modern CMake. To + get include directories for Trilinos packages and TPLs, one must link + against the Trilinos target `Trilinos::all_libs` or + `Trilinos::all_selected_libs` or by linking against the individual package + targets `::all_libs` and/or the TPL targets + `::all_libs`. To upgrade downstream CMake projects that are + showing missing include directories (i.e. header files can't be found) + just add `target_link_libraries()` calls with the appropriate + `::all_libs` targets for the desired package and/or TPL. (See the + section "Using the installed software in downstream CMake projects" in the + updated build reference guide.) However, backward compatibility is + maintained for most customers which are linking all of their libraries + against `${Trilinos_LIBRARIES}`. For these projects, no changes will need + to be made. + + However, this change to modern CMake targets will also cause downstream + CMake projects to pull in include directories as `SYSTEM` includes + (e.g. using `-isystem` instead of `-I`) from IMPORTED library targets. + This changes how these include directories are searched and could break + some fragile build environments that have the same header file names in + multiple include directories searched by the compiler. Also, this will + silence any regular compiler warnings from header files found under these + include directories. This constitutes a **break in backward compatibility** that will break some customer CMake project builds that use Trilinos on fragile environments where the search order of the include directories is important. From 47fc3261d441859f396eee139331a1992a71c40e Mon Sep 17 00:00:00 2001 From: "Roscoe A. Bartlett" Date: Thu, 16 Jun 2022 11:09:44 -0600 Subject: [PATCH 08/37] Always call tribits_tpl_find_include_dirs_and_libraries() for Ptread::all_libs (TriBITSPub/TriBITS#299) I was able to reproduce the build errors associated with this. I needed to do another round of Trilinos testing when I removed checks for TARGET ::all_libs. --- cmake/TPLs/FindTPLPthread.cmake | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/cmake/TPLs/FindTPLPthread.cmake b/cmake/TPLs/FindTPLPthread.cmake index fc401d754335..488d4fe943cb 100644 --- a/cmake/TPLs/FindTPLPthread.cmake +++ b/cmake/TPLs/FindTPLPthread.cmake @@ -56,27 +56,31 @@ SET(USE_THREADS FALSE) -IF(NOT TPL_Pthread_INCLUDE_DIRS AND NOT TPL_Pthread_LIBRARY_DIRS AND NOT TPL_Pthread_LIBRARIES) +IF (NOT TPL_Pthread_INCLUDE_DIRS AND NOT TPL_Pthread_LIBRARY_DIRS + AND NOT TPL_Pthread_LIBRARIES + ) # Use CMake's Thread finder since it is a bit smarter in determining # whether pthreads is already built into the compiler and doesn't need # a library to link. FIND_PACKAGE(Threads) #If Threads found a copy of pthreads make sure it is one of the cases the tribits #tpl system cannot handle. - IF(Threads_FOUND AND CMAKE_USE_PTHREADS_INIT) - IF(CMAKE_THREAD_LIBS_INIT STREQUAL "" OR CMAKE_THREAD_LIBS_INIT STREQUAL "-pthread") + IF (Threads_FOUND AND CMAKE_USE_PTHREADS_INIT) + IF(CMAKE_THREAD_LIBS_INIT STREQUAL "" OR CMAKE_THREAD_LIBS_INIT STREQUAL "-pthread") SET(USE_THREADS TRUE) + SET(TPL_Pthread_INCLUDE_DIRS "") + SET(TPL_Pthread_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}") + SET(TPL_Pthread_LIBRARY_DIRS "") ENDIF() ENDIF() ENDIF() -IF(USE_THREADS) - SET(TPL_Pthread_INCLUDE_DIRS "") - SET(TPL_Pthread_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}") - SET(TPL_Pthread_LIBRARY_DIRS "") +IF (USE_THREADS AND CMAKE_THREAD_LIBS_INIT STREQUAL "") + # Produce dummy Pthread::all_libs target and PthreadConfig.cmake file + TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES(Pthread) ELSE() TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES( Pthread REQUIRED_HEADERS pthread.h REQUIRED_LIBS_NAMES pthread - ) + ) ENDIF() From bbde8cbe342718b6c7f258cf164def5b203cb8ec Mon Sep 17 00:00:00 2001 From: "Roscoe A. Bartlett" Date: Thu, 16 Jun 2022 11:23:21 -0600 Subject: [PATCH 09/37] Lower-case CMake commands using lower_case_cmake.py (TriBITSPub/TriBITS#274) --- cmake/TPLs/FindTPLPthread.cmake | 34 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/cmake/TPLs/FindTPLPthread.cmake b/cmake/TPLs/FindTPLPthread.cmake index 488d4fe943cb..0c556c8aaa0b 100644 --- a/cmake/TPLs/FindTPLPthread.cmake +++ b/cmake/TPLs/FindTPLPthread.cmake @@ -54,33 +54,33 @@ # @HEADER -SET(USE_THREADS FALSE) +set(USE_THREADS FALSE) -IF (NOT TPL_Pthread_INCLUDE_DIRS AND NOT TPL_Pthread_LIBRARY_DIRS +if (NOT TPL_Pthread_INCLUDE_DIRS AND NOT TPL_Pthread_LIBRARY_DIRS AND NOT TPL_Pthread_LIBRARIES ) # Use CMake's Thread finder since it is a bit smarter in determining # whether pthreads is already built into the compiler and doesn't need # a library to link. - FIND_PACKAGE(Threads) + find_package(Threads) #If Threads found a copy of pthreads make sure it is one of the cases the tribits #tpl system cannot handle. - IF (Threads_FOUND AND CMAKE_USE_PTHREADS_INIT) - IF(CMAKE_THREAD_LIBS_INIT STREQUAL "" OR CMAKE_THREAD_LIBS_INIT STREQUAL "-pthread") - SET(USE_THREADS TRUE) - SET(TPL_Pthread_INCLUDE_DIRS "") - SET(TPL_Pthread_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}") - SET(TPL_Pthread_LIBRARY_DIRS "") - ENDIF() - ENDIF() -ENDIF() + if (Threads_FOUND AND CMAKE_USE_PTHREADS_INIT) + if(CMAKE_THREAD_LIBS_INIT STREQUAL "" OR CMAKE_THREAD_LIBS_INIT STREQUAL "-pthread") + set(USE_THREADS TRUE) + set(TPL_Pthread_INCLUDE_DIRS "") + set(TPL_Pthread_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}") + set(TPL_Pthread_LIBRARY_DIRS "") + endif() + endif() +endif() -IF (USE_THREADS AND CMAKE_THREAD_LIBS_INIT STREQUAL "") +if (USE_THREADS AND CMAKE_THREAD_LIBS_INIT STREQUAL "") # Produce dummy Pthread::all_libs target and PthreadConfig.cmake file - TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES(Pthread) -ELSE() - TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES( Pthread + tribits_tpl_find_include_dirs_and_libraries(Pthread) +else() + tribits_tpl_find_include_dirs_and_libraries( Pthread REQUIRED_HEADERS pthread.h REQUIRED_LIBS_NAMES pthread ) -ENDIF() +endif() From 0d31074b0cb135a043df7d934b51e8234d9edfe7 Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Fri, 17 Jun 2022 10:02:21 -0600 Subject: [PATCH 10/37] Intrelab: Switch to target based Intrelab CMake build --- .../intrepid/matlab/intrelab/CMakeLists.txt | 288 ++++++++++-------- 1 file changed, 157 insertions(+), 131 deletions(-) diff --git a/packages/intrepid/matlab/intrelab/CMakeLists.txt b/packages/intrepid/matlab/intrelab/CMakeLists.txt index e0d3be02c82c..9d5c611f78c2 100644 --- a/packages/intrepid/matlab/intrelab/CMakeLists.txt +++ b/packages/intrepid/matlab/intrelab/CMakeLists.txt @@ -26,6 +26,12 @@ if(DEFINED ENV{MATLAB_BIN_DIR}) set(MATLAB_BIN_DIR $ENV{MATLAB_BIN_DIR}) endif() +set(Matlab_ROOT_DIR "/usr/local/matlab/R2021b/") +if(DEFINED ENV{Matlab_ROOT_DIR}) + set(Matlab_ROOT_DIR $ENV{Matlab_ROOT_DIR}) +endif() +find_package(Matlab) + # --> ACTION: define install directory (full path or relative to the intrelab directory) set(INST_DIR "install") @@ -39,9 +45,9 @@ endif() FIND_PACKAGE(Trilinos REQUIRED) -# set Matlab mex path with -largeArrayDims option -set(MEX "${MATLAB_BIN_DIR}/mex") -message(STATUS "MEX: ${MEX}") +## set Matlab mex path with -largeArrayDims option +#set(MEX "${MATLAB_BIN_DIR}/mex") +#message(STATUS "MEX: ${MEX}") # set compilers to Trilinos compilers set(CMAKE_CXX_COMPILER ${Trilinos_CXX_COMPILER}) @@ -50,127 +56,128 @@ set(CMAKE_C_COMPILER ${Trilinos_C_COMPILER}) # set flags to Trilinos flags set(CMAKE_CXX_FLAGS ${Trilinos_CXX_COMPILER_FLAGS}) -# Trilinos doesn't propagate its C++ standard -set(MEX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -fPIC") -if (APPLE) - # Trilinos doesn't propagate its sysroot - message(STATUS "CMAKE_OSX_SYSROOT: ${CMAKE_OSX_SYSROOT}") - set(MEX_FLAGS "--sysroot=${CMAKE_OSX_SYSROOT} ${MEX_FLAGS}") -endif(APPLE) - -list (APPEND CMAKE_INSTALL_RPATH ${Trilinos_LIBRARY_DIRS}) -list (APPEND CMAKE_INSTALL_RPATH ${Trilinos_TPL_LIBRARY_DIRS}) - -if (Trilinos_INCLUDE_DIRS) - set(Trilinos_INCLUDE_DIRS "-I${Trilinos_INCLUDE_DIRS}") -endif() -if (Trilinos_TPL_INCLUDE_DIRS) - set(Trilinos_TPL_INCLUDE_DIRS "-I${Trilinos_TPL_INCLUDE_DIRS}") -endif() -if (Trilinos_LIBRARY_DIRS) - set(Trilinos_LIBRARY_DIRS "-L${Trilinos_LIBRARY_DIRS}") -endif() -if (Trilinos_TPL_LIBRARY_DIRS) - set(Trilinos_TPL_LIBRARY_DIRS "-L${Trilinos_TPL_LIBRARY_DIRS}") -endif() - -set(l_Trilinos "") -foreach(alib ${Trilinos_LIBRARIES}) - set(l_Trilinos "${l_Trilinos} -l${alib}") -endforeach() - -set(l_Trilinos_TPL "") -foreach(alib ${Trilinos_TPL_LIBRARIES}) - # check if library has a "." in it - string(REGEX MATCH "\.*" lib_ext_result ${alib}) - if (lib_ext_result) - - if (APPLE) - string(FIND ${alib} ".tbd" alib_result) - # make sure .tbd not found in library name - else() - string(FIND ${alib} ".so" alib_result) - # make sure .so not found in library name - endif(APPLE) - - if (alib_result LESS 0) - # extension found but not .tbd or .so - message(FATAL_ERROR "${alib} encountered as TPL with unrecognized file extension.") - else() - # remove extension and get library name - get_filename_component(libname ${alib} NAME_WLE) - string(SUBSTRING ${libname} 3 -1 reduced_libname) - set(l_Trilinos_TPL "${l_Trilinos_TPL} -l${reduced_libname}") - endif() - else() - # no extension on library name - set(l_Trilinos_TPL "${l_Trilinos_TPL} -l${alib}") - endif() -endforeach() - -if(APPLE) - if(Trilinos_BUILD_SHARED_LIBS) - set(MEX_LD_FLAGS "LDFLAGS=") - set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -rpath ${Trilinos_INSTALL_DIR}/lib") - set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -rpath ${MATLAB_BIN_DIR}/maci64") - set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -shared") - endif() -else() - set(MEX_LD_FLAGS "LDFLAGS=") - foreach(rp ${CMAKE_INSTALL_RPATH}) - set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -Wl,-R,${rp}") - endforeach() - set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -Wl,-R,${MATLAB_BIN_DIR}/glnxa64") - set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -Wl,--enable-new-dtags") -endif() - -separate_arguments(ll UNIX_COMMAND ${l_Trilinos}) -set(l_Trilinos ${ll}) - -separate_arguments(ll UNIX_COMMAND ${l_Trilinos_TPL}) -set(l_Trilinos_TPL ${ll}) - -if(APPLE) - set(MEX_EXTENSION "mexmaci64") -else() - set(MEX_EXTENSION "mexa64") -endif(APPLE) - -# create objs folder -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/objs) -add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o - COMMAND "${MEX}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" -c ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp" - BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/objs - ) - -function(make_mex fname) - - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o - COMMAND "${MEX}" "LDFLAGS=-shared" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" -c ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp" - BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/objs - ) - - #add_custom_command(OUTPUT ${fname}.${MEX_EXTENSION} - # COMMAND "${MEX}" "LDFLAGS=-shared" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} ${Trilinos_LIBRARY_DIRS} ${Trilinos_TPL_LIBRARY_DIRS} ${l_Trilinos} ${l_Trilinos_TPL} "${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o" "${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o" - # DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o - # BYPRODUCTS ${fname}.${MEX_EXTENSION} - # WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - # ) - - add_custom_command(OUTPUT ${fname}.${MEX_EXTENSION} - COMMAND "${MEX}" "${MEX_LD_FLAGS}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} ${Trilinos_LIBRARY_DIRS} ${Trilinos_TPL_LIBRARY_DIRS} ${l_Trilinos} ${l_Trilinos_TPL} "${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp" - #DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o - BYPRODUCTS ${fname}.${MEX_EXTENSION} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - ) - - install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${fname}.${MEX_EXTENSION} DESTINATION ${CMAKE_INSTALL_PREFIX}) +## Trilinos doesn't propagate its C++ standard +#set(MEX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -fPIC") +#if (APPLE) +# # Trilinos doesn't propagate its sysroot +# message(STATUS "CMAKE_OSX_SYSROOT: ${CMAKE_OSX_SYSROOT}") +# set(MEX_FLAGS "--sysroot=${CMAKE_OSX_SYSROOT} ${MEX_FLAGS}") +#endif(APPLE) +# +#list (APPEND CMAKE_INSTALL_RPATH ${Trilinos_LIBRARY_DIRS}) +#list (APPEND CMAKE_INSTALL_RPATH ${Trilinos_TPL_LIBRARY_DIRS}) +# +#if (Trilinos_INCLUDE_DIRS) +# set(Trilinos_INCLUDE_DIRS "-I${Trilinos_INCLUDE_DIRS}") +#endif() +#if (Trilinos_TPL_INCLUDE_DIRS) +# set(Trilinos_TPL_INCLUDE_DIRS "-I${Trilinos_TPL_INCLUDE_DIRS}") +#endif() +#if (Trilinos_LIBRARY_DIRS) +# set(Trilinos_LIBRARY_DIRS "-L${Trilinos_LIBRARY_DIRS}") +#endif() +#if (Trilinos_TPL_LIBRARY_DIRS) +# set(Trilinos_TPL_LIBRARY_DIRS "-L${Trilinos_TPL_LIBRARY_DIRS}") +#endif() +# +#set(l_Trilinos "") +#foreach(alib ${Trilinos_LIBRARIES}) +# set(l_Trilinos "${l_Trilinos} -l${alib}") +#endforeach() + +#message(STATUS "TRILINOS::TPL:: ${Trilinos_TPL_LIBRARIES}") +#set(l_Trilinos_TPL "") +#foreach(alib ${Trilinos_TPL_LIBRARIES}) +# # check if library has a "." in it +# string(REGEX MATCH "\.*" lib_ext_result ${alib}) +# if (lib_ext_result) +# +# if (APPLE) +# string(FIND ${alib} ".tbd" alib_result) +# # make sure .tbd not found in library name +# else() +# string(FIND ${alib} ".so" alib_result) +# # make sure .so not found in library name +# endif(APPLE) +# +# if (alib_result LESS 0) +# # extension found but not .tbd or .so +# message(FATAL_ERROR "${alib} encountered as TPL with unrecognized file extension.") +# else() +# # remove extension and get library name +# get_filename_component(libname ${alib} NAME_WLE) +# string(SUBSTRING ${libname} 3 -1 reduced_libname) +# set(l_Trilinos_TPL "${l_Trilinos_TPL} -l${reduced_libname}") +# endif() +# else() +# # no extension on library name +# set(l_Trilinos_TPL "${l_Trilinos_TPL} -l${alib}") +# endif() +#endforeach() + +#if(APPLE) +# if(Trilinos_BUILD_SHARED_LIBS) +# set(MEX_LD_FLAGS "LDFLAGS=") +# set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -rpath ${Trilinos_INSTALL_DIR}/lib") +# set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -rpath ${MATLAB_BIN_DIR}/maci64") +# set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -shared") +# endif() +#else() +# set(MEX_LD_FLAGS "LDFLAGS=") +# foreach(rp ${CMAKE_INSTALL_RPATH}) +# set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -Wl,-R,${rp}") +# endforeach() +# set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -Wl,-R,${MATLAB_BIN_DIR}/glnxa64") +# set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -Wl,--enable-new-dtags") +#endif() +# +#separate_arguments(ll UNIX_COMMAND ${l_Trilinos}) +#set(l_Trilinos ${ll}) +# +#separate_arguments(ll UNIX_COMMAND ${l_Trilinos_TPL}) +#set(l_Trilinos_TPL ${ll}) + +#if(APPLE) +# set(MEX_EXTENSION "mexmaci64") +#else() +# set(MEX_EXTENSION "mexa64") +#endif(APPLE) +# +## create objs folder +#file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/objs) +#add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o +# COMMAND "${MEX}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" -c ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp" +# BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o +# DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp +# WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/objs +# ) -endfunction(make_mex) +#function(make_mex fname) +# +# add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o +# COMMAND "${MEX}" "LDFLAGS=-shared" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" -c ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp" +# BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o +# DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp +# WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/objs +# ) +# +# #add_custom_command(OUTPUT ${fname}.${MEX_EXTENSION} +# # COMMAND "${MEX}" "LDFLAGS=-shared" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} ${Trilinos_LIBRARY_DIRS} ${Trilinos_TPL_LIBRARY_DIRS} ${l_Trilinos} ${l_Trilinos_TPL} "${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o" "${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o" +# # DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o +# # BYPRODUCTS ${fname}.${MEX_EXTENSION} +# # WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +# # ) +# +# add_custom_command(OUTPUT ${fname}.${MEX_EXTENSION} +# COMMAND "${MEX}" "${MEX_LD_FLAGS}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} ${Trilinos_LIBRARY_DIRS} ${Trilinos_TPL_LIBRARY_DIRS} ${l_Trilinos} ${l_Trilinos_TPL} "${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp" +# #DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o +# BYPRODUCTS ${fname}.${MEX_EXTENSION} +# WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +# ) +# +# install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${fname}.${MEX_EXTENSION} DESTINATION ${CMAKE_INSTALL_PREFIX}) +# +#endfunction(make_mex) set(MOBJS "intrepid_setJacobian;intrepid_setJacobianInv;intrepid_setJacobianDet;intrepid_getNumCubaturePoints;intrepid_getCubature;intrepid_getBasisValues;intrepid_computeCellMeasure;intrepid_HGRADtransformGRAD;intrepid_HGRADtransformVALUE;intrepid_multiplyMeasure;intrepid_integrate;intrepid_mapToPhysicalFrame;intrepid_mapToReferenceFrame;intrepid_scalarMultiplyDataField;intrepid_scalarMultiplyDataData;intrepid_dataIntegral;intrepid_evaluate;intrepid_multiplyVectorDataField;intrepid_dotMultiplyDataField;intrepid_vectorMultiplyDataField;intrepid_dotMultiplyDataData;intrepid_computeEdgeMeasure;intrepid_computeFaceMeasure;intrepid_getCellDeviatoricMat;intrepid_getCellVolumetricMat;intrepid_getPhysicalSideNormals;intrepid_mapToReferenceSubcell;intrepid_tensorMultiplyDataData;intrepid_tensorMultiplyDataField;defGrad;evaluateVectorField;evaluateVectorGradField;externalForceElastostaticsTL;geometricBmat;intrepid_det;intrepid_inverse;intrepid_transpose;materialBmat;strainEulerianLagrangian;stress;tangentStiffnessElastostaticsTL;tensorMultiplyDataField;myMatVecProductDataField;myMatVecProductDataData") @@ -180,15 +187,34 @@ set(MOBJS "intrepid_setJacobian;intrepid_setJacobianInv;intrepid_setJacobianDet; # COMMAND # left intentionally blank # DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o # ) + +#foreach(fname ${MOBJS}) +# make_mex(${fname}) +# # builds dependency chain +# add_custom_target(${fname} +# ALL +# COMMAND # left intentionally blank +# #DEPENDS m2i_helpers ${fname}.${MEX_EXTENSION} +# DEPENDS ${fname}.${MEX_EXTENSION} +# ) +#endforeach() +matlab_add_mex(NAME m2i_helpers + SHARED + SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp +) +target_link_libraries(m2i_helpers Trilinos::all_libs) +function(make_mex fname) + matlab_add_mex(NAME ${fname} + SHARED + #SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp + SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp + ) + target_link_libraries(${fname} Trilinos::all_libs) + target_link_libraries(${fname} m2i_helpers) +endfunction(make_mex) + foreach(fname ${MOBJS}) - make_mex(${fname}) - # builds dependency chain - add_custom_target(${fname} - ALL - COMMAND # left intentionally blank - #DEPENDS m2i_helpers ${fname}.${MEX_EXTENSION} - DEPENDS ${fname}.${MEX_EXTENSION} - ) + make_mex(${fname}) endforeach() if(APPLE) From 887dbb0c74d8a553331ca840d33b7215396847ba Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Fri, 17 Jun 2022 14:22:22 -0600 Subject: [PATCH 11/37] Add mac version of matlab_add_mex() --- .../intrepid/matlab/intrelab/CMakeLists.txt | 305 +++++++++--------- 1 file changed, 145 insertions(+), 160 deletions(-) diff --git a/packages/intrepid/matlab/intrelab/CMakeLists.txt b/packages/intrepid/matlab/intrelab/CMakeLists.txt index 9d5c611f78c2..78b53c449960 100644 --- a/packages/intrepid/matlab/intrelab/CMakeLists.txt +++ b/packages/intrepid/matlab/intrelab/CMakeLists.txt @@ -10,9 +10,10 @@ PROJECT(Intrelab) CMAKE_MINIMUM_REQUIRED(VERSION 3.10) +#set(MATLAB_FIND_DEBUG TRUE) # --> ACTION: define Trilinos install directory -#set(TRILINOS_INSTALL_DIR "/Users/pakuber/Compadre/Trilinos-new/pthread/install_release") +#set(TRILINOS_INSTALL_DIR "/Users/pakuber/Compadre/Trilinos-intrelab/pthread/install_release") set(TRILINOS_INSTALL_DIR "/ascldap/users/pakuber/Compadre/Trilinos-intrelab/build/install") if(DEFINED ENV{TRILINOS_INSTALL_DIR}) set(TRILINOS_INSTALL_DIR $ENV{TRILINOS_INSTALL_DIR}) @@ -20,17 +21,12 @@ endif() # --> ACTION: define Matlab binary directory -#set(MATLAB_BIN_DIR "/Applications/MATLAB_R2020a.app/bin/") -set(MATLAB_BIN_DIR "/usr/local/matlab/R2021b/bin/") -if(DEFINED ENV{MATLAB_BIN_DIR}) - set(MATLAB_BIN_DIR $ENV{MATLAB_BIN_DIR}) -endif() - +#set(Matlab_ROOT_DIR "/Applications/MATLAB_R2020a.app/") set(Matlab_ROOT_DIR "/usr/local/matlab/R2021b/") if(DEFINED ENV{Matlab_ROOT_DIR}) set(Matlab_ROOT_DIR $ENV{Matlab_ROOT_DIR}) endif() -find_package(Matlab) +find_package(Matlab REQUIRED) # --> ACTION: define install directory (full path or relative to the intrelab directory) set(INST_DIR "install") @@ -45,10 +41,6 @@ endif() FIND_PACKAGE(Trilinos REQUIRED) -## set Matlab mex path with -largeArrayDims option -#set(MEX "${MATLAB_BIN_DIR}/mex") -#message(STATUS "MEX: ${MEX}") - # set compilers to Trilinos compilers set(CMAKE_CXX_COMPILER ${Trilinos_CXX_COMPILER}) set(CMAKE_C_COMPILER ${Trilinos_C_COMPILER}) @@ -56,159 +48,152 @@ set(CMAKE_C_COMPILER ${Trilinos_C_COMPILER}) # set flags to Trilinos flags set(CMAKE_CXX_FLAGS ${Trilinos_CXX_COMPILER_FLAGS}) -## Trilinos doesn't propagate its C++ standard -#set(MEX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -fPIC") -#if (APPLE) -# # Trilinos doesn't propagate its sysroot -# message(STATUS "CMAKE_OSX_SYSROOT: ${CMAKE_OSX_SYSROOT}") -# set(MEX_FLAGS "--sysroot=${CMAKE_OSX_SYSROOT} ${MEX_FLAGS}") -#endif(APPLE) -# -#list (APPEND CMAKE_INSTALL_RPATH ${Trilinos_LIBRARY_DIRS}) -#list (APPEND CMAKE_INSTALL_RPATH ${Trilinos_TPL_LIBRARY_DIRS}) -# -#if (Trilinos_INCLUDE_DIRS) -# set(Trilinos_INCLUDE_DIRS "-I${Trilinos_INCLUDE_DIRS}") -#endif() -#if (Trilinos_TPL_INCLUDE_DIRS) -# set(Trilinos_TPL_INCLUDE_DIRS "-I${Trilinos_TPL_INCLUDE_DIRS}") -#endif() -#if (Trilinos_LIBRARY_DIRS) -# set(Trilinos_LIBRARY_DIRS "-L${Trilinos_LIBRARY_DIRS}") -#endif() -#if (Trilinos_TPL_LIBRARY_DIRS) -# set(Trilinos_TPL_LIBRARY_DIRS "-L${Trilinos_TPL_LIBRARY_DIRS}") -#endif() -# -#set(l_Trilinos "") -#foreach(alib ${Trilinos_LIBRARIES}) -# set(l_Trilinos "${l_Trilinos} -l${alib}") -#endforeach() - -#message(STATUS "TRILINOS::TPL:: ${Trilinos_TPL_LIBRARIES}") -#set(l_Trilinos_TPL "") -#foreach(alib ${Trilinos_TPL_LIBRARIES}) -# # check if library has a "." in it -# string(REGEX MATCH "\.*" lib_ext_result ${alib}) -# if (lib_ext_result) -# -# if (APPLE) -# string(FIND ${alib} ".tbd" alib_result) -# # make sure .tbd not found in library name -# else() -# string(FIND ${alib} ".so" alib_result) -# # make sure .so not found in library name -# endif(APPLE) -# -# if (alib_result LESS 0) -# # extension found but not .tbd or .so -# message(FATAL_ERROR "${alib} encountered as TPL with unrecognized file extension.") -# else() -# # remove extension and get library name -# get_filename_component(libname ${alib} NAME_WLE) -# string(SUBSTRING ${libname} 3 -1 reduced_libname) -# set(l_Trilinos_TPL "${l_Trilinos_TPL} -l${reduced_libname}") -# endif() -# else() -# # no extension on library name -# set(l_Trilinos_TPL "${l_Trilinos_TPL} -l${alib}") -# endif() -#endforeach() - -#if(APPLE) -# if(Trilinos_BUILD_SHARED_LIBS) -# set(MEX_LD_FLAGS "LDFLAGS=") -# set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -rpath ${Trilinos_INSTALL_DIR}/lib") -# set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -rpath ${MATLAB_BIN_DIR}/maci64") -# set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -shared") -# endif() -#else() -# set(MEX_LD_FLAGS "LDFLAGS=") -# foreach(rp ${CMAKE_INSTALL_RPATH}) -# set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -Wl,-R,${rp}") -# endforeach() -# set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -Wl,-R,${MATLAB_BIN_DIR}/glnxa64") -# set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -Wl,--enable-new-dtags") -#endif() -# -#separate_arguments(ll UNIX_COMMAND ${l_Trilinos}) -#set(l_Trilinos ${ll}) -# -#separate_arguments(ll UNIX_COMMAND ${l_Trilinos_TPL}) -#set(l_Trilinos_TPL ${ll}) - -#if(APPLE) -# set(MEX_EXTENSION "mexmaci64") -#else() -# set(MEX_EXTENSION "mexa64") -#endif(APPLE) -# -## create objs folder -#file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/objs) -#add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o -# COMMAND "${MEX}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" -c ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp" -# BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o -# DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp -# WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/objs -# ) - -#function(make_mex fname) -# -# add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o -# COMMAND "${MEX}" "LDFLAGS=-shared" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" -c ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp" -# BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o -# DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp -# WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/objs -# ) -# -# #add_custom_command(OUTPUT ${fname}.${MEX_EXTENSION} -# # COMMAND "${MEX}" "LDFLAGS=-shared" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} ${Trilinos_LIBRARY_DIRS} ${Trilinos_TPL_LIBRARY_DIRS} ${l_Trilinos} ${l_Trilinos_TPL} "${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o" "${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o" -# # DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o -# # BYPRODUCTS ${fname}.${MEX_EXTENSION} -# # WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} -# # ) -# -# add_custom_command(OUTPUT ${fname}.${MEX_EXTENSION} -# COMMAND "${MEX}" "${MEX_LD_FLAGS}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} ${Trilinos_LIBRARY_DIRS} ${Trilinos_TPL_LIBRARY_DIRS} ${l_Trilinos} ${l_Trilinos_TPL} "${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp" -# #DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o -# BYPRODUCTS ${fname}.${MEX_EXTENSION} -# WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} -# ) -# -# install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${fname}.${MEX_EXTENSION} DESTINATION ${CMAKE_INSTALL_PREFIX}) -# -#endfunction(make_mex) +# Trilinos doesn't propagate its C++ standard +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -fPIC") +if (APPLE) + # Trilinos doesn't propagate its sysroot + message(STATUS "CMAKE_OSX_SYSROOT: ${CMAKE_OSX_SYSROOT}") + set(CMAKE_CXX_FLAGS "--sysroot=${CMAKE_OSX_SYSROOT} ${CMAKE_CXX_FLAGS}") +endif(APPLE) + +# fork of matlab_add_mex from FindMatlab.cmake from CMake@3.21.4 +# without symbol exporting and use of *.map files +function(matlab_add_mex_mac) + + if(NOT WIN32) + # we do not need all this on Windows + # pthread options + if(CMAKE_CXX_COMPILER_LOADED) + check_cxx_compiler_flag(-pthread HAS_MINUS_PTHREAD) + elseif(CMAKE_C_COMPILER_LOADED) + check_c_compiler_flag(-pthread HAS_MINUS_PTHREAD) + endif() + # we should use try_compile instead, the link flags are discarded from + # this compiler_flag function. + #check_cxx_compiler_flag(-Wl,--exclude-libs,ALL HAS_SYMBOL_HIDING_CAPABILITY) + + endif() + + set(options EXECUTABLE MODULE SHARED R2017b R2018a EXCLUDE_FROM_ALL) + set(oneValueArgs NAME DOCUMENTATION OUTPUT_NAME) + set(multiValueArgs LINK_TO SRC) + + set(prefix _matlab_addmex_prefix) + cmake_parse_arguments(${prefix} "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) + + if(NOT ${prefix}_NAME) + message(FATAL_ERROR "[MATLAB] The MEX target name cannot be empty") + endif() + + if(NOT ${prefix}_OUTPUT_NAME) + set(${prefix}_OUTPUT_NAME ${${prefix}_NAME}) + endif() + + if(NOT Matlab_VERSION_STRING VERSION_LESS "9.1") # For 9.1 (R2016b) and newer, add version source file + # Add the correct version file depending on which languages are enabled in the project + if(CMAKE_C_COMPILER_LOADED) + # If C is enabled, use the .c file as it will work fine also with C++ + set(MEX_VERSION_FILE "${Matlab_ROOT_DIR}/extern/version/c_mexapi_version.c") + elseif(CMAKE_CXX_COMPILER_LOADED) + # If C is not enabled, check if CXX is enabled and use the .cpp file + # to avoid that the .c file is silently ignored + set(MEX_VERSION_FILE "${Matlab_ROOT_DIR}/extern/version/cpp_mexapi_version.cpp") + else() + # If neither C or CXX is enabled, warn because we cannot add the source. + # TODO: add support for fortran mex files + message(WARNING "[MATLAB] matlab_add_mex requires that at least C or CXX are enabled languages") + endif() + endif() + + # For 9.4 (R2018a) and newer, add API macro. + # Add it for unknown versions too, just in case. + if(NOT Matlab_VERSION_STRING VERSION_LESS "9.4" + OR Matlab_VERSION_STRING STREQUAL "unknown") + if(${${prefix}_R2018a}) + set(MEX_API_MACRO "MATLAB_DEFAULT_RELEASE=R2018a") + else() + set(MEX_API_MACRO "MATLAB_DEFAULT_RELEASE=R2017b") + endif() + endif() + + set(_option_EXCLUDE_FROM_ALL) + if(${prefix}_EXCLUDE_FROM_ALL) + set(_option_EXCLUDE_FROM_ALL "EXCLUDE_FROM_ALL") + endif() + + if(${prefix}_EXECUTABLE) + add_executable(${${prefix}_NAME} + ${_option_EXCLUDE_FROM_ALL} + ${${prefix}_SRC} + ${MEX_VERSION_FILE} + ${${prefix}_DOCUMENTATION} + ${${prefix}_UNPARSED_ARGUMENTS}) + else() + if(${prefix}_MODULE) + set(type MODULE) + else() + set(type SHARED) + endif() + + add_library(${${prefix}_NAME} + ${type} + ${_option_EXCLUDE_FROM_ALL} + ${${prefix}_SRC} + ${MEX_VERSION_FILE} + ${${prefix}_DOCUMENTATION} + ${${prefix}_UNPARSED_ARGUMENTS}) + endif() + + target_include_directories(${${prefix}_NAME} PRIVATE ${Matlab_INCLUDE_DIRS}) + + if(Matlab_HAS_CPP_API) + if(Matlab_ENGINE_LIBRARY) + target_link_libraries(${${prefix}_NAME} ${Matlab_ENGINE_LIBRARY}) + endif() + if(Matlab_DATAARRAY_LIBRARY) + target_link_libraries(${${prefix}_NAME} ${Matlab_DATAARRAY_LIBRARY}) + endif() + endif() + + target_link_libraries(${${prefix}_NAME} ${Matlab_MEX_LIBRARY} ${Matlab_MX_LIBRARY} ${${prefix}_LINK_TO}) + set_target_properties(${${prefix}_NAME} + PROPERTIES + PREFIX "" + OUTPUT_NAME ${${prefix}_OUTPUT_NAME} + SUFFIX ".${Matlab_MEX_EXTENSION}") + + target_compile_definitions(${${prefix}_NAME} PRIVATE ${MEX_API_MACRO} MATLAB_MEX_FILE) + +endfunction(matlab_add_mex_mac) set(MOBJS "intrepid_setJacobian;intrepid_setJacobianInv;intrepid_setJacobianDet;intrepid_getNumCubaturePoints;intrepid_getCubature;intrepid_getBasisValues;intrepid_computeCellMeasure;intrepid_HGRADtransformGRAD;intrepid_HGRADtransformVALUE;intrepid_multiplyMeasure;intrepid_integrate;intrepid_mapToPhysicalFrame;intrepid_mapToReferenceFrame;intrepid_scalarMultiplyDataField;intrepid_scalarMultiplyDataData;intrepid_dataIntegral;intrepid_evaluate;intrepid_multiplyVectorDataField;intrepid_dotMultiplyDataField;intrepid_vectorMultiplyDataField;intrepid_dotMultiplyDataData;intrepid_computeEdgeMeasure;intrepid_computeFaceMeasure;intrepid_getCellDeviatoricMat;intrepid_getCellVolumetricMat;intrepid_getPhysicalSideNormals;intrepid_mapToReferenceSubcell;intrepid_tensorMultiplyDataData;intrepid_tensorMultiplyDataField;defGrad;evaluateVectorField;evaluateVectorGradField;externalForceElastostaticsTL;geometricBmat;intrepid_det;intrepid_inverse;intrepid_transpose;materialBmat;strainEulerianLagrangian;stress;tangentStiffnessElastostaticsTL;tensorMultiplyDataField;myMatVecProductDataField;myMatVecProductDataData") -# dummy targets to build up dependencies -#add_custom_target(m2i_helpers -# ALL -# COMMAND # left intentionally blank -# DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o -# ) - -#foreach(fname ${MOBJS}) -# make_mex(${fname}) -# # builds dependency chain -# add_custom_target(${fname} -# ALL -# COMMAND # left intentionally blank -# #DEPENDS m2i_helpers ${fname}.${MEX_EXTENSION} -# DEPENDS ${fname}.${MEX_EXTENSION} -# ) -#endforeach() -matlab_add_mex(NAME m2i_helpers - SHARED - SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp -) -target_link_libraries(m2i_helpers Trilinos::all_libs) -function(make_mex fname) - matlab_add_mex(NAME ${fname} +if (APPLE) + matlab_add_mex_mac(NAME m2i_helpers + SHARED + SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp + ) +else() + matlab_add_mex(NAME m2i_helpers SHARED - #SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp - SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp + SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp ) +endif() +target_link_libraries(m2i_helpers Trilinos::all_libs) + +function(make_mex fname) + if (APPLE) + matlab_add_mex_mac(NAME ${fname} + SHARED + SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp + ) + else() + matlab_add_mex(NAME ${fname} + SHARED + #SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp + SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp + ) + endif() target_link_libraries(${fname} Trilinos::all_libs) target_link_libraries(${fname} m2i_helpers) endfunction(make_mex) From b14d4ec586c8d477d612d6f6e528835ccef27ea0 Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Fri, 17 Jun 2022 15:18:02 -0600 Subject: [PATCH 12/37] Make intrelab libraries installable --- packages/intrepid/matlab/intrelab/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/intrepid/matlab/intrelab/CMakeLists.txt b/packages/intrepid/matlab/intrelab/CMakeLists.txt index 78b53c449960..f65c712a21ec 100644 --- a/packages/intrepid/matlab/intrelab/CMakeLists.txt +++ b/packages/intrepid/matlab/intrelab/CMakeLists.txt @@ -10,6 +10,7 @@ PROJECT(Intrelab) CMAKE_MINIMUM_REQUIRED(VERSION 3.10) +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) #set(MATLAB_FIND_DEBUG TRUE) # --> ACTION: define Trilinos install directory @@ -190,7 +191,6 @@ function(make_mex fname) else() matlab_add_mex(NAME ${fname} SHARED - #SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp ) endif() @@ -202,6 +202,10 @@ foreach(fname ${MOBJS}) make_mex(${fname}) endforeach() +install(TARGETS ${MOBJS} + DESTINATION ${CMAKE_INSTALL_PREFIX} +) + if(APPLE) message("\"*.dylib was built for newer macOS version (*.*) than being linked (10.9)\" type warnings can be safely ignored. MEX compiler specifies a -mmacosx-min-version=10.9, which can not be overridden.") endif(APPLE) From 2f6d8b356d313c40b21ce1b95d2ff8b313d04885 Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Fri, 17 Jun 2022 15:19:11 -0600 Subject: [PATCH 13/37] Change comment about matlab directory --- packages/intrepid/matlab/intrelab/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/intrepid/matlab/intrelab/CMakeLists.txt b/packages/intrepid/matlab/intrelab/CMakeLists.txt index f65c712a21ec..366eb680fc07 100644 --- a/packages/intrepid/matlab/intrelab/CMakeLists.txt +++ b/packages/intrepid/matlab/intrelab/CMakeLists.txt @@ -21,7 +21,7 @@ if(DEFINED ENV{TRILINOS_INSTALL_DIR}) endif() -# --> ACTION: define Matlab binary directory +# --> ACTION: define Matlab root directory #set(Matlab_ROOT_DIR "/Applications/MATLAB_R2020a.app/") set(Matlab_ROOT_DIR "/usr/local/matlab/R2021b/") if(DEFINED ENV{Matlab_ROOT_DIR}) From 4e027dbedf0a79caca141a019b4bdf9f2a7193b4 Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Wed, 22 Jun 2022 13:48:29 -0600 Subject: [PATCH 14/37] Remove custom matlab_add_mex_mac() --- .../intrepid/matlab/intrelab/CMakeLists.txt | 134 ++---------------- 1 file changed, 12 insertions(+), 122 deletions(-) diff --git a/packages/intrepid/matlab/intrelab/CMakeLists.txt b/packages/intrepid/matlab/intrelab/CMakeLists.txt index 366eb680fc07..b214fc0b89b0 100644 --- a/packages/intrepid/matlab/intrelab/CMakeLists.txt +++ b/packages/intrepid/matlab/intrelab/CMakeLists.txt @@ -14,16 +14,16 @@ set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) #set(MATLAB_FIND_DEBUG TRUE) # --> ACTION: define Trilinos install directory -#set(TRILINOS_INSTALL_DIR "/Users/pakuber/Compadre/Trilinos-intrelab/pthread/install_release") -set(TRILINOS_INSTALL_DIR "/ascldap/users/pakuber/Compadre/Trilinos-intrelab/build/install") +set(TRILINOS_INSTALL_DIR "/Users/pakuber/Compadre/Trilinos-intrelab/pthread/install_release") +#set(TRILINOS_INSTALL_DIR "/ascldap/users/pakuber/Compadre/Trilinos-intrelab/build/install") if(DEFINED ENV{TRILINOS_INSTALL_DIR}) set(TRILINOS_INSTALL_DIR $ENV{TRILINOS_INSTALL_DIR}) endif() # --> ACTION: define Matlab root directory -#set(Matlab_ROOT_DIR "/Applications/MATLAB_R2020a.app/") -set(Matlab_ROOT_DIR "/usr/local/matlab/R2021b/") +set(Matlab_ROOT_DIR "/Applications/MATLAB_R2020a.app/") +#set(Matlab_ROOT_DIR "/usr/local/matlab/R2021b/") if(DEFINED ENV{Matlab_ROOT_DIR}) set(Matlab_ROOT_DIR $ENV{Matlab_ROOT_DIR}) endif() @@ -57,145 +57,35 @@ if (APPLE) set(CMAKE_CXX_FLAGS "--sysroot=${CMAKE_OSX_SYSROOT} ${CMAKE_CXX_FLAGS}") endif(APPLE) -# fork of matlab_add_mex from FindMatlab.cmake from CMake@3.21.4 -# without symbol exporting and use of *.map files -function(matlab_add_mex_mac) - - if(NOT WIN32) - # we do not need all this on Windows - # pthread options - if(CMAKE_CXX_COMPILER_LOADED) - check_cxx_compiler_flag(-pthread HAS_MINUS_PTHREAD) - elseif(CMAKE_C_COMPILER_LOADED) - check_c_compiler_flag(-pthread HAS_MINUS_PTHREAD) - endif() - # we should use try_compile instead, the link flags are discarded from - # this compiler_flag function. - #check_cxx_compiler_flag(-Wl,--exclude-libs,ALL HAS_SYMBOL_HIDING_CAPABILITY) - - endif() - - set(options EXECUTABLE MODULE SHARED R2017b R2018a EXCLUDE_FROM_ALL) - set(oneValueArgs NAME DOCUMENTATION OUTPUT_NAME) - set(multiValueArgs LINK_TO SRC) - - set(prefix _matlab_addmex_prefix) - cmake_parse_arguments(${prefix} "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) - - if(NOT ${prefix}_NAME) - message(FATAL_ERROR "[MATLAB] The MEX target name cannot be empty") - endif() - - if(NOT ${prefix}_OUTPUT_NAME) - set(${prefix}_OUTPUT_NAME ${${prefix}_NAME}) - endif() - - if(NOT Matlab_VERSION_STRING VERSION_LESS "9.1") # For 9.1 (R2016b) and newer, add version source file - # Add the correct version file depending on which languages are enabled in the project - if(CMAKE_C_COMPILER_LOADED) - # If C is enabled, use the .c file as it will work fine also with C++ - set(MEX_VERSION_FILE "${Matlab_ROOT_DIR}/extern/version/c_mexapi_version.c") - elseif(CMAKE_CXX_COMPILER_LOADED) - # If C is not enabled, check if CXX is enabled and use the .cpp file - # to avoid that the .c file is silently ignored - set(MEX_VERSION_FILE "${Matlab_ROOT_DIR}/extern/version/cpp_mexapi_version.cpp") - else() - # If neither C or CXX is enabled, warn because we cannot add the source. - # TODO: add support for fortran mex files - message(WARNING "[MATLAB] matlab_add_mex requires that at least C or CXX are enabled languages") - endif() - endif() - - # For 9.4 (R2018a) and newer, add API macro. - # Add it for unknown versions too, just in case. - if(NOT Matlab_VERSION_STRING VERSION_LESS "9.4" - OR Matlab_VERSION_STRING STREQUAL "unknown") - if(${${prefix}_R2018a}) - set(MEX_API_MACRO "MATLAB_DEFAULT_RELEASE=R2018a") - else() - set(MEX_API_MACRO "MATLAB_DEFAULT_RELEASE=R2017b") - endif() - endif() - - set(_option_EXCLUDE_FROM_ALL) - if(${prefix}_EXCLUDE_FROM_ALL) - set(_option_EXCLUDE_FROM_ALL "EXCLUDE_FROM_ALL") - endif() - - if(${prefix}_EXECUTABLE) - add_executable(${${prefix}_NAME} - ${_option_EXCLUDE_FROM_ALL} - ${${prefix}_SRC} - ${MEX_VERSION_FILE} - ${${prefix}_DOCUMENTATION} - ${${prefix}_UNPARSED_ARGUMENTS}) - else() - if(${prefix}_MODULE) - set(type MODULE) - else() - set(type SHARED) - endif() - - add_library(${${prefix}_NAME} - ${type} - ${_option_EXCLUDE_FROM_ALL} - ${${prefix}_SRC} - ${MEX_VERSION_FILE} - ${${prefix}_DOCUMENTATION} - ${${prefix}_UNPARSED_ARGUMENTS}) - endif() - - target_include_directories(${${prefix}_NAME} PRIVATE ${Matlab_INCLUDE_DIRS}) - - if(Matlab_HAS_CPP_API) - if(Matlab_ENGINE_LIBRARY) - target_link_libraries(${${prefix}_NAME} ${Matlab_ENGINE_LIBRARY}) - endif() - if(Matlab_DATAARRAY_LIBRARY) - target_link_libraries(${${prefix}_NAME} ${Matlab_DATAARRAY_LIBRARY}) - endif() - endif() - - target_link_libraries(${${prefix}_NAME} ${Matlab_MEX_LIBRARY} ${Matlab_MX_LIBRARY} ${${prefix}_LINK_TO}) - set_target_properties(${${prefix}_NAME} - PROPERTIES - PREFIX "" - OUTPUT_NAME ${${prefix}_OUTPUT_NAME} - SUFFIX ".${Matlab_MEX_EXTENSION}") - - target_compile_definitions(${${prefix}_NAME} PRIVATE ${MEX_API_MACRO} MATLAB_MEX_FILE) - -endfunction(matlab_add_mex_mac) - set(MOBJS "intrepid_setJacobian;intrepid_setJacobianInv;intrepid_setJacobianDet;intrepid_getNumCubaturePoints;intrepid_getCubature;intrepid_getBasisValues;intrepid_computeCellMeasure;intrepid_HGRADtransformGRAD;intrepid_HGRADtransformVALUE;intrepid_multiplyMeasure;intrepid_integrate;intrepid_mapToPhysicalFrame;intrepid_mapToReferenceFrame;intrepid_scalarMultiplyDataField;intrepid_scalarMultiplyDataData;intrepid_dataIntegral;intrepid_evaluate;intrepid_multiplyVectorDataField;intrepid_dotMultiplyDataField;intrepid_vectorMultiplyDataField;intrepid_dotMultiplyDataData;intrepid_computeEdgeMeasure;intrepid_computeFaceMeasure;intrepid_getCellDeviatoricMat;intrepid_getCellVolumetricMat;intrepid_getPhysicalSideNormals;intrepid_mapToReferenceSubcell;intrepid_tensorMultiplyDataData;intrepid_tensorMultiplyDataField;defGrad;evaluateVectorField;evaluateVectorGradField;externalForceElastostaticsTL;geometricBmat;intrepid_det;intrepid_inverse;intrepid_transpose;materialBmat;strainEulerianLagrangian;stress;tangentStiffnessElastostaticsTL;tensorMultiplyDataField;myMatVecProductDataField;myMatVecProductDataData") if (APPLE) - matlab_add_mex_mac(NAME m2i_helpers - SHARED - SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp - ) + #matlab_add_mex(NAME m2i_helpers + # SHARED + # SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp + #) else() matlab_add_mex(NAME m2i_helpers SHARED SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp ) + target_link_libraries(m2i_helpers Trilinos::all_libs) endif() -target_link_libraries(m2i_helpers Trilinos::all_libs) function(make_mex fname) if (APPLE) - matlab_add_mex_mac(NAME ${fname} + matlab_add_mex(NAME ${fname} SHARED - SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp + SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp ) else() matlab_add_mex(NAME ${fname} SHARED SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp ) + target_link_libraries(${fname} m2i_helpers) endif() target_link_libraries(${fname} Trilinos::all_libs) - target_link_libraries(${fname} m2i_helpers) endfunction(make_mex) foreach(fname ${MOBJS}) From 0368ebf4fba517e5614960ff882fb60a309a8003 Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Fri, 24 Jun 2022 13:49:08 -0600 Subject: [PATCH 15/37] Removed redundant CXX flag copying --- .../intrepid/matlab/intrelab/CMakeLists.txt | 24 ++++--------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/packages/intrepid/matlab/intrelab/CMakeLists.txt b/packages/intrepid/matlab/intrelab/CMakeLists.txt index b214fc0b89b0..ec3e27cd535b 100644 --- a/packages/intrepid/matlab/intrelab/CMakeLists.txt +++ b/packages/intrepid/matlab/intrelab/CMakeLists.txt @@ -14,16 +14,16 @@ set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) #set(MATLAB_FIND_DEBUG TRUE) # --> ACTION: define Trilinos install directory -set(TRILINOS_INSTALL_DIR "/Users/pakuber/Compadre/Trilinos-intrelab/pthread/install_release") -#set(TRILINOS_INSTALL_DIR "/ascldap/users/pakuber/Compadre/Trilinos-intrelab/build/install") +#set(TRILINOS_INSTALL_DIR "/Users/pakuber/Compadre/Trilinos-intrelab/pthread/install_release") +set(TRILINOS_INSTALL_DIR "/ascldap/users/pakuber/Compadre/Trilinos-intrelab/build/install") if(DEFINED ENV{TRILINOS_INSTALL_DIR}) set(TRILINOS_INSTALL_DIR $ENV{TRILINOS_INSTALL_DIR}) endif() # --> ACTION: define Matlab root directory -set(Matlab_ROOT_DIR "/Applications/MATLAB_R2020a.app/") -#set(Matlab_ROOT_DIR "/usr/local/matlab/R2021b/") +#set(Matlab_ROOT_DIR "/Applications/MATLAB_R2020a.app/") +set(Matlab_ROOT_DIR "/usr/local/matlab/R2021b/") if(DEFINED ENV{Matlab_ROOT_DIR}) set(Matlab_ROOT_DIR $ENV{Matlab_ROOT_DIR}) endif() @@ -42,15 +42,6 @@ endif() FIND_PACKAGE(Trilinos REQUIRED) -# set compilers to Trilinos compilers -set(CMAKE_CXX_COMPILER ${Trilinos_CXX_COMPILER}) -set(CMAKE_C_COMPILER ${Trilinos_C_COMPILER}) - -# set flags to Trilinos flags -set(CMAKE_CXX_FLAGS ${Trilinos_CXX_COMPILER_FLAGS}) - -# Trilinos doesn't propagate its C++ standard -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -fPIC") if (APPLE) # Trilinos doesn't propagate its sysroot message(STATUS "CMAKE_OSX_SYSROOT: ${CMAKE_OSX_SYSROOT}") @@ -59,12 +50,7 @@ endif(APPLE) set(MOBJS "intrepid_setJacobian;intrepid_setJacobianInv;intrepid_setJacobianDet;intrepid_getNumCubaturePoints;intrepid_getCubature;intrepid_getBasisValues;intrepid_computeCellMeasure;intrepid_HGRADtransformGRAD;intrepid_HGRADtransformVALUE;intrepid_multiplyMeasure;intrepid_integrate;intrepid_mapToPhysicalFrame;intrepid_mapToReferenceFrame;intrepid_scalarMultiplyDataField;intrepid_scalarMultiplyDataData;intrepid_dataIntegral;intrepid_evaluate;intrepid_multiplyVectorDataField;intrepid_dotMultiplyDataField;intrepid_vectorMultiplyDataField;intrepid_dotMultiplyDataData;intrepid_computeEdgeMeasure;intrepid_computeFaceMeasure;intrepid_getCellDeviatoricMat;intrepid_getCellVolumetricMat;intrepid_getPhysicalSideNormals;intrepid_mapToReferenceSubcell;intrepid_tensorMultiplyDataData;intrepid_tensorMultiplyDataField;defGrad;evaluateVectorField;evaluateVectorGradField;externalForceElastostaticsTL;geometricBmat;intrepid_det;intrepid_inverse;intrepid_transpose;materialBmat;strainEulerianLagrangian;stress;tangentStiffnessElastostaticsTL;tensorMultiplyDataField;myMatVecProductDataField;myMatVecProductDataData") -if (APPLE) - #matlab_add_mex(NAME m2i_helpers - # SHARED - # SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp - #) -else() +if (NOT APPLE) matlab_add_mex(NAME m2i_helpers SHARED SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp From 4e000b4739b2a29e350a60f832702866082b13f8 Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Fri, 24 Jun 2022 13:51:42 -0600 Subject: [PATCH 16/37] Remove sysroot modification and warning for mac --- packages/intrepid/matlab/intrelab/CMakeLists.txt | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/packages/intrepid/matlab/intrelab/CMakeLists.txt b/packages/intrepid/matlab/intrelab/CMakeLists.txt index ec3e27cd535b..704a01d5a158 100644 --- a/packages/intrepid/matlab/intrelab/CMakeLists.txt +++ b/packages/intrepid/matlab/intrelab/CMakeLists.txt @@ -42,12 +42,6 @@ endif() FIND_PACKAGE(Trilinos REQUIRED) -if (APPLE) - # Trilinos doesn't propagate its sysroot - message(STATUS "CMAKE_OSX_SYSROOT: ${CMAKE_OSX_SYSROOT}") - set(CMAKE_CXX_FLAGS "--sysroot=${CMAKE_OSX_SYSROOT} ${CMAKE_CXX_FLAGS}") -endif(APPLE) - set(MOBJS "intrepid_setJacobian;intrepid_setJacobianInv;intrepid_setJacobianDet;intrepid_getNumCubaturePoints;intrepid_getCubature;intrepid_getBasisValues;intrepid_computeCellMeasure;intrepid_HGRADtransformGRAD;intrepid_HGRADtransformVALUE;intrepid_multiplyMeasure;intrepid_integrate;intrepid_mapToPhysicalFrame;intrepid_mapToReferenceFrame;intrepid_scalarMultiplyDataField;intrepid_scalarMultiplyDataData;intrepid_dataIntegral;intrepid_evaluate;intrepid_multiplyVectorDataField;intrepid_dotMultiplyDataField;intrepid_vectorMultiplyDataField;intrepid_dotMultiplyDataData;intrepid_computeEdgeMeasure;intrepid_computeFaceMeasure;intrepid_getCellDeviatoricMat;intrepid_getCellVolumetricMat;intrepid_getPhysicalSideNormals;intrepid_mapToReferenceSubcell;intrepid_tensorMultiplyDataData;intrepid_tensorMultiplyDataField;defGrad;evaluateVectorField;evaluateVectorGradField;externalForceElastostaticsTL;geometricBmat;intrepid_det;intrepid_inverse;intrepid_transpose;materialBmat;strainEulerianLagrangian;stress;tangentStiffnessElastostaticsTL;tensorMultiplyDataField;myMatVecProductDataField;myMatVecProductDataData") if (NOT APPLE) @@ -81,8 +75,3 @@ endforeach() install(TARGETS ${MOBJS} DESTINATION ${CMAKE_INSTALL_PREFIX} ) - -if(APPLE) - message("\"*.dylib was built for newer macOS version (*.*) than being linked (10.9)\" type warnings can be safely ignored. MEX compiler specifies a -mmacosx-min-version=10.9, which can not be overridden.") -endif(APPLE) - From fd94aa978df15957e627033834e2a1e937f89772 Mon Sep 17 00:00:00 2001 From: "Roscoe A. Bartlett" Date: Thu, 16 Jun 2022 17:22:41 -0600 Subject: [PATCH 17/37] Remove usage of old sems-archive modules These module load commands were bombing. The updated SPRAC module uses CMake 3.23.2. We can get an updated Ninja 1.10.1 from the new SEMS stack. --- cmake/std/atdm/cee-rhel7/environment.sh | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cmake/std/atdm/cee-rhel7/environment.sh b/cmake/std/atdm/cee-rhel7/environment.sh index f1e5311a6f6b..666c763779cd 100755 --- a/cmake/std/atdm/cee-rhel7/environment.sh +++ b/cmake/std/atdm/cee-rhel7/environment.sh @@ -195,10 +195,8 @@ fi # to be safe. Also, we need to set OMP_* env vars here because the SPARC # modules change them! -# Use updated Ninja and CMake -module load sems-archive-env -module load sems-archive-cmake/3.19.1 -module load sems-archive-ninja_fortran/1.8.2 +# Use updated Ninja +module load sems-ninja/1.10.1 export ATDM_CONFIG_USE_HWLOC=OFF From f9d943a24b6aa409c24dd567dffb0c764395714a Mon Sep 17 00:00:00 2001 From: "Roscoe A. Bartlett" Date: Thu, 16 Jun 2022 17:37:45 -0600 Subject: [PATCH 18/37] Just use the sems ninja that SPARC module uses The SEMS modules sems-ninja/1.10.1 seems to be broken. It fails on generation with CMake 3.23. So this current reverts to the Ninja: $ which ninja /usr/netpub/ninja/ninja $ ninja --version 1.7.2.git.kitware.dyndep-1 I guess that is good enough. --- cmake/std/atdm/cee-rhel7/environment.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/cmake/std/atdm/cee-rhel7/environment.sh b/cmake/std/atdm/cee-rhel7/environment.sh index 666c763779cd..b949cb70c00c 100755 --- a/cmake/std/atdm/cee-rhel7/environment.sh +++ b/cmake/std/atdm/cee-rhel7/environment.sh @@ -195,9 +195,6 @@ fi # to be safe. Also, we need to set OMP_* env vars here because the SPARC # modules change them! -# Use updated Ninja -module load sems-ninja/1.10.1 - export ATDM_CONFIG_USE_HWLOC=OFF export ATDM_CONFIG_BINUTILS_LIBS="/usr/lib64/libbfd.so;/usr/lib64/libiberty.a" From 52b8825e533812d721e38259215658cb1e1a9813 Mon Sep 17 00:00:00 2001 From: "Roscoe A. Bartlett" Date: Thu, 16 Jun 2022 16:29:21 -0600 Subject: [PATCH 19/37] Fix FindTPL.cmake files and TPL dependencies (TriBITSPub/TriBITS/#299) With new TriBITS, *all* FindTPL.cmake files must produce ::all_libs targets and a Config.cmake file. Also, with the new TriBITS implementation, we took out the sorting of TPLs by the TPL order. Therefore, to restore the correct TPL ordering, we need to tell CMake the ordering between the TPLs. For now, I am just hacking this by setting the var _LIB_ENABLED_DEPENDENCIES in until we can come up with offical support in TriBITS for FindTPLDependencies.cmake files. NOTE: You get link errors if you don't set these dependencies. This calls tribits_tpl_find_include_dirs_and_libraries(...) at the end to create the ::all_libs target and triggers the generation and install of the Config.cmake file. For the CUDA-related TPLs, for some reason, calling raw find_library() finds these libs okay but using the find_library() call inside of tribits_tpl_find_include_dirs_and_libraries() does not. I will have to debug that because these FindTPL.cmake files should be about two lines long. I tested this on several different Trilinos builds, including a CUDA build on 'vortex'. --- TPLsList.cmake | 12 ++++++++++++ cmake/TPLs/FindTPLCUBLAS.cmake | 7 ++++--- cmake/TPLs/FindTPLCUSOLVER.cmake | 7 ++++--- cmake/TPLs/FindTPLCUSPARSE.cmake | 7 ++++--- cmake/TPLs/FindTPLParMETIS.cmake | 4 +--- cmake/TPLs/FindTPLScotch.cmake | 4 +--- cmake/TPLs/FindTPLSuperLU.cmake | 4 +--- cmake/TPLs/FindTPLSuperLUDist.cmake | 6 ++---- 8 files changed, 29 insertions(+), 22 deletions(-) diff --git a/TPLsList.cmake b/TPLsList.cmake index 776288a4866d..0635187dcb9f 100644 --- a/TPLsList.cmake +++ b/TPLsList.cmake @@ -178,3 +178,15 @@ TRIBITS_REPOSITORY_DEFINE_TPLS( # ParMETIS include directories must come before the # Scotch include directories. # + + +# Temp hack for setting up TPL dependencies (until we support +# FindTPLDependencies.cmake files in #63). +advanced_set(LAPACK_LIB_ENABLED_DEPENDENCIES BLAS + CACHE STRING "LAPACK TPL deps") +advanced_set(ParMETIS_LIB_ENABLED_DEPENDENCIES METIS + CACHE STRING "ParMETIS TPL deps") +advanced_set(SuperLUDist_LIB_ENABLED_DEPENDENCIES ParMETIS BLAS + CACHE STRING "SuperLUDist TPL deps") +advanced_set(CUSPARSE_LIB_ENABLED_DEPENDENCIES CUBLAS + CACHE STRING "CUSPARSE TPL deps") diff --git a/cmake/TPLs/FindTPLCUBLAS.cmake b/cmake/TPLs/FindTPLCUBLAS.cmake index 8ce61e78e661..84b2cae78edc 100644 --- a/cmake/TPLs/FindTPLCUBLAS.cmake +++ b/cmake/TPLs/FindTPLCUBLAS.cmake @@ -63,8 +63,9 @@ ELSE() IF(CUDA_cublas_LIBRARY STREQUAL "CUDA_cublas_LIBRARY-NOTFOUND") MESSAGE(FATAL_ERROR "\nCUBLAS: could not find cublas library.") ENDIF() - GLOBAL_SET(TPL_CUBLAS_LIBRARY_DIRS) - GLOBAL_SET(TPL_CUBLAS_INCLUDE_DIRS ${TPL_CUDA_INCLUDE_DIRS}) - GLOBAL_SET(TPL_CUBLAS_LIBRARIES ${CUDA_cublas_LIBRARY}) + SET(TPL_CUBLAS_LIBRARIES ${CUDA_cublas_LIBRARY}) ENDIF() +tribits_tpl_find_include_dirs_and_libraries(CUBLAS REQUIRED_LIBS_NAMES cublas) + +unset(TPL_CUBLAS_LIBRARIES) diff --git a/cmake/TPLs/FindTPLCUSOLVER.cmake b/cmake/TPLs/FindTPLCUSOLVER.cmake index 7725cc028cfc..6750944c8b24 100644 --- a/cmake/TPLs/FindTPLCUSOLVER.cmake +++ b/cmake/TPLs/FindTPLCUSOLVER.cmake @@ -63,8 +63,9 @@ ELSE() IF(CUDA_cusolver_LIBRARY STREQUAL "CUDA_cusolver_LIBRARY-NOTFOUND") MESSAGE(FATAL_ERROR "\nCUSOLVER: could not find cusolver library.") ENDIF() - GLOBAL_SET(TPL_CUSOLVER_LIBRARY_DIRS) - GLOBAL_SET(TPL_CUSOLVER_INCLUDE_DIRS ${TPL_CUDA_INCLUDE_DIRS}) - GLOBAL_SET(TPL_CUSOLVER_LIBRARIES ${CUDA_cusolver_LIBRARY}) + SET(TPL_CUSOLVER_LIBRARIES ${CUDA_cusolver_LIBRARY}) ENDIF() +tribits_tpl_find_include_dirs_and_libraries(CUSOLVER REQUIRED_LIBS_NAMES cusparse) + +unset(TPL_CUSOLVER_LIBRARIES) diff --git a/cmake/TPLs/FindTPLCUSPARSE.cmake b/cmake/TPLs/FindTPLCUSPARSE.cmake index aad1e2bad762..b6a3859d1ffa 100644 --- a/cmake/TPLs/FindTPLCUSPARSE.cmake +++ b/cmake/TPLs/FindTPLCUSPARSE.cmake @@ -68,8 +68,9 @@ ELSE() MESSAGE(FATAL_ERROR "\nCUSPARSE: could not find cuspasre library.") ENDIF() ENDIF(CMAKE_VERSION VERSION_LESS "2.8.8") - GLOBAL_SET(TPL_CUSPARSE_LIBRARY_DIRS) - GLOBAL_SET(TPL_CUSPARSE_INCLUDE_DIRS ${TPL_CUDA_INCLUDE_DIRS}) - GLOBAL_SET(TPL_CUSPARSE_LIBRARIES ${CUDA_cusparse_LIBRARY}) + SET(TPL_CUSPARSE_LIBRARIES ${CUDA_cusparse_LIBRARY}) ENDIF() +tribits_tpl_find_include_dirs_and_libraries(CUSPARSE REQUIRED_LIBS_NAMES cusparse) + +unset(TPL_CUSPARSE_LIBRARIES) diff --git a/cmake/TPLs/FindTPLParMETIS.cmake b/cmake/TPLs/FindTPLParMETIS.cmake index ac97987e1713..e53218627b98 100644 --- a/cmake/TPLs/FindTPLParMETIS.cmake +++ b/cmake/TPLs/FindTPLParMETIS.cmake @@ -82,9 +82,7 @@ FUNCTION(CHECK_PARMETIS_HAS_VERSION_4_0_3 VARNAME) " ) - SET(CMAKE_REQUIRED_INCLUDES ${TPL_ParMETIS_INCLUDE_DIRS}) - SET(CMAKE_REQUIRED_LIBRARIES ${TPL_ParMETIS_LIBRARIES}) - SET(CMAKE_REQUIRED_FLAGS ${CMAKE_EXE_LINKER_FLAGS}) + SET(CMAKE_REQUIRED_LIBRARIES ParMETIS::all_libs) CHECK_C_SOURCE_COMPILES("${SOURCE}" ${VARNAME}) ENDFUNCTION() diff --git a/cmake/TPLs/FindTPLScotch.cmake b/cmake/TPLs/FindTPLScotch.cmake index f4de130a3c99..22c4c7c24860 100644 --- a/cmake/TPLs/FindTPLScotch.cmake +++ b/cmake/TPLs/FindTPLScotch.cmake @@ -94,9 +94,7 @@ FUNCTION(CHECK_SCOTCH_VERSION_6_0_3 VARNAME) } " ) - SET(CMAKE_REQUIRED_INCLUDES ${TPL_Scotch_INCLUDE_DIRS}) - SET(CMAKE_REQUIRED_LIBRARIES ${TPL_Scotch_LIBRARIES}) - SET(CMAKE_REQUIRED_FLAGS ${CMAKE_EXE_LINKER_FLAGS}) + SET(CMAKE_REQUIRED_LIBRARIES Scotch::all_libs) CHECK_C_SOURCE_COMPILES("${SOURCE}" ${VARNAME}) ENDFUNCTION() diff --git a/cmake/TPLs/FindTPLSuperLU.cmake b/cmake/TPLs/FindTPLSuperLU.cmake index 6ab392ccac8c..8446f0d4981c 100644 --- a/cmake/TPLs/FindTPLSuperLU.cmake +++ b/cmake/TPLs/FindTPLSuperLU.cmake @@ -89,9 +89,7 @@ int main() " ) - SET(CMAKE_REQUIRED_INCLUDES ${TPL_SuperLU_INCLUDE_DIRS}) - SET(CMAKE_REQUIRED_LIBRARIES ${TPL_SuperLU_LIBRARIES} ${TPL_METIS_LIBRARIES} ${TPL_BLAS_LIBRARIES}) - SET(CMAKE_REQUIRED_FLAGS ${CMAKE_EXE_LINKER_FLAGS}) + SET(CMAKE_REQUIRED_LIBRARIES SuperLU::all_libs ParMETIS::all_libs BLAS::all_libs) CHECK_C_SOURCE_COMPILES("${SOURCE}" ${VARNAME}) ENDFUNCTION() diff --git a/cmake/TPLs/FindTPLSuperLUDist.cmake b/cmake/TPLs/FindTPLSuperLUDist.cmake index 233e173b3d0e..e77da9d841c3 100644 --- a/cmake/TPLs/FindTPLSuperLUDist.cmake +++ b/cmake/TPLs/FindTPLSuperLUDist.cmake @@ -79,8 +79,7 @@ int main() " ) - SET(CMAKE_REQUIRED_INCLUDES ${TPL_SuperLUDist_INCLUDE_DIRS}) - SET(CMAKE_REQUIRED_LIBRARIES ${TPL_SuperLUDist_LIBRARIES} ${TPL_ParMETIS_LIBRARIES} ${TPL_METIS_LIBRARIES} ${TPL_BLAS_LIBRARIES}) + SET(CMAKE_REQUIRED_LIBRARIES SuperLUDist::all_libs ParMETIS::all_libs METIS::all_libs BLAS::all_libs) SET(CMAKE_REQUIRED_FLAGS ${CMAKE_EXE_LINKER_FLAGS}) CHECK_C_SOURCE_COMPILES("${SOURCE}" ${VARNAME}) ENDFUNCTION() @@ -101,8 +100,7 @@ int main() " ) - SET(CMAKE_REQUIRED_INCLUDES ${TPL_SuperLUDist_INCLUDE_DIRS}) - SET(CMAKE_REQUIRED_LIBRARIES ${TPL_SuperLUDist_LIBRARIES} ${TPL_ParMETIS_LIBRARIES} ${TPL_METIS_LIBRARIES} ${TPL_BLAS_LIBRARIES}) + SET(CMAKE_REQUIRED_LIBRARIES SuperLUDist::all_libs ParMETIS::all_libs METIS::all_libs BLAS::all_libs) SET(CMAKE_REQUIRED_FLAGS ${CMAKE_EXE_LINKER_FLAGS}) CHECK_C_SOURCE_COMPILES("${SOURCE}" ${VARNAME}) ENDFUNCTION() From b1afc4a1959dee45e65cd18b6d1c1a67250ff48a Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Tue, 28 Jun 2022 16:40:30 -0600 Subject: [PATCH 20/37] Support MATLAB_ROOT_DIR (all caps) variable setting --- packages/intrepid/matlab/intrelab/CMakeLists.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/intrepid/matlab/intrelab/CMakeLists.txt b/packages/intrepid/matlab/intrelab/CMakeLists.txt index 704a01d5a158..4a2ffa29746f 100644 --- a/packages/intrepid/matlab/intrelab/CMakeLists.txt +++ b/packages/intrepid/matlab/intrelab/CMakeLists.txt @@ -22,8 +22,21 @@ endif() # --> ACTION: define Matlab root directory + #set(Matlab_ROOT_DIR "/Applications/MATLAB_R2020a.app/") set(Matlab_ROOT_DIR "/usr/local/matlab/R2021b/") + +# allow for all caps version of variable +if (MATLAB_ROOT_DIR) + if (NOT Matlab_ROOT_DIR) + set(Matlab_ROOT_DIR ${MATLAB_ROOT_DIR}) + endif() +endif() + +# look for environment variable and give it precedence +if(DEFINED ENV{MATLAB_ROOT_DIR}) + set(Matlab_ROOT_DIR $ENV{MATLAB_ROOT_DIR}) +endif() if(DEFINED ENV{Matlab_ROOT_DIR}) set(Matlab_ROOT_DIR $ENV{Matlab_ROOT_DIR}) endif() From 7cb98be22eaf252c26d653522b9816b7cbd1a5d4 Mon Sep 17 00:00:00 2001 From: "Roscoe A. Bartlett" Date: Wed, 29 Jun 2022 10:22:59 -0600 Subject: [PATCH 21/37] Give Trilinos own FindTPL*.cmake modules for BLAS and LAPACK (TriBITSPub/TriBITS#299) Somehow, the Trilinos 'develop' branch got a different version of the modules tribits/common_tools/FindTPLBLAS.cmake and FindTPLLAPACK.cmake that what is in the TriBITS 'master' branch. That problem with that is that if you are building Trilinos with external TriBITS with: -DTrilinos_TRIBITS_DIR:STRING=TriBITS/tribits you get different behavior for finding BLAS and LAPACK than if you are using the versions in Trilinos. That is not good and it has cost people real lost time (e.g. the testing of Trilinos PR #10614 with an offline email discussion as part of working TriBITSPub/TriBITS#299). The fix implemented here was to: * Copy these modules from Trilinos/cmake/tribits/common_tools/ to Trilinos/cmake/TPLs/. * Point BLAS and LAPACK in Trilinos/TPLsList.cmake to FindTPL*.cmake files under cmake/TPLs/ instead of cmake/tribits/common_tools/. * Make the versions of the FindTPL*.cmake under cmake/tribits/common_tpls/ on the Trilinos develop branch to be identical to what is in the currently snapshotted version of TriBITS in the merged-in 'tribits_github_snapshot' branch. The current version of TriBITS 'master' snapshotted in is given in the most current snapshotted commit: commit fb578c9143f5489488b7adc0ddbb253eee9eed66 (github/tribits_github_snapshot, tribits_github_snapshot) Author: Roscoe A. Bartlett Date: Fri Jun 10 13:40:24 2022 -0600 Automatic snapshot commit from tribits at e82c4544 Origin repo remote tracking branch: 'github/master' Origin repo remote repo URL: 'github = git@github.com:TriBITSPub/TriBITS.git' At commit: commit e82c4544fbd50769b85bab45cb98ef009ca4643c Author: Roscoe A. Bartlett Date: Fri Jun 10 11:08:38 2022 -0600 Summary: Remove internal quotes for git log --pretty=format: strings (#485) Later, we could sync up the FindTPLBLAS.cmake and FindTPLLAPACK.cmake modules but that will break someone's backward compatibility. --- TPLsList.cmake | 4 +- cmake/TPLs/FindTPLBLAS.cmake | 80 +++++++++++++++++++ cmake/TPLs/FindTPLLAPACK.cmake | 74 +++++++++++++++++ cmake/tribits/common_tpls/FindTPLBLAS.cmake | 35 +++++++- cmake/tribits/common_tpls/FindTPLLAPACK.cmake | 41 +++++++++- 5 files changed, 229 insertions(+), 5 deletions(-) create mode 100644 cmake/TPLs/FindTPLBLAS.cmake create mode 100644 cmake/TPLs/FindTPLLAPACK.cmake diff --git a/TPLsList.cmake b/TPLsList.cmake index 0635187dcb9f..fbfc86a5305c 100644 --- a/TPLsList.cmake +++ b/TPLsList.cmake @@ -71,8 +71,8 @@ TRIBITS_REPOSITORY_DEFINE_TPLS( ARPREC "packages/teuchos/cmake/tpls/" ST QD "packages/teuchos/cmake/tpls/" ST MPI "${${PROJECT_NAME}_TRIBITS_DIR}/core/std_tpls/" PT - BLAS "${${PROJECT_NAME}_TRIBITS_DIR}/common_tpls/" PT - LAPACK "${${PROJECT_NAME}_TRIBITS_DIR}/common_tpls/" PT + BLAS "cmake/TPLs/" PT + LAPACK "cmake/TPLs/" PT Boost "${${PROJECT_NAME}_TRIBITS_DIR}/common_tpls/" PT Scotch "cmake/TPLs/" ST OVIS "cmake/TPLs/" ST diff --git a/cmake/TPLs/FindTPLBLAS.cmake b/cmake/TPLs/FindTPLBLAS.cmake new file mode 100644 index 000000000000..dc04355fdd26 --- /dev/null +++ b/cmake/TPLs/FindTPLBLAS.cmake @@ -0,0 +1,80 @@ +# @HEADER +# ************************************************************************ +# +# Trilinos: An Object-Oriented Solver Framework +# Copyright (2001) Sandia Corporation +# +# +# Copyright (2001) Sandia Corporation. Under the terms of Contract +# DE-AC04-94AL85000, there is a non-exclusive license for use of this +# work by or on behalf of the U.S. Government. Export of this program +# may require a license from the United States Government. +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Corporation nor the names of the +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# NOTICE: The United States Government is granted for itself and others +# acting on its behalf a paid-up, nonexclusive, irrevocable worldwide +# license in this data to reproduce, prepare derivative works, and +# perform publicly and display publicly. Beginning five (5) years from +# July 25, 2001, the United States Government is granted for itself and +# others acting on its behalf a paid-up, nonexclusive, irrevocable +# worldwide license in this data to reproduce, prepare derivative works, +# distribute copies to the public, perform publicly and display +# publicly, and to permit others to do so. +# +# NEITHER THE UNITED STATES GOVERNMENT, NOR THE UNITED STATES DEPARTMENT +# OF ENERGY, NOR SANDIA CORPORATION, NOR ANY OF THEIR EMPLOYEES, MAKES +# ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL LIABILITY OR +# RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR USEFULNESS OF ANY +# INFORMATION, APPARATUS, PRODUCT, OR PROCESS DISCLOSED, OR REPRESENTS +# THAT ITS USE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS. +# +# ************************************************************************ +# @HEADER + + +if (MSVC AND NOT + (BLAS_LIBRARY_DIRS OR + (NOT "${BLAS_LIBRARY_NAMES}" STREQUAL "blas blas_win32" AND + NOT "${BLAS_LIBRARY_NAMES}" STREQUAL "") OR + BLAS_INCLUDE_DIRS OR + BLAS_INCLUDE_NAMES OR + (NOT "${TPL_BLAS_LIBRARIES}" STREQUAL "blas" AND + NOT "${TPL_BLAS_LIBRARIES}" STREQUAL "") OR + TPL_BLAS_INCLUDE_DIRS) + ) + # Find the CLAPACK built by CMake on the machine for MSVC if found it will + # set the BLAS and LAPACK libraries. NOTE: This the FindCLAPACK module must + # be called every configure or this does not work! + # If the user has specified alternate name or location of their blas that + # will be used instead. + find_package(CLAPACK 3.2.1 NO_MODULE) + if (CLAPACK_FOUND) + advanced_set(TPL_BLAS_LIBRARIES blas + CACHE FILEPATH "Set from MSVC CLAPACK specialization") + endif() +endif() + +tribits_tpl_find_include_dirs_and_libraries( BLAS + REQUIRED_LIBS_NAMES "blas blas_win32") diff --git a/cmake/TPLs/FindTPLLAPACK.cmake b/cmake/TPLs/FindTPLLAPACK.cmake new file mode 100644 index 000000000000..443924df0d7a --- /dev/null +++ b/cmake/TPLs/FindTPLLAPACK.cmake @@ -0,0 +1,74 @@ +# @HEADER +# ************************************************************************ +# +# Trilinos: An Object-Oriented Solver Framework +# Copyright (2001) Sandia Corporation +# +# +# Copyright (2001) Sandia Corporation. Under the terms of Contract +# DE-AC04-94AL85000, there is a non-exclusive license for use of this +# work by or on behalf of the U.S. Government. Export of this program +# may require a license from the United States Government. +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Corporation nor the names of the +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# NOTICE: The United States Government is granted for itself and others +# acting on its behalf a paid-up, nonexclusive, irrevocable worldwide +# license in this data to reproduce, prepare derivative works, and +# perform publicly and display publicly. Beginning five (5) years from +# July 25, 2001, the United States Government is granted for itself and +# others acting on its behalf a paid-up, nonexclusive, irrevocable +# worldwide license in this data to reproduce, prepare derivative works, +# distribute copies to the public, perform publicly and display +# publicly, and to permit others to do so. +# +# NEITHER THE UNITED STATES GOVERNMENT, NOR THE UNITED STATES DEPARTMENT +# OF ENERGY, NOR SANDIA CORPORATION, NOR ANY OF THEIR EMPLOYEES, MAKES +# ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL LIABILITY OR +# RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR USEFULNESS OF ANY +# INFORMATION, APPARATUS, PRODUCT, OR PROCESS DISCLOSED, OR REPRESENTS +# THAT ITS USE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS. +# +# ************************************************************************ +# @HEADER + + +if (MSVC AND NOT + (LAPACK_LIBRARY_DIRS OR + (NOT "${LAPACK_LIBRARY_NAMES}" STREQUAL "lapack lapack_win32" AND + NOT "${LAPACK_LIBRARY_NAMES}" STREQUAL "") OR + LAPACK_INCLUDE_DIRS OR + LAPACK_INCLUDE_NAMES OR + (NOT "${TPL_LAPACK_LIBRARIES}" STREQUAL "lapack" AND + NOT "${TPL_LAPACK_LIBRARIES}" STREQUAL "") OR + TPL_LAPACK_INCLUDE_DIRS) + ) + if(CLAPACK_FOUND) + advanced_set(TPL_LAPACK_LIBRARIES lapack + CACHE FILEPATH "Set from MSVC CLAPACK specialization") + endif() +endif() + +tribits_tpl_find_include_dirs_and_libraries( LAPACK + REQUIRED_LIBS_NAMES "lapack lapack_win32") diff --git a/cmake/tribits/common_tpls/FindTPLBLAS.cmake b/cmake/tribits/common_tpls/FindTPLBLAS.cmake index dc04355fdd26..78ba327150e2 100644 --- a/cmake/tribits/common_tpls/FindTPLBLAS.cmake +++ b/cmake/tribits/common_tpls/FindTPLBLAS.cmake @@ -54,6 +54,31 @@ # @HEADER +set(REQUIRED_LIBS_NAMES "blas blas_win32") + +# +# Second, search for BLAS components (if allowed) using the standard +# find_package(BLAS ...). +# +tribits_tpl_allow_pre_find_package(BLAS BLAS_ALLOW_PREFIND) +if (BLAS_ALLOW_PREFIND) + + message("-- Using find_package(BLAS ...) ...") + + find_package(BLAS) + + if (BLAS_FOUND) + # Tell TriBITS that we found BLAS and there no need to look any further! + set(TPL_BLAS_INCLUDE_DIRS "" CACHE PATH + "BLAS include dirs") + set(TPL_BLAS_LIBRARIES ${BLAS_LIBRARIES} CACHE FILEPATH + "BLAS libraries") + set(TPL_BLAS_LIBRARY_DIRS "" CACHE PATH + "BLAS library dirs") + endif() + +endif() + if (MSVC AND NOT (BLAS_LIBRARY_DIRS OR (NOT "${BLAS_LIBRARY_NAMES}" STREQUAL "blas blas_win32" AND @@ -75,6 +100,12 @@ if (MSVC AND NOT CACHE FILEPATH "Set from MSVC CLAPACK specialization") endif() endif() - +# +# Third, call tribits_tpl_find_include_dirs_and_libraries() +# tribits_tpl_find_include_dirs_and_libraries( BLAS - REQUIRED_LIBS_NAMES "blas blas_win32") + REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} + ) +# NOTE: If find_package(BLAS ...) was called and successfully found BLAS, then +# tribits_tpl_find_include_dirs_and_libraries() will use the already-set +# variables TPL_BLAS_INCLUDE_DIRS and TPL_BLAS_LIBRARIES and then print them diff --git a/cmake/tribits/common_tpls/FindTPLLAPACK.cmake b/cmake/tribits/common_tpls/FindTPLLAPACK.cmake index 443924df0d7a..5e8d9724200b 100644 --- a/cmake/tribits/common_tpls/FindTPLLAPACK.cmake +++ b/cmake/tribits/common_tpls/FindTPLLAPACK.cmake @@ -53,6 +53,37 @@ # ************************************************************************ # @HEADER +# +# First, set up the variables for the (backward-compatible) TriBITS way of +# finding LAPACK. These are used in case find_package(LAPACK ...) is not called +# or does not find LAPACK. Also, these variables need to be non-null in order +# to trigger the right behavior in the function +# tribits_tpl_find_include_dirs_and_libraries(). +# +set(REQUIRED_LIBS_NAMES "lapack lapack_win32") + +# +# Second, search for LAPACK components (if allowed) using the standard +# find_package(LAPACK ...). +# +tribits_tpl_allow_pre_find_package(LAPACK LAPACK_ALLOW_PREFIND) +if (LAPACK_ALLOW_PREFIND) + + message("-- Using find_package(LAPACK ...) ...") + + find_package(LAPACK) + + if (LAPACK_FOUND) + # Tell TriBITS that we found LAPACK and there no need to look any further! + set(TPL_LAPACK_INCLUDE_DIRS "" CACHE PATH + "LAPACK include dirs") + set(TPL_LAPACK_LIBRARIES ${LAPACK_LIBRARIES} CACHE FILEPATH + "LAPACK libraries") + set(TPL_LAPACK_LIBRARY_DIRS "" CACHE PATH + "LAPACK library dirs") + endif() + +endif() if (MSVC AND NOT (LAPACK_LIBRARY_DIRS OR @@ -70,5 +101,13 @@ if (MSVC AND NOT endif() endif() +# +# Third, call tribits_tpl_find_include_dirs_and_libraries() +# tribits_tpl_find_include_dirs_and_libraries( LAPACK - REQUIRED_LIBS_NAMES "lapack lapack_win32") + REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} + ) +# NOTE: If find_package(LAPACK ...) was called and successfully found LAPACK, then +# tribits_tpl_find_include_dirs_and_libraries() will use the already-set +# variables TPL_LAPACK_INCLUDE_DIRS and TPL_LAPACK_LIBRARIES and then print them +# out (and set some other standard variables as well). This is the final From 567eb286135e1398afbe5e759af2b2fc6c764800 Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Wed, 29 Jun 2022 12:53:34 -0600 Subject: [PATCH 22/37] Removed m2i_helpers as a target and moved it to a source --- .../intrepid/matlab/intrelab/CMakeLists.txt | 22 +++---------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/packages/intrepid/matlab/intrelab/CMakeLists.txt b/packages/intrepid/matlab/intrelab/CMakeLists.txt index 4a2ffa29746f..c9d41dfd8ad5 100644 --- a/packages/intrepid/matlab/intrelab/CMakeLists.txt +++ b/packages/intrepid/matlab/intrelab/CMakeLists.txt @@ -57,27 +57,11 @@ FIND_PACKAGE(Trilinos REQUIRED) set(MOBJS "intrepid_setJacobian;intrepid_setJacobianInv;intrepid_setJacobianDet;intrepid_getNumCubaturePoints;intrepid_getCubature;intrepid_getBasisValues;intrepid_computeCellMeasure;intrepid_HGRADtransformGRAD;intrepid_HGRADtransformVALUE;intrepid_multiplyMeasure;intrepid_integrate;intrepid_mapToPhysicalFrame;intrepid_mapToReferenceFrame;intrepid_scalarMultiplyDataField;intrepid_scalarMultiplyDataData;intrepid_dataIntegral;intrepid_evaluate;intrepid_multiplyVectorDataField;intrepid_dotMultiplyDataField;intrepid_vectorMultiplyDataField;intrepid_dotMultiplyDataData;intrepid_computeEdgeMeasure;intrepid_computeFaceMeasure;intrepid_getCellDeviatoricMat;intrepid_getCellVolumetricMat;intrepid_getPhysicalSideNormals;intrepid_mapToReferenceSubcell;intrepid_tensorMultiplyDataData;intrepid_tensorMultiplyDataField;defGrad;evaluateVectorField;evaluateVectorGradField;externalForceElastostaticsTL;geometricBmat;intrepid_det;intrepid_inverse;intrepid_transpose;materialBmat;strainEulerianLagrangian;stress;tangentStiffnessElastostaticsTL;tensorMultiplyDataField;myMatVecProductDataField;myMatVecProductDataData") -if (NOT APPLE) - matlab_add_mex(NAME m2i_helpers +function(make_mex fname) + matlab_add_mex(NAME ${fname} SHARED - SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp + SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp ) - target_link_libraries(m2i_helpers Trilinos::all_libs) -endif() - -function(make_mex fname) - if (APPLE) - matlab_add_mex(NAME ${fname} - SHARED - SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp - ) - else() - matlab_add_mex(NAME ${fname} - SHARED - SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp - ) - target_link_libraries(${fname} m2i_helpers) - endif() target_link_libraries(${fname} Trilinos::all_libs) endfunction(make_mex) From b9aa9d0d390ce128e9f4c611d5f67ef2d5969ae3 Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Tue, 5 Jul 2022 07:03:24 -0600 Subject: [PATCH 23/37] Update CMake version, installation variables, and formatting - Changes from requiring CMake 3.10 to 3.12 to ensure "*_ROOT" is supported - Reformat MOBJS list - Change variable modification to work with Matlab_ROOT, MATLAB_ROOT, Matlab_ROOT_DIR, and MATLAB_ROOT_DIR as well as Trilinos_ROOT and TRILINOS_ROOT --- .../intrepid/matlab/intrelab/CMakeLists.txt | 89 ++++++++++++++----- 1 file changed, 68 insertions(+), 21 deletions(-) diff --git a/packages/intrepid/matlab/intrelab/CMakeLists.txt b/packages/intrepid/matlab/intrelab/CMakeLists.txt index c9d41dfd8ad5..2bd69c0b33d8 100644 --- a/packages/intrepid/matlab/intrelab/CMakeLists.txt +++ b/packages/intrepid/matlab/intrelab/CMakeLists.txt @@ -9,43 +9,76 @@ # PROJECT(Intrelab) -CMAKE_MINIMUM_REQUIRED(VERSION 3.10) +CMAKE_MINIMUM_REQUIRED(VERSION 3.12) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) -#set(MATLAB_FIND_DEBUG TRUE) +set(MATLAB_FIND_DEBUG TRUE) -# --> ACTION: define Trilinos install directory -#set(TRILINOS_INSTALL_DIR "/Users/pakuber/Compadre/Trilinos-intrelab/pthread/install_release") -set(TRILINOS_INSTALL_DIR "/ascldap/users/pakuber/Compadre/Trilinos-intrelab/build/install") -if(DEFINED ENV{TRILINOS_INSTALL_DIR}) - set(TRILINOS_INSTALL_DIR $ENV{TRILINOS_INSTALL_DIR}) -endif() - - -# --> ACTION: define Matlab root directory - -#set(Matlab_ROOT_DIR "/Applications/MATLAB_R2020a.app/") -set(Matlab_ROOT_DIR "/usr/local/matlab/R2021b/") +# --> ACTIONS: +# 1.) Specify Trilinos install directory with -DTrilinos_ROOT= (case-sensitive) +# 2.) Specify Matlab install directory with -DMatlab_ROOT_DIR= (case-sensitive and note extra _DIR) +# 3.) Specify directory to install intrelab -DINST_DIR= (case-sensitive) -# allow for all caps version of variable +# handle Matlab_ROOT_DIR and all variants +# allow for {Matlab_ROOT_DIR, MATLAB_ROOT_DIR, Matlab_ROOT, MATLAB_ROOT} if (MATLAB_ROOT_DIR) if (NOT Matlab_ROOT_DIR) set(Matlab_ROOT_DIR ${MATLAB_ROOT_DIR}) endif() endif() - +if (Matlab_ROOT) + if (NOT Matlab_ROOT_DIR) + set(Matlab_ROOT_DIR ${Matlab_ROOT}) + endif() +endif() +if (MATLAB_ROOT) + if (NOT Matlab_ROOT_DIR) + set(Matlab_ROOT_DIR ${MATLAB_ROOT}) + endif() +endif() # look for environment variable and give it precedence +# allow for {MATLAB_ROOT, Matlab_ROOT, MATLAB_ROOT_DIR, Matlab_ROOT_DIR} +if(DEFINED ENV{MATLAB_ROOT}) + set(Matlab_ROOT_DIR $ENV{MATLAB_ROOT}) +endif() +if(DEFINED ENV{Matlab_ROOT}) + set(Matlab_ROOT_DIR $ENV{Matlab_ROOT}) +endif() if(DEFINED ENV{MATLAB_ROOT_DIR}) set(Matlab_ROOT_DIR $ENV{MATLAB_ROOT_DIR}) endif() if(DEFINED ENV{Matlab_ROOT_DIR}) set(Matlab_ROOT_DIR $ENV{Matlab_ROOT_DIR}) endif() +if (NOT Matlab_ROOT_DIR) + message(WARNING "Matlab_ROOT_DIR has NOT been specified.") +endif() + find_package(Matlab REQUIRED) +# handle Trilinos_ROOT and all variants +# allow for {Trilinos_ROOT, TRILINOS_ROOT} +if (TRILINOS_ROOT) + if (NOT Trilinos_ROOT) + set(Trilinos_ROOT ${TRILINOS_ROOT}) + endif() +endif() +# look for environment variable and give it precedence +# allow for {Trilinos_ROOT, TRILINOS_ROOT} +if(DEFINED ENV{TRILINOS_ROOT}) + set(Trilinos_ROOT $ENV{TRILINOS_ROOT}) +endif() +if(DEFINED ENV{Trilinos_ROOT}) + set(Trilinos_ROOT $ENV{Trilinos_ROOT}) +endif() +if (NOT Trilinos_ROOT) + message(WARNING "Trilinos_ROOT has NOT been specified.") +endif() + +FIND_PACKAGE(Trilinos REQUIRED) + # --> ACTION: define install directory (full path or relative to the intrelab directory) set(INST_DIR "install") - set(CMAKE_PREFIX_PATH ${TRILINOS_INSTALL_DIR} ${CMAKE_PREFIX_PATH}) if(IS_ABSOLUTE ${INST_DIR}) set(CMAKE_INSTALL_PREFIX ${INST_DIR}) @@ -53,9 +86,23 @@ else() set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/${INST_DIR}") endif() -FIND_PACKAGE(Trilinos REQUIRED) - -set(MOBJS "intrepid_setJacobian;intrepid_setJacobianInv;intrepid_setJacobianDet;intrepid_getNumCubaturePoints;intrepid_getCubature;intrepid_getBasisValues;intrepid_computeCellMeasure;intrepid_HGRADtransformGRAD;intrepid_HGRADtransformVALUE;intrepid_multiplyMeasure;intrepid_integrate;intrepid_mapToPhysicalFrame;intrepid_mapToReferenceFrame;intrepid_scalarMultiplyDataField;intrepid_scalarMultiplyDataData;intrepid_dataIntegral;intrepid_evaluate;intrepid_multiplyVectorDataField;intrepid_dotMultiplyDataField;intrepid_vectorMultiplyDataField;intrepid_dotMultiplyDataData;intrepid_computeEdgeMeasure;intrepid_computeFaceMeasure;intrepid_getCellDeviatoricMat;intrepid_getCellVolumetricMat;intrepid_getPhysicalSideNormals;intrepid_mapToReferenceSubcell;intrepid_tensorMultiplyDataData;intrepid_tensorMultiplyDataField;defGrad;evaluateVectorField;evaluateVectorGradField;externalForceElastostaticsTL;geometricBmat;intrepid_det;intrepid_inverse;intrepid_transpose;materialBmat;strainEulerianLagrangian;stress;tangentStiffnessElastostaticsTL;tensorMultiplyDataField;myMatVecProductDataField;myMatVecProductDataData") +set(MOBJS intrepid_setJacobian intrepid_setJacobianInv intrepid_setJacobianDet + intrepid_getNumCubaturePoints intrepid_getCubature intrepid_getBasisValues + intrepid_computeCellMeasure intrepid_HGRADtransformGRAD + intrepid_HGRADtransformVALUE intrepid_multiplyMeasure intrepid_integrate + intrepid_mapToPhysicalFrame intrepid_mapToReferenceFrame + intrepid_scalarMultiplyDataField intrepid_scalarMultiplyDataData + intrepid_dataIntegral intrepid_evaluate intrepid_multiplyVectorDataField + intrepid_dotMultiplyDataField intrepid_vectorMultiplyDataField + intrepid_dotMultiplyDataData intrepid_computeEdgeMeasure + intrepid_computeFaceMeasure intrepid_getCellDeviatoricMat + intrepid_getCellVolumetricMat intrepid_getPhysicalSideNormals + intrepid_mapToReferenceSubcell intrepid_tensorMultiplyDataData + intrepid_tensorMultiplyDataField defGrad;evaluateVectorField + evaluateVectorGradField externalForceElastostaticsTL geometricBmat + intrepid_det intrepid_inverse intrepid_transpose materialBmat + strainEulerianLagrangian stress tangentStiffnessElastostaticsTL + tensorMultiplyDataField myMatVecProductDataField myMatVecProductDataData) function(make_mex fname) matlab_add_mex(NAME ${fname} @@ -63,7 +110,7 @@ function(make_mex fname) SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp ) target_link_libraries(${fname} Trilinos::all_libs) -endfunction(make_mex) +endfunction() foreach(fname ${MOBJS}) make_mex(${fname}) From 02c6880d81a79c472e719e726a9af2ee5db421da Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Tue, 5 Jul 2022 09:03:13 -0600 Subject: [PATCH 24/37] Switch from Trilinos::all_libs to Trilinos::all_selected_libs --- packages/intrepid/matlab/intrelab/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/intrepid/matlab/intrelab/CMakeLists.txt b/packages/intrepid/matlab/intrelab/CMakeLists.txt index 2bd69c0b33d8..531ff812aee7 100644 --- a/packages/intrepid/matlab/intrelab/CMakeLists.txt +++ b/packages/intrepid/matlab/intrelab/CMakeLists.txt @@ -74,7 +74,7 @@ if (NOT Trilinos_ROOT) message(WARNING "Trilinos_ROOT has NOT been specified.") endif() -FIND_PACKAGE(Trilinos REQUIRED) +FIND_PACKAGE(Trilinos COMPONENTS Intrepid REQUIRED) # --> ACTION: define install directory (full path or relative to the intrelab directory) set(INST_DIR "install") @@ -109,7 +109,7 @@ function(make_mex fname) SHARED SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp ) - target_link_libraries(${fname} Trilinos::all_libs) + target_link_libraries(${fname} Trilinos::all_selected_libs) endfunction() foreach(fname ${MOBJS}) From f772b2a9d9effea14d2e27cf441f5a357f0eb18f Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Tue, 5 Jul 2022 11:54:12 -0600 Subject: [PATCH 25/37] Change required CMake version to 3.17.0 and support Trilinos_DIR - Adds -O3, -mtune, -march flags for Release builds --- .../intrepid/matlab/intrelab/CMakeLists.txt | 49 ++++++++++++------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/packages/intrepid/matlab/intrelab/CMakeLists.txt b/packages/intrepid/matlab/intrelab/CMakeLists.txt index 531ff812aee7..091599d001cc 100644 --- a/packages/intrepid/matlab/intrelab/CMakeLists.txt +++ b/packages/intrepid/matlab/intrelab/CMakeLists.txt @@ -9,31 +9,25 @@ # PROJECT(Intrelab) -CMAKE_MINIMUM_REQUIRED(VERSION 3.12) +CMAKE_MINIMUM_REQUIRED(VERSION 3.17.0 FATAL_ERROR) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) set(MATLAB_FIND_DEBUG TRUE) # --> ACTIONS: -# 1.) Specify Trilinos install directory with -DTrilinos_ROOT= (case-sensitive) -# 2.) Specify Matlab install directory with -DMatlab_ROOT_DIR= (case-sensitive and note extra _DIR) -# 3.) Specify directory to install intrelab -DINST_DIR= (case-sensitive) +# 1.) Specify Trilinos install directory with -DTrilinos_ROOT = (case-sensitive) +# 2.) Specify Matlab install directory with -DMatlab_ROOT_DIR = (case-sensitive and note extra _DIR) +# 3.) Specify directory to install intrelab -DINST_DIR = (case-sensitive) # handle Matlab_ROOT_DIR and all variants # allow for {Matlab_ROOT_DIR, MATLAB_ROOT_DIR, Matlab_ROOT, MATLAB_ROOT} if (MATLAB_ROOT_DIR) - if (NOT Matlab_ROOT_DIR) - set(Matlab_ROOT_DIR ${MATLAB_ROOT_DIR}) - endif() + set(Matlab_ROOT_DIR ${MATLAB_ROOT_DIR}) endif() if (Matlab_ROOT) - if (NOT Matlab_ROOT_DIR) - set(Matlab_ROOT_DIR ${Matlab_ROOT}) - endif() + set(Matlab_ROOT_DIR ${Matlab_ROOT}) endif() if (MATLAB_ROOT) - if (NOT Matlab_ROOT_DIR) - set(Matlab_ROOT_DIR ${MATLAB_ROOT}) - endif() + set(Matlab_ROOT_DIR ${MATLAB_ROOT}) endif() # look for environment variable and give it precedence # allow for {MATLAB_ROOT, Matlab_ROOT, MATLAB_ROOT_DIR, Matlab_ROOT_DIR} @@ -52,30 +46,43 @@ endif() if (NOT Matlab_ROOT_DIR) message(WARNING "Matlab_ROOT_DIR has NOT been specified.") endif() +set(Matlab_ROOT_DIR "${Matlab_ROOT_DIR}" CACHE STRING "Matlab installation directory") find_package(Matlab REQUIRED) # handle Trilinos_ROOT and all variants -# allow for {Trilinos_ROOT, TRILINOS_ROOT} +# allow for {Trilinos_DIR, TRILINOS_DIR, Trilinos_ROOT, TRILINOS_ROOT} +if (TRILINOS_DIR) + set(Trilinos_ROOT ${TRILINOS_DIR}) +endif() +if (Trilinos_DIR) + set(Trilinos_ROOT ${Trilinos_DIR}) +endif() if (TRILINOS_ROOT) - if (NOT Trilinos_ROOT) - set(Trilinos_ROOT ${TRILINOS_ROOT}) - endif() + set(Trilinos_ROOT ${TRILINOS_ROOT}) endif() # look for environment variable and give it precedence -# allow for {Trilinos_ROOT, TRILINOS_ROOT} if(DEFINED ENV{TRILINOS_ROOT}) set(Trilinos_ROOT $ENV{TRILINOS_ROOT}) endif() if(DEFINED ENV{Trilinos_ROOT}) set(Trilinos_ROOT $ENV{Trilinos_ROOT}) endif() -if (NOT Trilinos_ROOT) +if(DEFINED ENV{TRILINOS_DIR}) + set(Trilinos_ROOT $ENV{TRILINOS_DIR}) +endif() +if(DEFINED ENV{Trilinos_DIR}) + set(Trilinos_ROOT $ENV{Trilinos_DIR}) +endif() +message(WARNING "Trilinos_ROOT: ${Trilinos_ROOT}") +if ("${Trilinos_ROOT}" STREQUAL "") message(WARNING "Trilinos_ROOT has NOT been specified.") endif() +set(Trilinos_ROOT "${Trilinos_ROOT}" CACHE STRING "Trilinos installation directory") FIND_PACKAGE(Trilinos COMPONENTS Intrepid REQUIRED) + # --> ACTION: define install directory (full path or relative to the intrelab directory) set(INST_DIR "install") @@ -104,12 +111,16 @@ set(MOBJS intrepid_setJacobian intrepid_setJacobianInv intrepid_setJacobianDet strainEulerianLagrangian stress tangentStiffnessElastostaticsTL tensorMultiplyDataField myMatVecProductDataField myMatVecProductDataData) +string(TOLOWER "${Trilinos_CMAKE_BUILD_TYPE}" Trilinos_CMAKE_BUILD_TYPE_lower) function(make_mex fname) matlab_add_mex(NAME ${fname} SHARED SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp ) target_link_libraries(${fname} Trilinos::all_selected_libs) + if(Trilinos_CMAKE_BUILD_TYPE_lower STREQUAL "release") + target_compile_options(${fname} PRIVATE "-O3;-march=native;-mtune=native") + endif() endfunction() foreach(fname ${MOBJS}) From 46c3ba32eaa5df3d439c2ed6ac465a25810e9297 Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Tue, 5 Jul 2022 18:16:59 -0600 Subject: [PATCH 26/37] Make output less verbose --- packages/intrepid/matlab/intrelab/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/intrepid/matlab/intrelab/CMakeLists.txt b/packages/intrepid/matlab/intrelab/CMakeLists.txt index 091599d001cc..f59e5df0d2ce 100644 --- a/packages/intrepid/matlab/intrelab/CMakeLists.txt +++ b/packages/intrepid/matlab/intrelab/CMakeLists.txt @@ -11,7 +11,7 @@ PROJECT(Intrelab) CMAKE_MINIMUM_REQUIRED(VERSION 3.17.0 FATAL_ERROR) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) -set(MATLAB_FIND_DEBUG TRUE) +#set(MATLAB_FIND_DEBUG TRUE) # --> ACTIONS: # 1.) Specify Trilinos install directory with -DTrilinos_ROOT = (case-sensitive) @@ -74,13 +74,13 @@ endif() if(DEFINED ENV{Trilinos_DIR}) set(Trilinos_ROOT $ENV{Trilinos_DIR}) endif() -message(WARNING "Trilinos_ROOT: ${Trilinos_ROOT}") if ("${Trilinos_ROOT}" STREQUAL "") message(WARNING "Trilinos_ROOT has NOT been specified.") endif() set(Trilinos_ROOT "${Trilinos_ROOT}" CACHE STRING "Trilinos installation directory") FIND_PACKAGE(Trilinos COMPONENTS Intrepid REQUIRED) +message(STATUS "Found Trilinos: ${Trilinos_INSTALL_DIR}") # --> ACTION: define install directory (full path or relative to the intrelab directory) From 9b31e86a378fe630048d25d9fd7d7d71c1d1e50b Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Tue, 5 Jul 2022 19:15:02 -0600 Subject: [PATCH 27/37] Change INST_DIR to a CACHE variable --- packages/intrepid/matlab/intrelab/CMakeLists.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/intrepid/matlab/intrelab/CMakeLists.txt b/packages/intrepid/matlab/intrelab/CMakeLists.txt index f59e5df0d2ce..ca411a0b340b 100644 --- a/packages/intrepid/matlab/intrelab/CMakeLists.txt +++ b/packages/intrepid/matlab/intrelab/CMakeLists.txt @@ -15,9 +15,14 @@ set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) # --> ACTIONS: # 1.) Specify Trilinos install directory with -DTrilinos_ROOT = (case-sensitive) +# Also accepts: TRILINOS_ROOT, Trilinos_DIR, TRILINOS_DIR } # 2.) Specify Matlab install directory with -DMatlab_ROOT_DIR = (case-sensitive and note extra _DIR) +# Also accepts: MATLAB_ROOT, Matlab_ROOT, MATLAB_ROOT_DIR # 3.) Specify directory to install intrelab -DINST_DIR = (case-sensitive) +# define install directory (full path or relative to the intrelab directory) +set(INST_DIR "install" CACHE STRING "Intrelab installation directory (absolute or relative to Intrelab source directory)") + # handle Matlab_ROOT_DIR and all variants # allow for {Matlab_ROOT_DIR, MATLAB_ROOT_DIR, Matlab_ROOT, MATLAB_ROOT} if (MATLAB_ROOT_DIR) @@ -82,10 +87,6 @@ set(Trilinos_ROOT "${Trilinos_ROOT}" CACHE STRING "Trilinos installation directo FIND_PACKAGE(Trilinos COMPONENTS Intrepid REQUIRED) message(STATUS "Found Trilinos: ${Trilinos_INSTALL_DIR}") - -# --> ACTION: define install directory (full path or relative to the intrelab directory) -set(INST_DIR "install") - set(CMAKE_PREFIX_PATH ${TRILINOS_INSTALL_DIR} ${CMAKE_PREFIX_PATH}) if(IS_ABSOLUTE ${INST_DIR}) set(CMAKE_INSTALL_PREFIX ${INST_DIR}) From 5011ab5b0835584768f51cd1ed7368d45387c206 Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Tue, 5 Jul 2022 21:13:30 -0600 Subject: [PATCH 28/37] Removed INST_DIR in favor of CMAKE_INSTALL_PREFIX --- .../intrepid/matlab/intrelab/CMakeLists.txt | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/packages/intrepid/matlab/intrelab/CMakeLists.txt b/packages/intrepid/matlab/intrelab/CMakeLists.txt index ca411a0b340b..30dd3f558fc6 100644 --- a/packages/intrepid/matlab/intrelab/CMakeLists.txt +++ b/packages/intrepid/matlab/intrelab/CMakeLists.txt @@ -14,14 +14,17 @@ set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) #set(MATLAB_FIND_DEBUG TRUE) # --> ACTIONS: -# 1.) Specify Trilinos install directory with -DTrilinos_ROOT = (case-sensitive) +# 1.) Specify Trilinos install directory with -DTrilinos_ROOT = (case-sensitive) # Also accepts: TRILINOS_ROOT, Trilinos_DIR, TRILINOS_DIR } -# 2.) Specify Matlab install directory with -DMatlab_ROOT_DIR = (case-sensitive and note extra _DIR) +# 2.) Specify Matlab install directory with -DMatlab_ROOT_DIR = (case-sensitive and note extra _DIR) # Also accepts: MATLAB_ROOT, Matlab_ROOT, MATLAB_ROOT_DIR -# 3.) Specify directory to install intrelab -DINST_DIR = (case-sensitive) +# 3.) Specify directory to install intrelab -DCMAKE_INSTALL_PREFIX = (case-sensitive) # define install directory (full path or relative to the intrelab directory) -set(INST_DIR "install" CACHE STRING "Intrelab installation directory (absolute or relative to Intrelab source directory)") +# per https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT.html +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}/install" CACHE PATH "..." FORCE) +endif() # handle Matlab_ROOT_DIR and all variants # allow for {Matlab_ROOT_DIR, MATLAB_ROOT_DIR, Matlab_ROOT, MATLAB_ROOT} @@ -87,13 +90,6 @@ set(Trilinos_ROOT "${Trilinos_ROOT}" CACHE STRING "Trilinos installation directo FIND_PACKAGE(Trilinos COMPONENTS Intrepid REQUIRED) message(STATUS "Found Trilinos: ${Trilinos_INSTALL_DIR}") -set(CMAKE_PREFIX_PATH ${TRILINOS_INSTALL_DIR} ${CMAKE_PREFIX_PATH}) -if(IS_ABSOLUTE ${INST_DIR}) - set(CMAKE_INSTALL_PREFIX ${INST_DIR}) -else() - set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/${INST_DIR}") -endif() - set(MOBJS intrepid_setJacobian intrepid_setJacobianInv intrepid_setJacobianDet intrepid_getNumCubaturePoints intrepid_getCubature intrepid_getBasisValues intrepid_computeCellMeasure intrepid_HGRADtransformGRAD From bf3504cecbdb89123ef0dbd59dcc73c5b0a601d8 Mon Sep 17 00:00:00 2001 From: "Roscoe A. Bartlett" Date: Tue, 12 Jul 2022 10:00:35 -0600 Subject: [PATCH 29/37] Automatic snapshot commit from tribits at c81102e2 Origin repo remote tracking branch: 'github/master' Origin repo remote repo URL: 'github = git@github.com:TriBITSPub/TriBITS.git' At commit: commit c81102e2dd516b16ef9674a1efa480909da5ede9 Author: Roscoe A. Bartlett Date: Mon Jul 11 19:30:52 2022 -0600 Summary: Add/update documentation for TriBITS TPLs (#299) --- cmake/tribits/CHANGELOG.md | 14 +- ...TribitsExternalPackageFindTplHelpers.cmake | 132 +++ ...ribitsExternalPackageWriteConfigFile.cmake | 158 +++- .../TribitsGitRepoVersionInfo.cmake | 2 +- .../package_arch/TribitsGlobalMacros.cmake | 4 +- .../TribitsProcessEnabledTpl.cmake | 4 +- ...ribitsTplFindIncludeDirsAndLibraries.cmake | 87 +- cmake/tribits/core/std_tpls/FindTPLCUDA.cmake | 14 +- .../TribitsGetImportedLocationProperty.cmake | 2 +- .../TribitsCTestDriverCoreHelpers.cmake | 2 +- .../guides/TribitsCoreDetailedReference.rst | 2 +- .../tribits/doc/guides/TribitsGuidesBody.rst | 767 +++++++++++------- .../TribitsMacroFunctionDocTemplate.rst | 5 + .../TribitsSystemMacroFunctionDocTemplate.rst | 7 + .../guides/users_guide/TribitsUsersGuide.rst | 12 +- .../cmake/tpls/FindTPLTpl1.cmake | 52 +- .../cmake/tpls/FindTPLTpl2.cmake | 27 +- .../cmake/tpls/FindTPLTpl3.cmake | 27 +- .../cmake/tpls/FindTPLTpl4.cmake | 24 +- cmake/tribits/python_utils/SnapshotDir.py | 2 +- 20 files changed, 929 insertions(+), 415 deletions(-) create mode 100644 cmake/tribits/core/package_arch/TribitsExternalPackageFindTplHelpers.cmake diff --git a/cmake/tribits/CHANGELOG.md b/cmake/tribits/CHANGELOG.md index 63761777b5f4..f851f07ce727 100644 --- a/cmake/tribits/CHANGELOG.md +++ b/cmake/tribits/CHANGELOG.md @@ -2,7 +2,19 @@ ChangeLog for TriBITS ---------------------------------------- -## 2022-05-16: +## 2022-05-25: + +* **Changed:** Dependencies between external packages (TPLs) must + now be specified in order for correct linkage. No longer will listing + the external packages (TPLs) in the correct order in the + `/TPLsList.cmake` file and listing all upstream external packages (TPLs) in + `/cmake/Dependencies.cmake` be sufficient. For now, dependencies + between external packages (TPLs) can be set in the `/TPLsList.cmake` + file by setting the cache var `_LIB_ENABLED_DEPENDENCIES` for each downstream + external package (TPL). (See [`TribitsExampleProject2/TPLsList.cmake`](https://github.com/TriBITSPub/TriBITS/blob/master/tribits/examples/TribitsExampleProject2/TPLsList.cmake) + for an example.) Later, a more scalable approach for setting these vars will + be devised. However, this means it is no longer necessary for a package + to list all of its upstream external packages/TPLs, only its direct dependencies. * **Changed:** All compliant external packages (TPLs) must now set the imported target `::all_libs` in their `FindTPL.cmake` diff --git a/cmake/tribits/core/package_arch/TribitsExternalPackageFindTplHelpers.cmake b/cmake/tribits/core/package_arch/TribitsExternalPackageFindTplHelpers.cmake new file mode 100644 index 000000000000..474f42c5e683 --- /dev/null +++ b/cmake/tribits/core/package_arch/TribitsExternalPackageFindTplHelpers.cmake @@ -0,0 +1,132 @@ +# @HEADER +# ************************************************************************ +# +# TriBITS: Tribal Build, Integrate, and Test System +# Copyright 2013 Sandia Corporation +# +# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +# the U.S. Government retains certain rights in this software. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Corporation nor the names of the +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# ************************************************************************ +# @HEADER + + +# @FUNCTION: tribits_external_package_create_imported_all_libs_target_and_config_file() +# +# Call from a ``FindTPL.cmake`` module that calls inner +# ``find_package()`` for external package that uses modern CMake +# IMPORTED targets. +# +# Usage:: +# +# tribits_external_package_create_imported_all_libs_target_and_config_file( +# +# INNER_FIND_PACKAGE_NAME +# IMPORTED_TARGETS_FOR_ALL_LIBS ... ) +# +# This function is called in a TriBITS ``FindTPL.cmake`` wrapper +# module after it calls ``find_package()`` and then creates the +# IMPORTED target ``::all_libs`` from the list of IMPORTED targets +# `` ...`` which are defined from the call +# ``find_package()``. This function also takes care of +# generating the correct ``Config.cmake`` file under the directory:: +# +# ${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR} +# +# The generated ``Config.cmake`` file calls +# ``find_dependency()`` (with no other argument) and then, again, +# defines the correct imported library dependency. +# +# For more details, see `Creating FindTPL*.cmake using find_package() with +# IMPORTED targets`_. +# +function(tribits_external_package_create_imported_all_libs_target_and_config_file + tplName + ) + + # Parse arguments + cmake_parse_arguments( + PARSE_ARGV 1 + PARSE "" "" # prefix, options, one_value_keywords + "INNER_FIND_PACKAGE_NAME;IMPORTED_TARGETS_FOR_ALL_LIBS" #multi_value_keywords + ) + tribits_check_for_unparsed_arguments(PARSE) + tribits_assert_parse_arg_one_value(PARSE INNER_FIND_PACKAGE_NAME) + tribits_assert_parse_arg_one_or_more_values(PARSE IMPORTED_TARGETS_FOR_ALL_LIBS) + + # Create imported target ::all_libs + add_library(${tplName}::all_libs INTERFACE IMPORTED GLOBAL) + foreach (importedTarget IN LISTS PARSE_IMPORTED_TARGETS_FOR_ALL_LIBS) + target_link_libraries(${tplName}::all_libs INTERFACE ${importedTarget}) + endforeach() + + # Create Config.cmake file + tribits_external_package_create_package_config_file_with_imported_targets( + ${tplName} + INNER_FIND_PACKAGE_NAME ${PARSE_INNER_FIND_PACKAGE_NAME} + IMPORTED_TARGETS_FOR_ALL_LIBS ${PARSE_IMPORTED_TARGETS_FOR_ALL_LIBS} ) + +endfunction() + + +function(tribits_external_package_create_package_config_file_with_imported_targets + tplName + ) + + # Parse arguments + cmake_parse_arguments( + PARSE_ARGV 1 + PARSE "" "" # prefix, options, one_value_keywords + "INNER_FIND_PACKAGE_NAME;IMPORTED_TARGETS_FOR_ALL_LIBS" #multi_value_keywords + ) + tribits_check_for_unparsed_arguments(PARSE) + tribits_assert_parse_arg_one_value(PARSE INNER_FIND_PACKAGE_NAME) + tribits_assert_parse_arg_one_or_more_values(PARSE IMPORTED_TARGETS_FOR_ALL_LIBS) + set(externalPkg ${PARSE_INNER_FIND_PACKAGE_NAME}) + + # Create Config.cmake file + set(configFileStr "") + string(APPEND configFileStr + "include(CMakeFindDependencyMacro)\n" + "set(${externalPkg}_DIR \"${${externalPkg}_DIR}\")\n" + "find_dependency(${externalPkg})\n" + "add_library(${tplName}::all_libs INTERFACE IMPORTED GLOBAL)\n" + ) + foreach (importedTarget IN LISTS PARSE_IMPORTED_TARGETS_FOR_ALL_LIBS) + string(APPEND configFileStr + "target_link_libraries(${tplName}::all_libs INTERFACE ${importedTarget})\n") + endforeach() + set(buildDirExternalPkgsDir + "${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR}") + set(tplConfigFile + "${buildDirExternalPkgsDir}/${tplName}/${tplName}Config.cmake") + file(WRITE "${tplConfigFile}" "${configFileStr}") + +endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake b/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake index 0ab3cc48b73e..d5b2b6eb1907 100644 --- a/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake +++ b/cmake/tribits/core/package_arch/TribitsExternalPackageWriteConfigFile.cmake @@ -61,9 +61,9 @@ cmake_policy(SET CMP0057 NEW) # Support if ( ... IN_LIST ... ) # ````: 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. +# 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) @@ -172,30 +172,81 @@ endfunction() # tribits_external_package_write_config_file_str( # ) # -# The arguments are: +# The function arguments are: # # ````: Name of the external package/TPL # # ````: Name of variable that will contain the string # for the config file on output. # -# This function reads from the variables ``TPL__INCLUDE_DIRS`` -# ``TPL__LIBRARIES``, and ``_LIB_ENABLED_DEPENDENCIES`` +# This function reads from the (cache) variables +# +# * ``TPL__INCLUDE_DIRS`` +# * ``TPL__LIBRARIES`` +# * ``_LIB_ENABLED_DEPENDENCIES`` +# # (which must already be set) and uses that information to produce the # contents of the ``Config.cmake`` which is returned as a string # variable that contains IMPORTED targets to represent these libraries and # include directories as well as ``find_dependency()`` calls for upstream -# packages listed in ``_LIB_ENABLED_DEPENDENCIES`` +# packages listed in ``_LIB_ENABLED_DEPENDENCIES``. +# +# The arguments in ``TPL__LIBRARIES`` are handled in special ways in +# order to create the namespaced IMPORTED targets ``::`` and +# the ``::all_libs`` target that depends on these. The types of +# arguments that are handled and how the are interpreted: +# +# ``/[lib].`` +# +# Arguments that are absolute file paths are treated as libraries and an +# imported target name ```` is derived from the file name (of the +# form ``lib.`` removing beginning ``lib`` and file +# extension ``.``). The IMPORTED target +# ``::`` is created and the file path is set using the +# ``IMPORTED_LOCATION`` target property. +# +# ``-l`` +# +# Arguments of the form ``-l`` are used to create IMPORTED +# targets with the name ``::`` using the +# ``IMPORTED_LIBNAME`` target property. +# +# ```` # -# ToDo: Flesh out more documentation for behavior as more features are added -# for handling: +# Arguments that are a raw name that matches the regex +# ``^[a-zA-Z_][a-zA-Z0-9_-]*$`` are interpreted to be a library name +# ```` and is used to create an IMPORTED targets +# ``::`` using the ``IMPORTED_LIBNAME`` target property. # -# * ``TPL__LIBRARIES`` containing ``-l`` and ``-L`` arguments ... +# ``-L`` +# +# Link directories. These are pulled off and added to the +# ``::all_libs`` using ``target_link_options()``. (The order of +# these options is maintained.) +# +# ``-`` +# +# Any other option that starts with ``-`` is assumed to +# be a link argument where the order does not matter in relation to the +# libraries (but the order of these extra options are maintained w.r.t. each +# other). +# +# ```` # -# * ``TPL__LIBRARIES`` containing arguments other than library files -# * or ``-l`` and ``-L`` arguments and files. +# Any other argument that does not match one of the above patterns is +# regarded as an error. # -function(tribits_external_package_write_config_file_str tplName tplConfigFileStrOut) +# For more details on the handling of individual ``TPL__LIBRARIES`` +# arguments, see `tribits_tpl_libraries_entry_type()`_. +# +# The list of directories given in ``TPL__INCLUDE_DIRS`` is added to +# the ``::all_libs`` target using ``target_include_directories()``. +# +# Finally, for every ```` listed in +# ``_LIB_ENABLED_DEPENDENCIES``, a link dependency is created using +# ``target_link_library(::all_libs INTERFACE )``. +# +function(tribits_external_package_write_config_file_str tplName tplConfigFileStrOut) # A) Set up beginning of config file text set(configFileStr "") @@ -402,30 +453,36 @@ function(tribits_external_package_process_libraries_list tplName) endfunction() +# @FUNCTION: tribits_tpl_libraries_entry_type() +# # Returns the type of the library entry in the list TPL__LIBRARIES # +# Usage:: +# +# tribits_tpl_libraries_entry_type( ) +# # Arguments: # -# ``libentry`` [in]: Element of ``TPL__LIBRARIES`` +# ```` [in]: Element of ``TPL__LIBRARIES`` # -# ``libEntryTypeOut`` [out]: Variable set on output to the type of entry. +# ```` [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 +# * ``FULL_LIB_PATH``: A full library path # -# ``LIB_NAME_LINK_OPTION``: A library name link option of the form -# ``-l`` +# * ``LIB_NAME_LINK_OPTION``: A library name link option of the form +# ``-l`` # -# ``LIB_NAME``: A library name of the form ```` +# * ``LIB_NAME``: A library name of the form ```` # -# ``LIB_DIR_LINK_OPTION``: A library directory search option of the form -# ``-L`` +# * ``LIB_DIR_LINK_OPTION``: A library directory search option of the form +# ``-L`` # -# ``GENERAL_LINK_OPTION``: Some other general link option that starts with -# ``-`` but is not ``-l`` or ``-L``. +# * ``GENERAL_LINK_OPTION``: Some other general link option that starts with +# ``-`` but is not ``-l`` or ``-L``. # -# ``UNSUPPORTED_LIB_ENTRY``: An unsupported lib option +# * ``UNSUPPORTED_LIB_ENTRY``: An unsupported lib option # function(tribits_tpl_libraries_entry_type libentry libEntryTypeOut) string(SUBSTRING "${libentry}" 0 1 firstCharLibEntry) @@ -497,6 +554,7 @@ endfunction() # imported targets :: for this TPL are linked to this first # :: which has the needed dependencies. + function(tribits_external_package_get_libname_and_path_from_libentry libentry libEntryType libnameOut libpathOut ) @@ -548,27 +606,59 @@ 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 "${full_lib_path}" NAME_WLE) + get_filename_component(full_libname "${full_lib_path}" NAME_WE) + # Begins with 'lib'? + tribits_external_package_libname_begins_with_lib("${full_libname}" beginsWithLib) # Assert is a valid lib name and get lib name + set(libname "") string(LENGTH "${full_libname}" full_libname_len) if (full_libname_len LESS 0) - tribits_print_invalid_lib_name(${tplName} "${full_libname}") + tribits_print_invalid_lib_name(${tplName} "${full_lib_path}") endif() if (WIN32) # Native windows compilers does not prepend library names with 'lib' set(libname "${full_libname}") - 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}") + elseif (APPLE) + # On MacOSX, CMake allows using frameworks that *don't* begin with 'lib' + # so we have to allow for that + if (beginsWithLib) + string(SUBSTRING "${full_libname}" 3 -1 libname) + else() + # Must be a framework dir with extension .framework + get_filename_component(last_ext "${full_lib_path}" LAST_EXT) + if (last_ext STREQUAL ".framework") + set(libname "${full_libname}") + else() + tribits_print_invalid_lib_name(${tplName} "${full_lib_path}") + endif() + endif() + else() # I.e. Linux + # Every other system (i.e. Linux) prepends the library name with 'lib' so + # assert for that + if (NOT beginsWithLib) + tribits_print_invalid_lib_name(${tplName} "${full_lib_path}") + else() + string(SUBSTRING "${full_libname}" 3 -1 libname) endif() - string(SUBSTRING "${full_libname}" 3 -1 libname) endif() + # Set output set(${libnameOut} ${libname} PARENT_SCOPE) endfunction() +function(tribits_external_package_libname_begins_with_lib full_libname + libnameBeginsWithLibOut + ) + string(SUBSTRING "${full_libname}" 0 3 libPart) + if (libPart STREQUAL "lib") + set(libnameBeginsWithLib TRUE) + else() + set(libnameBeginsWithLib FALSE) + endif() + set(${libnameBeginsWithLibOut} ${libnameBeginsWithLib} PARENT_SCOPE) +endfunction() + + function(tribits_external_package_get_libname_from_lib_name_link_option lib_name_link_option libnameOut ) @@ -585,8 +675,8 @@ 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!") + message_wrapper(SEND_ERROR + "ERROR: TPL_${tplName}_LIBRARIES entry '${full_libname}' not a valid lib file name!") endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsGitRepoVersionInfo.cmake b/cmake/tribits/core/package_arch/TribitsGitRepoVersionInfo.cmake index 8dbe8f519c97..1b345ec0a2ac 100644 --- a/cmake/tribits/core/package_arch/TribitsGitRepoVersionInfo.cmake +++ b/cmake/tribits/core/package_arch/TribitsGitRepoVersionInfo.cmake @@ -153,7 +153,7 @@ function(tribits_generate_single_repo_version_string gitRepoDir endfunction() # NOTE: Above, it is fine if ${maxSummaryLen} > len(${gitCmndOutput}) as -# string(SUBSTRING ...) will just shorten this to the lenght of the string. +# string(SUBSTRING ...) will just shorten this to the length of the string. function(tribits_assert_git_executable) diff --git a/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake b/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake index 50340fb5afbd..ca763c91480b 100644 --- a/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake @@ -542,7 +542,7 @@ macro(tribits_define_global_options_and_define_extra_repos) advanced_set(${PROJECT_NAME}_IMPORTED_NO_SYSTEM ${${PROJECT_NAME}_IMPORTED_NO_SYSTEM_DEFAULT} CACHE BOOL - "If set TRUE, then set IMPORTED_NO_SYSTEM proeprty on all exported libraries.") + "If set TRUE, then set IMPORTED_NO_SYSTEM property on all exported libraries.") if (CMAKE_VERSION VERSION_LESS 3.23 AND ${PROJECT_NAME}_IMPORTED_NO_SYSTEM) message(FATAL_ERROR "Error, setting ${PROJECT_NAME}_IMPORTED_NO_SYSTEM='${${PROJECT_NAME}_IMPORTED_NO_SYSTEM}' for CMake version '${CMAKE_VERSION}' < 3.23 is not allowed!") @@ -2035,7 +2035,7 @@ endfunction() # Configure the enabled packages # -# This macro actally calls add_subdirectory() on the enabled +# This macro actually calls add_subdirectory() on the enabled # TriBITS packages. # macro(tribits_configure_enabled_packages) diff --git a/cmake/tribits/core/package_arch/TribitsProcessEnabledTpl.cmake b/cmake/tribits/core/package_arch/TribitsProcessEnabledTpl.cmake index e112a8f9e66c..221e8fb9065f 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(TribitsExternalPackageFindTplHelpers) include(TribitsExternalPackageWriteConfigFile) include(TribitsTplFindIncludeDirsAndLibraries) include(TribitsGeneralMacros) @@ -148,9 +149,6 @@ function(tribits_process_enabled_tpl TPL_NAME) "ERROR: TPL_${TPL_NAME}_NOT_FOUND=${TPL_${TPL_NAME}_NOT_FOUND}, aborting!") endif() - # Assert that the TPL correctly defined all of these variables - assert_defined(TPL_${TPL_NAME}_LIBRARIES) - # Generate the ConfigVersion.cmake file if it has not been # created yet and add install targets for Config[Version].cmake set(buildDirExternalPkgsDir diff --git a/cmake/tribits/core/package_arch/TribitsTplFindIncludeDirsAndLibraries.cmake b/cmake/tribits/core/package_arch/TribitsTplFindIncludeDirsAndLibraries.cmake index d3ebe2795030..3a514943d3e9 100644 --- a/cmake/tribits/core/package_arch/TribitsTplFindIncludeDirsAndLibraries.cmake +++ b/cmake/tribits/core/package_arch/TribitsTplFindIncludeDirsAndLibraries.cmake @@ -99,8 +99,9 @@ include(Split) # to disable the prefind call to ``find_package()`` even if it would be # allowed otherwise. # -# See `How to use find_package() for a TriBITS TPL`_ for details in how to use -# this function to create a ``FindTPL.cmake`` module file. +# See `Creating FindTPL*.cmake using find_package() without IMPORTED targets`_ +# for details in how to use this function to create a +# ``FindTPL.cmake`` module file. # function(tribits_tpl_allow_pre_find_package TPL_NAME ALLOW_PACKAGE_PREFIND_OUT) @@ -157,10 +158,12 @@ endfunction() # @FUNCTION: tribits_tpl_find_include_dirs_and_libraries() # -# Function that sets up cache variables for users to specify where to find a -# `TriBITS TPL`_'s headers and libraries. This function is typically called -# inside of a ``FindTPL.cmake`` module file (see -# `${TPL_NAME}_FINDMOD`_). +# This function reads (cache) variables that specify where to find a `TriBITS +# TPL`_'s headers and libraries and then creates IMPORTED targets, the +# ``::all_libs`` target, and writes the file +# ``Config.cmake`` into the standard location in the build directory. +# This function is typically called inside of a ``FindTPL.cmake`` +# module file (see `${TPL_NAME}_FINDMOD`_). # # Usage:: # @@ -190,22 +193,23 @@ endfunction() # ``MUST_FIND_ALL_HEADERS`` # # If set, then all of the header files listed in ``REQUIRED_HEADERS`` must -# be found in order for ``TPL__INCLUDE_DIRS`` to be defined. +# be found (unless ``TPL__INCLUDE_DIRS`` is already set). # # ``REQUIRED_LIBS_NAMES`` # # List of libraries that are searched for when looking for the TPL's # libraries using ``find_library()``. This list can be overridden by the -# user by setting ``_LIBRARY_DIRS`` (see below). +# user by setting ``_LIBRARY_NAMES`` (see below). # # ``MUST_FIND_ALL_LIBS`` # # If set, then all of the library files listed in ``REQUIRED_LIBS_NAMES`` -# must be found or the TPL is considered not found! If the global cache -# var ``_MUST_FIND_ALL_TPL_LIBS`` is set to ``TRUE``, then this -# is turned on as well. WARNING: The default is not to require finding -# all of the listed libs. This is to maintain backward compatibility with -# some older ``FindTPL.cmake`` modules. +# must be found or the TPL is considered not found (unless +# ``TPL__LIBRARIES`` is already set). If the global cache var +# ``_MUST_FIND_ALL_TPL_LIBS`` is set to ``TRUE``, then this is +# turned on as well. WARNING: The default is not to require finding all +# of the listed libs. (This is to maintain backward compatibility with +# some older ``FindTPL.cmake`` modules.) # # ``NO_PRINT_ENABLE_SUCCESS_FAIL`` # @@ -214,50 +218,69 @@ endfunction() # This function implements the TPL find behavior described in `Enabling # support for an optional Third-Party Library (TPL)`_. # -# The following (cache) variables, if set, will be used by that this function: +# The following (cache) variables, if set, will be used by this function: # # ``_INCLUDE_DIRS`` (type ``PATH``) # # List of paths to search first for header files defined in -# ``REQUIRED_HEADERS``. +# ``REQUIRED_HEADERS ...``. # # ``_LIBRARY_DIRS`` (type ``PATH``) # # The list of directories to search first for libraries defined in -# ``REQUIRED_LIBS_NAMES``. If, for some reason, no libraries should be -# linked in for this particular configuration, then setting -# ``_LIBRARY_DIRS=OFF`` will +# ``REQUIRED_LIBS_NAMES ...``. If, for some reason, +# no libraries should be linked in for this particular configuration, then +# setting ``_LIBRARY_DIRS=OFF`` or is empty will no special paths +# will be searched. # # ``_LIBRARY_NAMES`` (type ``STRING``) # # List of library names to be looked for instead of what is specified in -# ``REQUIRED_LIBS_NAMES``. +# ``REQUIRED_LIBS_NAMES ...``. # -# This function sets global variables to return state so it can be called from -# anywhere in the call stack. The following cache variables are defined that -# are intended for the user to set and/or use: +# ``_LIB_ENABLED_DEPENDENCIES`` +# +# List of direct upstream external package/TPL dependencies that also +# define ``::all_libs`` targets. +# +# An addition, the function will avoid calling the find operations if the +# following (cache) variables are set on input: # # ``TPL__INCLUDE_DIRS`` (type ``PATH``) # # A list of common-separated full directory paths that contain the TPL's -# header files. If this variable is set before calling this function, -# then no headers are searched for and this variable will be assumed to -# have the correct list of header paths. +# header files. # # ``TPL__LIBRARIES`` (type ``FILEPATH``) # # A list of commons-separated full library names (i.e. output from -# ``find_library()``) for all of the libraries found for the TPL. If this -# variable is set before calling this function, then no libraries are -# searched for and this variable will be assumed to have the correct list -# of libraries to link to. +# ``find_library()``) for all of the libraries for the TPL. +# +# This function produces the following: # # ``TPL__NOT_FOUND`` (type ``BOOL``) # # Will be set to ``ON`` if all of the parts of the TPL could not be found. # -# ToDo: Document the behavior of this function for finding headers and -# libraries and when a find is successful and when it is not. +# ``::`` +# +# Namespaced IMPORTED target for every library found or specified in +# ``TPL__LIBRARIES``. These IMPORTED targets will have the +# ``::all_libs`` for the upstream external packages/TPLs +# listed in ``_LIB_ENABLED_DEPENDENCIES``. +# +# ``::all_libs`` +# +# INTERFACE target that depends on all of the created IMPORTED targets. +# +# ``/external_packages//Config.cmake`` +# +# A package configure file that contains all of the generated IMPORTED +# targets ``::`` and the ``::all_libs`` target. +# This fill will also call ``find_dependency()`` to pull in +# ``Config.cmake`` files for upstream TPLs that are +# listed in ``_LIB_ENABLED_DEPENDENCIES``. (For more +# information, see `tribits_external_package_write_config_file()`_.) # # Note, if ``TPL_TENTATIVE_ENABLE_=ON``, then if all of the parts of # the TPL can't be found, then ``TPL_ENABLE_`` will be (forced) set @@ -358,7 +381,7 @@ function(tribits_tpl_find_include_dirs_and_libraries TPL_NAME) else() - set(${TPL_NAME}_LIBRARY_DIRS) # Just to ignore below! + set(${TPL_NAME}_LIBRARY_DIRS "") # Just to ignore below! endif() diff --git a/cmake/tribits/core/std_tpls/FindTPLCUDA.cmake b/cmake/tribits/core/std_tpls/FindTPLCUDA.cmake index 86028fd4b666..b21487909c51 100644 --- a/cmake/tribits/core/std_tpls/FindTPLCUDA.cmake +++ b/cmake/tribits/core/std_tpls/FindTPLCUDA.cmake @@ -109,11 +109,17 @@ if(NOT _CUDA_FAILURE) macro(package_add_cuda_library cuda_target) tribits_add_library(${cuda_target} ${ARGN} CUDALIBRARY) endmacro() - global_set(TPL_CUDA_LIBRARY_DIRS) - global_set(TPL_CUDA_INCLUDE_DIRS ${CUDA_TOOLKIT_INCLUDE}) - global_set(TPL_CUDA_LIBRARIES ${CUDA_CUDART_LIBRARY} ${CUDA_cublas_LIBRARY} + set(TPL_CUDA_INCLUDE_DIRS ${CUDA_TOOLKIT_INCLUDE}) + set(TPL_CUDA_LIBRARIES ${CUDA_CUDART_LIBRARY} ${CUDA_cublas_LIBRARY} ${CUDA_cufft_LIBRARY}) else() - set(TPL_ENABLE_CUDA OFF PARENT_SCOPE) message(FATAL_ERROR "\nDid not find acceptable version of CUDA compiler") endif() + +tribits_tpl_find_include_dirs_and_libraries(CUDA) + +unset(TPL_CUDA_INCLUDE_DIRS) +unset(TPL_CUDA_LIBRARIES) + +# NOTE: Above, we need to generate the CUDA::all_libs target and the +# CUDAConfig.cmake file that will also provide the CUDA::all_libs target. diff --git a/cmake/tribits/core/utils/TribitsGetImportedLocationProperty.cmake b/cmake/tribits/core/utils/TribitsGetImportedLocationProperty.cmake index a4b4d7599a26..8e22614b16d9 100644 --- a/cmake/tribits/core/utils/TribitsGetImportedLocationProperty.cmake +++ b/cmake/tribits/core/utils/TribitsGetImportedLocationProperty.cmake @@ -42,7 +42,7 @@ include_guard() include(CMakeBuildTypesList) -# Return the value of the target proeprty IMPORTED_LOCATION_ for every +# Return the value of the target property IMPORTED_LOCATION_ for every # known and returns the fist non-null value. Otherwise, returns # empty. # diff --git a/cmake/tribits/ctest_driver/TribitsCTestDriverCoreHelpers.cmake b/cmake/tribits/ctest_driver/TribitsCTestDriverCoreHelpers.cmake index 58ffc6264ddf..f54285bb8c1f 100644 --- a/cmake/tribits/ctest_driver/TribitsCTestDriverCoreHelpers.cmake +++ b/cmake/tribits/ctest_driver/TribitsCTestDriverCoreHelpers.cmake @@ -1262,7 +1262,7 @@ endmacro() # ${PROJECT_NAME}_DISABLE_ENABLED_FORWARD_DEP_PACKAGES=ON but the target # _libs is attempted to be built anyway and we expect it to build # nothing and result in no error. (The outer ctest -S driver is not smart -# enough to know all the lgoic for if a package will actaully be enabled or +# enough to know all the lgoic for if a package will actually be enabled or # not. That is the job of the inner TriBITS dependency logic and # ${PROJECT_NAME}_DISABLE_ENABLED_FORWARD_DEP_PACKAGES=ON.) Otherwise, with # CMake 3.19+, cmake_build() catches errors in undefined global build targets diff --git a/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst b/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst index 62a35e6f5543..dfd5e4320172 100644 --- a/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst +++ b/cmake/tribits/doc/guides/TribitsCoreDetailedReference.rst @@ -369,7 +369,7 @@ 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`` + On WIN32 systems, the default for ``${PROJECT_NAME}_ENABLE_Fortran_DEFAULT`` is set to ``OFF`` since it can be difficult to get a Fortran compiler for native Windows. diff --git a/cmake/tribits/doc/guides/TribitsGuidesBody.rst b/cmake/tribits/doc/guides/TribitsGuidesBody.rst index fd4094662ae6..327960df22e5 100644 --- a/cmake/tribits/doc/guides/TribitsGuidesBody.rst +++ b/cmake/tribits/doc/guides/TribitsGuidesBody.rst @@ -2,12 +2,12 @@ Background ========== In order to easily find the most appropriate documentation, see the `TriBITS -Developer and User Roles`_ guide. This guide describes the different roles +Developer and User Roles`_ guide. This guide describes the different roles that users of TriBITS may play and offers links to relevant sections of the -documentation. Additionally, the reader may wish to review the `CMake Language -Overview and Gotchas`_ section which is meant for users that are new to both +documentation. Additionally, the reader may wish to review the `CMake Language +Overview and Gotchas`_ section which is meant for users that are new to both CMake and TriBITS. This section gives a brief overview of getting started with -CMake and provides some warnings about non-obvious CMake behavior that often +CMake and provides some warnings about non-obvious CMake behavior that often trips up new users of TriBITS. @@ -21,7 +21,7 @@ Project User`_, 2) `TriBITS Project Developer`_, 3) `TriBITS Project Architect`_, 4) `TriBITS System Developer`_, and 5) `TriBITS System Architect`_. Each of these roles builds on the necessary knowledge of the lower-level roles. - + .. _TriBITS Project User: .. _TriBITS Project Users: @@ -119,12 +119,12 @@ project. As a result, many people can come into a project that uses TriBITS and quickly start to contribute by adding new source files, adding new libraries, adding new tests, and even adding new TriBITS packages and TPLs; all without really having learned anything about CMake. Often one can use existing -example CMake code as a guide and be successful using basic functionality. As long -as nothing out of the ordinary happens, many people can get along just fine in this +example CMake code as a guide and be successful using basic functionality. As long +as nothing out of the ordinary happens, many people can get along just fine in this mode for a time. -However, we have observed that most mistakes and problems that people run into when -using TriBITS are due to lack of basic knowledge of the CMake language. One can find +However, we have observed that most mistakes and problems that people run into when +using TriBITS are due to lack of basic knowledge of the CMake language. One can find basic tutorials and references on the CMake language in various locations online for free. One can also purchase the `official CMake reference book`_. Also, documentation for any built-in CMake command is available locally by running:: @@ -143,15 +143,15 @@ greater understanding of how TriBITS works. .. _Official CMake reference book: http://www.cmake.org/cmake/help/book.html The CMake language is used to write CMake projects with TriBITS. In fact the -core TriBITS functionality itself is implemented in the CMake language (see -`TriBITS System Project Dependencies`_). CMake is a fairly simple programming -language with relatively simple rules (for the most part). However, compared -to other programming languages, there are a few peculiar aspects to the CMake -language that can make working with it difficult if you don't understand these -rules. For example there are unexpected variable scoping rules and how arguments -are passed to macros and functions can be tricky. Also, CMake has some interesting -gotchas. In order to effectively use TriBITS (or just raw CMake) to construct -and maintain a project's CMake files, one must know the basic rules of CMake +core TriBITS functionality itself is implemented in the CMake language (see +`TriBITS System Project Dependencies`_). CMake is a fairly simple programming +language with relatively simple rules (for the most part). However, compared +to other programming languages, there are a few peculiar aspects to the CMake +language that can make working with it difficult if you don't understand these +rules. For example there are unexpected variable scoping rules and how arguments +are passed to macros and functions can be tricky. Also, CMake has some interesting +gotchas. In order to effectively use TriBITS (or just raw CMake) to construct +and maintain a project's CMake files, one must know the basic rules of CMake and be aware of these gotchas. The first thing to understand about the CMake language is that nearly every @@ -217,9 +217,9 @@ control structures (i.e. see ``cmake --help-command if`` and ``cmake CMake offers a rich assortment of built-in commands for doing all sorts of things. Two of these are the built-in ``macro()`` and the ``function()`` commands which allow you to create user-defined macros and functions. TriBITS -is actually built on CMake functions and macros. All of the built-in and -user-defined macros, and some functions take an array of string arguments. -Some functions take in positional arguments. In fact, most functions take a +is actually built on CMake functions and macros. All of the built-in and +user-defined macros, and some functions take an array of string arguments. +Some functions take in positional arguments. In fact, most functions take a combination of positional and keyword arguments. Variable names are translated into their stored values using @@ -598,7 +598,7 @@ ${PROJECT_SOURCE_DIR}``) are:: project-checkin-test-config.py # [Optional] checkin-test.py config cmake/ NativeRepositoriesList.cmake # [Optional] Rarely used - ExtraRepositoriesList.cmake # [Optional] Lists repos and VC URLs + ExtraRepositoriesList.cmake # [Optional] Lists repos and VC URLs ProjectCiFileChangeLogic.py # [Optional] CI global change/test logic ProjectCompilerPostConfig.cmake # [Optional] Override/tweak build flags ProjectDependenciesSetup.cmake # [Optional] Project deps overrides @@ -903,16 +903,16 @@ are set. This file in Trilinos looked like:: ... include(${Kokkos_GEN_DIR}/kokkos_generated_settings.cmake) - + if (NOT KOKKOS_ARCH STREQUAL "None") - + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KOKKOS_CXX_FLAGS}") - + message("-- " "Skip adding flags for OpenMP because Kokkos flags does that ...") set(OpenMP_CXX_FLAGS_OVERRIDE " ") - + endif() - + endif() The exact context where this file is processed (if it exists) is described in @@ -1942,7 +1942,7 @@ A TriBITS Subpackage: ``${PARENT_PACKAGE_NAME}_ENABLE_TESTS=ON``. The contents of a TriBITS Subpackage are almost identical to those of a -TriBITS Package. The differences are described below and in `How is a TriBITS +TriBITS Package. The differences are described below and in `How is a TriBITS Subpackage different from a TriBITS Package?`_. For more details on the definition of a TriBITS Package (or subpackage), see: @@ -2149,8 +2149,10 @@ are some of the issues to consider when breaking up software into packages and subpackages that will be mentioned in other sections as well. -TriBITS TPL -+++++++++++ +.. _TriBITS TPL: + +TriBITS External Package/TPL +++++++++++++++++++++++++++++ A *TriBITS TPL*: @@ -2183,26 +2185,32 @@ disabled, all of the downstream packages that depend on that TPL will be automatically disabled as well (see `TPL disable triggers auto-disables of downstream dependencies`_). -For each TPL referenced in a `/TPLsList.cmake`_ file using the macro -`tribits_repository_define_tpls()`_, there must exist a file, typically called -``FindTPL${TPL_NAME}.cmake``, that once processed, produces the target -```${TPL_NAME}::all_libs``. Most ``FindTPL${TPL_NAME}.cmake`` files just use -the function `tribits_tpl_find_include_dirs_and_libraries()`_ to define the -TriBITS TPL. A simple example of such a file is the common TriBITS -``FindTPLPETSC.cmake`` module which is currently: + +TriBITS External Package/TPL Core Files +....................................... + +For each external package/TPL referenced in a `/TPLsList.cmake`_ file +using the macro `tribits_repository_define_tpls()`_, there must exist a file, +typically called ``FindTPL.cmake``, that once processed, produces the +target ```::all_libs`` and generates a wrapper package config file +``Config.cmake``. A simple example of such a file is the common +TriBITS ``FindTPLPETSC.cmake`` module which is currently: .. include:: ../../common_tpls/FindTPLPETSC.cmake :literal: -Some concrete ``FindTPL${TPL_NAME}.cmake`` files actually do use -``find_package()`` and a standard CMake package find module to fill in the -guts of finding at TPL which is perfectly fine. In this case, the purpose for -the wrapping ``FindTPL${TPL_NAME}.cmake`` file is to 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`_. +Many concrete ``FindTPL.cmake`` files use ``find_package()`` +internally and a standard CMake package find module or an installed +``Config.cmake`` file to fill in the guts of finding at TPL. In this +case, the purpose for the wrapping ``FindTPL.cmake`` file is to +ensure the definition of the complete target ``::all_libs`` which +contains all usage requirements for the external package/TPL (i.e. all of the +libraries, include directories, etc.). For more details creating or upgrading +a ``FindTPL.cmake`` file, see `How to add a new TriBITS TPL`_. + + +TriBITS External Package/TPL Core Variables +........................................... Once the `/TPLsList.cmake`_ files are all processed, then each defined TPL ``TPL_NAME`` is assigned the following global non-cache variables: @@ -2213,15 +2221,16 @@ defined TPL ``TPL_NAME`` is assigned the following global non-cache variables: ``${TPL_NAME}_FINDMOD`` - Gives the location for the TPL's find module. This is set using the - ``FINDMOD`` field in the call to `tribits_repository_define_tpls()`_. The - final value of the variable is defined by the *last* - `/TPLsList.cmake`_ file that is processed that declares the TPL - ``TPL_NAME``. For example, if ``Repo1/TPLsList.cmake`` and - ``Repo2/TPLsList.cmake`` both list the TPL ``SomeTpl``, then if ``Repo2`` - is processed after ``Repo1``, then ``SomeTpl_FINDMOD`` is determined by - ``Repo2/TPLsList.cmake`` and the find module listed in - ``Repo1/TPLsList.cmake`` is ignored. + Gives the location for the TPL's find module (typically called + ``FindTPL.cmake``, see `How to add a new TriBITS TPL`_). This is + set using the ``FINDMOD`` field in the call to + `tribits_repository_define_tpls()`_. The final value of the variable is + defined by the *last* `/TPLsList.cmake`_ file that is processed + that declares the TPL ``TPL_NAME``. For example, if + ``Repo1/TPLsList.cmake`` and ``Repo2/TPLsList.cmake`` both list the TPL + ``SomeTpl``, then if ``Repo2`` is processed after ``Repo1``, then + ``SomeTpl_FINDMOD`` is determined by ``Repo2/TPLsList.cmake`` and the find + module listed in ``Repo1/TPLsList.cmake`` is ignored. .. _${TPL_NAME}_TESTGROUP: @@ -2246,21 +2255,14 @@ As noted above, it is allowed for the same TPL to be listed in multiple the find module and the test group as as described above. The specification given in `Enabling support for an optional Third-Party -Library (TPL)`_ and `tribits_tpl_find_include_dirs_and_libraries()`_ describes -how the a ``FindTPL${TPL_NAME}.cmake`` module should behave and allow users to -override and specialize how a TPL's include directories and libraries are -determined. However, note that the TriBITS system does not require the usage -of the function ``tribits_tpl_find_include_dirs_and_libraries()`` and does not -even care about the TPL module name ``FindTPL${TPL_NAME}.cmake``. All that is -required is that some CMake file fragment exist such that, once included, will -define the target ``${TPL_NAME}::all_libs``. However, to be user friendly, -such a CMake file should respond to the same variables as accepted by the -standard ``tribits_tpl_find_include_dirs_and_libraries()`` function. - -The core variables related to an enabled TPL are ``${TPL_NAME}_LIBRARIES``, -``${TPL_NAME}_INCLUDE_DIRS``, and ``${TPL_NAME}_TESTGROUP`` as defined in -`tribits_tpl_find_include_dirs_and_libraries()`_ need to be defined. For more -details, see `tribits_repository_define_tpls()`_. +Library (TPL)`_ and `How to add a new TriBITS TPL`_ describes to create a +``FindTPL.cmake`` module. However, all that is required is that +some CMake file fragment exist such that, once included, will define the +target ``::all_libs`` and create the ``Config.cmake`` file +in the correct location. + + + Processing of TriBITS Files: Ordering and Details @@ -2337,7 +2339,7 @@ proceeds through the call to `tribits_project()`_. | 5) ``include(`` `/Version.cmake`_ ``)`` | 6) Define primary TriBITS options and read in the list of extra repositories | (calls ``tribits_define_global_options_and_define_extra_repos()``) -| * ``include(`` `/cmake/ExtraRepositoriesList.cmake`_ ``)`` +| * ``include(`` `/cmake/ExtraRepositoriesList.cmake`_ ``)`` | 7) For each ```` in all defined TriBITS repositories: | * ``include(`` `/cmake/CallbackSetupExtraOptions.cmake`_ ``)`` | * Call macro ``tribits_repository_setup_extra_options()`` @@ -2381,7 +2383,7 @@ project, repository, package, and subpackage files should be clear. All of this information should also be clear when enabling `File Processing Tracing`_ and watching the output from the ``cmake`` configure STDOUT. -Reduced Package Dependency Processing +Reduced Package Dependency Processing ++++++++++++++++++++++++++++++++++++++ In addition to the full processing that occurs as part of the `Full TriBITS @@ -2667,7 +2669,7 @@ without having to define its own ``QT`` TPL in its repository's TriBITS, it can be difficult to know where the right place is to set a given set of variables. The primary considerations for where to set a variable depend on: - + .. ToDo: Describe considerations on where to set variables ... @@ -3176,7 +3178,7 @@ enable/disable cache variables (with the initial default values):: Trilinos_ENABLE_Teuchos="" Trilinos_ENABLE_RTOp"" - Trilinos_ENABLE_Epetra="" + Trilinos_ENABLE_Epetra="" Trilinos_ENABLE_Triutils="" Trilinos_ENABLE_EpetraExt="" Trilinos_ENABLE_ThyraCore="" @@ -3443,7 +3445,7 @@ In more detail, these rules/behaviors are: variable `${PROJECT_NAME}_DISABLE_ENABLED_FORWARD_DEP_PACKAGES`_: .. _${PROJECT_NAME}_DISABLE_ENABLED_FORWARD_DEP_PACKAGES=ON: - + * If ``${PROJECT_NAME}_DISABLE_ENABLED_FORWARD_DEP_PACKAGES=ON``, then TriBITS will disable the explicit enable and continue on. In the above example, TriBITS will override ``Trilinos_ENABLE_RTOp=ON`` and set @@ -3475,7 +3477,7 @@ In more detail, these rules/behaviors are: Trilinos_ENABLE_ThyraGoodStuff=ON # Only if enabling ST code! Trilinos_ENABLE_ThyraEpetra=ON Trilinos_ENABLE_ThyraEpetraExt=ON # Only if enabling ST code! - + (Note that ``Trilinos_ENABLE_ThyraCrazyStuff`` is **not** set to ``ON`` because it is already set to ``OFF`` by default, see `EX SE packages disabled by default`_.) Likewise, explicitly setting @@ -3843,12 +3845,12 @@ tests/examples and TPLs can be clearly seen when processing the TPLs and top-level packages in the lines:: Getting information for all enabled TPLs ... - + -- Processing enabled TPL: BLAS -- Processing enabled TPL: LAPACK - + Configuring individual enabled Trilinos packages ... - + Processing enabled package: Teuchos (Libs) Processing enabled package: RTOp (Libs) Processing enabled package: Epetra (Libs) @@ -4681,7 +4683,7 @@ the `checkin-test.py`_ tool in extended pre-push testing. .. _Performance Testing: -**Performance Testing** +**Performance Testing** *Performance Testing* builds are a special class of builds that have tests that are specifically designed to test the run-time performance of a particular @@ -5158,26 +5160,26 @@ the commands:: $ git clone git@someurl.com:MetaProject $ cd MetaProject/ - $ ./cmake/tribits/ci_support/clone_extra_repos.py + $ ./cmake/tribits/ci_support/clone_extra_repos.py which produces the output like:: - ... - + ... + *** *** Clone the selected extra repos: *** - + Cloning repo ExtraRepo1 ... - + Running: git clone git@someurl.com:ExtraRepo1 ExtraRepo1 - + Cloning repo ExtraRepo2 ... - + Running: git clone git@someurl.com:ExtraRepo2 ExtraRepo1/ExtraRepo2 - + Cloning repo ExtraRepo3 ... - + Running: git clone git@someurl.com:ExtraRepo3 ExtraRepo3 See `clone_extra_repos.py --help`_ for more details. @@ -5224,7 +5226,7 @@ Some of the aggregate commands that one would typically run under the base The tool ``gitdist`` is provided under TriBITS directory:: - cmake/tribits/python_utils/gitidst + cmake/tribits/python_utils/gitidst and can be installed by the `install_devtools.py`_ tool (see `TriBITS Development Toolset`_). See `gitdist documentation`_ for more details. @@ -5452,43 +5454,54 @@ subpackages, do the following: and tests run as new pieces are added. -How to add a new TriBITS TPL ----------------------------- +.. _How to add a new TriBITS TPL: + +How to add a new TriBITS external package/TPL +--------------------------------------------- -In order for an SE package to define a dependency on a new TPL (i.e. one that -has not already been declared in the current repo's or an upstream repo's -`/TPLsList.cmake`_ file), one must add and modify a few -repository-level files. +In order for a TriBITS package to define a dependency on a new external +package/TPL (i.e. a TPL that has not already been declared in the current +repo's or an upstream repo's `/TPLsList.cmake`_ file), one must add +and modify a few repository-level files in addition to modifying files within +the TriBITS packages that use the new external package/TPL. To add a new TriBITS TPL, do the following: 1) Chose a name ```` for the new TPL (must be globally unique across all TriBITS repos, see `Globally unique TriBITS TPL names`_) and which - TriBITS repository (````) to define the new TPL in. The right - repo is usually the one where the package exists that needs the new TPL - dependency. - -2) Create the TPL find module, e.g. ``/tpls/FindTPL.cmake`` - (see `TriBITS TPL`_ and `tribits_tpl_find_include_dirs_and_libraries()`_ - for details). List the default required header files and/or libraries that - must be provided by the TPL. NOTE: This find module can also (optionally) - use ``find_package( ...)`` for the default find operation. For - details, see `How to use find_package() for a TriBITS TPL`_. + TriBITS repository (````) to define the new TPL inside of. (The + right repo is usually the one where the package exists that needs the new + TPL dependency.) + +2) Create the TPL find module file ``FindTPL.cmake`` (or some other + name, see `TriBITS TPL`_) under some location under ```` + (e.g. ``/cmake/tpls/``) or under the package that uses it + (e.g. ``/cmake/tpls/``). How this file is defined depends on + if it uses ``find_package()`` or not and if that + ``find_package()`` command creates modern CMake IMPORTED + targets or not (see `Creating FindTPL*.cmake using find_package() with + IMPORTED targets`_ and `Creating FindTPL*.cmake using find_package() + without IMPORTED targets`_). If not using ``find_package()``, + follow the instructions in `Creating a FindTPL*.cmake module without + find_package()`_. 3) Add a row for the new TPL to the `/TPLsList.cmake`_ file after any - TPLs that this new TPL may depend on. + TPLs that this new TPL may depend on. (One must also set the cache + variable ``_LIB_ENABLED_DEPENDENCIES`` to point the direct + dependencies of this new TPL. See the example in + ``TribitsExampleProject2/TPLsList.cmake``.) 4) Configure the TriBITS project enabling the new TPL with ``TPL_ENABLE_=ON`` and see that the new find module finds the TPL correctly at configure time. -5) List the new TPL in the package(s) that need this dependency in the - package's `/cmake/Dependencies.cmake`_ file (or - `//cmake/Dependencies.cmake`_ for a subpackage). +5) List the new external packages/TPL in the package(s) that need this + dependency in the package's `/cmake/Dependencies.cmake`_ file + (or `//cmake/Dependencies.cmake`_ for a subpackage). -6) If the TPL is an optional TPL for the package, then:: +6) If the TPL is optional for the package, then:: - #cmakedefine HAVE__ + #cmakedefine HAVE__ should be added to the package's ``_config.h.in`` file (see `tribits_configure_file()`_) so that the code knows if the TPL is defined @@ -5497,85 +5510,270 @@ To add a new TriBITS TPL, do the following: 7) Use the TPL in the packages that define the dependency on the new TPL, configure, test, etc. -.. ToDo: Provide more details on various things. +The following subsections describe the various use cases for creating (or +upgrading) ``FindTPL*.cmake`` modules. The main axes of variation for +``FindTPL*.cmake`` modules are: + +a) Use an inner ``find_package()`` call or just use a simple list + of header file names and library names? + +b) The call ``find_package()`` defines modern IMPORTED targets or + only provides variables for the list of include directories and libraries? + +c) Maintain backward compatibility with the legacy TriBITS TPL system that + allows the user to set cache variables for the include directories and link + libraries or force users to always call ``find_package()``? + + +Creating FindTPL*.cmake using find_package() +++++++++++++++++++++++++++++++++++++++++++++ + +When defining a ``FindTPL.cmake`` file, it encouraged to utilize +``find_package( ...)`` to provide the default find operation (and +also the definition of the IMPORTED targets needed to use the external package +when supported). (Here, typically ```` and ```` are the +same names, but there are cases where the names may be different or use +different capitalization.) However, the state of the current ecosystem of +``Find.cmake`` modules and ``Config.cmake`` package +config files is a bit uneven. While all find modules and package config files +should be defining modern CMake IMPORTED targets which contains all the needed +usage requirements (such as the target properties +``INTERFACE_INCLUDE_DIRECTORIES`` and ``INTERFACE_LINK_LIBRARIES``) and use +``find_dependency()`` to get all of their required external upstream package +dependencies, many do not. Also, many of these don't provide a complete +``::all_libs`` target which is required for a TriBITS-compatible +external package/TPL. + +In this case, the ``FindTPL.cmake`` file provides a thin "glue" layer +to adapt the information and objects provided by the +``find_package( ...)`` call into a complete +``::all_libs`` target and a wrapper ``Config.cmake`` file +for consumption by downstream TriBITS-compatible packages. + +The following subsections will describe how to create these TriBITS-compatible +``FindTPL.cmake`` modules for all of the various cases using +``find_package( ...)``. + + +Creating FindTPL*.cmake using find_package() with IMPORTED targets +.................................................................. + +For cases where ``find_package()`` provides complete and proper +modern (namespaced) IMPORTED targets (but is missing the +``::all_libs`` target or the name ```` and ```` +name are different), these ``FindTPL.cmake`` modules can call the +function +`tribits_external_package_create_imported_all_libs_target_and_config_file()`_ +after calling ``find_package()`` to create a very thin wrapper +``FindTPL.cmake`` module. In these cases, such a +``FindTPL.cmake`` module file is nothing more than:: + + find_package( REQUIRED) + tribits_external_package_create_imported_all_libs_target_and_config_file( + + INNER_FIND_PACKAGE_NAME + IMPORTED_TARGETS_FOR_ALL_LIBS ... ) + +The function +`tribits_external_package_create_imported_all_libs_target_and_config_file()`_ +creates the target ``::all_libs`` and the wrapper file +``Config.cmake`` which is installed by TriBITS. The only unique +information required to create this glue module is the name of the external +package ```` and the exact full names of the IMPORTED targets +`` ...`` provided by the +``find_package( ...)`` call. + +Such simple ``FindTPL.cmake`` modules do not follow the legacy +TriBITS TPL convention of allowing users to specify a TPL by setting the cache +variables ``_INCLUDE_DIRS``, ``_LIBRARY_DIRS``, and +``_LIBRARY_NAMES`` or by setting ``TPL__INCLUDE_DIRS`` and +``_LIBRARIES``. But as the ecosystem of CMake software transitions +to modern CMake and uniform usage of complete ``Config.cmake`` files, +that is the reasonable thing to do. + +However, to maintain backwards compatibility with the legacy TriBITS TPL +system (such as when upgrading a existing ``FindTPL.cmake`` file), a +``FindTPL.cmake`` file can be extended to use the +`tribits_tpl_allow_pre_find_package()`_ in combination with the function +`tribits_tpl_find_include_dirs_and_libraries()`_ function as follows:: + + set(REQUIRED_HEADERS ...) + set(REQUIRED_LIBS_NAMES ...) + set(IMPORTED_TARGETS_FOR_ALL_LIBS ...) -.. ToDo: Add an example of an optional TPL to some TribitsExampleProject -.. package and refer to it here. + tribits_tpl_allow_pre_find_package( _ALLOW_PREFIND) + if (_ALLOW_PREFIND) + message("-- Using find_package( ...) ...") + find_package() + if (_FOUND) + message("-- Found _DIR='${_DIR}'") + message("-- Generating ::all_libs and Config.cmake") + tribits_external_package_create_imported_all_libs_target_and_config_file( + INNER_FIND_PACKAGE_NAME + IMPORTED_TARGETS_FOR_ALL_LIBS ${IMPORTED_TARGETS_FOR_ALL_LIBS} ) + endif() + endif() -How to use find_package() for a TriBITS TPL -------------------------------------------- + if (NOT TARGET ::all_libs) + tribits_tpl_find_include_dirs_and_libraries( + REQUIRED_HEADERS ${REQUIRED_HEADERS} + REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} ) + endif() + +Above, if ``find_package()`` is called and returns +``_FOUND=FALSE``, then as fallback it will call +``tribits_tpl_find_include_dirs_and_libraries()`` to find the components of +the TPL. See the documentation for `tribits_tpl_allow_pre_find_package()`_ +for conditions where ``_ALLOW_PREFIND`` is set to ``FALSE`` (and +therefore ``find_package()`` is not called). + +Note that in the above ``FindTPL.cmake`` file that +``find_package()`` will be called even on reconfigures. That is +critical since ``find_package()`` defines IMPORTED targets that +must be available each time configure is called. Also, if +``find_package()`` is called and ``_FOUND=TRUE``, +then the function +`tribits_external_package_create_imported_all_libs_target_and_config_file()`_ +is called which defines the targets ``::all_libs`` which means that +the function ``tribits_tpl_find_include_dirs_and_libraries()`` will **not** be +called. + +A concrete (and tested) example of the latter case can be found in the file +``TribitsExampleProject2/cmake/tpls/FindTPLTpl2.cmake``: + +.. include:: ../../examples/TribitsExampleProject2/cmake/tpls/FindTPLTpl2.cmake + :literal: + + +Creating FindTPL*.cmake using find_package() without IMPORTED targets +..................................................................... + +There are cases where calling ``find_package()`` to find the +parts of an external package does not create proper IMPORTED targets that can +be directly used. For example, legacy ``Find.cmake`` modules +(even many standard ``Find*.cmake`` modules shipped with CMake as of CMake +3.23) do not provide IMPORTED targets and instead only provide variables for +the list of include directories ``_INCLUDE_DIRS``, a list of +library files ``_LIBRARIES``, and other information. In cases +such as this, one can implement the ``FindTPL.cmake`` module by +calling ``find_package()``, setting +``TPL__INCLUDE_DIRS`` and ``TPL__LIBRARIES``, and then +calling `tribits_tpl_find_include_dirs_and_libraries()`_ to create the +``::all_libs`` target and the ``Config.cmake`` wrapper +config file. + +The simplest way to implement ``FindTPL.cmake`` is to always call +``find_package()`` as:: + + message("-- Using find_package( ...) ...") + find_package( REQUIRED) + + # Tell TriBITS that we found and there no need to look any further + set(TPL__INCLUDE_DIRS ${_INCLUDE_DIRS} CACHE PATH "...") + set(TPL__LIBRARIES ${_LIBRARIES} CACHE FILEPATH "...") + set(TPL__LIBRARY_DIRS ${_LIBRARY_DIRS} CACHE PATH "...") + + tribits_tpl_find_include_dirs_and_libraries( + REQUIRED_HEADERS neverFindThisHeader + REQUIRED_LIBS_NAMES neverFindThisLib + ) + +The above will always call ``find_package( REQUIRED)``, and if it +can't find the package, it will error out and stop the configure process. + +While the above ``FindTPL.cmake`` file is pretty simple, it does not +allow for a fall-back using the legacy TriBITS TPL find system using +`tribits_tpl_find_include_dirs_and_libraries()`_. One can allow for a +fall-back find by passing a set of header files and library names for +``tribits_tpl_find_include_dirs_and_libraries()`` to find. This can be done +using the ``FindTPL.cmake`` module:: -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()`_. 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 - # not called or does not find . Also, these variables need to be - # non-null in order to trigger the right behavior in the function - # tribits_tpl_find_include_dirs_and_libraries(). set(REQUIRED_HEADERS ...) set(REQUIRED_LIBS_NAMES ...) - - # Second, search for components (if allowed) using the standard - # find_package( ...). + + message("-- Using find_package( ...) ...") + find_package() + if (_FOUND) + # Tell TriBITS that we found and there no need to look any further + set(TPL__INCLUDE_DIRS ${_INCLUDE_DIRS} CACHE PATH "...") + set(TPL__LIBRARIES ${_LIBRARIES} CACHE FILEPATH "...") + set(TPL__LIBRARY_DIRS ${_LIBRARY_DIRS} CACHE PATH "...") + endif() + + tribits_tpl_find_include_dirs_and_libraries( + REQUIRED_HEADERS ${REQUIRED_HEADERS} + REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} ) + +Above, if ``find_package()`` can't find ````, then +the function ``tribits_tpl_find_include_dirs_and_libraries()`` will try to +find the listed required header files and libraries, using the legacy TriBITS +TPL find system. And if ``find_package()`` can find +````, then all the call to +`tribits_tpl_find_include_dirs_and_libraries()`_ will not look for anything +and will just take the information in the variables +``TPL__INCLUDE_DIRS`` and ``TPL__LIBRARIES`` and build +IMPORTED targets and the ``::all_libs`` target. + +Finally, if one is upgrading an existing ``FindTPL.cmake`` file to +use ``find_package()`` but needs to maintain backward +compatibility for existing configure scripts for the project that might be +using the legacy TriBITS TPL system, one can use the function +`tribits_tpl_allow_pre_find_package()`_ to determine if +``find_package()`` can be called or if the legacy TriBITS TPL +find must be used (to maintain backward compatibility). This +``FindTPL.cmake`` looks like:: + + set(REQUIRED_HEADERS ...) + set(REQUIRED_LIBS_NAMES ...) + tribits_tpl_allow_pre_find_package( _ALLOW_PREFIND) + if (_ALLOW_PREFIND) - message("-- Using find_package( ...) ...") - find_package() - if (_FOUND) - # Tell TriBITS that we found and there no need to look any further! - set(TPL__INCLUDE_DIRS ${_INCLUDE_DIRS} CACHE PATH "...") - set(TPL__LIBRARIES ${_LIBRARIES} CACHE FILEPATH "...") - set(TPL__LIBRARY_DIRS ${_LIBRARY_DIRS} CACHE PATH "...") + message("-- Using find_package ...) ...") + find_package() + if (_FOUND) + # Tell TriBITS that we found and there no need to look any further + set(TPL__INCLUDE_DIRS ${_INCLUDE_DIRS} CACHE PATH "...") + set(TPL__LIBRARIES ${_LIBRARIES} CACHE FILEPATH "...") + set(TPL__LIBRARY_DIRS ${_LIBRARY_DIRS} CACHE PATH "...") endif() endif() - - # Third, call tribits_tpl_find_include_dirs_and_libraries() + tribits_tpl_find_include_dirs_and_libraries( REQUIRED_HEADERS ${REQUIRED_HEADERS} - REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} - ) - # NOTE: If find_package( ...) was called and successfully found - # , then tribits_tpl_find_include_dirs_and_libraries() will use the - # already-set variables and just print them out. This is the final "hook" - # into the TriBITS TPL system. - -With this approach, the ``FindTPL.cmake`` module preserves all of the -user behavior described in `Enabling support for an optional Third-Party -Library (TPL)`_ for overriding what TPL components to look for, where to look -and finally to override what is actually used. That is, if the user sets the -cache variables ``TPL__INCLUDE_DIRS``, ``TPL__LIBRARIES``, -or ``TPL__LIBRARY_DIRS``, then they should be used without question -(which is why the ``set( ... CACHE ...)`` calls in the above example do not -use ``FORCE``). + REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} ) + +The above will result in skipping the call of ``find_package()`` +if any of the legacy TPL find variables are set. But if the legacy TPL find +variables are not set, then the default find will use +``find_package()`` and will only fall back on the legacy TriBITS +TPL find operation if ``find_package()`` sets +``_FOUND=FALSE``. + +With this last approach, the ``FindTPL.cmake`` module preserves all +of the user behavior described in `Enabling support for an optional +Third-Party Library (TPL)`_ for overriding what TPL components to look for, +where to look, and finally to override what is actually used. That is, if the +user sets the cache variables ``TPL__INCLUDE_DIRS``, +``TPL__LIBRARIES``, or ``TPL__LIBRARY_DIRS``, then they +should be used without question (which is why the ``set( ... CACHE ...)`` +calls in the above example do not use ``FORCE``). If one wants to skip and ignore the standard TriBITS TPL override variables ``_INCLUDE_DIRS``, ``_LIBRARY_NAMES``, or ``_LIBRARY_DIRS``, then one can set:: - set(_FORCE_PRE_FIND_PACKAGE TRUE CACHE BOOL + set(_FORCE_PRE_FIND_PACKAGE TRUE CACHE BOOL "Always first call find_package( ...) unless explicit override") at the top of the 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. +``_INCLUDE_DIRS`` and ``_LIBRARY_DIRS`` with +``_INCLUDE_DIRS`` and ``_LIBRARY_DIRS`` (when `` == +``) which are often used in the concrete legacy CMake +``Find.cmake`` module files themselves. For a slightly more complex (but real-life) example, see ``FindTPLHDF5.cmake`` which is: @@ -5583,75 +5781,50 @@ which is: .. include:: ../../common_tpls/FindTPLHDF5.cmake :literal: -Note that some specialized ``Find.cmake`` modules do more than just -return a list of include directories and libraries. Some, like +Note that some specialized ``Find.cmake`` modules do more than +just return a list of include directories and libraries. Some, like ``FindQt4.cmake`` also return other variables that are used in downstream packages. therefore, in these cases, ``find_package(Qt4 ...)`` must be called -on every configure. In specialized cases such as this, one must write a more -specialized ``FindTPL.cmake`` file and can't use the -`tribits_tpl_allow_pre_find_package()`_ function like shown above. Such -find modules cannot completely adhere to the standard behavior described in -`Enabling support for an optional Third-Party Library (TPL)`_. +on every configure. Such find modules cannot completely adhere to the +standard legacy TriBITS behavior described in `Enabling support for an +optional Third-Party Library (TPL)`_. -One issue to be made aware of is that code in ``FindTPL.cmake`` must -generate the file:: - /external_packages//Config.cmake +Creating a FindTPL*.cmake module without find_package() ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -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: +For external packages that don't have a ``Find.cmake`` module or +``Config.cmake`` package config file, it may make sense to create +a simple ``FindTpl.cmake`` module that just calls +`tribits_tpl_find_include_dirs_and_libraries()`_ with the set of required +header files and libraries that must be found. A simple +``FindTPL.cmake`` module of this form is:: -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.) + tribits_tpl_find_include_dirs_and_libraries( + REQUIRED_HEADERS ... + REQUIRED_LIBS_NAMES ... + ) + + +Requirements for FindTPL*.cmake modules ++++++++++++++++++++++++++++++++++++++++ + +It is possible to create a ``FindTPL.cmake`` module without using any +TriBITS functions. The only firm requirements for a +``FindTPL.cmake`` file after it is included are: + +* The target ``::all_libs`` must be created and it must contain all + of the needed libraries, include directories, and other usage requirements + (including for all upstream external packages/TPLs). + +* The file ``/external_packages//Config.cmake`` + must be created in the build directory and when including the file + ``Config.cmake`` it must define the equivalent target + ``::all_libs`` (and must call ``find_dependency()`` correctly on + all upstream external packages/TPLs). + +Some of issues to consider in this case are described in the section `Tricky +considerations for TriBITS-generated Config.cmake files`_. How to add a new TriBITS Repository @@ -5744,7 +5917,7 @@ as follows: #if HAVE__ # include "_" - #endif + #endif 4) **For an optional dependency, use CMake if() statements based on ${PACKAGE_NAME}_ENABLE_${OPTIONAL_DEP_PACKAGE_NAME}:** When a package @@ -5761,7 +5934,7 @@ as follows: endif() .. ToDo: Find an example to point to in TribitsExampleProject. - + NOTE: TriBITS will automatically add the include directories for the upstream package to the compile lines for the downstream package source builds and will add the libraries for the upstream package to the link lines to the downstream @@ -5824,7 +5997,7 @@ follows: #if HAVE__ # include "_" - #endif + #endif 4) **For an optional dependency, use CMake if() statements based on ${PACKAGE_NAME}_ENABLE_${OPTIONAL_DEP_TPL_NAME}:** When a package @@ -5841,7 +6014,7 @@ follows: endif() .. ToDo: Find an example to point to in TribitsExampleProject. - + NOTE: TriBITS will automatically add the include directories for the upstream TPL to the compile lines for the downstream package source builds and will add the libraries for the upstream TPL to the link lines to the downstream package @@ -6296,7 +6469,7 @@ The following steps describe how to submit results to a CDash site using the /TribitsExamplProject and then run ``make dashboard``. - + 4) Add custom CTest -S driver scripts. For driving different builds and tests, one needs to set up one or more @@ -6355,7 +6528,7 @@ The following steps describe how to submit results to a CDash site using the submit to CDash in a variety of ways: * Cron jobs can be set up to run them at the same time every day. - + * Jenkins jobs can be set up to run them based on various criteria. * Travis CI can run them to respond to GitHub pushes. @@ -6404,22 +6577,21 @@ given below. )`` in the CTest -S ``*.cmake`` driver script itself or can set it in the environment when running the ctest -S driver script. For example:: - + $ env _TRACK= ... \ ctest -V -S .cmake - + If the "build type" for the CDash group ```` was set to "Daily", then set `CTEST_TEST_TYPE`_ to ``Nightly``. Otherwise, ``CTEST_TEST_TYPE`` can be set to ``Continuous`` or ``Experimental``. -Additional Topics -================= +Miscellaneous Topics +==================== In this section, a number of miscellaneous topics and TriBITS features are discussed. These features and topics are either not considered primary -features of TriBITS (but can be very useful in many situations) or don't neatly -fit into one of the other sections. +features of TriBITS or don't neatly fit into one of the other sections. TriBITS Repository Contents @@ -6624,6 +6796,53 @@ ready to compile code. All of the major variables set as part of this process are printed to the ``cmake`` stdout when the project is configured. +Tricky considerations for TriBITS-generated Config.cmake files +----------------------------------------------------------------------- + +An issue that comes up with external packages/TPLs like HDF5 that needs to be +discussed here is the fact that ``FindTPL.cmake`` files create (See +`How to add a new TriBITS TPL`_) and TriBITS installs files of the name +``Config.cmake`` and that could potentially be found by calls to +``find_package()`` (when `` == `` like with +HDF5). These TriBITS-generated ``Config.cmake`` files are primarily +meant to be included by and provide the ``::all_libs`` targets for +downstream TriBITS-compatible ``Config.cmake`` files. These +TriBITS-generated ``Config.cmake`` files will usually not behave the +same way that a more general ``Find.config`` modules or native +``Config.cmake`` configure files would behave as expected when found +by ``find_package()`` commands called in some arbitrary downstream +raw CMake project. Therefore, to avoid having an installed TriBITS-generated +``HDF5Config.cmake`` file, for example, being found by the inner call to +``find_package(HDF5 ...)`` in the file ``FindTPLHDF5.cmake`` (which would be +disastrous), TriBITS employs two safeguards. First, TriBITS-generated +``Config.cmake`` files are placed into the build directory under:: + + /external_packages//Config.cmake + +and installed into the directory under:: + + /lib/external_packages//Config.cmake + +so they will not be found by ``find_package()`` by default when +``/cmake_packages`` and/or ````, respectively, are added +to ``CMake_PREFIX_PATH``. Also, even if +``/lib/external_packages`` or ``/external_packages`` do +get added to the search path somehow (e.g. by appending those to +``CMAKE_INSTALL_PREFIX``), the TriBITS framework will set the variable +``TRIBITS_FINDING_RAW__PACKAGE_FIRST=TRUE`` before including +``FindTPL.cmake`` and there is special logic in the TriBITS-generated +``ConfigVersion.cmake`` file that will set +``PACKAGE_VERSION_COMPATIBLE=OFF`` and result in ``find_package()`` +not selecting the TriBITS-generated ``Config.cmake`` file. (It turns +out that CMake's ``find_package()`` command always includes the file +``ConfigVersion.cmake``, even if no version information is passed to +the command ``find_package()``. This allows special logic to be +placed in the file ``ConfigVersion.cmake`` to determine if +``find_package()`` will select a given ``Config.cmake`` file +that is in the search path based on a number of different criteria such as in +this case.) + + Installation considerations --------------------------- @@ -6891,12 +7110,12 @@ rebase by default) as shown in the following Trilinos commit:: commit 71ce56bd2d268922fda7b8eca74fad0ffbd7d807 Author: Roscoe A. Bartlett Date: Thu Feb 19 12:04:11 2015 -0500 - + Define HAVE_TEUCHOSCORE_CXX11 in TeuchosCore_config.h - + This makes TeuchosCore a good example for how Trilinos (or any TriBITS) subpackages should put in an optional dependency on C++11. - + Build/Test Cases Summary Enabled Packages: TeuchosCore Disabled Packages: [...] @@ -7045,16 +7264,16 @@ the commands:: $ cat ../git_bisect_log.log | grep "possible first bad commit" | \ sed "s/possible first bad commit://g" | sed "s/[a-z0-9]\{30\}\]/]/g" $ git bisect reset - + This set of commands yield the output:: Bisecting: 1128 revisions left to test after this (roughly 10 steps) [9634d462dba77704b598e89ba69ba3ffa5a71471] Revert "Trilinos: remove _def.hpp [...]" - + real 1m22.961s user 0m57.157s sys 3m40.376s - + # [165067ce53] MueLu: SemiCoarsenPFactory. Use strided maps to properly transfer [...] # [ada21a95a9] MueLu: refurbish LineDetectionFactory # [83f05e8970] MueLu: stop semi-coarsening if no z-layers are left. @@ -7068,7 +7287,7 @@ bounded in the set of commits ``8b79832..165067c``:: 165067c "MueLu: SemiCoarsenPFactory. Use strided maps to properly [...]." Author: Tobias Wiesner Date: Thu Jul 2 12:11:24 2015 -0600 - + 8b79832 "Ifpack2: RBILUK: adding additional ETI types" Author: Jonathan Hu Date: Thu Jul 2 14:17:40 2015 -0700 @@ -7095,7 +7314,7 @@ intermediate commits are in Trilinos. All that matters is the usage of the ``checkin-test.py`` tool (another motivation for the usage of the ``checkin-test.py`` tool, see `Pre-push Testing using checkin-test.py`_ for others as well). - + Note that above, we grep the output from ``git bisect log`` for the set of possible "bad" commits instead of just looking at the output from the ``git bisect run