static library: add property STATIC_LIBRARY_OPTIONS

issue: #18251
This commit is contained in:
Marc Chevrier
2018-08-15 15:20:18 +02:00
parent 349f8bfb25
commit 974de0e199
25 changed files with 187 additions and 15 deletions

View File

@@ -301,6 +301,7 @@ Properties on Targets
/prop_tgt/SOVERSION /prop_tgt/SOVERSION
/prop_tgt/STATIC_LIBRARY_FLAGS_CONFIG /prop_tgt/STATIC_LIBRARY_FLAGS_CONFIG
/prop_tgt/STATIC_LIBRARY_FLAGS /prop_tgt/STATIC_LIBRARY_FLAGS
/prop_tgt/STATIC_LIBRARY_OPTIONS
/prop_tgt/SUFFIX /prop_tgt/SUFFIX
/prop_tgt/TYPE /prop_tgt/TYPE
/prop_tgt/VERSION /prop_tgt/VERSION

View File

@@ -3,11 +3,12 @@ LINK_FLAGS
Additional flags to use when linking this target if it is a shared library, Additional flags to use when linking this target if it is a shared library,
module library, or an executable. Static libraries need to use module library, or an executable. Static libraries need to use
:prop_tgt:`STATIC_LIBRARY_FLAGS`. :prop_tgt:`STATIC_LIBRARY_OPTIONS` or :prop_tgt:`STATIC_LIBRARY_FLAGS`
properties.
The LINK_FLAGS property, managed as a string, can be used to add extra flags The ``LINK_FLAGS`` property, managed as a string, can be used to add extra
to the link step of a target. :prop_tgt:`LINK_FLAGS_<CONFIG>` will add to the flags to the link step of a target. :prop_tgt:`LINK_FLAGS_<CONFIG>` will add
configuration ``<CONFIG>``, for example, ``DEBUG``, ``RELEASE``, to the configuration ``<CONFIG>``, for example, ``DEBUG``, ``RELEASE``,
``MINSIZEREL``, ``RELWITHDEBINFO``, ... ``MINSIZEREL``, ``RELWITHDEBINFO``, ...
.. note:: .. note::

View File

@@ -1,7 +1,8 @@
LINK_FLAGS_<CONFIG> LINK_FLAGS_<CONFIG>
------------------- -------------------
Per-configuration linker flags for a shared library, module or executable target. Per-configuration linker flags for a shared library, module or executable
target.
This is the configuration-specific version of :prop_tgt:`LINK_FLAGS`. This is the configuration-specific version of :prop_tgt:`LINK_FLAGS`.

View File

@@ -1,7 +1,10 @@
LINK_OPTIONS LINK_OPTIONS
------------ ------------
List of options to use when linking this target. List of options to use for the link step of shared library, module
and executable targets. Targets that are static libraries need to use
the :prop_tgt:`STATIC_LIBRARY_OPTIONS` target property.
This property holds a :ref:`;-list <CMake Language Lists>` of options This property holds a :ref:`;-list <CMake Language Lists>` of options
specified so far for its target. Use the :command:`target_link_options` specified so far for its target. Use the :command:`target_link_options`

View File

@@ -2,11 +2,16 @@ STATIC_LIBRARY_FLAGS
-------------------- --------------------
Archiver (or MSVC librarian) flags for a static library target. Archiver (or MSVC librarian) flags for a static library target.
Targets that are shared libraries, modules, or executables can use Targets that are shared libraries, modules, or executables need to use
the :prop_tgt:`LINK_OPTIONS` or :prop_tgt:`LINK_FLAGS` target property. the :prop_tgt:`LINK_OPTIONS` or :prop_tgt:`LINK_FLAGS` target properties.
The STATIC_LIBRARY_FLAGS property, managed as a string, can be used to add The ``STATIC_LIBRARY_FLAGS`` property, managed as a string, can be used to add
extra flags to the link step of a static library target. extra flags to the link step of a static library target.
:prop_tgt:`STATIC_LIBRARY_FLAGS_<CONFIG>` will add to the configuration :prop_tgt:`STATIC_LIBRARY_FLAGS_<CONFIG>` will add to the configuration
``<CONFIG>``, for example, ``DEBUG``, ``RELEASE``, ``MINSIZEREL``, ``<CONFIG>``, for example, ``DEBUG``, ``RELEASE``, ``MINSIZEREL``,
``RELWITHDEBINFO``, ... ``RELWITHDEBINFO``, ...
.. note::
This property has been superseded by :prop_tgt:`STATIC_LIBRARY_OPTIONS`
property.

View File

@@ -1,6 +1,12 @@
STATIC_LIBRARY_FLAGS_<CONFIG> STATIC_LIBRARY_FLAGS_<CONFIG>
----------------------------- -----------------------------
Per-configuration archiver (or MSVC librarian) flags for a static library target. Per-configuration archiver (or MSVC librarian) flags for a static library
target.
This is the configuration-specific version of :prop_tgt:`STATIC_LIBRARY_FLAGS`. This is the configuration-specific version of :prop_tgt:`STATIC_LIBRARY_FLAGS`.
.. note::
This property has been superseded by :prop_tgt:`STATIC_LIBRARY_OPTIONS`
property.

View File

@@ -0,0 +1,20 @@
STATIC_LIBRARY_OPTIONS
----------------------
Archiver (or MSVC librarian) flags for a static library target.
Targets that are shared libraries, modules, or executables need to use
the :prop_tgt:`LINK_OPTIONS` target property.
This property holds a :ref:`;-list <CMake Language Lists>` of options
specified so far for its target. Use :command:`set_target_properties` or
:command:`set_property` commands to set its content.
Contents of ``STATIC_LIBRARY_OPTIONS`` 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.
.. note::
This property must be used in preference to :prop_tgt:`STATIC_LIBRARY_FLAGS`
property.

View File

@@ -0,0 +1,4 @@
STATIC_LIBRARY_OPTIONS
----------------------
* static library targets gained new :prop_tgt:`STATIC_LIBRARY_OPTIONS` property.

View File

@@ -3017,6 +3017,47 @@ void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result,
} }
} }
namespace {
void processStaticLibraryLinkOptions(
cmGeneratorTarget const* tgt,
const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
std::vector<std::string>& options,
std::unordered_set<std::string>& uniqueOptions,
cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
std::string const& language)
{
processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker,
config, false, "static library link options",
language, OptionsParse::Shell);
}
}
void cmGeneratorTarget::GetStaticLibraryLinkOptions(
std::vector<std::string>& result, const std::string& config,
const std::string& language) const
{
std::vector<cmGeneratorTarget::TargetPropertyEntry*> entries;
std::unordered_set<std::string> uniqueOptions;
cmGeneratorExpressionDAGChecker dagChecker(
this->GetName(), "STATIC_LIBRARY_OPTIONS", nullptr, nullptr);
if (const char* linkOptions = this->GetProperty("STATIC_LIBRARY_OPTIONS")) {
std::vector<std::string> options;
cmGeneratorExpression ge;
cmSystemTools::ExpandListArgument(linkOptions, options);
for (const auto& option : options) {
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(option);
entries.push_back(
new cmGeneratorTarget::TargetPropertyEntry(std::move(cge)));
}
}
processStaticLibraryLinkOptions(this, entries, result, uniqueOptions,
&dagChecker, config, language);
cmDeleteAll(entries);
}
namespace { namespace {
void processLinkDepends( void processLinkDepends(
cmGeneratorTarget const* tgt, cmGeneratorTarget const* tgt,

View File

@@ -424,6 +424,9 @@ public:
void GetLinkOptions(std::vector<std::string>& result, void GetLinkOptions(std::vector<std::string>& result,
const std::string& config, const std::string& config,
const std::string& language) const; const std::string& language) const;
void GetStaticLibraryLinkOptions(std::vector<std::string>& result,
const std::string& config,
const std::string& language) const;
void GetLinkDepends(std::vector<std::string>& result, void GetLinkDepends(std::vector<std::string>& result,
const std::string& config, const std::string& config,

View File

@@ -1844,7 +1844,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY || if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY ||
gtgt->GetType() == cmStateEnums::STATIC_LIBRARY) { gtgt->GetType() == cmStateEnums::STATIC_LIBRARY) {
this->CurrentLocalGenerator->GetStaticLibraryFlags( this->CurrentLocalGenerator->GetStaticLibraryFlags(
extraLinkOptions, cmSystemTools::UpperCase(configName), gtgt); extraLinkOptions, cmSystemTools::UpperCase(configName), llang, gtgt);
} else { } else {
const char* targetLinkFlags = gtgt->GetProperty("LINK_FLAGS"); const char* targetLinkFlags = gtgt->GetProperty("LINK_FLAGS");
if (targetLinkFlags) { if (targetLinkFlags) {

View File

@@ -979,6 +979,7 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
void cmLocalGenerator::GetStaticLibraryFlags(std::string& flags, void cmLocalGenerator::GetStaticLibraryFlags(std::string& flags,
std::string const& config, std::string const& config,
std::string const& linkLanguage,
cmGeneratorTarget* target) cmGeneratorTarget* target)
{ {
this->AppendFlags( this->AppendFlags(
@@ -992,6 +993,11 @@ void cmLocalGenerator::GetStaticLibraryFlags(std::string& flags,
std::string name = "STATIC_LIBRARY_FLAGS_" + config; std::string name = "STATIC_LIBRARY_FLAGS_" + config;
this->AppendFlags(flags, target->GetProperty(name)); this->AppendFlags(flags, target->GetProperty(name));
} }
std::vector<std::string> options;
target->GetStaticLibraryLinkOptions(options, config, linkLanguage);
// STATIC_LIBRARY_OPTIONS are escaped.
this->AppendCompileOptions(flags, options);
} }
void cmLocalGenerator::GetTargetFlags( void cmLocalGenerator::GetTargetFlags(
@@ -1009,7 +1015,7 @@ void cmLocalGenerator::GetTargetFlags(
switch (target->GetType()) { switch (target->GetType()) {
case cmStateEnums::STATIC_LIBRARY: case cmStateEnums::STATIC_LIBRARY:
this->GetStaticLibraryFlags(linkFlags, buildType, target); this->GetStaticLibraryFlags(linkFlags, buildType, linkLanguage, target);
break; break;
case cmStateEnums::MODULE_LIBRARY: case cmStateEnums::MODULE_LIBRARY:
libraryLinkVariable = "CMAKE_MODULE_LINKER_FLAGS"; libraryLinkVariable = "CMAKE_MODULE_LINKER_FLAGS";

View File

@@ -323,6 +323,7 @@ public:
/** Fill out the static linker flags for the given target. */ /** Fill out the static linker flags for the given target. */
void GetStaticLibraryFlags(std::string& flags, std::string const& config, void GetStaticLibraryFlags(std::string& flags, std::string const& config,
std::string const& linkLanguage,
cmGeneratorTarget* target); cmGeneratorTarget* target);
/** Fill out these strings for the given target. Libraries to link, /** Fill out these strings for the given target. Libraries to link,

View File

@@ -1038,7 +1038,9 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
} }
} }
std::string libflags; std::string libflags;
this->GetStaticLibraryFlags(libflags, configTypeUpper, target); this->GetStaticLibraryFlags(libflags, configTypeUpper,
target->GetLinkerLanguage(configName),
target);
if (!libflags.empty()) { if (!libflags.empty()) {
fout << "\t\t\t\tAdditionalOptions=\"" << libflags << "\"\n"; fout << "\t\t\t\tAdditionalOptions=\"" << libflags << "\"\n";
} }

View File

@@ -148,7 +148,7 @@ void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
std::string extraFlags; std::string extraFlags;
this->LocalGenerator->GetStaticLibraryFlags( this->LocalGenerator->GetStaticLibraryFlags(
extraFlags, cmSystemTools::UpperCase(this->ConfigName), extraFlags, cmSystemTools::UpperCase(this->ConfigName), linkLanguage,
this->GeneratorTarget); this->GeneratorTarget);
this->WriteLibraryRules(linkRuleVar, extraFlags, false); this->WriteLibraryRules(linkRuleVar, extraFlags, false);
} }

View File

@@ -3055,9 +3055,14 @@ void cmVisualStudio10TargetGenerator::WriteLibOptions(
this->GeneratorTarget->GetType() != cmStateEnums::OBJECT_LIBRARY) { this->GeneratorTarget->GetType() != cmStateEnums::OBJECT_LIBRARY) {
return; return;
} }
const std::string& linkLanguage =
this->GeneratorTarget->GetLinkClosure(config)->LinkerLanguage;
std::string libflags; std::string libflags;
this->LocalGenerator->GetStaticLibraryFlags( this->LocalGenerator->GetStaticLibraryFlags(
libflags, cmSystemTools::UpperCase(config), this->GeneratorTarget); libflags, cmSystemTools::UpperCase(config), linkLanguage,
this->GeneratorTarget);
if (!libflags.empty()) { if (!libflags.empty()) {
Elem e2(e1, "Lib"); Elem e2(e1, "Lib");
cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;

View File

@@ -0,0 +1,7 @@
#if defined(_WIN32)
__declspec(dllexport)
#endif
int flags_lib(void)
{
return 0;
}

View File

@@ -1,3 +1,30 @@
include(RunCMake) include(RunCMake)
run_cmake(LINK_SEARCH_STATIC) run_cmake(LINK_SEARCH_STATIC)
macro(run_cmake_target test subtest target)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
set(RunCMake_TEST_NO_CLEAN 1)
run_cmake_command(${test}-${subtest} ${CMAKE_COMMAND} --build . --target ${target} ${ARGN})
unset(RunCMake_TEST_BINARY_DIR)
unset(RunCMake_TEST_NO_CLEAN)
endmacro()
if (NOT CMAKE_C_COMPILER_ID STREQUAL "Intel")
# Intel compiler does not reject bad flags or objects!
set(RunCMake_TEST_OUTPUT_MERGE TRUE)
if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release)
endif()
run_cmake(STATIC_LIBRARY_OPTIONS)
run_cmake_target(STATIC_LIBRARY_OPTIONS basic StaticLinkOptions)
run_cmake_target(STATIC_LIBRARY_OPTIONS genex StaticLinkOptions_genex --config Release)
run_cmake_target(STATIC_LIBRARY_OPTIONS shared SharedLinkOptions)
unset(RunCMake_TEST_OPTIONS)
unset(RunCMake_TEST_OUTPUT_MERGE)
endif()

View File

@@ -0,0 +1,4 @@
if (NOT actual_stdout MATCHES "BADFLAG")
set (RunCMake_TEST_FAILED "Not found expected 'BADFLAG'.")
endif()

View File

@@ -0,0 +1 @@
.*

View File

@@ -0,0 +1,7 @@
if (NOT actual_stdout MATCHES "BADFLAG_RELEASE")
set (RunCMake_TEST_FAILED "Not found expected 'BADFLAG_RELEASE'.")
endif()
if (actual_stdout MATCHES "SHELL:")
string (APPEND RunCMake_TEST_FAILED "\nFound unexpected prefix 'SHELL:'.")
endif()

View File

@@ -0,0 +1 @@
.*

View File

@@ -0,0 +1,4 @@
if (actual_stdout MATCHES "BADFLAG")
string (APPEND RunCMake_TEST_FAILED "\nFound unexpected flag 'BADFLAG'.")
endif()

View File

@@ -0,0 +1 @@
.*

View File

@@ -0,0 +1,21 @@
enable_language(C)
set(obj "${CMAKE_C_OUTPUT_EXTENSION}")
if(BORLAND)
set(pre -)
endif()
add_library(StaticLinkOptions STATIC LinkOptionsLib.c)
set_property(TARGET StaticLinkOptions PROPERTY STATIC_LIBRARY_OPTIONS ${pre}BADFLAG${obj})
# static library with generator expression
add_library(StaticLinkOptions_genex STATIC LinkOptionsLib.c)
set_property(TARGET StaticLinkOptions_genex PROPERTY STATIC_LIBRARY_OPTIONS
$<$<CONFIG:Release>:${pre}BADFLAG_RELEASE${obj}>
"SHELL:" # produces no options
)
# shared library do not use property STATIC_LIBRARY_OPTIONS
add_library(SharedLinkOptions SHARED LinkOptionsLib.c)
set_property(TARGET SharedLinkOptions PROPERTY STATIC_LIBRARY_OPTIONS ${pre}BADFLAG${obj})