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 #12263 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;
// The library's soname. if(this->IsFrameworkOnApple())
this->ComputeVersionedName(soName, prefix, base, suffix, {
name, soversion); realName = prefix;
realName += "Versions/";
// The library's real name on disk. realName += this->GetFrameworkVersion();
this->ComputeVersionedName(realName, prefix, base, suffix, realName += "/";
name, version); realName += base;
soName = realName;
}
else
{
// The library's soname.
this->ComputeVersionedName(soName, prefix, base, suffix,
name, soversion);
// The library's real name on disk.
this->ComputeVersionedName(realName, prefix, base, suffix,
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,59 +5917,86 @@ 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";
fpath += this->GetFrameworkVersion(); if(!rootDir)
fpath += "/"; {
fpath += "/Versions/";
fpath += this->GetFrameworkVersion();
}
return fpath;
}
//----------------------------------------------------------------------------
std::string cmTarget::GetCFBundleDirectory(const char* config,
bool contentOnly)
{
std::string fpath;
fpath += this->GetOutputName(config, false);
fpath += ".";
const char *ext = this->GetProperty("BUNDLE_EXTENSION");
if (!ext)
{
ext = "bundle";
}
fpath += ext;
fpath += "/Contents";
if(!contentOnly)
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; return fpath;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
std::string cmTarget::BuildMacContentDirectory(const std::string& base, std::string cmTarget::BuildMacContentDirectory(const std::string& base,
const char* config, const char* config,
bool includeMacOS) bool contentOnly)
{ {
std::string fpath = base; std::string fpath = base;
if(this->IsAppBundleOnApple()) if(this->IsAppBundleOnApple())
{ {
fpath += this->GetFullName(config, false); fpath += this->GetAppBundleDirectory(config, contentOnly);
fpath += ".app/Contents/";
if(includeMacOS)
fpath += "MacOS/";
} }
if(this->IsFrameworkOnApple()) if(this->IsFrameworkOnApple())
{ {
fpath += this->GetFrameworkDirectory(config); fpath += this->GetFrameworkDirectory(config, contentOnly);
} }
if(this->IsCFBundleOnApple()) if(this->IsCFBundleOnApple())
{ {
fpath += this->GetFullName(config, false); fpath += this->GetCFBundleDirectory(config, contentOnly);
fpath += ".";
const char *ext = this->GetProperty("BUNDLE_EXTENSION");
if (!ext)
{
ext = "bundle";
}
fpath += ext;
fpath += "/Contents/";
if(includeMacOS)
fpath += "MacOS/";
} }
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