mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
@@ -89,6 +89,18 @@ files within those directories.
|
||||
|
||||
Sources intended to be used via a language's ``#include`` mechanism.
|
||||
|
||||
``SOURCES``
|
||||
.. versionadded:: 4.4
|
||||
|
||||
Specifies sources to use when building a target and/or its dependents.
|
||||
With the scope ``PRIVATE`` and ``PUBLIC``, items will populate the
|
||||
:prop_fs:`SOURCES` property of ``<set>``, which are used when building the
|
||||
target itself. With the scope ``PUBLIC`` and ``INTERFACE``, items will
|
||||
populate the :prop_fs:`INTERFACE_SOURCES` property of ``<set>``, which are
|
||||
used when building dependents. The sources specified by the
|
||||
:prop_fs:`INTERFACE_SOURCES` property are propagated, transitively, to all
|
||||
the dependents.
|
||||
|
||||
``CXX_MODULES``
|
||||
.. versionadded:: 3.28
|
||||
|
||||
@@ -106,8 +118,8 @@ have their :prop_sf:`HEADER_FILE_ONLY` property set to ``TRUE``. Files in an
|
||||
:command:`install(TARGETS)` command, and exported with the
|
||||
:command:`install(EXPORT)` and :command:`export` commands.
|
||||
|
||||
Each ``target_sources(FILE_SET)`` entry starts with ``INTERFACE``, ``PUBLIC``, or
|
||||
``PRIVATE`` and accepts the following arguments:
|
||||
Each ``target_sources(FILE_SET)`` entry starts with ``INTERFACE``, ``PUBLIC``,
|
||||
or ``PRIVATE`` and accepts the following arguments:
|
||||
|
||||
``FILE_SET <set>``
|
||||
|
||||
@@ -164,6 +176,15 @@ For file sets of type ``HEADERS``:
|
||||
* :prop_tgt:`HEADER_DIRS`
|
||||
* :prop_tgt:`HEADER_DIRS_<NAME>`
|
||||
|
||||
For file sets of type ``SOURCES``:
|
||||
|
||||
* :prop_tgt:`SOURCE_SETS`
|
||||
* :prop_tgt:`INTERFACE_SOURCE_SETS`
|
||||
* :prop_tgt:`SOURCE_SET`
|
||||
* :prop_tgt:`SOURCE_SET_<NAME>`
|
||||
* :prop_tgt:`SOURCE_DIRS`
|
||||
* :prop_tgt:`SOURCE_DIRS_<NAME>`
|
||||
|
||||
For file sets of type ``CXX_MODULES``:
|
||||
|
||||
* :prop_tgt:`CXX_MODULE_SETS`
|
||||
|
||||
@@ -307,6 +307,7 @@ Properties on Targets
|
||||
/prop_tgt/INTERFACE_LINK_OPTIONS
|
||||
/prop_tgt/INTERFACE_POSITION_INDEPENDENT_CODE
|
||||
/prop_tgt/INTERFACE_PRECOMPILE_HEADERS
|
||||
/prop_tgt/INTERFACE_SOURCE_SETS
|
||||
/prop_tgt/INTERFACE_SOURCES
|
||||
/prop_tgt/INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
|
||||
/prop_tgt/INTERPROCEDURAL_OPTIMIZATION
|
||||
@@ -409,6 +410,11 @@ Properties on Targets
|
||||
/prop_tgt/SKIP_BUILD_RPATH
|
||||
/prop_tgt/SKIP_LINTING
|
||||
/prop_tgt/SOURCE_DIR
|
||||
/prop_tgt/SOURCE_DIRS
|
||||
/prop_tgt/SOURCE_DIRS_NAME
|
||||
/prop_tgt/SOURCE_SET
|
||||
/prop_tgt/SOURCE_SET_NAME
|
||||
/prop_tgt/SOURCE_SETS
|
||||
/prop_tgt/SOURCES
|
||||
/prop_tgt/SOVERSION
|
||||
/prop_tgt/SPDX_LICENSE
|
||||
@@ -535,6 +541,12 @@ Properties on File Sets
|
||||
:maxdepth: 1
|
||||
|
||||
/prop_fs/BASE_DIRS
|
||||
/prop_fs/COMPILE_DEFINITIONS
|
||||
/prop_fs/COMPILE_OPTIONS
|
||||
/prop_fs/INCLUDE_DIRECTORIES
|
||||
/prop_fs/INTERFACE_COMPILE_DEFINITIONS
|
||||
/prop_fs/INTERFACE_COMPILE_OPTIONS
|
||||
/prop_fs/INTERFACE_INCLUDE_DIRECTORIES
|
||||
/prop_fs/INTERFACE_SOURCES
|
||||
/prop_fs/SCOPE
|
||||
/prop_fs/SOURCES
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
COMPILE_DEFINITIONS
|
||||
-------------------
|
||||
|
||||
.. versionadded:: 4.4
|
||||
|
||||
Preprocessor definitions for compiling a source file.
|
||||
|
||||
The ``COMPILE_DEFINITIONS`` property may be set to a semicolon-separated
|
||||
list of preprocessor definitions using the syntax ``VAR`` or ``VAR=value``.
|
||||
Function-style definitions are not supported. CMake will
|
||||
automatically escape the value correctly for the native build system
|
||||
(note that CMake language syntax may require escapes to specify some
|
||||
values).
|
||||
|
||||
CMake will automatically drop some definitions that are not supported
|
||||
by the native build tool. :generator:`Xcode` does not support
|
||||
per-configuration definitions on source files.
|
||||
|
||||
.. include:: /include/COMPILE_DEFINITIONS_DISCLAIMER.rst
|
||||
|
||||
Contents of ``COMPILE_DEFINITIONS`` may use :manual:`cmake-generator-expressions(7)`
|
||||
with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
|
||||
manual for available expressions. However, :generator:`Xcode`
|
||||
does not support per-config per-source settings, so expressions
|
||||
that depend on the build configuration are not allowed with that
|
||||
generator.
|
||||
|
||||
Related properties:
|
||||
|
||||
* Use :prop_fs:`COMPILE_OPTIONS` to pass additional compile flags.
|
||||
* Use :prop_fs:`INCLUDE_DIRECTORIES` to pass additional include directories.
|
||||
|
||||
Related commands:
|
||||
|
||||
* :command:`add_compile_definitions` for directory-wide settings
|
||||
* :command:`target_compile_definitions` for target-specific settings
|
||||
* :command:`set_source_files_properties` for source-specific settings
|
||||
@@ -0,0 +1,36 @@
|
||||
COMPILE_OPTIONS
|
||||
---------------
|
||||
|
||||
.. versionadded:: 4.4
|
||||
|
||||
List of additional options to pass to the compiler.
|
||||
|
||||
This property holds a :ref:`semicolon-separated list <CMake Language Lists>`
|
||||
of options and will be added to the list of compile flags when the sources of
|
||||
this file set are built. The options will be added after target-wide options
|
||||
and source level ones.
|
||||
|
||||
Contents of ``COMPILE_OPTIONS`` may use "generator expressions" with the
|
||||
syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual
|
||||
for available expressions. However, :generator:`Xcode`
|
||||
does not support per-config per-source settings, so expressions
|
||||
that depend on the build configuration are not allowed with that
|
||||
generator.
|
||||
|
||||
Usage example:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
set_property(FILE_SET SOURCES TARGET foo PROPERTY
|
||||
COMPILE_OPTIONS "-Wno-unused-parameter;-Wno-missing-field-initializer")
|
||||
|
||||
Related properties:
|
||||
|
||||
* Use :prop_fs:`COMPILE_DEFINITIONS` to pass additional preprocessor definitions.
|
||||
* Use :prop_fs:`INCLUDE_DIRECTORIES` to pass additional include directories.
|
||||
|
||||
Related commands:
|
||||
|
||||
* :command:`add_compile_options` for directory-wide settings
|
||||
* :command:`target_compile_options` for target-specific settings
|
||||
* :command:`set_source_files_properties` for source-specific settings
|
||||
@@ -0,0 +1,31 @@
|
||||
INCLUDE_DIRECTORIES
|
||||
-------------------
|
||||
|
||||
.. versionadded:: 4.4
|
||||
|
||||
List of preprocessor include file search directories.
|
||||
|
||||
This property holds a :ref:`semicolon-separated list <CMake Language Lists>` of paths
|
||||
and will be added to the list of include directories when the sources of this
|
||||
file set are built. These directories will take precedence over directories
|
||||
defined at target level and source level except for :generator:`Xcode`
|
||||
generator due to technical limitations.
|
||||
|
||||
Relative paths should not be added to this property directly.
|
||||
|
||||
Contents of ``INCLUDE_DIRECTORIES`` may use "generator expressions" with
|
||||
the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual
|
||||
for available expressions. However, :generator:`Xcode` does not support
|
||||
per-config per-source settings, so expressions that depend on the build
|
||||
configuration are not allowed with that generator.
|
||||
|
||||
Related properties:
|
||||
|
||||
* Use :prop_fs:`COMPILE_DEFINITIONS` to pass additional preprocessor definitions.
|
||||
* Use :prop_fs:`COMPILE_OPTIONS` to pass additional compile flags.
|
||||
|
||||
Related commands:
|
||||
|
||||
* :command:`include_directories` for directory-wide settings
|
||||
* :command:`target_include_directories` for target-specific settings
|
||||
* :command:`set_source_files_properties` for source-specific settings
|
||||
@@ -0,0 +1,15 @@
|
||||
INTERFACE_COMPILE_DEFINITIONS
|
||||
-----------------------------
|
||||
|
||||
.. versionadded:: 4.4
|
||||
|
||||
.. |property_name| replace:: compile definitions
|
||||
.. |command_name| replace:: :command:`set_property(FILE_SET)`
|
||||
.. |PROPERTY_INTERFACE_NAME| replace:: ``INTERFACE_COMPILE_DEFINITIONS``
|
||||
.. include:: include/INTERFACE_BUILD_PROPERTY.rst
|
||||
|
||||
Related properties:
|
||||
|
||||
* Use :prop_fs:`INTERFACE_COMPILE_OPTIONS` to pass additional compile flags.
|
||||
* Use :prop_fs:`INTERFACE_INCLUDE_DIRECTORIES` to pass additional include
|
||||
directories.
|
||||
@@ -0,0 +1,16 @@
|
||||
INTERFACE_COMPILE_OPTIONS
|
||||
-------------------------
|
||||
|
||||
.. versionadded:: 4.4
|
||||
|
||||
.. |property_name| replace:: compile options
|
||||
.. |command_name| replace:: :command:`set_property(FILE_SET)`
|
||||
.. |PROPERTY_INTERFACE_NAME| replace:: ``INTERFACE_COMPILE_OPTIONS``
|
||||
.. include:: include/INTERFACE_BUILD_PROPERTY.rst
|
||||
|
||||
Related properties:
|
||||
|
||||
* Use :prop_fs:`INTERFACE_COMPILE_DEFINITIONS` to pass additional preprocessor
|
||||
definitions.
|
||||
* Use :prop_fs:`INTERFACE_INCLUDE_DIRECTORIES` to pass additional include
|
||||
directories.
|
||||
@@ -0,0 +1,35 @@
|
||||
INTERFACE_INCLUDE_DIRECTORIES
|
||||
-----------------------------
|
||||
|
||||
.. versionadded:: 4.4
|
||||
|
||||
.. |property_name| replace:: include directories
|
||||
.. |command_name| replace:: :command:`set_property(FILE_SET)`
|
||||
.. |PROPERTY_INTERFACE_NAME| replace:: ``INTERFACE_INCLUDE_DIRECTORIES``
|
||||
.. include:: include/INTERFACE_BUILD_PROPERTY.rst
|
||||
|
||||
Include directories usage requirements commonly differ between the build-tree
|
||||
and the install-tree. The ``BUILD_INTERFACE`` and ``INSTALL_INTERFACE``
|
||||
generator expressions can be used to describe separate usage requirements
|
||||
based on the usage location. Relative paths are allowed within the
|
||||
``INSTALL_INTERFACE`` expression and are interpreted relative to the
|
||||
installation prefix. For example:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
set_property(FILE_SET myfile_set TARGET mylib PROPERTY INTERFACE_INCLUDE_DIRECTORIES
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/mylib>
|
||||
$<INSTALL_INTERFACE:include/mylib> # <prefix>/include/mylib
|
||||
)
|
||||
|
||||
Related properties:
|
||||
|
||||
* Use :prop_fs:`INTERFACE_COMPILE_DEFINITIONS` to pass additional preprocessor
|
||||
definitions.
|
||||
* Use :prop_fs:`INTERFACE_COMPILE_OPTIONS` to pass additional compile flags.
|
||||
|
||||
Creating Relocatable Packages
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. |INTERFACE_PROPERTY_LINK| replace:: ``INTERFACE_INCLUDE_DIRECTORIES``
|
||||
.. include:: /include/INTERFACE_INCLUDE_DIRECTORIES_WARNING.rst
|
||||
@@ -7,4 +7,4 @@ The type of the file set.
|
||||
|
||||
This read-only property can be used to retrieve the
|
||||
:ref:`type <File Sets>` of the given file set.
|
||||
Possible values are ``CXX_MODULES`` or ``HEADERS``.
|
||||
Possible values are ``CXX_MODULES``, ``SOURCES``, or ``HEADERS``.
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
List of public |property_name| requirements for a file set.
|
||||
|
||||
File sets may populate this property to publish the |property_name|
|
||||
required to compile the sources for the target. The |command_name|
|
||||
command populates this property.
|
||||
|
||||
When target dependencies are specified using :command:`target_link_libraries`,
|
||||
CMake will read this property from file sets of all target dependencies to
|
||||
determine the build properties of the consumer. These build properties are only
|
||||
applied to the sources of the file sets. The other sources of the consumer are
|
||||
unaffected.
|
||||
|
||||
Contents of |PROPERTY_INTERFACE_NAME| may use "generator expressions"
|
||||
with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
|
||||
manual for available expressions. See the :manual:`cmake-buildsystem(7)`
|
||||
-manual for more on defining buildsystem properties.
|
||||
@@ -0,0 +1,14 @@
|
||||
INTERFACE_SOURCE_SETS
|
||||
---------------------
|
||||
|
||||
.. versionadded:: 4.4
|
||||
|
||||
Read-only list of the target's ``INTERFACE`` and ``PUBLIC`` source sets (i.e.
|
||||
all file sets with the type ``SOURCES``). Files listed in these source sets
|
||||
can be installed with :command:`install(TARGETS)` and exported with
|
||||
:command:`install(EXPORT)` and :command:`export`.
|
||||
|
||||
Source sets may be defined using the :command:`target_sources` command
|
||||
``FILE_SET`` option with type ``SOURCES``.
|
||||
|
||||
See also :prop_tgt:`SOURCE_SETS`.
|
||||
@@ -0,0 +1,14 @@
|
||||
SOURCE_DIRS
|
||||
-----------
|
||||
|
||||
.. versionadded:: 4.4
|
||||
|
||||
Semicolon-separated list of base directories of the target's default
|
||||
source set (i.e. the file set with name and type ``SOURCES``). The property
|
||||
supports :manual:`generator expressions <cmake-generator-expressions(7)>`.
|
||||
|
||||
This property is normally only set by :command:`target_sources(FILE_SET)`
|
||||
rather than being manipulated directly.
|
||||
|
||||
See :prop_tgt:`SOURCE_DIRS_<NAME>` for the list of base directories in
|
||||
other source sets.
|
||||
@@ -0,0 +1,15 @@
|
||||
SOURCE_DIRS_<NAME>
|
||||
------------------
|
||||
|
||||
.. versionadded:: 4.4
|
||||
|
||||
Semicolon-separated list of base directories of the target's ``<NAME>``
|
||||
source set, which has the set type ``SOURCES``. The property supports
|
||||
:manual:`generator expressions <cmake-generator-expressions(7)>`.
|
||||
|
||||
This property is normally only set by :command:`target_sources(FILE_SET)`
|
||||
rather than being manipulated directly.
|
||||
|
||||
See :prop_tgt:`SOURCE_DIRS` for the list of base directories in the
|
||||
default source set. See :prop_tgt:`SOURCE_SETS` for the file set names of all
|
||||
source sets.
|
||||
@@ -0,0 +1,15 @@
|
||||
SOURCE_SET
|
||||
----------
|
||||
|
||||
.. versionadded:: 4.4
|
||||
|
||||
Semicolon-separated list of files in the target's default source set,
|
||||
(i.e. the file set with name and type ``SOURCES``). If any of the paths
|
||||
are relative, they are computed relative to the target's source directory.
|
||||
The property supports
|
||||
:manual:`generator expressions <cmake-generator-expressions(7)>`.
|
||||
|
||||
This property is normally only set by :command:`target_sources(FILE_SET)`
|
||||
rather than being manipulated directly.
|
||||
|
||||
See :prop_tgt:`SOURCE_SET_<NAME>` for the list of files in other source sets.
|
||||
@@ -0,0 +1,14 @@
|
||||
SOURCE_SETS
|
||||
-----------
|
||||
|
||||
.. versionadded:: 4.4
|
||||
|
||||
Read-only list of the target's ``PRIVATE`` and ``PUBLIC`` source sets (i.e.
|
||||
all file sets with the type ``SOURCES``). Files listed in these file sets are
|
||||
treated as source files.
|
||||
|
||||
Source sets may be defined using the :command:`target_sources` command
|
||||
``FILE_SET`` option with type ``SOURCES``.
|
||||
|
||||
See also :prop_tgt:`SOURCE_SET_<NAME>`, :prop_tgt:`SOURCE_SET` and
|
||||
:prop_tgt:`INTERFACE_SOURCE_SETS`.
|
||||
@@ -0,0 +1,15 @@
|
||||
SOURCE_SET_<NAME>
|
||||
-----------------
|
||||
|
||||
.. versionadded:: 4.4
|
||||
|
||||
Semicolon-separated list of files in the target's ``<NAME>`` source set,
|
||||
which has the set type ``SOURCES``. If any of the paths are relative,
|
||||
they are computed relative to the target's source directory. The property
|
||||
supports :manual:`generator expressions <cmake-generator-expressions(7)>`.
|
||||
|
||||
This property is normally only set by :command:`target_sources(FILE_SET)`
|
||||
rather than being manipulated directly.
|
||||
|
||||
See :prop_tgt:`SOURCE_SET` for the list of files in the default source set.
|
||||
See :prop_tgt:`SOURCE_SETS` for the file set names of all source sets.
|
||||
@@ -0,0 +1,4 @@
|
||||
FILE_SET-SOURCES
|
||||
----------------
|
||||
|
||||
* The :ref:`file set <file sets>` gains the support of the ``SOURCES`` type.
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "cmGenExContext.h"
|
||||
#include "cmGenExEvaluation.h"
|
||||
#include "cmGeneratorFileSets.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmLinkItem.h"
|
||||
#include "cmList.h"
|
||||
@@ -73,6 +74,31 @@ void addInterfaceEntry(cmGeneratorTarget const* headTarget,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addInterfaceFileSetsEntry(cmGeneratorTarget const* headTarget,
|
||||
cm::string_view type, std::string const& prop,
|
||||
cm::GenEx::Context const& context,
|
||||
cmGeneratorExpressionDAGChecker* dagChecker,
|
||||
EvaluatedTargetPropertyEntries& entries,
|
||||
std::vector<cmLinkItem> const& libraries)
|
||||
{
|
||||
for (cmLinkItem const& lib : libraries) {
|
||||
if (lib.Target) {
|
||||
EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace);
|
||||
// Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in our
|
||||
// caller's property and hand-evaluate it as if it were compiled.
|
||||
// Create a context as cmCompiledGeneratorExpression::Evaluate does.
|
||||
cm::GenEx::Evaluation eval(context, false, headTarget, headTarget, true,
|
||||
lib.Backtrace);
|
||||
cmExpandList(
|
||||
lib.Target->GetGeneratorFileSets()->EvaluateInterfaceProperty(
|
||||
type, prop, &eval, dagChecker),
|
||||
ee.Values);
|
||||
ee.ContextDependent = eval.HadContextSensitiveCondition;
|
||||
entries.Entries.emplace_back(std::move(ee));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddInterfaceEntries(cmGeneratorTarget const* headTarget,
|
||||
@@ -108,4 +134,19 @@ void AddInterfaceEntries(cmGeneratorTarget const* headTarget,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddInterfaceFileSetsEntries(cmGeneratorTarget const* headTarget,
|
||||
cm::string_view type, std::string const& prop,
|
||||
cm::GenEx::Context const& context,
|
||||
cmGeneratorExpressionDAGChecker* dagChecker,
|
||||
EvaluatedTargetPropertyEntries& entries)
|
||||
{
|
||||
if (cmLinkImplementationLibraries const* impl =
|
||||
headTarget->GetLinkImplementationLibraries(
|
||||
context.Config, cmGeneratorTarget::UseTo::Compile)) {
|
||||
entries.HadContextSensitiveCondition = impl->HadContextSensitiveCondition;
|
||||
addInterfaceFileSetsEntry(headTarget, type, prop, context, dagChecker,
|
||||
entries, impl->Libraries);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <cm/string_view>
|
||||
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmListFileCache.h"
|
||||
|
||||
@@ -83,4 +85,10 @@ void AddInterfaceEntries(
|
||||
EvaluatedTargetPropertyEntries& entries,
|
||||
IncludeRuntimeInterface searchRuntime,
|
||||
cmGeneratorTarget::UseTo usage = cmGeneratorTarget::UseTo::Compile);
|
||||
|
||||
void AddInterfaceFileSetsEntries(cmGeneratorTarget const* headTarget,
|
||||
cm::string_view type, std::string const& prop,
|
||||
cm::GenEx::Context const& context,
|
||||
cmGeneratorExpressionDAGChecker* dagChecker,
|
||||
EvaluatedTargetPropertyEntries& entries);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#include "cmFastbuildTargetGenerator.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGeneratorFileSet.h"
|
||||
#include "cmGeneratorFileSets.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmGlobalCommonGenerator.h"
|
||||
#include "cmGlobalFastbuildGenerator.h"
|
||||
@@ -117,7 +119,20 @@ std::string cmFastbuildNormalTargetGenerator::DetectCompilerFlags(
|
||||
cmGeneratorExpressionInterpreter genexInterpreter(
|
||||
this->GetLocalGenerator(), Config, this->GeneratorTarget, language);
|
||||
|
||||
auto const* fileSet =
|
||||
this->GeneratorTarget->GetGeneratorFileSets()->GetFileSetForSource(
|
||||
this->Config, &srcFile);
|
||||
|
||||
std::vector<std::string> sourceIncludesVec;
|
||||
if (fileSet) {
|
||||
auto fsIncludes = fileSet->BelongsTo(this->GeneratorTarget)
|
||||
? fileSet->GetIncludeDirectories(this->Config, language)
|
||||
: fileSet->GetInterfaceIncludeDirectories(this->Config, language);
|
||||
if (!fsIncludes.empty()) {
|
||||
this->LocalGenerator->AppendIncludeDirectories(
|
||||
sourceIncludesVec, cm::remove_BT(fsIncludes), srcFile);
|
||||
}
|
||||
}
|
||||
if (cmValue cincludes = srcFile.GetProperty(INCLUDE_DIRECTORIES)) {
|
||||
this->LocalGenerator->AppendIncludeDirectories(
|
||||
sourceIncludesVec,
|
||||
@@ -140,6 +155,17 @@ std::string cmFastbuildNormalTargetGenerator::DetectCompilerFlags(
|
||||
this->LocalGenerator->AppendCompileOptions(
|
||||
compileFlags, genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS));
|
||||
}
|
||||
// Add flags from file set properties.
|
||||
if (fileSet) {
|
||||
auto options = fileSet->BelongsTo(this->GeneratorTarget)
|
||||
? fileSet->GetCompileOptions(this->Config, language)
|
||||
: fileSet->GetInterfaceCompileOptions(this->Config, language);
|
||||
if (!options.empty()) {
|
||||
this->LocalGenerator->AppendCompileOptions(compileFlags,
|
||||
cm::remove_BT(options));
|
||||
}
|
||||
}
|
||||
|
||||
// Source includes take precedence over target includes.
|
||||
this->LocalGenerator->AppendFlags(compileFlags, sourceIncludesStr);
|
||||
this->LocalGenerator->AppendFlags(compileFlags,
|
||||
@@ -411,6 +437,17 @@ std::string cmFastbuildNormalTargetGenerator::ComputeDefines(
|
||||
genexInterpreter.Evaluate(*config_compile_defs, COMPILE_DEFINITIONS));
|
||||
}
|
||||
|
||||
if (auto const* fileSet =
|
||||
this->GeneratorTarget->GetGeneratorFileSets()->GetFileSetForSource(
|
||||
this->Config, &srcFile)) {
|
||||
auto fsDefines = fileSet->BelongsTo(this->GeneratorTarget)
|
||||
? fileSet->GetCompileDefinitions(this->Config, language)
|
||||
: fileSet->GetInterfaceCompileDefinitions(this->Config, language);
|
||||
if (!fsDefines.empty()) {
|
||||
this->LocalGenerator->AppendDefines(defines, fsDefines);
|
||||
}
|
||||
}
|
||||
|
||||
std::string definesString = this->GetDefines(language, Config);
|
||||
LogMessage(cmStrCat("TARGET DEFINES = ", definesString));
|
||||
this->GetLocalGenerator()->JoinDefines(defines, definesString, language);
|
||||
|
||||
+135
-2
@@ -16,6 +16,7 @@
|
||||
#include "cmMakefile.h"
|
||||
#include "cmMessageType.h"
|
||||
#include "cmPolicies.h"
|
||||
#include "cmRange.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmTarget.h"
|
||||
|
||||
@@ -57,6 +58,33 @@ void cmFileSet::AddFileEntry(BT<std::string> files)
|
||||
this->FileEntries.push_back(std::move(files));
|
||||
}
|
||||
|
||||
cmBTStringRange cmFileSet::GetIncludeDirectories() const
|
||||
{
|
||||
return cmMakeRange(this->IncludeDirectories);
|
||||
}
|
||||
cmBTStringRange cmFileSet::GetInterfaceIncludeDirectories() const
|
||||
{
|
||||
return cmMakeRange(this->InterfaceIncludeDirectories);
|
||||
}
|
||||
|
||||
cmBTStringRange cmFileSet::GetCompileOptions() const
|
||||
{
|
||||
return cmMakeRange(this->CompileOptions);
|
||||
}
|
||||
cmBTStringRange cmFileSet::GetInterfaceCompileOptions() const
|
||||
{
|
||||
return cmMakeRange(this->InterfaceCompileOptions);
|
||||
}
|
||||
|
||||
cmBTStringRange cmFileSet::GetCompileDefinitions() const
|
||||
{
|
||||
return cmMakeRange(this->CompileDefinitions);
|
||||
}
|
||||
cmBTStringRange cmFileSet::GetInterfaceCompileDefinitions() const
|
||||
{
|
||||
return cmMakeRange(this->InterfaceCompileDefinitions);
|
||||
}
|
||||
|
||||
namespace {
|
||||
enum class ReadOnlyCondition
|
||||
{
|
||||
@@ -142,9 +170,15 @@ bool IsSettableProperty(cmMakefile* context, cmTarget* target,
|
||||
cm::string_view const BASE_DIRS = "BASE_DIRS"_s;
|
||||
cm::string_view const SOURCES = "SOURCES"_s;
|
||||
cm::string_view const INTERFACE_SOURCES = "INTERFACE_SOURCES"_s;
|
||||
cm::string_view const COMPILE_DEFINITIONS = "COMPILE_DEFINITIONS"_s;
|
||||
cm::string_view const COMPILE_OPTIONS = "COMPILE_OPTIONS"_s;
|
||||
cm::string_view const INCLUDE_DIRECTORIES = "INCLUDE_DIRECTORIES"_s;
|
||||
cm::string_view const INTERFACE_INCLUDE_DIRECTORIES =
|
||||
"INTERFACE_INCLUDE_DIRECTORIES"_s;
|
||||
cm::string_view const COMPILE_DEFINITIONS = "COMPILE_DEFINITIONS"_s;
|
||||
cm::string_view const INTERFACE_COMPILE_DEFINITIONS =
|
||||
"INTERFACE_COMPILE_DEFINITIONS"_s;
|
||||
cm::string_view const COMPILE_OPTIONS = "COMPILE_OPTIONS"_s;
|
||||
cm::string_view const INTERFACE_COMPILE_OPTIONS =
|
||||
"INTERFACE_COMPILE_OPTIONS"_s;
|
||||
}
|
||||
|
||||
void cmFileSet::SetProperty(std::string const& prop, cmValue value)
|
||||
@@ -178,23 +212,59 @@ void cmFileSet::SetProperty(std::string const& prop, cmValue value)
|
||||
this->AddFileEntry(BT<std::string>{ value, lfbt });
|
||||
}
|
||||
} else if (prop == INCLUDE_DIRECTORIES) {
|
||||
if (!this->IsForSelf()) {
|
||||
return;
|
||||
}
|
||||
this->IncludeDirectories.clear();
|
||||
if (value) {
|
||||
cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
|
||||
this->IncludeDirectories.emplace_back(value, lfbt);
|
||||
}
|
||||
} else if (prop == INTERFACE_INCLUDE_DIRECTORIES) {
|
||||
if (!this->IsForInterface()) {
|
||||
return;
|
||||
}
|
||||
this->InterfaceIncludeDirectories.clear();
|
||||
if (value) {
|
||||
cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
|
||||
this->InterfaceIncludeDirectories.emplace_back(value, lfbt);
|
||||
}
|
||||
} else if (prop == COMPILE_OPTIONS) {
|
||||
if (!this->IsForSelf()) {
|
||||
return;
|
||||
}
|
||||
this->CompileOptions.clear();
|
||||
if (value) {
|
||||
cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
|
||||
this->CompileOptions.emplace_back(value, lfbt);
|
||||
}
|
||||
} else if (prop == INTERFACE_COMPILE_OPTIONS) {
|
||||
if (!this->IsForInterface()) {
|
||||
return;
|
||||
}
|
||||
this->InterfaceCompileOptions.clear();
|
||||
if (value) {
|
||||
cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
|
||||
this->InterfaceCompileOptions.emplace_back(value, lfbt);
|
||||
}
|
||||
} else if (prop == COMPILE_DEFINITIONS) {
|
||||
if (!this->IsForSelf()) {
|
||||
return;
|
||||
}
|
||||
this->CompileDefinitions.clear();
|
||||
if (value) {
|
||||
cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
|
||||
this->CompileDefinitions.emplace_back(value, lfbt);
|
||||
}
|
||||
} else if (prop == INTERFACE_COMPILE_DEFINITIONS) {
|
||||
if (!this->IsForInterface()) {
|
||||
return;
|
||||
}
|
||||
this->InterfaceCompileDefinitions.clear();
|
||||
if (value) {
|
||||
cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
|
||||
this->InterfaceCompileDefinitions.emplace_back(value, lfbt);
|
||||
}
|
||||
} else {
|
||||
this->Properties.SetProperty(prop, value);
|
||||
}
|
||||
@@ -229,20 +299,53 @@ void cmFileSet::AppendProperty(std::string const& prop,
|
||||
this->AddFileEntry(BT<std::string>{ value, lfbt });
|
||||
}
|
||||
} else if (prop == INCLUDE_DIRECTORIES) {
|
||||
if (!this->IsForSelf()) {
|
||||
return;
|
||||
}
|
||||
if (!value.empty()) {
|
||||
cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
|
||||
this->IncludeDirectories.emplace_back(value, lfbt);
|
||||
}
|
||||
} else if (prop == INTERFACE_INCLUDE_DIRECTORIES) {
|
||||
if (!this->IsForInterface()) {
|
||||
return;
|
||||
}
|
||||
if (!value.empty()) {
|
||||
cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
|
||||
this->InterfaceIncludeDirectories.emplace_back(value, lfbt);
|
||||
}
|
||||
} else if (prop == COMPILE_OPTIONS) {
|
||||
if (!this->IsForSelf()) {
|
||||
return;
|
||||
}
|
||||
if (!value.empty()) {
|
||||
cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
|
||||
this->CompileOptions.emplace_back(value, lfbt);
|
||||
}
|
||||
} else if (prop == INTERFACE_COMPILE_OPTIONS) {
|
||||
if (!this->IsForInterface()) {
|
||||
return;
|
||||
}
|
||||
if (!value.empty()) {
|
||||
cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
|
||||
this->InterfaceCompileOptions.emplace_back(value, lfbt);
|
||||
}
|
||||
} else if (prop == COMPILE_DEFINITIONS) {
|
||||
if (!this->IsForSelf()) {
|
||||
return;
|
||||
}
|
||||
if (!value.empty()) {
|
||||
cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
|
||||
this->CompileDefinitions.emplace_back(value, lfbt);
|
||||
}
|
||||
} else if (prop == INTERFACE_COMPILE_DEFINITIONS) {
|
||||
if (!this->IsForInterface()) {
|
||||
return;
|
||||
}
|
||||
if (!value.empty()) {
|
||||
cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
|
||||
this->InterfaceCompileDefinitions.emplace_back(value, lfbt);
|
||||
}
|
||||
} else {
|
||||
this->Properties.AppendProperty(prop, value, asString);
|
||||
}
|
||||
@@ -286,6 +389,16 @@ cmValue cmFileSet::GetProperty(std::string const& prop) const
|
||||
return cmValue(output);
|
||||
}
|
||||
|
||||
if (prop == INTERFACE_INCLUDE_DIRECTORIES) {
|
||||
if (this->InterfaceIncludeDirectories.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static std::string output;
|
||||
output = cmList::to_string(this->InterfaceIncludeDirectories);
|
||||
return cmValue(output);
|
||||
}
|
||||
|
||||
if (prop == COMPILE_OPTIONS) {
|
||||
if (this->CompileOptions.empty()) {
|
||||
return nullptr;
|
||||
@@ -296,6 +409,16 @@ cmValue cmFileSet::GetProperty(std::string const& prop) const
|
||||
return cmValue(output);
|
||||
}
|
||||
|
||||
if (prop == INTERFACE_COMPILE_OPTIONS) {
|
||||
if (this->InterfaceCompileOptions.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static std::string output;
|
||||
output = cmList::to_string(this->InterfaceCompileOptions);
|
||||
return cmValue(output);
|
||||
}
|
||||
|
||||
if (prop == COMPILE_DEFINITIONS) {
|
||||
if (this->CompileDefinitions.empty()) {
|
||||
return nullptr;
|
||||
@@ -306,6 +429,16 @@ cmValue cmFileSet::GetProperty(std::string const& prop) const
|
||||
return cmValue(output);
|
||||
}
|
||||
|
||||
if (prop == INTERFACE_COMPILE_DEFINITIONS) {
|
||||
if (this->InterfaceCompileDefinitions.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static std::string output;
|
||||
output = cmList::to_string(this->InterfaceCompileDefinitions);
|
||||
return cmValue(output);
|
||||
}
|
||||
|
||||
if (prop == "TYPE"_s) {
|
||||
return cmValue{ this->GetType() };
|
||||
}
|
||||
|
||||
+17
-3
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <cm/string_view>
|
||||
|
||||
#include "cmAlgorithms.h"
|
||||
#include "cmFileSetMetadata.h"
|
||||
#include "cmListFileCache.h"
|
||||
#include "cmPropertyMap.h"
|
||||
@@ -42,7 +43,7 @@ public:
|
||||
}
|
||||
bool CanBeIncluded() const
|
||||
{
|
||||
return this->Type == cm::FileSetMetadata::HEADERS;
|
||||
return this->Type != cm::FileSetMetadata::CXX_MODULES;
|
||||
}
|
||||
|
||||
void CopyEntries(cmFileSet const* fs);
|
||||
@@ -61,6 +62,16 @@ public:
|
||||
return this->FileEntries;
|
||||
}
|
||||
|
||||
// Special properties
|
||||
cmBTStringRange GetIncludeDirectories() const;
|
||||
cmBTStringRange GetInterfaceIncludeDirectories() const;
|
||||
|
||||
cmBTStringRange GetCompileOptions() const;
|
||||
cmBTStringRange GetInterfaceCompileOptions() const;
|
||||
|
||||
cmBTStringRange GetCompileDefinitions() const;
|
||||
cmBTStringRange GetInterfaceCompileDefinitions() const;
|
||||
|
||||
//! Set/Get a property of this file set
|
||||
void SetProperty(std::string const& prop, cmValue value);
|
||||
void SetProperty(std::string const& prop, std::nullptr_t)
|
||||
@@ -88,7 +99,10 @@ private:
|
||||
std::vector<BT<std::string>> DirectoryEntries;
|
||||
std::vector<BT<std::string>> FileEntries;
|
||||
cmPropertyMap Properties;
|
||||
std::vector<BT<std::string>> CompileOptions;
|
||||
std::vector<BT<std::string>> CompileDefinitions;
|
||||
std::vector<BT<std::string>> IncludeDirectories;
|
||||
std::vector<BT<std::string>> InterfaceIncludeDirectories;
|
||||
std::vector<BT<std::string>> CompileOptions;
|
||||
std::vector<BT<std::string>> InterfaceCompileOptions;
|
||||
std::vector<BT<std::string>> CompileDefinitions;
|
||||
std::vector<BT<std::string>> InterfaceCompileDefinitions;
|
||||
};
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
file LICENSE.rst or https://cmake.org/licensing for details. */
|
||||
#include "cmFileSetMetadata.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <cmext/algorithm>
|
||||
#include <cmext/string_view>
|
||||
@@ -74,14 +76,36 @@ bool VisibilityIsForInterface(Visibility vis)
|
||||
}
|
||||
|
||||
cm::string_view const HEADERS = "HEADERS"_s;
|
||||
cm::string_view const SOURCES = "SOURCES"_s;
|
||||
cm::string_view const CXX_MODULES = "CXX_MODULES"_s;
|
||||
|
||||
namespace {
|
||||
std::vector<cm::string_view> KnownTypes{ HEADERS, CXX_MODULES };
|
||||
std::map<cm::string_view, FileSetDescriptor> const FileSetDescriptors{
|
||||
{ cm::FileSetMetadata::HEADERS,
|
||||
{ cm::FileSetMetadata::HEADERS,
|
||||
cm::FileSetMetadata::FileSetLookup::Target } },
|
||||
{ cm::FileSetMetadata::SOURCES,
|
||||
{ cm::FileSetMetadata::SOURCES,
|
||||
cm::FileSetMetadata::FileSetLookup::Dependencies } },
|
||||
{ cm::FileSetMetadata::CXX_MODULES,
|
||||
{ cm::FileSetMetadata::CXX_MODULES,
|
||||
cm::FileSetMetadata::FileSetLookup::Target } },
|
||||
};
|
||||
|
||||
std::vector<cm::string_view> KnownTypes{ HEADERS, SOURCES, CXX_MODULES };
|
||||
|
||||
cmsys::RegularExpression const ValidNameRegex("^[a-z0-9][a-zA-Z0-9_]*$");
|
||||
}
|
||||
|
||||
cm::optional<FileSetDescriptor> GetFileSetDescriptor(cm::string_view type)
|
||||
{
|
||||
auto it = FileSetDescriptors.find(type);
|
||||
if (it != FileSetDescriptors.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return cm::nullopt;
|
||||
}
|
||||
|
||||
std::vector<cm::string_view> const& GetKnownTypes()
|
||||
{
|
||||
return KnownTypes;
|
||||
@@ -97,6 +121,5 @@ bool IsValidName(cm::string_view name)
|
||||
cmsys::RegularExpressionMatch match;
|
||||
return ValidNameRegex.find(name.data(), match);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <cm/optional>
|
||||
#include <cm/string_view>
|
||||
|
||||
class cmMakefile;
|
||||
@@ -25,8 +26,31 @@ bool VisibilityIsForInterface(Visibility vis);
|
||||
|
||||
// Pre-defined FileSet types
|
||||
extern cm::string_view const HEADERS;
|
||||
extern cm::string_view const SOURCES;
|
||||
extern cm::string_view const CXX_MODULES;
|
||||
|
||||
enum class FileSetLookup
|
||||
{
|
||||
// Search for file sets attached to the target
|
||||
Target,
|
||||
// Search also file sets inherited from link libraries
|
||||
Dependencies
|
||||
};
|
||||
|
||||
struct FileSetDescriptor
|
||||
{
|
||||
FileSetDescriptor(cm::string_view type, FileSetLookup lookup)
|
||||
: Type(type)
|
||||
, Lookup(lookup)
|
||||
{
|
||||
}
|
||||
|
||||
cm::string_view const Type;
|
||||
FileSetLookup const Lookup;
|
||||
};
|
||||
|
||||
cm::optional<FileSetDescriptor> GetFileSetDescriptor(cm::string_view type);
|
||||
|
||||
std::vector<cm::string_view> const& GetKnownTypes();
|
||||
bool IsKnownType(cm::string_view type);
|
||||
|
||||
|
||||
@@ -12,10 +12,16 @@
|
||||
|
||||
#include <cm/memory>
|
||||
#include <cm/optional>
|
||||
#include <cm/string_view>
|
||||
#include <cmext/string_view>
|
||||
|
||||
#include "cmAlgorithms.h"
|
||||
#include "cmEvaluatedTargetProperty.h"
|
||||
#include "cmFileSet.h"
|
||||
#include "cmGenExContext.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGeneratorExpressionDAGChecker.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmList.h"
|
||||
#include "cmListFileCache.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
@@ -27,6 +33,7 @@
|
||||
|
||||
class cmLinkItem;
|
||||
|
||||
namespace {
|
||||
class FileSetPropertyEntry : public cm::TargetPropertyEntry
|
||||
{
|
||||
public:
|
||||
@@ -92,12 +99,105 @@ private:
|
||||
mutable std::string Value;
|
||||
};
|
||||
|
||||
void CreatePropertyGeneratorExpressions(
|
||||
cmake& cmakeInstance, cmBTStringRange entries,
|
||||
std::vector<std::unique_ptr<cm::TargetPropertyEntry>>& items)
|
||||
{
|
||||
for (auto const& entry : entries) {
|
||||
items.emplace_back(
|
||||
cm::TargetPropertyEntry::Create(cmakeInstance, entry, false));
|
||||
}
|
||||
}
|
||||
|
||||
enum class OptionsParse
|
||||
{
|
||||
None,
|
||||
Shell
|
||||
};
|
||||
|
||||
std::vector<BT<std::string>> ProcessOptions(
|
||||
cm::EvaluatedTargetPropertyEntries const& entries,
|
||||
OptionsParse parse = OptionsParse::None)
|
||||
{
|
||||
std::vector<BT<std::string>> options;
|
||||
std::unordered_set<std::string> uniqueOptions;
|
||||
|
||||
for (cm::EvaluatedTargetPropertyEntry const& entry : entries.Entries) {
|
||||
for (std::string const& opt : entry.Values) {
|
||||
if (uniqueOptions.insert(opt).second) {
|
||||
if (parse == OptionsParse::Shell &&
|
||||
cmHasLiteralPrefix(opt, "SHELL:")) {
|
||||
std::vector<std::string> tmp;
|
||||
cmSystemTools::ParseUnixCommandLine(opt.c_str() + 6, tmp);
|
||||
for (std::string& o : tmp) {
|
||||
options.emplace_back(std::move(o), entry.Backtrace);
|
||||
}
|
||||
} else {
|
||||
options.emplace_back(opt, entry.Backtrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return options;
|
||||
}
|
||||
std::vector<BT<std::string>> ProcessIncludes(
|
||||
cmGeneratorTarget const* target, std::string const& fileSetName,
|
||||
cm::string_view property, cm::EvaluatedTargetPropertyEntries& entries)
|
||||
{
|
||||
std::vector<BT<std::string>> includes;
|
||||
std::unordered_set<std::string> uniqueIncludes;
|
||||
|
||||
for (cm::EvaluatedTargetPropertyEntry& entry : entries.Entries) {
|
||||
for (std::string& include : entry.Values) {
|
||||
if (!cmValue::IsOff(include)) {
|
||||
cmSystemTools::ConvertToUnixSlashes(include);
|
||||
}
|
||||
|
||||
if (!cmSystemTools::FileIsFullPath(include)) {
|
||||
target->GetLocalGenerator()->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
cmStrCat("File set \"", fileSetName, "\" from the target \"",
|
||||
target->GetName(), "\" contains relative path in its ",
|
||||
property, ":\n \"", include, "\""));
|
||||
return includes;
|
||||
}
|
||||
|
||||
if (uniqueIncludes.insert(include).second) {
|
||||
includes.emplace_back(include, entry.Backtrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
return includes;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Class cmGeneratorFileSet
|
||||
//
|
||||
cmGeneratorFileSet::cmGeneratorFileSet(cmFileSet const* fileSet)
|
||||
: FileSet(fileSet)
|
||||
cmGeneratorFileSet::cmGeneratorFileSet(cmGeneratorTarget const* target,
|
||||
cmFileSet const* fileSet)
|
||||
: Target(target)
|
||||
, FileSet(fileSet)
|
||||
{
|
||||
auto& cmake = *target->GetLocalGenerator()->GetCMakeInstance();
|
||||
|
||||
CreatePropertyGeneratorExpressions(cmake, fileSet->GetIncludeDirectories(),
|
||||
this->IncludeDirectories);
|
||||
CreatePropertyGeneratorExpressions(cmake,
|
||||
fileSet->GetInterfaceIncludeDirectories(),
|
||||
this->InterfaceIncludeDirectories);
|
||||
|
||||
CreatePropertyGeneratorExpressions(cmake, fileSet->GetCompileOptions(),
|
||||
this->CompileOptions);
|
||||
CreatePropertyGeneratorExpressions(cmake,
|
||||
fileSet->GetInterfaceCompileOptions(),
|
||||
this->InterfaceCompileOptions);
|
||||
|
||||
CreatePropertyGeneratorExpressions(cmake, fileSet->GetCompileDefinitions(),
|
||||
this->CompileDefinitions);
|
||||
CreatePropertyGeneratorExpressions(cmake,
|
||||
fileSet->GetInterfaceCompileDefinitions(),
|
||||
this->InterfaceCompileDefinitions);
|
||||
}
|
||||
|
||||
std::string const& cmGeneratorFileSet::GetName() const
|
||||
@@ -131,6 +231,161 @@ cmValue cmGeneratorFileSet::GetProperty(std::string const& prop) const
|
||||
return this->FileSet->GetProperty(prop);
|
||||
}
|
||||
|
||||
std::vector<BT<std::string>> cmGeneratorFileSet::GetIncludeDirectories(
|
||||
std::string const& config, std::string const& lang) const
|
||||
{
|
||||
ConfigAndLanguage cacheKey(config, lang);
|
||||
{
|
||||
auto it = this->IncludeDirectoriesCache.find(cacheKey);
|
||||
if (it != this->IncludeDirectoriesCache.end()) {
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
cm::GenEx::Context context(this->Target->GetLocalGenerator(), config, lang);
|
||||
cmGeneratorExpressionDAGChecker dagChecker{
|
||||
this->Target, "INCLUDE_DIRECTORIES", nullptr, nullptr, context,
|
||||
};
|
||||
|
||||
cm::EvaluatedTargetPropertyEntries entries =
|
||||
cm::EvaluateTargetPropertyEntries(this->Target, context, &dagChecker,
|
||||
this->IncludeDirectories);
|
||||
auto includes = ProcessIncludes(this->Target, this->GetName(),
|
||||
"INCLUDE_DIRECTORIES"_s, entries);
|
||||
this->IncludeDirectoriesCache.emplace(cacheKey, includes);
|
||||
|
||||
return includes;
|
||||
}
|
||||
std::vector<BT<std::string>>
|
||||
cmGeneratorFileSet::GetInterfaceIncludeDirectories(
|
||||
std::string const& config, std::string const& lang) const
|
||||
{
|
||||
ConfigAndLanguage cacheKey(config, lang);
|
||||
{
|
||||
auto it = this->InterfaceIncludeDirectoriesCache.find(cacheKey);
|
||||
if (it != this->InterfaceIncludeDirectoriesCache.end()) {
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
cm::GenEx::Context context(this->Target->GetLocalGenerator(), config, lang);
|
||||
cmGeneratorExpressionDAGChecker dagChecker{
|
||||
this->Target, "INCLUDE_DIRECTORIES", nullptr, nullptr, context,
|
||||
};
|
||||
|
||||
cm::EvaluatedTargetPropertyEntries entries =
|
||||
cm::EvaluateTargetPropertyEntries(this->Target, context, &dagChecker,
|
||||
this->InterfaceIncludeDirectories);
|
||||
auto includes = ProcessIncludes(this->Target, this->GetName(),
|
||||
"INTERFACE_INCLUDE_DIRECTORIES"_s, entries);
|
||||
this->InterfaceIncludeDirectoriesCache.emplace(cacheKey, includes);
|
||||
|
||||
return includes;
|
||||
}
|
||||
|
||||
std::vector<BT<std::string>> cmGeneratorFileSet::GetCompileOptions(
|
||||
std::string const& config, std::string const& language) const
|
||||
{
|
||||
ConfigAndLanguage cacheKey(config, language);
|
||||
{
|
||||
auto it = this->CompileOptionsCache.find(cacheKey);
|
||||
if (it != this->CompileOptionsCache.end()) {
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
cm::GenEx::Context context(this->Target->GetLocalGenerator(), config,
|
||||
language);
|
||||
cmGeneratorExpressionDAGChecker dagChecker{
|
||||
this->Target, "COMPILE_OPTIONS", nullptr, nullptr, context,
|
||||
};
|
||||
|
||||
cm::EvaluatedTargetPropertyEntries entries =
|
||||
cm::EvaluateTargetPropertyEntries(this->Target, context, &dagChecker,
|
||||
this->CompileOptions);
|
||||
auto options = ProcessOptions(entries, OptionsParse::Shell);
|
||||
this->CompileOptionsCache.emplace(cacheKey, options);
|
||||
|
||||
return options;
|
||||
}
|
||||
std::vector<BT<std::string>> cmGeneratorFileSet::GetInterfaceCompileOptions(
|
||||
std::string const& config, std::string const& language) const
|
||||
{
|
||||
ConfigAndLanguage cacheKey(config, language);
|
||||
{
|
||||
auto it = this->InterfaceCompileOptionsCache.find(cacheKey);
|
||||
if (it != this->InterfaceCompileOptionsCache.end()) {
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
cm::GenEx::Context context(this->Target->GetLocalGenerator(), config,
|
||||
language);
|
||||
cmGeneratorExpressionDAGChecker dagChecker{
|
||||
this->Target, "COMPILE_OPTIONS", nullptr, nullptr, context,
|
||||
};
|
||||
|
||||
cm::EvaluatedTargetPropertyEntries entries =
|
||||
cm::EvaluateTargetPropertyEntries(this->Target, context, &dagChecker,
|
||||
this->InterfaceCompileOptions);
|
||||
auto options = ProcessOptions(entries, OptionsParse::Shell);
|
||||
this->InterfaceCompileOptionsCache.emplace(cacheKey, options);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
std::vector<BT<std::string>> cmGeneratorFileSet::GetCompileDefinitions(
|
||||
std::string const& config, std::string const& language) const
|
||||
{
|
||||
ConfigAndLanguage cacheKey(config, language);
|
||||
{
|
||||
auto it = this->CompileDefinitionsCache.find(cacheKey);
|
||||
if (it != this->CompileDefinitionsCache.end()) {
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
cm::GenEx::Context context(this->Target->GetLocalGenerator(), config,
|
||||
language);
|
||||
cmGeneratorExpressionDAGChecker dagChecker{
|
||||
this->Target, "COMPILE_DEFINITIONS", nullptr, nullptr, context,
|
||||
};
|
||||
|
||||
cm::EvaluatedTargetPropertyEntries entries =
|
||||
cm::EvaluateTargetPropertyEntries(this->Target, context, &dagChecker,
|
||||
this->CompileDefinitions);
|
||||
auto defines = ProcessOptions(entries);
|
||||
this->CompileDefinitionsCache.emplace(cacheKey, defines);
|
||||
|
||||
return defines;
|
||||
}
|
||||
std::vector<BT<std::string>>
|
||||
cmGeneratorFileSet::GetInterfaceCompileDefinitions(
|
||||
std::string const& config, std::string const& language) const
|
||||
{
|
||||
ConfigAndLanguage cacheKey(config, language);
|
||||
{
|
||||
auto it = this->InterfaceCompileDefinitionsCache.find(cacheKey);
|
||||
if (it != this->InterfaceCompileDefinitionsCache.end()) {
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
cm::GenEx::Context context(this->Target->GetLocalGenerator(), config,
|
||||
language);
|
||||
cmGeneratorExpressionDAGChecker dagChecker{
|
||||
this->Target, "COMPILE_DEFINITIONS", nullptr, nullptr, context,
|
||||
};
|
||||
|
||||
cm::EvaluatedTargetPropertyEntries entries =
|
||||
cm::EvaluateTargetPropertyEntries(this->Target, context, &dagChecker,
|
||||
this->InterfaceCompileDefinitions);
|
||||
auto defines = ProcessOptions(entries);
|
||||
this->InterfaceCompileDefinitionsCache.emplace(cacheKey, defines);
|
||||
|
||||
return defines;
|
||||
}
|
||||
|
||||
std::vector<BT<std::string>> const& cmGeneratorFileSet::GetDirectoryEntries()
|
||||
const
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "cmFileSetMetadata.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmListFileCache.h"
|
||||
#include "cmTargetPropertyEntry.h"
|
||||
#include "cmValue.h"
|
||||
|
||||
@@ -21,9 +22,6 @@ struct Context;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class BT;
|
||||
|
||||
struct cmGeneratorExpressionDAGChecker;
|
||||
|
||||
class cmFileSet;
|
||||
@@ -34,7 +32,7 @@ class cmGeneratorFileSet
|
||||
public:
|
||||
using TargetPropertyEntry = cm::TargetPropertyEntry;
|
||||
|
||||
cmGeneratorFileSet(cmFileSet const*);
|
||||
cmGeneratorFileSet(cmGeneratorTarget const*, cmFileSet const*);
|
||||
~cmGeneratorFileSet() = default;
|
||||
|
||||
cmGeneratorFileSet(cmGeneratorFileSet&&) = default;
|
||||
@@ -49,10 +47,31 @@ public:
|
||||
bool IsForInterface() const;
|
||||
bool CanBeIncluded() const;
|
||||
|
||||
cmGeneratorTarget const* GetTarget() const { return this->Target; }
|
||||
bool BelongsTo(cmGeneratorTarget const* target) const
|
||||
{
|
||||
return this->Target == target;
|
||||
}
|
||||
|
||||
cmFileSet const* GetFileSet() const { return this->FileSet; }
|
||||
|
||||
cmValue GetProperty(std::string const& prop) const;
|
||||
|
||||
std::vector<BT<std::string>> GetIncludeDirectories(
|
||||
std::string const& config, std::string const& lang) const;
|
||||
std::vector<BT<std::string>> GetInterfaceIncludeDirectories(
|
||||
std::string const& config, std::string const& lang) const;
|
||||
|
||||
std::vector<BT<std::string>> GetCompileOptions(
|
||||
std::string const& config, std::string const& language) const;
|
||||
std::vector<BT<std::string>> GetInterfaceCompileOptions(
|
||||
std::string const& config, std::string const& language) const;
|
||||
|
||||
std::vector<BT<std::string>> GetCompileDefinitions(
|
||||
std::string const& config, std::string const& language) const;
|
||||
std::vector<BT<std::string>> GetInterfaceCompileDefinitions(
|
||||
std::string const& config, std::string const& language) const;
|
||||
|
||||
std::vector<BT<std::string>> const& GetDirectoryEntries() const;
|
||||
std::vector<BT<std::string>> const& GetFileEntries() const;
|
||||
|
||||
@@ -92,9 +111,29 @@ public:
|
||||
cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;
|
||||
|
||||
private:
|
||||
cmGeneratorTarget const* Target;
|
||||
cmFileSet const* FileSet;
|
||||
mutable std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>
|
||||
CompiledDirectoryEntries;
|
||||
mutable std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>
|
||||
CompiledFileEntries;
|
||||
|
||||
using TargetPropertyEntries =
|
||||
std::vector<std::unique_ptr<TargetPropertyEntry>>;
|
||||
TargetPropertyEntries IncludeDirectories;
|
||||
TargetPropertyEntries InterfaceIncludeDirectories;
|
||||
TargetPropertyEntries CompileOptions;
|
||||
TargetPropertyEntries InterfaceCompileOptions;
|
||||
TargetPropertyEntries CompileDefinitions;
|
||||
TargetPropertyEntries InterfaceCompileDefinitions;
|
||||
|
||||
using ConfigAndLanguage = std::pair<std::string, std::string>;
|
||||
using ConfigAndLanguageToBTStrings =
|
||||
std::map<ConfigAndLanguage, std::vector<BT<std::string>>>;
|
||||
mutable ConfigAndLanguageToBTStrings IncludeDirectoriesCache;
|
||||
mutable ConfigAndLanguageToBTStrings InterfaceIncludeDirectoriesCache;
|
||||
mutable ConfigAndLanguageToBTStrings CompileOptionsCache;
|
||||
mutable ConfigAndLanguageToBTStrings InterfaceCompileOptionsCache;
|
||||
mutable ConfigAndLanguageToBTStrings CompileDefinitionsCache;
|
||||
mutable ConfigAndLanguageToBTStrings InterfaceCompileDefinitionsCache;
|
||||
};
|
||||
|
||||
+259
-22
@@ -5,18 +5,31 @@
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <cm/memory>
|
||||
#include <cm/optional>
|
||||
#include <cmext/algorithm>
|
||||
#include <cmext/string_view>
|
||||
|
||||
#include "cmFileSetMetadata.h"
|
||||
#include "cmGenExContext.h"
|
||||
#include "cmGenExEvaluation.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGeneratorExpressionDAGChecker.h"
|
||||
#include "cmGeneratorExpressionNode.h"
|
||||
#include "cmGeneratorFileSet.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmLinkItem.h"
|
||||
#include "cmList.h"
|
||||
#include "cmListFileCache.h"
|
||||
#include "cmSourceFile.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmTarget.h"
|
||||
#include "cmValue.h"
|
||||
|
||||
cmGeneratorFileSets::cmGeneratorFileSets(cmGeneratorTarget* target,
|
||||
cmLocalGenerator* lg)
|
||||
@@ -24,9 +37,10 @@ cmGeneratorFileSets::cmGeneratorFileSets(cmGeneratorTarget* target,
|
||||
, LocalGenerator(lg)
|
||||
{
|
||||
for (auto const& name : target->Target->GetAllPrivateFileSets()) {
|
||||
auto entry = this->FileSets.emplace(
|
||||
name,
|
||||
cm::make_unique<cmGeneratorFileSet>(target->Target->GetFileSet(name)));
|
||||
auto entry =
|
||||
this->FileSets.emplace(name,
|
||||
cm::make_unique<cmGeneratorFileSet>(
|
||||
target, target->Target->GetFileSet(name)));
|
||||
|
||||
auto const* fileSet = entry.first->second.get();
|
||||
this->AllFileSets.push_back(fileSet);
|
||||
@@ -36,9 +50,10 @@ cmGeneratorFileSets::cmGeneratorFileSets(cmGeneratorTarget* target,
|
||||
auto it = this->FileSets.find(name);
|
||||
cmGeneratorFileSet const* fileSet = nullptr;
|
||||
if (it == this->FileSets.end()) {
|
||||
auto entry = this->FileSets.emplace(
|
||||
name,
|
||||
cm::make_unique<cmGeneratorFileSet>(target->Target->GetFileSet(name)));
|
||||
auto entry =
|
||||
this->FileSets.emplace(name,
|
||||
cm::make_unique<cmGeneratorFileSet>(
|
||||
target, target->Target->GetFileSet(name)));
|
||||
fileSet = entry.first->second.get();
|
||||
this->AllFileSets.push_back(fileSet);
|
||||
} else {
|
||||
@@ -102,15 +117,28 @@ cmGeneratorFileSet const* cmGeneratorFileSets::GetFileSet(
|
||||
cmGeneratorFileSet const* cmGeneratorFileSets::GetFileSetForSource(
|
||||
std::string const& config, std::string const& path) const
|
||||
{
|
||||
using Lookup = cm::FileSetMetadata::FileSetLookup;
|
||||
|
||||
this->BuildInfoCache(config);
|
||||
|
||||
auto const& info = this->Configs[config];
|
||||
|
||||
auto const it = info.FileSetCache.find(path);
|
||||
if (it == info.FileSetCache.end()) {
|
||||
return nullptr;
|
||||
if (it != info.FileSetCache.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return it->second;
|
||||
|
||||
// search in all the dependents
|
||||
auto const it2 = info.InterfaceFileSetCache.find(path);
|
||||
if (it2 != info.InterfaceFileSetCache.end() &&
|
||||
cm::FileSetMetadata::GetFileSetDescriptor(it2->second->GetType())
|
||||
.value_or(
|
||||
cm::FileSetMetadata::FileSetDescriptor{ ""_s, Lookup::Target })
|
||||
.Lookup == Lookup::Dependencies) {
|
||||
return it2->second;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
cmGeneratorFileSet const* cmGeneratorFileSets::GetFileSetForSource(
|
||||
std::string const& config, cmSourceFile const* sf) const
|
||||
@@ -120,6 +148,7 @@ cmGeneratorFileSet const* cmGeneratorFileSets::GetFileSetForSource(
|
||||
|
||||
std::vector<std::unique_ptr<cm::TargetPropertyEntry>>
|
||||
cmGeneratorFileSets::GetSources(
|
||||
std::function<bool(cmGeneratorFileSet const*)> include,
|
||||
cm::GenEx::Context const& context, cmGeneratorTarget const* target,
|
||||
cmGeneratorExpressionDAGChecker* dagChecker) const
|
||||
{
|
||||
@@ -127,7 +156,7 @@ cmGeneratorFileSets::GetSources(
|
||||
|
||||
for (auto const& entry : this->FileSets) {
|
||||
auto const* fileSet = entry.second.get();
|
||||
if (fileSet->IsForSelf()) {
|
||||
if (include(fileSet)) {
|
||||
auto sources = fileSet->GetSources(context, target, dagChecker);
|
||||
std::move(sources.begin(), sources.end(), std::back_inserter(entries));
|
||||
}
|
||||
@@ -136,23 +165,216 @@ cmGeneratorFileSets::GetSources(
|
||||
return entries;
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<cm::TargetPropertyEntry>>
|
||||
cmGeneratorFileSets::GetSources(
|
||||
cm::GenEx::Context const& context, cmGeneratorTarget const* target,
|
||||
cmGeneratorExpressionDAGChecker* dagChecker) const
|
||||
{
|
||||
return this->GetSources(
|
||||
[](cmGeneratorFileSet const* fileSet) -> bool {
|
||||
return fileSet->IsForSelf();
|
||||
},
|
||||
context, target, dagChecker);
|
||||
}
|
||||
std::vector<std::unique_ptr<cm::TargetPropertyEntry>>
|
||||
cmGeneratorFileSets::GetSources(
|
||||
std::string type, cm::GenEx::Context const& context,
|
||||
cmGeneratorTarget const* target,
|
||||
cmGeneratorExpressionDAGChecker* dagChecker) const
|
||||
{
|
||||
std::vector<std::unique_ptr<TargetPropertyEntry>> entries;
|
||||
return this->GetSources(
|
||||
[&type](cmGeneratorFileSet const* fileSet) -> bool {
|
||||
return fileSet->IsForSelf() && fileSet->GetType() == type;
|
||||
},
|
||||
context, target, dagChecker);
|
||||
}
|
||||
|
||||
for (auto const& entry : this->FileSets) {
|
||||
auto const* fileSet = entry.second.get();
|
||||
if (!fileSet->IsForSelf() && fileSet->GetType() == type) {
|
||||
auto sources = fileSet->GetSources(context, target, dagChecker);
|
||||
std::move(sources.begin(), sources.end(), std::back_inserter(entries));
|
||||
std::vector<std::unique_ptr<cm::TargetPropertyEntry>>
|
||||
cmGeneratorFileSets::GetInterfaceSources(
|
||||
cm::GenEx::Context const& context, cmGeneratorTarget const* target,
|
||||
cmGeneratorExpressionDAGChecker* dagChecker) const
|
||||
{
|
||||
return this->GetSources(
|
||||
[](cmGeneratorFileSet const* fileSet) -> bool {
|
||||
return fileSet->IsForInterface();
|
||||
},
|
||||
context, target, dagChecker);
|
||||
}
|
||||
std::vector<std::unique_ptr<cm::TargetPropertyEntry>>
|
||||
cmGeneratorFileSets::GetInterfaceSources(
|
||||
std::string type, cm::GenEx::Context const& context,
|
||||
cmGeneratorTarget const* target,
|
||||
cmGeneratorExpressionDAGChecker* dagChecker) const
|
||||
{
|
||||
return this->GetSources(
|
||||
[&type](cmGeneratorFileSet const* fileSet) -> bool {
|
||||
return fileSet->IsForInterface() && fileSet->GetType() == type;
|
||||
},
|
||||
context, target, dagChecker);
|
||||
}
|
||||
|
||||
bool cmGeneratorFileSets::MaybeHaveInterfaceProperty(
|
||||
cm::string_view type, std::string const& prop,
|
||||
cm::GenEx::Evaluation* eval) const
|
||||
{
|
||||
std::string const key =
|
||||
cmStrCat(type, "::", prop, '@', eval->Context.Config);
|
||||
auto i = this->MaybeInterfacePropertyExists.find(key);
|
||||
if (i == this->MaybeInterfacePropertyExists.end()) {
|
||||
// Insert an entry now in case there is a cycle.
|
||||
i = this->MaybeInterfacePropertyExists.emplace(key, false).first;
|
||||
bool& maybeInterfaceProp = i->second;
|
||||
|
||||
for (auto const* fileSet : this->GetInterfaceFileSets(type)) {
|
||||
// If this file set itself has a non-empty property value, we are done.
|
||||
maybeInterfaceProp = !fileSet->GetProperty(prop).IsEmpty();
|
||||
if (maybeInterfaceProp) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, recurse to interface dependencies.
|
||||
if (!maybeInterfaceProp) {
|
||||
cmGeneratorTarget const* headTarget =
|
||||
eval->HeadTarget ? eval->HeadTarget : this->Target;
|
||||
if (cmLinkInterfaceLibraries const* iface =
|
||||
this->Target->GetLinkInterfaceLibraries(
|
||||
eval->Context.Config, headTarget,
|
||||
cmGeneratorTarget::UseTo::Compile)) {
|
||||
if (iface->HadHeadSensitiveCondition) {
|
||||
// With a different head target we may get to a library with
|
||||
// this interface property.
|
||||
maybeInterfaceProp = true;
|
||||
} else {
|
||||
// The transitive interface libraries do not depend on the
|
||||
// head target, so we can follow them.
|
||||
for (cmLinkItem const& lib : iface->Libraries) {
|
||||
if (lib.Target &&
|
||||
lib.Target->GetGeneratorFileSets()->MaybeHaveInterfaceProperty(
|
||||
type, prop, eval)) {
|
||||
maybeInterfaceProp = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return i->second;
|
||||
}
|
||||
|
||||
std::string cmGeneratorFileSets::EvaluateInterfaceProperty(
|
||||
cm::string_view type, std::string const& prop, cm::GenEx::Evaluation* eval,
|
||||
cmGeneratorExpressionDAGChecker* dagCheckerParent) const
|
||||
{
|
||||
// If the property does not appear transitively at all, we are done.
|
||||
if (!this->MaybeHaveInterfaceProperty(type, prop, eval)) {
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
cmList result;
|
||||
cmGeneratorExpressionDAGChecker dagChecker{
|
||||
this->Target, prop, nullptr,
|
||||
dagCheckerParent, eval->Context, eval->Backtrace,
|
||||
};
|
||||
switch (dagChecker.Check()) {
|
||||
case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
|
||||
dagChecker.ReportError(
|
||||
eval,
|
||||
cmStrCat("$<FILE_SET_PROPERTY:*,TARGET:", this->Target->GetName(), ',',
|
||||
prop, '>'));
|
||||
return std::string{};
|
||||
case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
|
||||
// No error. We just skip cyclic references.
|
||||
case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
|
||||
// No error. We have already seen this transitive property.
|
||||
return std::string{};
|
||||
case cmGeneratorExpressionDAGChecker::DAG:
|
||||
break;
|
||||
}
|
||||
|
||||
cmGeneratorTarget const* headTarget =
|
||||
eval->HeadTarget ? eval->HeadTarget : this->Target;
|
||||
|
||||
for (auto const* fileSet : this->GetInterfaceFileSets(type)) {
|
||||
if (cmValue p = fileSet->GetProperty(prop)) {
|
||||
result.append(cmGeneratorExpressionNode::EvaluateDependentExpression(
|
||||
*p, eval, headTarget, &dagChecker, this->Target));
|
||||
}
|
||||
}
|
||||
|
||||
return entries;
|
||||
if (cmLinkInterfaceLibraries const* iface =
|
||||
this->Target->GetLinkInterfaceLibraries(
|
||||
eval->Context.Config, headTarget,
|
||||
cmGeneratorTarget::UseTo::Compile)) {
|
||||
eval->HadContextSensitiveCondition = eval->HadContextSensitiveCondition ||
|
||||
iface->HadContextSensitiveCondition;
|
||||
for (cmLinkItem const& lib : iface->Libraries) {
|
||||
// Broken code can have a target in its own link interface.
|
||||
// Don't follow such link interface entries so as not to create a
|
||||
// self-referencing loop.
|
||||
if (lib.Target && lib.Target != this->Target) {
|
||||
// Pretend $<FILE_SET__PROPERTY:fileSet,TARGET:lib.Target,prop>
|
||||
// appeared in the above property and hand-evaluate it as if it were
|
||||
// compiled.
|
||||
// Create a context as cmCompiledGeneratorExpression::Evaluate does.
|
||||
cm::GenEx::Evaluation libEval(
|
||||
eval->Context, eval->Quiet, headTarget, this->Target,
|
||||
eval->EvaluateForBuildsystem, eval->Backtrace);
|
||||
std::string libResult = cmGeneratorExpression::StripEmptyListElements(
|
||||
lib.Target->GetGeneratorFileSets()->EvaluateInterfaceProperty(
|
||||
type, prop, &libEval, &dagChecker));
|
||||
if (!libResult.empty()) {
|
||||
result.append(libResult);
|
||||
}
|
||||
eval->HadContextSensitiveCondition =
|
||||
eval->HadContextSensitiveCondition ||
|
||||
libEval.HadContextSensitiveCondition;
|
||||
eval->HadHeadSensitiveCondition =
|
||||
eval->HadHeadSensitiveCondition || libEval.HadHeadSensitiveCondition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.to_string();
|
||||
}
|
||||
|
||||
namespace {
|
||||
void GetInterfaceFiles(cmGeneratorTarget const* target,
|
||||
cm::GenEx::Context const& context,
|
||||
std::unordered_set<cmGeneratorTarget const*>& targets,
|
||||
std::map<std::string, cmGeneratorFileSet const*>& cache)
|
||||
{
|
||||
namespace Metadata = cm::FileSetMetadata;
|
||||
|
||||
for (auto const& type : Metadata::GetKnownTypes()) {
|
||||
auto fileSetDescriptor = Metadata::GetFileSetDescriptor(type);
|
||||
if (fileSetDescriptor &&
|
||||
fileSetDescriptor->Lookup == Metadata::FileSetLookup::Dependencies) {
|
||||
for (auto const* fileSet : target->GetInterfaceFileSets(type)) {
|
||||
auto files = fileSet->GetFiles(context, target);
|
||||
|
||||
for (auto const& it : files.first) {
|
||||
for (auto const& filename : it.second) {
|
||||
auto collapsedFile = cmSystemTools::CollapseFullPath(filename);
|
||||
cache[collapsedFile] = fileSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cmLinkInterfaceLibraries const* iface =
|
||||
target->GetLinkInterfaceLibraries(context.Config, target,
|
||||
cmGeneratorTarget::UseTo::Compile)) {
|
||||
for (cmLinkItem const& lib : iface->Libraries) {
|
||||
if (lib.Target && lib.Target != target &&
|
||||
targets.insert(lib.Target).second) {
|
||||
GetInterfaceFiles(lib.Target, context, targets, cache);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cmGeneratorFileSets::BuildInfoCache(std::string const& config) const
|
||||
@@ -163,16 +385,31 @@ void cmGeneratorFileSets::BuildInfoCache(std::string const& config) const
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto const& item : this->FileSets) {
|
||||
cm::GenEx::Context context(this->LocalGenerator, config);
|
||||
auto const* file_set = item.second.get();
|
||||
cm::GenEx::Context context(this->LocalGenerator, config);
|
||||
|
||||
auto files = file_set->GetFiles(context, this->Target);
|
||||
for (auto const& item : this->FileSets) {
|
||||
auto const* fileSet = item.second.get();
|
||||
|
||||
auto files = fileSet->GetFiles(context, this->Target);
|
||||
|
||||
for (auto const& it : files.first) {
|
||||
for (auto const& filename : it.second) {
|
||||
auto collapsedFile = cmSystemTools::CollapseFullPath(filename);
|
||||
info.FileSetCache[collapsedFile] = file_set;
|
||||
info.FileSetCache[collapsedFile] = fileSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// retrieve all files inherited from dependent targets
|
||||
std::unordered_set<cmGeneratorTarget const*> targets;
|
||||
|
||||
if (cmLinkImplementationLibraries const* impl =
|
||||
this->Target->GetLinkImplementationLibraries(
|
||||
config, cmGeneratorTarget::UseTo::Compile)) {
|
||||
for (cmLinkItem const& lib : impl->Libraries) {
|
||||
if (lib.Target) {
|
||||
GetInterfaceFiles(lib.Target, context, targets,
|
||||
info.InterfaceFileSetCache);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "cmConfigure.h" // IWYU pragma: keep
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -17,6 +18,7 @@
|
||||
namespace cm {
|
||||
namespace GenEx {
|
||||
struct Context;
|
||||
struct Evaluation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +66,24 @@ public:
|
||||
cmGeneratorTarget const* target,
|
||||
cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;
|
||||
|
||||
std::vector<std::unique_ptr<TargetPropertyEntry>> GetInterfaceSources(
|
||||
cm::GenEx::Context const& context, cmGeneratorTarget const* target,
|
||||
cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;
|
||||
std::vector<std::unique_ptr<TargetPropertyEntry>> GetInterfaceSources(
|
||||
std::string type, cm::GenEx::Context const& context,
|
||||
cmGeneratorTarget const* target,
|
||||
cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;
|
||||
|
||||
std::string EvaluateInterfaceProperty(
|
||||
cm::string_view type, std::string const& prop, cm::GenEx::Evaluation* eval,
|
||||
cmGeneratorExpressionDAGChecker* dagCheckerParent) const;
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<cm::TargetPropertyEntry>> GetSources(
|
||||
std::function<bool(cmGeneratorFileSet const*)> include,
|
||||
cm::GenEx::Context const& context, cmGeneratorTarget const* target,
|
||||
cmGeneratorExpressionDAGChecker* dagChecker) const;
|
||||
|
||||
// file sets indexed by name
|
||||
std::map<std::string, std::unique_ptr<cmGeneratorFileSet>> FileSets;
|
||||
std::vector<cmGeneratorFileSet const*> AllFileSets;
|
||||
@@ -75,10 +94,16 @@ private:
|
||||
std::unordered_map<cm::string_view, std::vector<cmGeneratorFileSet const*>>
|
||||
InterfaceFileSets;
|
||||
|
||||
mutable std::unordered_map<std::string, bool> MaybeInterfacePropertyExists;
|
||||
bool MaybeHaveInterfaceProperty(cm::string_view type,
|
||||
std::string const& prop,
|
||||
cm::GenEx::Evaluation* eval) const;
|
||||
|
||||
struct InfoByConfig
|
||||
{
|
||||
bool BuiltCache = false;
|
||||
std::map<std::string, cmGeneratorFileSet const*> FileSetCache;
|
||||
std::map<std::string, cmGeneratorFileSet const*> InterfaceFileSetCache;
|
||||
};
|
||||
mutable std::map<std::string, InfoByConfig> Configs;
|
||||
|
||||
|
||||
@@ -92,12 +92,11 @@ static void CreatePropertyGeneratorExpressions(
|
||||
|
||||
cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
|
||||
: Target(t)
|
||||
, Makefile(t->GetMakefile())
|
||||
, LocalGenerator(lg)
|
||||
, GlobalGenerator(lg->GetGlobalGenerator())
|
||||
, FileSets(cm::make_unique<cmGeneratorFileSets>(this, lg))
|
||||
{
|
||||
this->Makefile = this->Target->GetMakefile();
|
||||
this->LocalGenerator = lg;
|
||||
this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
|
||||
|
||||
this->GlobalGenerator->ComputeTargetObjectDirectory(this);
|
||||
|
||||
CreatePropertyGeneratorExpressions(*lg->GetCMakeInstance(),
|
||||
@@ -5884,12 +5883,8 @@ bool cmGeneratorTarget::HaveFortranSources() const
|
||||
|
||||
bool cmGeneratorTarget::HaveCxx20ModuleSources() const
|
||||
{
|
||||
auto const& fileSets = this->GetAllFileSets();
|
||||
return std::any_of(fileSets.begin(), fileSets.end(),
|
||||
[](cmGeneratorFileSet const* file_set) -> bool {
|
||||
auto const& fs_type = file_set->GetType();
|
||||
return fs_type == cm::FileSetMetadata::CXX_MODULES;
|
||||
});
|
||||
return !this->GetFileSets(cm::FileSetMetadata::CXX_MODULES).empty() ||
|
||||
!this->GetInterfaceFileSets(cm::FileSetMetadata::CXX_MODULES).empty();
|
||||
}
|
||||
|
||||
cmGeneratorTarget::Cxx20SupportLevel cmGeneratorTarget::HaveCxxModuleSupport(
|
||||
|
||||
@@ -244,8 +244,12 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths(
|
||||
}
|
||||
|
||||
// Collect this target's file sets.
|
||||
cmGeneratorExpressionDAGChecker fsDagChecker{
|
||||
this, "SOURCES", nullptr, nullptr, context,
|
||||
};
|
||||
|
||||
cm::EvaluatedTargetPropertyEntries fileSetEntries;
|
||||
AddFileSetEntries(this, this->FileSets.get(), context, &dagChecker,
|
||||
AddFileSetEntries(this, this->FileSets.get(), context, &fsDagChecker,
|
||||
fileSetEntries);
|
||||
auto processFileSetEntry = [this, &config](cmSourceFile* sf) {
|
||||
auto const* fileSet = this->GetFileSetForSource(config, sf);
|
||||
@@ -273,9 +277,19 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths(
|
||||
processSources(this, config, fileSetEntries, files, uniqueSrcs,
|
||||
debugSources, processFileSetEntry);
|
||||
|
||||
// Collect file sets INTERFACE_SOURCES of all direct link-dependencies.
|
||||
cm::EvaluatedTargetPropertyEntries linkInterfaceFileSetsEntries;
|
||||
cm::AddInterfaceFileSetsEntries(this, cm::FileSetMetadata::SOURCES,
|
||||
"INTERFACE_SOURCES", context, &fsDagChecker,
|
||||
linkInterfaceFileSetsEntries);
|
||||
bool contextDependentInterfaceFileSets =
|
||||
processSources(this, config, linkInterfaceFileSetsEntries, files,
|
||||
uniqueSrcs, debugSources);
|
||||
|
||||
// Determine if sources are context-dependent or not.
|
||||
if (!contextDependentDirectSources && !contextDependentInterfaceSources &&
|
||||
!contextDependentObjects && !contextDependentFileSets) {
|
||||
!contextDependentObjects && !contextDependentFileSets &&
|
||||
!contextDependentInterfaceFileSets) {
|
||||
this->SourcesAreContextDependent = Tribool::False;
|
||||
} else {
|
||||
this->SourcesAreContextDependent = Tribool::True;
|
||||
|
||||
@@ -10,15 +10,19 @@
|
||||
#include <vector>
|
||||
|
||||
#include <cm/optional>
|
||||
#include <cmext/string_view>
|
||||
|
||||
#include "cmCustomCommand.h"
|
||||
#include "cmCustomCommandGenerator.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGeneratorFileSet.h"
|
||||
#include "cmGeneratorFileSets.h"
|
||||
#include "cmGeneratorOptions.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmGlobalGhsMultiGenerator.h"
|
||||
#include "cmLinkLineComputer.h" // IWYU pragma: keep
|
||||
#include "cmList.h"
|
||||
#include "cmListFileCache.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmLocalGhsMultiGenerator.h"
|
||||
#include "cmMakefile.h"
|
||||
@@ -503,6 +507,34 @@ void cmGhsMultiTargetGenerator::WriteSourceProperty(
|
||||
}
|
||||
}
|
||||
|
||||
void cmGhsMultiTargetGenerator::WriteFileSetProperty(
|
||||
std::ostream& fout, cmGeneratorFileSet const* fileSet,
|
||||
std::string const& lang, cm::string_view propName, cm::string_view propFlag)
|
||||
{
|
||||
if (!fileSet) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<BT<std::string>> entries;
|
||||
if (propName == "COMPILE_OPTIONS"_s) {
|
||||
entries = fileSet->BelongsTo(this->GeneratorTarget)
|
||||
? fileSet->GetCompileOptions(this->ConfigName, lang)
|
||||
: fileSet->GetInterfaceCompileOptions(this->ConfigName, lang);
|
||||
} else if (propName == "COMPILE_DEFINITIONS"_s) {
|
||||
entries = fileSet->BelongsTo(this->GeneratorTarget)
|
||||
? fileSet->GetCompileDefinitions(this->ConfigName, lang)
|
||||
: fileSet->GetInterfaceCompileDefinitions(this->ConfigName, lang);
|
||||
} else if (propName == "INCLUDE_DIRECTORIES"_s) {
|
||||
entries = fileSet->BelongsTo(this->GeneratorTarget)
|
||||
? fileSet->GetIncludeDirectories(this->ConfigName, lang)
|
||||
: fileSet->GetInterfaceIncludeDirectories(this->ConfigName, lang);
|
||||
}
|
||||
|
||||
for (auto const& entry : entries) {
|
||||
fout << " " << propFlag << entry.Value << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
|
||||
{
|
||||
/* vector of all sources for this target */
|
||||
@@ -642,9 +674,20 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
|
||||
|
||||
*fout << comment << fname << WriteObjectLangOverride(si) << '\n';
|
||||
if (compile) {
|
||||
// lookup for the associated file set, if any.
|
||||
auto const* fileSet =
|
||||
this->GeneratorTarget->GetGeneratorFileSets()->GetFileSetForSource(
|
||||
this->ConfigName, si);
|
||||
|
||||
this->WriteFileSetProperty(*fout, fileSet, si->GetLanguage(),
|
||||
"INCLUDE_DIRECTORIES"_s, "");
|
||||
this->WriteSourceProperty(*fout, si, "INCLUDE_DIRECTORIES", "-I");
|
||||
this->WriteSourceProperty(*fout, si, "COMPILE_DEFINITIONS", "-D");
|
||||
this->WriteFileSetProperty(*fout, fileSet, si->GetLanguage(),
|
||||
"COMPILE_DEFINITIONS"_s, "");
|
||||
this->WriteSourceProperty(*fout, si, "COMPILE_OPTIONS", "");
|
||||
this->WriteFileSetProperty(*fout, fileSet, si->GetLanguage(),
|
||||
"COMPILE_OPTIONS"_s, "");
|
||||
|
||||
/* to avoid clutter in the GUI only print out the objectName if it
|
||||
* has been renamed */
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <cm/string_view>
|
||||
|
||||
#include "cmGhsMultiGpj.h"
|
||||
|
||||
class cmCustomCommand;
|
||||
@@ -17,6 +19,7 @@ class cmGlobalGhsMultiGenerator;
|
||||
class cmLocalGhsMultiGenerator;
|
||||
class cmMakefile;
|
||||
class cmSourceFile;
|
||||
class cmGeneratorFileSet;
|
||||
|
||||
class cmGhsMultiTargetGenerator
|
||||
{
|
||||
@@ -65,6 +68,10 @@ private:
|
||||
void WriteSourceProperty(std::ostream& fout, cmSourceFile const* sf,
|
||||
std::string const& propName,
|
||||
std::string const& propFlag);
|
||||
void WriteFileSetProperty(std::ostream& fout,
|
||||
cmGeneratorFileSet const* fileSet,
|
||||
std::string const& lang, cm::string_view propName,
|
||||
cm::string_view propFlag);
|
||||
static std::string WriteObjectLangOverride(cmSourceFile const* sourceFile);
|
||||
|
||||
bool DetermineIfIntegrityApp();
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include "cmCustomCommandTypes.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGeneratorFileSet.h"
|
||||
#include "cmGeneratorFileSets.h"
|
||||
#include "cmGeneratorOptions.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmGlobalGeneratorFactory.h"
|
||||
@@ -1091,6 +1093,12 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
|
||||
break;
|
||||
}
|
||||
|
||||
// lookup for the associated file set, if any.
|
||||
//// sources are independent of the config but needed here
|
||||
auto const& config = this->CurrentConfigurationTypes[0];
|
||||
auto const* fileSet =
|
||||
gtgt->GetGeneratorFileSets()->GetFileSetForSource(config, sf);
|
||||
|
||||
// Explicitly add the explicit language flag before any other flag
|
||||
// so user flags can override it.
|
||||
gtgt->AddExplicitLanguageFlags(flags, *sf);
|
||||
@@ -1104,6 +1112,15 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
|
||||
lg->AppendCompileOptions(
|
||||
flags, genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS));
|
||||
}
|
||||
// Add flags from file set properties.
|
||||
if (fileSet) {
|
||||
auto options = fileSet->BelongsTo(gtgt)
|
||||
? fileSet->GetCompileOptions(config, lang)
|
||||
: fileSet->GetInterfaceCompileOptions(config, lang);
|
||||
if (!options.empty()) {
|
||||
lg->AppendCompileOptions(flags, cm::remove_BT(options));
|
||||
}
|
||||
}
|
||||
|
||||
// Add per-source definitions.
|
||||
BuildObjectListOrString flagsBuild(this, false);
|
||||
@@ -1114,6 +1131,15 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
|
||||
genexInterpreter.Evaluate(*compile_defs, COMPILE_DEFINITIONS).c_str(),
|
||||
true);
|
||||
}
|
||||
// Add file set preprocessor definitions
|
||||
if (fileSet) {
|
||||
auto fsDefines = fileSet->BelongsTo(gtgt)
|
||||
? fileSet->GetCompileDefinitions(config, lang)
|
||||
: fileSet->GetInterfaceCompileDefinitions(config, lang);
|
||||
if (!fsDefines.empty()) {
|
||||
this->AppendDefines(flagsBuild, cm::remove_BT(fsDefines), true);
|
||||
}
|
||||
}
|
||||
|
||||
if (sf->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) {
|
||||
this->AppendDefines(flagsBuild, "CMAKE_SKIP_PRECOMPILE_HEADERS", true);
|
||||
@@ -1126,8 +1152,17 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
|
||||
flags += flagsBuild.GetString();
|
||||
}
|
||||
|
||||
// Add per-source include directories.
|
||||
std::vector<std::string> includes;
|
||||
// Add include directories from file set properties.
|
||||
if (fileSet) {
|
||||
auto fsIncludes = fileSet->BelongsTo(gtgt)
|
||||
? fileSet->GetIncludeDirectories(config, lang)
|
||||
: fileSet->GetInterfaceIncludeDirectories(config, lang);
|
||||
if (!fsIncludes.empty()) {
|
||||
lg->AppendIncludeDirectories(includes, cm::remove_BT(fsIncludes), *sf);
|
||||
}
|
||||
}
|
||||
// Add per-source include directories.
|
||||
std::string const INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
|
||||
if (cmValue cincludes = sf->GetProperty(INCLUDE_DIRECTORIES)) {
|
||||
lg->AppendIncludeDirectories(
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
#include <cm/optional>
|
||||
#include <cm/string_view>
|
||||
#include <cmext/type_traits>
|
||||
|
||||
#include "cmList.h"
|
||||
#include "cmStack.h"
|
||||
@@ -220,6 +219,7 @@ template <typename T>
|
||||
std::vector<T> remove_BT(std::vector<BT<T>> const& container)
|
||||
{
|
||||
std::vector<T> result;
|
||||
result.reserve(container.size());
|
||||
for (auto const& entry : container) {
|
||||
result.emplace_back(entry.Value);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "cmCustomCommandLines.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGeneratorFileSet.h"
|
||||
#include "cmGeneratorFileSets.h"
|
||||
#include "cmGeneratorOptions.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
@@ -1496,6 +1498,9 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
|
||||
}
|
||||
|
||||
cmGeneratorExpressionInterpreter genexInterpreter(lg, config, gt, lang);
|
||||
// lookup for the associated file set, if any.
|
||||
auto const* fileSet =
|
||||
gt->GetGeneratorFileSets()->GetFileSetForSource(config, &sf);
|
||||
|
||||
bool needfc = false;
|
||||
if (!objectName.empty()) {
|
||||
@@ -1514,6 +1519,15 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
|
||||
genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS));
|
||||
needfc = true;
|
||||
}
|
||||
// Add flags from file set properties.
|
||||
if (fileSet) {
|
||||
auto options = fileSet->BelongsTo(gt)
|
||||
? fileSet->GetCompileOptions(config, lang)
|
||||
: fileSet->GetInterfaceCompileOptions(config, lang);
|
||||
if (!options.empty()) {
|
||||
lg->AppendCompileOptions(fc.CompileFlags, cm::remove_BT(options));
|
||||
}
|
||||
}
|
||||
// Add precompile headers compile options.
|
||||
std::string const pchSource = gt->GetPchSource(config, lang);
|
||||
if (!pchSource.empty() && !sf.GetProperty("SKIP_PRECOMPILE_HEADERS")) {
|
||||
@@ -1570,10 +1584,36 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
|
||||
genexInterpreter.Evaluate(*ccdefs, COMPILE_DEFINITIONS);
|
||||
needfc = true;
|
||||
}
|
||||
// Add file set preprocessor definitions
|
||||
if (fileSet) {
|
||||
auto defines = fileSet->BelongsTo(gt)
|
||||
? fileSet->GetCompileDefinitions(config, lang)
|
||||
: fileSet->GetInterfaceCompileDefinitions(config, lang);
|
||||
if (!defines.empty()) {
|
||||
if (!fc.CompileDefs.empty()) {
|
||||
fc.CompileDefs += ';';
|
||||
}
|
||||
fc.CompileDefs += cmList::to_string(defines);
|
||||
needfc = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Add file set include directories definitions
|
||||
if (fileSet) {
|
||||
auto includes = fileSet->BelongsTo(gt)
|
||||
? fileSet->GetIncludeDirectories(config, lang)
|
||||
: fileSet->GetInterfaceIncludeDirectories(config, lang);
|
||||
if (!includes.empty()) {
|
||||
fc.IncludeDirs = cmList::to_string(includes);
|
||||
needfc = true;
|
||||
}
|
||||
}
|
||||
std::string const INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
|
||||
if (cmValue cincs = sf.GetProperty(INCLUDE_DIRECTORIES)) {
|
||||
fc.IncludeDirs = genexInterpreter.Evaluate(*cincs, INCLUDE_DIRECTORIES);
|
||||
if (!fc.IncludeDirs.empty()) {
|
||||
fc.IncludeDirs += ';';
|
||||
}
|
||||
fc.IncludeDirs += genexInterpreter.Evaluate(*cincs, INCLUDE_DIRECTORIES);
|
||||
needfc = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,11 +29,13 @@
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGeneratorFileSet.h"
|
||||
#include "cmGeneratorFileSets.h"
|
||||
#include "cmGeneratorOptions.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmGlobalUnixMakefileGenerator3.h"
|
||||
#include "cmLinkLineComputer.h" // IWYU pragma: keep
|
||||
#include "cmList.h"
|
||||
#include "cmListFileCache.h"
|
||||
#include "cmLocalCommonGenerator.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmLocalUnixMakefileGenerator3.h"
|
||||
@@ -55,7 +57,6 @@
|
||||
#include "cmStateTypes.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmTarget.h"
|
||||
#include "cmValue.h"
|
||||
#include "cmake.h"
|
||||
|
||||
@@ -346,18 +347,6 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> file_set_map;
|
||||
|
||||
auto const* tgt = this->GeneratorTarget->Target;
|
||||
for (auto const* file_set : this->GeneratorTarget->GetAllFileSets()) {
|
||||
auto files = file_set->GetFiles(context, this->GeneratorTarget).first;
|
||||
for (auto const& it : files) {
|
||||
for (auto const& filename : it.second) {
|
||||
file_set_map[filename] = file_set->GetType();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<cmSourceFile const*> objectSources;
|
||||
this->GeneratorTarget->GetObjectSources(objectSources,
|
||||
this->GetConfigName());
|
||||
@@ -372,20 +361,17 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
|
||||
}
|
||||
|
||||
for (cmSourceFile const* sf : objectSources) {
|
||||
auto const& path = sf->GetFullPath();
|
||||
auto const it = file_set_map.find(path);
|
||||
if (it != file_set_map.end()) {
|
||||
auto const& file_set_type = it->second;
|
||||
if (file_set_type == cm::FileSetMetadata::CXX_MODULES) {
|
||||
if (sf->GetLanguage() != "CXX"_s) {
|
||||
this->Makefile->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
cmStrCat(
|
||||
"Target \"", tgt->GetName(), "\" contains the source\n ", path,
|
||||
"\nin a file set of type \"", file_set_type,
|
||||
R"(" but the source is not classified as a "CXX" source.)"));
|
||||
}
|
||||
}
|
||||
cmGeneratorFileSet const* fileSet =
|
||||
this->GeneratorTarget->GetFileSetForSource(this->GetConfigName(), sf);
|
||||
if (fileSet && fileSet->GetType() == cm::FileSetMetadata::CXX_MODULES &&
|
||||
sf->GetLanguage() != "CXX"_s) {
|
||||
this->Makefile->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
cmStrCat("Target \"", this->GeneratorTarget->GetName(),
|
||||
"\" contains the source\n ", sf->GetFullPath(),
|
||||
"\nin a file set of type \"",
|
||||
cm::FileSetMetadata::CXX_MODULES,
|
||||
R"(" but the source is not classified as a "CXX" source.)"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -765,6 +751,11 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
|
||||
ispcHeaderRelative, cmOutputConverter::SHELL);
|
||||
}
|
||||
|
||||
// lookup for the associated file set, if any.
|
||||
auto const* fileSet =
|
||||
this->GeneratorTarget->GetGeneratorFileSets()->GetFileSetForSource(
|
||||
config, &source);
|
||||
|
||||
// Add flags from source file properties.
|
||||
std::string const COMPILE_FLAGS("COMPILE_FLAGS");
|
||||
if (cmValue cflags = source.GetProperty(COMPILE_FLAGS)) {
|
||||
@@ -786,6 +777,22 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
// Add flags from file set properties.
|
||||
if (fileSet) {
|
||||
auto options = fileSet->BelongsTo(this->GeneratorTarget)
|
||||
? fileSet->GetCompileOptions(config, lang)
|
||||
: fileSet->GetInterfaceCompileOptions(config, lang);
|
||||
if (!options.empty()) {
|
||||
this->LocalGenerator->AppendCompileOptions(flags,
|
||||
cm::remove_BT(options));
|
||||
*this->FlagFileStream << "# Custom options (File Set '"
|
||||
<< fileSet->GetName() << "'): " << relativeObj
|
||||
<< "_OPTIONS = " << cmList::to_string(options)
|
||||
<< "\n"
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Add precompile headers compile options.
|
||||
if (!pchSources.empty() && !source.GetProperty("SKIP_PRECOMPILE_HEADERS")) {
|
||||
std::string pchOptions;
|
||||
@@ -807,9 +814,25 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
// Add include directories from source file properties.
|
||||
// Add include directories from file set properties.
|
||||
std::vector<std::string> includes;
|
||||
|
||||
if (fileSet) {
|
||||
auto fsIncludes = fileSet->BelongsTo(this->GeneratorTarget)
|
||||
? fileSet->GetIncludeDirectories(config, lang)
|
||||
: fileSet->GetInterfaceIncludeDirectories(config, lang);
|
||||
if (!fsIncludes.empty()) {
|
||||
this->LocalGenerator->AppendIncludeDirectories(
|
||||
includes, cm::remove_BT(fsIncludes), source);
|
||||
*this->FlagFileStream
|
||||
<< "# Custom include directories (File Set '" << fileSet->GetName()
|
||||
<< "'): " << relativeObj
|
||||
<< "_INCLUDE_DIRECTORIES = " << cmList::to_string(fsIncludes) << "\n"
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Add include directories from source file properties.
|
||||
std::string const INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
|
||||
if (cmValue cincludes = source.GetProperty(INCLUDE_DIRECTORIES)) {
|
||||
std::string const& evaluatedIncludes =
|
||||
@@ -846,6 +869,21 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
// Add file set preprocessor definitions
|
||||
if (fileSet) {
|
||||
auto fsDefines = fileSet->BelongsTo(this->GeneratorTarget)
|
||||
? fileSet->GetCompileDefinitions(config, lang)
|
||||
: fileSet->GetInterfaceCompileDefinitions(config, lang);
|
||||
if (!fsDefines.empty()) {
|
||||
this->LocalGenerator->AppendDefines(defines, fsDefines);
|
||||
*this->FlagFileStream << "# Custom defines (File Set '"
|
||||
<< fileSet->GetName() << "'): " << relativeObj
|
||||
<< "_DEFINES = " << cmList::to_string(fsDefines)
|
||||
<< "\n"
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Get the output paths for source and object files.
|
||||
std::string const sourceFile = this->LocalGenerator->ConvertToOutputFormat(
|
||||
source.GetFullPath(), cmOutputConverter::SHELL);
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGeneratorFileSet.h"
|
||||
#include "cmGeneratorFileSets.h"
|
||||
#include "cmGeneratorOptions.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmGlobalCommonGenerator.h"
|
||||
@@ -238,6 +239,18 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
|
||||
flags, genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS));
|
||||
}
|
||||
|
||||
if (auto const* fileSet =
|
||||
this->GeneratorTarget->GetGeneratorFileSets()->GetFileSetForSource(
|
||||
config, source)) {
|
||||
auto options = fileSet->BelongsTo(this->GeneratorTarget)
|
||||
? fileSet->GetCompileOptions(config, language)
|
||||
: fileSet->GetInterfaceCompileOptions(config, language);
|
||||
if (!options.empty()) {
|
||||
this->LocalGenerator->AppendCompileOptions(flags,
|
||||
cm::remove_BT(options));
|
||||
}
|
||||
}
|
||||
|
||||
// Add precompile headers compile options.
|
||||
if (!pchSources.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) {
|
||||
std::string pchOptions;
|
||||
@@ -331,6 +344,17 @@ std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source,
|
||||
genexInterpreter.Evaluate(*config_compile_defs, COMPILE_DEFINITIONS));
|
||||
}
|
||||
|
||||
if (auto const* fileSet =
|
||||
this->GeneratorTarget->GetGeneratorFileSets()->GetFileSetForSource(
|
||||
config, source)) {
|
||||
auto fsDefines = fileSet->BelongsTo(this->GeneratorTarget)
|
||||
? fileSet->GetCompileDefinitions(config, language)
|
||||
: fileSet->GetInterfaceCompileDefinitions(config, language);
|
||||
if (!fsDefines.empty()) {
|
||||
this->LocalGenerator->AppendDefines(defines, fsDefines);
|
||||
}
|
||||
}
|
||||
|
||||
std::string definesString = this->GetDefines(language, config);
|
||||
this->LocalGenerator->JoinDefines(defines, definesString, language);
|
||||
|
||||
@@ -342,6 +366,19 @@ std::string cmNinjaTargetGenerator::ComputeIncludes(
|
||||
std::string const& config)
|
||||
{
|
||||
std::vector<std::string> includes;
|
||||
|
||||
if (auto const* fileSet =
|
||||
this->GeneratorTarget->GetGeneratorFileSets()->GetFileSetForSource(
|
||||
config, source)) {
|
||||
auto fsIncludes = fileSet->BelongsTo(this->GeneratorTarget)
|
||||
? fileSet->GetIncludeDirectories(config, language)
|
||||
: fileSet->GetInterfaceIncludeDirectories(config, language);
|
||||
if (!fsIncludes.empty()) {
|
||||
this->LocalGenerator->AppendIncludeDirectories(
|
||||
includes, cm::remove_BT(fsIncludes), *source);
|
||||
}
|
||||
}
|
||||
|
||||
cmGeneratorExpressionInterpreter genexInterpreter(
|
||||
this->LocalGenerator, config, this->GeneratorTarget, language);
|
||||
|
||||
|
||||
@@ -714,6 +714,12 @@ cmTargetInternals::cmTargetInternals()
|
||||
"Header"_s, "The default header set"_s, "Header set"_s,
|
||||
FileSetEntries{ "HEADER_SETS"_s },
|
||||
FileSetEntries{ "INTERFACE_HEADER_SETS"_s } } },
|
||||
{ cm::FileSetMetadata::SOURCES,
|
||||
{ cm::FileSetMetadata::SOURCES, "SOURCE_DIRS"_s,
|
||||
"SOURCE_SET"_s, "SOURCE_DIRS_"_s, "SOURCE_SET_"_s,
|
||||
"Source"_s, "The default source set"_s, "Source set"_s,
|
||||
FileSetEntries{ "SOURCE_SETS"_s },
|
||||
FileSetEntries{ "INTERFACE_SOURCE_SETS"_s } } },
|
||||
{ cm::FileSetMetadata::CXX_MODULES,
|
||||
{ cm::FileSetMetadata::CXX_MODULES, "CXX_MODULE_DIRS"_s,
|
||||
"CXX_MODULE_SET"_s, "CXX_MODULE_DIRS_"_s,
|
||||
|
||||
@@ -284,7 +284,7 @@ bool TargetSourcesImpl::HandleOneFileSet(
|
||||
this->SetError(
|
||||
cmStrCat(R"(File set TYPE ")", cm::FileSetMetadata::CXX_MODULES,
|
||||
R"(" may not have "PUBLIC" )"
|
||||
R"(or "PRIVATE" visibility on INTERFACE libraries.)"));
|
||||
R"(or "PRIVATE" scope on INTERFACE libraries.)"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -297,11 +297,21 @@ bool TargetSourcesImpl::HandleOneFileSet(
|
||||
if (type == cm::FileSetMetadata::CXX_MODULES) {
|
||||
this->SetError(cmStrCat(R"(File set TYPE ")",
|
||||
cm::FileSetMetadata::CXX_MODULES,
|
||||
R"(" may not have "INTERFACE" visibility)"));
|
||||
R"(" may not have "INTERFACE" scope)"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (cm::FileSetMetadata::VisibilityIsForSelf(visibility) &&
|
||||
this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY &&
|
||||
type == cm::FileSetMetadata::SOURCES) {
|
||||
this->SetError(
|
||||
cmStrCat(R"(File set TYPE ")", cm::FileSetMetadata::SOURCES,
|
||||
R"(" may not have "PUBLIC" )"
|
||||
R"(or "PRIVATE" scope on INTERFACE libraries.)"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.BaseDirs.empty()) {
|
||||
args.BaseDirs.emplace_back(this->Makefile->GetCurrentSourceDirectory());
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGeneratorFileSet.h"
|
||||
#include "cmGeneratorFileSets.h"
|
||||
#include "cmGeneratorOptions.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
@@ -2883,14 +2884,36 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
|
||||
configDefines += *ccdefs;
|
||||
}
|
||||
|
||||
// lookup for the associated file set, if any.
|
||||
auto const* fileSet =
|
||||
this->GeneratorTarget->GetFileSetForSource(config, source);
|
||||
bool fileSetBelongsToTarget = false;
|
||||
std::vector<std::string> fsOptions;
|
||||
std::vector<std::string> fsDefines;
|
||||
std::vector<std::string> fsIncludes;
|
||||
|
||||
if (fileSet) {
|
||||
fileSetBelongsToTarget = fileSet->BelongsTo(this->GeneratorTarget);
|
||||
fsOptions =
|
||||
cm::remove_BT(fileSetBelongsToTarget
|
||||
? fileSet->GetCompileOptions(config, lang)
|
||||
: fileSet->GetInterfaceCompileOptions(config, lang));
|
||||
fsDefines = cm::remove_BT(
|
||||
fileSetBelongsToTarget
|
||||
? fileSet->GetCompileDefinitions(config, lang)
|
||||
: fileSet->GetInterfaceCompileDefinitions(config, lang));
|
||||
fsIncludes = cm::remove_BT(
|
||||
fileSetBelongsToTarget
|
||||
? fileSet->GetIncludeDirectories(config, lang)
|
||||
: fileSet->GetInterfaceIncludeDirectories(config, lang));
|
||||
}
|
||||
|
||||
bool const shouldScanForModules = lang == "CXX"_s &&
|
||||
this->GeneratorTarget->NeedDyndepForSource(lang, config, source);
|
||||
auto const* fs =
|
||||
this->GeneratorTarget->GetFileSetForSource(config, source);
|
||||
char const* compileAsPerConfig = compileAs;
|
||||
if (fs && fs->GetType() == cm::FileSetMetadata::CXX_MODULES) {
|
||||
if (fileSet && fileSet->GetType() == cm::FileSetMetadata::CXX_MODULES) {
|
||||
if (lang == "CXX"_s) {
|
||||
if (fs->GetType() == cm::FileSetMetadata::CXX_MODULES) {
|
||||
if (fileSet->GetType() == cm::FileSetMetadata::CXX_MODULES) {
|
||||
isCppModule = true;
|
||||
if (shouldScanForModules &&
|
||||
this->GlobalGenerator->IsScanDependenciesSupported()) {
|
||||
@@ -2909,7 +2932,7 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
|
||||
cmStrCat(
|
||||
"Target \"", this->GeneratorTarget->Target->GetName(),
|
||||
"\" contains the source\n ", source->GetFullPath(),
|
||||
"\nin a file set of type \"", fs->GetType(),
|
||||
"\nin a file set of type \"", fileSet->GetType(),
|
||||
R"(" but the source is not classified as a "CXX" source.)"));
|
||||
}
|
||||
}
|
||||
@@ -2935,9 +2958,10 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
|
||||
|
||||
// if we have flags or defines for this config then
|
||||
// use them
|
||||
if (!flags.empty() || !options.empty() || !configDefines.empty() ||
|
||||
!includes.empty() || compileAsPerConfig || noWinRT ||
|
||||
!options.empty() || needsPCHFlags ||
|
||||
if (!flags.empty() || !options.empty() || !fsOptions.empty() ||
|
||||
!configDefines.empty() || !fsDefines.empty() || !includes.empty() ||
|
||||
!fsIncludes.empty() || compileAsPerConfig || noWinRT ||
|
||||
needsPCHFlags ||
|
||||
(shouldScanForModules !=
|
||||
this->ScanSourceForModuleDependencies[config])) {
|
||||
cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
|
||||
@@ -3010,8 +3034,8 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
|
||||
}
|
||||
}
|
||||
|
||||
std::string expandedOptions;
|
||||
if (!options.empty()) {
|
||||
std::string expandedOptions;
|
||||
if (configDependentOptions) {
|
||||
this->LocalGenerator->AppendCompileOptions(
|
||||
expandedOptions,
|
||||
@@ -3019,6 +3043,12 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
|
||||
} else {
|
||||
this->LocalGenerator->AppendCompileOptions(expandedOptions, options);
|
||||
}
|
||||
}
|
||||
// Add flags from file set properties.
|
||||
if (!fsOptions.empty()) {
|
||||
this->LocalGenerator->AppendCompileOptions(expandedOptions, fsOptions);
|
||||
}
|
||||
if (!expandedOptions.empty()) {
|
||||
clOptions.Parse(expandedOptions);
|
||||
}
|
||||
if (clOptions.HasFlag("DisableSpecificWarnings")) {
|
||||
@@ -3034,7 +3064,16 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
|
||||
} else {
|
||||
clOptions.AddDefines(configDefines);
|
||||
}
|
||||
// Add defines from file set properties.
|
||||
if (!fsDefines.empty()) {
|
||||
clOptions.AddDefines(fsDefines);
|
||||
}
|
||||
std::vector<std::string> includeList;
|
||||
// Add include directories from file set properties.
|
||||
if (!fsIncludes.empty()) {
|
||||
this->LocalGenerator->AppendIncludeDirectories(includeList, fsIncludes,
|
||||
*source);
|
||||
}
|
||||
if (configDependentIncludes) {
|
||||
this->LocalGenerator->AppendIncludeDirectories(
|
||||
includeList,
|
||||
|
||||
@@ -623,6 +623,8 @@ add_RunCMake_test(TargetArtifacts -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME})
|
||||
add_RunCMake_test(TargetObjects)
|
||||
add_RunCMake_test(TargetProperties)
|
||||
add_RunCMake_test(FileSetProperties)
|
||||
add_RunCMake_test(FileSet-SOURCES -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
|
||||
-DMSVC_VERSION=${MSVC_VERSION})
|
||||
add_RunCMake_test(ToolchainFile)
|
||||
|
||||
if(NOT CMake_TEST_EXTERNAL_CMAKE)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
CMake Error at FileSetModulesInterfaceOnInterface\.cmake:[0-9]+ \(target_sources\):
|
||||
target_sources File set TYPE "CXX_MODULES" may not have "INTERFACE"
|
||||
visibility
|
||||
target_sources File set TYPE "CXX_MODULES" may not have "INTERFACE" scope
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
CMake Error at FileSetModulesInterfaceOnStatic\.cmake:[0-9]+ \(target_sources\):
|
||||
target_sources File set TYPE "CXX_MODULES" may not have "INTERFACE"
|
||||
visibility
|
||||
target_sources File set TYPE "CXX_MODULES" may not have "INTERFACE" scope
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
^CMake Error at FileSetModulesPrivateOnInterface\.cmake:[0-9]+ \(target_sources\):
|
||||
target_sources File set TYPE "CXX_MODULES" may not have "PUBLIC" or
|
||||
"PRIVATE" visibility on INTERFACE libraries\.
|
||||
"PRIVATE" scope on INTERFACE libraries\.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)$
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
^CMake Error at FileSetModulesPublicOnInterface\.cmake:[0-9]+ \(target_sources\):
|
||||
target_sources File set TYPE "CXX_MODULES" may not have "PUBLIC" or
|
||||
"PRIVATE" visibility on INTERFACE libraries\.
|
||||
"PRIVATE" scope on INTERFACE libraries\.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)$
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
cmake_minimum_required(VERSION 4.0)
|
||||
project(${RunCMake_TEST} LANGUAGES NONE)
|
||||
include(${RunCMake_TEST}.cmake NO_POLICY_SCOPE)
|
||||
@@ -0,0 +1,9 @@
|
||||
if(RunCMake_GENERATOR MATCHES "Xcode")
|
||||
if (NOT actual_stdout MATCHES "-DOPT_SRC +-DOPT_FS")
|
||||
set (RunCMake_TEST_FAILED "Wrong compile options order.")
|
||||
endif()
|
||||
else()
|
||||
if (NOT actual_stdout MATCHES "(/|-)D *OPT_TGT.+(/|-)D *OPT_SRC.+(/|-)D *OPT_FS")
|
||||
set (RunCMake_TEST_FAILED "Wrong compile options order.")
|
||||
endif()
|
||||
endif()
|
||||
@@ -0,0 +1,15 @@
|
||||
enable_language(C)
|
||||
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
set(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS OFF)
|
||||
# ensure no temp file will be used
|
||||
string(REPLACE "${CMAKE_START_TEMP_FILE}" "" CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT}")
|
||||
string(REPLACE "${CMAKE_END_TEMP_FILE}" "" CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT}")
|
||||
|
||||
add_library(lib1 STATIC)
|
||||
target_sources(lib1 PUBLIC FILE_SET a TYPE SOURCES FILES lib1.c)
|
||||
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY COMPILE_OPTIONS -DOPT_FS)
|
||||
|
||||
set_property(TARGET lib1 PROPERTY COMPILE_OPTIONS -DOPT_TGT)
|
||||
set_property(SOURCE lib1.c PROPERTY COMPILE_OPTIONS -DOPT_SRC)
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
enable_language(C)
|
||||
|
||||
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/custom.c"
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/lib1.c"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/custom.c")
|
||||
|
||||
add_library(lib1 STATIC)
|
||||
target_sources(lib1 PRIVATE FILE_SET SOURCES BASE_DIRS "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
FILES "${CMAKE_CURRENT_BINARY_DIR}/custom.c")
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,4 @@
|
||||
CMake Error at FileNoExist\.cmake:[0-9]+ \(target_sources\):
|
||||
Cannot find source file:
|
||||
|
||||
.+/Tests/RunCMake/FileSet-SOURCES/noexist\.c
|
||||
@@ -0,0 +1,4 @@
|
||||
enable_language(C)
|
||||
|
||||
add_library(lib1 STATIC lib1.c)
|
||||
target_sources(lib1 PRIVATE FILE_SET SOURCES BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} FILES noexist.c)
|
||||
@@ -0,0 +1,19 @@
|
||||
enable_language(C)
|
||||
|
||||
add_library(lib1 STATIC)
|
||||
target_sources(lib1 PRIVATE lib1.c)
|
||||
target_sources(lib1 PUBLIC FILE_SET a TYPE SOURCES FILES lib2.c)
|
||||
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY COMPILE_DEFINITIONS LIB1_A)
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/subdir1")
|
||||
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_COMPILE_DEFINITIONS INTERFACE_LIB1_A)
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/subdir2")
|
||||
|
||||
add_executable(main main.c)
|
||||
target_link_libraries(main PRIVATE lib1)
|
||||
target_compile_definitions(main PRIVATE CONSUMER)
|
||||
|
||||
add_library(lib2 SHARED)
|
||||
target_link_libraries(lib2 PRIVATE lib1)
|
||||
target_compile_definitions(lib2 PRIVATE CONSUMER)
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
if (NOT actual_stdout MATCHES "(/|-)D *OPT_FS" OR actual_stdout MATCHES "(/|-)D *OPT_INTERFACE_FS")
|
||||
set (RunCMake_TEST_FAILED "Wrong compile options specified.")
|
||||
endif()
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
if (NOT actual_stdout MATCHES "(/|-)D *OPT_INTERFACE_FS" OR actual_stdout MATCHES "(/|-)D *OPT_FS")
|
||||
set (RunCMake_TEST_FAILED "Wrong compile options specified.")
|
||||
endif()
|
||||
@@ -0,0 +1,17 @@
|
||||
enable_language(C)
|
||||
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
set(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS OFF)
|
||||
# ensure no temp file will be used
|
||||
string(REPLACE "${CMAKE_START_TEMP_FILE}" "" CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT}")
|
||||
string(REPLACE "${CMAKE_END_TEMP_FILE}" "" CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT}")
|
||||
|
||||
add_library(lib1 STATIC)
|
||||
target_sources(lib1 PRIVATE lib1.c)
|
||||
target_sources(lib1 PUBLIC FILE_SET a TYPE SOURCES FILES lib4.c)
|
||||
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY COMPILE_OPTIONS -DOPT_FS)
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_COMPILE_OPTIONS -DOPT_INTERFACE_FS)
|
||||
|
||||
add_executable(main main.c)
|
||||
target_link_libraries(main PRIVATE lib1)
|
||||
@@ -0,0 +1,17 @@
|
||||
enable_language(C)
|
||||
|
||||
add_library(lib1 STATIC)
|
||||
target_sources(lib1 PUBLIC FILE_SET a TYPE SOURCES FILES lib2.c)
|
||||
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY COMPILE_DEFINITIONS LIB1_A)
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/subdir1")
|
||||
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_COMPILE_DEFINITIONS INTERFACE_LIB1_A)
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/subdir2")
|
||||
|
||||
add_library(lib2 STATIC lib1.c)
|
||||
target_link_libraries(lib2 INTERFACE lib1)
|
||||
|
||||
add_executable(main main.c)
|
||||
target_link_libraries(main PRIVATE lib2)
|
||||
target_compile_definitions(main PRIVATE CONSUMER)
|
||||
@@ -0,0 +1,11 @@
|
||||
enable_language(C)
|
||||
|
||||
add_library(lib1 STATIC)
|
||||
target_sources(lib1 PUBLIC FILE_SET a TYPE SOURCES FILES lib3.c)
|
||||
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/dir")
|
||||
|
||||
if(NOT CMAKE_GENERATOR MATCHES "Xcode")
|
||||
set_property(TARGET lib1 PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/subdir1")
|
||||
endif()
|
||||
set_property(SOURCE lib3.c PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/subdir2")
|
||||
@@ -0,0 +1,43 @@
|
||||
|
||||
include(RunCMake)
|
||||
|
||||
function(run_and_build test)
|
||||
if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
|
||||
set(config_options "-DCMAKE_CONFIGURATION_TYPES=Debug")
|
||||
else()
|
||||
set(config_options -DCMAKE_BUILD_TYPE=Debug)
|
||||
endif()
|
||||
set(RunCMake_TEST_OPTIONS ${config_options})
|
||||
set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/${test}-build")
|
||||
run_cmake_with_options(${test})
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
if(ARGN)
|
||||
foreach(target IN LISTS ARGN)
|
||||
run_cmake_command(${test}-${target} ${CMAKE_COMMAND} --build . --config Debug --target ${target} --verbose)
|
||||
endforeach()
|
||||
else()
|
||||
run_cmake_command(${test}-build ${CMAKE_COMMAND} --build . --config Debug --verbose)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(run_and_check test)
|
||||
set(RunCMake_TEST_OUTPUT_MERGE TRUE)
|
||||
run_and_build(${test} ${ARGN})
|
||||
endfunction()
|
||||
|
||||
|
||||
run_cmake(FileNoExist)
|
||||
run_cmake(TargetProperties)
|
||||
|
||||
run_and_build(FileSetProperties)
|
||||
run_and_build(CustomCommandInput)
|
||||
run_and_build(IncludeDirectoriesOrder)
|
||||
run_and_build(FileSetTransitivity)
|
||||
run_and_check(CompileOptionsOrder)
|
||||
|
||||
# Some environments are excluded because they are not able to honor verbose mode
|
||||
if ((RunCMake_GENERATOR MATCHES "Makefiles|Ninja|Xcode"
|
||||
OR (RunCMake_GENERATOR MATCHES "Visual Studio" AND MSVC_VERSION GREATER_EQUAL "1600"))
|
||||
AND NOT CMAKE_C_COMPILER_ID STREQUAL "Intel")
|
||||
run_and_check(FileSetProperties2 lib1 main)
|
||||
endif()
|
||||
@@ -0,0 +1,61 @@
|
||||
enable_language(C)
|
||||
|
||||
function(assert_prop_undef tgt prop)
|
||||
unset(actual_value)
|
||||
get_property(actual_value TARGET ${tgt} PROPERTY ${prop})
|
||||
if(DEFINED actual_value)
|
||||
message(SEND_ERROR "${prop} should be undefined, actual value:\n ${actual_value}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(assert_prop_eq tgt prop value)
|
||||
unset(actual_value)
|
||||
get_property(actual_value TARGET ${tgt} PROPERTY ${prop})
|
||||
if(NOT actual_value STREQUAL value)
|
||||
message(SEND_ERROR "Expected value of ${prop}:\n ${value}\nActual value:\n ${actual_value}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
add_library(lib1 STATIC)
|
||||
assert_prop_eq(lib1 SOURCE_SETS "")
|
||||
assert_prop_eq(lib1 INTERFACE_SOURCE_SETS "")
|
||||
|
||||
target_sources(lib1 PUBLIC FILE_SET a TYPE SOURCES BASE_DIRS "." FILES lib1.c lib2.c)
|
||||
assert_prop_eq(lib1 SOURCE_SETS "a")
|
||||
assert_prop_eq(lib1 INTERFACE_SOURCE_SETS "a")
|
||||
assert_prop_eq(lib1 SOURCE_DIRS_a "${CMAKE_CURRENT_SOURCE_DIR}/.")
|
||||
assert_prop_eq(lib1 SOURCE_SET_a "${CMAKE_CURRENT_SOURCE_DIR}/lib1.c;${CMAKE_CURRENT_SOURCE_DIR}/lib2.c")
|
||||
|
||||
target_sources(lib1 PUBLIC FILE_SET a FILES lib3.c)
|
||||
assert_prop_eq(lib1 SOURCE_SETS "a")
|
||||
assert_prop_eq(lib1 INTERFACE_SOURCE_SETS "a")
|
||||
assert_prop_eq(lib1 SOURCE_DIRS_a "${CMAKE_CURRENT_SOURCE_DIR}/.")
|
||||
assert_prop_eq(lib1 SOURCE_SET_a "${CMAKE_CURRENT_SOURCE_DIR}/lib1.c;${CMAKE_CURRENT_SOURCE_DIR}/lib2.c;${CMAKE_CURRENT_SOURCE_DIR}/lib3.c")
|
||||
|
||||
target_sources(lib1 PRIVATE FILE_SET b TYPE SOURCES BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/dir" FILES dir/dir.c)
|
||||
assert_prop_eq(lib1 SOURCE_SETS "a;b")
|
||||
assert_prop_eq(lib1 INTERFACE_SOURCE_SETS "a")
|
||||
assert_prop_eq(lib1 SOURCE_DIRS_b "${CMAKE_CURRENT_SOURCE_DIR}/dir")
|
||||
assert_prop_eq(lib1 SOURCE_SET_b "${CMAKE_CURRENT_SOURCE_DIR}/dir/dir.c")
|
||||
|
||||
target_sources(lib1 INTERFACE FILE_SET c TYPE SOURCES FILE_SET d TYPE SOURCES)
|
||||
assert_prop_eq(lib1 SOURCE_SETS "a;b")
|
||||
assert_prop_eq(lib1 INTERFACE_SOURCE_SETS "a;c;d")
|
||||
assert_prop_eq(lib1 SOURCE_DIRS_c "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
assert_prop_eq(lib1 SOURCE_SET_c "")
|
||||
assert_prop_eq(lib1 SOURCE_DIRS_d "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
assert_prop_eq(lib1 SOURCE_SET_d "")
|
||||
|
||||
target_sources(lib1 PUBLIC FILE_SET SOURCES BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}" FILES lib4.c)
|
||||
assert_prop_eq(lib1 INTERFACE_SOURCE_SETS "a;c;d;SOURCES")
|
||||
assert_prop_eq(lib1 SOURCE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
assert_prop_eq(lib1 SOURCE_SET "${CMAKE_CURRENT_SOURCE_DIR}/lib4.c")
|
||||
assert_prop_eq(lib1 SOURCE_DIRS_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
assert_prop_eq(lib1 SOURCE_SET_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/lib4.c")
|
||||
|
||||
target_sources(lib1 PUBLIC FILE_SET SOURCES FILES lib5.c)
|
||||
assert_prop_eq(lib1 INTERFACE_SOURCE_SETS "a;c;d;SOURCES")
|
||||
assert_prop_eq(lib1 SOURCE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
assert_prop_eq(lib1 SOURCE_SET "${CMAKE_CURRENT_SOURCE_DIR}/lib4.c;${CMAKE_CURRENT_SOURCE_DIR}/lib5.c")
|
||||
assert_prop_eq(lib1 SOURCE_DIRS_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
assert_prop_eq(lib1 SOURCE_SET_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/lib4.c;${CMAKE_CURRENT_SOURCE_DIR}/lib5.c")
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
#if defined(INTERFACE_LIB1_A)
|
||||
# error "INTERFACE_LIB1_A defined"
|
||||
#endif
|
||||
#if defined(LIB1_A)
|
||||
# error "LIB1_A defined"
|
||||
#endif
|
||||
#if defined(CONSUMER)
|
||||
# error "CONSUMER defined"
|
||||
#endif
|
||||
|
||||
void f1(void)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
#if defined(CONSUMER)
|
||||
# if defined(LIB1_A)
|
||||
# error "LIB1_A defined"
|
||||
# endif
|
||||
# if !defined(INTERFACE_LIB1_A)
|
||||
# error "INTERFACE_LIB1_A not defined"
|
||||
# endif
|
||||
|
||||
# include "h2.h"
|
||||
#else
|
||||
# if !defined(LIB1_A)
|
||||
# error "LIB1_A not defined"
|
||||
# endif
|
||||
# if defined(INTERFACE_LIB1_A)
|
||||
# error "INTERFACE_LIB1_A defined"
|
||||
# endif
|
||||
|
||||
# include "h1.h"
|
||||
#endif
|
||||
|
||||
void f2(void)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
|
||||
#include "h3.h"
|
||||
|
||||
void f3(void)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
void f2(void)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
extern void f2(void);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
f2();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
#error "TARGET INCLUDE_DIRECTORIES"
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
#error "SOURCE INCLUDE_DIRECTORIES"
|
||||
@@ -1,3 +1,5 @@
|
||||
enable_language(C)
|
||||
|
||||
macro(test_target_property PROP)
|
||||
add_custom_target(CustomTarget)
|
||||
set_property(TARGET CustomTarget PROPERTY ${PROP} x)
|
||||
@@ -28,8 +30,8 @@ macro(test_directory_property PROP)
|
||||
endmacro()
|
||||
|
||||
macro(test_file_set_property PROP)
|
||||
add_library(foo INTERFACE)
|
||||
target_sources(foo INTERFACE FILE_SET foo TYPE HEADERS)
|
||||
add_library(foo STATIC foo.c)
|
||||
target_sources(foo PRIVATE FILE_SET foo TYPE HEADERS)
|
||||
set_property(FILE_SET foo TARGET foo PROPERTY ${PROP} x)
|
||||
set_property(FILE_SET foo TARGET foo PROPERTY ${PROP})
|
||||
set_property(FILE_SET foo TARGET foo APPEND PROPERTY ${PROP})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
^CMake Error at FileSetDefaultWrongType\.cmake:[0-9]+ \(target_sources\):
|
||||
target_sources FILE_SET names starting with a capital letter are reserved
|
||||
for built-in file sets and may only be "HEADERS", "CXX_MODULES"
|
||||
for built-in file sets and may only be "HEADERS", "SOURCES", "CXX_MODULES"
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)$
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,12 @@
|
||||
CMake Error at FileSetIncompatibleScopes\.cmake:[0-9]+ \(target_sources\):
|
||||
target_sources File set TYPE "CXX_MODULES" may not have "PUBLIC" or
|
||||
"PRIVATE" scope on INTERFACE libraries\.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:3 \(include\)
|
||||
|
||||
|
||||
CMake Error at FileSetIncompatibleScopes\.cmake:[0-9]+ \(target_sources\):
|
||||
target_sources File set TYPE "SOURCES" may not have "PUBLIC" or "PRIVATE"
|
||||
scope on INTERFACE libraries\.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:3 \(include\)
|
||||
@@ -0,0 +1,5 @@
|
||||
enable_language(C)
|
||||
|
||||
add_library(lib1 INTERFACE)
|
||||
target_sources(lib1 PUBLIC FILE_SET CXX_MODULES FILES lib1.c)
|
||||
target_sources(lib1 PUBLIC FILE_SET SOURCES FILES lib2.c)
|
||||
@@ -1,4 +1,5 @@
|
||||
^CMake Error at FileSetWrongType\.cmake:[0-9]+ \(target_sources\):
|
||||
target_sources File set TYPE may only be "HEADERS", "CXX_MODULES"
|
||||
target_sources File set TYPE may only be "HEADERS", "SOURCES",
|
||||
"CXX_MODULES"
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)$
|
||||
|
||||
@@ -26,6 +26,7 @@ run_cmake(FileSetProperties)
|
||||
run_cmake(FileSetNoType)
|
||||
run_cmake(FileSetWrongType)
|
||||
run_cmake(FileSetDefaultWrongType)
|
||||
run_cmake(FileSetIncompatibleScopes)
|
||||
run_cmake(FileSetChangeScope)
|
||||
run_cmake(FileSetChangeType)
|
||||
run_cmake(FileSetWrongBaseDirs)
|
||||
|
||||
Reference in New Issue
Block a user