summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2014-12-15 14:52:48 (GMT)
committerBrad King <brad.king@kitware.com>2014-12-15 16:45:49 (GMT)
commitdd089e08b578f20b7dc7d2ce658e3df05e346e35 (patch)
tree2bae57f141cbff3933ba867a2be0ec98430c27e8
parent1b3ab3318dcdabe074da3c95b54f9483d47f95be (diff)
downloadCMake-dd089e08b578f20b7dc7d2ce658e3df05e346e35.zip
CMake-dd089e08b578f20b7dc7d2ce658e3df05e346e35.tar.gz
CMake-dd089e08b578f20b7dc7d2ce658e3df05e346e35.tar.bz2
install: Allow absolute EXPORT destination with relative targets (#15258)
When install(EXPORT) is given an absolute destination we cannot compute the install prefix relative to the installed export file location. Previously we disallowed installation of targets in such exports with a relative destination, but did not enforce this for target property values besides the location of the main target file. This could lead to broken installations when the EXPORT is installed to an absolute path but usage requirements are specified relative to the install prefix. Since an EXPORT installed to an absolute destination cannot be relocated we can just hard-code the value of CMAKE_INSTALL_PREFIX as the base for relative paths. This will allow absolute install(EXPORT) destinations to work with relative destinations for targets and usage requirements. Extend the ExportImport test with a case covering this behavior.
-rw-r--r--Help/release/dev/install-EXPORT-absolute-prefix.rst9
-rw-r--r--Source/cmExportInstallFileGenerator.cxx57
-rw-r--r--Source/cmExportInstallFileGenerator.h4
-rw-r--r--Tests/ExportImport/Export/CMakeLists.txt15
-rw-r--r--Tests/ExportImport/Export/include/abs/1a/testLibAbs1a.h1
-rw-r--r--Tests/ExportImport/Export/include/abs/1b/testLibAbs1b.h1
-rw-r--r--Tests/ExportImport/Export/include/abs/testLibAbs1.h1
-rw-r--r--Tests/ExportImport/Export/testLibAbs1.c1
-rw-r--r--Tests/ExportImport/Import/A/CMakeLists.txt10
-rw-r--r--Tests/ExportImport/Import/A/imp_testExeAbs1.c15
10 files changed, 73 insertions, 41 deletions
diff --git a/Help/release/dev/install-EXPORT-absolute-prefix.rst b/Help/release/dev/install-EXPORT-absolute-prefix.rst
new file mode 100644
index 0000000..1b2a01c
--- /dev/null
+++ b/Help/release/dev/install-EXPORT-absolute-prefix.rst
@@ -0,0 +1,9 @@
+install-EXPORT-absolute-prefix
+------------------------------
+
+* The :command:`install(EXPORT)` command now works with an absolute
+ ``DESTINATION`` even if targets in the export set are installed
+ with a destination or usage requirements specified relative to the
+ install prefix. The value of the :variable:`CMAKE_INSTALL_PREFIX`
+ variable is hard-coded into the installed export file as the base
+ for relative references.
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index 23180f1..3f5866a 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -69,13 +69,24 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
this->GenerateExpectedTargetsCode(os, expectedTargets);
}
- // Add code to compute the installation prefix relative to the
- // import file location.
+ // Set an _IMPORT_PREFIX variable for import location properties
+ // to reference if they are relative to the install prefix.
+ std::string installPrefix =
+ this->IEGen->GetMakefile()->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
const char* installDest = this->IEGen->GetDestination();
- if(!cmSystemTools::FileIsFullPath(installDest))
+ if(cmSystemTools::FileIsFullPath(installDest))
{
- std::string installPrefix =
- this->IEGen->GetMakefile()->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
+ // The export file is being installed to an absolute path so the
+ // package is not relocatable. Use the configured install prefix.
+ os <<
+ "# The installation prefix configured by this project.\n"
+ "set(_IMPORT_PREFIX \"" << installPrefix << "\")\n"
+ "\n";
+ }
+ else
+ {
+ // Add code to compute the installation prefix relative to the
+ // import file location.
std::string absDest = installPrefix + "/" + installDest;
std::string absDestS = absDest + "/";
os << "# Compute the installation prefix relative to this file.\n"
@@ -106,9 +117,6 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
dest = cmSystemTools::GetFilenamePath(dest);
}
os << "\n";
-
- // Import location properties may reference this variable.
- this->ImportPrefix = "${_IMPORT_PREFIX}/";
}
std::vector<std::string> missingTargets;
@@ -209,12 +217,9 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
<< "\n";
// Cleanup the import prefix variable.
- if(!this->ImportPrefix.empty())
- {
- os << "# Cleanup temporary variables.\n"
- << "set(_IMPORT_PREFIX)\n"
- << "\n";
- }
+ os << "# Cleanup temporary variables.\n"
+ << "set(_IMPORT_PREFIX)\n"
+ << "\n";
this->GenerateImportedFileCheckLoop(os);
bool result = true;
@@ -394,11 +399,7 @@ cmExportInstallFileGenerator
if(!cmSystemTools::FileIsFullPath(dest.c_str()))
{
// The target is installed relative to the installation prefix.
- if(this->ImportPrefix.empty())
- {
- this->ComplainAboutImportPrefix(itgen);
- }
- value = this->ImportPrefix;
+ value = "${_IMPORT_PREFIX}/";
}
value += dest;
value += "/";
@@ -508,24 +509,6 @@ cmExportInstallFileGenerator
return namespaces;
}
-
-//----------------------------------------------------------------------------
-void
-cmExportInstallFileGenerator
-::ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen)
-{
- const char* installDest = this->IEGen->GetDestination();
- cmOStringStream e;
- e << "install(EXPORT \""
- << this->IEGen->GetExportSet()->GetName()
- << "\") given absolute "
- << "DESTINATION \"" << installDest << "\" but the export "
- << "references an installation of target \""
- << itgen->GetTarget()->GetName() << "\" which has relative "
- << "DESTINATION \"" << itgen->GetDestination() << "\".";
- cmSystemTools::Error(e.str().c_str());
-}
-
//----------------------------------------------------------------------------
void
cmExportInstallFileGenerator
diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h
index b851ad5..6f86ac9 100644
--- a/Source/cmExportInstallFileGenerator.h
+++ b/Source/cmExportInstallFileGenerator.h
@@ -83,14 +83,10 @@ protected:
std::set<std::string>& importedLocations
);
- void ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen);
-
std::string InstallNameDir(cmTarget* target, const std::string& config);
cmInstallExportGenerator* IEGen;
- std::string ImportPrefix;
-
// The import file generated for each configuration.
std::map<std::string, std::string> ConfigImportFiles;
};
diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt
index febdfe6..e130eca 100644
--- a/Tests/ExportImport/Export/CMakeLists.txt
+++ b/Tests/ExportImport/Export/CMakeLists.txt
@@ -508,3 +508,18 @@ export(TARGETS testExe2 testLib4 testLib5 testLib6 testExe3 testExe2lib
)
add_subdirectory(Interface)
+
+#-----------------------------------------------------------------------------
+# Install export with absolute destination but relative pieces.
+add_library(testLibAbs1 STATIC testLibAbs1.c)
+target_include_directories(testLibAbs1 INTERFACE
+ "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include/abs/1a;include/abs/1b>"
+ )
+install(
+ TARGETS testLibAbs1
+ EXPORT expAbs
+ ARCHIVE DESTINATION lib
+ INCLUDES DESTINATION include/abs
+ )
+install(DIRECTORY include/abs DESTINATION include)
+install(EXPORT expAbs NAMESPACE expAbs_ DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/expAbs)
diff --git a/Tests/ExportImport/Export/include/abs/1a/testLibAbs1a.h b/Tests/ExportImport/Export/include/abs/1a/testLibAbs1a.h
new file mode 100644
index 0000000..4421227
--- /dev/null
+++ b/Tests/ExportImport/Export/include/abs/1a/testLibAbs1a.h
@@ -0,0 +1 @@
+#define testLibAbs1a
diff --git a/Tests/ExportImport/Export/include/abs/1b/testLibAbs1b.h b/Tests/ExportImport/Export/include/abs/1b/testLibAbs1b.h
new file mode 100644
index 0000000..00a2a29
--- /dev/null
+++ b/Tests/ExportImport/Export/include/abs/1b/testLibAbs1b.h
@@ -0,0 +1 @@
+#define testLibAbs1b
diff --git a/Tests/ExportImport/Export/include/abs/testLibAbs1.h b/Tests/ExportImport/Export/include/abs/testLibAbs1.h
new file mode 100644
index 0000000..19d80a5
--- /dev/null
+++ b/Tests/ExportImport/Export/include/abs/testLibAbs1.h
@@ -0,0 +1 @@
+extern int testLibAbs1(void);
diff --git a/Tests/ExportImport/Export/testLibAbs1.c b/Tests/ExportImport/Export/testLibAbs1.c
new file mode 100644
index 0000000..34aec75
--- /dev/null
+++ b/Tests/ExportImport/Export/testLibAbs1.c
@@ -0,0 +1 @@
+int testLibAbs1(void) { return 0; }
diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt
index eb0bbf8..9450c82 100644
--- a/Tests/ExportImport/Import/A/CMakeLists.txt
+++ b/Tests/ExportImport/Import/A/CMakeLists.txt
@@ -96,6 +96,16 @@ foreach(c DEBUG RELWITHDEBINFO)
endforeach()
#-----------------------------------------------------------------------------
+include(${CMAKE_INSTALL_PREFIX}/lib/expAbs/expAbs.cmake)
+
+add_executable(imp_testExeAbs1
+ imp_testExeAbs1.c
+ )
+target_link_libraries(imp_testExeAbs1
+ expAbs_testLibAbs1
+ )
+
+#-----------------------------------------------------------------------------
# Create a custom target to generate a header for the libraries below.
# Drive the header generation through an indirect chain of imported
# target dependencies.
diff --git a/Tests/ExportImport/Import/A/imp_testExeAbs1.c b/Tests/ExportImport/Import/A/imp_testExeAbs1.c
new file mode 100644
index 0000000..069c3f0
--- /dev/null
+++ b/Tests/ExportImport/Import/A/imp_testExeAbs1.c
@@ -0,0 +1,15 @@
+#include "testLibAbs1.h"
+#include "testLibAbs1a.h"
+#include "testLibAbs1b.h"
+#ifndef testLibAbs1a
+# error "testLibAbs1a not defined"
+#endif
+#ifndef testLibAbs1b
+# error "testLibAbs1b not defined"
+#endif
+int main()
+{
+ return 0
+ + testLibAbs1()
+ ;
+}