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:
parent
ff6de6d325
commit
650e61f833
|
@ -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())
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 = ";";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 "
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
///@}
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -9,3 +9,4 @@ run_cmake(RelativePathInInterface)
|
|||
run_cmake(ImportedTarget)
|
||||
run_cmake(RelativePathInGenex)
|
||||
run_cmake(CMP0021)
|
||||
run_cmake(TargetInterfaceIncludes)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -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\)
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
add_library(empty empty.cpp)
|
||||
install(TARGETS empty DESTINATION lib INCLUDES DESTINATION include)
|
||||
# install(EXPORT )
|
Loading…
Reference in New Issue