|
|
|
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
|
|
file Copyright.txt or https://cmake.org/licensing for details. */
|
|
|
|
#include "cmOSXBundleGenerator.h"
|
|
|
|
|
|
|
|
#include <cassert>
|
|
|
|
|
|
|
|
#include "cmGeneratorTarget.h"
|
|
|
|
#include "cmLocalGenerator.h"
|
|
|
|
#include "cmMakefile.h"
|
|
|
|
#include "cmStateTypes.h"
|
|
|
|
#include "cmStringAlgorithms.h"
|
|
|
|
#include "cmSystemTools.h"
|
|
|
|
#include "cmTarget.h"
|
|
|
|
#include "cmValue.h"
|
|
|
|
|
|
|
|
class cmSourceFile;
|
|
|
|
|
|
|
|
cmOSXBundleGenerator::cmOSXBundleGenerator(cmGeneratorTarget* target)
|
|
|
|
: GT(target)
|
|
|
|
, Makefile(target->Target->GetMakefile())
|
|
|
|
, LocalGenerator(target->GetLocalGenerator())
|
|
|
|
{
|
|
|
|
if (this->MustSkip()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cmOSXBundleGenerator::MustSkip()
|
|
|
|
{
|
|
|
|
return !this->GT->HaveWellDefinedOutputFiles();
|
|
|
|
}
|
|
|
|
|
|
|
|
void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName,
|
|
|
|
std::string& outpath,
|
|
|
|
const std::string& config)
|
|
|
|
{
|
|
|
|
if (this->MustSkip()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute bundle directory names.
|
|
|
|
std::string out = cmStrCat(
|
|
|
|
outpath, '/',
|
|
|
|
this->GT->GetAppBundleDirectory(config, cmGeneratorTarget::FullLevel));
|
|
|
|
cmSystemTools::MakeDirectory(out);
|
|
|
|
this->Makefile->AddCMakeOutputFile(out);
|
|
|
|
|
|
|
|
// Configure the Info.plist file. Note that it needs the executable name
|
|
|
|
// to be set.
|
|
|
|
std::string plist = cmStrCat(
|
|
|
|
outpath, '/',
|
|
|
|
this->GT->GetAppBundleDirectory(config, cmGeneratorTarget::ContentLevel),
|
|
|
|
"/Info.plist");
|
|
|
|
this->LocalGenerator->GenerateAppleInfoPList(this->GT, targetName, plist);
|
|
|
|
this->Makefile->AddCMakeOutputFile(plist);
|
|
|
|
outpath = out;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cmOSXBundleGenerator::CreateFramework(
|
|
|
|
const std::string& targetName, const std::string& outpath,
|
|
|
|
const std::string& config, const cmOSXBundleGenerator::SkipParts& skipParts)
|
|
|
|
{
|
|
|
|
if (this->MustSkip()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(this->MacContentFolders);
|
|
|
|
|
|
|
|
// Compute the location of the top-level foo.framework directory.
|
|
|
|
std::string contentdir = cmStrCat(
|
|
|
|
outpath, '/',
|
|
|
|
this->GT->GetFrameworkDirectory(config, cmGeneratorTarget::ContentLevel),
|
|
|
|
'/');
|
|
|
|
|
|
|
|
std::string newoutpath = outpath + "/" +
|
|
|
|
this->GT->GetFrameworkDirectory(config, cmGeneratorTarget::FullLevel);
|
|
|
|
|
|
|
|
std::string frameworkVersion = this->GT->GetFrameworkVersion();
|
|
|
|
|
|
|
|
std::string name = cmSystemTools::GetFilenameName(targetName);
|
|
|
|
if (!skipParts.InfoPlist) {
|
|
|
|
// Configure the Info.plist file
|
|
|
|
std::string plist = newoutpath;
|
|
|
|
if (!this->Makefile->PlatformIsAppleEmbedded()) {
|
|
|
|
// Put the Info.plist file into the Resources directory.
|
|
|
|
this->MacContentFolders->insert("Resources");
|
|
|
|
plist += "/Resources";
|
|
|
|
}
|
|
|
|
plist += "/Info.plist";
|
|
|
|
this->LocalGenerator->GenerateFrameworkInfoPList(this->GT, name, plist);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate Versions directory only for MacOSX frameworks
|
|
|
|
if (this->Makefile->PlatformIsAppleEmbedded()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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 = cmStrCat(contentdir, "Versions");
|
|
|
|
cmSystemTools::MakeDirectory(versions);
|
|
|
|
|
|
|
|
// Make foo.framework/Versions/version
|
|
|
|
cmSystemTools::MakeDirectory(newoutpath);
|
|
|
|
|
|
|
|
// Current -> version
|
|
|
|
oldName = frameworkVersion;
|
|
|
|
newName = cmStrCat(versions, "/Current");
|
|
|
|
cmSystemTools::RemoveFile(newName);
|
|
|
|
cmSystemTools::CreateSymlink(oldName, newName);
|
|
|
|
this->Makefile->AddCMakeOutputFile(newName);
|
|
|
|
|
|
|
|
// foo -> Versions/Current/foo
|
|
|
|
oldName = cmStrCat("Versions/Current/", name);
|
|
|
|
newName = cmStrCat(contentdir, name);
|
|
|
|
cmSystemTools::RemoveFile(newName);
|
|
|
|
cmSystemTools::CreateSymlink(oldName, newName);
|
|
|
|
this->Makefile->AddCMakeOutputFile(newName);
|
|
|
|
|
|
|
|
if (!skipParts.TextStubs) {
|
|
|
|
// foo.tbd -> Versions/Current/foo.tbd
|
|
|
|
cmValue tbdSuffix =
|
|
|
|
this->Makefile->GetDefinition("CMAKE_APPLE_IMPORT_FILE_SUFFIX");
|
|
|
|
oldName = cmStrCat("Versions/Current/", name, tbdSuffix);
|
|
|
|
newName = cmStrCat(contentdir, name, tbdSuffix);
|
|
|
|
cmSystemTools::RemoveFile(newName);
|
|
|
|
cmSystemTools::CreateSymlink(oldName, newName);
|
|
|
|
this->Makefile->AddCMakeOutputFile(newName);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Resources -> Versions/Current/Resources
|
|
|
|
if (this->MacContentFolders->find("Resources") !=
|
|
|
|
this->MacContentFolders->end()) {
|
|
|
|
oldName = "Versions/Current/Resources";
|
|
|
|
newName = cmStrCat(contentdir, "Resources");
|
|
|
|
cmSystemTools::RemoveFile(newName);
|
|
|
|
cmSystemTools::CreateSymlink(oldName, newName);
|
|
|
|
this->Makefile->AddCMakeOutputFile(newName);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Headers -> Versions/Current/Headers
|
|
|
|
if (this->MacContentFolders->find("Headers") !=
|
|
|
|
this->MacContentFolders->end()) {
|
|
|
|
oldName = "Versions/Current/Headers";
|
|
|
|
newName = cmStrCat(contentdir, "Headers");
|
|
|
|
cmSystemTools::RemoveFile(newName);
|
|
|
|
cmSystemTools::CreateSymlink(oldName, newName);
|
|
|
|
this->Makefile->AddCMakeOutputFile(newName);
|
|
|
|
}
|
|
|
|
|
|
|
|
// PrivateHeaders -> Versions/Current/PrivateHeaders
|
|
|
|
if (this->MacContentFolders->find("PrivateHeaders") !=
|
|
|
|
this->MacContentFolders->end()) {
|
|
|
|
oldName = "Versions/Current/PrivateHeaders";
|
|
|
|
newName = cmStrCat(contentdir, "PrivateHeaders");
|
|
|
|
cmSystemTools::RemoveFile(newName);
|
|
|
|
cmSystemTools::CreateSymlink(oldName, newName);
|
|
|
|
this->Makefile->AddCMakeOutputFile(newName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName,
|
|
|
|
const std::string& root,
|
|
|
|
const std::string& config)
|
|
|
|
{
|
|
|
|
if (this->MustSkip()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute bundle directory names.
|
|
|
|
std::string out = cmStrCat(
|
|
|
|
root, '/',
|
|
|
|
this->GT->GetCFBundleDirectory(config, cmGeneratorTarget::FullLevel));
|
|
|
|
cmSystemTools::MakeDirectory(out);
|
|
|
|
this->Makefile->AddCMakeOutputFile(out);
|
|
|
|
|
|
|
|
// Configure the Info.plist file. Note that it needs the executable name
|
|
|
|
// to be set.
|
|
|
|
std::string plist = cmStrCat(
|
|
|
|
root, '/',
|
|
|
|
this->GT->GetCFBundleDirectory(config, cmGeneratorTarget::ContentLevel),
|
|
|
|
"/Info.plist");
|
|
|
|
std::string name = cmSystemTools::GetFilenameName(targetName);
|
|
|
|
this->LocalGenerator->GenerateAppleInfoPList(this->GT, name, plist);
|
|
|
|
this->Makefile->AddCMakeOutputFile(plist);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cmOSXBundleGenerator::GenerateMacOSXContentStatements(
|
|
|
|
std::vector<cmSourceFile const*> const& sources,
|
|
|
|
MacOSXContentGeneratorType* generator, const std::string& config)
|
|
|
|
{
|
|
|
|
if (this->MustSkip()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (cmSourceFile const* source : sources) {
|
|
|
|
cmGeneratorTarget::SourceFileFlags tsFlags =
|
|
|
|
this->GT->GetTargetSourceFileFlags(source);
|
|
|
|
if (tsFlags.Type != cmGeneratorTarget::SourceFileTypeNormal) {
|
|
|
|
(*generator)(*source, tsFlags.MacFolder, config);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string cmOSXBundleGenerator::InitMacOSXContentDirectory(
|
|
|
|
const char* pkgloc, const std::string& config)
|
|
|
|
{
|
|
|
|
// Construct the full path to the content subdirectory.
|
|
|
|
|
|
|
|
std::string macdir = cmStrCat(this->GT->GetMacContentDirectory(
|
|
|
|
config, cmStateEnums::RuntimeBinaryArtifact),
|
|
|
|
'/', pkgloc);
|
|
|
|
cmSystemTools::MakeDirectory(macdir);
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|