Merge topic 'install-interface-includes'

650e61f Add a convenient way to add the includes install dir to the INTERFACE.
This commit is contained in:
Brad King 2013-07-26 09:01:06 -04:00 committed by CMake Topic Stage
commit c82b1cbe83
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( void cmExportFileGenerator::PopulateIncludeDirectoriesInterface(
cmTarget *target, cmTargetExport *tei,
cmGeneratorExpression::PreprocessContext preprocessRule, cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap &properties, ImportPropertyMap &properties,
std::vector<std::string> &missingTargets) std::vector<std::string> &missingTargets)
{ {
cmTarget *target = tei->Target;
assert(preprocessRule == cmGeneratorExpression::InstallInterface); assert(preprocessRule == cmGeneratorExpression::InstallInterface);
const char *propName = "INTERFACE_INCLUDE_DIRECTORIES"; const char *propName = "INTERFACE_INCLUDE_DIRECTORIES";
const char *input = target->GetProperty(propName); const char *input = target->GetProperty(propName);
if (!input) if (!input && tei->InterfaceIncludeDirectories.empty())
{ {
return; return;
} }
if (!*input) if (!*input && tei->InterfaceIncludeDirectories.empty())
{ {
// Set to empty // Set to empty
properties[propName] = ""; properties[propName] = "";
return; 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); preprocessRule);
if (!prepro.empty()) if (!prepro.empty())
{ {

View File

@ -15,6 +15,8 @@
#include "cmCommand.h" #include "cmCommand.h"
#include "cmGeneratorExpression.h" #include "cmGeneratorExpression.h"
class cmTargetExport;
/** \class cmExportFileGenerator /** \class cmExportFileGenerator
* \brief Generate a file exporting targets from a build or install tree. * \brief Generate a file exporting targets from a build or install tree.
* *
@ -114,7 +116,7 @@ protected:
void GenerateInterfaceProperties(cmTarget *target, std::ostream& os, void GenerateInterfaceProperties(cmTarget *target, std::ostream& os,
const ImportPropertyMap &properties); const ImportPropertyMap &properties);
void PopulateIncludeDirectoriesInterface( void PopulateIncludeDirectoriesInterface(
cmTarget *target, cmTargetExport *target,
cmGeneratorExpression::PreprocessContext preprocessRule, cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap &properties, ImportPropertyMap &properties,
std::vector<std::string> &missingTargets); std::vector<std::string> &missingTargets);

View File

@ -39,7 +39,7 @@ std::string cmExportInstallFileGenerator::GetConfigImportFileGlob()
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
{ {
std::vector<cmTarget*> allTargets; std::vector<cmTargetExport*> allTargets;
{ {
std::string expectedTargets; std::string expectedTargets;
std::string sep; std::string sep;
@ -49,10 +49,10 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
{ {
expectedTargets += sep + this->Namespace + (*tei)->Target->GetExportName(); expectedTargets += sep + this->Namespace + (*tei)->Target->GetExportName();
sep = " "; sep = " ";
cmTargetExport const* te = *tei; cmTargetExport * te = *tei;
if(this->ExportedTargets.insert(te->Target).second) if(this->ExportedTargets.insert(te->Target).second)
{ {
allTargets.push_back(te->Target); allTargets.push_back(te);
} }
else else
{ {
@ -115,16 +115,16 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
bool require2_8_12 = false; bool require2_8_12 = false;
// Create all the imported targets. // Create all the imported targets.
for(std::vector<cmTarget*>::const_iterator for(std::vector<cmTargetExport*>::const_iterator
tei = allTargets.begin(); tei = allTargets.begin();
tei != allTargets.end(); ++tei) tei != allTargets.end(); ++tei)
{ {
cmTarget* te = *tei; cmTarget* te = (*tei)->Target;
this->GenerateImportTargetCode(os, te); this->GenerateImportTargetCode(os, te);
ImportPropertyMap properties; ImportPropertyMap properties;
this->PopulateIncludeDirectoriesInterface(te, this->PopulateIncludeDirectoriesInterface(*tei,
cmGeneratorExpression::InstallInterface, cmGeneratorExpression::InstallInterface,
properties, missingTargets); properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", 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 runtimeArgVector (&argHelper,"RUNTIME",&group);
cmCAStringVector frameworkArgVector (&argHelper,"FRAMEWORK",&group); cmCAStringVector frameworkArgVector (&argHelper,"FRAMEWORK",&group);
cmCAStringVector bundleArgVector (&argHelper,"BUNDLE",&group); cmCAStringVector bundleArgVector (&argHelper,"BUNDLE",&group);
cmCAStringVector includesArgVector (&argHelper,"INCLUDES",&group);
cmCAStringVector privateHeaderArgVector(&argHelper,"PRIVATE_HEADER",&group); cmCAStringVector privateHeaderArgVector(&argHelper,"PRIVATE_HEADER",&group);
cmCAStringVector publicHeaderArgVector (&argHelper,"PUBLIC_HEADER",&group); cmCAStringVector publicHeaderArgVector (&argHelper,"PUBLIC_HEADER",&group);
cmCAStringVector resourceArgVector (&argHelper,"RESOURCE",&group); cmCAStringVector resourceArgVector (&argHelper,"RESOURCE",&group);
@ -247,6 +248,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
cmInstallCommandArguments privateHeaderArgs(this->DefaultComponentName); cmInstallCommandArguments privateHeaderArgs(this->DefaultComponentName);
cmInstallCommandArguments publicHeaderArgs(this->DefaultComponentName); cmInstallCommandArguments publicHeaderArgs(this->DefaultComponentName);
cmInstallCommandArguments resourceArgs(this->DefaultComponentName); cmInstallCommandArguments resourceArgs(this->DefaultComponentName);
cmInstallCommandIncludesArgument includesArgs;
// now parse the args for specific parts of the target (e.g. LIBRARY, // now parse the args for specific parts of the target (e.g. LIBRARY,
// RUNTIME, ARCHIVE etc. // RUNTIME, ARCHIVE etc.
@ -258,6 +260,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
privateHeaderArgs.Parse(&privateHeaderArgVector.GetVector(), &unknownArgs); privateHeaderArgs.Parse(&privateHeaderArgVector.GetVector(), &unknownArgs);
publicHeaderArgs.Parse (&publicHeaderArgVector.GetVector(), &unknownArgs); publicHeaderArgs.Parse (&publicHeaderArgVector.GetVector(), &unknownArgs);
resourceArgs.Parse (&resourceArgVector.GetVector(), &unknownArgs); resourceArgs.Parse (&resourceArgVector.GetVector(), &unknownArgs);
includesArgs.Parse (&includesArgVector.GetVector(), &unknownArgs);
if(!unknownArgs.empty()) if(!unknownArgs.empty())
{ {
@ -292,6 +295,13 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
return false; 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 // Enforce argument rules too complex to specify for the
// general-purpose parser. // general-purpose parser.
if(archiveArgs.GetNamelinkOnly() || if(archiveArgs.GetNamelinkOnly() ||
@ -747,6 +757,20 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
te->RuntimeGenerator = runtimeGenerator; te->RuntimeGenerator = runtimeGenerator;
this->Makefile->GetLocalGenerator()->GetGlobalGenerator() this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
->GetExportSets()[exports.GetString()]->AddTargetExport(te); ->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" " [[ARCHIVE|LIBRARY|RUNTIME|FRAMEWORK|BUNDLE|\n"
" PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE]\n" " PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE]\n"
" [DESTINATION <dir>]\n" " [DESTINATION <dir>]\n"
" [INCLUDES DESTINATION [<dir> ...]]\n"
" [PERMISSIONS permissions...]\n" " [PERMISSIONS permissions...]\n"
" [CONFIGURATIONS [Debug|Release|...]]\n" " [CONFIGURATIONS [Debug|Release|...]]\n"
" [COMPONENT <component>]\n" " [COMPONENT <component>]\n"
@ -130,6 +131,10 @@ public:
"all target types. If only one is given then only targets of that " "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 " "type will be installed (which can be used to install just a DLL or "
"just an import library)." "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" "\n"
"The PRIVATE_HEADER, PUBLIC_HEADER, and RESOURCE arguments cause " "The PRIVATE_HEADER, PUBLIC_HEADER, and RESOURCE arguments cause "
"subsequent properties to be applied to installing a FRAMEWORK " "subsequent properties to be applied to installing a FRAMEWORK "

View File

@ -203,3 +203,37 @@ bool cmInstallCommandArguments::CheckPermissions(
// This is not a valid permission. // This is not a valid permission.
return false; 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(); 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 #endif

View File

@ -12,6 +12,8 @@
#ifndef cmTargetExport_h #ifndef cmTargetExport_h
#define cmTargetExport_h #define cmTargetExport_h
#include "cmStandardIncludes.h"
class cmTarget; class cmTarget;
class cmInstallTargetGenerator; class cmInstallTargetGenerator;
class cmInstallFilesGenerator; class cmInstallFilesGenerator;
@ -33,6 +35,7 @@ public:
cmInstallTargetGenerator* FrameworkGenerator; cmInstallTargetGenerator* FrameworkGenerator;
cmInstallTargetGenerator* BundleGenerator; cmInstallTargetGenerator* BundleGenerator;
cmInstallFilesGenerator* HeaderGenerator; cmInstallFilesGenerator* HeaderGenerator;
std::string InterfaceIncludeDirectories;
///@} ///@}
}; };

View File

@ -271,9 +271,26 @@ install(TARGETS testLibRequired
testLibIncludeRequired5 testLibIncludeRequired5
testLibIncludeRequired6 testLibIncludeRequired6
testSharedLibRequired 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) 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(TARGETS testLibDepends testSharedLibDepends EXPORT DependsExp DESTINATION lib )
install(EXPORT DependsExp FILE testLibDependsTargets.cmake DESTINATION lib/cmake/testLibDepends) install(EXPORT DependsExp FILE testLibDependsTargets.cmake DESTINATION lib/cmake/testLibDepends)

View File

@ -3,6 +3,9 @@
#include "testLibIncludeRequired2.h" #include "testLibIncludeRequired2.h"
#include "testLibIncludeRequired6.h" #include "testLibIncludeRequired6.h"
#include "installIncludesTest.h"
#include "installIncludesTest2.h"
#ifndef testLibRequired_IFACE_DEFINE #ifndef testLibRequired_IFACE_DEFINE
#error Expected testLibRequired_IFACE_DEFINE #error Expected testLibRequired_IFACE_DEFINE
#endif #endif

View File

@ -9,3 +9,4 @@ run_cmake(RelativePathInInterface)
run_cmake(ImportedTarget) run_cmake(ImportedTarget)
run_cmake(RelativePathInGenex) run_cmake(RelativePathInGenex)
run_cmake(CMP0021) 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 )