ENH: Add InstallNameFixupPath to support installing built frameworks on the Mac. Change Application to Applications in the BundleTest. Also correct small typo (tcl->Tcl) noted in bug 4572.

This commit is contained in:
David Cole 2007-08-24 13:30:41 -04:00
parent 6d508a3094
commit 9a4e7ea742
8 changed files with 106 additions and 44 deletions

View File

@ -181,6 +181,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
targetList.Follows(0); targetList.Follows(0);
genericArgs.ArgumentGroup.Follows(&targetList); genericArgs.ArgumentGroup.Follows(&targetList);
genericArgs.Parse(&genericArgVector.GetVector(), &unknownArgs); genericArgs.Parse(&genericArgVector.GetVector(), &unknownArgs);
bool success = genericArgs.Finalize();
cmInstallCommandArguments archiveArgs; cmInstallCommandArguments archiveArgs;
cmInstallCommandArguments libraryArgs; cmInstallCommandArguments libraryArgs;
@ -219,7 +220,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
publicHeaderArgs.SetGenericArguments(&genericArgs); publicHeaderArgs.SetGenericArguments(&genericArgs);
privateHeaderArgs.SetGenericArguments(&genericArgs); privateHeaderArgs.SetGenericArguments(&genericArgs);
bool success = archiveArgs.Finalize(); success = success && archiveArgs.Finalize();
success = success && libraryArgs.Finalize(); success = success && libraryArgs.Finalize();
success = success && runtimeArgs.Finalize(); success = success && runtimeArgs.Finalize();
success = success && frameworkArgs.Finalize(); success = success && frameworkArgs.Finalize();

View File

@ -154,10 +154,9 @@ cmInstallTargetGenerator
Indent const& indent) Indent const& indent)
{ {
// Compute the full path to the main installed file for this target. // Compute the full path to the main installed file for this target.
std::string toFullPath = "$ENV{DESTDIR}"; std::string toInstallPath = this->Destination;
toFullPath += this->Destination; toInstallPath += "/";
toFullPath += "/"; toInstallPath += this->GetInstallFilename(this->Target, config,
toFullPath += this->GetInstallFilename(this->Target, config,
this->ImportLibrary, false); this->ImportLibrary, false);
// Compute the list of files to install for this target. // Compute the list of files to install for this target.
@ -198,8 +197,8 @@ cmInstallTargetGenerator
type = cmTarget::INSTALL_DIRECTORY; type = cmTarget::INSTALL_DIRECTORY;
// Need to apply install_name_tool and stripping to binary // Need to apply install_name_tool and stripping to binary
// inside bundle. // inside bundle.
toFullPath += ".app/Contents/MacOS/"; toInstallPath += ".app/Contents/MacOS/";
toFullPath += this->GetInstallFilename(this->Target, config, toInstallPath += this->GetInstallFilename(this->Target, config,
this->ImportLibrary, false); this->ImportLibrary, false);
literal_args += " USE_SOURCE_PERMISSIONS"; literal_args += " USE_SOURCE_PERMISSIONS";
} }
@ -234,6 +233,25 @@ cmInstallTargetGenerator
// An import library looks like a static library. // An import library looks like a static library.
type = cmTarget::STATIC_LIBRARY; type = cmTarget::STATIC_LIBRARY;
} }
else if(this->Target->GetMakefile()->IsOn("APPLE") &&
this->Target->GetPropertyAsBool("FRAMEWORK"))
{
// Compute the build tree location of the framework directory
std::string from1 = fromDirConfig;
// Remove trailing slashes
cmSystemTools::ConvertToUnixSlashes(from1);
files.push_back(from1);
type = cmTarget::INSTALL_DIRECTORY;
// Need to apply install_name_tool and stripping to binary
// inside framework.
toInstallPath += ".framework/";
toInstallPath += this->GetInstallFilename(this->Target, config,
this->ImportLibrary, false);
literal_args += " USE_SOURCE_PERMISSIONS";
}
else else
{ {
std::string from1 = fromDirConfig; std::string from1 = fromDirConfig;
@ -266,11 +284,20 @@ cmInstallTargetGenerator
no_rename, literal_args.c_str(), no_rename, literal_args.c_str(),
indent); indent);
os << indent << "IF(EXISTS \"" << toFullPath << "\")\n"; std::string toDestDirPath = "$ENV{DESTDIR}";
this->AddInstallNamePatchRule(os, indent.Next(), config, toFullPath); if(toInstallPath[0] != '/')
this->AddRanlibRule(os, indent.Next(), type, toFullPath); {
this->AddStripRule(os, indent.Next(), type, toFullPath); toDestDirPath += "/";
os << indent << "ENDIF(EXISTS \"" << toFullPath << "\")\n"; }
toDestDirPath += toInstallPath;
this->Target->SetInstallNameFixupPath(toInstallPath.c_str());
os << indent << "IF(EXISTS \"" << toDestDirPath << "\")\n";
this->AddInstallNamePatchRule(os, indent.Next(), config, toDestDirPath);
this->AddRanlibRule(os, indent.Next(), type, toDestDirPath);
this->AddStripRule(os, indent.Next(), type, toDestDirPath);
os << indent << "ENDIF(EXISTS \"" << toDestDirPath << "\")\n";
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -343,7 +370,7 @@ std::string cmInstallTargetGenerator::GetInstallFilename(cmTarget* target,
void void
cmInstallTargetGenerator cmInstallTargetGenerator
::AddInstallNamePatchRule(std::ostream& os, Indent const& indent, ::AddInstallNamePatchRule(std::ostream& os, Indent const& indent,
const char* config, std::string const& toFullPath) const char* config, std::string const& toDestDirPath)
{ {
if(this->ImportLibrary || if(this->ImportLibrary ||
!(this->Target->GetType() == cmTarget::SHARED_LIBRARY || !(this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
@ -393,16 +420,24 @@ cmInstallTargetGenerator
std::string for_build = tgt->GetInstallNameDirForBuildTree(config); std::string for_build = tgt->GetInstallNameDirForBuildTree(config);
std::string for_install = std::string for_install =
tgt->GetInstallNameDirForInstallTree(config); tgt->GetInstallNameDirForInstallTree(config);
if(for_build != for_install)
{
std::string fname = std::string fname =
this->GetInstallFilename(tgt, config, false, true); this->GetInstallFilename(tgt, config, false, true);
// Map from the build-tree install_name. // Map from the build-tree install_name.
for_build += fname; for_build += fname;
// Map to the install-tree install_name. // Map to the install-tree install_name.
if (!for_install.empty())
{
for_install += fname; for_install += fname;
}
else
{
for_install = tgt->GetInstallNameFixupPath();
}
if(for_build != for_install)
{
// Store the mapping entry. // Store the mapping entry.
install_name_remap[for_build] = for_install; install_name_remap[for_build] = for_install;
} }
@ -419,12 +454,22 @@ cmInstallTargetGenerator
this->Target->GetInstallNameDirForBuildTree(config); this->Target->GetInstallNameDirForBuildTree(config);
std::string for_install = std::string for_install =
this->Target->GetInstallNameDirForInstallTree(config); this->Target->GetInstallNameDirForInstallTree(config);
std::string fname =
this->GetInstallFilename(this->Target, config, this->ImportLibrary,
true);
for_build += fname;
if (!for_install.empty())
{
for_install += fname;
}
else
{
for_install = this->Target->GetInstallNameFixupPath();
}
if(for_build != for_install) if(for_build != for_install)
{ {
// Prepare to refer to the install-tree install_name. // Prepare to refer to the install-tree install_name.
new_id = for_install; new_id = for_install;
new_id += this->GetInstallFilename(this->Target, config,
this->ImportLibrary, true);
} }
} }
@ -445,7 +490,7 @@ cmInstallTargetGenerator
os << "\n" << indent << " -change \"" os << "\n" << indent << " -change \""
<< i->first << "\" \"" << i->second << "\""; << i->first << "\" \"" << i->second << "\"";
} }
os << "\n" << indent << " \"" << toFullPath << "\")\n"; os << "\n" << indent << " \"" << toDestDirPath << "\")\n";
} }
} }
@ -454,7 +499,7 @@ void
cmInstallTargetGenerator::AddStripRule(std::ostream& os, cmInstallTargetGenerator::AddStripRule(std::ostream& os,
Indent const& indent, Indent const& indent,
cmTarget::TargetType type, cmTarget::TargetType type,
const std::string& toFullPath) const std::string& toDestDirPath)
{ {
// don't strip static libraries, because it removes the only symbol table // don't strip static libraries, because it removes the only symbol table
@ -479,7 +524,7 @@ cmInstallTargetGenerator::AddStripRule(std::ostream& os,
os << indent << "IF(CMAKE_INSTALL_DO_STRIP)\n"; os << indent << "IF(CMAKE_INSTALL_DO_STRIP)\n";
os << indent << " EXECUTE_PROCESS(COMMAND \"" os << indent << " EXECUTE_PROCESS(COMMAND \""
<< this->Target->GetMakefile()->GetDefinition("CMAKE_STRIP") << this->Target->GetMakefile()->GetDefinition("CMAKE_STRIP")
<< "\" \"" << toFullPath << "\")\n"; << "\" \"" << toDestDirPath << "\")\n";
os << indent << "ENDIF(CMAKE_INSTALL_DO_STRIP)\n"; os << indent << "ENDIF(CMAKE_INSTALL_DO_STRIP)\n";
} }
@ -488,7 +533,7 @@ void
cmInstallTargetGenerator::AddRanlibRule(std::ostream& os, cmInstallTargetGenerator::AddRanlibRule(std::ostream& os,
Indent const& indent, Indent const& indent,
cmTarget::TargetType type, cmTarget::TargetType type,
const std::string& toFullPath) const std::string& toDestDirPath)
{ {
// Static libraries need ranlib on this platform. // Static libraries need ranlib on this platform.
if(type != cmTarget::STATIC_LIBRARY) if(type != cmTarget::STATIC_LIBRARY)
@ -511,5 +556,5 @@ cmInstallTargetGenerator::AddRanlibRule(std::ostream& os,
} }
os << indent << "EXECUTE_PROCESS(COMMAND \"" os << indent << "EXECUTE_PROCESS(COMMAND \""
<< ranlib << "\" \"" << toFullPath << "\")\n"; << ranlib << "\" \"" << toDestDirPath << "\")\n";
} }

View File

@ -53,13 +53,13 @@ protected:
Indent const& indent); Indent const& indent);
void AddInstallNamePatchRule(std::ostream& os, Indent const& indent, void AddInstallNamePatchRule(std::ostream& os, Indent const& indent,
const char* config, const char* config,
const std::string& toFullPath); const std::string& toDestDirPath);
void AddStripRule(std::ostream& os, Indent const& indent, void AddStripRule(std::ostream& os, Indent const& indent,
cmTarget::TargetType type, cmTarget::TargetType type,
const std::string& toFullPath); const std::string& toDestDirPath);
void AddRanlibRule(std::ostream& os, Indent const& indent, void AddRanlibRule(std::ostream& os, Indent const& indent,
cmTarget::TargetType type, cmTarget::TargetType type,
const std::string& toFullPath); const std::string& toDestDirPath);
cmTarget* Target; cmTarget* Target;
bool ImportLibrary; bool ImportLibrary;

View File

@ -145,6 +145,18 @@ public:
bool GetHaveInstallRule() { return this->HaveInstallRule; } bool GetHaveInstallRule() { return this->HaveInstallRule; }
void SetHaveInstallRule(bool h) { this->HaveInstallRule = h; } void SetHaveInstallRule(bool h) { this->HaveInstallRule = h; }
/**
* Get/Set the path needed for calls to install_name_tool regarding this
* target. Used to support fixing up installed libraries and executables on
* the Mac (including bundles and frameworks). Only used if the target does
* not have an INSTALL_NAME_DIR property.
* See cmInstallTargetGenerator::AddInstallNamePatchRule and callers for
* more information.
*/
std::string GetInstallNameFixupPath() { return this->InstallNameFixupPath; }
void SetInstallNameFixupPath(const char *path) {
this->InstallNameFixupPath = path; }
/** Add a utility on which this project depends. A utility is an executable /** Add a utility on which this project depends. A utility is an executable
* name as would be specified to the ADD_EXECUTABLE or UTILITY_SOURCE * name as would be specified to the ADD_EXECUTABLE or UTILITY_SOURCE
* commands. It is not a full path nor does it have an extension. * commands. It is not a full path nor does it have an extension.
@ -382,6 +394,7 @@ private:
std::vector<std::string> LinkDirectories; std::vector<std::string> LinkDirectories;
std::vector<std::string> ExplicitLinkDirectories; std::vector<std::string> ExplicitLinkDirectories;
bool HaveInstallRule; bool HaveInstallRule;
std::string InstallNameFixupPath;
std::string InstallPath; std::string InstallPath;
std::string RuntimeInstallPath; std::string RuntimeInstallPath;
std::string OutputDir; std::string OutputDir;

View File

@ -27,7 +27,7 @@ ADD_EXECUTABLE(SecondBundle
TARGET_LINK_LIBRARIES(SecondBundle BundleTestLib) TARGET_LINK_LIBRARIES(SecondBundle BundleTestLib)
# Test bundle installation. # Test bundle installation.
INSTALL(TARGETS SecondBundle DESTINATION Application) INSTALL(TARGETS SecondBundle DESTINATION Applications)
# Test whether bundles respect the output name. Since the library is # Test whether bundles respect the output name. Since the library is
# installed into a location that uses this output name this will fail if the # installed into a location that uses this output name this will fail if the

View File

@ -36,9 +36,9 @@ ADD_EXECUTABLE(BundleTest
TARGET_LINK_LIBRARIES(BundleTest BundleTestLib) TARGET_LINK_LIBRARIES(BundleTest BundleTestLib)
# Test bundle installation. # Test bundle installation.
#INSTALL(TARGETS BundleTestLib DESTINATION Application/BundleTestExe.app/Contents/Plugins) #INSTALL(TARGETS BundleTestLib DESTINATION Applications/BundleTestExe.app/Contents/Plugins)
INSTALL(TARGETS BundleTestLib DESTINATION Application/SecondBundleExe.app/Contents/Plugins) INSTALL(TARGETS BundleTestLib DESTINATION Applications/SecondBundleExe.app/Contents/Plugins)
INSTALL(TARGETS BundleTest DESTINATION Application) INSTALL(TARGETS BundleTest DESTINATION Applications)
# Test whether bundles respect the output name. Since the library is # Test whether bundles respect the output name. Since the library is
# installed into a location that uses this output name this will fail if the # installed into a location that uses this output name this will fail if the
@ -59,7 +59,7 @@ INCLUDE(CPack)
# test the framework find stuff # test the framework find stuff
IF(EXISTS /usr/lib/libtcl.dylib IF(EXISTS /usr/lib/libtcl.dylib
AND EXISTS /System/Library/Frameworks/tcl.framework) AND EXISTS /System/Library/Frameworks/Tcl.framework)
SET(TCL NOTFOUND) SET(TCL NOTFOUND)
FIND_LIBRARY(TCL tcl) FIND_LIBRARY(TCL tcl)
MESSAGE("frame: ${TCL}") MESSAGE("frame: ${TCL}")
@ -87,6 +87,6 @@ IF(EXISTS /usr/lib/libtcl.dylib
ENDIF(NOT "${TCL}" MATCHES .framework) ENDIF(NOT "${TCL}" MATCHES .framework)
MESSAGE("frame: ${TCL}") MESSAGE("frame: ${TCL}")
ENDIF(EXISTS /usr/lib/libtcl.dylib ENDIF(EXISTS /usr/lib/libtcl.dylib
AND EXISTS /System/Library/Frameworks/tcl.framework) AND EXISTS /System/Library/Frameworks/Tcl.framework)
SUBDIRS(BundleSubDir) SUBDIRS(BundleSubDir)

View File

@ -597,7 +597,7 @@ IF(BUILD_TESTING)
--build-options "-DCMAKE_INSTALL_PREFIX:PATH=${BundleTestInstallDir}" --build-options "-DCMAKE_INSTALL_PREFIX:PATH=${BundleTestInstallDir}"
"-DCMake_SOURCE_DIR:PATH=${CMAKE_SOURCE_DIR}" "-DCMake_SOURCE_DIR:PATH=${CMAKE_SOURCE_DIR}"
--test-command --test-command
${BundleTestInstallDir}/Application/SecondBundleExe.app/Contents/MacOS/SecondBundleExe) ${BundleTestInstallDir}/Applications/SecondBundleExe.app/Contents/MacOS/SecondBundleExe)
ADD_TEST_MACRO(ObjC++ ObjC++) ADD_TEST_MACRO(ObjC++ ObjC++)
ENDIF (APPLE AND CMAKE_COMPILER_IS_GNUCXX) ENDIF (APPLE AND CMAKE_COMPILER_IS_GNUCXX)

View File

@ -27,7 +27,10 @@ set_source_files_properties(test.lua PROPERTIES
) )
add_executable(bar bar.cxx) add_executable(bar bar.cxx)
target_link_libraries(bar foo) target_link_libraries(bar foo)
install(TARGETS foo bar
RUNTIME DESTINATION /Applications/CMakeTestsFramework/bin
FRAMEWORK DESTINATION /Library/Frameworks
)
# Make a static library and apply the framework properties to it to verify # Make a static library and apply the framework properties to it to verify
# that everything still builds correctly, but it will not actually produce # that everything still builds correctly, but it will not actually produce