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>
This commit is contained in:
Robert Maynard
2017-01-23 14:13:49 -05:00
committed by Brad King
parent ac0cf7ff4f
commit 93c89bc75c
12 changed files with 102 additions and 14 deletions
+6
View File
@@ -136,6 +136,12 @@ indirectly by using an :ref:`Interface Library <Interface Libraries>`
whose :prop_tgt:`INTERFACE_SOURCES` target property is set to name whose :prop_tgt:`INTERFACE_SOURCES` target property is set to name
``$<TARGET_OBJECTS:objlib>``. ``$<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 Build Specification and Usage Requirements
========================================== ==========================================
@@ -290,9 +290,7 @@ Available output expressions are:
Content of ``...`` converted to a C identifier. Content of ``...`` converted to a C identifier.
``$<TARGET_OBJECTS:objLib>`` ``$<TARGET_OBJECTS:objLib>``
List of objects resulting from build of ``objLib``. ``objLib`` must be an List of objects resulting from build of ``objLib``. ``objLib`` must be an
object of type ``OBJECT_LIBRARY``. This expression may only be used in object of type ``OBJECT_LIBRARY``.
the sources of :command:`add_library` and :command:`add_executable`
commands.
``$<SHELL_PATH:...>`` ``$<SHELL_PATH:...>``
Content of ``...`` converted to shell path style. For example, slashes are Content of ``...`` converted to shell path style. For example, slashes are
converted to backslashes in Windows shells and drive letters are converted converted to backslashes in Windows shells and drive letters are converted
@@ -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)>`.
@@ -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)>`.
@@ -64,8 +64,10 @@ void cmGeneratorExpressionEvaluationFile::Generate(
return; return;
} }
std::ostringstream e; std::ostringstream e;
e << "Evaluation file to be written multiple times for different " e << "Evaluation file to be written multiple times with different "
"configurations or languages with different content:\n " "content. "
"This is generally caused by the content evaluating the "
"configuration type, language, or location of object files:\n "
<< outputFileName; << outputFileName;
lg->IssueMessage(cmake::FATAL_ERROR, e.str()); lg->IssueMessage(cmake::FATAL_ERROR, e.str());
return; return;
+25 -7
View File
@@ -1243,20 +1243,38 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode
return std::string(); return std::string();
} }
if (!context->EvaluateForBuildsystem) { if (!context->EvaluateForBuildsystem) {
std::ostringstream e; cmGlobalGenerator* gg = context->LG->GetGlobalGenerator();
e << "The evaluation of the TARGET_OBJECTS generator expression " std::string reason;
"is only suitable for consumption by CMake. It is not suitable " if (!gg->HasKnownObjectFileLocation(&reason)) {
"for writing out elsewhere."; std::ostringstream e;
reportError(context, content->GetOriginalExpression(), e.str()); e << "The evaluation of the TARGET_OBJECTS generator expression "
return std::string(); "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; std::vector<std::string> objects;
gt->GetTargetObjectNames(context->Config, 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(); for (std::vector<std::string>::iterator oi = objects.begin();
oi != objects.end(); ++oi) { oi != objects.end(); ++oi) {
*oi = gt->ObjectDirectory + *oi; *oi = obj_dir + *oi;
} }
// Create the cmSourceFile instances in the referencing directory. // Create the cmSourceFile instances in the referencing directory.
+16
View File
@@ -292,3 +292,19 @@ set(CMP0044_TYPE NEW)
add_subdirectory(CMP0044 ${CMAKE_BINARY_DIR}/CMP0044-NEW) add_subdirectory(CMP0044 ${CMAKE_BINARY_DIR}/CMP0044-NEW)
set(CMP0044_TYPE OLD) set(CMP0044_TYPE OLD)
add_subdirectory(CMP0044 ${CMAKE_BINARY_DIR}/CMP0044-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()
@@ -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()
+4
View File
@@ -0,0 +1,4 @@
void objlib1()
{
}
+4
View File
@@ -0,0 +1,4 @@
void objlib2()
{
}
@@ -1,5 +1,6 @@
CMake Error in CMakeLists.txt: CMake Error in CMakeLists.txt:
Evaluation file to be written multiple times for different configurations Evaluation file to be written multiple times with different content. This
or languages with different content: is generally caused by the content evaluating the configuration type,
language, or location of object files:
.*output.txt .*output.txt
@@ -1,3 +1,4 @@
enable_language(CXX)
file(GENERATE file(GENERATE
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/$<BOOL:$<TARGET_OBJECTS:foo>>somefile.cpp" OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/$<BOOL:$<TARGET_OBJECTS:foo>>somefile.cpp"