Commit 974de0e1 authored by Marc Chevrier's avatar Marc Chevrier

static library: add property STATIC_LIBRARY_OPTIONS

issue: #18251
parent 349f8bfb
......@@ -301,6 +301,7 @@ Properties on Targets
/prop_tgt/SOVERSION
/prop_tgt/STATIC_LIBRARY_FLAGS_CONFIG
/prop_tgt/STATIC_LIBRARY_FLAGS
/prop_tgt/STATIC_LIBRARY_OPTIONS
/prop_tgt/SUFFIX
/prop_tgt/TYPE
/prop_tgt/VERSION
......
......@@ -3,11 +3,12 @@ LINK_FLAGS
Additional flags to use when linking this target if it is a shared library,
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
to the link step of a target. :prop_tgt:`LINK_FLAGS_<CONFIG>` will add to the
configuration ``<CONFIG>``, for example, ``DEBUG``, ``RELEASE``,
The ``LINK_FLAGS`` property, managed as a string, can be used to add extra
flags to the link step of a target. :prop_tgt:`LINK_FLAGS_<CONFIG>` will add
to the configuration ``<CONFIG>``, for example, ``DEBUG``, ``RELEASE``,
``MINSIZEREL``, ``RELWITHDEBINFO``, ...
.. note::
......
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`.
......
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
specified so far for its target. Use the :command:`target_link_options`
......
......@@ -2,11 +2,16 @@ STATIC_LIBRARY_FLAGS
--------------------
Archiver (or MSVC librarian) flags for a static library target.
Targets that are shared libraries, modules, or executables can use
the :prop_tgt:`LINK_OPTIONS` or :prop_tgt:`LINK_FLAGS` target property.
Targets that are shared libraries, modules, or executables need to use
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.
:prop_tgt:`STATIC_LIBRARY_FLAGS_<CONFIG>` will add to the configuration
``<CONFIG>``, for example, ``DEBUG``, ``RELEASE``, ``MINSIZEREL``,
``RELWITHDEBINFO``, ...
.. note::
This property has been superseded by :prop_tgt:`STATIC_LIBRARY_OPTIONS`
property.
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`.
.. note::
This property has been superseded by :prop_tgt:`STATIC_LIBRARY_OPTIONS`
property.
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.
STATIC_LIBRARY_OPTIONS
----------------------
* static library targets gained new :prop_tgt:`STATIC_LIBRARY_OPTIONS` property.
......@@ -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 {
void processLinkDepends(
cmGeneratorTarget const* tgt,
......
......@@ -424,6 +424,9 @@ public:
void GetLinkOptions(std::vector<std::string>& result,
const std::string& config,
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,
const std::string& config,
......
......@@ -1844,7 +1844,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY ||
gtgt->GetType() == cmStateEnums::STATIC_LIBRARY) {
this->CurrentLocalGenerator->GetStaticLibraryFlags(
extraLinkOptions, cmSystemTools::UpperCase(configName), gtgt);
extraLinkOptions, cmSystemTools::UpperCase(configName), llang, gtgt);
} else {
const char* targetLinkFlags = gtgt->GetProperty("LINK_FLAGS");
if (targetLinkFlags) {
......
......@@ -979,6 +979,7 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
void cmLocalGenerator::GetStaticLibraryFlags(std::string& flags,
std::string const& config,
std::string const& linkLanguage,
cmGeneratorTarget* target)
{
this->AppendFlags(
......@@ -992,6 +993,11 @@ void cmLocalGenerator::GetStaticLibraryFlags(std::string& flags,
std::string name = "STATIC_LIBRARY_FLAGS_" + config;
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(
......@@ -1009,7 +1015,7 @@ void cmLocalGenerator::GetTargetFlags(
switch (target->GetType()) {
case cmStateEnums::STATIC_LIBRARY:
this->GetStaticLibraryFlags(linkFlags, buildType, target);
this->GetStaticLibraryFlags(linkFlags, buildType, linkLanguage, target);
break;
case cmStateEnums::MODULE_LIBRARY:
libraryLinkVariable = "CMAKE_MODULE_LINKER_FLAGS";
......
......@@ -323,6 +323,7 @@ public:
/** Fill out the static linker flags for the given target. */
void GetStaticLibraryFlags(std::string& flags, std::string const& config,
std::string const& linkLanguage,
cmGeneratorTarget* target);
/** Fill out these strings for the given target. Libraries to link,
......
......@@ -1038,7 +1038,9 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
}
}
std::string libflags;
this->GetStaticLibraryFlags(libflags, configTypeUpper, target);
this->GetStaticLibraryFlags(libflags, configTypeUpper,
target->GetLinkerLanguage(configName),
target);
if (!libflags.empty()) {
fout << "\t\t\t\tAdditionalOptions=\"" << libflags << "\"\n";
}
......
......@@ -148,7 +148,7 @@ void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
std::string extraFlags;
this->LocalGenerator->GetStaticLibraryFlags(
extraFlags, cmSystemTools::UpperCase(this->ConfigName),
extraFlags, cmSystemTools::UpperCase(this->ConfigName), linkLanguage,
this->GeneratorTarget);
this->WriteLibraryRules(linkRuleVar, extraFlags, false);
}
......
......@@ -3055,9 +3055,14 @@ void cmVisualStudio10TargetGenerator::WriteLibOptions(
this->GeneratorTarget->GetType() != cmStateEnums::OBJECT_LIBRARY) {
return;
}
const std::string& linkLanguage =
this->GeneratorTarget->GetLinkClosure(config)->LinkerLanguage;
std::string libflags;
this->LocalGenerator->GetStaticLibraryFlags(
libflags, cmSystemTools::UpperCase(config), this->GeneratorTarget);
libflags, cmSystemTools::UpperCase(config), linkLanguage,
this->GeneratorTarget);
if (!libflags.empty()) {
Elem e2(e1, "Lib");
cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
......
#if defined(_WIN32)
__declspec(dllexport)
#endif
int flags_lib(void)
{
return 0;
}
include(RunCMake)
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()
if (NOT actual_stdout MATCHES "BADFLAG")
set (RunCMake_TEST_FAILED "Not found expected 'BADFLAG'.")
endif()
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()
if (actual_stdout MATCHES "BADFLAG")
string (APPEND RunCMake_TEST_FAILED "\nFound unexpected flag 'BADFLAG'.")
endif()
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})
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment