Commit a1b80334 authored by Nicolas Despres's avatar Nicolas Despres Committed by Peter Kümmel
Browse files

Re-factor OS X bundle and framework generation.

parent 3ba74ad9
......@@ -219,6 +219,8 @@ SET(SRCS
cmMakefileExecutableTargetGenerator.cxx
cmMakefileLibraryTargetGenerator.cxx
cmMakefileUtilityTargetGenerator.cxx
cmOSXBundleGenerator.cxx
cmOSXBundleGenerator.h
cmNewLineStyle.h
cmNewLineStyle.cxx
cmOrderDirectories.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());
}
......@@ -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
......@@ -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())
{
......
......@@ -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
......@@ -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());
}
}
......@@ -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
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2012 Nicolas Despres <nicolas.despres@gmail.com>
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.
<