diff options
30 files changed, 531 insertions, 372 deletions
diff --git a/Help/command/FIND_XXX.txt b/Help/command/FIND_XXX.txt index 48a1a71..38c231a 100644 --- a/Help/command/FIND_XXX.txt +++ b/Help/command/FIND_XXX.txt @@ -62,8 +62,11 @@ added to the search. If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows: .. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR| replace:: - |prefix_XXX_SUBDIR| for each ``<prefix>`` in ``PackageName_ROOT`` if called - from within a find module + |prefix_XXX_SUBDIR| for each ``<prefix>`` in the + :variable:`<PackageName>_ROOT` CMake variable and the + :envvar:`<PackageName>_ROOT` environment variable if + called from within a find module loaded by + :command:`find_package(<PackageName>)` .. |CMAKE_PREFIX_PATH_XXX_SUBDIR| replace:: |prefix_XXX_SUBDIR| for each ``<prefix>`` in :variable:`CMAKE_PREFIX_PATH` @@ -76,13 +79,16 @@ If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows: |prefix_XXX_SUBDIR| for each ``<prefix>`` in :variable:`CMAKE_SYSTEM_PREFIX_PATH` -1. If called from within a find module, search prefix paths unique to the - current package being found. Specifically look in the ``PackageName_ROOT`` - CMake and environment variables. The package root variables are maintained - as a stack so if called from nested find modules, root paths from the - parent's find module will be searched after paths from the current module, - i.e. ``CurrentPackage_ROOT``, ``ENV{CurrentPackage_ROOT}``, - ``ParentPackage_ROOT``, ``ENV{ParentPackage_ROOT}``, etc. +1. If called from within a find module loaded by + :command:`find_package(<PackageName>)`, search prefixes unique to the + current package being found. Specifically look in the + :variable:`<PackageName>_ROOT` CMake variable and the + :envvar:`<PackageName>_ROOT` environment variable. + The package root variables are maintained as a stack so if called from + nested find modules, root paths from the parent's find module will be + searched after paths from the current module, + i.e. ``<CurrentPackage>_ROOT``, ``ENV{<CurrentPackage>_ROOT}``, + ``<ParentPackage>_ROOT``, ``ENV{<ParentPackage>_ROOT}``, etc. This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed. See policy :policy:`CMP0074`. diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst index 53f3819..a4416ab 100644 --- a/Help/command/find_package.rst +++ b/Help/command/find_package.rst @@ -262,8 +262,10 @@ The set of installation prefixes is constructed using the following steps. If ``NO_DEFAULT_PATH`` is specified all ``NO_*`` options are enabled. -1. Search paths specified in the ``PackageName_ROOT`` CMake and environment - variables. The package root variables are maintained as a stack so if +1. Search paths specified in the :variable:`<PackageName>_ROOT` CMake + variable and the :envvar:`<PackageName>_ROOT` environment variable, + where ``<PackageName>`` is the package to be found. + The package root variables are maintained as a stack so if called from within a find module, root paths from the parent's find module will also be searched after paths for the current package. This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed. diff --git a/Help/dev/maint.rst b/Help/dev/maint.rst index ec76479..a8942cd 100644 --- a/Help/dev/maint.rst +++ b/Help/dev/maint.rst @@ -51,15 +51,18 @@ using a local branch named ``release-$ver``, where ``$ver`` is the version number of the current release in the form ``$major.$minor``. It is always merged into ``master`` before publishing. -To merge some ``$topic`` branch into ``release``, first create the local -branch: +Before merging a ``$topic`` branch into ``release``, verify that the +``$topic`` branch has already been merged to ``master`` via the usual +``Do: merge`` process. Then, to merge the ``$topic`` branch into +``release``, start by creating the local branch: .. code-block:: shell git fetch origin git checkout -b release-$ver origin/release -Merge the ``$topic`` branch into the local ``release-$ver`` branch: +Merge the ``$topic`` branch into the local ``release-$ver`` branch, making +sure to include a ``Merge-request: !xxxx`` footer in the commit message: .. code-block:: shell diff --git a/Help/envvar/PackageName_ROOT.rst b/Help/envvar/PackageName_ROOT.rst new file mode 100644 index 0000000..e01009b --- /dev/null +++ b/Help/envvar/PackageName_ROOT.rst @@ -0,0 +1,15 @@ +<PackageName>_ROOT +------------------ + +Calls to :command:`find_package(<PackageName>)` will search in prefixes +specified by the ``<PackageName>_ROOT`` environment variable, where +``<PackageName>`` is the name given to the ``find_package`` call +and ``_ROOT`` is literal. For example, ``find_package(Foo)`` will search +prefixes specified in the ``Foo_ROOT`` environment variable (if set). +See policy :policy:`CMP0074`. + +This variable may hold a single prefix or a list of prefixes separated +by ``:`` on UNIX or ``;`` on Windows (the same as the ``PATH`` environment +variable convention on those platforms). + +See also the :variable:`<PackageName>_ROOT` CMake variable. diff --git a/Help/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst index 2d17bb5..42aeabc 100644 --- a/Help/manual/cmake-env-variables.7.rst +++ b/Help/manual/cmake-env-variables.7.rst @@ -20,6 +20,7 @@ Environment Variables that Control the Build /envvar/DESTDIR /envvar/LDFLAGS /envvar/MACOSX_DEPLOYMENT_TARGET + /envvar/PackageName_ROOT Environment Variables for Languages =================================== diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 451bd23..48b1f20 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -204,6 +204,7 @@ Variables that Change Behavior /variable/CMAKE_WARN_DEPRECATED /variable/CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION /variable/CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY + /variable/PackageName_ROOT Variables that Describe the System ================================== diff --git a/Help/policy/CMP0074.rst b/Help/policy/CMP0074.rst index ffac4a7..896936b 100644 --- a/Help/policy/CMP0074.rst +++ b/Help/policy/CMP0074.rst @@ -1,18 +1,19 @@ CMP0074 ------- -:command:`find_package` uses ``PackageName_ROOT`` variables. +:command:`find_package` uses ``<PackageName>_ROOT`` variables. -In CMake 3.12 and above the ``find_package(PackageName)`` command now searches -a prefix specified by a ``PackageName_ROOT`` CMake or environment variable. +In CMake 3.12 and above the :command:`find_package(<PackageName>)` command now +searches prefixes specified by the :variable:`<PackageName>_ROOT` CMake +variable and the :envvar:`<PackageName>_ROOT` environment variable. Package roots are maintained as a stack so nested calls to all ``find_*`` commands inside find modules also search the roots as prefixes. This policy provides compatibility with projects that have not been updated to avoid using -``PackageName_ROOT`` variables for other purposes. +``<PackageName>_ROOT`` variables for other purposes. -The ``OLD`` behavior for this policy is to ignore ``PackageName_ROOT`` -variables. The ``NEW`` behavior for this policy is to use ``PackageName_ROOT`` -variables. +The ``OLD`` behavior for this policy is to ignore ``<PackageName>_ROOT`` +variables. The ``NEW`` behavior for this policy is to use +``<PackageName>_ROOT`` variables. This policy was introduced in CMake version 3.12. CMake version |release| warns when the policy is not set and uses ``OLD`` behavior. diff --git a/Help/release/3.12.rst b/Help/release/3.12.rst index bbeb11e..481027e 100644 --- a/Help/release/3.12.rst +++ b/Help/release/3.12.rst @@ -46,8 +46,9 @@ Commands were added to expose ``TOUCH`` functionality without having to use CMake's command-line tool mode with :command:`execute_process`. -* The :command:`find_package` command now searches a prefix specified by - a ``PackageName_ROOT`` CMake or environment variable. Package roots are +* The :command:`find_package` command now searches prefixes specified by + the :variable:`<PackageName>_ROOT` CMake variable and the + :envvar:`<PackageName>_ROOT` environment variable. Package roots are maintained as a stack so nested calls to all ``find_*`` commands inside find modules also search the roots as prefixes. See policy :policy:`CMP0074`. diff --git a/Help/release/dev/pkgc-global.rst b/Help/release/dev/pkgc-global.rst new file mode 100644 index 0000000..0c07d9e --- /dev/null +++ b/Help/release/dev/pkgc-global.rst @@ -0,0 +1,5 @@ +pkgc-global +----------- + +* Module ``FindPkgConfig`` gains capability to create imported targets in + global scope. diff --git a/Help/variable/PackageName_ROOT.rst b/Help/variable/PackageName_ROOT.rst new file mode 100644 index 0000000..4f6c25b --- /dev/null +++ b/Help/variable/PackageName_ROOT.rst @@ -0,0 +1,14 @@ +<PackageName>_ROOT +------------------ + +Calls to :command:`find_package(<PackageName>)` will search in prefixes +specified by the ``<PackageName>_ROOT`` CMake variable, where +``<PackageName>`` is the name given to the ``find_package`` call +and ``_ROOT`` is literal. For example, ``find_package(Foo)`` will search +prefixes specified in the ``Foo_ROOT`` CMake variable (if set). +See policy :policy:`CMP0074`. + +This variable may hold a single prefix or a +:ref:`;-list <CMake Language Lists>` of multiple prefixes. + +See also the :envvar:`<PackageName>_ROOT` environment variable. diff --git a/Modules/BundleUtilities.cmake b/Modules/BundleUtilities.cmake index 121a8f0..4727f03 100644 --- a/Modules/BundleUtilities.cmake +++ b/Modules/BundleUtilities.cmake @@ -421,7 +421,12 @@ function(get_item_rpaths item rpaths_var) execute_process( COMMAND "${otool_cmd}" -l "${item}" OUTPUT_VARIABLE load_cmds_ov + RESULT_VARIABLE otool_rv + ERROR_VARIABLE otool_ev ) + if(NOT otool_rv STREQUAL "0") + message(FATAL_ERROR "otool -l failed: ${otool_rv}\n${otool_ev}") + endif() string(REGEX REPLACE "[^\n]+cmd LC_RPATH\n[^\n]+\n[^\n]+path ([^\n]+) \\(offset[^\n]+\n" "rpath \\1\n" load_cmds_ov "${load_cmds_ov}") string(REGEX MATCHALL "rpath [^\n]+" load_cmds_ov "${load_cmds_ov}") string(REGEX REPLACE "rpath " "" load_cmds_ov "${load_cmds_ov}") diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake index 775a9d7..3934867 100644 --- a/Modules/FindPkgConfig.cmake +++ b/Modules/FindPkgConfig.cmake @@ -114,12 +114,13 @@ macro(_pkgconfig_invoke_dyn _pkglist _prefix _varname cleanup_regexp) endmacro() # Splits given arguments into options and a package list -macro(_pkgconfig_parse_options _result _is_req _is_silent _no_cmake_path _no_cmake_environment_path _imp_target) +macro(_pkgconfig_parse_options _result _is_req _is_silent _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global) set(${_is_req} 0) set(${_is_silent} 0) set(${_no_cmake_path} 0) set(${_no_cmake_environment_path} 0) set(${_imp_target} 0) + set(${_imp_target_global} 0) if(DEFINED PKG_CONFIG_USE_CMAKE_PREFIX_PATH) if(NOT PKG_CONFIG_USE_CMAKE_PREFIX_PATH) set(${_no_cmake_path} 1) @@ -146,14 +147,22 @@ macro(_pkgconfig_parse_options _result _is_req _is_silent _no_cmake_path _no_cma if (_pkg STREQUAL "IMPORTED_TARGET") set(${_imp_target} 1) endif() + if (_pkg STREQUAL "GLOBAL") + set(${_imp_target_global} 1) + endif() endforeach() + if (${_imp_target_global} AND NOT ${_imp_target}) + message(SEND_ERROR "the argument GLOBAL may only be used together with IMPORTED_TARGET") + endif() + set(${_result} ${ARGN}) list(REMOVE_ITEM ${_result} "REQUIRED") list(REMOVE_ITEM ${_result} "QUIET") list(REMOVE_ITEM ${_result} "NO_CMAKE_PATH") list(REMOVE_ITEM ${_result} "NO_CMAKE_ENVIRONMENT_PATH") list(REMOVE_ITEM ${_result} "IMPORTED_TARGET") + list(REMOVE_ITEM ${_result} "GLOBAL") endmacro() # Add the content of a variable or an environment variable to a list of @@ -225,11 +234,16 @@ function(_pkg_find_libs _prefix _no_cmake_path _no_cmake_environment_path) endfunction() # create an imported target from all the information returned by pkg-config -function(_pkg_create_imp_target _prefix) +function(_pkg_create_imp_target _prefix _imp_target_global) # only create the target if it is linkable, i.e. no executables if (NOT TARGET PkgConfig::${_prefix} AND ( ${_prefix}_INCLUDE_DIRS OR ${_prefix}_LINK_LIBRARIES OR ${_prefix}_CFLAGS_OTHER )) - add_library(PkgConfig::${_prefix} INTERFACE IMPORTED) + if(${_imp_target_global}) + set(_global_opt "GLOBAL") + else() + unset(_global_opt) + endif() + add_library(PkgConfig::${_prefix} INTERFACE IMPORTED ${_global_opt}) if(${_prefix}_INCLUDE_DIRS) set_property(TARGET PkgConfig::${_prefix} PROPERTY @@ -248,15 +262,15 @@ endfunction() # recalculate the dynamic output # this is a macro and not a function so the result of _pkg_find_libs is automatically propagated -macro(_pkg_recalculate _prefix _no_cmake_path _no_cmake_environment_path _imp_target) +macro(_pkg_recalculate _prefix _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global) _pkg_find_libs(${_prefix} ${_no_cmake_path} ${_no_cmake_environment_path}) if(${_imp_target}) - _pkg_create_imp_target(${_prefix}) + _pkg_create_imp_target(${_prefix} ${_imp_target_global}) endif() endmacro() ### -macro(_pkg_check_modules_internal _is_required _is_silent _no_cmake_path _no_cmake_environment_path _imp_target _prefix) +macro(_pkg_check_modules_internal _is_required _is_silent _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global _prefix) _pkgconfig_unset(${_prefix}_FOUND) _pkgconfig_unset(${_prefix}_VERSION) _pkgconfig_unset(${_prefix}_PREFIX) @@ -474,7 +488,7 @@ macro(_pkg_check_modules_internal _is_required _is_silent _no_cmake_path _no_cma _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS "" --cflags ) _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS_OTHER "" --cflags-only-other ) - _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target}) + _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} ${_imp_target_global}) endif() if(NOT "${_extra_paths}" STREQUAL "") @@ -502,7 +516,7 @@ endmacro() [REQUIRED] [QUIET] [NO_CMAKE_PATH] [NO_CMAKE_ENVIRONMENT_PATH] - [IMPORTED_TARGET] + [IMPORTED_TARGET [GLOBAL]] <moduleSpec> [<moduleSpec>...]) When the ``REQUIRED`` argument is given, the command will fail with an error @@ -521,7 +535,8 @@ endmacro() The ``IMPORTED_TARGET`` argument will create an imported target named ``PkgConfig::<prefix>`` that can be passed directly as an argument to - :command:`target_link_libraries`. + :command:`target_link_libraries`. The ``GLOBAL`` argument will make the + imported target available in global scope. Each ``<moduleSpec>`` must be in one of the following formats:: @@ -594,12 +609,12 @@ endmacro() XRENDER_STATIC_LIBRARIES=Xrender;X11;pthread;Xau;Xdmcp #]========================================] macro(pkg_check_modules _prefix _module0) - _pkgconfig_parse_options(_pkg_modules _pkg_is_required _pkg_is_silent _no_cmake_path _no_cmake_environment_path _imp_target "${_module0}" ${ARGN}) + _pkgconfig_parse_options(_pkg_modules _pkg_is_required _pkg_is_silent _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global "${_module0}" ${ARGN}) # check cached value if (NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION} OR NOT ${_prefix}_FOUND OR (NOT "${ARGN}" STREQUAL "" AND NOT "${__pkg_config_arguments_${_prefix}}" STREQUAL "${_module0};${ARGN}") OR ( "${ARGN}" STREQUAL "" AND NOT "${__pkg_config_arguments_${_prefix}}" STREQUAL "${_module0}")) - _pkg_check_modules_internal("${_pkg_is_required}" "${_pkg_is_silent}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} "${_prefix}" ${_pkg_modules}) + _pkg_check_modules_internal("${_pkg_is_required}" "${_pkg_is_silent}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} ${_imp_target_global} "${_prefix}" ${_pkg_modules}) _pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION}) if (${_prefix}_FOUND) @@ -607,7 +622,7 @@ macro(pkg_check_modules _prefix _module0) endif() else() if (${_prefix}_FOUND) - _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target}) + _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} ${_imp_target_global}) endif() endif() endmacro() @@ -624,7 +639,7 @@ endmacro() [REQUIRED] [QUIET] [NO_CMAKE_PATH] [NO_CMAKE_ENVIRONMENT_PATH] - [IMPORTED_TARGET] + [IMPORTED_TARGET [GLOBAL]] <moduleSpec> [<moduleSpec>...]) Examples @@ -634,7 +649,7 @@ endmacro() pkg_search_module (BAR libxml-2.0 libxml2 libxml>=2) #]========================================] macro(pkg_search_module _prefix _module0) - _pkgconfig_parse_options(_pkg_modules_alt _pkg_is_required _pkg_is_silent _no_cmake_path _no_cmake_environment_path _imp_target "${_module0}" ${ARGN}) + _pkgconfig_parse_options(_pkg_modules_alt _pkg_is_required _pkg_is_silent _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global "${_module0}" ${ARGN}) # check cached value if (NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION} OR NOT ${_prefix}_FOUND) set(_pkg_modules_found 0) @@ -646,7 +661,7 @@ macro(pkg_search_module _prefix _module0) # iterate through all modules and stop at the first working one. foreach(_pkg_alt ${_pkg_modules_alt}) if(NOT _pkg_modules_found) - _pkg_check_modules_internal(0 1 ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} "${_prefix}" "${_pkg_alt}") + _pkg_check_modules_internal(0 1 ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} ${_imp_target_global} "${_prefix}" "${_pkg_alt}") endif() if (${_prefix}_FOUND) @@ -662,7 +677,7 @@ macro(pkg_search_module _prefix _module0) _pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION}) elseif (${_prefix}_FOUND) - _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target}) + _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} ${_imp_target_global}) endif() endmacro() diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake index 08f07fd..fe3df91 100644 --- a/Modules/FindPython/Support.cmake +++ b/Modules/FindPython/Support.cmake @@ -196,10 +196,6 @@ endif() set (CMAKE_FIND_FRAMEWORK LAST) -unset (${_PYTHON_PREFIX}_VERSION_MAJOR) -unset (${_PYTHON_PREFIX}_VERSION_MINOR) -unset (${_PYTHON_PREFIX}_VERSION_PATCH) - unset (_${_PYTHON_PREFIX}_REQUIRED_VARS) unset (_${_PYTHON_PREFIX}_CACHED_VARS) @@ -259,7 +255,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) # try more generic names if (NOT ${_PYTHON_PREFIX}_EXECUTABLE) find_program (${_PYTHON_PREFIX}_EXECUTABLE - NAMES python${${_PYTHON_PREFIX}_VERSION_MAJOR} python + NAMES python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} python ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} HINTS ${_${_PYTHON_PREFIX}_HINTS} PATH_SUFFIXES bin) diff --git a/Modules/GetPrerequisites.cmake b/Modules/GetPrerequisites.cmake index d397791..ca71009 100644 --- a/Modules/GetPrerequisites.cmake +++ b/Modules/GetPrerequisites.cmake @@ -275,7 +275,6 @@ function(gp_item_default_embedded_path item default_embedded_path_var) # as the executable by default: # set(path "@executable_path") - set(overridden 0) # On the Mac, relative to the executable depending on the type # of the thing we are embedding: @@ -294,20 +293,11 @@ function(gp_item_default_embedded_path item default_embedded_path_var) # set(path "@executable_path/../../Contents/MacOS") - # Embed .dylibs right next to the main bundle executable: + # Embed frameworks and .dylibs in the embedded "Frameworks" directory + # (sibling of MacOS): # - if(item MATCHES "\\.dylib$") - set(path "@executable_path/../MacOS") - set(overridden 1) - endif() - - # Embed frameworks in the embedded "Frameworks" directory (sibling of MacOS): - # - if(NOT overridden) - if(item MATCHES "[^/]+\\.framework/") - set(path "@executable_path/../Frameworks") - set(overridden 1) - endif() + if(item MATCHES "[^/]+\\.framework/" OR item MATCHES "\\.dylib$") + set(path "@executable_path/../Frameworks") endif() endif() diff --git a/Modules/GoogleTest.cmake b/Modules/GoogleTest.cmake index bfb83e1..2c9ee11 100644 --- a/Modules/GoogleTest.cmake +++ b/Modules/GoogleTest.cmake @@ -238,6 +238,10 @@ same as the Google Test name (i.e. ``suite.testcase``); see also #]=======================================================================] +# Save project's policies +cmake_policy(PUSH) +cmake_policy(SET CMP0057 NEW) # if IN_LIST + #------------------------------------------------------------------------------ function(gtest_add_tests) @@ -454,3 +458,6 @@ endfunction() set(_GOOGLETEST_DISCOVER_TESTS_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/GoogleTestAddTests.cmake ) + +# Restore project's policies +cmake_policy(POP) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index d9f5396..8d037e4 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 12) -set(CMake_VERSION_PATCH 20180719) +set(CMake_VERSION_PATCH 20180727) #set(CMake_VERSION_RC 1) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 02297d5..042ce41 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -386,12 +386,46 @@ void cmGlobalXCodeGenerator::AddExtraIDETargets() } } +void cmGlobalXCodeGenerator::ComputeTargetOrder() +{ + size_t index = 0; + auto const& lgens = this->GetLocalGenerators(); + for (cmLocalGenerator* lgen : lgens) { + auto const& targets = lgen->GetGeneratorTargets(); + for (cmGeneratorTarget const* gt : targets) { + this->ComputeTargetOrder(gt, index); + } + } + assert(index == this->TargetOrderIndex.size()); +} + +void cmGlobalXCodeGenerator::ComputeTargetOrder(cmGeneratorTarget const* gt, + size_t& index) +{ + std::map<cmGeneratorTarget const*, size_t>::value_type value(gt, 0); + auto insertion = this->TargetOrderIndex.insert(value); + if (!insertion.second) { + return; + } + auto entry = insertion.first; + + auto& deps = this->GetTargetDirectDepends(gt); + for (auto& d : deps) { + this->ComputeTargetOrder(d, index); + } + + entry->second = index++; +} + void cmGlobalXCodeGenerator::Generate() { this->cmGlobalGenerator::Generate(); if (cmSystemTools::GetErrorOccuredFlag()) { return; } + + this->ComputeTargetOrder(); + for (auto keyVal : this->ProjectMap) { cmLocalGenerator* root = keyVal.second[0]; @@ -1031,15 +1065,17 @@ struct cmSourceFilePathCompare struct cmCompareTargets { - bool operator()(std::string const& a, std::string const& b) const + bool operator()(cmXCodeObject* l, cmXCodeObject* r) const { + std::string const& a = l->GetTarget()->GetName(); + std::string const& b = r->GetTarget()->GetName(); if (a == "ALL_BUILD") { return true; } if (b == "ALL_BUILD") { return false; } - return strcmp(a.c_str(), b.c_str()) < 0; + return a < b; } }; @@ -1047,274 +1083,279 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets( cmLocalGenerator* gen, std::vector<cmXCodeObject*>& targets) { this->SetCurrentLocalGenerator(gen); - typedef std::map<std::string, cmGeneratorTarget*, cmCompareTargets> - cmSortedTargets; - cmSortedTargets sortedTargets; - for (auto tgt : this->CurrentLocalGenerator->GetGeneratorTargets()) { - sortedTargets[tgt->GetName()] = tgt; + std::vector<cmGeneratorTarget*> gts = + this->CurrentLocalGenerator->GetGeneratorTargets(); + std::sort(gts.begin(), gts.end(), + [this](cmGeneratorTarget const* l, cmGeneratorTarget const* r) { + return this->TargetOrderIndex[l] < this->TargetOrderIndex[r]; + }); + for (auto gtgt : gts) { + if (!this->CreateXCodeTarget(gtgt, targets)) { + return false; + } } - for (auto& sortedTarget : sortedTargets) { - cmGeneratorTarget* gtgt = sortedTarget.second; - - std::string targetName = gtgt->GetName(); + std::sort(targets.begin(), targets.end(), cmCompareTargets()); + return true; +} - // make sure ALL_BUILD, INSTALL, etc are only done once - if (this->SpecialTargetEmitted(targetName)) { - continue; - } +bool cmGlobalXCodeGenerator::CreateXCodeTarget( + cmGeneratorTarget* gtgt, std::vector<cmXCodeObject*>& targets) +{ + std::string targetName = gtgt->GetName(); - if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { - continue; - } + // make sure ALL_BUILD, INSTALL, etc are only done once + if (this->SpecialTargetEmitted(targetName)) { + return true; + } - if (gtgt->GetType() == cmStateEnums::UTILITY || - gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) { - cmXCodeObject* t = this->CreateUtilityTarget(gtgt); - if (!t) { - return false; - } - targets.push_back(t); - continue; - } + if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + return true; + } - // organize the sources - std::vector<cmSourceFile*> classes; - if (!gtgt->GetConfigCommonSourceFiles(classes)) { + if (gtgt->GetType() == cmStateEnums::UTILITY || + gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) { + cmXCodeObject* t = this->CreateUtilityTarget(gtgt); + if (!t) { return false; } + targets.push_back(t); + return true; + } - // Add CMakeLists.txt file for user convenience. - this->AddXCodeProjBuildRule(gtgt, classes); + // organize the sources + std::vector<cmSourceFile*> classes; + if (!gtgt->GetConfigCommonSourceFiles(classes)) { + return false; + } - std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare()); + // Add CMakeLists.txt file for user convenience. + this->AddXCodeProjBuildRule(gtgt, classes); - gtgt->ComputeObjectMapping(); + std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare()); - std::vector<cmXCodeObject*> externalObjFiles; - std::vector<cmXCodeObject*> headerFiles; - std::vector<cmXCodeObject*> resourceFiles; - std::vector<cmXCodeObject*> sourceFiles; - for (auto sourceFile : classes) { - cmXCodeObject* xsf = this->CreateXCodeSourceFile( - this->CurrentLocalGenerator, sourceFile, gtgt); - cmXCodeObject* fr = xsf->GetObject("fileRef"); - cmXCodeObject* filetype = fr->GetObject()->GetObject("explicitFileType"); + gtgt->ComputeObjectMapping(); - cmGeneratorTarget::SourceFileFlags tsFlags = - gtgt->GetTargetSourceFileFlags(sourceFile); + std::vector<cmXCodeObject*> externalObjFiles; + std::vector<cmXCodeObject*> headerFiles; + std::vector<cmXCodeObject*> resourceFiles; + std::vector<cmXCodeObject*> sourceFiles; + for (auto sourceFile : classes) { + cmXCodeObject* xsf = this->CreateXCodeSourceFile( + this->CurrentLocalGenerator, sourceFile, gtgt); + cmXCodeObject* fr = xsf->GetObject("fileRef"); + cmXCodeObject* filetype = fr->GetObject()->GetObject("explicitFileType"); - if (filetype && filetype->GetString() == "compiled.mach-o.objfile") { - if (sourceFile->GetObjectLibrary().empty()) { - externalObjFiles.push_back(xsf); - } - } else if (this->IsHeaderFile(sourceFile) || - (tsFlags.Type == - cmGeneratorTarget::SourceFileTypePrivateHeader) || - (tsFlags.Type == - cmGeneratorTarget::SourceFileTypePublicHeader)) { - headerFiles.push_back(xsf); - } else if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource) { - resourceFiles.push_back(xsf); - } else if (!sourceFile->GetPropertyAsBool("HEADER_FILE_ONLY")) { - // Include this file in the build if it has a known language - // and has not been listed as an ignored extension for this - // generator. - if (!this->CurrentLocalGenerator->GetSourceFileLanguage(*sourceFile) - .empty() && - !this->IgnoreFile(sourceFile->GetExtension().c_str())) { - sourceFiles.push_back(xsf); - } - } - } + cmGeneratorTarget::SourceFileFlags tsFlags = + gtgt->GetTargetSourceFileFlags(sourceFile); - if (this->XcodeVersion < 50) { - // Add object library contents as external objects. (Equivalent to - // the externalObjFiles above, except each one is not a cmSourceFile - // within the target.) - std::vector<cmSourceFile const*> objs; - gtgt->GetExternalObjects(objs, ""); - for (auto sourceFile : objs) { - if (sourceFile->GetObjectLibrary().empty()) { - continue; - } - std::string const& obj = sourceFile->GetFullPath(); - cmXCodeObject* xsf = - this->CreateXCodeSourceFileFromPath(obj, gtgt, "", nullptr); + if (filetype && filetype->GetString() == "compiled.mach-o.objfile") { + if (sourceFile->GetObjectLibrary().empty()) { externalObjFiles.push_back(xsf); } - } - - // some build phases only apply to bundles and/or frameworks - bool isFrameworkTarget = gtgt->IsFrameworkOnApple(); - bool isBundleTarget = gtgt->GetPropertyAsBool("MACOSX_BUNDLE"); - bool isCFBundleTarget = gtgt->IsCFBundleOnApple(); - - cmXCodeObject* buildFiles = nullptr; - - // create source build phase - cmXCodeObject* sourceBuildPhase = nullptr; - if (!sourceFiles.empty()) { - sourceBuildPhase = - this->CreateObject(cmXCodeObject::PBXSourcesBuildPhase); - sourceBuildPhase->SetComment("Sources"); - sourceBuildPhase->AddAttribute("buildActionMask", - this->CreateString("2147483647")); - buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); - for (auto& sourceFile : sourceFiles) { - buildFiles->AddObject(sourceFile); + } else if (this->IsHeaderFile(sourceFile) || + (tsFlags.Type == + cmGeneratorTarget::SourceFileTypePrivateHeader) || + (tsFlags.Type == + cmGeneratorTarget::SourceFileTypePublicHeader)) { + headerFiles.push_back(xsf); + } else if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource) { + resourceFiles.push_back(xsf); + } else if (!sourceFile->GetPropertyAsBool("HEADER_FILE_ONLY")) { + // Include this file in the build if it has a known language + // and has not been listed as an ignored extension for this + // generator. + if (!this->CurrentLocalGenerator->GetSourceFileLanguage(*sourceFile) + .empty() && + !this->IgnoreFile(sourceFile->GetExtension().c_str())) { + sourceFiles.push_back(xsf); } - sourceBuildPhase->AddAttribute("files", buildFiles); - sourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", - this->CreateString("0")); } + } - // create header build phase - only for framework targets - cmXCodeObject* headerBuildPhase = nullptr; - if (!headerFiles.empty() && isFrameworkTarget) { - headerBuildPhase = - this->CreateObject(cmXCodeObject::PBXHeadersBuildPhase); - headerBuildPhase->SetComment("Headers"); - headerBuildPhase->AddAttribute("buildActionMask", - this->CreateString("2147483647")); - buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); - for (auto& headerFile : headerFiles) { - buildFiles->AddObject(headerFile); + if (this->XcodeVersion < 50) { + // Add object library contents as external objects. (Equivalent to + // the externalObjFiles above, except each one is not a cmSourceFile + // within the target.) + std::vector<cmSourceFile const*> objs; + gtgt->GetExternalObjects(objs, ""); + for (auto sourceFile : objs) { + if (sourceFile->GetObjectLibrary().empty()) { + continue; } - headerBuildPhase->AddAttribute("files", buildFiles); - headerBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", - this->CreateString("0")); + std::string const& obj = sourceFile->GetFullPath(); + cmXCodeObject* xsf = + this->CreateXCodeSourceFileFromPath(obj, gtgt, "", nullptr); + externalObjFiles.push_back(xsf); + } + } + + // some build phases only apply to bundles and/or frameworks + bool isFrameworkTarget = gtgt->IsFrameworkOnApple(); + bool isBundleTarget = gtgt->GetPropertyAsBool("MACOSX_BUNDLE"); + bool isCFBundleTarget = gtgt->IsCFBundleOnApple(); + + cmXCodeObject* buildFiles = nullptr; + + // create source build phase + cmXCodeObject* sourceBuildPhase = nullptr; + if (!sourceFiles.empty()) { + sourceBuildPhase = this->CreateObject(cmXCodeObject::PBXSourcesBuildPhase); + sourceBuildPhase->SetComment("Sources"); + sourceBuildPhase->AddAttribute("buildActionMask", + this->CreateString("2147483647")); + buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + for (auto& sourceFile : sourceFiles) { + buildFiles->AddObject(sourceFile); + } + sourceBuildPhase->AddAttribute("files", buildFiles); + sourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); + } + + // create header build phase - only for framework targets + cmXCodeObject* headerBuildPhase = nullptr; + if (!headerFiles.empty() && isFrameworkTarget) { + headerBuildPhase = this->CreateObject(cmXCodeObject::PBXHeadersBuildPhase); + headerBuildPhase->SetComment("Headers"); + headerBuildPhase->AddAttribute("buildActionMask", + this->CreateString("2147483647")); + buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + for (auto& headerFile : headerFiles) { + buildFiles->AddObject(headerFile); + } + headerBuildPhase->AddAttribute("files", buildFiles); + headerBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); + } + + // create resource build phase - only for framework or bundle targets + cmXCodeObject* resourceBuildPhase = nullptr; + if (!resourceFiles.empty() && + (isFrameworkTarget || isBundleTarget || isCFBundleTarget)) { + resourceBuildPhase = + this->CreateObject(cmXCodeObject::PBXResourcesBuildPhase); + resourceBuildPhase->SetComment("Resources"); + resourceBuildPhase->AddAttribute("buildActionMask", + this->CreateString("2147483647")); + buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + for (auto& resourceFile : resourceFiles) { + buildFiles->AddObject(resourceFile); } + resourceBuildPhase->AddAttribute("files", buildFiles); + resourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); + } - // create resource build phase - only for framework or bundle targets - cmXCodeObject* resourceBuildPhase = nullptr; - if (!resourceFiles.empty() && - (isFrameworkTarget || isBundleTarget || isCFBundleTarget)) { - resourceBuildPhase = - this->CreateObject(cmXCodeObject::PBXResourcesBuildPhase); - resourceBuildPhase->SetComment("Resources"); - resourceBuildPhase->AddAttribute("buildActionMask", - this->CreateString("2147483647")); - buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); - for (auto& resourceFile : resourceFiles) { - buildFiles->AddObject(resourceFile); - } - resourceBuildPhase->AddAttribute("files", buildFiles); - resourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", - this->CreateString("0")); - } - - // create vector of "non-resource content file" build phases - only for - // framework or bundle targets - std::vector<cmXCodeObject*> contentBuildPhases; - if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) { - typedef std::map<std::string, std::vector<cmSourceFile*>> - mapOfVectorOfSourceFiles; - mapOfVectorOfSourceFiles bundleFiles; - for (auto sourceFile : classes) { - cmGeneratorTarget::SourceFileFlags tsFlags = - gtgt->GetTargetSourceFileFlags(sourceFile); - if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) { - bundleFiles[tsFlags.MacFolder].push_back(sourceFile); - } + // create vector of "non-resource content file" build phases - only for + // framework or bundle targets + std::vector<cmXCodeObject*> contentBuildPhases; + if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) { + typedef std::map<std::string, std::vector<cmSourceFile*>> + mapOfVectorOfSourceFiles; + mapOfVectorOfSourceFiles bundleFiles; + for (auto sourceFile : classes) { + cmGeneratorTarget::SourceFileFlags tsFlags = + gtgt->GetTargetSourceFileFlags(sourceFile); + if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) { + bundleFiles[tsFlags.MacFolder].push_back(sourceFile); } - for (auto keySources : bundleFiles) { - cmXCodeObject* copyFilesBuildPhase = - this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase); - copyFilesBuildPhase->SetComment("Copy files"); - copyFilesBuildPhase->AddAttribute("buildActionMask", - this->CreateString("2147483647")); - copyFilesBuildPhase->AddAttribute("dstSubfolderSpec", - this->CreateString("6")); - std::ostringstream ostr; - if (gtgt->IsFrameworkOnApple()) { - // dstPath in frameworks is relative to Versions/<version> + } + for (auto keySources : bundleFiles) { + cmXCodeObject* copyFilesBuildPhase = + this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase); + copyFilesBuildPhase->SetComment("Copy files"); + copyFilesBuildPhase->AddAttribute("buildActionMask", + this->CreateString("2147483647")); + copyFilesBuildPhase->AddAttribute("dstSubfolderSpec", + this->CreateString("6")); + std::ostringstream ostr; + if (gtgt->IsFrameworkOnApple()) { + // dstPath in frameworks is relative to Versions/<version> + ostr << keySources.first; + } else if (keySources.first != "MacOS") { + if (gtgt->Target->GetMakefile()->PlatformIsAppleEmbedded()) { ostr << keySources.first; - } else if (keySources.first != "MacOS") { - if (gtgt->Target->GetMakefile()->PlatformIsAppleEmbedded()) { - ostr << keySources.first; - } else { - // dstPath in bundles is relative to Contents/MacOS - ostr << "../" << keySources.first; - } - } - copyFilesBuildPhase->AddAttribute("dstPath", - this->CreateString(ostr.str())); - copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", - this->CreateString("0")); - buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); - copyFilesBuildPhase->AddAttribute("files", buildFiles); - for (auto sourceFile : keySources.second) { - cmXCodeObject* xsf = this->CreateXCodeSourceFile( - this->CurrentLocalGenerator, sourceFile, gtgt); - buildFiles->AddObject(xsf); + } else { + // dstPath in bundles is relative to Contents/MacOS + ostr << "../" << keySources.first; } - contentBuildPhases.push_back(copyFilesBuildPhase); } + copyFilesBuildPhase->AddAttribute("dstPath", + this->CreateString(ostr.str())); + copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); + buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + copyFilesBuildPhase->AddAttribute("files", buildFiles); + for (auto sourceFile : keySources.second) { + cmXCodeObject* xsf = this->CreateXCodeSourceFile( + this->CurrentLocalGenerator, sourceFile, gtgt); + buildFiles->AddObject(xsf); + } + contentBuildPhases.push_back(copyFilesBuildPhase); } + } - // create vector of "resource content file" build phases - only for - // framework or bundle targets - if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) { - typedef std::map<std::string, std::vector<cmSourceFile*>> - mapOfVectorOfSourceFiles; - mapOfVectorOfSourceFiles bundleFiles; - for (auto sourceFile : classes) { - cmGeneratorTarget::SourceFileFlags tsFlags = - gtgt->GetTargetSourceFileFlags(sourceFile); - if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeDeepResource) { - bundleFiles[tsFlags.MacFolder].push_back(sourceFile); - } - } - for (auto keySources : bundleFiles) { - cmXCodeObject* copyFilesBuildPhase = - this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase); - copyFilesBuildPhase->SetComment("Copy files"); - copyFilesBuildPhase->AddAttribute("buildActionMask", - this->CreateString("2147483647")); - copyFilesBuildPhase->AddAttribute("dstSubfolderSpec", - this->CreateString("7")); - copyFilesBuildPhase->AddAttribute( - "dstPath", this->CreateString(keySources.first)); - copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", - this->CreateString("0")); - buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); - copyFilesBuildPhase->AddAttribute("files", buildFiles); - for (auto sourceFile : keySources.second) { - cmXCodeObject* xsf = this->CreateXCodeSourceFile( - this->CurrentLocalGenerator, sourceFile, gtgt); - buildFiles->AddObject(xsf); - } - contentBuildPhases.push_back(copyFilesBuildPhase); + // create vector of "resource content file" build phases - only for + // framework or bundle targets + if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) { + typedef std::map<std::string, std::vector<cmSourceFile*>> + mapOfVectorOfSourceFiles; + mapOfVectorOfSourceFiles bundleFiles; + for (auto sourceFile : classes) { + cmGeneratorTarget::SourceFileFlags tsFlags = + gtgt->GetTargetSourceFileFlags(sourceFile); + if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeDeepResource) { + bundleFiles[tsFlags.MacFolder].push_back(sourceFile); } } - - // create framework build phase - cmXCodeObject* frameworkBuildPhase = nullptr; - if (!externalObjFiles.empty()) { - frameworkBuildPhase = - this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase); - frameworkBuildPhase->SetComment("Frameworks"); - frameworkBuildPhase->AddAttribute("buildActionMask", + for (auto keySources : bundleFiles) { + cmXCodeObject* copyFilesBuildPhase = + this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase); + copyFilesBuildPhase->SetComment("Copy files"); + copyFilesBuildPhase->AddAttribute("buildActionMask", this->CreateString("2147483647")); + copyFilesBuildPhase->AddAttribute("dstSubfolderSpec", + this->CreateString("7")); + copyFilesBuildPhase->AddAttribute("dstPath", + this->CreateString(keySources.first)); + copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); - frameworkBuildPhase->AddAttribute("files", buildFiles); - for (auto& externalObjFile : externalObjFiles) { - buildFiles->AddObject(externalObjFile); + copyFilesBuildPhase->AddAttribute("files", buildFiles); + for (auto sourceFile : keySources.second) { + cmXCodeObject* xsf = this->CreateXCodeSourceFile( + this->CurrentLocalGenerator, sourceFile, gtgt); + buildFiles->AddObject(xsf); } - frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", - this->CreateString("0")); + contentBuildPhases.push_back(copyFilesBuildPhase); + } + } + + // create framework build phase + cmXCodeObject* frameworkBuildPhase = nullptr; + if (!externalObjFiles.empty()) { + frameworkBuildPhase = + this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase); + frameworkBuildPhase->SetComment("Frameworks"); + frameworkBuildPhase->AddAttribute("buildActionMask", + this->CreateString("2147483647")); + buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + frameworkBuildPhase->AddAttribute("files", buildFiles); + for (auto& externalObjFile : externalObjFiles) { + buildFiles->AddObject(externalObjFile); } + frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); + } - // create list of build phases and create the Xcode target - cmXCodeObject* buildPhases = - this->CreateObject(cmXCodeObject::OBJECT_LIST); + // create list of build phases and create the Xcode target + cmXCodeObject* buildPhases = this->CreateObject(cmXCodeObject::OBJECT_LIST); - this->CreateCustomCommands(buildPhases, sourceBuildPhase, headerBuildPhase, - resourceBuildPhase, contentBuildPhases, - frameworkBuildPhase, gtgt); + this->CreateCustomCommands(buildPhases, sourceBuildPhase, headerBuildPhase, + resourceBuildPhase, contentBuildPhases, + frameworkBuildPhase, gtgt); - targets.push_back(this->CreateXCodeTarget(gtgt, buildPhases)); - } + targets.push_back(this->CreateXCodeTarget(gtgt, buildPhases)); return true; } @@ -3319,13 +3360,6 @@ void cmGlobalXCodeGenerator::OutputXCodeProject( if (generators.empty()) { return; } - // Skip local generators that are excluded from this project. - for (auto generator : generators) { - if (this->IsExcluded(root, generator)) { - continue; - } - } - if (!this->CreateXCodeObjects(root, generators)) { return; } diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index ccef6e2..f7bca13 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -109,6 +109,8 @@ public: protected: void AddExtraIDETargets() override; + void ComputeTargetOrder(); + void ComputeTargetOrder(cmGeneratorTarget const* gt, size_t& index); void Generate() override; private: @@ -204,6 +206,8 @@ private: void AddXCodeProjBuildRule(cmGeneratorTarget* target, std::vector<cmSourceFile*>& sources) const; bool CreateXCodeTargets(cmLocalGenerator* gen, std::vector<cmXCodeObject*>&); + bool CreateXCodeTarget(cmGeneratorTarget* gtgt, + std::vector<cmXCodeObject*>&); bool IsHeaderFile(cmSourceFile*); void AddDependTarget(cmXCodeObject* target, cmXCodeObject* dependTarget); void CreateXCodeDependHackTarget(std::vector<cmXCodeObject*>& targets); @@ -286,6 +290,7 @@ private: std::string ObjectDirArchDefault; std::string ObjectDirArch; std::string GeneratorToolset; + std::map<cmGeneratorTarget const*, size_t> TargetOrderIndex; }; #endif diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 072b958..647697a 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -844,12 +844,11 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, cmGeneratorTarget const* target, const std::string& lang, const std::string& config, - bool stripImplicitInclDirs) const + bool stripImplicitDirs, + bool appendAllImplicitDirs) const { - // Need to decide whether to automatically include the source and - // binary directories at the beginning of the include path. - bool includeSourceDir = false; - bool includeBinaryDir = false; + // Do not repeat an include path. + std::set<std::string> emitted; // When automatic include directories are requested for a build then // include the source and binary directories at the beginning of the @@ -859,26 +858,21 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, // cannot fix this because not all native build tools support // per-source-file include paths. if (this->Makefile->IsOn("CMAKE_INCLUDE_CURRENT_DIR")) { - includeSourceDir = true; - includeBinaryDir = true; - } - - // Do not repeat an include path. - std::set<std::string> emitted; - - // Store the automatic include paths. - if (includeBinaryDir) { - std::string binDir = this->StateSnapshot.GetDirectory().GetCurrentBinary(); - if (emitted.find(binDir) == emitted.end()) { - dirs.push_back(binDir); - emitted.insert(binDir); + // Current binary directory + { + std::string binDir = + this->StateSnapshot.GetDirectory().GetCurrentBinary(); + if (emitted.insert(binDir).second) { + dirs.push_back(std::move(binDir)); + } } - } - if (includeSourceDir) { - std::string srcDir = this->StateSnapshot.GetDirectory().GetCurrentSource(); - if (emitted.find(srcDir) == emitted.end()) { - dirs.push_back(srcDir); - emitted.insert(srcDir); + // Current source directory + { + std::string srcDir = + this->StateSnapshot.GetDirectory().GetCurrentSource(); + if (emitted.insert(srcDir).second) { + dirs.push_back(std::move(srcDir)); + } } } @@ -886,43 +880,45 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, return; } - std::string rootPath; - if (const char* sysrootCompile = - this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) { - rootPath = sysrootCompile; - } else { - rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); - } - + // Implicit include directories std::vector<std::string> implicitDirs; - // Load implicit include directories for this language. - std::string impDirVar = "CMAKE_"; - impDirVar += lang; - impDirVar += "_IMPLICIT_INCLUDE_DIRECTORIES"; - if (const char* value = this->Makefile->GetDefinition(impDirVar)) { - std::vector<std::string> impDirVec; - cmSystemTools::ExpandListArgument(value, impDirVec); - for (std::string const& i : impDirVec) { - std::string d = rootPath + i; - cmSystemTools::ConvertToUnixSlashes(d); - emitted.insert(std::move(d)); - if (!stripImplicitInclDirs) { + { + std::string rootPath; + if (const char* sysrootCompile = + this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) { + rootPath = sysrootCompile; + } else { + rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); + } + + // Load implicit include directories for this language. + std::string key = "CMAKE_"; + key += lang; + key += "_IMPLICIT_INCLUDE_DIRECTORIES"; + if (const char* value = this->Makefile->GetDefinition(key)) { + std::vector<std::string> impDirVec; + cmSystemTools::ExpandListArgument(value, impDirVec); + for (std::string const& i : impDirVec) { + { + std::string d = rootPath + i; + cmSystemTools::ConvertToUnixSlashes(d); + emitted.insert(std::move(d)); + } implicitDirs.push_back(i); } } } // Get the target-specific include directories. - std::vector<std::string> includes; - - includes = target->GetIncludeDirectories(config, lang); + std::vector<std::string> userDirs = + target->GetIncludeDirectories(config, lang); // Support putting all the in-project include directories first if // it is requested by the project. if (this->Makefile->IsOn("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE")) { std::string const &topSourceDir = this->GetState()->GetSourceDirectory(), &topBinaryDir = this->GetState()->GetBinaryDirectory(); - for (std::string const& i : includes) { + for (std::string const& i : userDirs) { // Emit this directory only if it is a subdirectory of the // top-level source or binary tree. if (cmSystemTools::ComparePath(i, topSourceDir) || @@ -937,7 +933,7 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, } // Construct the final ordered include directory list. - for (std::string const& i : includes) { + for (std::string const& i : userDirs) { if (emitted.insert(i).second) { dirs.push_back(i); } @@ -946,22 +942,38 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, this->MoveSystemIncludesToEnd(dirs, config, lang, target); // Add standard include directories for this language. - // We do not filter out implicit directories here. - std::string const standardIncludesVar = - "CMAKE_" + lang + "_STANDARD_INCLUDE_DIRECTORIES"; - std::string const standardIncludes = - this->Makefile->GetSafeDefinition(standardIncludesVar); - std::vector<std::string>::size_type const before = includes.size(); - cmSystemTools::ExpandListArgument(standardIncludes, includes); - for (std::vector<std::string>::iterator i = includes.begin() + before; - i != includes.end(); ++i) { - cmSystemTools::ConvertToUnixSlashes(*i); - dirs.push_back(*i); - } - - for (std::string const& i : implicitDirs) { - if (std::find(includes.begin(), includes.end(), i) != includes.end()) { - dirs.push_back(i); + { + std::vector<std::string>::size_type const before = userDirs.size(); + { + std::string key = "CMAKE_"; + key += lang; + key += "_STANDARD_INCLUDE_DIRECTORIES"; + std::string const value = this->Makefile->GetSafeDefinition(key); + cmSystemTools::ExpandListArgument(value, userDirs); + } + for (std::vector<std::string>::iterator i = userDirs.begin() + before, + ie = userDirs.end(); + i != ie; ++i) { + cmSystemTools::ConvertToUnixSlashes(*i); + dirs.push_back(*i); + } + } + + if (!stripImplicitDirs) { + if (!appendAllImplicitDirs) { + // Append only those implicit directories that were requested by the user + for (std::string const& i : implicitDirs) { + if (std::find(userDirs.begin(), userDirs.end(), i) != userDirs.end()) { + dirs.push_back(i); + } + } + } else { + // Append all implicit directories + for (std::string const& i : implicitDirs) { + if (std::find(dirs.begin(), dirs.end(), i) == dirs.end()) { + dirs.push_back(i); + } + } } } } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 9ba62cc..52f0396 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -237,12 +237,18 @@ public: return true; } - /** Get the include flags for the current makefile and language. */ + /** @brief Get the include directories for the current makefile and language. + * @arg stripImplicitDirs Strip all directories found in + * CMAKE_<LANG>_IMPLICIT_INCLUDE_DIRECTORIES from the result. + * @arg appendAllImplicitDirs Append all directories found in + * CMAKE_<LANG>_IMPLICIT_INCLUDE_DIRECTORIES to the result. + */ void GetIncludeDirectories(std::vector<std::string>& dirs, cmGeneratorTarget const* target, const std::string& lang = "C", const std::string& config = "", - bool stripImplicitInclDirs = true) const; + bool stripImplicitDirs = true, + bool appendAllImplicitDirs = false) const; void AddCompileOptions(std::string& flags, cmGeneratorTarget* target, const std::string& lang, const std::string& config); void AddCompileDefinitions(std::set<std::string>& defines, diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index a9b0b78..c868159 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -1526,6 +1526,8 @@ void cmMakefile::Configure() project.Name.Lower = "project"; project.Arguments.emplace_back("Project", cmListFileArgument::Unquoted, 0); + project.Arguments.emplace_back("__CMAKE_INJECTED_PROJECT_COMMAND__", + cmListFileArgument::Unquoted, 0); listFile.Functions.insert(listFile.Functions.begin(), project); } } diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index d0d9307..d6f7c54 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -219,8 +219,8 @@ class cmMakefile; SELECT(POLICY, CMP0073, \ "Do not produce legacy _LIB_DEPENDS cache entries.", 3, 12, 0, \ cmPolicies::WARN) \ - SELECT(POLICY, CMP0074, "find_package uses PackageName_ROOT variables.", 3, \ - 12, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0074, "find_package uses <PackageName>_ROOT variables.", \ + 3, 12, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0075, \ "Include file check macros honor CMAKE_REQUIRED_LIBRARIES.", 3, 12, \ 0, cmPolicies::WARN) \ diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index a25bd6b..ee44007 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -69,6 +69,7 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, bool haveLanguages = false; bool haveDescription = false; bool haveHomepage = false; + bool injectedProjectCommand = false; std::string version; std::string description; std::string homepage; @@ -160,6 +161,8 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, "by a value that expanded to nothing."); resetReporter(); }; + } else if (i == 1 && args[i] == "__CMAKE_INJECTED_PROJECT_COMMAND__") { + injectedProjectCommand = true; } else if (doing == DoingVersion) { doing = DoingLanguages; version = args[i]; @@ -280,8 +283,10 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, const char* v = this->Makefile->GetDefinition(i); if (v && *v) { if (cmp0048 == cmPolicies::WARN) { - vw += "\n "; - vw += i; + if (!injectedProjectCommand) { + vw += "\n "; + vw += i; + } } else { this->Makefile->AddDefinition(i, ""); } diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 97c3178..c030cda 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -242,6 +242,7 @@ add_RunCMake_test(math) add_RunCMake_test(message) add_RunCMake_test(option) add_RunCMake_test(project -DCMake_TEST_RESOURCES=${CMake_TEST_RESOURCES}) +add_RunCMake_test(project_injected) add_RunCMake_test(return) add_RunCMake_test(separate_arguments) add_RunCMake_test(set_property) diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_IMPORTED_TARGET.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_IMPORTED_TARGET.cmake index 1150568..24e7202 100644 --- a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_IMPORTED_TARGET.cmake +++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_IMPORTED_TARGET.cmake @@ -1,10 +1,12 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.12) project(FindPkgConfig_IMPORTED_TARGET C) find_package(PkgConfig REQUIRED) pkg_check_modules(NCURSES IMPORTED_TARGET QUIET ncurses) +message(STATUS "source: ${CMAKE_CURRENT_SOURCE_DIR} bin ${CMAKE_CURRENT_BINARY_DIR}") + if (NCURSES_FOUND) set(tgt PkgConfig::NCURSES) if (NOT TARGET ${tgt}) @@ -66,6 +68,16 @@ if (NOT TARGET PkgConfig::FakePackage1) message(FATAL_ERROR "No import target for fake package 1 with prefix path") endif() +# find targets in subdir and check their visibility +add_subdirectory(target_subdir) +if (TARGET PkgConfig::FakePackage1_dir) + message(FATAL_ERROR "imported target PkgConfig::FakePackage1_dir is visible outside it's directory") +endif() + +if (NOT TARGET PkgConfig::FakePackage1_global) + message(FATAL_ERROR "imported target PkgConfig::FakePackage1_global is not visible outside it's directory") +endif() + # And now do the same for the NO_CMAKE_ENVIRONMENT_PATH - ENV{CMAKE_PREFIX_PATH} # combination unset(CMAKE_PREFIX_PATH) diff --git a/Tests/RunCMake/FindPkgConfig/target_subdir/CMakeLists.txt b/Tests/RunCMake/FindPkgConfig/target_subdir/CMakeLists.txt new file mode 100644 index 0000000..2171ef6 --- /dev/null +++ b/Tests/RunCMake/FindPkgConfig/target_subdir/CMakeLists.txt @@ -0,0 +1,5 @@ +# a target with visibility only in this directory +pkg_check_modules(FakePackage1_dir REQUIRED QUIET IMPORTED_TARGET cmakeinternalfakepackage1) + +# the same with global visibility +pkg_check_modules(FakePackage1_global REQUIRED QUIET IMPORTED_TARGET GLOBAL cmakeinternalfakepackage1) diff --git a/Tests/RunCMake/find_package/CMP0074-WARN-stderr.txt b/Tests/RunCMake/find_package/CMP0074-WARN-stderr.txt index 27fbb86..fc08163 100644 --- a/Tests/RunCMake/find_package/CMP0074-WARN-stderr.txt +++ b/Tests/RunCMake/find_package/CMP0074-WARN-stderr.txt @@ -3,7 +3,7 @@ Foo_ROOT :<base>/foo/cmake_root ENV{Foo_ROOT} :<base>/foo/env_root + CMake Warning \(dev\) at CMP0074-common.cmake:[0-9]+ \(find_package\): - Policy CMP0074 is not set: find_package uses PackageName_ROOT variables. + Policy CMP0074 is not set: find_package uses <PackageName>_ROOT variables. Run "cmake --help-policy CMP0074" for policy details. Use the cmake_policy command to set the policy and suppress this warning. diff --git a/Tests/RunCMake/project_injected/CMP0048-WARN.cmake b/Tests/RunCMake/project_injected/CMP0048-WARN.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/project_injected/CMP0048-WARN.cmake diff --git a/Tests/RunCMake/project_injected/CMakeLists.txt b/Tests/RunCMake/project_injected/CMakeLists.txt new file mode 100644 index 0000000..1b4931b --- /dev/null +++ b/Tests/RunCMake/project_injected/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.12.2) # old enough to not set CMP0048 +# no project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/project_injected/RunCMakeTest.cmake b/Tests/RunCMake/project_injected/RunCMakeTest.cmake new file mode 100644 index 0000000..ba1a003 --- /dev/null +++ b/Tests/RunCMake/project_injected/RunCMakeTest.cmake @@ -0,0 +1,12 @@ +include(RunCMake) + +set(RunCMake_TEST_OPTIONS + # Simulate a previous CMake run that used `project(... VERSION ...)` + # in a non-injected call site. + -DCMAKE_PROJECT_VERSION:STATIC=1.2.3 + -DCMAKE_PROJECT_VERSION_MAJOR:STATIC=1 + -DCMAKE_PROJECT_VERSION_MINOR:STATIC=2 + -DCMAKE_PROJECT_VERSION_PATCH:STATIC=3 + ) +run_cmake(CMP0048-WARN) +unset(RunCMake_TEST_OPTIONS) |