瀏覽代碼

Merge topic 'framework-refactor'

373faae Refactor how bundles and frameworks are supported.
Brad King 12 年之前
父節點
當前提交
b0759da303

+ 1 - 1
Source/cmExportBuildFileGenerator.cxx

@@ -143,7 +143,7 @@ cmExportBuildFileGenerator
   std::string prop = "IMPORTED_LOCATION";
   prop += suffix;
   std::string value;
-  if(target->IsFrameworkOnApple() || target->IsAppBundleOnApple())
+  if(target->IsAppBundleOnApple())
     {
     value = target->GetFullPath(config, false);
     }

+ 1 - 7
Source/cmExportInstallFileGenerator.cxx

@@ -351,13 +351,7 @@ cmExportInstallFileGenerator
     prop += suffix;
 
     // Append the installed file name.
-    if(target->IsFrameworkOnApple())
-      {
-      value += itgen->GetInstallFilename(target, config);
-      value += ".framework/";
-      value += itgen->GetInstallFilename(target, config);
-      }
-    else if(target->IsCFBundleOnApple())
+    if(target->IsCFBundleOnApple())
       {
       const char *ext = target->GetProperty("BUNDLE_EXTENSION");
       if (!ext)

+ 7 - 2
Source/cmGlobalXCodeGenerator.cxx

@@ -1821,6 +1821,11 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
       pndir = target.GetDirectory(configName);
       }
 
+    if(target.IsFrameworkOnApple())
+      {
+      pnprefix = "";
+      }
+
     buildSettings->AddAttribute("EXECUTABLE_PREFIX",
                                 this->CreateString(pnprefix.c_str()));
     buildSettings->AddAttribute("EXECUTABLE_SUFFIX",
@@ -2154,14 +2159,14 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
   if(target.GetType() == cmTarget::SHARED_LIBRARY)
     {
     // Get the install_name directory for the build tree.
-    install_name_dir = target.GetInstallNameDirForBuildTree(configName, true);
+    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.GetFullName(configName);
+      extraLinkOptions += target.GetSOName(configName);
       }
     else
       {

+ 6 - 8
Source/cmInstallTargetGenerator.cxx

@@ -198,14 +198,12 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
       // Install the whole framework directory.
       type = cmInstallType_DIRECTORY;
       literal_args += " USE_SOURCE_PERMISSIONS";
-      std::string from1 = fromDirConfig + targetName + ".framework";
+
+      std::string from1 = fromDirConfig + targetName;
+      from1 = cmSystemTools::GetFilenamePath(from1);
 
       // Tweaks apply to the binary inside the bundle.
-      std::string to1 = toDir + targetName;
-      to1 += ".framework/Versions/";
-      to1 += this->Target->GetFrameworkVersion();
-      to1 += "/";
-      to1 += targetName;
+      std::string to1 = toDir + targetNameReal;
 
       filesFrom.push_back(from1);
       filesTo.push_back(to1);
@@ -528,7 +526,7 @@ cmInstallTargetGenerator
       // components of the install_name field then we need to create a
       // mapping to be applied after installation.
       std::string for_build = tgt->GetInstallNameDirForBuildTree(config);
-      std::string for_install = tgt->GetInstallNameDirForInstallTree(config);
+      std::string for_install = tgt->GetInstallNameDirForInstallTree();
       if(for_build != for_install)
         {
         // The directory portions differ.  Append the filename to
@@ -555,7 +553,7 @@ cmInstallTargetGenerator
     std::string for_build =
       this->Target->GetInstallNameDirForBuildTree(config);
     std::string for_install =
-      this->Target->GetInstallNameDirForInstallTree(config);
+      this->Target->GetInstallNameDirForInstallTree();
 
     if(this->Target->IsFrameworkOnApple() && for_install.empty())
       {

+ 1 - 4
Source/cmMakefileExecutableTargetGenerator.cxx

@@ -30,11 +30,8 @@ cmMakefileExecutableTargetGenerator
     this->TargetNamePDB, this->ConfigName);
 
   this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target,
-                                                      this->TargetNameOut,
                                                       this->ConfigName);
   this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
-  this->MacContentDirectory =
-    this->OSXBundleGenerator->GetMacContentDirectory();
 }
 
 //----------------------------------------------------------------------------
@@ -103,11 +100,11 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
 
   // Construct the full path version of the names.
   std::string outpath = this->Target->GetDirectory(this->ConfigName);
-  outpath += "/";
   if(this->Target->IsAppBundleOnApple())
     {
     this->OSXBundleGenerator->CreateAppBundle(targetName, outpath);
     }
+  outpath += "/";
   std::string outpathImp;
   if(relink)
     {

+ 6 - 7
Source/cmMakefileLibraryTargetGenerator.cxx

@@ -32,11 +32,8 @@ cmMakefileLibraryTargetGenerator
     this->TargetNameImport, this->TargetNamePDB, this->ConfigName);
 
   this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target,
-                                                      this->TargetNameOut,
                                                       this->ConfigName);
   this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
-  this->MacContentDirectory =
-    this->OSXBundleGenerator->GetMacContentDirectory();
 }
 
 //----------------------------------------------------------------------------
@@ -292,14 +289,15 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
   std::string outpathImp;
   if(this->Target->IsFrameworkOnApple())
     {
-    outpath = this->MacContentDirectory;
-    this->OSXBundleGenerator->CreateFramework(targetName);
+    outpath = this->Target->GetDirectory(this->ConfigName);
+    this->OSXBundleGenerator->CreateFramework(targetName, outpath);
+    outpath += "/";
     }
   else if(this->Target->IsCFBundleOnApple())
     {
     outpath = this->Target->GetDirectory(this->ConfigName);
-    outpath += "/";
     this->OSXBundleGenerator->CreateCFBundle(targetName, outpath);
+    outpath += "/";
     }
   else if(relink)
     {
@@ -727,7 +725,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
   commands1.clear();
 
   // Add a rule to create necessary symlinks for the library.
-  if(targetOutPath != targetOutPathReal)
+  // Frameworks are handled by cmOSXBundleGenerator.
+  if(targetOutPath != targetOutPathReal && !this->Target->IsFrameworkOnApple())
     {
     std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_library ";
     symlink += targetOutPathReal;

+ 1 - 1
Source/cmMakefileTargetGenerator.cxx

@@ -357,7 +357,7 @@ cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()
   (cmSourceFile& source, const char* pkgloc)
 {
   // Skip OS X content when not building a Framework or Bundle.
-  if(this->Generator->MacContentDirectory.empty())
+  if(!this->Generator->GetTarget()->IsBundleOnApple())
     {
     return;
     }

+ 0 - 1
Source/cmMakefileTargetGenerator.h

@@ -233,7 +233,6 @@ protected:
   std::string TargetNamePDB;
 
   // Mac OS X content info.
-  std::string MacContentDirectory;
   std::set<cmStdString> MacContentFolders;
   cmOSXBundleGenerator* OSXBundleGenerator;
   MacOSXContentGeneratorType* MacOSXContentGenerator;

+ 0 - 3
Source/cmMakefileUtilityTargetGenerator.cxx

@@ -25,11 +25,8 @@ cmMakefileUtilityTargetGenerator
 {
   this->CustomCommandDriver = OnUtility;
   this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target,
-                                                      this->TargetNameOut,
                                                       this->ConfigName);
   this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
-  this->MacContentDirectory =
-    this->OSXBundleGenerator->GetMacContentDirectory();
 }
 
 //----------------------------------------------------------------------------

+ 13 - 6
Source/cmNinjaNormalTargetGenerator.cxx

@@ -61,7 +61,6 @@ cmNinjaNormalTargetGenerator(cmTarget* target)
     }
 
   this->OSXBundleGenerator = new cmOSXBundleGenerator(target,
-                                                      this->TargetNameOut,
                                                       this->GetConfigName());
   this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
 }
@@ -383,24 +382,32 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
   if (this->GetTarget()->IsAppBundleOnApple())
     {
     // Create the app bundle
-    std::string outpath;
+    std::string outpath =
+      this->GetTarget()->GetDirectory(this->GetConfigName());
     this->OSXBundleGenerator->CreateAppBundle(this->TargetNameOut, outpath);
 
     // Calculate the output path
-    targetOutput = outpath + this->TargetNameOut;
+    targetOutput = outpath;
+    targetOutput += "/";
+    targetOutput += this->TargetNameOut;
     targetOutput = this->ConvertToNinjaPath(targetOutput.c_str());
-    targetOutputReal = outpath + this->TargetNameReal;
+    targetOutputReal = outpath;
+    targetOutputReal += "/";
+    targetOutputReal += this->TargetNameReal;
     targetOutputReal = this->ConvertToNinjaPath(targetOutputReal.c_str());
     }
   else if (this->GetTarget()->IsFrameworkOnApple())
     {
     // Create the library framework.
-    this->OSXBundleGenerator->CreateFramework(this->TargetNameOut);
+    std::string outpath =
+      this->GetTarget()->GetDirectory(this->GetConfigName());
+    this->OSXBundleGenerator->CreateFramework(this->TargetNameOut, outpath);
     }
   else if(this->GetTarget()->IsCFBundleOnApple())
     {
     // Create the core foundation bundle.
-    std::string outpath;
+    std::string outpath =
+      this->GetTarget()->GetDirectory(this->GetConfigName());
     this->OSXBundleGenerator->CreateCFBundle(this->TargetNameOut, outpath);
     }
 

+ 1 - 1
Source/cmNinjaTargetGenerator.cxx

@@ -699,7 +699,7 @@ cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()(
   cmSourceFile& source, const char* pkgloc)
 {
   // Skip OS X content when not building a Framework or Bundle.
-  if(this->Generator->OSXBundleGenerator->GetMacContentDirectory().empty())
+  if(!this->Generator->GetTarget()->IsBundleOnApple())
     {
     return;
     }

+ 56 - 46
Source/cmOSXBundleGenerator.cxx

@@ -28,26 +28,16 @@ void cmOSXBundleGenerator::PrepareTargetProperties(cmTarget* target)
 //----------------------------------------------------------------------------
 cmOSXBundleGenerator::
 cmOSXBundleGenerator(cmTarget* target,
-                     std::string targetNameOut,
                      const char* configName)
  : Target(target)
  , Makefile(target->GetMakefile())
  , LocalGenerator(Makefile->GetLocalGenerator())
- , TargetNameOut(targetNameOut)
  , ConfigName(configName)
- , MacContentDirectory()
- , FrameworkVersion()
  , MacContentFolders(0)
 {
   if (this->MustSkip())
     return;
 
-  this->MacContentDirectory =
-    this->Target->GetMacContentDirectory(this->ConfigName,
-                                         /*implib*/ false,
-                                         /*includeMacOS*/ false);
-  if(this->Target->IsFrameworkOnApple())
-    this->FrameworkVersion = this->Target->GetFrameworkVersion();
 }
 
 //----------------------------------------------------------------------------
@@ -57,41 +47,60 @@ bool cmOSXBundleGenerator::MustSkip()
 }
 
 //----------------------------------------------------------------------------
-void cmOSXBundleGenerator::CreateAppBundle(std::string& targetName,
+void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName,
                                            std::string& outpath)
 {
   if (this->MustSkip())
     return;
 
   // Compute bundle directory names.
-  outpath = this->MacContentDirectory;
-  outpath += "MacOS";
-  cmSystemTools::MakeDirectory(outpath.c_str());
-  outpath += "/";
-  this->Makefile->AddCMakeOutputFile(outpath.c_str());
+  std::string out = outpath;
+  out += "/";
+  out += this->Target->GetAppBundleDirectory(this->ConfigName, false);
+  cmSystemTools::MakeDirectory(out.c_str());
+  this->Makefile->AddCMakeOutputFile(out.c_str());
+
+  std::string newoutpath = out;
 
   // Configure the Info.plist file.  Note that it needs the executable name
   // to be set.
-  std::string plist = this->MacContentDirectory + "Info.plist";
+  std::string plist = outpath;
+  plist += "/";
+  plist += this->Target->GetAppBundleDirectory(this->ConfigName, true);
+  plist += "/Info.plist";
   this->LocalGenerator->GenerateAppleInfoPList(this->Target,
                                                targetName.c_str(),
                                                plist.c_str());
   this->Makefile->AddCMakeOutputFile(plist.c_str());
+  outpath = newoutpath;
 }
 
 //----------------------------------------------------------------------------
-void cmOSXBundleGenerator::CreateFramework(std::string const& targetName)
+void cmOSXBundleGenerator::CreateFramework(
+  const std::string& targetName, const std::string& outpath)
 {
   if (this->MustSkip())
     return;
 
   assert(this->MacContentFolders);
 
+  // Compute the location of the top-level foo.framework directory.
+  std::string contentdir = outpath + "/" +
+    this->Target->GetFrameworkDirectory(this->ConfigName, true);
+  contentdir += "/";
+
+  std::string newoutpath = outpath + "/" +
+    this->Target->GetFrameworkDirectory(this->ConfigName, false);
+
+  std::string frameworkVersion = this->Target->GetFrameworkVersion();
+
   // Configure the Info.plist file into the Resources directory.
   this->MacContentFolders->insert("Resources");
-  std::string plist = this->MacContentDirectory + "Resources/Info.plist";
+  std::string plist = newoutpath;
+  plist += "/Resources/Info.plist";
+  std::string name = cmSystemTools::GetFilenameName(targetName);
   this->LocalGenerator->GenerateFrameworkInfoPList(this->Target,
-                                                   targetName.c_str(),
+                                                   name.c_str(),
                                                    plist.c_str());
 
   // TODO: Use the cmMakefileTargetGenerator::ExtraFiles vector to
@@ -99,25 +108,17 @@ void cmOSXBundleGenerator::CreateFramework(std::string const& targetName)
   std::string oldName;
   std::string newName;
 
-  // Compute the location of the top-level foo.framework directory.
-  std::string top = this->Target->GetDirectory(this->ConfigName);
-  top += "/";
-  top += this->TargetNameOut;
-  top += ".framework/";
 
   // Make foo.framework/Versions
-  std::string versions = top;
+  std::string versions = contentdir;
   versions += "Versions";
   cmSystemTools::MakeDirectory(versions.c_str());
 
   // Make foo.framework/Versions/version
-  std::string version = versions;
-  version += "/";
-  version += this->FrameworkVersion;
-  cmSystemTools::MakeDirectory(version.c_str());
+  cmSystemTools::MakeDirectory(newoutpath.c_str());
 
   // Current -> version
-  oldName = this->FrameworkVersion;
+  oldName = frameworkVersion;
   newName = versions;
   newName += "/Current";
   cmSystemTools::RemoveFile(newName.c_str());
@@ -126,9 +127,9 @@ void cmOSXBundleGenerator::CreateFramework(std::string const& targetName)
 
   // foo -> Versions/Current/foo
   oldName = "Versions/Current/";
-  oldName += this->TargetNameOut;
-  newName = top;
-  newName += this->TargetNameOut;
+  oldName += name;
+  newName = contentdir;
+  newName += name;
   cmSystemTools::RemoveFile(newName.c_str());
   cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
   this->Makefile->AddCMakeOutputFile(newName.c_str());
@@ -138,7 +139,7 @@ void cmOSXBundleGenerator::CreateFramework(std::string const& targetName)
      this->MacContentFolders->end())
     {
     oldName = "Versions/Current/Resources";
-    newName = top;
+    newName = contentdir;
     newName += "Resources";
     cmSystemTools::RemoveFile(newName.c_str());
     cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
@@ -150,7 +151,7 @@ void cmOSXBundleGenerator::CreateFramework(std::string const& targetName)
      this->MacContentFolders->end())
     {
     oldName = "Versions/Current/Headers";
-    newName = top;
+    newName = contentdir;
     newName += "Headers";
     cmSystemTools::RemoveFile(newName.c_str());
     cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
@@ -162,7 +163,7 @@ void cmOSXBundleGenerator::CreateFramework(std::string const& targetName)
      this->MacContentFolders->end())
     {
     oldName = "Versions/Current/PrivateHeaders";
-    newName = top;
+    newName = contentdir;
     newName += "PrivateHeaders";
     cmSystemTools::RemoveFile(newName.c_str());
     cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
@@ -171,27 +172,32 @@ void cmOSXBundleGenerator::CreateFramework(std::string const& targetName)
 }
 
 //----------------------------------------------------------------------------
-void cmOSXBundleGenerator::CreateCFBundle(std::string& targetName,
+void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName,
                                           std::string& outpath)
 {
   if (this->MustSkip())
     return;
 
   // Compute bundle directory names.
-  outpath = this->MacContentDirectory;
-  outpath += "MacOS";
-  cmSystemTools::MakeDirectory(outpath.c_str());
-  outpath += "/";
-  this->Makefile->AddCMakeOutputFile(outpath.c_str());
+  std::string out = outpath;
+  out += "/";
+  out += this->Target->GetCFBundleDirectory(this->ConfigName, true);
+  std::string top = out;
+  out += "/MacOS";
+  cmSystemTools::MakeDirectory(out.c_str());
+  this->Makefile->AddCMakeOutputFile(out.c_str());
+
+  std::string newoutpath = out;
 
   // Configure the Info.plist file.  Note that it needs the executable name
   // to be set.
-  std::string plist = this->MacContentDirectory;
-  plist += "Info.plist";
+  std::string plist = top;
+  plist += "/Info.plist";
   this->LocalGenerator->GenerateAppleInfoPList(this->Target,
                                                targetName.c_str(),
                                                plist.c_str());
   this->Makefile->AddCMakeOutputFile(plist.c_str());
+  outpath = newoutpath;
 }
 
 //----------------------------------------------------------------------------
@@ -220,7 +226,11 @@ std::string
 cmOSXBundleGenerator::InitMacOSXContentDirectory(const char* pkgloc)
 {
   // Construct the full path to the content subdirectory.
-  std::string macdir = this->MacContentDirectory;
+
+  std::string macdir =
+    this->Target->GetMacContentDirectory(this->ConfigName,
+                                         /*implib*/ false);
+  macdir += "/";
   macdir += pkgloc;
   cmSystemTools::MakeDirectory(macdir.c_str());
 

+ 11 - 11
Source/cmOSXBundleGenerator.h

@@ -28,12 +28,19 @@ public:
   static void PrepareTargetProperties(cmTarget* target);
 
   cmOSXBundleGenerator(cmTarget* target,
-                       std::string targetNameOut,
                        const char* configName);
 
-  void CreateAppBundle(std::string& targetName, std::string& outpath);
-  void CreateFramework(std::string const& targetName);
-  void CreateCFBundle(std::string& targetName, std::string& outpath);
+  // create an app bundle at a given root, and return
+  // the directory within the bundle that contains the executable
+  void CreateAppBundle(const std::string& targetName, std::string& root);
+
+  // create a framework at a given root
+  void CreateFramework(const std::string& targetName,
+                       const std::string& root);
+
+  // create a cf bundle at a given root and return the
+  // directory within the bundle that contains the library
+  void CreateCFBundle(const std::string& targetName, std::string& outpath);
 
   struct MacOSXContentGeneratorType
   {
@@ -46,10 +53,6 @@ public:
     MacOSXContentGeneratorType* generator);
   std::string InitMacOSXContentDirectory(const char* pkgloc);
 
-  std::string GetMacContentDirectory() const
-  { return this->MacContentDirectory; }
-  std::string GetFrameworkVersion() const
-  { return this->FrameworkVersion; }
   void SetMacContentFolders(std::set<cmStdString>* macContentFolders)
   { this->MacContentFolders = macContentFolders; }
 
@@ -60,10 +63,7 @@ private:
   cmTarget* Target;
   cmMakefile* Makefile;
   cmLocalGenerator* LocalGenerator;
-  std::string TargetNameOut;
   const char* ConfigName;
-  std::string MacContentDirectory;
-  std::string FrameworkVersion;
   std::set<cmStdString>* MacContentFolders;
 };
 

+ 104 - 56
Source/cmTarget.cxx

@@ -1682,6 +1682,13 @@ bool cmTarget::IsCFBundleOnApple()
           this->GetPropertyAsBool("BUNDLE"));
 }
 
+//----------------------------------------------------------------------------
+bool cmTarget::IsBundleOnApple()
+{
+  return this->IsFrameworkOnApple() || this->IsAppBundleOnApple() ||
+         this->IsCFBundleOnApple();
+}
+
 //----------------------------------------------------------------------------
 class cmTargetTraceDependencies
 {
@@ -3379,17 +3386,23 @@ const char* cmTarget::NormalGetLocation(const char* config)
 
   // Now handle the deprecated build-time configuration location.
   this->Location = this->GetDirectory();
-  if(!this->Location.empty())
-    {
-    this->Location += "/";
-    }
   const char* cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR");
   if(cfgid && strcmp(cfgid, ".") != 0)
     {
-    this->Location += cfgid;
     this->Location += "/";
+    this->Location += cfgid;
+    }
+
+  if(this->IsCFBundleOnApple() || this->IsAppBundleOnApple())
+    {
+    std::string macdir = this->BuildMacContentDirectory("", config, false);
+    if(!macdir.empty())
+      {
+      this->Location += "/";
+      this->Location += macdir;
+      }
     }
-  this->Location = this->BuildMacContentDirectory(this->Location, config);
+  this->Location += "/";
   this->Location += this->GetFullName(config, false);
   return this->Location.c_str();
 }
@@ -3991,7 +4004,13 @@ std::string cmTarget::GetFullPath(const char* config, bool implib,
 std::string cmTarget::NormalGetFullPath(const char* config, bool implib,
                                         bool realname)
 {
-  std::string fpath = this->GetMacContentDirectory(config, implib);
+  std::string fpath = this->GetDirectory(config, implib);
+  fpath += "/";
+  if(this->IsCFBundleOnApple() || this->IsAppBundleOnApple())
+    {
+    fpath = this->BuildMacContentDirectory(fpath, config, false);
+    fpath += "/";
+    }
 
   // Add the full name of the target.
   if(implib)
@@ -4123,10 +4142,13 @@ void cmTarget::GetFullNameInternal(const char* config,
     targetSuffix = this->Makefile->GetSafeDefinition(suffixVar);
     }
 
-  // frameworks do not have a prefix or a suffix
+  // frameworks have directory prefix but no suffix
+  std::string fw_prefix;
   if(this->IsFrameworkOnApple())
     {
-    targetPrefix = 0;
+    fw_prefix = this->GetOutputName(config, false);
+    fw_prefix += ".framework/";
+    targetPrefix = fw_prefix.c_str();
     targetSuffix = 0;
     }
 
@@ -4206,13 +4228,24 @@ void cmTarget::GetLibraryNames(std::string& name,
   // The library name.
   name = prefix+base+suffix;
 
-  // The library's soname.
-  this->ComputeVersionedName(soName, prefix, base, suffix,
-                             name, soversion);
-
-  // The library's real name on disk.
-  this->ComputeVersionedName(realName, prefix, base, suffix,
-                             name, version);
+  if(this->IsFrameworkOnApple())
+    {
+    realName = prefix;
+    realName += "Versions/";
+    realName += this->GetFrameworkVersion();
+    realName += "/";
+    realName += base;
+    soName = realName;
+    }
+  else
+    {
+    // The library's soname.
+    this->ComputeVersionedName(soName, prefix, base, suffix,
+                               name, soversion);
+    // The library's real name on disk.
+    this->ComputeVersionedName(realName, prefix, base, suffix,
+                               name, version);
+    }
 
   // The import library name.
   if(this->GetType() == cmTarget::SHARED_LIBRARY ||
@@ -4500,14 +4533,13 @@ bool cmTarget::NeedRelinkBeforeInstall(const char* config)
 }
 
 //----------------------------------------------------------------------------
-std::string cmTarget::GetInstallNameDirForBuildTree(const char* config,
-                                                    bool for_xcode)
+std::string cmTarget::GetInstallNameDirForBuildTree(const char* config)
 {
   // If building directly for installation then the build tree install_name
   // is the same as the install tree.
   if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"))
     {
-    return GetInstallNameDirForInstallTree(config, for_xcode);
+    return GetInstallNameDirForInstallTree();
     }
 
   // Use the build tree directory for the target.
@@ -4517,10 +4549,6 @@ std::string cmTarget::GetInstallNameDirForBuildTree(const char* config,
     {
     std::string dir = this->GetDirectory(config);
     dir += "/";
-    if(this->IsFrameworkOnApple() && !for_xcode)
-      {
-      dir += this->GetFrameworkDirectory(config);
-      }
     return dir;
     }
   else
@@ -4530,8 +4558,7 @@ std::string cmTarget::GetInstallNameDirForBuildTree(const char* config,
 }
 
 //----------------------------------------------------------------------------
-std::string cmTarget::GetInstallNameDirForInstallTree(const char* config,
-                                                      bool for_xcode)
+std::string cmTarget::GetInstallNameDirForInstallTree()
 {
   if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
     {
@@ -4547,12 +4574,6 @@ std::string cmTarget::GetInstallNameDirForInstallTree(const char* config,
         dir += "/";
         }
       }
-
-    if(this->IsFrameworkOnApple() && !for_xcode)
-      {
-      dir += this->GetFrameworkDirectory(config);
-      }
-
     return dir;
     }
   else
@@ -6010,59 +6031,86 @@ cmTarget::GetLinkInformation(const char* config, cmTarget *head)
 }
 
 //----------------------------------------------------------------------------
-std::string cmTarget::GetFrameworkDirectory(const char* config)
+std::string cmTarget::GetFrameworkDirectory(const char* config,
+                                            bool rootDir)
 {
   std::string fpath;
-  fpath += this->GetFullName(config, false);
-  fpath += ".framework/Versions/";
-  fpath += this->GetFrameworkVersion();
-  fpath += "/";
+  fpath += this->GetOutputName(config, false);
+  fpath += ".framework";
+  if(!rootDir)
+    {
+    fpath += "/Versions/";
+    fpath += this->GetFrameworkVersion();
+    }
+  return fpath;
+}
+
+//----------------------------------------------------------------------------
+std::string cmTarget::GetCFBundleDirectory(const char* config,
+                                           bool contentOnly)
+{
+  std::string fpath;
+  fpath += this->GetOutputName(config, false);
+  fpath += ".";
+  const char *ext = this->GetProperty("BUNDLE_EXTENSION");
+  if (!ext)
+    {
+    ext = "bundle";
+    }
+  fpath += ext;
+  fpath += "/Contents";
+  if(!contentOnly)
+    fpath += "/MacOS";
+  return fpath;
+}
+
+//----------------------------------------------------------------------------
+std::string cmTarget::GetAppBundleDirectory(const char* config,
+                                            bool contentOnly)
+{
+  std::string fpath = this->GetFullName(config, false);
+  fpath += ".app/Contents";
+  if(!contentOnly)
+    fpath += "/MacOS";
   return fpath;
 }
 
 //----------------------------------------------------------------------------
 std::string cmTarget::BuildMacContentDirectory(const std::string& base,
                                                const char* config,
-                                               bool includeMacOS)
+                                               bool contentOnly)
 {
   std::string fpath = base;
   if(this->IsAppBundleOnApple())
     {
-    fpath += this->GetFullName(config, false);
-    fpath += ".app/Contents/";
-    if(includeMacOS)
-      fpath += "MacOS/";
+    fpath += this->GetAppBundleDirectory(config, contentOnly);
     }
   if(this->IsFrameworkOnApple())
     {
-    fpath += this->GetFrameworkDirectory(config);
+    fpath += this->GetFrameworkDirectory(config, contentOnly);
     }
   if(this->IsCFBundleOnApple())
     {
-    fpath += this->GetFullName(config, false);
-    fpath += ".";
-    const char *ext = this->GetProperty("BUNDLE_EXTENSION");
-    if (!ext)
-      {
-      ext = "bundle";
-      }
-    fpath += ext;
-    fpath += "/Contents/";
-    if(includeMacOS)
-      fpath += "MacOS/";
+    fpath += this->GetCFBundleDirectory(config, contentOnly);
     }
   return fpath;
 }
 
 //----------------------------------------------------------------------------
 std::string cmTarget::GetMacContentDirectory(const char* config,
-                                             bool implib,
-                                             bool includeMacOS)
+                                             bool implib)
 {
   // Start with the output directory for the target.
   std::string fpath = this->GetDirectory(config, implib);
   fpath += "/";
-  fpath = this->BuildMacContentDirectory(fpath, config, includeMacOS);
+  bool contentOnly = true;
+  if(this->IsFrameworkOnApple())
+    {
+    // additional files with a framework go into the version specific
+    // directory
+    contentOnly = false;
+    }
+  fpath = this->BuildMacContentDirectory(fpath, config, contentOnly);
   return fpath;
 }
 

+ 20 - 13
Source/cmTarget.h

@@ -412,10 +412,8 @@ public:
   /** Return true if builtin chrpath will work for this target */
   bool IsChrpathUsed(const char* config);
 
-  std::string GetInstallNameDirForBuildTree(const char* config,
-                                            bool for_xcode = false);
-  std::string GetInstallNameDirForInstallTree(const char* config,
-                                              bool for_xcode = false);
+  std::string GetInstallNameDirForBuildTree(const char* config);
+  std::string GetInstallNameDirForInstallTree();
 
   cmComputeLinkInformation* GetLinkInformation(const char* config,
                                                cmTarget *head = 0);
@@ -467,6 +465,10 @@ public:
   /** Return whether this target is an executable Bundle on Apple.  */
   bool IsAppBundleOnApple();
 
+  /** Return whether this target is an executable Bundle, a framework
+      or CFBundle on Apple.  */
+  bool IsBundleOnApple();
+
   /** Return the framework version string.  Undefined if
       IsFrameworkOnApple returns false.  */
   std::string GetFrameworkVersion();
@@ -481,21 +483,21 @@ public:
       directory.  */
   bool UsesDefaultOutputDir(const char* config, bool implib);
 
-  /** Append to @a base the mac content directory and return it. */
-  std::string BuildMacContentDirectory(const std::string& base,
-                                       const char* config = 0,
-                                       bool includeMacOS = true);
-
   /** @return the mac content directory for this target. */
-  std::string GetMacContentDirectory(const char* config = 0,
-                                     bool implib = false,
-                                     bool includeMacOS = true);
+  std::string GetMacContentDirectory(const char* config,
+                                     bool implib);
 
   /** @return whether this target have a well defined output file name. */
   bool HaveWellDefinedOutputFiles();
 
   /** @return the Mac framework directory without the base. */
-  std::string GetFrameworkDirectory(const char* config = 0);
+  std::string GetFrameworkDirectory(const char* config, bool rootDir);
+
+  /** @return the Mac CFBundle directory without the base */
+  std::string GetCFBundleDirectory(const char* config, bool contentOnly);
+
+  /** @return the Mac App directory without the base */
+  std::string GetAppBundleDirectory(const char* config, bool contentOnly);
 
   std::vector<std::string> GetIncludeDirectories(const char *config);
   void InsertInclude(const cmValueWithOrigin &entry,
@@ -601,6 +603,11 @@ private:
       the same as GetFullName.  */
   std::string NormalGetRealName(const char* config);
 
+  /** Append to @a base the mac content directory and return it. */
+  std::string BuildMacContentDirectory(const std::string& base,
+                                       const char* config,
+                                       bool contentOnly);
+
 private:
   std::string Name;
   std::vector<cmCustomCommand> PreBuildCommands;

+ 1 - 2
Tests/BundleUtilities/CMakeLists.txt

@@ -12,8 +12,7 @@ add_library(shared2 SHARED shared2.cpp shared2.h)
 
 # a framework library
 add_library(framework SHARED framework.cpp framework.h)
-# TODO: fix problems with local frameworks without rpaths
-#set_target_properties(framework PROPERTIES FRAMEWORK 1)
+set_target_properties(framework PROPERTIES FRAMEWORK 1)
 
 # make sure rpaths are not helping BundleUtilities or the executables
 set_target_properties(shared shared2 framework PROPERTIES