diff --git a/Build/AtlasCMake/modules/AtlasFunctions.cmake b/Build/AtlasCMake/modules/AtlasFunctions.cmake index 5a53feee7eabe89244d9a900275a2542d11cac9d..0bd98dcb47c16ffb9ad094968be5121b4906a99e 100644 --- a/Build/AtlasCMake/modules/AtlasFunctions.cmake +++ b/Build/AtlasCMake/modules/AtlasFunctions.cmake @@ -1,7 +1,5 @@ -# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 1995-2017 CERN for the benefit of the ATLAS collaboration -# $Id: AtlasFunctions.cmake 760944 2016-07-11 09:03:46Z krasznaa $ -# # This is the main file that needs to be included in order to get access to the # ATLAS CMake functions. # @@ -55,7 +53,8 @@ include( AtlasCompilerSettings ) function( atlas_project name version ) # Parse all options: - cmake_parse_arguments( ARG "RELEASE_RECOMPILE;FORTRAN" "" "USE" ${ARGN} ) + cmake_parse_arguments( ARG "RELEASE_RECOMPILE;FORTRAN" "PROJECT_ROOT" "USE" + ${ARGN} ) # Tell the user what's happening: message( STATUS "Configuring ATLAS project with name " @@ -92,8 +91,8 @@ function( atlas_project name version ) # Do not consider header files that are outside of the project's source # and binary directory in the dependency tree of the source files. - set( CMAKE_DEPENDS_IN_PROJECT_ONLY ON ) - set( CMAKE_DEPENDS_IN_PROJECT_ONLY ON PARENT_SCOPE ) + #set( CMAKE_DEPENDS_IN_PROJECT_ONLY ON ) + #set( CMAKE_DEPENDS_IN_PROJECT_ONLY ON PARENT_SCOPE ) # Decide about the languages used in the project: set( _languages CXX C ) @@ -288,12 +287,32 @@ function( atlas_project name version ) unset( _thisFile ) unset( _thisDir ) + # Set up the "atlas_tests" target. One that all of the unit test builds + # will depend on. This target will either be built by default or not based + # on the value of the ATLAS_ALWAYS_BUILD_TESTS configuration option. + option( ATLAS_ALWAYS_BUILD_TESTS + "Make unit test building part of the default build target" ON ) + if( ATLAS_ALWAYS_BUILD_TESTS ) + message( STATUS "Unit tests will be built by default" ) + add_custom_target( atlas_tests ALL ) + else() + message( STATUS "Unit tests will *NOT* be built by default" ) + message( STATUS "Use the 'atlas_tests' build target to build the tests" ) + add_custom_target( atlas_tests ) + endif() + set_property( TARGET atlas_tests PROPERTY FOLDER ${name} ) + # Find the packages in the current working directory: set( _packageDirs ) - file( GLOB_RECURSE cmakelist_files RELATIVE ${CMAKE_SOURCE_DIR} - CMakeLists.txt ) + if( ARG_PROJECT_ROOT ) + file( GLOB_RECURSE cmakelist_files RELATIVE ${CMAKE_SOURCE_DIR} + ${ARG_PROJECT_ROOT}/CMakeLists.txt ) + else() + file( GLOB_RECURSE cmakelist_files RELATIVE ${CMAKE_SOURCE_DIR} + CMakeLists.txt ) + endif() foreach( file ${cmakelist_files} ) - # Ignore the top level file itself: + # Ignore the CMakeLists.txt file calling this function: if( NOT file STREQUAL CMakeLists.txt ) get_filename_component( package ${file} PATH ) list( APPEND _packageDirs ${package} ) @@ -358,16 +377,36 @@ function( atlas_project name version ) # Include the packages: set( _counter 0 ) + set( _selectedPackages 0 ) + set( _selectedPackageNames ) foreach( _pkgDir ${_packageDirs} ) + # Construct a binary directory name: + set( _binDir ${_pkgDir} ) + if( ARG_PROJECT_ROOT ) + file( RELATIVE_PATH _binDir ${ARG_PROJECT_ROOT} + ${CMAKE_CURRENT_SOURCE_DIR}/${_pkgDir} ) + endif() + # Update the counter: math( EXPR _doNotPrint "${_counter} % 10" ) math( EXPR _counter "${_counter} + 1" ) if( NOT _doNotPrint ) - message( STATUS "Configuring package ${_counter} / ${_nPackageDirs}" ) + message( STATUS "Considering package ${_counter} / ${_nPackageDirs}" ) + endif() + # Check if this package should be set up: + atlas_is_package_selected( ${_binDir} _isSelected ) + if( NOT "${_isSelected}" ) + continue() endif() - add_subdirectory( ${_pkgDir} ) + add_subdirectory( ${_pkgDir} ${_binDir} ) + list( APPEND _selectedPackageNames ${_binDir} ) + math( EXPR _selectedPackages "${_selectedPackages} + 1" ) + unset( _binDir ) endforeach() + message( STATUS "Number of packages configured: ${_selectedPackages}" ) unset( _counter ) unset( _doNotPrint ) + unset( _isSelected ) + unset( _selectedPackages ) # Find the releases' packages again, this time setting each of them up: if( ARG_USE ) @@ -471,22 +510,13 @@ function( atlas_project name version ) file( WRITE ${_packagesFileName} "# Regular package(s) built in ${CMAKE_PROJECT_NAME} - " "${CMAKE_PROJECT_VERSION}\n" ) - foreach( _pkgDir ${_packageDirs} ) - # Get the version of the package: + foreach( _pkgDir ${_selectedPackageNames} ) + # The package version is no longer defined... set( _version "<unknown>" ) - if( EXISTS "${CMAKE_SOURCE_DIR}/${_pkgDir}/version.cmake" ) - file( READ "${CMAKE_SOURCE_DIR}/${_pkgDir}/version.cmake" - _version LIMIT 10000 ) - string( STRIP ${_version} _version ) - elseif( EXISTS "${CMAKE_SOURCE_DIR}/${_pkgDir}/cmt/version.cmt" ) - # For backwards compatibility: - file( READ "${CMAKE_SOURCE_DIR}/${_pkgDir}/cmt/version.cmt" - _version LIMIT 10000 ) - string( STRIP ${_version} _version ) - endif() # Add a line into the file: file( APPEND ${_packagesFileName} "${_pkgDir} ${_version}\n" ) endforeach() + unset( _selectedPackageNames ) # Add some possible special packages to the file: get_property( _specialPackagesSet GLOBAL PROPERTY ATLAS_SPECIAL_PACKAGES SET ) @@ -671,6 +701,28 @@ function( atlas_project name version ) mark_as_advanced( _ctestCustom ) unset( _ctestCustom ) + # On MacOS X copy the system's default BASH executable into the build + # directory, and use it from there. To get around the issue with Apple's + # system protection against passing some environment variables to certain + # applications. + + # Find bash: + find_program( _bash_executable bash ) + if( NOT _bash_executable ) + message( WARNING "BASH not found. The build will fail." ) + endif() + + if( APPLE ) + # Copy bash into the build directory: + file( COPY "${_bash_executable}" + DESTINATION "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" ) + # And now set BASH_EXECUTABLE to point at this private copy: + set( BASH_EXECUTABLE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/bash" ) + else() + # Just take bash from its normal location: + set( BASH_EXECUTABLE "${_bash_executable}" ) + endif() + # Set up a script that can be used during the build to run executables # in a "full runtime environment": find_file( _buildRun atlas_build_run.sh.in @@ -909,7 +961,7 @@ macro( atlas_subdir name ) # Check if a package with this name was already declared: if( TARGET ${name}Pkg OR TARGET ${name}PkgPrivate OR - TARGET Package_${name} ) + TARGET Package_${name} OR TARGET Package_${name}_tests ) message( WARNING "Package ${name} is already declared." ) else() @@ -965,6 +1017,13 @@ macro( atlas_subdir name ) atlas_get_package_dir( pkgDir ) set_property( TARGET Package_${name} PROPERTY FOLDER ${pkgDir} ) + # Create a "tests target" for the package: + add_custom_target( Package_${name}_tests + COMMAND ${CMAKE_COMMAND} -E echo + "${name}: Package build succeeded" ) + add_dependencies( atlas_tests Package_${name}_tests ) + set_property( TARGET Package_${name}_tests PROPERTY FOLDER ${pkgDir} ) + # Set up the installation of the source files from the package: install( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${CMAKE_INSTALL_SRCDIR}/${pkgDir} @@ -1283,6 +1342,7 @@ function( atlas_add_executable exeName ) if( NOT TARGET ${exeName}ExeAttribSet ) add_custom_target( ${exeName}ExeAttribSet ALL COMMAND chmod 755 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${exeName}.exe ) + add_dependencies( Package_${pkgName} ${exeName}ExeAttribSet ) set_property( TARGET ${exeName}ExeAttribSet PROPERTY LABELS ${pkgName} ) set_property( TARGET ${exeName}ExeAttribSet PROPERTY FOLDER @@ -1392,11 +1452,11 @@ function( atlas_add_test testName ) endif() # Declare the executable: - add_executable( ${pkgName}_${testName} ${_sources} ) + add_executable( ${pkgName}_${testName} EXCLUDE_FROM_ALL ${_sources} ) # Set it's properties: add_dependencies( ${pkgName}_${testName} ${pkgName}Pkg ) - add_dependencies( Package_${pkgName} ${pkgName}_${testName} ) + add_dependencies( Package_${pkgName}_tests ${pkgName}_${testName} ) set_property( TARGET ${pkgName}_${testName} PROPERTY LABELS ${pkgName} ) set_property( TARGET ${pkgName}_${testName} PROPERTY FOLDER ${pkgDir} ) set_property( TARGET ${pkgName}_${testName} PROPERTY @@ -1421,9 +1481,10 @@ function( atlas_add_test testName ) # Create the test script installation target of the package if it # doesn't exist yet: if( NOT TARGET ${pkgName}TestScriptInstall ) - add_custom_target( ${pkgName}TestScriptInstall ALL SOURCES + add_custom_target( ${pkgName}TestScriptInstall SOURCES $<TARGET_PROPERTY:${pkgName}TestScriptInstall,TEST_SCRIPTS> ) - add_dependencies( Package_${pkgName} ${pkgName}TestScriptInstall ) + add_dependencies( Package_${pkgName}_tests + ${pkgName}TestScriptInstall ) set_property( TARGET ${pkgName}TestScriptInstall PROPERTY LABELS ${pkgName} ) set_property( TARGET ${pkgName}TestScriptInstall @@ -1472,6 +1533,15 @@ function( atlas_add_test testName ) fi" ) endif() + # Decide where to take bash from: + if( APPLE ) + # atlas_project(...) should take care of putting it here: + set( BASH_EXECUTABLE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/bash" ) + else() + # Just take it from its default location: + find_program( BASH_EXECUTABLE bash ) + endif() + # Generate a test script that will run this unit test in the # correct environment: find_file( _utSkeleton unit_test_executor.sh.in diff --git a/Build/AtlasCMake/modules/AtlasInternals.cmake b/Build/AtlasCMake/modules/AtlasInternals.cmake index 97b82a290788fe0f228547c3151f03d5d5f736ad..abf9e8509d13eaadfe5c5715d52a982c0eb52efd 100644 --- a/Build/AtlasCMake/modules/AtlasInternals.cmake +++ b/Build/AtlasCMake/modules/AtlasInternals.cmake @@ -1,7 +1,5 @@ -# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 1995-2017 CERN for the benefit of the ATLAS collaboration -# $Id: AtlasInternals.cmake 755445 2016-06-16 15:09:56Z krasznaa $ -# # Functions used internally by functions declared in AtlasFunctions. # Which are for general use inside the package descriptions. @@ -50,10 +48,10 @@ endfunction( atlas_get_package_name ) # function( atlas_get_package_dir dir ) - # Just remove the prefix of the source directory of the current - # package's source directory, and that's it... - string( REPLACE "${CMAKE_SOURCE_DIR}/" "" _packageDir - ${CMAKE_CURRENT_SOURCE_DIR} ) + # Just remove the prefix of the binary directory of the current + # package's binary directory, and that's it... + string( REPLACE "${CMAKE_BINARY_DIR}/" "" _packageDir + ${CMAKE_CURRENT_BINARY_DIR} ) # Return the string: set( ${dir} ${_packageDir} PARENT_SCOPE ) @@ -440,6 +438,17 @@ macro( atlas_ctest_setup ) set_property( GLOBAL PROPERTY ATLAS_CTEST_CONFIGURED TRUE ) if( NOT _ctestConfigured ) + # Decide where to take bash from: + if( APPLE ) + # atlas_project(...) should take care of putting it here: + atlas_platform_id( _platform ) + set( BASH_EXECUTABLE "${CMAKE_BINARY_DIR}/${_platform}/bin/bash" ) + unset( _platform ) + else() + # Just take it from its default location: + find_program( BASH_EXECUTABLE bash ) + endif() + # Only do anything fancy if we are in CTEST_USE_LAUNCHERS mode: if( CTEST_USE_LAUNCHERS ) # Find the atlas_ctest.sh.in script skeleton: @@ -505,6 +514,15 @@ macro( atlas_cpack_setup ) # Taken from ROOT. Not clear whether we need it... #include( InstallRequiredSystemLibraries ) + # Decide where to take bash from: + if( APPLE ) + # atlas_project(...) should take care of putting it here: + set( BASH_EXECUTABLE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/bash" ) + else() + # Just take it from its default location: + find_program( BASH_EXECUTABLE bash ) + endif() + # Set some variables, constructed from variables set originally for CMake # itself: if( CMAKE_PROJECT_NAME AND CMAKE_PROJECT_VERSION ) @@ -947,3 +965,88 @@ endfunction( atlas_merge_project_files ) # Delete the private macro: unset( _merge_files ) + +# Function filtering which packages from the repository should be used in a +# particular build setup. +# +# Usage: atlas_is_package_selected( ${pkgDir} isSelected ) +# +function( atlas_is_package_selected dirName returnName ) + + # Check if the configuration file was already read in: + if( NOT DEFINED ATLAS_PACKAGE_FILTERS ) + # The default location of the filter: + set( ATLAS_PACKAGE_FILTER_FILE "${CMAKE_SOURCE_DIR}/package_filters.txt" + CACHE FILEPATH "File describing the package filtering rules" ) + # Check if the file exists: + if( EXISTS "${ATLAS_PACKAGE_FILTER_FILE}" ) + # Intermediate list with the rules read: + set( _filters ) + # Read in the file: + file( STRINGS ${ATLAS_PACKAGE_FILTER_FILE} _fileContents ) + # Process all lines: + foreach( _line ${_fileContents} ) + # Strip the line: + string( STRIP "${_line}" _line ) + # Skip empty or comment lines: + if( "${_line}" STREQUAL "" OR + "${_line}" MATCHES " *#.*" ) + continue() + endif() + # Now interpret this line: + if( "${_line}" MATCHES "^([\+-]) *([^ ]*)" ) + list( APPEND _filters ${CMAKE_MATCH_1} ${CMAKE_MATCH_2} ) + else() + message( WARNING "Line \"${_line}\" not understood" ) + endif() + endforeach() + # Remember the selection rules: + set( ATLAS_PACKAGE_FILTERS "${_filters}" + CACHE INTERNAL "Package filtering rules" FORCE ) + # Print the rules that were read: + message( STATUS "Package filtering rules read:" ) + while( _filters ) + list( GET _filters 0 _ruleCommand ) + list( GET _filters 1 _rulePath ) + list( REMOVE_AT _filters 0 1 ) + message( STATUS " ${_ruleCommand} ${_rulePath}" ) + unset( _ruleCommand ) + unset( _rulePath ) + endwhile() + # Clean up: + unset( _filters ) + unset( _fileContents ) + else() + # Set an empty ruleset: + set( ATLAS_PACKAGE_FILTERS "" + CACHE INTERNAL "Package filtering rules" FORCE ) + message( STATUS "No package filtering rules read" ) + endif() + endif() + + # Loop over the rules: + set( _rulesCopy ${ATLAS_PACKAGE_FILTERS} ) + while( _rulesCopy ) + # Extract the rule from the list: + list( GET _rulesCopy 0 _ruleCommand ) + list( GET _rulesCopy 1 _rulePath ) + list( REMOVE_AT _rulesCopy 0 1 ) + # Check if the rule applies to the directory passed to the function: + if( "${dirName}" MATCHES "^${_rulePath}.*" ) + # Now decide what to do: + if( "${_ruleCommand}" STREQUAL "+" ) + set( ${returnName} TRUE PARENT_SCOPE ) + return() + elseif( "${_ruleCommand}" STREQUAL "-" ) + set( ${returnName} FALSE PARENT_SCOPE ) + return() + else() + message( SEND_ERROR "Internal coding error detected" ) + endif() + endif() + endwhile() + + # If no rule was found for the package, then it is selected: + set( ${returnName} TRUE PARENT_SCOPE ) + +endfunction( atlas_is_package_selected )