summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Modules/AutomocInfo.cmake.in2
-rw-r--r--Source/QtDialog/AddCacheEntry.cxx12
-rw-r--r--Source/QtDialog/AddCacheEntry.h3
-rw-r--r--Source/QtDialog/CMakeSetupDialog.cxx25
-rw-r--r--Source/QtDialog/CMakeSetupDialog.h10
-rw-r--r--Source/cmExportFileGenerator.cxx63
-rw-r--r--Source/cmExportFileGenerator.h5
-rw-r--r--Source/cmExportInstallFileGenerator.cxx30
-rw-r--r--Source/cmExportInstallFileGenerator.h4
-rw-r--r--Source/cmQtAutomoc.cxx6
-rw-r--r--Source/cmTargetLinkLibrariesCommand.cxx50
-rw-r--r--Source/cmTargetLinkLibrariesCommand.h33
-rw-r--r--Source/kwsys/kwsysDateStamp.cmake4
-rw-r--r--Tests/CMakeCommands/target_link_libraries/CMakeLists.txt58
-rw-r--r--Tests/CMakeCommands/target_link_libraries/depA.cpp7
-rw-r--r--Tests/CMakeCommands/target_link_libraries/depA.h7
-rw-r--r--Tests/CMakeCommands/target_link_libraries/depB.cpp11
-rw-r--r--Tests/CMakeCommands/target_link_libraries/depB.h7
-rw-r--r--Tests/CMakeCommands/target_link_libraries/depC.cpp13
-rw-r--r--Tests/CMakeCommands/target_link_libraries/depC.h12
-rw-r--r--Tests/CMakeCommands/target_link_libraries/targetA.cpp12
-rw-r--r--Tests/CMakeLists.txt2
22 files changed, 332 insertions, 44 deletions
diff --git a/Modules/AutomocInfo.cmake.in b/Modules/AutomocInfo.cmake.in
index 8542ff6..2c7c724 100644
--- a/Modules/AutomocInfo.cmake.in
+++ b/Modules/AutomocInfo.cmake.in
@@ -11,5 +11,5 @@ set(AM_QT_MOC_EXECUTABLE "@QT_MOC_EXECUTABLE@")
set(AM_CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@/")
set(AM_CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@/")
set(AM_QT_VERSION_MAJOR "@QT_VERSION_MAJOR@" )
-set(AM_Qt5SrcTools_VERSION_MAJOR "@Qt5SrcTools_VERSION_MAJOR@" )
+set(AM_Qt5Core_VERSION_MAJOR "@Qt5Core_VERSION_MAJOR@" )
set(AM_TARGET_NAME "@_moc_target_name@")
diff --git a/Source/QtDialog/AddCacheEntry.cxx b/Source/QtDialog/AddCacheEntry.cxx
index b4d9191..00aaf69 100644
--- a/Source/QtDialog/AddCacheEntry.cxx
+++ b/Source/QtDialog/AddCacheEntry.cxx
@@ -12,15 +12,16 @@
#include "AddCacheEntry.h"
#include <QMetaProperty>
+#include <QCompleter>
static const int NumTypes = 4;
-static const QString TypeStrings[NumTypes] =
+static const QString TypeStrings[NumTypes] =
{ "BOOL", "PATH", "FILEPATH", "STRING" };
-static const QCMakeProperty::PropertyType Types[NumTypes] =
- { QCMakeProperty::BOOL, QCMakeProperty::PATH,
- QCMakeProperty::FILEPATH, QCMakeProperty::STRING};
+static const QCMakeProperty::PropertyType Types[NumTypes] =
+ { QCMakeProperty::BOOL, QCMakeProperty::PATH,
+ QCMakeProperty::FILEPATH, QCMakeProperty::STRING};
-AddCacheEntry::AddCacheEntry(QWidget* p)
+AddCacheEntry::AddCacheEntry(QWidget* p, const QStringList& completions)
: QWidget(p)
{
this->setupUi(this);
@@ -42,6 +43,7 @@ AddCacheEntry::AddCacheEntry(QWidget* p)
this->setTabOrder(path, filepath);
this->setTabOrder(filepath, string);
this->setTabOrder(string, this->Description);
+ this->Name->setCompleter(new QCompleter(completions, this));
}
QString AddCacheEntry::name() const
diff --git a/Source/QtDialog/AddCacheEntry.h b/Source/QtDialog/AddCacheEntry.h
index db6baf9..e219d4e 100644
--- a/Source/QtDialog/AddCacheEntry.h
+++ b/Source/QtDialog/AddCacheEntry.h
@@ -15,6 +15,7 @@
#include <QWidget>
#include <QCheckBox>
+#include <QStringList>
#include "QCMake.h"
#include "ui_AddCacheEntry.h"
@@ -23,7 +24,7 @@ class AddCacheEntry : public QWidget, public Ui::AddCacheEntry
{
Q_OBJECT
public:
- AddCacheEntry(QWidget* p);
+ AddCacheEntry(QWidget* p, const QStringList& completions);
QString name() const;
QVariant value() const;
diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx
index c8c4bfa..1c058d3 100644
--- a/Source/QtDialog/CMakeSetupDialog.cxx
+++ b/Source/QtDialog/CMakeSetupDialog.cxx
@@ -68,6 +68,9 @@ CMakeSetupDialog::CMakeSetupDialog()
int w = settings.value("Width", 700).toInt();
this->resize(w, h);
+ this->AddVariableCompletions = settings.value("AddVariableCompletionEntries",
+ QStringList("CMAKE_INSTALL_PREFIX")).toStringList();
+
QWidget* cont = new QWidget(this);
this->setupUi(cont);
this->Splitter->setStretchFactor(0, 3);
@@ -1008,7 +1011,7 @@ void CMakeSetupDialog::addCacheEntry()
dialog.resize(400, 200);
dialog.setWindowTitle(tr("Add Cache Entry"));
QVBoxLayout* l = new QVBoxLayout(&dialog);
- AddCacheEntry* w = new AddCacheEntry(&dialog);
+ AddCacheEntry* w = new AddCacheEntry(&dialog, this->AddVariableCompletions);
QDialogButtonBox* btns = new QDialogButtonBox(
QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
Qt::Horizontal, &dialog);
@@ -1021,6 +1024,26 @@ void CMakeSetupDialog::addCacheEntry()
{
QCMakeCacheModel* m = this->CacheValues->cacheModel();
m->insertProperty(w->type(), w->name(), w->description(), w->value(), false);
+
+ // only add variable names to the completion which are new
+ if (!this->AddVariableCompletions.contains(w->name()))
+ {
+ this->AddVariableCompletions << w->name();
+ // limit to at most 100 completion items
+ if (this->AddVariableCompletions.size() > 100)
+ {
+ this->AddVariableCompletions.removeFirst();
+ }
+ // make sure CMAKE_INSTALL_PREFIX is always there
+ if (!this->AddVariableCompletions.contains("CMAKE_INSTALL_PREFIX"))
+ {
+ this->AddVariableCompletions << QString("CMAKE_INSTALL_PREFIX");
+ }
+ QSettings settings;
+ settings.beginGroup("Settings/StartPath");
+ settings.setValue("AddVariableCompletionEntries",
+ this->AddVariableCompletions);
+ }
}
}
diff --git a/Source/QtDialog/CMakeSetupDialog.h b/Source/QtDialog/CMakeSetupDialog.h
index 5121759..2599675 100644
--- a/Source/QtDialog/CMakeSetupDialog.h
+++ b/Source/QtDialog/CMakeSetupDialog.h
@@ -36,7 +36,7 @@ public slots:
void setBinaryDirectory(const QString& dir);
void setSourceDirectory(const QString& dir);
-protected slots:
+protected slots:
void initialize();
void doConfigure();
void doGenerate();
@@ -46,7 +46,7 @@ protected slots:
void doInterrupt();
void error(const QString& message);
void message(const QString& message);
-
+
void doSourceBrowse();
void doBinaryBrowse();
void doReloadCache();
@@ -105,6 +105,8 @@ protected:
QTextCharFormat ErrorFormat;
QTextCharFormat MessageFormat;
+ QStringList AddVariableCompletions;
+
QEventLoop LocalLoop;
float ProgressOffset;
@@ -118,8 +120,8 @@ class QCMakeThread : public QThread
public:
QCMakeThread(QObject* p);
QCMake* cmakeInstance() const;
-
-signals:
+
+signals:
void cmakeInitialized();
protected:
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 9e5c91e..c4f5dfb 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -368,3 +368,66 @@ cmExportFileGenerator
os << " )\n"
<< "\n";
}
+
+
+//----------------------------------------------------------------------------
+void
+cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os)
+{
+ // Add code which verifies at cmake time that the file which is being
+ // imported actually exists on disk. This should in theory always be theory
+ // case, but still when packages are split into normal and development
+ // packages this might get broken (e.g. the Config.cmake could be part of
+ // the non-development package, something similar happened to me without
+ // on SUSE with a mysql pkg-config file, which claimed everything is fine,
+ // but the development package was not installed.).
+ os << "# Loop over all imported files and verify that they actually exist\n"
+ "FOREACH(target ${_IMPORT_CHECK_TARGETS} )\n"
+ " FOREACH(file ${_IMPORT_CHECK_FILES_FOR_${target}} )\n"
+ " IF(NOT EXISTS \"${file}\" )\n"
+ " MESSAGE(FATAL_ERROR \"The imported target \\\"${target}\\\""
+ " references the file\n"
+ " \\\"${file}\\\"\n"
+ "but this file does not exist. Possible reasons include:\n"
+ "* The file was deleted, renamed, or moved to another location.\n"
+ "* An install or uninstall procedure did not complete successfully.\n"
+ "* The installation package was faulty and contained\n"
+ " \\\"${CMAKE_CURRENT_LIST_FILE}\\\"\n"
+ "but not all the files it references.\n"
+ "\")\n"
+ " ENDIF()\n"
+ " ENDFOREACH()\n"
+ " UNSET(_IMPORT_CHECK_FILES_FOR_${target})\n"
+ "ENDFOREACH()\n"
+ "UNSET(_IMPORT_CHECK_TARGETS)\n"
+ "\n";
+}
+
+
+//----------------------------------------------------------------------------
+void
+cmExportFileGenerator
+::GenerateImportedFileChecksCode(std::ostream& os, cmTarget* target,
+ ImportPropertyMap const& properties,
+ const std::set<std::string>& importedLocations)
+{
+ // Construct the imported target name.
+ std::string targetName = this->Namespace;
+ targetName += target->GetName();
+
+ os << "LIST(APPEND _IMPORT_CHECK_TARGETS " << targetName << " )\n"
+ "LIST(APPEND _IMPORT_CHECK_FILES_FOR_" << targetName << " ";
+
+ for(std::set<std::string>::const_iterator li = importedLocations.begin();
+ li != importedLocations.end();
+ ++li)
+ {
+ ImportPropertyMap::const_iterator pi = properties.find(*li);
+ if (pi != properties.end())
+ {
+ os << "\"" << pi->second << "\" ";
+ }
+ }
+
+ os << ")\n\n";
+}
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index 05f73a2..f271e55 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -56,6 +56,11 @@ protected:
void GenerateImportPropertyCode(std::ostream& os, const char* config,
cmTarget* target,
ImportPropertyMap const& properties);
+ void GenerateImportedFileChecksCode(std::ostream& os, cmTarget* target,
+ ImportPropertyMap const& properties,
+ const std::set<std::string>& importedLocations);
+ void GenerateImportedFileCheckLoop(std::ostream& os);
+
// Collect properties with detailed information about targets beyond
// their location on disk.
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index 23ff5fb..da14dd7 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -167,16 +167,18 @@ cmExportInstallFileGenerator
// Collect import properties for this target.
cmTargetExport* te = *tei;
ImportPropertyMap properties;
+ std::set<std::string> importedLocations;
+ this->SetImportLocationProperty(config, suffix, te->ArchiveGenerator,
+ properties, importedLocations);
+ this->SetImportLocationProperty(config, suffix, te->LibraryGenerator,
+ properties, importedLocations);
this->SetImportLocationProperty(config, suffix,
- te->ArchiveGenerator, properties);
- this->SetImportLocationProperty(config, suffix,
- te->LibraryGenerator, properties);
- this->SetImportLocationProperty(config, suffix,
- te->RuntimeGenerator, properties);
- this->SetImportLocationProperty(config, suffix,
- te->FrameworkGenerator, properties);
- this->SetImportLocationProperty(config, suffix,
- te->BundleGenerator, properties);
+ te->RuntimeGenerator, properties,
+ importedLocations);
+ this->SetImportLocationProperty(config, suffix, te->FrameworkGenerator,
+ properties, importedLocations);
+ this->SetImportLocationProperty(config, suffix, te->BundleGenerator,
+ properties, importedLocations);
// If any file location was set for the target add it to the
// import file.
@@ -194,9 +196,13 @@ cmExportInstallFileGenerator
// Generate code in the export file.
this->GenerateImportPropertyCode(os, config, te->Target, properties);
+ this->GenerateImportedFileChecksCode(os, te->Target, properties,
+ importedLocations);
}
}
+ this->GenerateImportedFileCheckLoop(os);
+
// Cleanup the import prefix variable.
if(!this->ImportPrefix.empty())
{
@@ -211,7 +217,9 @@ void
cmExportInstallFileGenerator
::SetImportLocationProperty(const char* config, std::string const& suffix,
cmInstallTargetGenerator* itgen,
- ImportPropertyMap& properties)
+ ImportPropertyMap& properties,
+ std::set<std::string>& importedLocations
+ )
{
// Skip rules that do not match this configuration.
if(!(itgen && itgen->InstallsForConfig(config)))
@@ -249,6 +257,7 @@ cmExportInstallFileGenerator
// Store the property.
properties[prop] = value;
+ importedLocations.insert(prop);
}
else
{
@@ -291,6 +300,7 @@ cmExportInstallFileGenerator
// Store the property.
properties[prop] = value;
+ importedLocations.insert(prop);
}
}
diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h
index 8c8fb44..fb678e8 100644
--- a/Source/cmExportInstallFileGenerator.h
+++ b/Source/cmExportInstallFileGenerator.h
@@ -75,7 +75,9 @@ protected:
void SetImportLocationProperty(const char* config,
std::string const& suffix,
cmInstallTargetGenerator* itgen,
- ImportPropertyMap& properties);
+ ImportPropertyMap& properties,
+ std::set<std::string>& importedLocations
+ );
void ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen);
diff --git a/Source/cmQtAutomoc.cxx b/Source/cmQtAutomoc.cxx
index 7a80f28..d07f84b 100644
--- a/Source/cmQtAutomoc.cxx
+++ b/Source/cmQtAutomoc.cxx
@@ -49,11 +49,11 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
{
cmMakefile* makefile = target->GetMakefile();
const char* targetName = target->GetName();
- // don't do anything if there is no Qt4 or Qt5SrcTools (which contains moc):
+ // don't do anything if there is no Qt4 or Qt5Core (which contains moc):
std::string qtMajorVersion = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
if (qtMajorVersion == "")
{
- qtMajorVersion = makefile->GetSafeDefinition("Qt5SrcTools_VERSION_MAJOR");
+ qtMajorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
}
if (qtMajorVersion != "4" && qtMajorVersion != "5")
{
@@ -229,7 +229,7 @@ bool cmQtAutomoc::ReadAutomocInfoFile(cmMakefile* makefile,
if (this->QtMajorVersion == "")
{
this->QtMajorVersion = makefile->GetSafeDefinition(
- "AM_Qt5SrcTools_VERSION_MAJOR");
+ "AM_Qt5Core_VERSION_MAJOR");
}
this->Sources = makefile->GetSafeDefinition("AM_SOURCES");
this->Headers = makefile->GetSafeDefinition("AM_HEADERS");
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index 805959d..36c4ca8 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -95,8 +95,8 @@ bool cmTargetLinkLibrariesCommand
bool haveLLT = false;
// Start with primary linking and switch to link interface
- // specification when the keyword is encountered.
- this->DoingInterface = false;
+ // specification if the keyword is encountered as the first argument.
+ this->CurrentProcessingState = ProcessingLinkLibraries;
// add libraries, nothe that there is an optional prefix
// of debug and optimized than can be used
@@ -104,7 +104,7 @@ bool cmTargetLinkLibrariesCommand
{
if(args[i] == "LINK_INTERFACE_LIBRARIES")
{
- this->DoingInterface = true;
+ this->CurrentProcessingState = ProcessingLinkInterface;
if(i != 1)
{
this->Makefile->IssueMessage(
@@ -115,6 +115,32 @@ bool cmTargetLinkLibrariesCommand
return true;
}
}
+ else if(args[i] == "LINK_PUBLIC")
+ {
+ if(i != 1 && this->CurrentProcessingState != ProcessingPrivateInterface)
+ {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ "The LINK_PUBLIC or LINK_PRIVATE option must appear as the second "
+ "argument, just after the target name."
+ );
+ return true;
+ }
+ this->CurrentProcessingState = ProcessingPublicInterface;
+ }
+ else if(args[i] == "LINK_PRIVATE")
+ {
+ if(i != 1 && this->CurrentProcessingState != ProcessingPublicInterface)
+ {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ "The LINK_PUBLIC or LINK_PRIVATE option must appear as the second "
+ "argument, just after the target name."
+ );
+ return true;
+ }
+ this->CurrentProcessingState = ProcessingPrivateInterface;
+ }
else if(args[i] == "debug")
{
if(haveLLT)
@@ -186,10 +212,12 @@ bool cmTargetLinkLibrariesCommand
cmSystemTools::SetFatalErrorOccured();
}
- // If the INTERFACE option was given, make sure the
- // LINK_INTERFACE_LIBRARIES property exists. This allows the
- // command to be used to specify an empty link interface.
- if(this->DoingInterface &&
+ // If any of the LINK_ options were given, make sure the
+ // LINK_INTERFACE_LIBRARIES target property exists.
+ // Use of any of the new keywords implies awareness of
+ // this property. And if no libraries are named, it should
+ // result in an empty link interface.
+ if(this->CurrentProcessingState != ProcessingLinkLibraries &&
!this->Target->GetProperty("LINK_INTERFACE_LIBRARIES"))
{
this->Target->SetProperty("LINK_INTERFACE_LIBRARIES", "");
@@ -217,11 +245,15 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
cmTarget::LinkLibraryType llt)
{
// Handle normal case first.
- if(!this->DoingInterface)
+ if(this->CurrentProcessingState != ProcessingLinkInterface)
{
this->Makefile
->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt);
- return;
+ if (this->CurrentProcessingState != ProcessingPublicInterface)
+ {
+ // Not LINK_INTERFACE_LIBRARIES or LINK_PUBLIC, do not add to interface.
+ return;
+ }
}
// Get the list of configurations considered to be DEBUG.
diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h
index ce57df7..8df4ac0 100644
--- a/Source/cmTargetLinkLibrariesCommand.h
+++ b/Source/cmTargetLinkLibrariesCommand.h
@@ -19,7 +19,7 @@
*
* cmTargetLinkLibrariesCommand is used to specify a list of libraries to link
* into executable(s) or shared objects. The names of the libraries
- * should be those defined by the LIBRARY(library) command(s).
+ * should be those defined by the LIBRARY(library) command(s).
*/
class cmTargetLinkLibrariesCommand : public cmCommand
{
@@ -27,7 +27,7 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
+ virtual cmCommand* Clone()
{
return new cmTargetLinkLibrariesCommand;
}
@@ -47,12 +47,12 @@ public:
/**
* Succinct documentation.
*/
- virtual const char* GetTerseDocumentation()
+ virtual const char* GetTerseDocumentation()
{
- return
+ return
"Link a target to given libraries.";
}
-
+
/**
* More documentation.
*/
@@ -107,6 +107,18 @@ public:
"Libraries specified as \"general\" (or without any keyword) are "
"treated as if specified for both \"debug\" and \"optimized\"."
"\n"
+ " target_link_libraries(<target>\n"
+ " <LINK_PRIVATE|LINK_PUBLIC>\n"
+ " [[debug|optimized|general] <lib>] ...\n"
+ " [<LINK_PRIVATE|LINK_PUBLIC>\n"
+ " [[debug|optimized|general] <lib>] ...])\n"
+ "The LINK_PUBLIC and LINK_PRIVATE modes can be used to specify both "
+ "the link dependencies and the link interface in one command. "
+ "Libraries and targets following LINK_PUBLIC are linked to, and are "
+ "made part of the LINK_INTERFACE_LIBRARIES. Libraries and targets "
+ "following LINK_PRIVATE are linked to, but are not made part of the "
+ "LINK_INTERFACE_LIBRARIES. "
+ "\n"
"The library dependency graph is normally acyclic (a DAG), but in the "
"case of mutually-dependent STATIC libraries CMake allows the graph "
"to contain cycles (strongly connected components). "
@@ -130,14 +142,21 @@ public:
")"
;
}
-
+
cmTypeMacro(cmTargetLinkLibrariesCommand, cmCommand);
private:
void LinkLibraryTypeSpecifierWarning(int left, int right);
static const char* LinkLibraryTypeNames[3];
cmTarget* Target;
- bool DoingInterface;
+ enum ProcessingState {
+ ProcessingLinkLibraries,
+ ProcessingLinkInterface,
+ ProcessingPublicInterface,
+ ProcessingPrivateInterface
+ };
+
+ ProcessingState CurrentProcessingState;
void HandleLibrary(const char* lib, cmTarget::LinkLibraryType llt);
};
diff --git a/Source/kwsys/kwsysDateStamp.cmake b/Source/kwsys/kwsysDateStamp.cmake
index 0a1f936..bd72486 100644
--- a/Source/kwsys/kwsysDateStamp.cmake
+++ b/Source/kwsys/kwsysDateStamp.cmake
@@ -15,7 +15,7 @@
SET(KWSYS_DATE_STAMP_YEAR 2011)
# KWSys version date month component. Format is MM.
-SET(KWSYS_DATE_STAMP_MONTH 11)
+SET(KWSYS_DATE_STAMP_MONTH 12)
# KWSys version date day component. Format is DD.
-SET(KWSYS_DATE_STAMP_DAY 23)
+SET(KWSYS_DATE_STAMP_DAY 01)
diff --git a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
new file mode 100644
index 0000000..1faa888
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
@@ -0,0 +1,58 @@
+cmake_minimum_required(VERSION 2.8)
+
+project(target_link_libraries)
+
+file(WRITE
+ "${CMAKE_CURRENT_BINARY_DIR}/main.cxx"
+ "int main() { return 0; }
+"
+)
+
+add_executable(
+ target_link_libraries
+ "${CMAKE_CURRENT_BINARY_DIR}/main.cxx"
+)
+
+macro(ASSERT_PROPERTY _target _property _value)
+ get_target_property(_out ${_target} ${_property})
+ if (NOT _out)
+ set(_out "")
+ endif()
+ if (NOT "${_out}" STREQUAL "${_value}")
+ message(SEND_ERROR "Target ${_target} does not have property ${_property} with value ${_value}. Actual value: ${_out}")
+ endif()
+endmacro()
+
+include(GenerateExportHeader)
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+add_library(depA SHARED depA.cpp)
+generate_export_header(depA)
+
+add_library(depB SHARED depB.cpp)
+generate_export_header(depB)
+
+target_link_libraries(depB LINK_PRIVATE depA)
+
+add_library(depC SHARED depC.cpp)
+generate_export_header(depC)
+
+target_link_libraries(depC LINK_PUBLIC depA)
+
+assert_property(depA LINK_INTERFACE_LIBRARIES "")
+assert_property(depB LINK_INTERFACE_LIBRARIES "")
+assert_property(depC LINK_INTERFACE_LIBRARIES "depA")
+
+add_executable(targetA targetA.cpp)
+
+target_link_libraries(targetA LINK_INTERFACE_LIBRARIES depA depB)
+
+assert_property(targetA LINK_INTERFACE_LIBRARIES "depA;depB")
+
+set_target_properties(targetA PROPERTIES LINK_INTERFACE_LIBRARIES "")
+
+assert_property(targetA LINK_INTERFACE_LIBRARIES "")
+
+target_link_libraries(targetA depB depC)
+
+assert_property(targetA LINK_INTERFACE_LIBRARIES "")
diff --git a/Tests/CMakeCommands/target_link_libraries/depA.cpp b/Tests/CMakeCommands/target_link_libraries/depA.cpp
new file mode 100644
index 0000000..c2e8e7b
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/depA.cpp
@@ -0,0 +1,7 @@
+
+#include "depA.h"
+
+int DepA::foo()
+{
+ return 0;
+}
diff --git a/Tests/CMakeCommands/target_link_libraries/depA.h b/Tests/CMakeCommands/target_link_libraries/depA.h
new file mode 100644
index 0000000..7a85948
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/depA.h
@@ -0,0 +1,7 @@
+
+#include "depa_export.h"
+
+struct DEPA_EXPORT DepA
+{
+ int foo();
+};
diff --git a/Tests/CMakeCommands/target_link_libraries/depB.cpp b/Tests/CMakeCommands/target_link_libraries/depB.cpp
new file mode 100644
index 0000000..97e5be2
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/depB.cpp
@@ -0,0 +1,11 @@
+
+#include "depB.h"
+
+#include "depA.h"
+
+int DepB::foo()
+{
+ DepA a;
+
+ return 0;
+}
diff --git a/Tests/CMakeCommands/target_link_libraries/depB.h b/Tests/CMakeCommands/target_link_libraries/depB.h
new file mode 100644
index 0000000..e617813
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/depB.h
@@ -0,0 +1,7 @@
+
+#include "depb_export.h"
+
+struct DEPB_EXPORT DepB
+{
+ int foo();
+};
diff --git a/Tests/CMakeCommands/target_link_libraries/depC.cpp b/Tests/CMakeCommands/target_link_libraries/depC.cpp
new file mode 100644
index 0000000..93410a8
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/depC.cpp
@@ -0,0 +1,13 @@
+
+#include "depC.h"
+
+int DepC::foo()
+{
+ return 0;
+}
+
+DepA DepC::getA()
+{
+ DepA a;
+ return a;
+} \ No newline at end of file
diff --git a/Tests/CMakeCommands/target_link_libraries/depC.h b/Tests/CMakeCommands/target_link_libraries/depC.h
new file mode 100644
index 0000000..4d65c9e
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/depC.h
@@ -0,0 +1,12 @@
+
+#include "depc_export.h"
+
+#include "depA.h"
+
+struct DEPC_EXPORT DepC
+{
+ int foo();
+
+ DepA getA();
+
+};
diff --git a/Tests/CMakeCommands/target_link_libraries/targetA.cpp b/Tests/CMakeCommands/target_link_libraries/targetA.cpp
new file mode 100644
index 0000000..3c6472e
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/targetA.cpp
@@ -0,0 +1,12 @@
+
+#include "depB.h"
+#include "depC.h"
+
+int main(int argc, char **argv)
+{
+ DepA a;
+ DepB b;
+ DepC c;
+
+ return a.foo() + b.foo() + c.foo();
+}
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 28c6261..1851f7a 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -1658,6 +1658,8 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
-P "${CMake_SOURCE_DIR}/Tests/CMakeCommands/build_command/RunCMake.cmake"
)
+ ADD_TEST_MACRO(CMakeCommands.target_link_libraries target_link_libraries)
+
CONFIGURE_FILE(
"${CMake_SOURCE_DIR}/Tests/CTestTestCrash/test.cmake.in"
"${CMake_BINARY_DIR}/Tests/CTestTestCrash/test.cmake"