library is always installed if the headers and CMake export file are present.
.. versionadded:: 3.7
- In addition to cmake language files, the ``EXPORT_ANDROID_MK`` mode maybe
+ In addition to cmake language files, the ``EXPORT_ANDROID_MK`` mode may be
used to specify an export to the android ndk build system. This mode
accepts the same options as the normal export mode. The Android
NDK supports the use of prebuilt libraries, both static and shared. This
.. code-block:: cmake
string(JSON <out-var> [ERROR_VARIABLE <error-variable>]
- LENGTH <json-string> <member|index> [<member|index> ...])
+ LENGTH <json-string> [<member|index> ...])
Get the length of an element in ``<json-string>`` at the location
given by the list of ``<member|index>`` arguments.
``INTERFACE``, ``PUBLIC``, or ``PRIVATE``, one or more base directories, and
files within those directories. The only acceptable type is ``HEADERS``. The
optional default file sets are named after their type. The target may not be a
-custom target.
+custom target or :prop_tgt:`FRAMEWORK` target.
Files in a ``PRIVATE`` or ``PUBLIC`` file set are marked as source files for
the purposes of IDE integration. Additionally, files in ``HEADERS`` file sets
Release versions do not have the development topic section of
the CMake Release Notes index page.
-Update ``.gitlab-ci.yml`` to drop the upload jobs from the
-packaging pipeline by renaming them to start in ``.``:
-
-.. code-block:: shell
-
- sed -i 's/^u:/.u:/' .gitlab-ci.yml
-
-Commit with a message such as::
-
- gitlab-ci: Drop package pipeline upload jobs for release branch
-
- The package pipeline for release versions should not upload packages
- automatically to our archive of nightly development versions.
-
Update ``Source/CMakeVersion.cmake`` to set the version to
``$major.$minor.0-rc0``:
git merge --no-ff release-$ver
Begin post-release development by restoring the development branch release
-note infrastructure, the nightly package pipeline upload jobs, and
-the version date from ``origin/master``:
+note infrastructure, and the version date from ``origin/master``:
.. code-block:: shell
git checkout origin/master -- \
Source/CMakeVersion.cmake Help/release/dev/0-sample-topic.rst
sed -i $'/^Releases/ i\\\n.. include:: dev.txt\\\n' Help/release/index.rst
- sed -i 's/^\.u:/u:/' .gitlab-ci.yml
Update ``Source/CMakeVersion.cmake`` to set the version to
``$major.$minor.$date``:
In CMake 3.18 and lower a dependency on the evaluated target of the above
generator expressions would always be added. CMake 3.19 and above prefer
to not add this dependency. This policy provides compatibility for projects
-that have not been updated to expect the new behavior.
+that have not been updated to expect the new behavior. The policy setting
+is recorded on each target when it is created, and decides whether generator
+expressions referencing that target imply a dependency on it.
The ``OLD`` behavior for this policy is to add a dependency on the evaluated
target for the above generator expressions. The ``NEW`` behavior of
.. versionadded:: 3.23
-List of the target's ``PRIVATE`` and ``PUBLIC`` header sets (i.e. all
-file sets with the type ``HEADERS``). Files listed in these file sets
-are treated as source files for the purpose of IDE integration.
-The files also have their :prop_sf:`HEADER_FILE_ONLY` property set to
-``TRUE``.
+Read-only list of the target's ``PRIVATE`` and ``PUBLIC`` header sets (i.e.
+all file sets with the type ``HEADERS``). Files listed in these file sets are
+treated as source files for the purpose of IDE integration. The files also
+have their :prop_sf:`HEADER_FILE_ONLY` property set to ``TRUE``.
-This property is normally only set by :command:`target_sources(FILE_SET)`
-rather than being manipulated directly.
+Header sets may be defined using the :command:`target_sources` command
+``FILE_SET`` option with type ``HEADERS``.
See also :prop_tgt:`HEADER_SET_<NAME>`, :prop_tgt:`HEADER_SET` and
:prop_tgt:`INTERFACE_HEADER_SETS`.
.. versionadded:: 3.23
-List of the target's ``INTERFACE`` and ``PUBLIC`` header sets (i.e. all
-file sets with the type ``HEADERS``). Files listed in these header sets
+Read-only list of the target's ``INTERFACE`` and ``PUBLIC`` header sets (i.e.
+all file sets with the type ``HEADERS``). Files listed in these header sets
can be installed with :command:`install(TARGETS)` and exported with
:command:`install(EXPORT)` and :command:`export`.
-This property is normally only set by :command:`target_sources(FILE_SET)`
-rather than being manipulated directly.
+Header sets may be defined using the :command:`target_sources` command
+``FILE_SET`` option with type ``HEADERS``.
See also :prop_tgt:`HEADER_SETS`.
* The :cpack_gen:`CPack NSIS Generator` now requires NSIS 3.03 or later.
+Updates
+=======
+
+Changes made since CMake 3.22.0 include the following.
+
3.22.1
------
-This version made no changes to documented features or interfaces.
-Some implementation updates were made to support ecosystem changes
-and/or fix regressions.
+* This version made no changes to documented features or interfaces.
+ Some implementation updates were made to support ecosystem changes
+ and/or fix regressions.
3.22.2
------
errors in existing projects. The fix has been reverted to restore
compatibility. The fix may be restored in a future version of CMake
via a policy.
+
+3.22.4
+------
+
+* This version made no changes to documented features or interfaces.
+ Some implementation updates were made to support ecosystem changes
+ and/or fix regressions.
Properties
----------
-* The :prop_tgt:`HEADER_SETS` and :prop_tgt:`INTERFACE_HEADER_SETS` target
- properties were added to list header sets associated with a target.
+* The :prop_tgt:`HEADER_SETS` and :prop_tgt:`INTERFACE_HEADER_SETS` read-only
+ target properties were added to list header sets associated with a target.
* The :prop_tgt:`HEADER_SET` and :prop_tgt:`HEADER_SET_<NAME>` target
properties were added to list files in the default header set
* :manual:`ccmake(1)` may now be enabled on Windows when building
CMake from source. This is experimental, and so is not included
in official distributions.
+
+Updates
+=======
+
+Changes made since CMake 3.23.0 include the following.
+
+3.23.1
+------
+
+* The :command:`target_sources` ``FILE_SET`` feature added in CMake 3.23.0
+ does not yet place header files properly in Apple :prop_tgt:`FRAMEWORK`
+ targets. Pending further work in a future version of CMake, it is now
+ an error to add a ``FILE_SET`` of type ``HEADERS`` to such targets on
+ Apple platforms.
+
+* The :prop_tgt:`HEADER_SETS` and :prop_tgt:`INTERFACE_HEADER_SETS` target
+ properties added in CMake 3.23.0 are now read-only records of the header
+ sets created by the :command:`target_sources` command.
CMAKE_CACHEFILE_DIR
-------------------
-The directory with the ``CMakeCache.txt`` file.
-
-This is the full path to the directory that has the ``CMakeCache.txt``
-file in it. This is the same as :variable:`CMAKE_BINARY_DIR`.
+This variable is used internally by CMake, and may not be set during
+the first configuration of a build tree. When it is set, it has the
+same value as :variable:`CMAKE_BINARY_DIR`. Use that variable instead.
cmake_dependent_option(<option> "<help_text>" <value> <depends> <force>)
- Makes ``<option>`` available to the user if ``<depends>`` is true. When
- ``<option>`` is available, the given ``<help_text>`` and initial ``<value>``
- are used. If the ``<depends>`` condition is not true, ``<option>`` will not be
- presented and will always have the value given by ``<force>``. Any value set by
- the user is preserved for when the option is presented again. In case ``<depends>``
- is a :ref:`semicolon-separated list <CMake Language Lists>`, all elements must
- be true in order to initialize ``<option>`` with ``<value>``.
+ Makes ``<option>`` available to the user if the
+ :ref:`semicolon-separated list <CMake Language Lists>` of conditions in
+ ``<depends>`` are all true. Otherwise, a local variable named ``<option>``
+ is set to ``<force>``.
+
+ When ``<option>`` is available, the given ``<help_text>`` and initial
+ ``<value>`` are used. Otherwise, any value set by the user is preserved for
+ when ``<depends>`` is satisfied in the future.
+
+ Note that the ``<option>`` variable only has a value which satisfies the
+ ``<depends>`` condition within the scope of the caller because it is a local
+ variable.
Example invocation:
Options are:
``OUTPUT_VARIABLE <output>``
- Set ``<output>`` variable with details about any error.
+ Set ``<output>`` variable with details about any error. If the check is
+ bypassed because it uses cached results from a previous call, the output
+ will be empty even if errors were present in the previous call.
``LANGUAGES <lang>...``
Check the linkers used for each of the specified languages.
+ If this option is not provided, the command checks all enabled languages.
``C``, ``CXX``, ``Fortran`` are supported.
For each language checked, two boolean cache variables are defined.
``CMAKE_<lang>_LINK_PIE_SUPPORTED``
- Set to ``YES`` if ``PIE`` is supported by the linker and ``NO`` otherwise.
+ Set to true if ``PIE`` is supported by the linker and false otherwise.
``CMAKE_<lang>_LINK_NO_PIE_SUPPORTED``
- Set to ``YES`` if ``NO_PIE`` is supported by the linker and ``NO`` otherwise.
+ Set to true if ``NO_PIE`` is supported by the linker and false otherwise.
Examples
^^^^^^^^
# no support at link time. Set cache variables to NO
set(CMAKE_${lang}_LINK_PIE_SUPPORTED NO CACHE INTERNAL "PIE (${lang})")
set(CMAKE_${lang}_LINK_NO_PIE_SUPPORTED NO CACHE INTERNAL "NO_PIE (${lang})")
- string (APPEND outputs "PIE and NO_PIE are not supported by linker for ${lang}")
+ string (APPEND outputs "PIE and NO_PIE are not supported by linker for ${lang}\n")
endif()
endforeach()
# In Windows the default installation of PostgreSQL uses that as part of the path.
# E.g C:\Program Files\PostgreSQL\8.4.
# Currently, the following version numbers are known to this module:
-# "13" "12" "11" "10" "9.6" "9.5" "9.4" "9.3" "9.2" "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0"
+# "14" "13" "12" "11" "10" "9.6" "9.5" "9.4" "9.3" "9.2" "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0"
#
# To use this variable just do something like this:
# set(PostgreSQL_ADDITIONAL_VERSIONS "9.2" "8.4.4")
set(PostgreSQL_KNOWN_VERSIONS ${PostgreSQL_ADDITIONAL_VERSIONS}
- "13" "12" "11" "10" "9.6" "9.5" "9.4" "9.3" "9.2" "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0")
+ "14" "13" "12" "11" "10" "9.6" "9.5" "9.4" "9.3" "9.2" "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0")
# Define additional search paths for root directories.
set( PostgreSQL_ROOT_DIRECTORIES
object code libraries (``lib`` or ``lib64``)
On Debian, this may be ``lib/<multiarch-tuple>`` when
- :variable:`CMAKE_INSTALL_PREFIX` is ``/``, ``/usr``, or ``/usr/local``.
+ :variable:`CMAKE_INSTALL_PREFIX` is ``/usr``.
``INCLUDEDIR``
C header files (``include``)
``OLDINCLUDEDIR``
if(__system_type_for_install STREQUAL "debian")
if(CMAKE_LIBRARY_ARCHITECTURE)
- if("${CMAKE_INSTALL_PREFIX}" STREQUAL "/"
- OR "${CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/?$"
- OR "${CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/local/?$")
+ if("${CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/?$")
set(_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}")
endif()
if(DEFINED _GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX
return()
endif()
# Normalize locale during test compilation.
- set(_locale_vars LC_ALL LC_MESSAGES LANG)
- foreach(v IN LISTS _locale_vars)
+ set(_CFCC_locale_vars LC_ALL LC_MESSAGES LANG)
+ foreach(v IN LISTS _CFCC_locale_vars)
set(_CMAKE_CHECK_FLAG_COMMON_CONFIG_locale_vars_saved_${v} "$ENV{${v}}")
set(ENV{${v}} C)
endforeach()
--- /dev/null
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+
+# Do NOT include this module directly into any of your code. It is used by
+# the try_compile() implementation to work around a specific issue with
+# conflicting flags when building for Apple platforms.
+if(NOT APPLE)
+ return()
+endif()
+
+cmake_policy(PUSH)
+cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced
+
+function(__cmake_internal_workaround_headerpad_flag_conflict _LANG)
+
+ # Until we can avoid hard-coding -Wl,-headerpad_max_install_names in the
+ # linker flags, we need to remove it here for cases where we know it will
+ # conflict with other flags, generate a warning and be ignored.
+ set(regex "(^| )(-fembed-bitcode(-marker|=(all|bitcode|marker))?|-bundle_bitcode)($| )")
+ set(remove_headerpad NO)
+
+ # Check arbitrary flags that the user or project has set. These compiler
+ # flags get added to the linker command line.
+ if("${CMAKE_${_LANG}_FLAGS}" MATCHES "${regex}")
+ set(remove_headerpad YES)
+ endif()
+ if(NOT remove_headerpad)
+ get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+ if(is_multi_config)
+ # Only one of these config-specific variables will be set by try_compile()
+ # and the rest will be unset, but we can't easily tell which one is set.
+ # No harm to just add them all here, empty ones won't add flags to check.
+ foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES)
+ if("${CMAKE_${_LANG}_FLAGS_${config}}" MATCHES "${regex}")
+ set(remove_headerpad YES)
+ break()
+ endif()
+ endforeach()
+ else()
+ if("${CMAKE_${_LANG}_FLAGS_${CMAKE_BUILD_TYPE}}" MATCHES "${regex}")
+ set(remove_headerpad YES)
+ endif()
+ endif()
+ endif()
+
+ # The try_compile() command passes compiler flags to check in a way that
+ # results in them being added to add_definitions(). Those don't end up on
+ # the linker command line, so we don't need to check them here.
+
+ if(remove_headerpad)
+ foreach(flag IN ITEMS
+ CMAKE_${_LANG}_LINK_FLAGS
+ CMAKE_SHARED_LIBRARY_CREATE_${_LANG}_FLAGS
+ CMAKE_SHARED_MODULE_CREATE_${_LANG}_FLAGS)
+ string(REPLACE "-Wl,-headerpad_max_install_names" "" ${flag} "${${flag}}")
+ set(${flag} "${${flag}}" PARENT_SCOPE)
+ endforeach()
+ endif()
+endfunction()
+
+get_property(__enabled_languages GLOBAL PROPERTY ENABLED_LANGUAGES)
+foreach(__lang IN LISTS __enabled_languages)
+ __cmake_internal_workaround_headerpad_flag_conflict(${__lang})
+endforeach()
+unset(__lang)
+unset(__enabled_languages)
+
+cmake_policy(POP)
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 23)
-set(CMake_VERSION_PATCH 0)
+set(CMake_VERSION_PATCH 1)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
if(NOT CMake_VERSION_NO_GIT)
# If this source was exported by 'git archive', use its commit info.
- set(git_info [==[00677703d0 CMake 3.23.0]==])
+ set(git_info [==[efe08e2894 CMake 3.23.1]==])
# Otherwise, try to identify the current development source version.
if(NOT git_info MATCHES "^([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]?[0-9a-f]?)[0-9a-f]* "
? "NEW"
: "OLD");
+ // Workaround for -Wl,-headerpad_max_install_names issue until we can avoid
+ // adding that flag in the platform and compiler language files
+ fprintf(fout,
+ "include(\"${CMAKE_ROOT}/Modules/Internal/"
+ "HeaderpadWorkaround.cmake\")\n");
+
if (targetType == cmStateEnums::EXECUTABLE) {
/* Put the executable at a known location (for COPY_FILE). */
fprintf(fout, "set(CMAKE_RUNTIME_OUTPUT_DIRECTORY \"%s\")\n",
#include <utility>
#include <vector>
+#include <cmext/string_view>
+
#include "cmsys/RegularExpression.hxx"
#include "cmGeneratorExpression.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmake.h"
-cmFileSet::cmFileSet(std::string name, std::string type)
+cm::static_string_view cmFileSetVisibilityToName(cmFileSetVisibility vis)
+{
+ switch (vis) {
+ case cmFileSetVisibility::Interface:
+ return "INTERFACE"_s;
+ case cmFileSetVisibility::Public:
+ return "PUBLIC"_s;
+ case cmFileSetVisibility::Private:
+ return "PRIVATE"_s;
+ }
+ return ""_s;
+}
+
+cmFileSetVisibility cmFileSetVisibilityFromName(cm::string_view name,
+ cmMakefile* mf)
+{
+ if (name == "INTERFACE"_s) {
+ return cmFileSetVisibility::Interface;
+ }
+ if (name == "PUBLIC"_s) {
+ return cmFileSetVisibility::Public;
+ }
+ if (name == "PRIVATE"_s) {
+ return cmFileSetVisibility::Private;
+ }
+ mf->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("File set visibility \"", name, "\" is not valid."));
+ return cmFileSetVisibility::Private;
+}
+
+bool cmFileSetVisibilityIsForSelf(cmFileSetVisibility vis)
+{
+ switch (vis) {
+ case cmFileSetVisibility::Interface:
+ return false;
+ case cmFileSetVisibility::Public:
+ case cmFileSetVisibility::Private:
+ return true;
+ }
+ return false;
+}
+
+bool cmFileSetVisibilityIsForInterface(cmFileSetVisibility vis)
+{
+ switch (vis) {
+ case cmFileSetVisibility::Interface:
+ case cmFileSetVisibility::Public:
+ return true;
+ case cmFileSetVisibility::Private:
+ return false;
+ }
+ return false;
+}
+
+cmFileSet::cmFileSet(std::string name, std::string type,
+ cmFileSetVisibility visibility)
: Name(std::move(name))
, Type(std::move(type))
+ , Visibility(visibility)
{
}
#include <string>
#include <vector>
+#include <cm/string_view>
+#include <cmext/string_view>
+
#include "cmListFileCache.h"
class cmCompiledGeneratorExpression;
struct cmGeneratorExpressionDAGChecker;
class cmGeneratorTarget;
class cmLocalGenerator;
+class cmMakefile;
+
+enum class cmFileSetVisibility
+{
+ Private,
+ Public,
+ Interface,
+};
+cm::static_string_view cmFileSetVisibilityToName(cmFileSetVisibility vis);
+cmFileSetVisibility cmFileSetVisibilityFromName(cm::string_view name,
+ cmMakefile* mf);
+bool cmFileSetVisibilityIsForSelf(cmFileSetVisibility vis);
+bool cmFileSetVisibilityIsForInterface(cmFileSetVisibility vis);
class cmFileSet
{
public:
- cmFileSet(std::string name, std::string type);
+ cmFileSet(std::string name, std::string type,
+ cmFileSetVisibility visibility);
const std::string& GetName() const { return this->Name; }
const std::string& GetType() const { return this->Type; }
+ cmFileSetVisibility GetVisibility() const { return this->Visibility; }
void ClearDirectoryEntries();
void AddDirectoryEntry(BT<std::string> directories);
private:
std::string Name;
std::string Type;
+ cmFileSetVisibility Visibility;
std::vector<BT<std::string>> DirectoryEntries;
std::vector<BT<std::string>> FileEntries;
};
static const std::array<std::string, 4> langs = { { "C", "CXX", "OBJC",
"OBJCXX" } };
- bool haveAnyPch = false;
+ std::set<std::string> pchLangSet;
if (this->GetGlobalGenerator()->IsXcode()) {
for (const std::string& lang : langs) {
const std::string pchHeader = target->GetPchHeader(config, lang, "");
if (!pchHeader.empty()) {
- haveAnyPch = true;
+ pchLangSet.emplace(lang);
}
}
}
const std::string pchHeader = target->GetPchHeader(config, lang, arch);
if (pchSource.empty() || pchHeader.empty()) {
- if (this->GetGlobalGenerator()->IsXcode() && haveAnyPch) {
+ if (this->GetGlobalGenerator()->IsXcode() && !pchLangSet.empty()) {
for (auto* sf : sources) {
- sf->SetProperty("SKIP_PRECOMPILE_HEADERS", "ON");
+ if (pchLangSet.find(sf->GetLanguage()) == pchLangSet.end()) {
+ sf->SetProperty("SKIP_PRECOMPILE_HEADERS", "ON");
+ }
}
}
continue;
compileObjectVars.Includes = includes.c_str();
// Rule for compiling object file.
- std::vector<std::string> compileCmds;
+ std::string cudaCompileMode;
if (language == "CUDA") {
- std::string cmdVar;
if (this->GeneratorTarget->GetPropertyAsBool(
"CUDA_SEPARABLE_COMPILATION")) {
- cmdVar = "CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION";
- } else if (this->GeneratorTarget->GetPropertyAsBool(
- "CUDA_PTX_COMPILATION")) {
- cmdVar = "CMAKE_CUDA_COMPILE_PTX_COMPILATION";
+ const std::string& rdcFlag =
+ this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_RDC_FLAG");
+ cudaCompileMode = cmStrCat(cudaCompileMode, rdcFlag, " ");
+ }
+ if (this->GeneratorTarget->GetPropertyAsBool("CUDA_PTX_COMPILATION")) {
+ const std::string& ptxFlag =
+ this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_PTX_FLAG");
+ cudaCompileMode = cmStrCat(cudaCompileMode, ptxFlag);
} else {
- cmdVar = "CMAKE_CUDA_COMPILE_WHOLE_COMPILATION";
+ const std::string& wholeFlag =
+ this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_WHOLE_FLAG");
+ cudaCompileMode = cmStrCat(cudaCompileMode, wholeFlag);
}
- const std::string& compileCmd =
- this->GetMakefile()->GetRequiredDefinition(cmdVar);
- cmExpandList(compileCmd, compileCmds);
- } else {
- const std::string cmdVar = cmStrCat("CMAKE_", language, "_COMPILE_OBJECT");
- const std::string& compileCmd =
- this->GetMakefile()->GetRequiredDefinition(cmdVar);
- cmExpandList(compileCmd, compileCmds);
+ compileObjectVars.CudaCompileMode = cudaCompileMode.c_str();
}
+ std::vector<std::string> compileCmds;
+ const std::string cmdVar = cmStrCat("CMAKE_", language, "_COMPILE_OBJECT");
+ const std::string& compileCmd =
+ this->Makefile->GetRequiredDefinition(cmdVar);
+ cmExpandList(compileCmd, compileCmds);
+
std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
this->GetLocalGenerator()->CreateRulePlaceholderExpander());
BT<std::string>(value, this->impl->Makefile->GetBacktrace()));
}
} else if (prop == propHEADER_SETS) {
- if (value) {
- for (auto const& name : cmExpandedList(value)) {
- if (!this->GetFileSet(name)) {
- this->impl->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat("Header set \"", name, "\" has not yet been created."));
- return;
- }
- }
- }
- this->impl->HeaderSetsEntries.clear();
- if (!StringIsEmpty(value)) {
- this->impl->HeaderSetsEntries.emplace_back(
- value, this->impl->Makefile->GetBacktrace());
- }
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "HEADER_SETS property is read-only\n");
+ return;
} else if (prop == propINTERFACE_HEADER_SETS) {
- if (value) {
- for (auto const& name : cmExpandedList(value)) {
- if (!this->GetFileSet(name)) {
- this->impl->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat("Header set \"", name, "\" has not yet been created."));
- return;
- }
- }
- }
- this->impl->InterfaceHeaderSetsEntries.clear();
- if (!StringIsEmpty(value)) {
- this->impl->InterfaceHeaderSetsEntries.emplace_back(
- value, this->impl->Makefile->GetBacktrace());
- }
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "INTERFACE_HEADER_SETS property is read-only\n");
+ return;
} else {
this->impl->Properties.SetProperty(prop, value);
}
fileSet->AddFileEntry(
BT<std::string>(value, this->impl->Makefile->GetBacktrace()));
} else if (prop == "HEADER_SETS") {
- for (auto const& name : cmExpandedList(value)) {
- if (!this->GetFileSet(name)) {
- this->impl->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat("Header set \"", name, "\" has not yet been created."));
- return;
- }
- }
- this->impl->HeaderSetsEntries.emplace_back(
- value, this->impl->Makefile->GetBacktrace());
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "HEADER_SETS property is read-only\n");
+ return;
} else if (prop == "INTERFACE_HEADER_SETS") {
- for (auto const& name : cmExpandedList(value)) {
- if (!this->GetFileSet(name)) {
- this->impl->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat("Header set \"", name, "\" has not yet been created."));
- return;
- }
- }
- this->impl->InterfaceHeaderSetsEntries.emplace_back(
- value, this->impl->Makefile->GetBacktrace());
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "INTERFACE_HEADER_SETS property is read-only\n");
+ return;
} else {
this->impl->Properties.AppendProperty(prop, value, asString);
}
return cmValue(output);
}
if (prop == propHEADER_SETS) {
+ std::vector<std::string> set_names;
+ for (auto const& file_set : this->impl->FileSets) {
+ if (cmFileSetVisibilityIsForSelf(file_set.second.GetVisibility())) {
+ set_names.push_back(file_set.second.GetName());
+ }
+ }
static std::string output;
- output = cmJoin(this->impl->HeaderSetsEntries, ";"_s);
+ output = cmJoin(set_names, ";"_s);
return cmValue(output);
}
if (prop == propINTERFACE_HEADER_SETS) {
+ std::vector<std::string> set_names;
+ for (auto const& file_set : this->impl->FileSets) {
+ if (cmFileSetVisibilityIsForInterface(
+ file_set.second.GetVisibility())) {
+ set_names.push_back(file_set.second.GetName());
+ }
+ }
static std::string output;
- output = cmJoin(this->impl->InterfaceHeaderSetsEntries, ";"_s);
+ output = cmJoin(set_names, ";"_s);
return cmValue(output);
}
}
}
std::pair<cmFileSet*, bool> cmTarget::GetOrCreateFileSet(
- const std::string& name, const std::string& type)
+ const std::string& name, const std::string& type, cmFileSetVisibility vis)
{
- auto result =
- this->impl->FileSets.emplace(std::make_pair(name, cmFileSet(name, type)));
+ auto result = this->impl->FileSets.emplace(
+ std::make_pair(name, cmFileSet(name, type, vis)));
+ if (result.second) {
+ if (cmFileSetVisibilityIsForSelf(vis)) {
+ this->impl->HeaderSetsEntries.emplace_back(
+ name, this->impl->Makefile->GetBacktrace());
+ }
+ if (cmFileSetVisibilityIsForInterface(vis)) {
+ this->impl->InterfaceHeaderSetsEntries.emplace_back(
+ name, this->impl->Makefile->GetBacktrace());
+ }
+ }
return std::make_pair(&result.first->second, result.second);
}
#include <vector>
#include "cmAlgorithms.h"
+#include "cmFileSet.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmValue.h"
class cmCustomCommand;
-class cmFileSet;
class cmGlobalGenerator;
class cmInstallTargetGenerator;
class cmListFileBacktrace;
const cmFileSet* GetFileSet(const std::string& name) const;
cmFileSet* GetFileSet(const std::string& name);
std::pair<cmFileSet*, bool> GetOrCreateFileSet(const std::string& name,
- const std::string& type);
+ const std::string& type,
+ cmFileSetVisibility vis);
std::vector<std::string> GetAllInterfaceFileSets() const;
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTargetSourcesCommand.h"
-#include <algorithm>
#include <sstream>
#include <utility>
this->SetError("FILE_SETs may not be added to custom targets");
return false;
}
+ if (this->Target->IsFrameworkOnApple()) {
+ this->SetError("FILE_SETs may not be added to FRAMEWORK targets");
+ return false;
+ }
bool const isDefault = args.Type == args.FileSet ||
(args.Type.empty() && args.FileSet[0] >= 'A' && args.FileSet[0] <= 'Z');
std::string type = isDefault ? args.FileSet : args.Type;
- auto fileSet = this->Target->GetOrCreateFileSet(args.FileSet, type);
+ cmFileSetVisibility visibility =
+ cmFileSetVisibilityFromName(scope, this->Makefile);
+
+ auto fileSet =
+ this->Target->GetOrCreateFileSet(args.FileSet, type, visibility);
if (fileSet.second) {
if (!isDefault) {
if (!cmFileSet::IsValidName(args.FileSet)) {
if (args.BaseDirs.empty()) {
args.BaseDirs.emplace_back(this->Makefile->GetCurrentSourceDirectory());
}
-
- if (scope == "PRIVATE"_s || scope == "PUBLIC"_s) {
- this->Target->AppendProperty(cmTarget::GetFileSetsPropertyName(type),
- args.FileSet);
- }
- if (scope == "INTERFACE"_s || scope == "PUBLIC"_s) {
- this->Target->AppendProperty(
- cmTarget::GetInterfaceFileSetsPropertyName(type), args.FileSet);
- }
} else {
type = fileSet.first->GetType();
if (!args.Type.empty() && args.Type != type) {
return false;
}
- std::string existingScope = "PRIVATE";
-
- auto const fileSetsProperty = cmTarget::GetFileSetsPropertyName(type);
- auto const interfaceFileSetsProperty =
- cmTarget::GetInterfaceFileSetsPropertyName(type);
- std::vector<std::string> fileSets;
- std::vector<std::string> interfaceFileSets;
- cmExpandList(this->Target->GetSafeProperty(fileSetsProperty), fileSets);
- cmExpandList(this->Target->GetSafeProperty(interfaceFileSetsProperty),
- interfaceFileSets);
-
- if (std::find(interfaceFileSets.begin(), interfaceFileSets.end(),
- args.FileSet) != interfaceFileSets.end()) {
- existingScope = "INTERFACE";
- }
- if (std::find(fileSets.begin(), fileSets.end(), args.FileSet) !=
- fileSets.end()) {
- if (existingScope == "INTERFACE"_s) {
- existingScope = "PUBLIC";
- }
- } else if (existingScope != "INTERFACE"_s) {
- this->SetError(cmStrCat("File set \"", args.FileSet, "\" is not in ",
- fileSetsProperty, " or ",
- interfaceFileSetsProperty));
- return false;
- }
-
- if (scope != existingScope) {
+ if (visibility != fileSet.first->GetVisibility()) {
this->SetError(
cmStrCat("Scope ", scope, " for file set \"", args.FileSet,
- "\" does not match original scope ", existingScope));
+ "\" does not match original scope ",
+ cmFileSetVisibilityToName(fileSet.first->GetVisibility())));
return false;
}
}
for (auto const& dir : cmExpandedList(baseDirectories)) {
auto interfaceDirectoriesGenex =
cmStrCat("$<BUILD_INTERFACE:", dir, ">");
- if (scope == "PRIVATE"_s || scope == "PUBLIC"_s) {
+ if (cmFileSetVisibilityIsForSelf(visibility)) {
this->Target->AppendProperty("INCLUDE_DIRECTORIES",
interfaceDirectoriesGenex);
}
- if (scope == "INTERFACE"_s || scope == "PUBLIC"_s) {
+ if (cmFileSetVisibilityIsForInterface(visibility)) {
this->Target->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES",
interfaceDirectoriesGenex);
}
parsedArgs.emplace_back("--find-package");
return true;
} },
- CommandArgument{ "--list-presets", CommandArgument::Values::Zero,
- [&](std::string const&) -> bool {
+ CommandArgument{ "--list-presets", CommandArgument::Values::ZeroOrOne,
+ [&](std::string const& value) -> bool {
workingMode = cmake::HELP_MODE;
parsedArgs.emplace_back("--list-presets");
+ parsedArgs.emplace_back(value);
return true;
} },
};
cmake_minimum_required(VERSION 3.18)
project(WithDefs CUDA)
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+
set(release_compile_defs DEFREL)
#Goal for this example:
--- /dev/null
+^Not searching for unused variables given on the command line\.
+Available configure presets:
+
+ "zzzzzz" - Sleepy
+ "aaaaaaaa" - Screaming
+ "mmmmmm"
+ "no-generator"$
set(_unused_cli)
endif()
+ set(_preset "--preset=${name}")
+ if(CMakePresets_NO_PRESET)
+ set(_preset)
+ endif()
+
set(RunCMake_TEST_COMMAND ${CMAKE_COMMAND}
${_source_args}
-DRunCMake_TEST=${name}
-DRunCMake_GENERATOR=${RunCMake_GENERATOR}
-DCMAKE_MAKE_PROGRAM=${RunCMake_MAKE_PROGRAM}
${_unused_cli}
- --preset=${name}
+ ${_preset}
${ARGN}
)
run_cmake(${name})
set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/ListPresetsWorkingDir")
set(RunCMake_TEST_NO_CLEAN 1)
set(CMakePresets_NO_SOURCE_ARGS 1)
+set(CMakePresets_NO_PRESET 1)
run_cmake_presets(ListPresetsWorkingDir --list-presets)
+run_cmake_presets(ListConfigurePresetsWorkingDir --list-presets=configure)
+unset(CMakePresets_NO_PRESET)
unset(CMakePresets_NO_SOURCE_ARGS)
unset(RunCMake_TEST_NO_CLEAN)
unset(RunCMake_TEST_BINARY_DIR)
set(C 1) # test that this is tolerated
+# test that the check uses an isolated locale
+set(_env_LC_ALL "${LC_ALL}")
+set(ENV{LC_ALL} "BAD")
+
check_compiler_flag(C "-_this_is_not_a_flag_" SHOULD_FAIL)
if(SHOULD_FAIL)
message(SEND_ERROR "invalid C compile flag didn't fail.")
message(SEND_ERROR "${CMAKE_C_COMPILER_ID} compiler flag '-frtti' check passed but should have failed")
endif()
endif()
+
+if(NOT "$ENV{LC_ALL}" STREQUAL "BAD")
+ message(SEND_ERROR "ENV{LC_ALL} was not preserved by check_compiler_flag")
+endif()
+set(ENV{LC_ALL} ${_env_LC_ALL})
set(CXX 1) # test that this is tolerated
+# test that the check uses an isolated locale
+set(_env_LC_ALL "${LC_ALL}")
+set(ENV{LC_ALL} "BAD")
+
check_compiler_flag(CXX "-_this_is_not_a_flag_" SHOULD_FAIL)
if(SHOULD_FAIL)
message(SEND_ERROR "invalid CXX compile flag didn't fail.")
message(SEND_ERROR "${CMAKE_CXX_COMPILER_ID} compiler flag '-x c++' check failed")
endif()
endif()
+
+if(NOT "$ENV{LC_ALL}" STREQUAL "BAD")
+ message(SEND_ERROR "ENV{LC_ALL} was not preserved by check_compiler_flag")
+endif()
+set(ENV{LC_ALL} ${_env_LC_ALL})
--- /dev/null
+enable_language(C)
+
+include(CheckCompilerFlag)
+
+# Confirm we can check the conflicting flag directly. This should pass with
+# or without the workaround.
+check_compiler_flag(C "-fembed-bitcode" result1)
+if(NOT result1)
+ message(FATAL_ERROR "False negative when -fembed-bitcode tested directly")
+endif()
+
+# Check conflicting flag set by user or project won't cause a false negative
+# when testing a valid flag. This only passes with the workaround.
+set(CMAKE_C_FLAGS -fembed-bitcode)
+check_compiler_flag(C "-O" result2)
+if(NOT result2)
+ message(FATAL_ERROR "False negative when -fembed-bitcode set in CMAKE_C_FLAGS")
+endif()
if(CMake_TEST_HIP)
run_cmake(CheckHIPCompilerFlag)
endif()
+
+if(APPLE)
+ run_cmake_with_options(HeaderpadWorkaround --debug-trycompile)
+endif()
CMAKE_INSTALL_DOCDIR='usr/share/doc/Root'
CMAKE_INSTALL_INCLUDEDIR='usr/include'
CMAKE_INSTALL_INFODIR='usr/share/info'
-CMAKE_INSTALL_LIBDIR='usr/lib/arch'
+CMAKE_INSTALL_LIBDIR='usr/lib'
CMAKE_INSTALL_LIBEXECDIR='usr/libexec'
CMAKE_INSTALL_LOCALEDIR='usr/share/locale'
CMAKE_INSTALL_LOCALSTATEDIR='var'
CMAKE_INSTALL_FULL_DOCDIR='/usr/share/doc/Root'
CMAKE_INSTALL_FULL_INCLUDEDIR='/usr/include'
CMAKE_INSTALL_FULL_INFODIR='/usr/share/info'
-CMAKE_INSTALL_FULL_LIBDIR='/usr/lib/arch'
+CMAKE_INSTALL_FULL_LIBDIR='/usr/lib'
CMAKE_INSTALL_FULL_LIBEXECDIR='/usr/libexec'
CMAKE_INSTALL_FULL_LOCALEDIR='/usr/share/locale'
CMAKE_INSTALL_FULL_LOCALSTATEDIR='/var'
CMAKE_INSTALL_DOCDIR='share/doc/UsrLocal'
CMAKE_INSTALL_INCLUDEDIR='include'
CMAKE_INSTALL_INFODIR='share/info'
-CMAKE_INSTALL_LIBDIR='lib/arch'
+CMAKE_INSTALL_LIBDIR='lib'
CMAKE_INSTALL_LIBEXECDIR='libexec'
CMAKE_INSTALL_LOCALEDIR='share/locale'
CMAKE_INSTALL_LOCALSTATEDIR='var'
CMAKE_INSTALL_FULL_DOCDIR='/usr/local/share/doc/UsrLocal'
CMAKE_INSTALL_FULL_INCLUDEDIR='/usr/local/include'
CMAKE_INSTALL_FULL_INFODIR='/usr/local/share/info'
-CMAKE_INSTALL_FULL_LIBDIR='/usr/local/lib/arch'
+CMAKE_INSTALL_FULL_LIBDIR='/usr/local/lib'
CMAKE_INSTALL_FULL_LIBEXECDIR='/usr/local/libexec'
CMAKE_INSTALL_FULL_LOCALEDIR='/usr/local/share/locale'
CMAKE_INSTALL_FULL_LOCALSTATEDIR='/usr/local/var'
--- /dev/null
+cmake_minimum_required(VERSION 3.16)
+project(PchIncludedAllLanguages C CXX)
+
+if(CMAKE_CXX_COMPILE_OPTIONS_USE_PCH)
+ add_definitions(-DHAVE_PCH_SUPPORT)
+endif()
+
+add_executable(main
+ main.cpp
+ empty.c
+ pch-included.cpp
+)
+
+target_precompile_headers(main PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${CMAKE_CURRENT_SOURCE_DIR}/pch.h>)
+
+enable_testing()
+add_test(NAME main COMMAND main)
endif()
run_test(PchReuseFromObjLib)
run_test(PchIncludedAllLanguages)
+run_test(PchIncludedOneLanguage)
run_test(PchLibObjLibExe)
"|[^\n]*install_name_tool: warning: changes being made to the file will invalidate the code signature in:"
"|[^\n]*xcodebuild[^\n]*DVTPlugInManager"
"|[^\n]*xcodebuild[^\n]*warning: file type[^\n]*is based on missing file type"
- "|[^\n]*objc[^\n]*: Class AMSupportURL[^\n]* One of the two will be used. Which one is undefined."
+ "|[^\n]*objc[^\n]*: Class [^\n]* One of the two will be used. Which one is undefined."
"|[^\n]*is a member of multiple groups"
"|[^\n]*offset in archive not a multiple of 8"
"|[^\n]*from Time Machine by path"
--- /dev/null
+^CMake Error at FileSetFramework\.cmake:[0-9]+ \(target_sources\):
+ target_sources FILE_SETs may not be added to FRAMEWORK targets
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
--- /dev/null
+enable_language(C)
+
+add_library(lib1 SHARED lib1.c)
+set_property(TARGET lib1 PROPERTY FRAMEWORK ON)
+target_sources(lib1
+ PUBLIC FILE_SET HEADERS BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} FILES h1.h
+ )
include("${export_build_dir}/install/lib/cmake/export.cmake")
assert_prop_eq(export::lib1 HEADER_SETS "")
-assert_prop_eq(export::lib1 INTERFACE_HEADER_SETS "HEADERS;b;c;d;e;f;g;dir3")
+assert_prop_eq(export::lib1 INTERFACE_HEADER_SETS "HEADERS;b;c;d;dir3;e;f;g")
assert_prop_eq(export::lib1 HEADER_SET "${CMAKE_CURRENT_SOURCE_DIR}/error.c")
assert_prop_eq(export::lib1 HEADER_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")
assert_prop_eq(export::lib1 HEADER_SET_b "${CMAKE_CURRENT_SOURCE_DIR}/h2.h")
assert_prop_eq(export::lib1 INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR};$<1:${CMAKE_CURRENT_SOURCE_DIR}/dir>;${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/$<IF:$<CONFIG:Debug>,debug,release>;${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/dir1;${CMAKE_CURRENT_SOURCE_DIR}/dir2;${CMAKE_CURRENT_SOURCE_DIR}/dir3;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:$<1:${CMAKE_CURRENT_SOURCE_DIR}/dir>>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/$<IF:$<CONFIG:Debug>,debug,release>>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir1>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir2>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir3>")
assert_prop_eq(install::lib1 HEADER_SETS "")
-assert_prop_eq(install::lib1 INTERFACE_HEADER_SETS "HEADERS;b;c;d;e;f;g;dir3")
+assert_prop_eq(install::lib1 INTERFACE_HEADER_SETS "HEADERS;b;c;d;dir3;e;f;g")
assert_prop_eq(install::lib1 HEADER_SET "${export_build_dir}/install/include/error.c")
assert_prop_eq(install::lib1 HEADER_DIRS "${export_build_dir}/install/include")
assert_prop_eq(install::lib1 HEADER_SET_b "${export_build_dir}/install/include/h2.h")
+++ /dev/null
-^CMake Error at FileSetNoExistInterface\.cmake:[0-9]+ \(set_property\):
- Header set "a" has not yet been created\.
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)$
+++ /dev/null
-^CMake Error at FileSetNoExistPrivate\.cmake:[0-9]+ \(set_property\):
- Header set "a" has not yet been created\.
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)$
+++ /dev/null
-enable_language(C)
-
-add_library(lib1 STATIC empty.c)
-set_property(TARGET lib1 PROPERTY HEADER_SETS "a")
-
-# Error happens at configure-time, so this doesn't help.
-target_sources(lib1 PRIVATE FILE_SET a TYPE HEADERS)
+++ /dev/null
-^CMake Error at FileSetNoScope\.cmake:[0-9]+ \(target_sources\):
- target_sources File set "a" is not in HEADER_SETS or INTERFACE_HEADER_SETS
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)$
+++ /dev/null
-enable_language(C)
-
-add_library(lib1 STATIC empty.c)
-target_sources(lib1 PRIVATE FILE_SET a TYPE HEADERS BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} FILES h1.h)
-set_property(TARGET lib1 PROPERTY HEADER_SETS)
-target_sources(lib1 PRIVATE FILE_SET a TYPE HEADERS FILES h2.h)
assert_prop_eq(lib1 INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/.>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>")
target_sources(lib1 PUBLIC FILE_SET HEADERS BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}" FILES h1.h)
-assert_prop_eq(lib1 INTERFACE_HEADER_SETS "a;c;d;HEADERS")
+assert_prop_eq(lib1 INTERFACE_HEADER_SETS "HEADERS;a;c;d")
assert_prop_eq(lib1 HEADER_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")
assert_prop_eq(lib1 HEADER_SET "${CMAKE_CURRENT_SOURCE_DIR}/h1.h")
assert_prop_eq(lib1 INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/.>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>")
assert_prop_eq(lib1 INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/.>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>")
target_sources(lib1 PUBLIC FILE_SET HEADERS FILES h2.h)
-assert_prop_eq(lib1 INTERFACE_HEADER_SETS "a;c;d;HEADERS")
+assert_prop_eq(lib1 INTERFACE_HEADER_SETS "HEADERS;a;c;d")
assert_prop_eq(lib1 HEADER_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")
assert_prop_eq(lib1 HEADER_SET "${CMAKE_CURRENT_SOURCE_DIR}/h1.h;${CMAKE_CURRENT_SOURCE_DIR}/h2.h")
assert_prop_eq(lib1 INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/.>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>")
--- /dev/null
+^CMake Error at FileSetReadOnlyInterface\.cmake:[0-9]+ \(set_property\):
+ INTERFACE_HEADER_SETS property is read-only
+
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
add_library(lib1 STATIC empty.c)
set_property(TARGET lib1 PROPERTY INTERFACE_HEADER_SETS "a")
-
-# Error happens at configure-time, so this doesn't help.
-target_sources(lib1 INTERFACE FILE_SET a TYPE HEADERS)
--- /dev/null
+^CMake Error at FileSetReadOnlyPrivate\.cmake:[0-9]+ \(set_property\):
+ HEADER_SETS property is read-only
+
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
--- /dev/null
+enable_language(C)
+
+add_library(lib1 STATIC empty.c)
+set_property(TARGET lib1 PROPERTY HEADER_SETS "a")
run_cmake(FileSetOverlappingBaseDirs)
run_cmake(FileSetInstallMissingSetsPrivate)
run_cmake(FileSetInstallMissingSetsInterface)
-run_cmake(FileSetNoScope)
-run_cmake(FileSetNoExistPrivate)
-run_cmake(FileSetNoExistInterface)
+run_cmake(FileSetReadOnlyPrivate)
+run_cmake(FileSetReadOnlyInterface)
run_cmake(FileSetNoExistInstall)
run_cmake(FileSetDirectories)
run_cmake(FileSetCustomTarget)
run_cmake(FileSetBadName)
+if(APPLE)
+ run_cmake(FileSetFramework)
+endif()
set(RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0115=NEW)
run_cmake(FileSetFileNoExist)
SPHINX_HTML:BOOL=ON
SPHINX_MAN:BOOL=ON
SPHINX_QTHELP:BOOL=ON
-QCOLLECTIONGENERATOR_EXECUTABLE:PATH=/opt/qt/bin/qhelpgenerator
+QHELPGENERATOR_EXECUTABLE:PATH=/opt/qt/bin/qhelpgenerator
# We bootstrap as part of the build so skip its test.
CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE
SPHINX_HTML:BOOL=ON
SPHINX_MAN:BOOL=ON
SPHINX_QTHELP:BOOL=ON
-QCOLLECTIONGENERATOR_EXECUTABLE:PATH=/opt/qt/bin/qhelpgenerator
+QHELPGENERATOR_EXECUTABLE:PATH=/opt/qt/bin/qhelpgenerator
# We bootstrap as part of the build so skip its test.
CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE
SPHINX_HTML:BOOL=ON
SPHINX_MAN:BOOL=ON
SPHINX_QTHELP:BOOL=ON
-QCOLLECTIONGENERATOR_EXECUTABLE:PATH=C:/qt-i386/bin/qhelpgenerator.exe
+QHELPGENERATOR_EXECUTABLE:PATH=C:/qt-i386/bin/qhelpgenerator.exe
# No bootstrap with MSVC tools.
CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE
SPHINX_HTML:BOOL=ON
SPHINX_MAN:BOOL=ON
SPHINX_QTHELP:BOOL=ON
-QCOLLECTIONGENERATOR_EXECUTABLE:PATH=C:/qt-x86_64/bin/qhelpgenerator.exe
+QHELPGENERATOR_EXECUTABLE:PATH=C:/qt-x86_64/bin/qhelpgenerator.exe
# No bootstrap with MSVC tools.
CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE
set(conf_copyright "Kitware, Inc.")
endif()
+if(CMake_SPHINX_CMAKE_ORG)
+ set(conf_baseurl "https://cmake.org/cmake/help/latest")
+else()
+ set(conf_baseurl "")
+endif()
+
set(conf_docs "${CMake_SOURCE_DIR}/Help")
set(conf_path "${CMAKE_CURRENT_SOURCE_DIR}")
set(conf_version "${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH}")
if(SPHINX_QTHELP)
find_package(PythonInterp REQUIRED)
- find_program(QCOLLECTIONGENERATOR_EXECUTABLE
- NAMES qcollectiongenerator-qt5 qcollectiongenerator
- DOC "qcollectiongenerator tool"
+ find_program(QHELPGENERATOR_EXECUTABLE
+ NAMES qhelpgenerator-qt5 qhelpgenerator
+ DOC "qhelpgenerator tool"
)
- if (NOT QCOLLECTIONGENERATOR_EXECUTABLE)
- message(FATAL_ERROR "QCOLLECTIONGENERATOR_EXECUTABLE (qcollectiongenerator) not found!")
+ if(NOT QHELPGENERATOR_EXECUTABLE)
+ message(FATAL_ERROR "QHELPGENERATOR_EXECUTABLE (qhelpgenerator) not found!")
endif()
list(APPEND doc_formats qthelp)
"${CMAKE_CURRENT_SOURCE_DIR}/create_identifiers.py"
"${CMAKE_CURRENT_BINARY_DIR}/qthelp/"
- COMMAND ${QCOLLECTIONGENERATOR_EXECUTABLE}
+ COMMAND ${QHELPGENERATOR_EXECUTABLE}
${CMAKE_CURRENT_BINARY_DIR}/qthelp/CMake.qhcp
)
endif()
list(APPEND doc_formats latexpdf)
endif()
+set(doc_html_opts "")
+if(CMake_SPHINX_CMAKE_ORG)
+ list(APPEND doc_html_opts
+ -A googleanalytics=1
+ -A opensearch=1
+ -A versionswitch=1
+ )
+
+ if(CMake_SPHINX_CMAKE_ORG_OUTDATED)
+ list(APPEND doc_html_opts -A outdated=1)
+ endif()
+
+ list(APPEND qthelp_extra_commands
+ COMMAND ${CMAKE_COMMAND} -E copy
+ "${CMAKE_CURRENT_BINARY_DIR}/qthelp/CMake.qch"
+ "${CMAKE_CURRENT_BINARY_DIR}/html/CMake.qch"
+ )
+endif()
+
set(doc_format_outputs "")
set(doc_format_last "")
foreach(format ${doc_formats})
set(doc_format_output "doc_format_${format}")
set(doc_format_log "build-${format}.log")
+ if(CMake_SPHINX_CMAKE_ORG)
+ set(doctrees "doctrees/${format}")
+ else()
+ set(doctrees "doctrees")
+ endif()
if(format STREQUAL "latexpdf")
# This format does not use builder (-b) but make_mode (-M) which expects
# arguments in peculiar order
${CMake_SOURCE_DIR}/Help
${CMAKE_CURRENT_BINARY_DIR}/${format}
-c ${CMAKE_CURRENT_BINARY_DIR}
- -d ${CMAKE_CURRENT_BINARY_DIR}/doctrees
+ -d ${CMAKE_CURRENT_BINARY_DIR}/${doctrees}
${sphinx_flags}
+ ${doc_${format}_opts}
> ${doc_format_log} # log stdout, pass stderr
${${format}_extra_commands}
DEPENDS ${doc_format_last}
OUTPUT ${doc_format_output}
COMMAND ${SPHINX_EXECUTABLE}
-c ${CMAKE_CURRENT_BINARY_DIR}
- -d ${CMAKE_CURRENT_BINARY_DIR}/doctrees
+ -d ${CMAKE_CURRENT_BINARY_DIR}/${doctrees}
-b ${format}
${sphinx_flags}
+ ${doc_${format}_opts}
${CMake_SOURCE_DIR}/Help
${CMAKE_CURRENT_BINARY_DIR}/${format}
> ${doc_format_log} # log stdout, pass stderr
endif()
set_property(SOURCE ${doc_format_output} PROPERTY SYMBOLIC 1)
list(APPEND doc_format_outputs ${doc_format_output})
- set(doc_format_last ${doc_format_output})
+ if(NOT CMake_SPHINX_CMAKE_ORG)
+ set(doc_format_last ${doc_format_output})
+ endif()
endforeach()
add_custom_target(documentation ALL DEPENDS ${doc_format_outputs})
endforeach()
endif()
+if(CMake_SPHINX_CMAKE_ORG)
+ return()
+endif()
+
if(SPHINX_INFO)
CMake_OPTIONAL_COMPONENT(sphinx-info)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/texinfo/cmake.info
man_show_urls = False
man_make_section_directory = False
+html_baseurl = '@conf_baseurl@'
html_show_sourcelink = True
html_static_path = ['@conf_path@/static']
html_style = 'cmake.css'
dd > :first-child > p {
margin-top: 0px;
}
+
+div.outdated {
+ background-color: #f0f0c0;
+ color: black;
+ font-size: 90%;
+ padding-bottom: 5px;
+ padding-left: 2px;
+ padding-right: 2px;
+ padding-top: 5px;
+ text-align: center;
+ width: 100%;
+}
</li>
{% endblock %}
+{%- block relbar1 %}
+{{ super() }}
+{%- if outdated is defined %}
+ <div class="outdated">
+ This documents an old version of CMake.
+ <a href="https://cmake.org/cmake/help/latest/{{ pagename }}.html">
+ Click here to see the latest release.
+ </a>
+ <span class="version_switch_note"></span>
+ </div>
+{%- endif %}
+{%- endblock %}
+
{% block extrahead %}
- {% if versionswitch is defined %}
- <script type="text/javascript" src="{{ pathto('../version_switch.js', 1) }}"></script>
- {% endif %}
+ {%- if opensearch is defined %}
+ <link rel="search" type="application/opensearchdescription+xml"
+ title="Search within CMake Documentation of Latest Version"
+ href="{{ pathto('../latest-opensearch.xml', 1) }}"/>
+ {%- endif %}
+ {%- if versionswitch is defined %}
+ <script type="text/javascript" src="{{ pathto('../version_switch.js', 1) }}"></script>
+ {%- endif %}
{{ super() }}
{% endblock %}
{% block htmltitle %}
<title>{{ title|striptags|e }} {{ "—"|safe }} {{ docstitle|e }}</title>
{% endblock %}
+
+{%- block footer %}
+{{ super() }}
+{%- if googleanalytics is defined %}
+<script type="text/javascript">
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+</script>
+<script type="text/javascript">
+try {
+var pageTracker = _gat._getTracker("UA-6042509-4");
+pageTracker._trackPageview();
+} catch(err) {}
+</script>
+{%- endif %}
+{%- endblock %}