Browse Source

Re-factor OS X bundle and framework generation.

Nicolas Despres 13 years ago
parent
commit
a1b803349b

+ 2 - 0
Source/CMakeLists.txt

@@ -219,6 +219,8 @@ SET(SRCS
   cmMakefileExecutableTargetGenerator.cxx
   cmMakefileLibraryTargetGenerator.cxx
   cmMakefileUtilityTargetGenerator.cxx
+  cmOSXBundleGenerator.cxx
+  cmOSXBundleGenerator.h
   cmNewLineStyle.h
   cmNewLineStyle.cxx
   cmOrderDirectories.cxx

+ 16 - 30
Source/cmMakefileExecutableTargetGenerator.cxx

@@ -18,24 +18,31 @@
 #include "cmSourceFile.h"
 #include "cmTarget.h"
 #include "cmake.h"
+#include "cmOSXBundleGenerator.h"
 
 //----------------------------------------------------------------------------
 cmMakefileExecutableTargetGenerator
 ::cmMakefileExecutableTargetGenerator(cmTarget* target):
-  cmMakefileTargetGenerator(target)
+  cmMakefileTargetGenerator(target),
+  OSXBundleGenerator(0)
 {
   this->CustomCommandDriver = OnDepends;
   this->Target->GetExecutableNames(
     this->TargetNameOut, this->TargetNameReal, this->TargetNameImport,
     this->TargetNamePDB, this->ConfigName);
 
-  if(this->Target->IsAppBundleOnApple())
-    {
-    this->MacContentDirectory = this->Target->GetDirectory(this->ConfigName);
-    this->MacContentDirectory += "/";
-    this->MacContentDirectory += this->TargetNameOut;
-    this->MacContentDirectory += ".app/Contents/";
-    }
+  this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target,
+                                                      this->TargetNameOut,
+                                                      this->ConfigName);
+  this->MacContentDirectory =
+    this->OSXBundleGenerator->GetMacContentDirectory();
+}
+
+//----------------------------------------------------------------------------
+cmMakefileExecutableTargetGenerator
+::~cmMakefileExecutableTargetGenerator()
+{
+  delete this->OSXBundleGenerator;
 }
 
 //----------------------------------------------------------------------------
@@ -100,7 +107,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
   outpath += "/";
   if(this->Target->IsAppBundleOnApple())
     {
-    this->CreateAppBundle(targetName, outpath);
+    this->OSXBundleGenerator->CreateAppBundle(targetName, outpath);
     }
   std::string outpathImp;
   if(relink)
@@ -440,24 +447,3 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
                           exeCleanFiles.begin(),
                           exeCleanFiles.end());
 }
-
-//----------------------------------------------------------------------------
-void
-cmMakefileExecutableTargetGenerator::CreateAppBundle(std::string& targetName,
-                                                     std::string& outpath)
-{
-  // Compute bundle directory names.
-  outpath = this->MacContentDirectory;
-  outpath += "MacOS";
-  cmSystemTools::MakeDirectory(outpath.c_str());
-  this->Makefile->AddCMakeOutputFile(outpath.c_str());
-  outpath += "/";
-
-  // Configure the Info.plist file.  Note that it needs the executable name
-  // to be set.
-  std::string plist = this->MacContentDirectory + "Info.plist";
-  this->LocalGenerator->GenerateAppleInfoPList(this->Target,
-                                               targetName.c_str(),
-                                               plist.c_str());
-  this->Makefile->AddCMakeOutputFile(plist.c_str());
-}

+ 6 - 1
Source/cmMakefileExecutableTargetGenerator.h

@@ -14,10 +14,13 @@
 
 #include "cmMakefileTargetGenerator.h"
 
+class cmOSXBundleGenerator;
+
 class cmMakefileExecutableTargetGenerator: public cmMakefileTargetGenerator
 {
 public:
   cmMakefileExecutableTargetGenerator(cmTarget* target);
+  virtual ~cmMakefileExecutableTargetGenerator();
 
   /* the main entry point for this class. Writes the Makefiles associated
      with this target */
@@ -25,7 +28,9 @@ public:
 
 protected:
   virtual void WriteExecutableRule(bool relink);
-  void CreateAppBundle(std::string& targetName, std::string& outpath);
+
+private:
+  cmOSXBundleGenerator* OSXBundleGenerator;
 };
 
 #endif

+ 17 - 114
Source/cmMakefileLibraryTargetGenerator.cxx

@@ -18,13 +18,15 @@
 #include "cmSourceFile.h"
 #include "cmTarget.h"
 #include "cmake.h"
+#include "cmOSXBundleGenerator.h"
 
 #include <memory> // auto_ptr
 
 //----------------------------------------------------------------------------
 cmMakefileLibraryTargetGenerator
 ::cmMakefileLibraryTargetGenerator(cmTarget* target):
-  cmMakefileTargetGenerator(target)
+  cmMakefileTargetGenerator(target),
+  OSXBundleGenerator(0)
 {
   if(this->Target->IsCFBundleOnApple())
     {
@@ -37,30 +39,19 @@ cmMakefileLibraryTargetGenerator
     this->TargetNameOut, this->TargetNameSO, this->TargetNameReal,
     this->TargetNameImport, this->TargetNamePDB, this->ConfigName);
 
-  if(this->Target->IsFrameworkOnApple())
-    {
-    this->FrameworkVersion = this->Target->GetFrameworkVersion();
-    this->MacContentDirectory = this->Target->GetDirectory(this->ConfigName);
-    this->MacContentDirectory += "/";
-    this->MacContentDirectory += this->TargetNameOut;
-    this->MacContentDirectory += ".framework/Versions/";
-    this->MacContentDirectory += this->FrameworkVersion;
-    this->MacContentDirectory += "/";
-    }
-  else if(this->Target->IsCFBundleOnApple())
-    {
-    this->MacContentDirectory = this->Target->GetDirectory(this->ConfigName);
-    this->MacContentDirectory += "/";
-    this->MacContentDirectory += this->TargetNameOut;
-    this->MacContentDirectory += ".";
-    const char *ext = this->Target->GetProperty("BUNDLE_EXTENSION");
-    if (!ext)
-      {
-      ext = "bundle";
-      }
-    this->MacContentDirectory += ext;
-    this->MacContentDirectory += "/Contents/";
-    }
+  this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target,
+                                                      this->TargetNameOut,
+                                                      this->ConfigName);
+  this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
+  this->MacContentDirectory =
+    this->OSXBundleGenerator->GetMacContentDirectory();
+}
+
+//----------------------------------------------------------------------------
+cmMakefileLibraryTargetGenerator
+::~cmMakefileLibraryTargetGenerator()
+{
+  delete this->OSXBundleGenerator;
 }
 
 //----------------------------------------------------------------------------
@@ -258,94 +249,6 @@ void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink)
   this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
 }
 
-//----------------------------------------------------------------------------
-void
-cmMakefileLibraryTargetGenerator
-::CreateFramework(std::string const& targetName)
-{
-  // Configure the Info.plist file into the Resources directory.
-  this->MacContentFolders.insert("Resources");
-  std::string plist = this->MacContentDirectory + "Resources/Info.plist";
-  this->LocalGenerator->GenerateFrameworkInfoPList(this->Target,
-                                                   targetName.c_str(),
-                                                   plist.c_str());
-
-  // TODO: Use the cmMakefileTargetGenerator::ExtraFiles vector to
-  // drive rules to create these files at build time.
-  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;
-  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());
-
-  // Current -> version
-  oldName = this->FrameworkVersion;
-  newName = versions;
-  newName += "/Current";
-  cmSystemTools::RemoveFile(newName.c_str());
-  cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
-  this->Makefile->AddCMakeOutputFile(newName.c_str());
-
-  // foo -> Versions/Current/foo
-  oldName = "Versions/Current/";
-  oldName += this->TargetNameOut;
-  newName = top;
-  newName += this->TargetNameOut;
-  cmSystemTools::RemoveFile(newName.c_str());
-  cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
-  this->Makefile->AddCMakeOutputFile(newName.c_str());
-
-  // Resources -> Versions/Current/Resources
-  if(this->MacContentFolders.find("Resources") !=
-     this->MacContentFolders.end())
-    {
-    oldName = "Versions/Current/Resources";
-    newName = top;
-    newName += "Resources";
-    cmSystemTools::RemoveFile(newName.c_str());
-    cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
-    this->Makefile->AddCMakeOutputFile(newName.c_str());
-    }
-
-  // Headers -> Versions/Current/Headers
-  if(this->MacContentFolders.find("Headers") !=
-     this->MacContentFolders.end())
-    {
-    oldName = "Versions/Current/Headers";
-    newName = top;
-    newName += "Headers";
-    cmSystemTools::RemoveFile(newName.c_str());
-    cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
-    this->Makefile->AddCMakeOutputFile(newName.c_str());
-    }
-
-  // PrivateHeaders -> Versions/Current/PrivateHeaders
-  if(this->MacContentFolders.find("PrivateHeaders") !=
-     this->MacContentFolders.end())
-    {
-    oldName = "Versions/Current/PrivateHeaders";
-    newName = top;
-    newName += "PrivateHeaders";
-    cmSystemTools::RemoveFile(newName.c_str());
-    cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
-    this->Makefile->AddCMakeOutputFile(newName.c_str());
-    }
-}
-
 //----------------------------------------------------------------------------
 void
 cmMakefileLibraryTargetGenerator::CreateCFBundle(std::string& targetName,
@@ -419,7 +322,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
   if(this->Target->IsFrameworkOnApple())
     {
     outpath = this->MacContentDirectory;
-    this->CreateFramework(targetName);
+    this->OSXBundleGenerator->CreateFramework(targetName);
     }
   else if(this->Target->IsCFBundleOnApple())
     {

+ 6 - 1
Source/cmMakefileLibraryTargetGenerator.h

@@ -14,11 +14,14 @@
 
 #include "cmMakefileTargetGenerator.h"
 
+class cmOSXBundleGenerator;
+
 class cmMakefileLibraryTargetGenerator:
   public cmMakefileTargetGenerator
 {
 public:
   cmMakefileLibraryTargetGenerator(cmTarget* target);
+  virtual ~cmMakefileLibraryTargetGenerator();
 
   /* the main entry point for this class. Writes the Makefiles associated
      with this target */
@@ -33,7 +36,6 @@ protected:
                          bool relink);
   // MacOSX Framework support methods
   void WriteFrameworkRules(bool relink);
-  void CreateFramework(std::string const& targetName);
   void CreateCFBundle(std::string& targetName, std::string& outpath);
 
   // Store the computd framework version for OS X Frameworks.
@@ -41,6 +43,9 @@ protected:
 
   void AppendOSXVerFlag(std::string& flags, const char* lang,
                         const char* name, bool so);
+
+private:
+  cmOSXBundleGenerator* OSXBundleGenerator;
 };
 
 #endif

+ 10 - 147
Source/cmNinjaNormalTargetGenerator.cxx

@@ -16,6 +16,7 @@
 #include "cmSourceFile.h"
 #include "cmGeneratedFileStream.h"
 #include "cmMakefile.h"
+#include "cmOSXBundleGenerator.h"
 
 #include <assert.h>
 #include <algorithm>
@@ -34,8 +35,8 @@ cmNinjaNormalTargetGenerator(cmTarget* target)
   , TargetNameImport()
   , TargetNamePDB()
   , TargetLinkLanguage(0)
-  , MacContentDirectory()
-  , FrameworkVersion()
+  , OSXBundleGenerator(0)
+  , MacContentFolders()
 {
   this->TargetLinkLanguage = target->GetLinkerLanguage(this->GetConfigName());
   if (target->GetType() == cmTarget::EXECUTABLE)
@@ -59,43 +60,15 @@ cmNinjaNormalTargetGenerator(cmTarget* target)
     EnsureDirectoryExists(target->GetDirectory(this->GetConfigName()));
     }
 
-  // TODO: Factor with the cmMakefileExecutableTargetGenerator constructor.
-  if(target->IsAppBundleOnApple())
-    {
-    this->MacContentDirectory = target->GetDirectory(this->GetConfigName());
-    this->MacContentDirectory += "/";
-    this->MacContentDirectory += this->TargetNameOut;
-    this->MacContentDirectory += ".app/Contents/";
-    }
-  // TODO: Factor with the cmMakefileLibraryTargetGenerator constructor.
-  else if(target->IsFrameworkOnApple())
-    {
-    this->FrameworkVersion = target->GetFrameworkVersion();
-    this->MacContentDirectory = target->GetDirectory(this->GetConfigName());
-    this->MacContentDirectory += "/";
-    this->MacContentDirectory += this->TargetNameOut;
-    this->MacContentDirectory += ".framework/Versions/";
-    this->MacContentDirectory += this->FrameworkVersion;
-    this->MacContentDirectory += "/";
-    }
-  else if(target->IsCFBundleOnApple())
-    {
-    this->MacContentDirectory = target->GetDirectory(this->GetConfigName());
-    this->MacContentDirectory += "/";
-    this->MacContentDirectory += this->TargetNameOut;
-    this->MacContentDirectory += ".";
-    const char *ext = target->GetProperty("BUNDLE_EXTENSION");
-    if (!ext)
-      {
-      ext = "bundle";
-      }
-    this->MacContentDirectory += ext;
-    this->MacContentDirectory += "/Contents/";
-    }
+  this->OSXBundleGenerator = new cmOSXBundleGenerator(target,
+                                                      this->TargetNameOut,
+                                                      this->GetConfigName());
+  this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
 }
 
 cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator()
 {
+  delete this->OSXBundleGenerator;
 }
 
 void cmNinjaNormalTargetGenerator::Generate()
@@ -392,7 +365,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
     {
     // Create the app bundle
     std::string outpath;
-    this->CreateAppBundle(this->TargetNameOut, outpath);
+    this->OSXBundleGenerator->CreateAppBundle(this->TargetNameOut, outpath);
 
     // Calculate the output path
     targetOutput = outpath + this->TargetNameOut;
@@ -403,7 +376,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
   else if (this->GetTarget()->IsFrameworkOnApple())
     {
     // Create the library framework.
-    this->CreateFramework(this->TargetNameOut);
+    this->OSXBundleGenerator->CreateFramework(this->TargetNameOut);
     }
 
   // Write comments.
@@ -631,113 +604,3 @@ void cmNinjaNormalTargetGenerator::WriteObjectLibStatement()
   this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(),
                                              this->GetTarget());
 }
-
-// TODO: Factor with cmMakefileExecutableTargetGenerator::CreateAppBundle().
-void
-cmNinjaNormalTargetGenerator::CreateAppBundle(const std::string& targetName,
-                                              std::string& outpath)
-{
-  // Compute bundle directory names.
-  outpath = this->MacContentDirectory;
-  outpath += "MacOS";
-  cmSystemTools::MakeDirectory(outpath.c_str());
-  this->GetMakefile()->AddCMakeOutputFile(outpath.c_str());
-  outpath += "/";
-
-  // Configure the Info.plist file.  Note that it needs the executable name
-  // to be set.
-  std::string plist = this->MacContentDirectory + "Info.plist";
-  this->GetLocalGenerator()->GenerateAppleInfoPList(this->GetTarget(),
-                                                    targetName.c_str(),
-                                                    plist.c_str());
-  this->GetMakefile()->AddCMakeOutputFile(plist.c_str());
-}
-
-// TODO: Factor with cmMakefileLibraryTargetGenerator::CreateFramework().
-void
-cmNinjaNormalTargetGenerator::CreateFramework(std::string const& targetName)
-{
-  // Create the Resources directory.
-  std::string resources = this->MacContentDirectory + "Resources/";
-  cmSystemTools::MakeDirectory(resources.c_str());
-
-  // Configure the Info.plist file into the Resources directory.
-  std::set<cmStdString> macContentFolders;
-  macContentFolders.insert("Resources");
-  std::string plist = resources + "Info.plist";
-  this->GetLocalGenerator()->GenerateFrameworkInfoPList(this->GetTarget(),
-                                                        targetName.c_str(),
-                                                        plist.c_str());
-
-  // TODO: Use the cmMakefileTargetGenerator::ExtraFiles vector to
-  // drive rules to create these files at build time.
-  std::string oldName;
-  std::string newName;
-
-  // Compute the location of the top-level foo.framework directory.
-  std::string top = this->GetTarget()->GetDirectory(this->GetConfigName());
-  top += "/";
-  top += this->TargetNameOut;
-  top += ".framework/";
-
-  // Make foo.framework/Versions
-  std::string versions = top;
-  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());
-
-  // Current -> version
-  oldName = this->FrameworkVersion;
-  newName = versions;
-  newName += "/Current";
-  cmSystemTools::RemoveFile(newName.c_str());
-  cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
-  this->GetMakefile()->AddCMakeOutputFile(newName.c_str());
-
-  // foo -> Versions/Current/foo
-  oldName = "Versions/Current/";
-  oldName += this->TargetNameOut;
-  newName = top;
-  newName += this->TargetNameOut;
-  cmSystemTools::RemoveFile(newName.c_str());
-  cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
-  this->GetMakefile()->AddCMakeOutputFile(newName.c_str());
-
-  // Resources -> Versions/Current/Resources
-  if(macContentFolders.find("Resources") != macContentFolders.end())
-    {
-    oldName = "Versions/Current/Resources";
-    newName = top;
-    newName += "Resources";
-    cmSystemTools::RemoveFile(newName.c_str());
-    cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
-    this->GetMakefile()->AddCMakeOutputFile(newName.c_str());
-    }
-
-  // Headers -> Versions/Current/Headers
-  if(macContentFolders.find("Headers") != macContentFolders.end())
-    {
-    oldName = "Versions/Current/Headers";
-    newName = top;
-    newName += "Headers";
-    cmSystemTools::RemoveFile(newName.c_str());
-    cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
-    this->GetMakefile()->AddCMakeOutputFile(newName.c_str());
-    }
-
-  // PrivateHeaders -> Versions/Current/PrivateHeaders
-  if(macContentFolders.find("PrivateHeaders") != macContentFolders.end())
-    {
-    oldName = "Versions/Current/PrivateHeaders";
-    newName = top;
-    newName += "PrivateHeaders";
-    cmSystemTools::RemoveFile(newName.c_str());
-    cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
-    this->GetMakefile()->AddCMakeOutputFile(newName.c_str());
-    }
-}

+ 6 - 4
Source/cmNinjaNormalTargetGenerator.h

@@ -15,8 +15,12 @@
 
 #  include "cmNinjaTargetGenerator.h"
 #  include "cmNinjaTypes.h"
+#  include "cmStandardIncludes.h"
+
+#  include <set>
 
 class cmSourceFile;
+class cmOSXBundleGenerator;
 
 class cmNinjaNormalTargetGenerator : public cmNinjaTargetGenerator
 {
@@ -34,8 +38,6 @@ private:
   void WriteLinkStatement();
   void WriteObjectLibStatement();
   std::vector<std::string> ComputeLinkCmd();
-  void CreateAppBundle(const std::string& targetName, std::string& outpath);
-  void CreateFramework(std::string const& targetName);
 
 private:
   // Target name info.
@@ -45,8 +47,8 @@ private:
   std::string TargetNameImport;
   std::string TargetNamePDB;
   const char *TargetLinkLanguage;
-  std::string MacContentDirectory;
-  std::string FrameworkVersion;
+  cmOSXBundleGenerator* OSXBundleGenerator;
+  std::set<cmStdString> MacContentFolders;
 };
 
 #endif // ! cmNinjaNormalTargetGenerator_h

+ 171 - 0
Source/cmOSXBundleGenerator.cxx

@@ -0,0 +1,171 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2012 Nicolas Despres <[email protected]>
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+#include "cmOSXBundleGenerator.h"
+#include "cmMakefile.h"
+#include "cmTarget.h"
+#include "cmLocalGenerator.h"
+
+#include <cassert>
+
+cmOSXBundleGenerator::
+cmOSXBundleGenerator(cmTarget* target,
+                     std::string targetNameOut,
+                     const char* configName)
+ : Target(target)
+ , Makefile(target->GetMakefile())
+ , LocalGenerator(this->Makefile->GetLocalGenerator())
+ , TargetNameOut(targetNameOut)
+ , ConfigName(configName)
+ , MacContentDirectory()
+ , FrameworkVersion()
+ , MacContentFolders(0)
+{
+  if(this->Target->IsAppBundleOnApple())
+    {
+    this->MacContentDirectory = this->Target->GetDirectory(this->ConfigName);
+    this->MacContentDirectory += "/";
+    this->MacContentDirectory += this->TargetNameOut;
+    this->MacContentDirectory += ".app/Contents/";
+    }
+  else if(this->Target->IsFrameworkOnApple())
+    {
+    this->FrameworkVersion = this->Target->GetFrameworkVersion();
+    this->MacContentDirectory = this->Target->GetDirectory(this->ConfigName);
+    this->MacContentDirectory += "/";
+    this->MacContentDirectory += this->TargetNameOut;
+    this->MacContentDirectory += ".framework/Versions/";
+    this->MacContentDirectory += this->FrameworkVersion;
+    this->MacContentDirectory += "/";
+    }
+  else if(this->Target->IsCFBundleOnApple())
+    {
+    this->MacContentDirectory = this->Target->GetDirectory(this->ConfigName);
+    this->MacContentDirectory += "/";
+    this->MacContentDirectory += this->TargetNameOut;
+    this->MacContentDirectory += ".";
+    const char *ext = this->Target->GetProperty("BUNDLE_EXTENSION");
+    if (!ext)
+      {
+      ext = "bundle";
+      }
+    this->MacContentDirectory += ext;
+    this->MacContentDirectory += "/Contents/";
+    }
+}
+
+//----------------------------------------------------------------------------
+void cmOSXBundleGenerator::CreateAppBundle(std::string& targetName,
+                                           std::string& outpath)
+{
+  // Compute bundle directory names.
+  outpath = this->MacContentDirectory;
+  outpath += "MacOS";
+  cmSystemTools::MakeDirectory(outpath.c_str());
+  this->Makefile->AddCMakeOutputFile(outpath.c_str());
+  outpath += "/";
+
+  // Configure the Info.plist file.  Note that it needs the executable name
+  // to be set.
+  std::string plist = this->MacContentDirectory + "Info.plist";
+  this->LocalGenerator->GenerateAppleInfoPList(this->Target,
+                                               targetName.c_str(),
+                                               plist.c_str());
+  this->Makefile->AddCMakeOutputFile(plist.c_str());
+}
+
+//----------------------------------------------------------------------------
+void cmOSXBundleGenerator::CreateFramework(std::string const& targetName)
+{
+  assert(this->MacContentFolders);
+
+  // Configure the Info.plist file into the Resources directory.
+  this->MacContentFolders->insert("Resources");
+  std::string plist = this->MacContentDirectory + "Resources/Info.plist";
+  this->LocalGenerator->GenerateFrameworkInfoPList(this->Target,
+                                                   targetName.c_str(),
+                                                   plist.c_str());
+
+  // TODO: Use the cmMakefileTargetGenerator::ExtraFiles vector to
+  // drive rules to create these files at build time.
+  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;
+  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());
+
+  // Current -> version
+  oldName = this->FrameworkVersion;
+  newName = versions;
+  newName += "/Current";
+  cmSystemTools::RemoveFile(newName.c_str());
+  cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
+  this->Makefile->AddCMakeOutputFile(newName.c_str());
+
+  // foo -> Versions/Current/foo
+  oldName = "Versions/Current/";
+  oldName += this->TargetNameOut;
+  newName = top;
+  newName += this->TargetNameOut;
+  cmSystemTools::RemoveFile(newName.c_str());
+  cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
+  this->Makefile->AddCMakeOutputFile(newName.c_str());
+
+  // Resources -> Versions/Current/Resources
+  if(this->MacContentFolders->find("Resources") !=
+     this->MacContentFolders->end())
+    {
+    oldName = "Versions/Current/Resources";
+    newName = top;
+    newName += "Resources";
+    cmSystemTools::RemoveFile(newName.c_str());
+    cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
+    this->Makefile->AddCMakeOutputFile(newName.c_str());
+    }
+
+  // Headers -> Versions/Current/Headers
+  if(this->MacContentFolders->find("Headers") !=
+     this->MacContentFolders->end())
+    {
+    oldName = "Versions/Current/Headers";
+    newName = top;
+    newName += "Headers";
+    cmSystemTools::RemoveFile(newName.c_str());
+    cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
+    this->Makefile->AddCMakeOutputFile(newName.c_str());
+    }
+
+  // PrivateHeaders -> Versions/Current/PrivateHeaders
+  if(this->MacContentFolders->find("PrivateHeaders") !=
+     this->MacContentFolders->end())
+    {
+    oldName = "Versions/Current/PrivateHeaders";
+    newName = top;
+    newName += "PrivateHeaders";
+    cmSystemTools::RemoveFile(newName.c_str());
+    cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
+    this->Makefile->AddCMakeOutputFile(newName.c_str());
+    }
+}

+ 52 - 0
Source/cmOSXBundleGenerator.h

@@ -0,0 +1,52 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2012 Nicolas Despres <[email protected]>
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+#ifndef cmOSXBundleGenerator_h
+#define cmOSXBundleGenerator_h
+
+#include "cmStandardIncludes.h"
+
+#include <string>
+#include <set>
+
+class cmTarget;
+class cmMakefile;
+class cmLocalGenerator;
+
+class cmOSXBundleGenerator
+{
+public:
+  cmOSXBundleGenerator(cmTarget* target,
+                       std::string targetNameOut,
+                       const char* configName);
+
+  void CreateAppBundle(std::string& targetName, std::string& outpath);
+  void CreateFramework(std::string const& targetName);
+
+  std::string GetMacContentDirectory() const
+  { return this->MacContentDirectory; }
+  std::string GetFrameworkVersion() const
+  { return this->FrameworkVersion; }
+  void SetMacContentFolders(std::set<cmStdString>* macContentFolders)
+  { this->MacContentFolders = macContentFolders; }
+
+private:
+  cmTarget* Target;
+  cmMakefile* Makefile;
+  cmLocalGenerator* LocalGenerator;
+  std::string TargetNameOut;
+  const char* ConfigName;
+  std::string MacContentDirectory;
+  std::string FrameworkVersion;
+  std::set<cmStdString>* MacContentFolders;
+};
+
+#endif

+ 1 - 0
bootstrap

@@ -220,6 +220,7 @@ CMAKE_CXX_SOURCES="\
   cmMakefileLibraryTargetGenerator \
   cmMakefileTargetGenerator \
   cmMakefileUtilityTargetGenerator \
+  cmOSXBundleGenerator \
   cmNewLineStyle \
   cmBootstrapCommands \
   cmCommands \