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.
This commit is contained in:
Stephen Kelly 2013-01-05 12:13:49 +01:00
parent ff6de6d325
commit 650e61f833
14 changed files with 127 additions and 12 deletions

View File

@ -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())
{

View File

@ -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);

View File

@ -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",

View File

@ -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 = ";";
}
}
}
}

View File

@ -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 "

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;
///@}
};

View File

@ -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)

View File

@ -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

View File

@ -9,3 +9,4 @@ run_cmake(RelativePathInInterface)
run_cmake(ImportedTarget)
run_cmake(RelativePathInGenex)
run_cmake(CMP0021)
run_cmake(TargetInterfaceIncludes)

View File

@ -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\)

View File

@ -0,0 +1,4 @@
add_library(empty empty.cpp)
install(TARGETS empty DESTINATION lib INCLUDES DESTINATION include)
# install(EXPORT )