From fca1f29ee141325494b513bab852fa484b036ed8 Mon Sep 17 00:00:00 2001 From: Christian Gumpert <christian.gumpert@cern.ch> Date: Fri, 3 Feb 2017 14:15:51 +0100 Subject: [PATCH] Merge branch '21.0-buildfixes' into '21.0' Take CMake modules functions that build from git properly Note that this is a temporary fix, pending the switch to storing the ATLAS CMake helpers in the AtlasExternals repository (which @akraszna is doing) However, it should be accepted quite urgently as at the moment the cmake step on the 21.0 branch fails, so no builds are possible. See merge request !163 Former-commit-id: 2b6ec44c24cb1a63920b018bf735f6a461cea792 --- Build/AtlasCMake/modules/AtlasFunctions.cmake | 126 ++++++++++++++---- Build/AtlasCMake/modules/AtlasInternals.cmake | 117 +++++++++++++++- 2 files changed, 208 insertions(+), 35 deletions(-) diff --git a/Build/AtlasCMake/modules/AtlasFunctions.cmake b/Build/AtlasCMake/modules/AtlasFunctions.cmake index 5a53feee7ea..0bd98dcb47c 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 97b82a29078..abf9e8509d1 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 ) -- GitLab