install(EXPORT): Ensure clean INTERFACE_INCLUDE_DIRECTORIES

Check that source and binary directories are not part of the
INTERFACE_INCLUDE_DIRECTORIES for installed IMPORTED targets.

This is limited to directories which do not contain generator
expressions to evaluate. Such paths can only be checked at time
of use of the imported target, which will be done in a follow up
patch.
This commit is contained in:
Stephen Kelly 2013-03-24 21:18:17 +01:00 committed by Brad King
parent ddbe2e1d7d
commit af81a3c31b
15 changed files with 189 additions and 4 deletions

View File

@ -24,6 +24,7 @@
#include "cmComputeLinkInformation.h"
#include <cmsys/auto_ptr.hxx>
#include <assert.h>
//----------------------------------------------------------------------------
cmExportFileGenerator::cmExportFileGenerator()
@ -167,6 +168,116 @@ void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
}
}
//----------------------------------------------------------------------------
static bool isSubDirectory(const char* a, const char* b)
{
return (cmSystemTools::ComparePath(a, b) ||
cmSystemTools::IsSubDirectory(a, b));
}
//----------------------------------------------------------------------------
static bool checkInterfaceDirs(const std::string &prepro,
cmTarget *target)
{
const char* installDir =
target->GetMakefile()->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
const char* topSourceDir = target->GetMakefile()->GetHomeDirectory();
const char* topBinaryDir = target->GetMakefile()->GetHomeOutputDirectory();
std::vector<std::string> parts;
cmGeneratorExpression::Split(prepro, parts);
const bool inSourceBuild = strcmp(topSourceDir, topBinaryDir) == 0;
for(std::vector<std::string>::iterator li = parts.begin();
li != parts.end(); ++li)
{
if (cmGeneratorExpression::Find(*li) != std::string::npos)
{
continue;
}
if (strncmp(li->c_str(), "${_IMPORT_PREFIX}", 17) == 0)
{
continue;
}
if (!cmSystemTools::FileIsFullPath(li->c_str()))
{
cmOStringStream e;
e << "Target \"" << target->GetName() << "\" "
"INTERFACE_INCLUDE_DIRECTORIES property contains relative path:\n"
" \"" << *li << "\"";
target->GetMakefile()->IssueMessage(cmake::FATAL_ERROR,
e.str().c_str());
return false;
}
if (isSubDirectory(li->c_str(), installDir))
{
continue;
}
if (isSubDirectory(li->c_str(), topBinaryDir))
{
cmOStringStream e;
e << "Target \"" << target->GetName() << "\" "
"INTERFACE_INCLUDE_DIRECTORIES property contains path:\n"
" \"" << *li << "\"\nwhich is prefixed in the build directory.";
target->GetMakefile()->IssueMessage(cmake::FATAL_ERROR,
e.str().c_str());
return false;
}
if (!inSourceBuild)
{
if (isSubDirectory(li->c_str(), topSourceDir))
{
cmOStringStream e;
e << "Target \"" << target->GetName() << "\" "
"INTERFACE_INCLUDE_DIRECTORIES property contains path:\n"
" \"" << *li << "\"\nwhich is prefixed in the source directory.";
target->GetMakefile()->IssueMessage(cmake::FATAL_ERROR,
e.str().c_str());
return false;
}
}
}
return true;
}
//----------------------------------------------------------------------------
void cmExportFileGenerator::PopulateIncludeDirectoriesInterface(
cmTarget *target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap &properties,
std::vector<std::string> &missingTargets)
{
assert(preprocessRule == cmGeneratorExpression::InstallInterface);
const char *propName = "INTERFACE_INCLUDE_DIRECTORIES";
const char *input = target->GetProperty(propName);
if (!input)
{
return;
}
if (!*input)
{
// Set to empty
properties[propName] = "";
return;
}
std::string prepro = cmGeneratorExpression::Preprocess(input,
preprocessRule);
if (!prepro.empty())
{
this->ResolveTargetsInGeneratorExpressions(prepro, target,
missingTargets);
if (!checkInterfaceDirs(prepro, target))
{
return;
}
properties[propName] = prepro;
}
}
//----------------------------------------------------------------------------
void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
cmTarget *target,

View File

@ -107,6 +107,11 @@ protected:
ImportPropertyMap &properties);
void GenerateInterfaceProperties(cmTarget *target, std::ostream& os,
const ImportPropertyMap &properties);
void PopulateIncludeDirectoriesInterface(
cmTarget *target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap &properties,
std::vector<std::string> &missingTargets);
void SetImportLinkInterface(const char* config, std::string const& suffix,
cmGeneratorExpression::PreprocessContext preprocessRule,

View File

@ -120,8 +120,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
ImportPropertyMap properties;
this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES",
te,
this->PopulateIncludeDirectoriesInterface(te,
cmGeneratorExpression::InstallInterface,
properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS",

View File

@ -174,9 +174,14 @@ set_property(TARGET testSharedLibRequired
set_property(TARGET testSharedLibRequired APPEND PROPERTY
INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}"
)
install(FILES
"${CMAKE_CURRENT_SOURCE_DIR}/testSharedLibRequired.h"
"${CMAKE_CURRENT_BINARY_DIR}/testsharedlibrequired_export.h"
DESTINATION include/testSharedLibRequired
)
set_property(TARGET testSharedLibRequired APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}"
INTERFACE_INCLUDE_DIRECTORIES "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include/testSharedLibRequired>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}>"
)
set_property(TARGET testSharedLibRequired
APPEND PROPERTY
@ -205,6 +210,15 @@ set_property(TARGET testSharedLibDepends APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES
$<TARGET_PROPERTY:testSharedLibRequired,INTERFACE_INCLUDE_DIRECTORIES>
)
install(FILES
"${CMAKE_CURRENT_SOURCE_DIR}/testSharedLibDepends.h"
"${CMAKE_CURRENT_BINARY_DIR}/testsharedlibdepends_export.h"
DESTINATION include/testSharedLibDepends
)
set_property(TARGET testSharedLibDepends APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include/testSharedLibDepends>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}>"
)
set_property(TARGET testSharedLibDepends APPEND PROPERTY
LINK_INTERFACE_LIBRARIES
$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:$<TARGET_NAME:testSharedLibRequired>>

View File

@ -0,0 +1,6 @@
CMake Error in CMakeLists.txt:
Target "testTarget" INTERFACE_INCLUDE_DIRECTORIES property contains path:
".*RunCMake/include_directories/BinaryDirectoryInInterface-build/foo"
which is prefixed in the build directory.

View File

@ -0,0 +1,11 @@
project(BinaryDirectoryInInterface)
add_library(testTarget "${CMAKE_CURRENT_SOURCE_DIR}/empty.cpp")
target_include_directories(testTarget INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/foo")
install(TARGETS testTarget EXPORT testTargets
DESTINATION lib
)
install(EXPORT testTargets DESTINATION lib/cmake)

View File

@ -0,0 +1,5 @@
CMake Error in CMakeLists.txt:
Target "testTarget" INTERFACE_INCLUDE_DIRECTORIES property contains
relative path:
"foo"

View File

@ -0,0 +1,11 @@
project(RelativePathInInterface)
add_library(testTarget "${CMAKE_CURRENT_SOURCE_DIR}/empty.cpp")
set_property(TARGET testTarget PROPERTY INTERFACE_INCLUDE_DIRECTORIES "foo")
install(TARGETS testTarget EXPORT testTargets
DESTINATION lib
)
install(EXPORT testTargets DESTINATION lib/cmake)

View File

@ -3,3 +3,6 @@ include(RunCMake)
run_cmake(NotFoundContent)
run_cmake(DebugIncludes)
run_cmake(TID-bad-target)
run_cmake(SourceDirectoryInInterface)
run_cmake(BinaryDirectoryInInterface)
run_cmake(RelativePathInInterface)

View File

@ -0,0 +1,6 @@
CMake Error in CMakeLists.txt:
Target "testTarget" INTERFACE_INCLUDE_DIRECTORIES property contains path:
".*RunCMake/include_directories/foo"
which is prefixed in the source directory.

View File

@ -0,0 +1,11 @@
project(SourceDirectoryInInterface)
add_library(testTarget "${CMAKE_CURRENT_SOURCE_DIR}/empty.cpp")
target_include_directories(testTarget INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/foo")
install(TARGETS testTarget EXPORT testTargets
DESTINATION lib
)
install(EXPORT testTargets DESTINATION lib/cmake)