summaryrefslogtreecommitdiffstats
path: root/Source/cmTargetSourcesCommand.cxx
diff options
context:
space:
mode:
authorPatrick Stotko <stotko@cs.uni-bonn.de>2018-06-02 15:20:51 (GMT)
committerPatrick Stotko <stotko@cs.uni-bonn.de>2018-06-18 19:01:57 (GMT)
commit316815e1f4beb66b679f27f96800facef572889e (patch)
tree99c44018136c1fe6ead03b4c00359af72be1dc82 /Source/cmTargetSourcesCommand.cxx
parentf31d4ac7d68a1939d22ab7246b51e0ac10842bec (diff)
downloadCMake-316815e1f4beb66b679f27f96800facef572889e.zip
CMake-316815e1f4beb66b679f27f96800facef572889e.tar.gz
CMake-316815e1f4beb66b679f27f96800facef572889e.tar.bz2
target_sources: Interpret relative paths as relative to the calling directory
Previously the command considered non-absolute source file paths relative to the associated target on the LHS. This causes problems in incremental builds where files are added from subdirectories and forces users to workaround by manually converting to absolute paths. Change this to enable more intuitive usage by projects. Fixes #17981
Diffstat (limited to 'Source/cmTargetSourcesCommand.cxx')
-rw-r--r--Source/cmTargetSourcesCommand.cxx87
1 files changed, 86 insertions, 1 deletions
diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx
index 3dd3748..62e323c 100644
--- a/Source/cmTargetSourcesCommand.cxx
+++ b/Source/cmTargetSourcesCommand.cxx
@@ -2,10 +2,14 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTargetSourcesCommand.h"
+#include <cstring>
#include <sstream>
#include "cmAlgorithms.h"
+#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmake.h"
@@ -17,6 +21,14 @@ bool cmTargetSourcesCommand::InitialPass(std::vector<std::string> const& args,
return this->HandleArguments(args, "SOURCES");
}
+void cmTargetSourcesCommand::HandleInterfaceContent(
+ cmTarget* tgt, const std::vector<std::string>& content, bool prepend,
+ bool system)
+{
+ cmTargetPropCommandBase::HandleInterfaceContent(
+ tgt, ConvertToAbsoluteContent(tgt, content, true), prepend, system);
+}
+
void cmTargetSourcesCommand::HandleMissingTarget(const std::string& name)
{
std::ostringstream e;
@@ -35,6 +47,79 @@ std::string cmTargetSourcesCommand::Join(
bool cmTargetSourcesCommand::HandleDirectContent(
cmTarget* tgt, const std::vector<std::string>& content, bool, bool)
{
- tgt->AppendProperty("SOURCES", this->Join(content).c_str());
+ tgt->AppendProperty(
+ "SOURCES",
+ this->Join(ConvertToAbsoluteContent(tgt, content, false)).c_str());
return true; // Successfully handled.
}
+
+std::vector<std::string> cmTargetSourcesCommand::ConvertToAbsoluteContent(
+ cmTarget* tgt, const std::vector<std::string>& content,
+ bool isInterfaceContent)
+{
+ // Skip conversion in case old behavior has been explictly requested
+ if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0076) ==
+ cmPolicies::OLD) {
+ return content;
+ }
+
+ bool changedPath = false;
+ std::vector<std::string> absoluteContent;
+ absoluteContent.reserve(content.size());
+ for (std::string const& src : content) {
+ std::string absoluteSrc;
+ if (cmSystemTools::FileIsFullPath(src) ||
+ cmGeneratorExpression::Find(src) == 0 ||
+ (!isInterfaceContent &&
+ strcmp(this->Makefile->GetCurrentSourceDirectory(),
+ tgt->GetMakefile()->GetCurrentSourceDirectory()) == 0)) {
+ absoluteSrc = src;
+ } else {
+ changedPath = true;
+ absoluteSrc = this->Makefile->GetCurrentSourceDirectory();
+ absoluteSrc += "/";
+ absoluteSrc += src;
+ }
+ absoluteContent.push_back(absoluteSrc);
+ }
+
+ if (!changedPath) {
+ return content;
+ }
+
+ bool issueMessage = true;
+ bool useAbsoluteContent = false;
+ std::ostringstream e;
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0076)) {
+ case cmPolicies::WARN:
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0076) << "\n";
+ break;
+ case cmPolicies::OLD:
+ issueMessage = false;
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0076));
+ break;
+ case cmPolicies::NEW: {
+ issueMessage = false;
+ useAbsoluteContent = true;
+ break;
+ }
+ }
+
+ if (issueMessage) {
+ if (isInterfaceContent) {
+ e << "An interface source of target \"" << tgt->GetName()
+ << "\" has a relative path.";
+ } else {
+ e << "A private source from a directory other than that of target \""
+ << tgt->GetName() << "\" has a relative path.";
+ }
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+ }
+
+ return useAbsoluteContent ? absoluteContent : content;
+}