From 6db61f072588bb097b16094290b0b415fa4905e5 Mon Sep 17 00:00:00 2001 From: Wouter Klouwen Date: Thu, 8 Mar 2018 17:46:49 +0000 Subject: Export: allow exporting of additional properties This change introduces an additional property that may be set on a target to allow additional properties to be exported. Normally only a limited number of properties are exported. Additional properties may be exported by simply setting the `EXPORT_PROPERTIES` property on a target that is exported. --- Help/manual/cmake-properties.7.rst | 1 + Help/prop_tgt/EXPORT_PROPERTIES.rst | 14 ++++++++ Help/release/dev/export-properties.rst | 6 ++++ Source/cmExportBuildFileGenerator.cxx | 9 +++++ Source/cmExportFileGenerator.cxx | 40 ++++++++++++++++++++++ Source/cmExportFileGenerator.h | 4 +++ Source/cmExportInstallFileGenerator.cxx | 6 ++++ Tests/ExportImport/Export/CMakeLists.txt | 8 +++++ Tests/ExportImport/Import/A/CMakeLists.txt | 14 ++++++++ .../ForbiddenToExportImportedProperties-result.txt | 1 + .../ForbiddenToExportImportedProperties-stderr.txt | 3 ++ .../ForbiddenToExportImportedProperties.cmake | 12 +++++++ ...ForbiddenToExportInterfaceProperties-result.txt | 1 + ...ForbiddenToExportInterfaceProperties-stderr.txt | 3 ++ .../ForbiddenToExportInterfaceProperties.cmake | 12 +++++++ .../ForbiddenToExportPropertyWithGenExp-result.txt | 1 + .../ForbiddenToExportPropertyWithGenExp-stderr.txt | 3 ++ .../ForbiddenToExportPropertyWithGenExp.cmake | 12 +++++++ Tests/RunCMake/export/RunCMakeTest.cmake | 3 ++ Tests/RunCMake/export/empty.cpp | 7 ++++ 20 files changed, 160 insertions(+) create mode 100644 Help/prop_tgt/EXPORT_PROPERTIES.rst create mode 100644 Help/release/dev/export-properties.rst create mode 100644 Tests/RunCMake/export/ForbiddenToExportImportedProperties-result.txt create mode 100644 Tests/RunCMake/export/ForbiddenToExportImportedProperties-stderr.txt create mode 100644 Tests/RunCMake/export/ForbiddenToExportImportedProperties.cmake create mode 100644 Tests/RunCMake/export/ForbiddenToExportInterfaceProperties-result.txt create mode 100644 Tests/RunCMake/export/ForbiddenToExportInterfaceProperties-stderr.txt create mode 100644 Tests/RunCMake/export/ForbiddenToExportInterfaceProperties.cmake create mode 100644 Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp-result.txt create mode 100644 Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp-stderr.txt create mode 100644 Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp.cmake create mode 100644 Tests/RunCMake/export/empty.cpp diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 9d4a7e8..051306b 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -176,6 +176,7 @@ Properties on Targets /prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD_CONFIG /prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD /prop_tgt/EXPORT_NAME + /prop_tgt/EXPORT_PROPERTIES /prop_tgt/FOLDER /prop_tgt/Fortran_FORMAT /prop_tgt/Fortran_MODULE_DIRECTORY diff --git a/Help/prop_tgt/EXPORT_PROPERTIES.rst b/Help/prop_tgt/EXPORT_PROPERTIES.rst new file mode 100644 index 0000000..bcf47a6 --- /dev/null +++ b/Help/prop_tgt/EXPORT_PROPERTIES.rst @@ -0,0 +1,14 @@ +EXPORT_PROPERTIES +----------------- + +List additional properties to export for a target. + +This property contains a list of property names that should be exported by +the :command:`install(EXPORT)` and :command:`export` commands. By default +only a limited number of properties are exported. This property can be used +to additionally export other properties as well. + +Properties starting with ``INTERFACE_`` or ``IMPORTED_`` are not allowed as +they are reserved for internal CMake use. + +Properties containing generator expressions are also not allowed. diff --git a/Help/release/dev/export-properties.rst b/Help/release/dev/export-properties.rst new file mode 100644 index 0000000..9b20799 --- /dev/null +++ b/Help/release/dev/export-properties.rst @@ -0,0 +1,6 @@ +EXPORT_PROPERTIES +----------------- + +* An :prop_tgt:`EXPORT_PROPERTIES` target property was added to specify a + custom list of target properties to include in targets exported by the + :command:`install(EXPORT)` and :command:`export` commands. diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index f0ae47b..bbbc998 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -97,6 +97,15 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) properties, missingTargets); this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", gte, properties); + + std::string errorMessage; + if (!this->PopulateExportProperties(gte, properties, errorMessage)) { + this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage( + cmake::FATAL_ERROR, errorMessage, + this->LG->GetMakefile()->GetBacktrace()); + return false; + } + const bool newCMP0022Behavior = gte->GetPolicyStatusCMP0022() != cmPolicies::WARN && gte->GetPolicyStatusCMP0022() != cmPolicies::OLD; diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 0f1d745..2dcbfa0 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -11,6 +11,8 @@ #include "cmMakefile.h" #include "cmOutputConverter.h" #include "cmPolicies.h" +#include "cmProperty.h" +#include "cmPropertyMap.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -1097,3 +1099,41 @@ void cmExportFileGenerator::GenerateImportedFileChecksCode( os << ")\n\n"; } + +bool cmExportFileGenerator::PopulateExportProperties( + cmGeneratorTarget* gte, ImportPropertyMap& properties, + std::string& errorMessage) +{ + auto& targetProperties = gte->Target->GetProperties(); + const auto& exportProperties = targetProperties.find("EXPORT_PROPERTIES"); + if (exportProperties != targetProperties.end()) { + std::vector propsToExport; + cmSystemTools::ExpandListArgument(exportProperties->second.GetValue(), + propsToExport); + for (auto& prop : propsToExport) { + /* Black list reserved properties */ + if (cmSystemTools::StringStartsWith(prop, "IMPORTED_") || + cmSystemTools::StringStartsWith(prop, "INTERFACE_")) { + std::ostringstream e; + e << "Target \"" << gte->Target->GetName() << "\" contains property \"" + << prop << "\" in EXPORT_PROPERTIES but IMPORTED_* and INTERFACE_* " + << "properties are reserved."; + errorMessage = e.str(); + return false; + } + auto propertyValue = targetProperties.GetPropertyValue(prop); + std::string evaluatedValue = cmGeneratorExpression::Preprocess( + propertyValue, cmGeneratorExpression::StripAllGeneratorExpressions); + if (evaluatedValue != propertyValue) { + std::ostringstream e; + e << "Target \"" << gte->Target->GetName() << "\" contains property \"" + << prop << "\" in EXPORT_PROPERTIES but this property contains a " + << "generator expression. This is not allowed."; + errorMessage = e.str(); + return false; + } + properties[prop] = propertyValue; + } + } + return true; +} diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index e541372..954e6c5 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -168,6 +168,10 @@ protected: virtual void GenerateRequiredCMakeVersion(std::ostream& os, const char* versionString); + bool PopulateExportProperties(cmGeneratorTarget* gte, + ImportPropertyMap& properties, + std::string& errorMessage); + // The namespace in which the exports are placed in the generated file. std::string Namespace; diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 93ba2ce..63d04a6 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -104,6 +104,12 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) cmGeneratorExpression::InstallInterface, properties, missingTargets); + std::string errorMessage; + if (!this->PopulateExportProperties(gt, properties, errorMessage)) { + cmSystemTools::Error(errorMessage.c_str()); + return false; + } + const bool newCMP0022Behavior = gt->GetPolicyStatusCMP0022() != cmPolicies::WARN && gt->GetPolicyStatusCMP0022() != cmPolicies::OLD; diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index cbc8c6b..0f1a556 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -356,6 +356,14 @@ install(FILES set_property(TARGET testLib2 APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS USING_TESTLIB2) set_property(TARGET testLib3 APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS USING_TESTLIB3) +set_target_properties(testLib3 PROPERTIES + EXPORT_PROPERTIES "EXPORTED_PROPERTY1" + EXPORTED_PROPERTY1 "EXPORTING_TESTLIB3") +set_target_properties(testLib4 PROPERTIES + EXPORTED_PROPERTY2 "EXPORTING_TESTLIB4_1" + EXPORTED_PROPERTY3 "EXPORTING_TESTLIB4_2") +set_property(TARGET testLib4 PROPERTY + EXPORT_PROPERTIES EXPORTED_PROPERTY2 EXPORTED_PROPERTY3) set_property(TARGET cmp0022NEW APPEND PROPERTY INTERFACE_LINK_LIBRARIES testLib2) # set_property(TARGET cmp0022NEW APPEND PROPERTY LINK_INTERFACE_LIBRARIES testLibIncludeRequired2) # TODO: Test for error diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt index 4e8eac2..39a89dc 100644 --- a/Tests/ExportImport/Import/A/CMakeLists.txt +++ b/Tests/ExportImport/Import/A/CMakeLists.txt @@ -32,6 +32,20 @@ add_executable(imp_testExe1 ${Import_BINARY_DIR}/exp_generated4.c ) +function(checkForProperty _TARGET _PROP _EXPECTED) + get_target_property(EXPORTED_PROPERTY ${_TARGET} "${_PROP}") + if (NOT EXPORTED_PROPERTY STREQUAL "${_EXPECTED}") + message(SEND_ERROR "${_TARGET} was expected to export \"${_PROP}\" with value \"${_EXPECTED}\" but got \"${EXPORTED_PROPERTY}\"") + endif() +endfunction() + +checkForProperty(bld_testLib3 "EXPORTED_PROPERTY1" "EXPORTING_TESTLIB3") +checkForProperty(exp_testLib3 "EXPORTED_PROPERTY1" "EXPORTING_TESTLIB3") +checkForProperty(bld_testLib4 "EXPORTED_PROPERTY2" "EXPORTING_TESTLIB4_1") +checkForProperty(exp_testLib4 "EXPORTED_PROPERTY2" "EXPORTING_TESTLIB4_1") +checkForProperty(bld_testLib4 "EXPORTED_PROPERTY3" "EXPORTING_TESTLIB4_2") +checkForProperty(exp_testLib4 "EXPORTED_PROPERTY3" "EXPORTING_TESTLIB4_2") + # Try linking to a library imported from the install tree. target_link_libraries(imp_testExe1 exp_testLib2 diff --git a/Tests/RunCMake/export/ForbiddenToExportImportedProperties-result.txt b/Tests/RunCMake/export/ForbiddenToExportImportedProperties-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/export/ForbiddenToExportImportedProperties-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/export/ForbiddenToExportImportedProperties-stderr.txt b/Tests/RunCMake/export/ForbiddenToExportImportedProperties-stderr.txt new file mode 100644 index 0000000..ab03943 --- /dev/null +++ b/Tests/RunCMake/export/ForbiddenToExportImportedProperties-stderr.txt @@ -0,0 +1,3 @@ +CMake Error in CMakeLists.txt: + Target \"foo\" contains property \"IMPORTED_FOOBAR\" in EXPORT_PROPERTIES but + IMPORTED_\* and INTERFACE_\* properties are reserved. diff --git a/Tests/RunCMake/export/ForbiddenToExportImportedProperties.cmake b/Tests/RunCMake/export/ForbiddenToExportImportedProperties.cmake new file mode 100644 index 0000000..9c8653d --- /dev/null +++ b/Tests/RunCMake/export/ForbiddenToExportImportedProperties.cmake @@ -0,0 +1,12 @@ +enable_language(CXX) +add_library(foo empty.cpp) +set_target_properties(foo PROPERTIES + IMPORTED_FOOBAR "Some other string" + EXPORT_PROPERTIES "IMPORTED_FOOBAR" +) +export(TARGETS foo FILE "${CMAKE_CURRENT_BINARY_DIR}/foo.cmake") +install(TARGETS foo EXPORT fooExport + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib +) diff --git a/Tests/RunCMake/export/ForbiddenToExportInterfaceProperties-result.txt b/Tests/RunCMake/export/ForbiddenToExportInterfaceProperties-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/export/ForbiddenToExportInterfaceProperties-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/export/ForbiddenToExportInterfaceProperties-stderr.txt b/Tests/RunCMake/export/ForbiddenToExportInterfaceProperties-stderr.txt new file mode 100644 index 0000000..577602b --- /dev/null +++ b/Tests/RunCMake/export/ForbiddenToExportInterfaceProperties-stderr.txt @@ -0,0 +1,3 @@ +CMake Error in CMakeLists.txt: + Target \"foo\" contains property \"INTERFACE_FOOBAR\" in EXPORT_PROPERTIES but + IMPORTED_\* and INTERFACE_\* properties are reserved. diff --git a/Tests/RunCMake/export/ForbiddenToExportInterfaceProperties.cmake b/Tests/RunCMake/export/ForbiddenToExportInterfaceProperties.cmake new file mode 100644 index 0000000..bab8de0 --- /dev/null +++ b/Tests/RunCMake/export/ForbiddenToExportInterfaceProperties.cmake @@ -0,0 +1,12 @@ +enable_language(CXX) +add_library(foo empty.cpp) +set_target_properties(foo PROPERTIES + INTERFACE_FOOBAR "Some string" + EXPORT_PROPERTIES "INTERFACE_FOOBAR" +) +export(TARGETS foo FILE "${CMAKE_CURRENT_BINARY_DIR}/foo.cmake") +install(TARGETS foo EXPORT fooExport + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib +) diff --git a/Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp-result.txt b/Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp-stderr.txt b/Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp-stderr.txt new file mode 100644 index 0000000..56488e6 --- /dev/null +++ b/Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp-stderr.txt @@ -0,0 +1,3 @@ +CMake Error in CMakeLists.txt: + Target \"foo\" contains property \"JUST_A_PROPERTY\" in EXPORT_PROPERTIES but + this property contains a generator expression. This is not allowed. diff --git a/Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp.cmake b/Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp.cmake new file mode 100644 index 0000000..065cdbc --- /dev/null +++ b/Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp.cmake @@ -0,0 +1,12 @@ +enable_language(CXX) +add_library(foo empty.cpp) +set_target_properties(foo PROPERTIES + JUST_A_PROPERTY "$" + EXPORT_PROPERTIES "JUST_A_PROPERTY" +) +export(TARGETS foo FILE "${CMAKE_CURRENT_BINARY_DIR}/foo.cmake") +install(TARGETS foo EXPORT fooExport + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib +) diff --git a/Tests/RunCMake/export/RunCMakeTest.cmake b/Tests/RunCMake/export/RunCMakeTest.cmake index 6d0b7ca..10ced90 100644 --- a/Tests/RunCMake/export/RunCMakeTest.cmake +++ b/Tests/RunCMake/export/RunCMakeTest.cmake @@ -5,3 +5,6 @@ run_cmake(TargetNotFound) run_cmake(AppendExport) run_cmake(OldIface) run_cmake(NoExportSet) +run_cmake(ForbiddenToExportInterfaceProperties) +run_cmake(ForbiddenToExportImportedProperties) +run_cmake(ForbiddenToExportPropertyWithGenExp) diff --git a/Tests/RunCMake/export/empty.cpp b/Tests/RunCMake/export/empty.cpp new file mode 100644 index 0000000..11ec041 --- /dev/null +++ b/Tests/RunCMake/export/empty.cpp @@ -0,0 +1,7 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif + int empty() +{ + return 0; +} -- cgit v0.12