# @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(TribitsPackageSetupCompilerFlags) include(TribitsInternalPackageWriteConfigFile) include(TribitsGeneralMacros) include(TribitsLibIsTestOnly) include(CMakeParseArguments) include(GlobalNullSet) include(AppendGlobalSet) include(PrintVar) include(PrependSet) include(PrependGlobalSet) include(RemoveGlobalDuplicates) include(TribitsGatherBuildTargets) include(TribitsAddOptionAndDefine) include(TribitsPkgExportCacheVars) include(TribitsLibraryMacros) include(TribitsAddExecutable) include(TribitsAddExecutableAndTest) include(TribitsAddTest) include(TribitsAddAdvancedTest) include(TribitsCopyFilesToBinaryDir) include(TribitsReportInvalidTribitsUsage) # # Utility macros # # Macro that defines the package architecture system variables used to link # different packages together # # See README.DEPENDENCIES for information on what these variables mean and how # they are used. # macro(tribits_define_linkage_vars PACKAGE_NAME_IN) global_null_set(${PACKAGE_NAME_IN}_LIBRARIES "") global_set(${PACKAGE_NAME_IN}_HAS_NATIVE_LIBRARIES_TO_INSTALL FALSE) endmacro() # Macro that defines variables that create global targets # macro(tribits_define_target_vars PARENT_PACKAGE_NAME_IN) global_null_set(${PARENT_PACKAGE_NAME_IN}_LIB_TARGETS) global_null_set(${PARENT_PACKAGE_NAME_IN}_ALL_TARGETS) endmacro() # Set up some common variables used in the creation of an package # macro(tribits_set_common_vars PACKAGE_NAME_IN) string(TOUPPER ${PACKAGE_NAME_IN} PACKAGE_NAME_UC) # Write TRIBITS_PACKAGE versions of common variables set(PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") set(PACKAGE_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}") # Get the name of the directory this ${PROJECT_NAME} package is in file(TO_CMAKE_PATH ${CMAKE_CURRENT_SOURCE_DIR} STANDARD_PACKAGE_SOURCE_DIR) string(REGEX REPLACE "/.+/(.+)" "\\1" PACKAGE_DIR_NAME "${STANDARD_PACKAGE_SOURCE_DIR}") endmacro() # @MACRO: tribits_package_decl() # # Macro called at the very beginning of a package's top-level # `/CMakeLists.txt`_ file when a package has subpackages. # # Usage:: # # tribits_package_decl( # # [ENABLE_SHADOWING_WARNINGS] # [DISABLE_STRONG_WARNINGS] # [CLEANED] # [DISABLE_CIRCULAR_REF_DETECTION_FAILURE] # ) # # The arguments are: # # ```` # # Gives the name of the Package, mostly just for checking and # documentation purposes. This must match the name of the package # provided in the `/PackagesList.cmake`_ or an error is issued. # # ``ENABLE_SHADOWING_WARNINGS`` # # If specified, then shadowing warnings for the package's sources will be # turned on for supported platforms/compilers. The default is for # shadowing warnings to be turned off. Note that this can be overridden # globally by setting the cache variable # ``${PROJECT_NAME}_ENABLE_SHADOWING_WARNINGS``. # # ``DISABLE_STRONG_WARNINGS`` # # If specified, then all strong warnings for the package's sources will be # turned off, if they are not already turned off by global cache # variables. Strong warnings are turned on by default in development # mode. # # ``CLEANED`` # # If specified, then warnings will be promoted to errors for compiling the # package's sources for all defined warnings. # # ``DISABLE_CIRCULAR_REF_DETECTION_FAILURE`` # # If specified, then the standard grep looking for RCPNode circular # references in `tribits_add_test()`_ and `tribits_add_advanced_test()`_ # that causes tests to fail will be disabled. Note that if these warnings # are being produced then it means that the test is leaking memory and # user like may also be leaking memory. # # There are several side-effects of calling this macro: # # * The variables ``${PACKAGE_NAME}_LIB_TARGETS`` (lists all of the package's # targets) and ``${PACKAGE_NAME}_ALL_TARGETS`` (lists all of the package's # libraries) and are initialized to empty. # # * The local variables ``PACKAGE_SOURCE_DIR`` and ``PACKAGE_BINARY_DIR`` are # set for this package's use in its CMakeLists.txt files. # # * Package-specific compiler options are set up in package-scope (i.e., the # package's subdirs) in ``CMAKE__FLAG``. # # * This packages's cmake subdir ``${PACKAGE_SOURCE_DIR}/cmake`` is added to # ``CMAKE_MODULE_PATH`` locally so that the package's try-compile modules # can be read in with just a raw ``include()`` leaving off the full path and # the ``*.cmake`` extension. # # If the package does not have subpackages, just call `tribits_package()`_ # which calls this macro. # macro(tribits_package_decl PACKAGE_NAME_IN) if (${PROJECT_NAME}_VERBOSE_CONFIGURE) message("\nTRIBITS_PACKAGE_DECL: ${PACKAGE_NAME_IN}") endif() tribits_package_decl_assert_call_context() # # A) Parse the input arguments # cmake_parse_arguments( #prefix PARSE #options "CLEANED;ENABLE_SHADOWING_WARNINGS;DISABLE_STRONG_WARNINGS;DISABLE_CIRCULAR_REF_DETECTION_FAILURE" #one_value_keywords "" #multi_value_keywords "" ${ARGN} ) tribits_check_for_unparsed_arguments() # # B) Assert that the global and local package names are the same! # if (DEFINED PACKAGE_NAME) if (NOT ${PACKAGE_NAME_IN} STREQUAL ${PACKAGE_NAME}) message(FATAL_ERROR "Error, the package-defined package name" " '${PACKAGE_NAME_IN}' is not the same as the package name" " defined at the global level '${PACKAGE_NAME}'") endif() endif() # # C) Set up the CMake support for this ${PROJECT_NAME} package and define some # top-level variables. # tribits_set_common_vars(${PACKAGE_NAME_IN}) tribits_pkg_init_exported_vars(${PACKAGE_NAME_IN}) set(${PACKAGE_NAME_IN}_DISABLE_STRONG_WARNINGS OFF CACHE BOOL "If set to true, then strong warnings for package ${PACKAGE_NAME_IN} will be disabled." ) # Set up the compile flags for the package tribits_setup_compiler_flags(${PACKAGE_NAME_IN}) # Set up circular reference detection test failure if (PARSE_DISABLE_CIRCULAR_REF_DETECTION_FAILURE) set(${PACKAGE_NAME}_ENABLE_CIRCULAR_REF_DETECTION_FAILURE OFF) else() set(${PACKAGE_NAME}_ENABLE_CIRCULAR_REF_DETECTION_FAILURE ON) endif() # Set up parent package linkage variables tribits_define_target_vars(${PACKAGE_NAME}) # Define this as a CMake/CTest "Subproject" set_directory_properties(PROPERTIES LABELS "${PACKAGE_NAME}") # # Append the local package's cmake directory in order to help pull in # configure-time testing macros # prepend_set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) endmacro() macro(tribits_package_decl_assert_call_context) if (CURRENTLY_PROCESSING_SUBPACKAGE) tribits_report_invalid_tribits_usage( "Cannot call tribits_package_decl() in a subpackage." " Use tribits_subpackage() instead" " error in ${CURRENT_SUBPACKAGE_CMAKELIST_FILE}") endif() if(${PACKAGE_NAME}_TRIBITS_PACKAGE_DECL_CALLED) tribits_report_invalid_tribits_usage( "tribits_package_decl() called more than once in Package ${PACKAGE_NAME}" " This may be because tribits_package_decl() was explicitly called more than once or" " TRIBITS_PACKAGE_DECL was called after TRIBITS_PACKAGE. You do not need both." " If your package has subpackages then do not call tribits_package() instead call:" " tribits_pacakge_decl() then tribits_process_subpackages() then tribits package_def()" ) endif() # Set flag to check that macros are called in the correct order set(${PACKAGE_NAME}_TRIBITS_PACKAGE_DECL_CALLED TRUE) endmacro() # @MACRO: tribits_package_def() # # Macro called in `/CMakeLists.txt`_ after subpackages are # processed in order to handle the libraries, tests, and examples of the # parent package. # # Usage:: # # tribits_package_def() # # If the package does not have subpackages, just call `tribits_package()`_ # which calls this macro. # # This macro has several side effects: # # * The variable ``PACKAGE_NAME`` is set in the local scope for usage by the # package's ``CMakeLists.txt`` files. # # * The intra-package dependency variables (i.e. list of include directories, # list of libraries, etc.) are initialized to empty. # macro(tribits_package_def) if (${PROJECT_NAME}_VERBOSE_CONFIGURE) message("\nTRIBITS_PACKAGE_DEF: ${PACKAGE_NAME}") endif() tribits_package_def_assert_call_context() if (NOT ${PROJECT_NAME}_ENABLE_${PACKAGE_NAME}) if (${PROJECT_NAME}_VERBOSE_CONFIGURE) message("\n${PACKAGE_NAME} not enabled so exiting package processing") endif() return() endif() # Reset in case were changed by subpackages tribits_set_common_vars(${PACKAGE_NAME}) # Define package linkage variables tribits_define_linkage_vars(${PACKAGE_NAME}) endmacro() macro(tribits_package_def_assert_call_context) # check that this is not being called from a subpackage if(NOT ${SUBPACKAGE_FULLNAME}_TRIBITS_SUBPACKAGE_POSTPROCESS_CALLED) if (CURRENTLY_PROCESSING_SUBPACKAGE) tribits_report_invalid_tribits_usage( "Cannot call tribits_package_def() in a subpackage." " Use tribits_subpackage() instead" " error in ${CURRENT_SUBPACKAGE_CMAKELIST_FILE}") endif() endif() # Reset since it was changed by the subpackages set(PACKAGE_NAME ${PARENT_PACKAGE_NAME}) # check that this is not called morethan once in a package if (${PACKAGE_NAME}_TRIBITS_PACKAGE_DEF_CALLED) tribits_report_invalid_tribits_usage( "tribits_package_def() was called more than once in" "${CURRENT_SUBPACKAGE_CMAKELIST_FILE}") endif() set(${PACKAGE_NAME}_TRIBITS_PACKAGE_DEF_CALLED TRUE) endmacro() # @MACRO: tribits_package() # # Macro called at the very beginning of a package's top-level # `/CMakeLists.txt`_ file. # # Usage:: # # tribits_package( # # [ENABLE_SHADOWING_WARNINGS] # [DISABLE_STRONG_WARNINGS] # [CLEANED] # [DISABLE_CIRCULAR_REF_DETECTION_FAILURE] # ) # # See `tribits_package_decl()`_ for the documentation for the arguments and # `tribits_package_decl()`_ and `tribits_package()`_ for a description the # side-effects (and variables set) after calling this macro. # macro(tribits_package PACKAGE_NAME_IN) tribits_package_assert_call_context() tribits_package_decl(${PACKAGE_NAME_IN} ${ARGN}) tribits_package_def() endmacro() macro(tribits_package_assert_call_context) if (CURRENTLY_PROCESSING_SUBPACKAGE) if (NOT ${SUBPACKAGE_FULLNAME}_TRIBITS_SUBPACKAGE_POSTPROCESS_CALLED) tribits_report_invalid_tribits_usage( "Cannot call tribits_package() in a subpackage." " Use tribits_subpackage() instead" " error in ${CURRENT_SUBPACKAGE_CMAKELIST_FILE}") endif() endif() if(${PACKAGE_NAME}_SUBPACKAGES) tribits_report_invalid_tribits_usage( "This package has subpackages so you cannot use tribits_package()" "\n Instead use the following call order:" "\n tribits_project_decl(${PACKAGE_NAME})" "\n tribits_process_subpackages()" "\n [do other things you want to do]" "\n tribits_package_def()" "\n tribits_package_postprocess()" ) endif() if(${PACKAGE_NAME}_TRIBITS_PACKAGE_CALLED) tribits_report_invalid_tribits_usage( "Package ${PACKAGE_NAME} declared more than once!") endif() set(${PACKAGE_NAME}_TRIBITS_PACKAGE_CALLED TRUE) endmacro() # @MACRO: tribits_disable_optional_dependency() # # Macro called to disable an optional dependency in the current package for an # optional (internal or external) upstream package. # # Usage:: # # tribits_disable_optional_dependency( "") # # This macro can be called from a top-level package's # ``/CMakeLists.txt`` file to disable an optional dependency that # may have been enabled by the user or through automated enable/disable logic. # # This is most useful in cases where multiple criteria must be considered # before support for some upstream dependency can really be supported. In # that case, the dependency can be disabled in the current package and # telegraphed to all downstream packages. See `How to tweak downstream # TriBITS "ENABLE" variables during package configuration`_ for more details. # macro(tribits_disable_optional_dependency upstreamPackageName reasonStr) # Assert called in the correct context if (NOT "${${PACKAGE_NAME}_PARENT_PACKAGE}" STREQUAL "") message(FATAL_ERROR "ERROR: Calling tribits_disable_optional_dependency() from" " a subpackage it not allowed. It must be called from the parent package's" " ${${PACKAGE_NAME}_PARENT_PACKAGE} CMakeLists.txt file") endif() if (NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${${PACKAGE_NAME}_SOURCE_DIR}") message(FATAL_ERROR "ERROR: Calling tribits_disable_optional_dependency() from" " a subdirectory CMakeLists.txt file under '${CMAKE_CURRENT_SOURCE_DIR}' is not allowed." " Instead, please call this from the package's base CMakeLists.txt file" " '${${PACKAGE_NAME}_SOURCE_DIR}/CMakeLists.txt'" ) endif() # Get the variable names that are going to be set assert they exist already set(packageEnableVarName ${PACKAGE_NAME}_ENABLE_${upstreamPackageName}) assert_defined(${packageEnableVarName}) string(TOUPPER ${upstreamPackageName} upstreamPackageName_UC) set(havePackageUpstreamPackageMacroVarName HAVE_${PACKAGE_NAME_UC}_${upstreamPackageName_UC}) assert_defined(${havePackageUpstreamPackageMacroVarName}) # Set the variables to OFF in local and project-level scopes if (NOT "${reasonStr}" STREQUAL "") message("-- ${reasonStr}") endif() dual_scope_set(${packageEnableVarName} OFF) dual_scope_set(${havePackageUpstreamPackageMacroVarName} OFF) endmacro() # @MACRO: tribits_add_test_directories() # # Macro called to add a set of test directories for an package. # # Usage:: # # tribits_add_test_directories( ...) # # This macro only needs to be called from the top most ``CMakeLists.txt`` file # for which all subdirectories are all "tests". # # This macro can be called several times within a package and it will have the # right effect. # # Currently, all this macro does macro is to call ``add_subdirectory()`` # if ``${PACKAGE_NAME}_ENABLE_TESTS`` is ``TRUE``. # macro(tribits_add_test_directories) tribits_add_test_example_directories_assert_call_context( tribits_add_test_directories) if(${PACKAGE_NAME}_ENABLE_TESTS) foreach(TEST_DIR ${ARGN}) tribits_trace_file_processing(PACKAGE ADD_SUBDIR "${CMAKE_CURRENT_SOURCE_DIR}/${TEST_DIR}/CMakeLists.txt") add_subdirectory(${TEST_DIR}) endforeach() endif() endmacro() # # Macros to add common options to add to an package # # @MACRO: tribits_add_debug_option() # # Add the standard cache variable option ``${PACKAGE_NAME}_ENABLE_DEBUG`` for # the package. # # Usage:: # # tribits_add_debug_option() # # 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``). # # NOTE: This also calls `tribits_pkg_export_cache_var()`_ to export the # variable ``${PACKAGE_NAME}_ENABLE_DEBUG``. # macro(tribits_add_debug_option) tribits_add_option_and_define( ${PACKAGE_NAME}_ENABLE_DEBUG HAVE_${PACKAGE_NAME_UC}_DEBUG "Enable a host of runtime debug checking." ${${PROJECT_NAME}_ENABLE_DEBUG} ) endmacro() macro(tribits_add_enable_teuchos_time_monitor_option) option( ${PACKAGE_NAME}_ENABLE_TEUCHOS_TIME_MONITOR "Enable Teuchos time monitors for package ${PACKAGE_NAME}" ${${PROJECT_NAME}_ENABLE_TEUCHOS_TIME_MONITOR} ) endmacro() # @MACRO: tribits_add_show_deprecated_warnings_option() # # Add the standard option ``${PACKAGE_NAME}_SHOW_DEPRECATED_WARNINGS`` for the # package. # # Usage:: # # tribits_add_show_deprecated_warnings_option() # # This macro should be called in the package's /CMakeLists.txt`_ # file. This option is given the default value # ``${${PROJECT_NAME}_SHOW_DEPRECATED_WARNINGS}``. This option is then looked # for in `tribits_configure_file()`_ to add macros to add deprecated warnings # to deprecated parts of a package. # macro(tribits_add_show_deprecated_warnings_option) advanced_set( ${PACKAGE_NAME}_SHOW_DEPRECATED_WARNINGS ${${PROJECT_NAME}_SHOW_DEPRECATED_WARNINGS} CACHE BOOL "Show warnings about deprecated code in ${PACKAGE_NAME}" ) advanced_set( ${PACKAGE_NAME}_HIDE_DEPRECATED_CODE ${${PROJECT_NAME}_HIDE_DEPRECATED_CODE} CACHE BOOL "Fully exclude deprecated code in ${PACKAGE_NAME}" ) endmacro() macro(tribits_add_explicit_instantiation_option) tribits_add_option_and_define( ${PACKAGE_NAME}_ENABLE_EXPLICIT_INSTANTIATION HAVE_${PACKAGE_NAME_UC}_EXPLICIT_INSTANTIATION "Enable the use of explicit template instantiation." ${${PROJECT_NAME}_ENABLE_EXPLICIT_INSTANTIATION} ) endmacro() macro(tribits_add_eti_support) append_global_set(${PROJECT_NAME}_ETI_PACKAGES ${PACKAGE_NAME}) global_null_set(${PACKAGE_NAME}_ETI_LIBRARYSET) endmacro() # @MACRO: tribits_add_example_directories() # # Macro called to conditionally add a set of example directories for an # package. # # Usage:: # # tribits_add_example_directories( ...) # # This macro typically is called from the top-level # `/CMakeLists.txt`_ file for which all subdirectories are all # "examples" according to standard package layout. # # This macro can be called several times within a package as desired to break # up example directories any way one would like. # # Currently, all it does macro does is to call ``add_subdirectory()`` if # `${PACKAGE_NAME}_ENABLE_EXAMPLES`_ ``= TRUE``. # macro(tribits_add_example_directories) tribits_add_test_example_directories_assert_call_context( tribits_add_example_directories) if(${PACKAGE_NAME}_ENABLE_EXAMPLES) foreach(EXAMPLE_DIR ${ARGN}) tribits_trace_file_processing(PACKAGE ADD_SUBDIR "${CMAKE_CURRENT_SOURCE_DIR}/${EXAMPLE_DIR}/CMakeLists.txt") add_subdirectory(${EXAMPLE_DIR}) endforeach() endif() endmacro() macro(tribits_add_test_example_directories_assert_call_context macroName) 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 ${macroName}()" " in ${CURRENT_SUBPACKAGE_CMAKELIST_FILE}") endif() if(${SUBPACKAGE_FULLNAME}_TRIBITS_SUBPACKAGE_POSTPROCESS_CALLED) tribits_report_invalid_tribits_usage( "Must call ${macroName}() 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" " ${macroName}() in ${TRIBITS_PACKAGE_CMAKELIST_FILE}") endif() if(${PACKAGE_NAME}_TRIBITS_PACKAGE_POSTPROCESS_CALLED) tribits_report_invalid_tribits_usage( "Must call ${macroName}() before " " tribits_package_postprocess() in ${TRIBITS_PACKAGE_CMAKELIST_FILE}") endif() endif() 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) # A package with subpackages should get all of its dependency vars from # its enabled subpackages. set(PARENT_PACKAGE_LIBRARIES "") set(SUBPACKAGE_IDX 0) foreach(TRIBITS_SUBPACKAGE ${${PARENT_PACKAGE_NAME}_SUBPACKAGES}) set(SUBPACKAGE_NAME ${TRIBITS_SUBPACKAGE}) set(SUBPACKAGE_FULLNAME ${PARENT_PACKAGE_NAME}${TRIBITS_SUBPACKAGE}) if (${PROJECT_NAME}_ENABLE_${SUBPACKAGE_FULLNAME}) prepend_set(PARENT_PACKAGE_LIBRARIES ${${SUBPACKAGE_FULLNAME}_LIBRARIES}) endif() math(EXPR SUBPACKAGE_IDX "${SUBPACKAGE_IDX}+1") endforeach() # NOTE: There can't be any duplicate libraries in PARENT_PACKAGE_LIBRARIES # so no need to remove them. global_set(${PACKAGE_NAME}_LIBRARIES "${PARENT_PACKAGE_LIBRARIES}") endif() endfunction() # Helper macro for [SUB]tribits_package_postprocess() # macro(tribits_package_postprocess_common) if (${PROJECT_NAME}_VERBOSE_CONFIGURE) message("\nTRIBITS_PACKAGE_POSTPROCESS_COMMON: ${PACKAGE_NAME}") print_var(${PACKAGE_NAME}_LIBRARIES) endif() 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(). tribits_write_package_client_export_files(${PACKAGE_NAME}) endif() set(${PACKAGE_NAME}_FINISHED_FIRST_CONFIGURE TRUE CACHE INTERNAL "") endmacro() # Macro to create the ${PACKAGE_NAME}::all_libs INTERFACE target # macro(tribits_package_create_all_libs_interface_library) if (NOT TARGET ${PACKAGE_NAME}_all_libs) # Find all of the non-TESTONLY library targets tribits_get_all_build_targets_including_in_subdirs("${CMAKE_CURRENT_SOURCE_DIR}" "STATIC_LIBRARY;SHARED_LIBRARY" allPackageBuildableLibTargetsList ) #print_var(allPackageBuildableLibTargetsList) set(packageLibsInAllLibsList) foreach (libTarget IN LISTS allPackageBuildableLibTargetsList) tribits_lib_is_testonly(${libTarget} isTestOnlyLib) #print_var(isTestOnlyLib) if (NOT isTestOnlyLib) list(APPEND packageLibsInAllLibsList ${libTarget}) endif() endforeach() global_set(${PACKAGE_NAME}_EXPORTED_PACKAGE_LIBS_NAMES ${packageLibsInAllLibsList}) # Create the ${PACKAGE_NAME}_all_libs INTERFACE interface target add_library(${PACKAGE_NAME}_all_libs INTERFACE) target_link_libraries(${PACKAGE_NAME}_all_libs INTERFACE ${packageLibsInAllLibsList} ) set_target_properties(${PACKAGE_NAME}_all_libs PROPERTIES EXPORT_NAME all_libs) if (${PROJECT_NAME}_IMPORTED_NO_SYSTEM) set_target_properties(${PACKAGE_NAME}_all_libs PROPERTIES IMPORTED_NO_SYSTEM TRUE) endif() # Install the interface target (makes sure it gets put in # Targets.cmake file) install( TARGETS ${PACKAGE_NAME}_all_libs EXPORT ${PACKAGE_NAME} INCLUDES DESTINATION "${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}" RUNTIME DESTINATION "${${PROJECT_NAME}_INSTALL_RUNTIME_DIR}" LIBRARY DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}" ARCHIVE DESTINATION "${${PROJECT_NAME}_INSTALL_LIB_DIR}" COMPONENT ${PACKAGE_NAME} ) if (NOT TARGET ${PACKAGE_NAME}::all_libs) # Create ALIAS ${PACKAGE_NAME}::all_libs target add_library(${PACKAGE_NAME}::all_libs ALIAS ${PACKAGE_NAME}_all_libs) endif() endif() #include(CMakePrintHelpers) #cmake_print_properties(TARGETS ${PACKAGE_NAME}_all_libs ${PACKAGE_NAME}::all_libs # PROPERTIES TYPE ALIASED_TARGET INTERFACE_LINK_LIBRARIES) endmacro() # @MACRO: tribits_package_postprocess() # # Macro called at the very end of a package's top-level # `/CMakeLists.txt`_ file that performs some critical # post-processing activities. # # Usage:: # # 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 package's # top-level ``CMakeLists.txt`` file but limitations of the CMake language make # it necessary to do so. # macro(tribits_package_postprocess) # check that this is not being called from inside a subpackage if (CURRENTLY_PROCESSING_SUBPACKAGE) if(NOT ${SUBPACKAGE_FULLNAME}_TRIBITS_SUBPACKAGE_POSTPROCESS_CALLED) tribits_report_invalid_tribits_usage( "Cannot call tribits_package_postprocess() in a subpackage." " Use tribits_subpackage_postprocess() instead" " ${CURRENT_SUBPACKAGE_CMAKELIST_FILE}") endif() endif() if(${PACKAGE_NAME}_SUBPACKAGES) # This is a package that has subpackages if(NOT ${PACKAGE_NAME}_TRIBITS_PACKAGE_DECL_CALLED OR NOT ${PACKAGE_NAME}_TRIBITS_PACKAGE_DEF_CALLED OR NOT ${PACKAGE_NAME}_TRIBITS_PROCESS_SUBPACKAGES_CALLED ) tribits_report_invalid_tribits_usage( "Must call tribits_package_decl(), tribits_process_subpackages()" " and tribits_package_def() before tribits_package_postprocess()." " Because this package has subpackages you cannot use tribits_package()" " you must call these in the following order:" " tribits_package_decl()" " tribits_process_subpackages()" " tribits_package_def()" " tribits_package_postprocess()" " in: " "${TRIBITS_PACKAGE_CMAKELIST_FILE}" ) endif() else() # This is a package without subpackages if ( (NOT ${PACKAGE_NAME}_TRIBITS_PACKAGE_CALLED) AND (NOT ${PACKAGE_NAME}_TRIBITS_PACKAGE_DEF_CALLED) ) tribits_report_invalid_tribits_usage( "Must call tribits_package() or tribits_package_def() before" " tribits_package_postprocess()" " at the top of the file:\n" " ${TRIBITS_PACKAGE_CMAKELIST_FILE}" ) endif() endif() if(NOT ${PACKAGE_NAME}_TRIBITS_PACKAGE_DEF_CALLED) tribits_report_invalid_tribits_usage( "Must call tribits_package() before tribits_package_postprocess()." " Or if your package has subpackages you must first call tribits_package_decl()," " then tribits_process_subpackages(), then tribits_package_def(), then" " tribits_package_postprocess() in" " ${TRIBITS_PACKAGE_CMAKELIST_FILE}" ) endif() if(${PACKAGE_NAME}_TRIBITS_PACKAGE_POSTPROCESS_CALLED) tribits_report_invalid_tribits_usage( "tribits_package_postprocess() has been called more than once in" " ${TRIBITS_PACKAGE_CMAKELIST_FILE}") endif() # Only parent packages have the targets (${PACKAGE_NAME}_libs and # (${PACKAGE_NAME}_all if (${PROJECT_NAME}_VERBOSE_CONFIGURE) message("\nTRIBITS_PACKAGE_POSTPROCESS: ${PACKAGE_NAME}") print_var(${PACKAGE_NAME}_LIB_TARGETS) print_var(${PACKAGE_NAME}_ALL_TARGETS) endif() add_custom_target(${PACKAGE_NAME}_libs DEPENDS ${${PACKAGE_NAME}_LIB_TARGETS}) add_custom_target(${PACKAGE_NAME}_all DEPENDS ${${PACKAGE_NAME}_ALL_TARGETS}) tribits_package_finalize_dependency_vars() tribits_package_postprocess_common() if (${PACKAGE_NAME}_SOURCE_DIR STREQUAL ${PROJECT_NAME}_SOURCE_DIR) set(${PACKAGE_NAME}_TRIBITS_PACKAGE_POSTPROCESS TRUE) else() set(${PACKAGE_NAME}_TRIBITS_PACKAGE_POSTPROCESS TRUE PARENT_SCOPE) endif() set(${PACKAGE_NAME}_TRIBITS_PACKAGE_POSTPROCESS_CALLED TRUE) endmacro() # @MACRO: tribits_process_subpackages() # # Macro that processes the `TriBITS Subpackages`_ for a parent `TriBITS # package`_ for packages that are broken down into subpackages. This is # called in the parent packages top-level `/CMakeLists.txt`_ file. # # Usage:: # # tribits_process_subpackages() # # This macro must be called after `tribits_package_decl()`_ but before # `tribits_package_def()`_. # macro(tribits_process_subpackages) if (CURRENTLY_PROCESSING_SUBPACKAGE) tribits_report_invalid_tribits_usage( "Cannot call tribits_process_subpackages() in a subpackage." " subpackages cannot contain other subpackages" " ${CURRENT_SUBPACKAGE_CMAKELIST_FILE}") endif() if (${PACKAGE_NAME}_TRIBITS_PACKAGE_POSTPROCESS_CALLED) tribits_report_invalid_tribits_usage( "Must call tribits_process_subpackages() before tribits_package_postprocess()" " in ${TRIBITS_PACKAGE_CMAKELIST_FILE}") endif() if (NOT ${PACKAGE_NAME}_TRIBITS_PACKAGE_DECL_CALLED) tribits_report_invalid_tribits_usage( "Must call tribits_package_decl() before tribits_process_subpackages()" " in ${TRIBITS_PACKAGE_CMAKELIST_FILE}") endif() if (${PACKAGE_NAME}_TRIBITS_PACKAGE_DEF_CALLED) tribits_report_invalid_tribits_usage( "Must call tribits_package_def() after tribits_process_subpackages()" " in ${TRIBITS_PACKAGE_CMAKELIST_FILE}") endif() if (NOT ${PARENT_PACKAGE_NAME}_SUBPACKAGES) tribits_report_invalid_tribits_usage( "The TriBITS Package '${PACKAGE_NAME}' does not have any subpackages." " Therefore, you are not allowed to call tribits_process_subpackages()!") endif() set(SUBPACKAGE_IDX 0) foreach(TRIBITS_SUBPACKAGE ${${PARENT_PACKAGE_NAME}_SUBPACKAGES}) #message("") #print_var(SUBPACKAGE_IDX) #print_var(TRIBITS_SUBPACKAGE) set(SUBPACKAGE_NAME ${TRIBITS_SUBPACKAGE}) set(SUBPACKAGE_FULLNAME ${PARENT_PACKAGE_NAME}${TRIBITS_SUBPACKAGE}) #print_var(SUBPACKAGE_FULLNAME) if (${PROJECT_NAME}_ENABLE_${SUBPACKAGE_FULLNAME}) list(GET ${PARENT_PACKAGE_NAME}_SUBPACKAGE_DIRS ${SUBPACKAGE_IDX} SUBPACKAGE_DIR) #print_var(SUBPACKAGE_DIR) if (NOT ${PROJECT_NAME}_BINARY_DIR STREQUAL ${PARENT_PACKAGE_NAME}_BINARY_DIR) dual_scope_set(${SUBPACKAGE_FULLNAME}_BINARY_DIR ${${PARENT_PACKAGE_NAME}_BINARY_DIR}/${SUBPACKAGE_DIR}) else() set(${SUBPACKAGE_FULLNAME}_BINARY_DIR ${${PARENT_PACKAGE_NAME}_BINARY_DIR}/${SUBPACKAGE_DIR}) endif() set(CURRENT_SUBPACKAGE_CMAKELIST_FILE "${${SUBPACKAGE_FULLNAME}_SOURCE_DIR}/CMakeLists.txt") tribits_trace_file_processing(PACKAGE ADD_SUBDIR ${CURRENT_SUBPACKAGE_CMAKELIST_FILE} ) set(CURRENTLY_PROCESSING_SUBPACKAGE ${SUBPACKAGE_FULLNAME}) add_subdirectory(${${SUBPACKAGE_FULLNAME}_SOURCE_DIR} ${${SUBPACKAGE_FULLNAME}_BINARY_DIR}) endif() math(EXPR SUBPACKAGE_IDX "${SUBPACKAGE_IDX}+1") endforeach() set(CURRENTLY_PROCESSING_SUBPACKAGE FALSE) set(${PACKAGE_NAME}_TRIBITS_PROCESS_SUBPACKAGES_CALLED TRUE) endmacro()