Xcode: Add support for shared library versioning

Add a post-build command to shared library targets to create the
versioning symbolic links.
This commit is contained in:
Clinton Stimpson 2013-05-13 20:45:35 -06:00 committed by Brad King
parent 373faae5e1
commit cbe3f2072b
2 changed files with 81 additions and 21 deletions

View File

@ -207,12 +207,8 @@ if("${CMAKE_BACKWARDS_COMPATIBILITY}" MATCHES "^1\\.[0-6]$")
"${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -flat_namespace -undefined suppress") "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -flat_namespace -undefined suppress")
endif() endif()
if(NOT XCODE) # Enable shared library versioning.
# Enable shared library versioning. This flag is not actually referenced set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-install_name")
# but the fact that the setting exists will cause the generators to support
# soname computation.
set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-install_name")
endif()
# Xcode does not support -isystem yet. # Xcode does not support -isystem yet.
if(XCODE) if(XCODE)

View File

@ -1319,8 +1319,40 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases,
= cmtarget.GetPreBuildCommands(); = cmtarget.GetPreBuildCommands();
std::vector<cmCustomCommand> const & prelink std::vector<cmCustomCommand> const & prelink
= cmtarget.GetPreLinkCommands(); = cmtarget.GetPreLinkCommands();
std::vector<cmCustomCommand> const & postbuild std::vector<cmCustomCommand> postbuild
= cmtarget.GetPostBuildCommands(); = cmtarget.GetPostBuildCommands();
if(cmtarget.GetType() == cmTarget::SHARED_LIBRARY &&
!cmtarget.IsFrameworkOnApple())
{
cmCustomCommandLines cmd;
cmd.resize(1);
cmd[0].push_back(this->CurrentMakefile->GetDefinition("CMAKE_COMMAND"));
cmd[0].push_back("-E");
cmd[0].push_back("cmake_symlink_library");
std::string str_file = "$<TARGET_FILE:";
str_file += cmtarget.GetName();
str_file += ">";
std::string str_so_file = "$<TARGET_SONAME_FILE:";
str_so_file += cmtarget.GetName();
str_so_file += ">";
std::string str_link_file = "$<TARGET_LINKER_FILE:";
str_link_file += cmtarget.GetName();
str_link_file += ">";
cmd[0].push_back(str_file);
cmd[0].push_back(str_so_file);
cmd[0].push_back(str_link_file);
cmCustomCommand command(this->CurrentMakefile,
std::vector<std::string>(),
std::vector<std::string>(),
cmd,
"Creating symlinks",
"");
postbuild.push_back(command);
}
std::vector<cmSourceFile*>const &classes = cmtarget.GetSourceFiles(); std::vector<cmSourceFile*>const &classes = cmtarget.GetSourceFiles();
// add all the sources // add all the sources
std::vector<cmCustomCommand> commands; std::vector<cmCustomCommand> commands;
@ -1797,9 +1829,34 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
std::string pnprefix; std::string pnprefix;
std::string pnbase; std::string pnbase;
std::string pnsuffix; std::string pnsuffix;
target.GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName); target.GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName);
const char* version = target.GetProperty("VERSION");
const char* soversion = target.GetProperty("SOVERSION");
if(!target.HasSOName(configName) || target.IsFrameworkOnApple())
{
version = 0;
soversion = 0;
}
if(version && !soversion)
{
soversion = version;
}
if(!version && soversion)
{
version = soversion;
}
std::string realName = pnbase;
std::string soName = pnbase;
if(version && soversion)
{
realName += ".";
realName += version;
soName += ".";
soName += soversion;
}
// Set attributes to specify the proper name for the target. // Set attributes to specify the proper name for the target.
std::string pndir = this->CurrentMakefile->GetCurrentOutputDirectory(); std::string pndir = this->CurrentMakefile->GetCurrentOutputDirectory();
if(target.GetType() == cmTarget::STATIC_LIBRARY || if(target.GetType() == cmTarget::STATIC_LIBRARY ||
@ -1857,7 +1914,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
// Store the product name for all target types. // Store the product name for all target types.
buildSettings->AddAttribute("PRODUCT_NAME", buildSettings->AddAttribute("PRODUCT_NAME",
this->CreateString(pnbase.c_str())); this->CreateString(realName.c_str()));
buildSettings->AddAttribute("SYMROOT", buildSettings->AddAttribute("SYMROOT",
this->CreateString(pndir.c_str())); this->CreateString(pndir.c_str()));
@ -1935,9 +1992,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
{ {
if(target.GetPropertyAsBool("FRAMEWORK")) if(target.GetPropertyAsBool("FRAMEWORK"))
{ {
std::string version = target.GetFrameworkVersion(); std::string fw_version = target.GetFrameworkVersion();
buildSettings->AddAttribute("FRAMEWORK_VERSION", buildSettings->AddAttribute("FRAMEWORK_VERSION",
this->CreateString(version.c_str())); this->CreateString(fw_version.c_str()));
std::string plist = this->ComputeInfoPListLocation(target); std::string plist = this->ComputeInfoPListLocation(target);
// Xcode will create the final version of Info.plist at build time, // Xcode will create the final version of Info.plist at build time,
@ -2162,19 +2219,26 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
{ {
// Get the install_name directory for the build tree. // Get the install_name directory for the build tree.
install_name_dir = target.GetInstallNameDirForBuildTree(configName); install_name_dir = target.GetInstallNameDirForBuildTree(configName);
if(install_name_dir.empty()) // Xcode doesn't create the correct install_name in some cases.
{ // That is, if the INSTALL_PATH is empty, or if we have versioning
// Xcode will not pass the -install_name option at all if INSTALL_PATH // of dylib libraries, we want to specify the install_name.
// is not given or is empty. We must explicitly put the flag in the // This is done by adding a link flag to create an install_name
// link flags to create an install_name with just the library soname. // with just the library soname.
extraLinkOptions += " -install_name "; std::string install_name;
extraLinkOptions += target.GetSOName(configName); if(!install_name_dir.empty())
}
else
{ {
// Convert to a path for the native build tool. // Convert to a path for the native build tool.
cmSystemTools::ConvertToUnixSlashes(install_name_dir); cmSystemTools::ConvertToUnixSlashes(install_name_dir);
// do not escape spaces on this since it is only a single path install_name += install_name_dir;
install_name += "/";
}
install_name += target.GetSOName(configName);
if((realName != soName) || install_name_dir.empty())
{
install_name_dir = "";
extraLinkOptions += " -install_name ";
extraLinkOptions += XCodeEscapePath(install_name.c_str());
} }
} }
buildSettings->AddAttribute("INSTALL_PATH", buildSettings->AddAttribute("INSTALL_PATH",