diff options
author | Robert Maynard <robert.maynard@kitware.com> | 2017-01-23 14:13:49 -0500 |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2017-04-18 11:36:09 -0400 |
commit | 93c89bc75ceee599ba7c08b8fe1ac5104942054f (patch) | |
tree | fc956fd1c58cd967309e78b9dd0f2384505b8807 | |
parent | ac0cf7ff4f5a846381593cf28ebbc9cfaf107149 (diff) | |
download | cmake-93c89bc75ceee599ba7c08b8fe1ac5104942054f.tar.gz |
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.rst | 6 | ||||
-rw-r--r-- | Help/manual/cmake-generator-expressions.7.rst | 4 | ||||
-rw-r--r-- | Help/release/dev/add_custom_command-TARGET_OBJECTS.rst | 6 | ||||
-rw-r--r-- | Help/release/dev/file-GENERATE-TARGET_OBJECTS.rst | 6 | ||||
-rw-r--r-- | Source/cmGeneratorExpressionEvaluationFile.cxx | 6 | ||||
-rw-r--r-- | Source/cmGeneratorExpressionNode.cxx | 32 | ||||
-rw-r--r-- | Tests/GeneratorExpression/CMakeLists.txt | 16 | ||||
-rw-r--r-- | Tests/GeneratorExpression/check_object_files.cmake | 26 | ||||
-rw-r--r-- | Tests/GeneratorExpression/objlib1.c | 4 | ||||
-rw-r--r-- | Tests/GeneratorExpression/objlib2.c | 4 | ||||
-rw-r--r-- | Tests/RunCMake/File_Generate/OutputConflict-stderr.txt | 5 | ||||
-rw-r--r-- | Tests/RunCMake/File_Generate/OutputNameMatchesObjects.cmake | 1 |
12 files changed, 102 insertions, 14 deletions
diff --git a/Help/manual/cmake-buildsystem.7.rst b/Help/manual/cmake-buildsystem.7.rst index 2e6a803445..65d87bf1ae 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 3eac45fb7c..bddb174774 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 0000000000..c4a9ee8e62 --- /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 0000000000..853a803afb --- /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 dc54488582..15264545b4 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 65949a3a68..1215737812 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 adc87cdc47..8ac3419120 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 0000000000..cfccd2961f --- /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 0000000000..98a95a4038 --- /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 0000000000..b2c1050aec --- /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 0abb7df693..a242180047 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 d8074507bc..daa7c49ca6 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" |