CMake/Source/cmOSXBundleGenerator.cxx
Stephen Kelly c34968a9aa Port some of the generator API to cmGeneratorTarget.
Just enough to reach the BuildMacContentDirectory method and the
NeedRelinkBeforeInstall methods.

In the future, those methods can be moved to cmGeneratorTarget.
2013-11-22 15:06:25 +01:00

234 lines
7.6 KiB
C++

/*============================================================================
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(cmGeneratorTarget* target,
const char* configName)
: Target(target->Target)
, Makefile(target->Target->GetMakefile())
, LocalGenerator(Makefile->GetLocalGenerator())
, ConfigName(configName)
, MacContentFolders(0)
{
if (this->MustSkip())
return;
}
//----------------------------------------------------------------------------
bool cmOSXBundleGenerator::MustSkip()
{
return !this->Target->HaveWellDefinedOutputFiles();
}
//----------------------------------------------------------------------------
void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName,
std::string& outpath)
{
if (this->MustSkip())
return;
// Compute bundle directory names.
std::string out = outpath;
out += "/";
out += this->Target->GetAppBundleDirectory(this->ConfigName, false);
cmSystemTools::MakeDirectory(out.c_str());
this->Makefile->AddCMakeOutputFile(out);
std::string newoutpath = out;
// Configure the Info.plist file. Note that it needs the executable name
// to be set.
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);
outpath = newoutpath;
}
//----------------------------------------------------------------------------
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 = newoutpath;
plist += "/Resources/Info.plist";
std::string name = cmSystemTools::GetFilenameName(targetName);
this->LocalGenerator->GenerateFrameworkInfoPList(this->Target,
name.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;
// Make foo.framework/Versions
std::string versions = contentdir;
versions += "Versions";
cmSystemTools::MakeDirectory(versions.c_str());
// Make foo.framework/Versions/version
cmSystemTools::MakeDirectory(newoutpath.c_str());
// Current -> version
oldName = frameworkVersion;
newName = versions;
newName += "/Current";
cmSystemTools::RemoveFile(newName.c_str());
cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
this->Makefile->AddCMakeOutputFile(newName);
// foo -> Versions/Current/foo
oldName = "Versions/Current/";
oldName += name;
newName = contentdir;
newName += name;
cmSystemTools::RemoveFile(newName.c_str());
cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
this->Makefile->AddCMakeOutputFile(newName);
// Resources -> Versions/Current/Resources
if(this->MacContentFolders->find("Resources") !=
this->MacContentFolders->end())
{
oldName = "Versions/Current/Resources";
newName = contentdir;
newName += "Resources";
cmSystemTools::RemoveFile(newName.c_str());
cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
this->Makefile->AddCMakeOutputFile(newName);
}
// Headers -> Versions/Current/Headers
if(this->MacContentFolders->find("Headers") !=
this->MacContentFolders->end())
{
oldName = "Versions/Current/Headers";
newName = contentdir;
newName += "Headers";
cmSystemTools::RemoveFile(newName.c_str());
cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
this->Makefile->AddCMakeOutputFile(newName);
}
// PrivateHeaders -> Versions/Current/PrivateHeaders
if(this->MacContentFolders->find("PrivateHeaders") !=
this->MacContentFolders->end())
{
oldName = "Versions/Current/PrivateHeaders";
newName = contentdir;
newName += "PrivateHeaders";
cmSystemTools::RemoveFile(newName.c_str());
cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
this->Makefile->AddCMakeOutputFile(newName);
}
}
//----------------------------------------------------------------------------
void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName,
const std::string& root)
{
if (this->MustSkip())
return;
// Compute bundle directory names.
std::string out = root;
out += "/";
out += this->Target->GetCFBundleDirectory(this->ConfigName, false);
cmSystemTools::MakeDirectory(out.c_str());
this->Makefile->AddCMakeOutputFile(out);
// Configure the Info.plist file. Note that it needs the executable name
// to be set.
std::string plist =
this->Target->GetCFBundleDirectory(this->ConfigName, true);
plist += "/Info.plist";
this->LocalGenerator->GenerateAppleInfoPList(this->Target,
targetName.c_str(),
plist.c_str());
this->Makefile->AddCMakeOutputFile(plist);
}
//----------------------------------------------------------------------------
void
cmOSXBundleGenerator::
GenerateMacOSXContentStatements(std::vector<cmSourceFile*> const& sources,
MacOSXContentGeneratorType* generator)
{
if (this->MustSkip())
return;
for(std::vector<cmSourceFile*>::const_iterator
si = sources.begin(); si != sources.end(); ++si)
{
cmTarget::SourceFileFlags tsFlags =
this->Target->GetTargetSourceFileFlags(*si);
if(tsFlags.Type != cmTarget::SourceFileTypeNormal)
{
(*generator)(**si, tsFlags.MacFolder);
}
}
}
//----------------------------------------------------------------------------
std::string
cmOSXBundleGenerator::InitMacOSXContentDirectory(const char* pkgloc)
{
// Construct the full path to the content subdirectory.
std::string macdir =
this->Target->GetMacContentDirectory(this->ConfigName,
/*implib*/ false);
macdir += "/";
macdir += pkgloc;
cmSystemTools::MakeDirectory(macdir.c_str());
// Record use of this content location. Only the first level
// directory is needed.
{
std::string loc = pkgloc;
loc = loc.substr(0, loc.find('/'));
this->MacContentFolders->insert(loc);
}
return macdir;
}