summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Kelly <steveire@gmail.com>2013-01-05 11:13:49 (GMT)
committerStephen Kelly <steveire@gmail.com>2013-07-24 15:32:58 (GMT)
commit650e61f833c2cc3ace8405a22eb80a10cfc6187c (patch)
tree5cf31f8d89fab889dc622bf5f0f751dd0cb4db3e
parentff6de6d325fec9b4f257b27388be4a24fd8cadfe (diff)
downloadCMake-650e61f833c2cc3ace8405a22eb80a10cfc6187c.zip
CMake-650e61f833c2cc3ace8405a22eb80a10cfc6187c.tar.gz
CMake-650e61f833c2cc3ace8405a22eb80a10cfc6187c.tar.bz2
Add a convenient way to add the includes install dir to the INTERFACE.
Export the INCLUDES DESTINATION without appending to the INTERFACE_INCLUDE_DIRECTORIES of the target itself. That way, a target can be exported multiple times with different INCLUDES DESTINATION without unintended cross-pollution of export sets.
-rw-r--r--Source/cmExportFileGenerator.cxx12
-rw-r--r--Source/cmExportFileGenerator.h4
-rw-r--r--Source/cmExportInstallFileGenerator.cxx12
-rw-r--r--Source/cmInstallCommand.cxx24
-rw-r--r--Source/cmInstallCommand.h5
-rw-r--r--Source/cmInstallCommandArguments.cxx34
-rw-r--r--Source/cmInstallCommandArguments.h13
-rw-r--r--Source/cmTargetExport.h3
-rw-r--r--Tests/ExportImport/Export/CMakeLists.txt19
-rw-r--r--Tests/ExportImport/Import/A/deps_iface.c3
-rw-r--r--Tests/RunCMake/include_directories/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/include_directories/TargetInterfaceIncludes-result.txt1
-rw-r--r--Tests/RunCMake/include_directories/TargetInterfaceIncludes-stderr.txt4
-rw-r--r--Tests/RunCMake/include_directories/TargetInterfaceIncludes.cmake4
14 files changed, 127 insertions, 12 deletions
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index b4e6e81..cff539f 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -277,27 +277,31 @@ static bool checkInterfaceDirs(const std::string &prepro,
//----------------------------------------------------------------------------
void cmExportFileGenerator::PopulateIncludeDirectoriesInterface(
- cmTarget *target,
+ cmTargetExport *tei,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap &properties,
std::vector<std::string> &missingTargets)
{
+ cmTarget *target = tei->Target;
assert(preprocessRule == cmGeneratorExpression::InstallInterface);
const char *propName = "INTERFACE_INCLUDE_DIRECTORIES";
const char *input = target->GetProperty(propName);
- if (!input)
+ if (!input && tei->InterfaceIncludeDirectories.empty())
{
return;
}
- if (!*input)
+ if (!*input && tei->InterfaceIncludeDirectories.empty())
{
// Set to empty
properties[propName] = "";
return;
}
- std::string prepro = cmGeneratorExpression::Preprocess(input,
+ std::string includes = (input?input:"");
+ const char* sep = input ? ";" : "";
+ includes += sep + tei->InterfaceIncludeDirectories;
+ std::string prepro = cmGeneratorExpression::Preprocess(includes,
preprocessRule);
if (!prepro.empty())
{
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index a624ba6..9628b96 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -15,6 +15,8 @@
#include "cmCommand.h"
#include "cmGeneratorExpression.h"
+class cmTargetExport;
+
/** \class cmExportFileGenerator
* \brief Generate a file exporting targets from a build or install tree.
*
@@ -114,7 +116,7 @@ protected:
void GenerateInterfaceProperties(cmTarget *target, std::ostream& os,
const ImportPropertyMap &properties);
void PopulateIncludeDirectoriesInterface(
- cmTarget *target,
+ cmTargetExport *target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap &properties,
std::vector<std::string> &missingTargets);
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index ce7afc5..c97d4ff 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -39,7 +39,7 @@ std::string cmExportInstallFileGenerator::GetConfigImportFileGlob()
//----------------------------------------------------------------------------
bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
{
- std::vector<cmTarget*> allTargets;
+ std::vector<cmTargetExport*> allTargets;
{
std::string expectedTargets;
std::string sep;
@@ -49,10 +49,10 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
{
expectedTargets += sep + this->Namespace + (*tei)->Target->GetExportName();
sep = " ";
- cmTargetExport const* te = *tei;
+ cmTargetExport * te = *tei;
if(this->ExportedTargets.insert(te->Target).second)
{
- allTargets.push_back(te->Target);
+ allTargets.push_back(te);
}
else
{
@@ -115,16 +115,16 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
bool require2_8_12 = false;
// Create all the imported targets.
- for(std::vector<cmTarget*>::const_iterator
+ for(std::vector<cmTargetExport*>::const_iterator
tei = allTargets.begin();
tei != allTargets.end(); ++tei)
{
- cmTarget* te = *tei;
+ cmTarget* te = (*tei)->Target;
this->GenerateImportTargetCode(os, te);
ImportPropertyMap properties;
- this->PopulateIncludeDirectoriesInterface(te,
+ this->PopulateIncludeDirectoriesInterface(*tei,
cmGeneratorExpression::InstallInterface,
properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES",
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index d3a8037..4649eda 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -219,6 +219,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
cmCAStringVector runtimeArgVector (&argHelper,"RUNTIME",&group);
cmCAStringVector frameworkArgVector (&argHelper,"FRAMEWORK",&group);
cmCAStringVector bundleArgVector (&argHelper,"BUNDLE",&group);
+ cmCAStringVector includesArgVector (&argHelper,"INCLUDES",&group);
cmCAStringVector privateHeaderArgVector(&argHelper,"PRIVATE_HEADER",&group);
cmCAStringVector publicHeaderArgVector (&argHelper,"PUBLIC_HEADER",&group);
cmCAStringVector resourceArgVector (&argHelper,"RESOURCE",&group);
@@ -247,6 +248,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
cmInstallCommandArguments privateHeaderArgs(this->DefaultComponentName);
cmInstallCommandArguments publicHeaderArgs(this->DefaultComponentName);
cmInstallCommandArguments resourceArgs(this->DefaultComponentName);
+ cmInstallCommandIncludesArgument includesArgs;
// now parse the args for specific parts of the target (e.g. LIBRARY,
// RUNTIME, ARCHIVE etc.
@@ -258,6 +260,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
privateHeaderArgs.Parse(&privateHeaderArgVector.GetVector(), &unknownArgs);
publicHeaderArgs.Parse (&publicHeaderArgVector.GetVector(), &unknownArgs);
resourceArgs.Parse (&resourceArgVector.GetVector(), &unknownArgs);
+ includesArgs.Parse (&includesArgVector.GetVector(), &unknownArgs);
if(!unknownArgs.empty())
{
@@ -292,6 +295,13 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
return false;
}
+ if(!includesArgs.GetIncludeDirs().empty() && exports.GetString().empty())
+ {
+ this->SetError("TARGETS given INCLUDES DESTINATION, but EXPORT set "
+ "not specified.");
+ return false;
+ }
+
// Enforce argument rules too complex to specify for the
// general-purpose parser.
if(archiveArgs.GetNamelinkOnly() ||
@@ -747,6 +757,20 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
te->RuntimeGenerator = runtimeGenerator;
this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
->GetExportSets()[exports.GetString()]->AddTargetExport(te);
+
+ std::vector<std::string> dirs = includesArgs.GetIncludeDirs();
+ if(!dirs.empty())
+ {
+ std::string dirString;
+ const char *sep = "";
+ for (std::vector<std::string>::const_iterator it = dirs.begin();
+ it != dirs.end(); ++it)
+ {
+ te->InterfaceIncludeDirectories += sep;
+ te->InterfaceIncludeDirectories += *it;
+ sep = ";";
+ }
+ }
}
}
diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h
index 39acd23..6509501 100644
--- a/Source/cmInstallCommand.h
+++ b/Source/cmInstallCommand.h
@@ -102,6 +102,7 @@ public:
" [[ARCHIVE|LIBRARY|RUNTIME|FRAMEWORK|BUNDLE|\n"
" PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE]\n"
" [DESTINATION <dir>]\n"
+ " [INCLUDES DESTINATION [<dir> ...]]\n"
" [PERMISSIONS permissions...]\n"
" [CONFIGURATIONS [Debug|Release|...]]\n"
" [COMPONENT <component>]\n"
@@ -130,6 +131,10 @@ public:
"all target types. If only one is given then only targets of that "
"type will be installed (which can be used to install just a DLL or "
"just an import library)."
+ "The INCLUDES DESTINATION specifies a list of directories which will "
+ "be added to the INTERFACE_INCLUDE_DIRECTORIES of the <targets> when "
+ "exported by install(EXPORT). If a relative path is specified, it is "
+ "treated as relative to the $<INSTALL_PREFIX>."
"\n"
"The PRIVATE_HEADER, PUBLIC_HEADER, and RESOURCE arguments cause "
"subsequent properties to be applied to installing a FRAMEWORK "
diff --git a/Source/cmInstallCommandArguments.cxx b/Source/cmInstallCommandArguments.cxx
index 8e48f08..91ea861 100644
--- a/Source/cmInstallCommandArguments.cxx
+++ b/Source/cmInstallCommandArguments.cxx
@@ -203,3 +203,37 @@ bool cmInstallCommandArguments::CheckPermissions(
// This is not a valid permission.
return false;
}
+
+cmInstallCommandIncludesArgument::cmInstallCommandIncludesArgument()
+{
+
+}
+
+const std::vector<std::string>&
+cmInstallCommandIncludesArgument::GetIncludeDirs() const
+{
+ return this->IncludeDirs;
+}
+
+void cmInstallCommandIncludesArgument::Parse(
+ const std::vector<std::string>* args,
+ std::vector<std::string>*)
+{
+ if(args->empty())
+ {
+ return;
+ }
+ std::vector<std::string>::const_iterator it = args->begin();
+ ++it;
+ for ( ; it != args->end(); ++it)
+ {
+ std::string dir = *it;
+ if (!cmSystemTools::FileIsFullPath(it->c_str())
+ && cmGeneratorExpression::Find(*it) == std::string::npos)
+ {
+ dir = "$<INSTALL_PREFIX>/" + dir;
+ }
+ cmSystemTools::ConvertToUnixSlashes(dir);
+ this->IncludeDirs.push_back(dir);
+ }
+}
diff --git a/Source/cmInstallCommandArguments.h b/Source/cmInstallCommandArguments.h
index 01f7d56..90347e6 100644
--- a/Source/cmInstallCommandArguments.h
+++ b/Source/cmInstallCommandArguments.h
@@ -65,4 +65,17 @@ class cmInstallCommandArguments
bool CheckPermissions();
};
+class cmInstallCommandIncludesArgument
+{
+ public:
+ cmInstallCommandIncludesArgument();
+ void Parse(const std::vector<std::string>* args,
+ std::vector<std::string>* unconsumedArgs);
+
+ const std::vector<std::string>& GetIncludeDirs() const;
+
+ private:
+ std::vector<std::string> IncludeDirs;
+};
+
#endif
diff --git a/Source/cmTargetExport.h b/Source/cmTargetExport.h
index c9d87fb..7665888 100644
--- a/Source/cmTargetExport.h
+++ b/Source/cmTargetExport.h
@@ -12,6 +12,8 @@
#ifndef cmTargetExport_h
#define cmTargetExport_h
+#include "cmStandardIncludes.h"
+
class cmTarget;
class cmInstallTargetGenerator;
class cmInstallFilesGenerator;
@@ -33,6 +35,7 @@ public:
cmInstallTargetGenerator* FrameworkGenerator;
cmInstallTargetGenerator* BundleGenerator;
cmInstallFilesGenerator* HeaderGenerator;
+ std::string InterfaceIncludeDirectories;
///@}
};
diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt
index 370dffe..737ec43 100644
--- a/Tests/ExportImport/Export/CMakeLists.txt
+++ b/Tests/ExportImport/Export/CMakeLists.txt
@@ -270,9 +270,26 @@ install(TARGETS testLibRequired
testLibIncludeRequired5
testLibIncludeRequired6
testSharedLibRequired
- EXPORT RequiredExp DESTINATION lib )
+ EXPORT RequiredExp DESTINATION lib
+ INCLUDES DESTINATION
+ installIncludesTest
+ $<INSTALL_PREFIX>/installIncludesTest2)
install(EXPORT RequiredExp NAMESPACE Req:: FILE testLibRequiredTargets.cmake DESTINATION lib/cmake/testLibRequired)
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/installIncludesTest")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/installIncludesTest/installIncludesTest.h" "// No content\n")
+
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/installIncludesTest2")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/installIncludesTest2/installIncludesTest2.h" "// No content\n")
+install(FILES
+ "${CMAKE_CURRENT_BINARY_DIR}/installIncludesTest/installIncludesTest.h"
+ DESTINATION installIncludesTest
+)
+install(FILES
+ "${CMAKE_CURRENT_BINARY_DIR}/installIncludesTest2/installIncludesTest2.h"
+ DESTINATION installIncludesTest2
+)
+
install(TARGETS testLibDepends testSharedLibDepends EXPORT DependsExp DESTINATION lib )
install(EXPORT DependsExp FILE testLibDependsTargets.cmake DESTINATION lib/cmake/testLibDepends)
diff --git a/Tests/ExportImport/Import/A/deps_iface.c b/Tests/ExportImport/Import/A/deps_iface.c
index e73ca26..d9dc331 100644
--- a/Tests/ExportImport/Import/A/deps_iface.c
+++ b/Tests/ExportImport/Import/A/deps_iface.c
@@ -3,6 +3,9 @@
#include "testLibIncludeRequired2.h"
#include "testLibIncludeRequired6.h"
+#include "installIncludesTest.h"
+#include "installIncludesTest2.h"
+
#ifndef testLibRequired_IFACE_DEFINE
#error Expected testLibRequired_IFACE_DEFINE
#endif
diff --git a/Tests/RunCMake/include_directories/RunCMakeTest.cmake b/Tests/RunCMake/include_directories/RunCMakeTest.cmake
index 520dd44..e582960 100644
--- a/Tests/RunCMake/include_directories/RunCMakeTest.cmake
+++ b/Tests/RunCMake/include_directories/RunCMakeTest.cmake
@@ -9,3 +9,4 @@ run_cmake(RelativePathInInterface)
run_cmake(ImportedTarget)
run_cmake(RelativePathInGenex)
run_cmake(CMP0021)
+run_cmake(TargetInterfaceIncludes)
diff --git a/Tests/RunCMake/include_directories/TargetInterfaceIncludes-result.txt b/Tests/RunCMake/include_directories/TargetInterfaceIncludes-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/include_directories/TargetInterfaceIncludes-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/include_directories/TargetInterfaceIncludes-stderr.txt b/Tests/RunCMake/include_directories/TargetInterfaceIncludes-stderr.txt
new file mode 100644
index 0000000..d153927
--- /dev/null
+++ b/Tests/RunCMake/include_directories/TargetInterfaceIncludes-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at TargetInterfaceIncludes.cmake:3 \(install\):
+ install TARGETS given INCLUDES DESTINATION, but EXPORT set not specified.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/include_directories/TargetInterfaceIncludes.cmake b/Tests/RunCMake/include_directories/TargetInterfaceIncludes.cmake
new file mode 100644
index 0000000..92f31fc
--- /dev/null
+++ b/Tests/RunCMake/include_directories/TargetInterfaceIncludes.cmake
@@ -0,0 +1,4 @@
+
+add_library(empty empty.cpp)
+install(TARGETS empty DESTINATION lib INCLUDES DESTINATION include)
+# install(EXPORT )