summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Maynard <robert.maynard@kitware.com>2017-01-23 19:13:49 (GMT)
committerBrad King <brad.king@kitware.com>2017-04-18 15:36:09 (GMT)
commit93c89bc75ceee599ba7c08b8fe1ac5104942054f (patch)
treefc956fd1c58cd967309e78b9dd0f2384505b8807
parentac0cf7ff4f5a846381593cf28ebbc9cfaf107149 (diff)
downloadCMake-93c89bc75ceee599ba7c08b8fe1ac5104942054f.zip
CMake-93c89bc75ceee599ba7c08b8fe1ac5104942054f.tar.gz
CMake-93c89bc75ceee599ba7c08b8fe1ac5104942054f.tar.bz2
Genex: Allow TARGET_OBJECTS to be used everywhere
Previously the `TARGET_OBJECTS` generator expression was limited only to use in a buildsystem context so that Xcode's placeholders in object file paths can be evaluated. Lift this restriction so that the expression can at least be used in most settings. Co-Author: Brad King <brad.king@kitware.com>
-rw-r--r--Help/manual/cmake-buildsystem.7.rst6
-rw-r--r--Help/manual/cmake-generator-expressions.7.rst4
-rw-r--r--Help/release/dev/add_custom_command-TARGET_OBJECTS.rst6
-rw-r--r--Help/release/dev/file-GENERATE-TARGET_OBJECTS.rst6
-rw-r--r--Source/cmGeneratorExpressionEvaluationFile.cxx6
-rw-r--r--Source/cmGeneratorExpressionNode.cxx32
-rw-r--r--Tests/GeneratorExpression/CMakeLists.txt16
-rw-r--r--Tests/GeneratorExpression/check_object_files.cmake26
-rw-r--r--Tests/GeneratorExpression/objlib1.c4
-rw-r--r--Tests/GeneratorExpression/objlib2.c4
-rw-r--r--Tests/RunCMake/File_Generate/OutputConflict-stderr.txt5
-rw-r--r--Tests/RunCMake/File_Generate/OutputNameMatchesObjects.cmake1
12 files changed, 102 insertions, 14 deletions
diff --git a/Help/manual/cmake-buildsystem.7.rst b/Help/manual/cmake-buildsystem.7.rst
index 2e6a803..65d87bf 100644
--- a/Help/manual/cmake-buildsystem.7.rst
+++ b/Help/manual/cmake-buildsystem.7.rst
@@ -136,6 +136,12 @@ indirectly by using an :ref:`Interface Library <Interface Libraries>`
whose :prop_tgt:`INTERFACE_SOURCES` target property is set to name
``$<TARGET_OBJECTS:objlib>``.
+Although object libraries may not be used as the ``TARGET``
+in a use of the :command:`add_custom_command(TARGET)` command signature,
+the list of objects can be used by :command:`add_custom_command(OUTPUT)` or
+:command:`file(GENERATE)` by using ``$<TARGET_OBJECTS:objlib>``.
+
+
Build Specification and Usage Requirements
==========================================
diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index 3eac45f..bddb174 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -290,9 +290,7 @@ Available output expressions are:
Content of ``...`` converted to a C identifier.
``$<TARGET_OBJECTS:objLib>``
List of objects resulting from build of ``objLib``. ``objLib`` must be an
- object of type ``OBJECT_LIBRARY``. This expression may only be used in
- the sources of :command:`add_library` and :command:`add_executable`
- commands.
+ object of type ``OBJECT_LIBRARY``.
``$<SHELL_PATH:...>``
Content of ``...`` converted to shell path style. For example, slashes are
converted to backslashes in Windows shells and drive letters are converted
diff --git a/Help/release/dev/add_custom_command-TARGET_OBJECTS.rst b/Help/release/dev/add_custom_command-TARGET_OBJECTS.rst
new file mode 100644
index 0000000..c4a9ee8
--- /dev/null
+++ b/Help/release/dev/add_custom_command-TARGET_OBJECTS.rst
@@ -0,0 +1,6 @@
+add_custom_command-TARGET_OBJECTS
+---------------------------------
+
+* The :command:`add_custom_command` command learned to evaluate the
+ ``TARGET_OBJECTS``
+ :manual:`generator expression <cmake-generator-expressions(7)>`.
diff --git a/Help/release/dev/file-GENERATE-TARGET_OBJECTS.rst b/Help/release/dev/file-GENERATE-TARGET_OBJECTS.rst
new file mode 100644
index 0000000..853a803
--- /dev/null
+++ b/Help/release/dev/file-GENERATE-TARGET_OBJECTS.rst
@@ -0,0 +1,6 @@
+file-GENERATE-TARGET_OBJECTS
+----------------------------
+
+* The :command:`file(GENERATE)` subcommand learned to evaluate the
+ ``TARGET_OBJECTS``
+ :manual:`generator expression <cmake-generator-expressions(7)>`.
diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx
index dc54488..1526454 100644
--- a/Source/cmGeneratorExpressionEvaluationFile.cxx
+++ b/Source/cmGeneratorExpressionEvaluationFile.cxx
@@ -64,8 +64,10 @@ void cmGeneratorExpressionEvaluationFile::Generate(
return;
}
std::ostringstream e;
- e << "Evaluation file to be written multiple times for different "
- "configurations or languages with different content:\n "
+ e << "Evaluation file to be written multiple times with different "
+ "content. "
+ "This is generally caused by the content evaluating the "
+ "configuration type, language, or location of object files:\n "
<< outputFileName;
lg->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index 65949a3..1215737 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -1243,20 +1243,38 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode
return std::string();
}
if (!context->EvaluateForBuildsystem) {
- std::ostringstream e;
- e << "The evaluation of the TARGET_OBJECTS generator expression "
- "is only suitable for consumption by CMake. It is not suitable "
- "for writing out elsewhere.";
- reportError(context, content->GetOriginalExpression(), e.str());
- return std::string();
+ cmGlobalGenerator* gg = context->LG->GetGlobalGenerator();
+ std::string reason;
+ if (!gg->HasKnownObjectFileLocation(&reason)) {
+ std::ostringstream e;
+ e << "The evaluation of the TARGET_OBJECTS generator expression "
+ "is only suitable for consumption by CMake (limited"
+ << reason << "). "
+ "It is not suitable for writing out elsewhere.";
+ reportError(context, content->GetOriginalExpression(), e.str());
+ return std::string();
+ }
}
std::vector<std::string> objects;
gt->GetTargetObjectNames(context->Config, objects);
+ std::string obj_dir;
+ if (context->EvaluateForBuildsystem) {
+ // Use object file directory with buildsystem placeholder.
+ obj_dir = gt->ObjectDirectory;
+ // Here we assume that the set of object files produced
+ // by an object library does not vary with configuration
+ // and do not set HadContextSensitiveCondition to true.
+ } else {
+ // Use object file directory with per-config location.
+ obj_dir = gt->GetObjectDirectory(context->Config);
+ context->HadContextSensitiveCondition = true;
+ }
+
for (std::vector<std::string>::iterator oi = objects.begin();
oi != objects.end(); ++oi) {
- *oi = gt->ObjectDirectory + *oi;
+ *oi = obj_dir + *oi;
}
// Create the cmSourceFile instances in the referencing directory.
diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt
index adc87cd..8ac3419 100644
--- a/Tests/GeneratorExpression/CMakeLists.txt
+++ b/Tests/GeneratorExpression/CMakeLists.txt
@@ -292,3 +292,19 @@ set(CMP0044_TYPE NEW)
add_subdirectory(CMP0044 ${CMAKE_BINARY_DIR}/CMP0044-NEW)
set(CMP0044_TYPE OLD)
add_subdirectory(CMP0044 ${CMAKE_BINARY_DIR}/CMP0044-OLD)
+
+if(NOT CMAKE_GENERATOR STREQUAL Xcode OR NOT CMAKE_OSX_ARCHITECTURES MATCHES "[;$]")
+ add_library(objlib OBJECT objlib1.c objlib2.c)
+ file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/objlib_files_$<CONFIGURATION>"
+ CONTENT "$<JOIN:$<TARGET_OBJECTS:objlib>,\n>\n"
+ )
+
+ add_custom_target(check_object_files ALL
+ COMMAND ${CMAKE_COMMAND}
+ "-DOBJLIB_LISTFILE=${CMAKE_CURRENT_BINARY_DIR}/objlib_files_$<CONFIGURATION>"
+ -DEXPECTED_NUM_OBJECTFILES=2
+ -P "${CMAKE_CURRENT_SOURCE_DIR}/check_object_files.cmake"
+ DEPENDS objlib
+ )
+endif()
diff --git a/Tests/GeneratorExpression/check_object_files.cmake b/Tests/GeneratorExpression/check_object_files.cmake
new file mode 100644
index 0000000..cfccd29
--- /dev/null
+++ b/Tests/GeneratorExpression/check_object_files.cmake
@@ -0,0 +1,26 @@
+
+if (NOT EXISTS ${OBJLIB_LISTFILE})
+ message(SEND_ERROR "Object listing file \"${OBJLIB_LISTFILE}\" not found!")
+endif()
+
+file(STRINGS ${OBJLIB_LISTFILE} objlib_files ENCODING UTF-8)
+
+list(LENGTH objlib_files num_objectfiles)
+if (NOT EXPECTED_NUM_OBJECTFILES EQUAL num_objectfiles)
+ message(SEND_ERROR "Unexpected number of entries in object list file (${num_objectfiles} instead of ${EXPECTED_NUM_OBJECTFILES})")
+endif()
+
+foreach(objlib_file ${objlib_files})
+ set(file_exists False)
+ if (EXISTS ${objlib_file})
+ set(file_exists True)
+ endif()
+
+ if (NOT file_exists)
+ if(attempts)
+ list(REMOVE_DUPLICATES attempts)
+ set(tried " Tried ${attempts}")
+ endif()
+ message(SEND_ERROR "File \"${objlib_file}\" does not exist!${tried}")
+ endif()
+endforeach()
diff --git a/Tests/GeneratorExpression/objlib1.c b/Tests/GeneratorExpression/objlib1.c
new file mode 100644
index 0000000..98a95a4
--- /dev/null
+++ b/Tests/GeneratorExpression/objlib1.c
@@ -0,0 +1,4 @@
+
+void objlib1()
+{
+}
diff --git a/Tests/GeneratorExpression/objlib2.c b/Tests/GeneratorExpression/objlib2.c
new file mode 100644
index 0000000..b2c1050
--- /dev/null
+++ b/Tests/GeneratorExpression/objlib2.c
@@ -0,0 +1,4 @@
+
+void objlib2()
+{
+}
diff --git a/Tests/RunCMake/File_Generate/OutputConflict-stderr.txt b/Tests/RunCMake/File_Generate/OutputConflict-stderr.txt
index 0abb7df..a242180 100644
--- a/Tests/RunCMake/File_Generate/OutputConflict-stderr.txt
+++ b/Tests/RunCMake/File_Generate/OutputConflict-stderr.txt
@@ -1,5 +1,6 @@
CMake Error in CMakeLists.txt:
- Evaluation file to be written multiple times for different configurations
- or languages with different content:
+ Evaluation file to be written multiple times with different content. This
+ is generally caused by the content evaluating the configuration type,
+ language, or location of object files:
.*output.txt
diff --git a/Tests/RunCMake/File_Generate/OutputNameMatchesObjects.cmake b/Tests/RunCMake/File_Generate/OutputNameMatchesObjects.cmake
index d807450..daa7c49 100644
--- a/Tests/RunCMake/File_Generate/OutputNameMatchesObjects.cmake
+++ b/Tests/RunCMake/File_Generate/OutputNameMatchesObjects.cmake
@@ -1,3 +1,4 @@
+enable_language(CXX)
file(GENERATE
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/$<BOOL:$<TARGET_OBJECTS:foo>>somefile.cpp"