Refactor how bundles and frameworks are supported.

Make handling of directory separators consistent between
non-bundle and bundle code.

Remove xcode specific flag from cmTarget when getting install_name.

Add (more) consistent convenience functions in cmTarget to get
directories inside of bundles and frameworks to add files to.

This refactor also fixes bug  where frameworks
had the wrong install name when SKIP_BUILD_RPATH.

Also make install_name for frameworks consistent between Makefile
and Xcode generator.
This commit is contained in:
Clinton Stimpson 2013-05-05 20:19:05 -06:00 committed by Brad King
parent 78185f598c
commit 373faae5e1
16 changed files with 229 additions and 169 deletions

View File

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

View File

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

View File

@ -1823,6 +1823,11 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
pndir = target.GetDirectory(configName); pndir = target.GetDirectory(configName);
} }
if(target.IsFrameworkOnApple())
{
pnprefix = "";
}
buildSettings->AddAttribute("EXECUTABLE_PREFIX", buildSettings->AddAttribute("EXECUTABLE_PREFIX",
this->CreateString(pnprefix.c_str())); this->CreateString(pnprefix.c_str()));
buildSettings->AddAttribute("EXECUTABLE_SUFFIX", buildSettings->AddAttribute("EXECUTABLE_SUFFIX",
@ -2156,14 +2161,14 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
if(target.GetType() == cmTarget::SHARED_LIBRARY) if(target.GetType() == cmTarget::SHARED_LIBRARY)
{ {
// Get the install_name directory for the build tree. // 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()) if(install_name_dir.empty())
{ {
// Xcode will not pass the -install_name option at all if INSTALL_PATH // 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 // 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. // link flags to create an install_name with just the library soname.
extraLinkOptions += " -install_name "; extraLinkOptions += " -install_name ";
extraLinkOptions += target.GetFullName(configName); extraLinkOptions += target.GetSOName(configName);
} }
else else
{ {

View File

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

View File

@ -30,11 +30,8 @@ cmMakefileExecutableTargetGenerator
this->TargetNamePDB, this->ConfigName); this->TargetNamePDB, this->ConfigName);
this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target, this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target,
this->TargetNameOut,
this->ConfigName); this->ConfigName);
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); 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. // Construct the full path version of the names.
std::string outpath = this->Target->GetDirectory(this->ConfigName); std::string outpath = this->Target->GetDirectory(this->ConfigName);
outpath += "/";
if(this->Target->IsAppBundleOnApple()) if(this->Target->IsAppBundleOnApple())
{ {
this->OSXBundleGenerator->CreateAppBundle(targetName, outpath); this->OSXBundleGenerator->CreateAppBundle(targetName, outpath);
} }
outpath += "/";
std::string outpathImp; std::string outpathImp;
if(relink) if(relink)
{ {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1655,6 +1655,13 @@ bool cmTarget::IsCFBundleOnApple()
this->GetPropertyAsBool("BUNDLE")); this->GetPropertyAsBool("BUNDLE"));
} }
//----------------------------------------------------------------------------
bool cmTarget::IsBundleOnApple()
{
return this->IsFrameworkOnApple() || this->IsAppBundleOnApple() ||
this->IsCFBundleOnApple();
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
class cmTargetTraceDependencies class cmTargetTraceDependencies
{ {
@ -3264,17 +3271,23 @@ const char* cmTarget::NormalGetLocation(const char* config)
// Now handle the deprecated build-time configuration location. // Now handle the deprecated build-time configuration location.
this->Location = this->GetDirectory(); this->Location = this->GetDirectory();
if(!this->Location.empty())
{
this->Location += "/";
}
const char* cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR"); const char* cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR");
if(cfgid && strcmp(cfgid, ".") != 0) if(cfgid && strcmp(cfgid, ".") != 0)
{ {
this->Location += cfgid;
this->Location += "/"; this->Location += "/";
this->Location += cfgid;
} }
this->Location = this->BuildMacContentDirectory(this->Location, config);
if(this->IsCFBundleOnApple() || this->IsAppBundleOnApple())
{
std::string macdir = this->BuildMacContentDirectory("", config, false);
if(!macdir.empty())
{
this->Location += "/";
this->Location += macdir;
}
}
this->Location += "/";
this->Location += this->GetFullName(config, false); this->Location += this->GetFullName(config, false);
return this->Location.c_str(); return this->Location.c_str();
} }
@ -3876,7 +3889,13 @@ std::string cmTarget::GetFullPath(const char* config, bool implib,
std::string cmTarget::NormalGetFullPath(const char* config, bool implib, std::string cmTarget::NormalGetFullPath(const char* config, bool implib,
bool realname) 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. // Add the full name of the target.
if(implib) if(implib)
@ -4008,10 +4027,13 @@ void cmTarget::GetFullNameInternal(const char* config,
targetSuffix = this->Makefile->GetSafeDefinition(suffixVar); 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()) if(this->IsFrameworkOnApple())
{ {
targetPrefix = 0; fw_prefix = this->GetOutputName(config, false);
fw_prefix += ".framework/";
targetPrefix = fw_prefix.c_str();
targetSuffix = 0; targetSuffix = 0;
} }
@ -4091,13 +4113,24 @@ void cmTarget::GetLibraryNames(std::string& name,
// The library name. // The library name.
name = prefix+base+suffix; name = prefix+base+suffix;
if(this->IsFrameworkOnApple())
{
realName = prefix;
realName += "Versions/";
realName += this->GetFrameworkVersion();
realName += "/";
realName += base;
soName = realName;
}
else
{
// The library's soname. // The library's soname.
this->ComputeVersionedName(soName, prefix, base, suffix, this->ComputeVersionedName(soName, prefix, base, suffix,
name, soversion); name, soversion);
// The library's real name on disk. // The library's real name on disk.
this->ComputeVersionedName(realName, prefix, base, suffix, this->ComputeVersionedName(realName, prefix, base, suffix,
name, version); name, version);
}
// The import library name. // The import library name.
if(this->GetType() == cmTarget::SHARED_LIBRARY || if(this->GetType() == cmTarget::SHARED_LIBRARY ||
@ -4385,14 +4418,13 @@ bool cmTarget::NeedRelinkBeforeInstall(const char* config)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
std::string cmTarget::GetInstallNameDirForBuildTree(const char* config, std::string cmTarget::GetInstallNameDirForBuildTree(const char* config)
bool for_xcode)
{ {
// If building directly for installation then the build tree install_name // If building directly for installation then the build tree install_name
// is the same as the install tree. // is the same as the install tree.
if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"))
{ {
return GetInstallNameDirForInstallTree(config, for_xcode); return GetInstallNameDirForInstallTree();
} }
// Use the build tree directory for the target. // Use the build tree directory for the target.
@ -4402,10 +4434,6 @@ std::string cmTarget::GetInstallNameDirForBuildTree(const char* config,
{ {
std::string dir = this->GetDirectory(config); std::string dir = this->GetDirectory(config);
dir += "/"; dir += "/";
if(this->IsFrameworkOnApple() && !for_xcode)
{
dir += this->GetFrameworkDirectory(config);
}
return dir; return dir;
} }
else else
@ -4415,8 +4443,7 @@ std::string cmTarget::GetInstallNameDirForBuildTree(const char* config,
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
std::string cmTarget::GetInstallNameDirForInstallTree(const char* config, std::string cmTarget::GetInstallNameDirForInstallTree()
bool for_xcode)
{ {
if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
{ {
@ -4432,12 +4459,6 @@ std::string cmTarget::GetInstallNameDirForInstallTree(const char* config,
dir += "/"; dir += "/";
} }
} }
if(this->IsFrameworkOnApple() && !for_xcode)
{
dir += this->GetFrameworkDirectory(config);
}
return dir; return dir;
} }
else else
@ -5896,36 +5917,26 @@ 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; std::string fpath;
fpath += this->GetFullName(config, false); fpath += this->GetOutputName(config, false);
fpath += ".framework/Versions/"; fpath += ".framework";
if(!rootDir)
{
fpath += "/Versions/";
fpath += this->GetFrameworkVersion(); fpath += this->GetFrameworkVersion();
fpath += "/"; }
return fpath; return fpath;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
std::string cmTarget::BuildMacContentDirectory(const std::string& base, std::string cmTarget::GetCFBundleDirectory(const char* config,
const char* config, bool contentOnly)
bool includeMacOS)
{ {
std::string fpath = base; std::string fpath;
if(this->IsAppBundleOnApple()) fpath += this->GetOutputName(config, false);
{
fpath += this->GetFullName(config, false);
fpath += ".app/Contents/";
if(includeMacOS)
fpath += "MacOS/";
}
if(this->IsFrameworkOnApple())
{
fpath += this->GetFrameworkDirectory(config);
}
if(this->IsCFBundleOnApple())
{
fpath += this->GetFullName(config, false);
fpath += "."; fpath += ".";
const char *ext = this->GetProperty("BUNDLE_EXTENSION"); const char *ext = this->GetProperty("BUNDLE_EXTENSION");
if (!ext) if (!ext)
@ -5933,22 +5944,59 @@ std::string cmTarget::BuildMacContentDirectory(const std::string& base,
ext = "bundle"; ext = "bundle";
} }
fpath += ext; fpath += ext;
fpath += "/Contents/"; fpath += "/Contents";
if(includeMacOS) if(!contentOnly)
fpath += "MacOS/"; 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 contentOnly)
{
std::string fpath = base;
if(this->IsAppBundleOnApple())
{
fpath += this->GetAppBundleDirectory(config, contentOnly);
}
if(this->IsFrameworkOnApple())
{
fpath += this->GetFrameworkDirectory(config, contentOnly);
}
if(this->IsCFBundleOnApple())
{
fpath += this->GetCFBundleDirectory(config, contentOnly);
} }
return fpath; return fpath;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
std::string cmTarget::GetMacContentDirectory(const char* config, std::string cmTarget::GetMacContentDirectory(const char* config,
bool implib, bool implib)
bool includeMacOS)
{ {
// Start with the output directory for the target. // Start with the output directory for the target.
std::string fpath = this->GetDirectory(config, implib); std::string fpath = this->GetDirectory(config, implib);
fpath += "/"; 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; return fpath;
} }

View File

@ -407,10 +407,8 @@ public:
/** Return true if builtin chrpath will work for this target */ /** Return true if builtin chrpath will work for this target */
bool IsChrpathUsed(const char* config); bool IsChrpathUsed(const char* config);
std::string GetInstallNameDirForBuildTree(const char* config, std::string GetInstallNameDirForBuildTree(const char* config);
bool for_xcode = false); std::string GetInstallNameDirForInstallTree();
std::string GetInstallNameDirForInstallTree(const char* config,
bool for_xcode = false);
cmComputeLinkInformation* GetLinkInformation(const char* config, cmComputeLinkInformation* GetLinkInformation(const char* config,
cmTarget *head = 0); cmTarget *head = 0);
@ -462,6 +460,10 @@ public:
/** Return whether this target is an executable Bundle on Apple. */ /** Return whether this target is an executable Bundle on Apple. */
bool IsAppBundleOnApple(); 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 /** Return the framework version string. Undefined if
IsFrameworkOnApple returns false. */ IsFrameworkOnApple returns false. */
std::string GetFrameworkVersion(); std::string GetFrameworkVersion();
@ -476,21 +478,21 @@ public:
directory. */ directory. */
bool UsesDefaultOutputDir(const char* config, bool implib); 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. */ /** @return the mac content directory for this target. */
std::string GetMacContentDirectory(const char* config = 0, std::string GetMacContentDirectory(const char* config,
bool implib = false, bool implib);
bool includeMacOS = true);
/** @return whether this target have a well defined output file name. */ /** @return whether this target have a well defined output file name. */
bool HaveWellDefinedOutputFiles(); bool HaveWellDefinedOutputFiles();
/** @return the Mac framework directory without the base. */ /** @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); std::vector<std::string> GetIncludeDirectories(const char *config);
void InsertInclude(const cmValueWithOrigin &entry, void InsertInclude(const cmValueWithOrigin &entry,
@ -597,6 +599,11 @@ private:
the same as GetFullName. */ the same as GetFullName. */
std::string NormalGetRealName(const char* config); 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: private:
std::string Name; std::string Name;
std::vector<cmCustomCommand> PreBuildCommands; std::vector<cmCustomCommand> PreBuildCommands;

View File

@ -12,8 +12,7 @@ add_library(shared2 SHARED shared2.cpp shared2.h)
# a framework library # a framework library
add_library(framework SHARED framework.cpp framework.h) 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 # make sure rpaths are not helping BundleUtilities or the executables
set_target_properties(shared shared2 framework PROPERTIES set_target_properties(shared shared2 framework PROPERTIES