1# @HEADER 2# ************************************************************************ 3# 4# TriBITS: Tribal Build, Integrate, and Test System 5# Copyright 2013 Sandia Corporation 6# 7# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 8# the U.S. Government retains certain rights in this software. 9# 10# Redistribution and use in source and binary forms, with or without 11# modification, are permitted provided that the following conditions are 12# met: 13# 14# 1. Redistributions of source code must retain the above copyright 15# notice, this list of conditions and the following disclaimer. 16# 17# 2. Redistributions in binary form must reproduce the above copyright 18# notice, this list of conditions and the following disclaimer in the 19# documentation and/or other materials provided with the distribution. 20# 21# 3. Neither the name of the Corporation nor the names of the 22# contributors may be used to endorse or promote products derived from 23# this software without specific prior written permission. 24# 25# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 26# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 29# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 30# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 31# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 32# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 33# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 34# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 35# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36# 37# ************************************************************************ 38# @HEADER 39 40 41INCLUDE(SetCacheOnOffEmpty) 42INCLUDE(MultilineSet) 43INCLUDE(AdvancedOption) 44INCLUDE(AdvancedSet) 45INCLUDE(AssertDefined) 46INCLUDE(PrintVar) 47INCLUDE(MessageWrapper) 48INCLUDE(TribitsListHelpers) 49 50 51# 52# Helper functions 53# 54 55 56# 57# @MACRO: TRIBITS_REPOSITORY_DEFINE_PACKAGES() 58# 59# Define the set of packages for a given `TriBITS Repository`_. This macro is 60# typically called from inside of a `<repoDir>/PackagesList.cmake`_ file for a 61# given TriBITS repo. 62# 63# Usage:: 64# 65# TRIBITS_REPOSITORY_DEFINE_PACKAGES( 66# <pkg0> <pkg0_dir> <pkg0_classif> 67# <pkg1> <pkg1_dir> <pkg1_classif> 68# ... 69# ) 70# 71# This macro sets up a 2D array of ``NumPackages`` by ``NumColumns`` listing 72# out the packages for a TriBITS repository. Each row (with 3 column entries) 73# specifies a package which contains the columns (ordered 0-2): 74# 75# 0. **PACKAGE** (``<pkgi>``): The name of the TriBITS package. This name 76# must be unique across all other TriBITS packages in this or any other 77# TriBITS repo that might be combined into a single TriBITS project 78# meta-build (see `Globally unique TriBITS package names`_). The name 79# should be a valid identifier (e.g. matches the regex 80# ``[a-zA-Z_][a-zA-Z0-9_]*``). The package names tend to use mixed case 81# (e.g. ```SomePackge`` not ``SOMEPACKGE``). 82# 83# 1. **DIR** (``<pkgi_dir>``): The relative directory for the package 84# ``<packageDir>``. This directory is relative to the TriBITS repository 85# base directory ``<repoDir>``. Under this directory will be a 86# package-specific ``cmake/`` directory with the file 87# `<packageDir>/cmake/Dependencies.cmake`_ and a base-level 88# `<packageDir>/CMakeLists.txt`_ file. The entire contents of the package 89# including all of the source code and all of the tests should be contained 90# under this directory. The TriBITS testing infrastructure relies on the 91# mapping of changed files to these base directories when deciding what 92# packages are modified and need to be retested (along with downstream 93# packages). For details, see `checkin-test.py`_. 94# 95# 2. **CLASSIFICATION** (``<pkgi_classif>``): Gives the `SE Package Test 96# Group`_ `PT`_, `ST`_, or `EX`_ and the maturity level ``EP``, ``RS``, 97# ``PG``, ``PM``, ``GRS``, ``GPG``, ``GPM``, ``UM``. These are separated 98# by a coma with no space in between such as ``"RS,PT"`` for a "Research 99# Stable", "Primary Tested" package. No spaces are allowed so that CMake 100# treats this a one field in the array. The maturity level can be left off 101# in which case it is assumed to be ``UM`` for "Unspecified Maturity". 102# This classification for individual packages can be changed to ``EX`` for 103# specific platforms by calling `TRIBITS_DISABLE_PACKAGE_ON_PLATFORMS()`_. 104# 105# **IMPORTANT:** The packages must be listed in increasing order of package 106# dependencies. That is `No circular dependencies of any kind are allowed`_ 107# (see the *ADP (Acyclic Dependencies Principle)* in `Software Engineering 108# Packaging Principles`_). Package ``i`` can only list dependencies (in 109# `<packageDir>/cmake/Dependencies.cmake`_) for packages listed before this 110# package in this list (or in upstream TriBITS repositories). This avoids an 111# expensive package sorting algorithm and makes it easy to flag packages with 112# circular dependencies or misspelling of package names. 113# 114# NOTE: For some rare use cases, the package directory ``<pkgi_dir>`` is 115# allowed to be specified as an absolute directory but this absolute directory 116# must be a subdirectory of the project source base directory given by 117# `PROJECT_SOURCE_DIR`_. If not, ``MESSAGE(FATAL_ERROR ...)`` is called and 118# processing stops immediately. 119# 120# NOTE: This macro just sets the variable:: 121# 122# ${REPOSITORY_NAME}_PACKAGES_AND_DIRS_AND_CLASSIFICATIONS 123# 124# in the current scope. The advantages of using this macro instead of 125# directly setting this variable are that the macro: 126# 127# * Asserts that the variable ``REPOSITORY_NAME`` is defined and set 128# 129# * Avoids having to hard-code the assumed repository name 130# ``${REPOSITORY_NAME}``. This provides more flexibility for how other 131# TriBITS projects choose to name a given TriBITS repo (i.e. the name of 132# repo subdirs). 133# 134# * Avoid misspelling the name of the variable 135# ``${REPOSITORY_NAME}_PACKAGES_AND_DIRS_AND_CLASSIFICATIONS``. If one 136# misspells the name of the macro, it is an immediate error in CMake. 137# 138MACRO(TRIBITS_REPOSITORY_DEFINE_PACKAGES) 139 ASSERT_DEFINED(REPOSITORY_NAME) 140 SET(${REPOSITORY_NAME}_PACKAGES_AND_DIRS_AND_CLASSIFICATIONS "${ARGN}") 141ENDMACRO() 142 143 144# 145# @FUNCTION: TRIBITS_ALLOW_MISSING_EXTERNAL_PACKAGES() 146# 147# Allow listed packages to be missing and automatically excluded from the 148# package dependency data-structures. 149# 150# Usage:: 151# 152# TRIBITS_ALLOW_MISSING_EXTERNAL_PACKAGES(<pkg0> <plg1> ...) 153# 154# If the missing upstream SE package ``<pkgi>`` is optional, then the effect 155# will be to simply ignore the missing package (i.e. it will never be added to 156# package's list and not added to dependency data-structures) and remove it 157# from the dependency lists for downstream SE packages that have an optional 158# dependency on the missing upstream SE package ``<pkgi>``. However, all 159# downstream SE packages that have a required dependency on the missing 160# upstream SE package ``<pkgi>`` will be hard disabled, 161# i.e. ``${PROJECT_NAME}_ENABLE_{CURRENT_PACKAGE}=OFF`` and a note on the 162# disable will be printed. 163# 164# **WARNING**: This macro just sets the cache variable 165# ``<pkgi>_ALLOW_MISSING_EXTERNAL_PACKAGE=TRUE`` for each SE package 166# ``<pkgi>``. Therefore, using this function effectively turns off error 167# checking for misspelled package names so it is important to only use it when 168# it absolutely is needed (use cases mentioned below). Also note that missing 169# packages are silently ignored by default. Therefore, when doing development 170# involving these packages, it is usually a good idea to set:: 171# 172# -D<pkgi>_ALLOW_MISSING_EXTERNAL_PACKAGE=FALSE 173# 174# so that it will catch errors in the misspelling of package names or source 175# directories. However, notes on what missing packages are being ignored can 176# printed by configuring with:: 177# 178# -D <Project>_WARN_ABOUT_MISSING_EXTERNAL_PACKAGES=TRUE 179# 180# This macro is typically called in one of two different contexts: 181# 182# * Called from `<packageDir>/cmake/Dependencies.cmake`_ when the upstream 183# package ``<pkgi>`` is defined in an optional upstream `TriBITS 184# Repository`_. This allows the downstream repos and packages to still be 185# enabled (assuming they don't have required dependencies on the missing 186# packages) when one or more upstream repos are missing. 187# 188# * Called from `<repoDir>/PackagesList.cmake`_ when the package ``<pkgi>`` 189# might be defined in an optional non-TriBITS repo (see `How to insert a 190# package into an upstream repo`_). 191# 192# For some meta-projects that composes packages from may different TriBITS 193# repositories, one might need to also call this function from the file 194# `<projectDir>/cmake/ProjectDependenciesSetup.cmake`_. 195# 196FUNCTION(TRIBITS_ALLOW_MISSING_EXTERNAL_PACKAGES) 197 FOREACH(TRIBITS_PACKAGE ${ARGN}) 198 ADVANCED_SET(${TRIBITS_PACKAGE}_ALLOW_MISSING_EXTERNAL_PACKAGE TRUE 199 CACHE BOOL 200 "Default set by TRIBITS_ALLOW_MISSING_EXTERNAL_PACKAGES()!" 201 ) 202 ENDFOREACH() 203ENDFUNCTION() 204 205 206# 207# Below, we change the value of user cache values like 208# ${PROJECT_NAME}_ENABLE_${PACKAGE_NAME}, 209# ${PACKAGE_NAME}_ENABLE_TESTS, and ${PACKAGE_NAME}_ENABLE_EXAMPLES by 210# just setting them to regular variables that live in the top scope 211# instead of putting them back in the cache. That means that they are 212# used as global variables but we don't want to disturb the cache 213# since that would change the behavior for future invocations of cmake 214# (which is very confusing). Because of this, these macros must all 215# be called from the top-level ${PROJECT_NAME} CMakeLists.txt file and 216# macros must call macros as not to change the variable scope. 217# 218# I had to do it this way in order to be able to get the right behavior which 219# is: 220# 221# 1) Override the value of these variables in all CMake processing 222# 223# 2) Avoid changing the user cache values because that would be confusing and 224# would make it hard to change package enables/disable later without blowing 225# away the cache 226# 227 228 229# 230# Macro that sets up standard user options a package 231# 232# On completion, the following variables are set: 233# 234# * ${PACKAGE_NAME_IN}_TESTGROUP: Set to PT, ST, or EX 235# 236 237MACRO(TRIBITS_INSERT_STANDARD_PACKAGE_OPTIONS PACKAGE_NAME_IN PACKAGE_TESTGROUP_IN) 238 239 IF (TRIBITS_INSERT_STANDARD_PACKAGE_OPTIONS_DEBUG) 240 MESSAGE("TRIBITS_INSERT_STANDARD_PACKAGE_OPTIONS: ${PACKAGE_NAME_IN} ${PACKAGE_TESTGROUP_IN}") 241 PRINT_VAR(${PACKAGE_NAME_IN}_TESTGROUP) 242 ENDIF() 243 244 SET(PACKAGE_TESTGROUP_LOCAL ${PACKAGE_TESTGROUP_IN}) 245 246 # ${PROJECT_NAME}_ELEVATE_ST_TO_PT is deprecated but allowed for backward compatibility 247 IF (${PROJECT_NAME}_ELEVATE_SS_TO_PS) 248 SET(${PROJECT_NAME}_ELEVATE_ST_TO_PT ON) 249 ENDIF() 250 251 IF (${PACKAGE_TESTGROUP_IN} STREQUAL PT OR ${PACKAGE_TESTGROUP_IN} STREQUAL ST) 252 IF (TRIBITS_INSERT_STANDARD_PACKAGE_OPTIONS_DEBUG) 253 MESSAGE("-- " "PT or ST") 254 PRINT_VAR(${PROJECT_NAME}_ELEVATE_ST_TO_PT) 255 ENDIF() 256 IF (${PROJECT_NAME}_ELEVATE_ST_TO_PT) 257 SET(PACKAGE_TESTGROUP_LOCAL PT) 258 ENDIF() 259 IF (TRIBITS_INSERT_STANDARD_PACKAGE_OPTIONS_DEBUG) 260 PRINT_VAR(PACKAGE_TESTGROUP_LOCAL) 261 ENDIF() 262 SET(PACKAGE_ENABLE "") 263 ELSEIF (${PACKAGE_TESTGROUP_IN} STREQUAL EX) 264 IF (TRIBITS_INSERT_STANDARD_PACKAGE_OPTIONS_DEBUG) 265 MESSAGE("-- " "EX") 266 ENDIF() 267 SET(PACKAGE_ENABLE OFF) 268 ELSE() 269 MESSAGE(FATAL_ERROR "Error the package classification '${PACKAGE_TESTGROUP_IN}'" 270 " for the package ${PACKAGE_NAME_IN} is not a valid classification." ) 271 ENDIF() 272 273 IF (TRIBITS_INSERT_STANDARD_PACKAGE_OPTIONS_DEBUG) 274 PRINT_VAR(PACKAGE_ENABLE) 275 PRINT_VAR(${PACKAGE_NAME_IN}_TESTGROUP) 276 ENDIF() 277 278 IF ("${${PACKAGE_NAME_IN}_TESTGROUP}" STREQUAL "") # Allow testing override 279 IF (TRIBITS_INSERT_STANDARD_PACKAGE_OPTIONS_DEBUG) 280 MESSAGE("-- " "Setting classification to ${PACKAGE_TESTGROUP_LOCAL}") 281 PRINT_VAR(PACKAGE_TESTGROUP_LOCAL) 282 ENDIF() 283 SET(${PACKAGE_NAME_IN}_TESTGROUP "${PACKAGE_TESTGROUP_LOCAL}") 284 ENDIF() 285 286 IF (TRIBITS_INSERT_STANDARD_PACKAGE_OPTIONS_DEBUG) 287 PRINT_VAR(${PACKAGE_NAME_IN}_TESTGROUP) 288 ENDIF() 289 290 MULTILINE_SET(DOCSTR 291 "Enable the package ${PACKAGE_NAME_IN}. Set to 'ON', 'OFF', or leave" 292 " empty to allow for other logic to decide." 293 ) 294 SET_CACHE_ON_OFF_EMPTY( ${PROJECT_NAME}_ENABLE_${PACKAGE_NAME_IN} 295 "${PACKAGE_ENABLE}" ${DOCSTR} ) 296 297ENDMACRO() 298 299 300# 301# Function that determines if a package is a primary meta-project package 302# according to the variables 303# ${PARENT_REPO_NAME}_NO_PRIMARY_META_PROJECT_PACKAGES[_EXCEPT]. 304# 305 306FUNCTION(TRIBITS_IS_PRIMARY_META_PROJECT_PACKAGE PACKAGE_NAME_IN 307 IS_PRIMARY_META_PROJECT_PACKAGE_OUT 308 ) 309 310 SET(IS_PRIMARY_META_PROJECT_PACKAGE TRUE) 311 312 ASSERT_DEFINED(${PACKAGE_NAME_IN}_PARENT_REPOSITORY) 313 SET(PARENT_REPO_NAME ${${PACKAGE_NAME_IN}_PARENT_REPOSITORY}) 314 IF (${PARENT_REPO_NAME}_NO_PRIMARY_META_PROJECT_PACKAGES) 315 FIND_LIST_ELEMENT( 316 ${PARENT_REPO_NAME}_NO_PRIMARY_META_PROJECT_PACKAGES_EXCEPT 317 ${PACKAGE_NAME_IN} PACKAGE_EXCEPTED 318 ) 319 IF (PACKAGE_EXCEPTED) 320 IF (${PROJECT_NAME}_VERBOSE_CONFIGURE) 321 MESSAGE("-- " 322 "NOTE: ${PACKAGE_NAME_IN} is classified as a primary meta-project packages even" 323 " though ${PARENT_REPO_NAME}_NO_PRIMARY_META_PROJECT_PACKAGES=ON " 324 " because the package is included in the list ${PARENT_REPO_NAME}_NO_PRIMARY_META_PROJECT_PACKAGES_EXCEPT!") 325 ENDIF() 326 ELSE() 327 IF (${PROJECT_NAME}_VERBOSE_CONFIGURE) 328 MESSAGE("-- " 329 "NOTE: ${PACKAGE_NAME_IN} is not as a primary meta-project packages" 330 " because ${PARENT_REPO_NAME}_NO_PRIMARY_META_PROJECT_PACKAGES=ON " 331 ) 332 ENDIF() 333 SET(IS_PRIMARY_META_PROJECT_PACKAGE FALSE) 334 ENDIF() 335 ENDIF() 336 337 SET(${IS_PRIMARY_META_PROJECT_PACKAGE_OUT} ${IS_PRIMARY_META_PROJECT_PACKAGE} 338 PARENT_SCOPE ) 339 340ENDFUNCTION() 341 342 343# 344# Function that determines if it is okay to allow an implicit package enable 345# based on its classification. 346# 347 348FUNCTION(TRIBITS_IMPLICIT_PACKAGE_ENABLE_IS_ALLOWED UPSTREAM_PACKAGE_NAME_IN PACKAGE_NAME_IN 349 IMPLICIT_PACKAGE_ENABLE_ALLOWED_OUT 350 ) 351 352 IF (${PACKAGE_NAME_IN}_TESTGROUP STREQUAL PT) 353 SET(IMPLICIT_PACKAGE_ENABLE_ALLOWED TRUE) 354 ELSEIF (${PACKAGE_NAME_IN}_TESTGROUP STREQUAL ST 355 AND ${PROJECT_NAME}_ENABLE_SECONDARY_TESTED_CODE 356 ) 357 SET(IMPLICIT_PACKAGE_ENABLE_ALLOWED TRUE) 358 ELSE() 359 IF (UPSTREAM_PACKAGE_NAME_IN) 360 MESSAGE("-- " "NOTE: Not Setting ${PROJECT_NAME}_ENABLE_${PACKAGE_NAME_IN}=ON" 361 " even though ${UPSTREAM_PACKAGE_NAME_IN} has an optional dependence on" 362 " ${PACKAGE_NAME_IN} because ${PROJECT_NAME}_ENABLE_SECONDARY_TESTED_CODE=OFF" ) 363 ENDIF() 364 SET(IMPLICIT_PACKAGE_ENABLE_ALLOWED FALSE) 365 ENDIF() 366 367 SET(${IMPLICIT_PACKAGE_ENABLE_ALLOWED_OUT} ${IMPLICIT_PACKAGE_ENABLE_ALLOWED} 368 PARENT_SCOPE ) 369 370ENDFUNCTION() 371 372 373# 374# Macro that processes ${REPOSITORY_NAME}_PACKAGES_AND_DIRS_AND_CLASSIFICATIONS into 375# ${PROJECT_NAME}_PACKAGES, ${PROJECT_NAME}_PACKAGE_DIRS, ${PROJECT_NAME}_NUM_PACKAGES, 376# ${PROJECT_NAME}_LAST_PACKAGE_IDX, and ${PROJECT_NAME}_REVERSE_PACKAGES. 377# 378# This macro also sets up the standard package options along with 379# default enables/disables. 380# 381# NOTE: Set TRIBITS_PROCESS_PACKAGES_AND_DIRS_LISTS_VERBOSE=TRUE to see really verbose 382# debug ouptut from this macro. 383# 384 385MACRO(TRIBITS_PROCESS_PACKAGES_AND_DIRS_LISTS REPOSITORY_NAME REPOSITORY_DIR) 386 387 IF (${PROJECT_NAME}_VERBOSE_CONFIGURE) 388 MESSAGE("TRIBITS_PROCESS_PACKAGES_AND_DIRS_LISTS: '${REPOSITORY_NAME}' '${REPOSITORY_DIR}'") 389 ENDIF() 390 391 # 392 # Separate out separate lists of package names and directories 393 # 394 395 # Get the total number of packages defined 396 397 ASSERT_DEFINED(${REPOSITORY_NAME}_PACKAGES_AND_DIRS_AND_CLASSIFICATIONS) 398 IF (TRIBITS_PROCESS_PACKAGES_AND_DIRS_LISTS_VERBOSE) 399 PRINT_VAR(${REPOSITORY_NAME}_PACKAGES_AND_DIRS_AND_CLASSIFICATIONS) 400 ENDIF() 401 LIST(LENGTH ${REPOSITORY_NAME}_PACKAGES_AND_DIRS_AND_CLASSIFICATIONS 402 ${REPOSITORY_NAME}_NUM_PACKAGES_AND_FIELDS ) 403 MATH(EXPR ${REPOSITORY_NAME}_NUM_PACKAGES 404 "${${REPOSITORY_NAME}_NUM_PACKAGES_AND_FIELDS}/${PLH_NUM_FIELDS_PER_PACKAGE}") 405 IF (TRIBITS_PROCESS_PACKAGES_AND_DIRS_LISTS_VERBOSE) 406 PRINT_VAR(${REPOSITORY_NAME}_NUM_PACKAGES) 407 ENDIF() 408 MATH(EXPR ${REPOSITORY_NAME}_LAST_PACKAGE_IDX "${${REPOSITORY_NAME}_NUM_PACKAGES}-1") 409 410 # Process each of the packages defined 411 412 IF (${REPOSITORY_NAME}_NUM_PACKAGES GREATER 0) 413 414 FOREACH(PACKAGE_IDX RANGE ${${REPOSITORY_NAME}_LAST_PACKAGE_IDX}) 415 416 IF (TRIBITS_PROCESS_PACKAGES_AND_DIRS_LISTS_VERBOSE) 417 MESSAGE("") 418 PRINT_VAR(${PROJECT_NAME}_PACKAGES) 419 ENDIF() 420 421 MATH(EXPR PACKAGE_NAME_IDX "${PACKAGE_IDX}*${PLH_NUM_FIELDS_PER_PACKAGE}+0") 422 LIST(GET ${REPOSITORY_NAME}_PACKAGES_AND_DIRS_AND_CLASSIFICATIONS 423 ${PACKAGE_NAME_IDX} TRIBITS_PACKAGE ) 424 IF (TRIBITS_PROCESS_PACKAGES_AND_DIRS_LISTS_VERBOSE) 425 PRINT_VAR(TRIBITS_PACKAGE) 426 ENDIF() 427 428 MATH(EXPR PACKAGE_DIR_IDX 429 "${PACKAGE_IDX}*${PLH_NUM_FIELDS_PER_PACKAGE}+${PLH_NUM_PACKAGE_DIR_OFFSET}") 430 LIST(GET ${REPOSITORY_NAME}_PACKAGES_AND_DIRS_AND_CLASSIFICATIONS 431 ${PACKAGE_DIR_IDX} PACKAGE_DIR ) 432 IF (TRIBITS_PROCESS_PACKAGES_AND_DIRS_LISTS_VERBOSE) 433 PRINT_VAR(PACKAGE_DIR) 434 ENDIF() 435 436 MATH(EXPR PACKAGE_CLASSIFICATION_IDX 437 "${PACKAGE_IDX}*${PLH_NUM_FIELDS_PER_PACKAGE}+${PLH_NUM_PACKAGE_CLASSIFICATION_OFFSET}") 438 LIST(GET ${REPOSITORY_NAME}_PACKAGES_AND_DIRS_AND_CLASSIFICATIONS 439 ${PACKAGE_CLASSIFICATION_IDX} PACKAGE_CLASSIFICATION ) 440 IF (TRIBITS_PROCESS_PACKAGES_AND_DIRS_LISTS_VERBOSE) 441 PRINT_VAR(PACKAGE_CLASSIFICATION) 442 ENDIF() 443 444 # ToDo: Parse out TESTGROUP and MATURITYLEVEL (Trilinos #6042) 445 SET(PACKAGE_TESTGROUP ${PACKAGE_CLASSIFICATION}) 446 447 TRIBITS_UPDATE_PS_PT_SS_ST(Package ${TRIBITS_PACKAGE} PACKAGE_TESTGROUP) 448 449 IF (${TRIBITS_PACKAGE}_SOURCE_DIR_OVERRIDE) 450 MESSAGE("-- " 451 "NOTE: ${TRIBITS_PACKAGE}_SOURCE_DIR_OVERRIDE='${${TRIBITS_PACKAGE}_SOURCE_DIR_OVERRIDE}'" 452 " is overriding default path '${PACKAGE_DIR}'") 453 SET(PACKAGE_DIR "${${TRIBITS_PACKAGE}_SOURCE_DIR_OVERRIDE}") 454 ENDIF() 455 456 IF (IS_ABSOLUTE "${PACKAGE_DIR}") 457 458 SET(PACKAGE_ABS_DIR "${PACKAGE_DIR}") 459 460 STRING(LENGTH "${PROJECT_SOURCE_DIR}" PROJECT_SOURCE_DIR_LEN) 461 STRING(LENGTH "${PACKAGE_ABS_DIR}" PACKAGE_ABS_DIR_LEN) 462 463 # See if the package dir is under the project dir 464 465 SET(PACKAGE_ABS_DIR_UNDER_PROJECT_SOURCE_DIR TRUE) 466 467 IF (PACKAGE_ABS_DIR_UNDER_PROJECT_SOURCE_DIR) 468 # Determine package abs dir is too short to be under project 469 IF (PACKAGE_ABS_DIR_LEN LESS PROJECT_SOURCE_DIR_LEN) 470 SET(PACKAGE_ABS_DIR_UNDER_PROJECT_SOURCE_DIR FALSE) 471 ENDIF() 472 ENDIF() 473 474 IF (PACKAGE_ABS_DIR_UNDER_PROJECT_SOURCE_DIR) 475 # Determine if the package abs base dir base is the project dir 476 STRING(SUBSTRING "${PACKAGE_ABS_DIR}" 0 ${PROJECT_SOURCE_DIR_LEN} 477 PROJECT_SOURCE_DIR_BASE_MATCH) 478 PRINT_VAR(PROJECT_SOURCE_DIR_BASE_MATCH) 479 IF (NOT PROJECT_SOURCE_DIR_BASE_MATCH STREQUAL "${PROJECT_SOURCE_DIR}") 480 SET(PACKAGE_ABS_DIR_UNDER_PROJECT_SOURCE_DIR FALSE) 481 ENDIF() 482 ENDIF() 483 484 IF (PACKAGE_ABS_DIR_UNDER_PROJECT_SOURCE_DIR) 485 # Get the path of the package dir under the project dir 486 MATH(EXPR PACKAGE_REL_DIR_BEGIN "${PROJECT_SOURCE_DIR_LEN}+1") 487 STRING(SUBSTRING "${PACKAGE_ABS_DIR}" ${PACKAGE_REL_DIR_BEGIN} -1 488 REPOSITORY_AND_PACKAGE_DIR) 489 ELSE() 490 MESSAGE_WRAPPER(FATAL_ERROR 491 "Error: The pacakge '${TRIBITS_PACKAGE}' was given an absolute directory '${PACKAGE_ABS_DIR}' which is *not* under the project's source directory '${PROJECT_SOURCE_DIR}/'!") 492 SET(REPOSITORY_AND_PACKAGE_DIR "ERROR-BAD-PACKAGE-ABS-DIR") 493 # ToDo: We could just put in a relative path but that requries 494 # knowing the common path between the two directory paths but CMake 495 # does not give an easy way to determine that. I would have to 496 # write that function myself. 497 ENDIF() 498 499 ELSE() 500 501 # PACKAGE_DIR is a relative path 502 503 IF ("${REPOSITORY_DIR}" STREQUAL ".") 504 SET(REPOSITORY_AND_PACKAGE_DIR "${PACKAGE_DIR}") 505 ELSEIF("${PACKAGE_DIR}" STREQUAL ".") 506 SET(REPOSITORY_AND_PACKAGE_DIR "${REPOSITORY_DIR}") 507 ELSE() 508 SET(REPOSITORY_AND_PACKAGE_DIR "${REPOSITORY_DIR}/${PACKAGE_DIR}") 509 ENDIF() 510 SET(PACKAGE_ABS_DIR "${PROJECT_SOURCE_DIR}/${REPOSITORY_AND_PACKAGE_DIR}") 511 512 ENDIF() 513 514 IF (EXISTS ${PACKAGE_ABS_DIR}) 515 SET(PACKAGE_EXISTS TRUE) 516 ELSE() 517 SET(PACKAGE_EXISTS FALSE) 518 ENDIF() 519 520 IF (TRIBITS_PROCESS_PACKAGES_AND_DIRS_LISTS_VERBOSE) 521 PRINT_VAR(PROJECT_SOURCE_DIR) 522 PRINT_VAR(REPOSITORY_AND_PACKAGE_DIR) 523 PRINT_VAR(PACKAGE_ABS_DIR) 524 PRINT_VAR(PACKAGE_EXISTS) 525 PRINT_VAR(${PROJECT_NAME}_ASSERT_MISSING_PACKAGES) 526 PRINT_VAR(${TRIBITS_PACKAGE}_ALLOW_MISSING_EXTERNAL_PACKAGE) 527 ENDIF() 528 529 IF (${PROJECT_NAME}_ASSERT_MISSING_PACKAGES 530 AND NOT PACKAGE_EXISTS 531 AND NOT ${TRIBITS_PACKAGE}_ALLOW_MISSING_EXTERNAL_PACKAGE 532 ) 533 MESSAGE( 534 "\n***" 535 "\n*** Error, the package ${TRIBITS_PACKAGE} directory ${PACKAGE_ABS_DIR} does not exist!" 536 "\n***\n" ) 537 MESSAGE(FATAL_ERROR "Stopping due to above error!") 538 ENDIF() 539 540 IF (PACKAGE_EXISTS OR ${PROJECT_NAME}_IGNORE_PACKAGE_EXISTS_CHECK) 541 LIST(APPEND ${PROJECT_NAME}_PACKAGES ${TRIBITS_PACKAGE}) 542 LIST(APPEND ${PROJECT_NAME}_PACKAGE_DIRS "${REPOSITORY_AND_PACKAGE_DIR}") 543 TRIBITS_INSERT_STANDARD_PACKAGE_OPTIONS(${TRIBITS_PACKAGE} ${PACKAGE_TESTGROUP}) 544 SET(${TRIBITS_PACKAGE}_SOURCE_DIR "${PROJECT_SOURCE_DIR}/${REPOSITORY_AND_PACKAGE_DIR}") 545 SET(${TRIBITS_PACKAGE}_PARENT_PACKAGE "") 546 SET(${TRIBITS_PACKAGE}_PARENT_REPOSITORY ${REPOSITORY_NAME}) 547 ELSE() 548 IF (${PROJECT_NAME}_VERBOSE_CONFIGURE) 549 MESSAGE( 550 "\n***" 551 "\n*** NOTE: Excluding package ${TRIBITS_PACKAGE} because ${PACKAGE_ABS_DIR}" 552 " does not exist!" 553 "\n***\n" ) 554 ENDIF() 555 ENDIF() 556 # NOTE: The variable ${PROJECT_NAME}_IGNORE_PACKAGE_EXISTS_CHECK only 557 # gets set to TRUE for some unit tests. Otherwise, in every legitimate 558 # usage of this macro it is always FALSE. 559 560 IF (TRIBITS_PROCESS_PACKAGES_AND_DIRS_LISTS_VERBOSE) 561 PRINT_VAR(${TRIBITS_PACKAGE}_SOURCE_DIR) 562 PRINT_VAR(${TRIBITS_PACKAGE}_PARENT_PACKAGE) 563 PRINT_VAR(${TRIBITS_PACKAGE}_PARENT_REPOSITORY) 564 ENDIF() 565 566 IF (TRIBITS_PROCESS_PACKAGES_AND_DIRS_LISTS_VERBOSE) 567 PRINT_VAR(${PROJECT_NAME}_PACKAGES) 568 ENDIF() 569 570 ENDFOREACH() 571 572 # Get the actual number of packages that actually exist 573 574 LIST(LENGTH ${PROJECT_NAME}_PACKAGES ${PROJECT_NAME}_NUM_PACKAGES ) 575 MATH(EXPR ${PROJECT_NAME}_LAST_PACKAGE_IDX "${${PROJECT_NAME}_NUM_PACKAGES}-1") 576 577 # Create a reverse list for later use 578 579 SET(${PROJECT_NAME}_REVERSE_PACKAGES ${${PROJECT_NAME}_PACKAGES}) 580 LIST(REVERSE ${PROJECT_NAME}_REVERSE_PACKAGES) 581 582 ELSE() 583 584 SET(${REPOSITORY_NAME}_NUM_PACKAGES 0) 585 586 ENDIF() 587 588 IF (${PROJECT_NAME}_VERBOSE_CONFIGURE) 589 PRINT_VAR(${REPOSITORY_NAME}_NUM_PACKAGES) 590 ENDIF() 591 592 PRINT_VAR(${PROJECT_NAME}_NUM_PACKAGES) 593 594 # Print the final set of packages in debug mode 595 596 IF (${PROJECT_NAME}_VERBOSE_CONFIGURE) 597 PRINT_VAR(${PROJECT_NAME}_PACKAGES) 598 PRINT_VAR(${PROJECT_NAME}_PACKAGE_DIRS) 599 ENDIF() 600 601ENDMACRO() 602