From cbe3f2072bdd181660bc4f9174a73febd3ed5230 Mon Sep 17 00:00:00 2001 From: Clinton Stimpson Date: Mon, 13 May 2013 20:45:35 -0600 Subject: Xcode: Add support for shared library versioning Add a post-build command to shared library targets to create the versioning symbolic links. --- Modules/Platform/Darwin.cmake | 8 +--- Source/cmGlobalXCodeGenerator.cxx | 94 ++++++++++++++++++++++++++++++++------- 2 files changed, 81 insertions(+), 21 deletions(-) diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake index 2e6b71e..6e5d449 100644 --- a/Modules/Platform/Darwin.cmake +++ b/Modules/Platform/Darwin.cmake @@ -207,12 +207,8 @@ if("${CMAKE_BACKWARDS_COMPATIBILITY}" MATCHES "^1\\.[0-6]$") "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -flat_namespace -undefined suppress") endif() -if(NOT XCODE) - # Enable shared library versioning. This flag is not actually referenced - # 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() +# Enable shared library versioning. +set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-install_name") # Xcode does not support -isystem yet. if(XCODE) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 240d60c..9bbf186 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1319,8 +1319,40 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases, = cmtarget.GetPreBuildCommands(); std::vector const & prelink = cmtarget.GetPreLinkCommands(); - std::vector const & postbuild + std::vector postbuild = 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 = "$CurrentMakefile, + std::vector(), + std::vector(), + cmd, + "Creating symlinks", + ""); + + postbuild.push_back(command); + } + std::vectorconst &classes = cmtarget.GetSourceFiles(); // add all the sources std::vector commands; @@ -1797,9 +1829,34 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, std::string pnprefix; std::string pnbase; std::string pnsuffix; - 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. std::string pndir = this->CurrentMakefile->GetCurrentOutputDirectory(); if(target.GetType() == cmTarget::STATIC_LIBRARY || @@ -1857,7 +1914,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, // Store the product name for all target types. buildSettings->AddAttribute("PRODUCT_NAME", - this->CreateString(pnbase.c_str())); + this->CreateString(realName.c_str())); buildSettings->AddAttribute("SYMROOT", this->CreateString(pndir.c_str())); @@ -1935,9 +1992,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, { if(target.GetPropertyAsBool("FRAMEWORK")) { - std::string version = target.GetFrameworkVersion(); + std::string fw_version = target.GetFrameworkVersion(); buildSettings->AddAttribute("FRAMEWORK_VERSION", - this->CreateString(version.c_str())); + this->CreateString(fw_version.c_str())); std::string plist = this->ComputeInfoPListLocation(target); // 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. install_name_dir = target.GetInstallNameDirForBuildTree(configName); - if(install_name_dir.empty()) - { - // Xcode will not pass the -install_name option at all if INSTALL_PATH - // is not given or is empty. We must explicitly put the flag in the - // link flags to create an install_name with just the library soname. - extraLinkOptions += " -install_name "; - extraLinkOptions += target.GetSOName(configName); - } - else + // Xcode doesn't create the correct install_name in some cases. + // That is, if the INSTALL_PATH is empty, or if we have versioning + // of dylib libraries, we want to specify the install_name. + // This is done by adding a link flag to create an install_name + // with just the library soname. + std::string install_name; + if(!install_name_dir.empty()) { // Convert to a path for the native build tool. 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", -- cgit v0.12