BUG: Correct Mac OS X framework behavior

- Place the built library in foo.framework/Versions/A/foo
  - Do not create unused content symlinks (like PrivateHeaders)
  - Do not use VERSION/SOVERSION properties for frameworks
  - Make cmTarget::GetDirectory return by value
  - Remove the foo.framework part from cmTarget::GetDirectory
  - Correct install_name construction and conversion on install
  - Fix MACOSX_PACKAGE_LOCATION under Xcode to use the
    Versions/<version> directory for frameworks
  - Update the Framework test to try these things
This commit is contained in:
Brad King 2008-04-08 00:06:47 -04:00
parent 5c3a5daaf1
commit 67834f2d53
12 changed files with 303 additions and 281 deletions

View File

@ -611,20 +611,10 @@ void cmComputeLinkInformation::AddItem(std::string const& item, cmTarget* tgt)
std::string lib = tgt->GetFullPath(config, implib, true); std::string lib = tgt->GetFullPath(config, implib, true);
this->Depends.push_back(lib); this->Depends.push_back(lib);
if(tgt->IsFrameworkOnApple())
{
// Frameworks on OS X need only the framework directory to
// link.
std::string fw = tgt->GetDirectory(config, implib);
this->AddFrameworkItem(fw);
}
else
{
this->AddTargetItem(lib, tgt); this->AddTargetItem(lib, tgt);
this->AddLibraryRuntimeInfo(lib, tgt); this->AddLibraryRuntimeInfo(lib, tgt);
} }
} }
}
else else
{ {
// This is not a CMake target. Use the name given. // This is not a CMake target. Use the name given.
@ -1023,7 +1013,7 @@ void cmComputeLinkInformation::AddTargetItem(std::string const& item,
// For compatibility with CMake 2.4 include the item's directory in // For compatibility with CMake 2.4 include the item's directory in
// the linker search path. // the linker search path.
if(this->OldLinkDirMode && if(this->OldLinkDirMode && !target->IsFrameworkOnApple() &&
this->OldLinkDirMask.find(cmSystemTools::GetFilenamePath(item)) == this->OldLinkDirMask.find(cmSystemTools::GetFilenamePath(item)) ==
this->OldLinkDirMask.end()) this->OldLinkDirMask.end())
{ {

View File

@ -803,8 +803,14 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
copyFilesBuildPhase->AddAttribute("dstSubfolderSpec", copyFilesBuildPhase->AddAttribute("dstSubfolderSpec",
this->CreateString("6")); this->CreateString("6"));
cmOStringStream ostr; cmOStringStream ostr;
if ( mit->first != "MacOS" ) if (cmtarget.IsFrameworkOnApple())
{ {
// dstPath in frameworks is relative to Versions/<version>
ostr << mit->first;
}
else if ( mit->first != "MacOS" )
{
// dstPath in bundles is relative to Contents/MacOS
ostr << "../" << mit->first.c_str(); ostr << "../" << mit->first.c_str();
} }
copyFilesBuildPhase->AddAttribute("dstPath", copyFilesBuildPhase->AddAttribute("dstPath",
@ -1357,11 +1363,6 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
target.GetType() == cmTarget::EXECUTABLE) target.GetType() == cmTarget::EXECUTABLE)
{ {
std::string pndir = target.GetDirectory(); std::string pndir = target.GetDirectory();
if(target.IsFrameworkOnApple())
{
pndir += "/..";
pndir = cmSystemTools::CollapseFullPath(pndir.c_str());
}
buildSettings->AddAttribute("SYMROOT", buildSettings->AddAttribute("SYMROOT",
this->CreateString(pndir.c_str())); this->CreateString(pndir.c_str()));
buildSettings->AddAttribute("EXECUTABLE_PREFIX", buildSettings->AddAttribute("EXECUTABLE_PREFIX",
@ -1429,17 +1430,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
fileType = "wrapper.framework"; fileType = "wrapper.framework";
productType = "com.apple.product-type.framework"; productType = "com.apple.product-type.framework";
const char* version = target.GetProperty("FRAMEWORK_VERSION"); std::string version = target.GetFrameworkVersion();
if(!version)
{
version = target.GetProperty("VERSION");
}
if(!version)
{
version = "A";
}
buildSettings->AddAttribute("FRAMEWORK_VERSION", buildSettings->AddAttribute("FRAMEWORK_VERSION",
this->CreateString(version)); this->CreateString(version.c_str()));
} }
else else
{ {
@ -1649,18 +1642,7 @@ 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); install_name_dir = target.GetInstallNameDirForBuildTree(configName, true);
if(target.GetPropertyAsBool("FRAMEWORK"))
{
if(install_name_dir.find(".framework") != install_name_dir.npos)
{
install_name_dir = install_name_dir + "/..";
install_name_dir =
cmSystemTools::CollapseFullPath(install_name_dir.c_str());
//std::cerr << "new install name " << install_name_dir << "\n";
}
}
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
@ -2867,22 +2849,6 @@ cmGlobalXCodeGenerator
if(this->XcodeVersion > 20) if(this->XcodeVersion > 20)
{ {
if(config) if(config)
{
if(dir.find(".framework") != dir.npos)
{
// Remove trailing slashes (so that the rfind does not find the one at
// the very end...!)
//
cmSystemTools::ConvertToUnixSlashes(dir);
std::string::size_type pos = dir.rfind("/");
std::string framework = dir.substr(pos);
std::string newDir = dir.substr(0, pos);
newDir += "/";
newDir += config;
dir = newDir;
dir += framework;
}
else
{ {
dir += prefix; dir += prefix;
dir += config; dir += config;
@ -2890,7 +2856,6 @@ cmGlobalXCodeGenerator
} }
} }
} }
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
std::string cmGlobalXCodeGenerator::LookupFlags(const char* varNamePrefix, std::string cmGlobalXCodeGenerator::LookupFlags(const char* varNamePrefix,

View File

@ -239,16 +239,17 @@ cmInstallTargetGenerator
// Compute the build tree location of the framework directory // Compute the build tree location of the framework directory
std::string from1 = fromDirConfig; std::string from1 = fromDirConfig;
// Remove trailing slashes... so that from1 ends with ".framework": from1 += targetName;
// from1 += ".framework";
cmSystemTools::ConvertToUnixSlashes(from1);
files.push_back(from1); files.push_back(from1);
type = cmTarget::INSTALL_DIRECTORY; type = cmTarget::INSTALL_DIRECTORY;
// Need to apply install_name_tool and stripping to binary // Need to apply install_name_tool and stripping to binary
// inside framework. // inside framework.
toInstallPath += ".framework/"; toInstallPath += ".framework/Versions/";
toInstallPath += this->Target->GetFrameworkVersion();
toInstallPath += "/";
toInstallPath += this->GetInstallFilename(this->Target, config, toInstallPath += this->GetInstallFilename(this->Target, config,
NameNormal); NameNormal);

View File

@ -668,7 +668,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
if ( this->Version >= 8 ) if ( this->Version >= 8 )
{ {
// Check the filesystem type where the target will be written. // Check the filesystem type where the target will be written.
if(cmLVS6G_IsFAT(target.GetDirectory(configName))) if(cmLVS6G_IsFAT(target.GetDirectory(configName).c_str()))
{ {
// Add a flag telling the manifest tool to use a workaround // Add a flag telling the manifest tool to use a workaround
// for FAT32 file systems, which can cause an empty manifest // for FAT32 file systems, which can cause an empty manifest

View File

@ -39,20 +39,11 @@ cmMakefileLibraryTargetGenerator
if(this->Target->IsFrameworkOnApple()) if(this->Target->IsFrameworkOnApple())
{ {
if(const char* fversion = this->Target->GetProperty("FRAMEWORK_VERSION")) this->FrameworkVersion = this->Target->GetFrameworkVersion();
{
this->FrameworkVersion = fversion;
}
else if(const char* tversion = this->Target->GetProperty("VERSION"))
{
this->FrameworkVersion = tversion;
}
else
{
this->FrameworkVersion = "A";
}
this->MacContentDirectory = this->Target->GetDirectory(); this->MacContentDirectory = this->Target->GetDirectory();
this->MacContentDirectory += "/Versions/"; this->MacContentDirectory += "/";
this->MacContentDirectory += this->TargetNameOut;
this->MacContentDirectory += ".framework/Versions/";
this->MacContentDirectory += this->FrameworkVersion; this->MacContentDirectory += this->FrameworkVersion;
this->MacContentDirectory += "/"; this->MacContentDirectory += "/";
} }
@ -244,50 +235,82 @@ void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmMakefileLibraryTargetGenerator::CreateFramework( void cmMakefileLibraryTargetGenerator::CreateFramework()
std::string& targetName,
std::string& outpath)
{ {
std::string symlink; // TODO: Use the cmMakefileTargetGenerator::ExtraFiles vector to
std::string symlink2; // drive rules to create these files at build time.
std::string oldName;
std::string newName;
// Compute the location of the top-level foo.framework directory.
std::string top = this->Target->GetDirectory();
top += "/";
top += this->TargetNameOut;
top += ".framework/";
// Make foo.framework/Versions // Make foo.framework/Versions
std::string dir = outpath; std::string versions = top;
dir += "Versions"; versions += "Versions";
cmSystemTools::MakeDirectory(dir.c_str()); cmSystemTools::MakeDirectory(versions.c_str());
std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
// cd foo.framework to setup symlinks with relative paths // Make foo.framework/Versions/version
cmSystemTools::ChangeDirectory((outpath+"Versions").c_str()); std::string version = versions;
version += "/";
version += this->FrameworkVersion;
cmSystemTools::MakeDirectory(version.c_str());
// Current -> version // Current -> version
symlink = this->FrameworkVersion; oldName = this->FrameworkVersion;
symlink2 = "Current"; newName = versions;
cmSystemTools::RemoveFile("Current"); newName += "/Current";
cmSystemTools::CreateSymlink(symlink.c_str(), symlink2.c_str()); cmSystemTools::RemoveFile(newName.c_str());
this->Makefile->AddCMakeOutputFile((outpath + "Versions/Current").c_str()); cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
// change to top level of framework to create next set of symlinks this->Makefile->AddCMakeOutputFile(newName.c_str());
cmSystemTools::ChangeDirectory(outpath.c_str());
// foo -> Versions/Current/foo // foo -> Versions/Current/foo
symlink = "Versions/Current/"; oldName = "Versions/Current/";
symlink += targetName; oldName += this->TargetNameOut;
symlink2 = targetName; newName = top;
cmSystemTools::CreateSymlink(symlink.c_str(), symlink2.c_str()); newName += this->TargetNameOut;
this->Makefile->AddCMakeOutputFile((outpath + targetName).c_str()); cmSystemTools::RemoveFile(newName.c_str());
cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
this->Makefile->AddCMakeOutputFile(newName.c_str());
// Resources -> Versions/Current/Resources // Resources -> Versions/Current/Resources
symlink = "Versions/Current/Resources"; if(this->MacContentFolders.find("Resources") !=
symlink2 = "Resources"; this->MacContentFolders.end())
cmSystemTools::CreateSymlink(symlink.c_str(), symlink2.c_str()); {
this->Makefile->AddCMakeOutputFile((outpath + "Resources").c_str()); oldName = "Versions/Current/Resources";
newName = top;
newName += "Resources";
cmSystemTools::RemoveFile(newName.c_str());
cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
this->Makefile->AddCMakeOutputFile(newName.c_str());
}
// Headers -> Versions/Current/Headers // Headers -> Versions/Current/Headers
symlink = "Versions/Current/Headers"; if(this->MacContentFolders.find("Headers") !=
symlink2 = "Headers"; this->MacContentFolders.end())
cmSystemTools::CreateSymlink(symlink.c_str(), symlink2.c_str()); {
this->Makefile->AddCMakeOutputFile((outpath + "Headers").c_str()); oldName = "Versions/Current/Headers";
newName = top;
newName += "Headers";
cmSystemTools::RemoveFile(newName.c_str());
cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
this->Makefile->AddCMakeOutputFile(newName.c_str());
}
// PrivateHeaders -> Versions/Current/PrivateHeaders // PrivateHeaders -> Versions/Current/PrivateHeaders
symlink = "Versions/Current/PrivateHeaders"; if(this->MacContentFolders.find("PrivateHeaders") !=
symlink2 = "PrivateHeaders"; this->MacContentFolders.end())
cmSystemTools::CreateSymlink(symlink.c_str(), symlink2.c_str()); {
this->Makefile->AddCMakeOutputFile((outpath + "PrivateHeaders").c_str()); oldName = "Versions/Current/PrivateHeaders";
// go back to where we were newName = top;
cmSystemTools::ChangeDirectory(cwd.c_str()); newName += "PrivateHeaders";
cmSystemTools::RemoveFile(newName.c_str());
cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
this->Makefile->AddCMakeOutputFile(newName.c_str());
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -354,7 +377,12 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
// Construct the full path version of the names. // Construct the full path version of the names.
std::string outpath; std::string outpath;
std::string outpathImp; std::string outpathImp;
if(relink) if(this->Target->IsFrameworkOnApple())
{
outpath = this->MacContentDirectory;
this->CreateFramework();
}
else if(relink)
{ {
outpath = this->Makefile->GetStartOutputDirectory(); outpath = this->Makefile->GetStartOutputDirectory();
outpath += cmake::GetCMakeFilesDirectory(); outpath += cmake::GetCMakeFilesDirectory();
@ -379,12 +407,6 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
} }
} }
// If we're creating a framework, place the output into a framework directory
if(this->Target->IsFrameworkOnApple())
{
this->CreateFramework(targetName, outpath);
}
std::string targetFullPath = outpath + targetName; std::string targetFullPath = outpath + targetName;
std::string targetFullPathPDB = outpath + targetNamePDB; std::string targetFullPathPDB = outpath + targetNamePDB;
std::string targetFullPathSO = outpath + targetNameSO; std::string targetFullPathSO = outpath + targetNameSO;

View File

@ -37,8 +37,7 @@ protected:
bool relink); bool relink);
// MacOSX Framework support methods // MacOSX Framework support methods
void WriteFrameworkRules(bool relink); void WriteFrameworkRules(bool relink);
void CreateFramework(std::string& targetName, void CreateFramework();
std::string& outpath);
// Store the computd framework version for OS X Frameworks. // Store the computd framework version for OS X Frameworks.
std::string FrameworkVersion; std::string FrameworkVersion;

View File

@ -334,6 +334,9 @@ void cmMakefileTargetGenerator::WriteMacOSXContentRules(cmSourceFile& source,
macdir += pkgloc; macdir += pkgloc;
cmSystemTools::MakeDirectory(macdir.c_str()); cmSystemTools::MakeDirectory(macdir.c_str());
// Record use of this content location.
this->MacContentFolders.insert(pkgloc);
// Get the input file location. // Get the input file location.
std::string input = source.GetFullPath(); std::string input = source.GetFullPath();
@ -1456,11 +1459,8 @@ void cmMakefileTargetGenerator
if(cmTarget* tgt = if(cmTarget* tgt =
this->GlobalGenerator->FindTarget(0, lib->first.c_str())) this->GlobalGenerator->FindTarget(0, lib->first.c_str()))
{ {
if(const char* location = const char* config = this->LocalGenerator->ConfigurationName.c_str();
tgt->GetLocation(this->LocalGenerator->ConfigurationName.c_str())) depends.push_back(tgt->GetFullPath(config, false));
{
depends.push_back(location);
}
} }
// depend on full path libs as well // depend on full path libs as well
else if(cmSystemTools::FileIsFullPath(lib->first.c_str())) else if(cmSystemTools::FileIsFullPath(lib->first.c_str()))

View File

@ -204,6 +204,7 @@ protected:
// Mac OS X content info. // Mac OS X content info.
std::string MacContentDirectory; std::string MacContentDirectory;
std::set<cmStdString> MacContentFolders;
// Target-wide Fortran module output directory. // Target-wide Fortran module output directory.
bool FortranModuleDirectoryComputed; bool FortranModuleDirectoryComputed;

View File

@ -1626,44 +1626,32 @@ void cmTarget::MarkAsImported()
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
const char* cmTarget::GetDirectory(const char* config, bool implib) std::string cmTarget::GetDirectory(const char* config, bool implib)
{ {
if (this->IsImported()) if (this->IsImported())
{ {
return this->ImportedGetDirectory(config, implib); // Return the directory from which the target is imported.
return
cmSystemTools::GetFilenamePath(
this->ImportedGetFullPath(config, implib));
} }
else else
{ {
return this->NormalGetDirectory(config, implib); // Return the directory in which the target will be built.
}
}
//----------------------------------------------------------------------------
const char* cmTarget::ImportedGetDirectory(const char* config, bool implib)
{
this->Directory =
cmSystemTools::GetFilenamePath(
this->ImportedGetFullPath(config, implib));
return this->Directory.c_str();
}
//----------------------------------------------------------------------------
const char* cmTarget::NormalGetDirectory(const char* config, bool implib)
{
if(config && *config) if(config && *config)
{ {
// Do not create the directory when config is given:
this->Directory = this->GetOutputDir(implib);
// Add the configuration's subdirectory. // Add the configuration's subdirectory.
std::string dir = this->GetOutputDir(implib);
this->Makefile->GetLocalGenerator()->GetGlobalGenerator()-> this->Makefile->GetLocalGenerator()->GetGlobalGenerator()->
AppendDirectoryForConfig("/", config, "", this->Directory); AppendDirectoryForConfig("/", config, "", dir);
return this->Directory.c_str(); return dir;
} }
else else
{ {
return this->GetOutputDir(implib); return this->GetOutputDir(implib);
} }
} }
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
const char* cmTarget::GetLocation(const char* config) const char* cmTarget::GetLocation(const char* config)
@ -1688,22 +1676,31 @@ const char* cmTarget::ImportedGetLocation(const char* config)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
const char* cmTarget::NormalGetLocation(const char* config) const char* cmTarget::NormalGetLocation(const char* config)
{ {
this->Location = this->GetDirectory(config); // Handle the configuration-specific case first.
if(config)
{
this->Location = this->GetFullPath(config, false);
return this->Location.c_str();
}
// Now handle the deprecated build-time configuration location.
this->Location = this->GetDirectory();
if(!this->Location.empty()) if(!this->Location.empty())
{ {
this->Location += "/"; this->Location += "/";
} }
if(!config)
{
// No specific configuration was given so it will not appear on
// the result of GetDirectory. Add a name here to be replaced at
// build time.
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 += cfgid;
this->Location += "/"; this->Location += "/";
} }
if(this->IsFrameworkOnApple())
{
this->Location += this->GetFullName(config, false);
this->Location += ".framework/Versions/";
this->Location += this->GetFrameworkVersion();
this->Location += "/";
} }
this->Location += this->GetFullName(config, false); this->Location += this->GetFullName(config, false);
return this->Location.c_str(); return this->Location.c_str();
@ -2203,6 +2200,14 @@ std::string cmTarget::NormalGetFullPath(const char* config, bool implib,
std::string fpath = this->GetDirectory(config, implib); std::string fpath = this->GetDirectory(config, implib);
fpath += "/"; fpath += "/";
if(this->IsFrameworkOnApple())
{
fpath += this->GetFullName(config, false);
fpath += ".framework/Versions/";
fpath += this->GetFrameworkVersion();
fpath += "/";
}
// Add the full name of the target. // Add the full name of the target.
if(implib) if(implib)
{ {
@ -2474,7 +2479,8 @@ void cmTarget::GetLibraryNamesInternal(std::string& name,
const char* version = this->GetProperty("VERSION"); const char* version = this->GetProperty("VERSION");
const char* soversion = this->GetProperty("SOVERSION"); const char* soversion = this->GetProperty("SOVERSION");
if((type != cmTarget::SHARED_LIBRARY && type != cmTarget::MODULE_LIBRARY) || if((type != cmTarget::SHARED_LIBRARY && type != cmTarget::MODULE_LIBRARY) ||
!this->Makefile->GetDefinition(sonameFlag.c_str())) !this->Makefile->GetDefinition(sonameFlag.c_str()) ||
this->IsFrameworkOnApple())
{ {
// Versioning is supported only for shared libraries and modules, // Versioning is supported only for shared libraries and modules,
// and then only when the platform supports an soname flag. // and then only when the platform supports an soname flag.
@ -2801,13 +2807,14 @@ bool cmTarget::NeedRelinkBeforeInstall()
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
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); return GetInstallNameDirForInstallTree(config, for_xcode);
} }
// Use the build tree directory for the target. // Use the build tree directory for the target.
@ -2817,6 +2824,13 @@ 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->GetFullName(config, false);
dir += ".framework/Versions/";
dir += this->GetFrameworkVersion();
dir += "/";
}
return dir; return dir;
} }
else else
@ -2826,7 +2840,8 @@ std::string cmTarget::GetInstallNameDirForBuildTree(const char* config)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
std::string cmTarget::GetInstallNameDirForInstallTree(const char*) std::string cmTarget::GetInstallNameDirForInstallTree(const char* config,
bool for_xcode)
{ {
// Lookup the target property. // Lookup the target property.
const char* install_name_dir = this->GetProperty("INSTALL_NAME_DIR"); const char* install_name_dir = this->GetProperty("INSTALL_NAME_DIR");
@ -2836,6 +2851,13 @@ std::string cmTarget::GetInstallNameDirForInstallTree(const char*)
{ {
std::string dir = install_name_dir; std::string dir = install_name_dir;
dir += "/"; dir += "/";
if(this->IsFrameworkOnApple() && !for_xcode)
{
dir += this->GetFullName(config, false);
dir += ".framework/Versions/";
dir += this->GetFrameworkVersion();
dir += "/";
}
return dir; return dir;
} }
else else
@ -2845,7 +2867,7 @@ std::string cmTarget::GetInstallNameDirForInstallTree(const char*)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
const char* cmTarget::GetOutputDir(bool implib) std::string cmTarget::GetOutputDir(bool implib)
{ {
// The implib option is only allowed for shared libraries, module // The implib option is only allowed for shared libraries, module
// libraries, and executables. // libraries, and executables.
@ -2879,12 +2901,22 @@ const char* cmTarget::GetOutputDir(bool implib)
msg.c_str()); msg.c_str());
} }
return this->ComputeBaseOutputDir(implib);
}
//----------------------------------------------------------------------------
std::string const& cmTarget::ComputeBaseOutputDir(bool implib)
{
// Select whether we are constructing the directory for the main // Select whether we are constructing the directory for the main
// target or the import library. // target or the import library.
std::string& out = implib? this->OutputDirImplib : this->OutputDir; std::string& out = implib? this->BaseOutputDirImplib : this->BaseOutputDir;
if(out.empty()) // Return immediately if the directory has already been computed.
if(!out.empty())
{ {
return out;
}
// Look for a target property defining the target output directory // Look for a target property defining the target output directory
// based on the target type. // based on the target type.
const char* propertyName = 0; const char* propertyName = 0;
@ -2970,26 +3002,30 @@ const char* cmTarget::GetOutputDir(bool implib)
// Default to the current output directory. // Default to the current output directory.
out = "."; out = ".";
} }
// Convert the output path to a full path in case it is // Convert the output path to a full path in case it is
// specified as a relative path. Treat a relative path as // specified as a relative path. Treat a relative path as
// relative to the current output directory for this makefile. // relative to the current output directory for this makefile.
out = out = (cmSystemTools::CollapseFullPath
cmSystemTools::CollapseFullPath (out.c_str(), this->Makefile->GetStartOutputDirectory()));
(out.c_str(), this->Makefile->GetStartOutputDirectory()); return out;
}
// TODO: Make AppBundle and Framework directory computation in //----------------------------------------------------------------------------
// target consistent. Why do we add the .framework part here for std::string cmTarget::GetFrameworkVersion()
// frameworks but not the .app part for bundles? We should
// probably not add it for either.
if(this->IsFrameworkOnApple())
{ {
out += "/"; if(const char* fversion = this->GetProperty("FRAMEWORK_VERSION"))
out += this->GetFullName(0, implib); {
out += ".framework"; return fversion;
} }
else if(const char* tversion = this->GetProperty("VERSION"))
{
return tversion;
}
else
{
return "A";
} }
return out.c_str();
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View File

@ -253,7 +253,7 @@ public:
configuration name is given then the generator will add its configuration name is given then the generator will add its
subdirectory for that configuration. Otherwise just the canonical subdirectory for that configuration. Otherwise just the canonical
output directory is given. */ output directory is given. */
const char* GetDirectory(const char* config = 0, bool implib = false); std::string GetDirectory(const char* config = 0, bool implib = false);
/** Get the location of the target in the build tree for the given /** Get the location of the target in the build tree for the given
configuration. This location is suitable for use as the LOCATION configuration. This location is suitable for use as the LOCATION
@ -348,8 +348,10 @@ public:
/** Return true if builtin chrpath will work for this target */ /** Return true if builtin chrpath will work for this target */
bool IsChrpathUsed(); bool IsChrpathUsed();
std::string GetInstallNameDirForBuildTree(const char* config); std::string GetInstallNameDirForBuildTree(const char* config,
std::string GetInstallNameDirForInstallTree(const char* config); bool for_xcode = false);
std::string GetInstallNameDirForInstallTree(const char* config,
bool for_xcode = false);
cmComputeLinkInformation* GetLinkInformation(const char* config); cmComputeLinkInformation* GetLinkInformation(const char* config);
@ -384,6 +386,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 the framework version string. Undefined if
IsFrameworkOnApple returns false. */
std::string GetFrameworkVersion();
/** Get a backtrace from the creation of the target. */ /** Get a backtrace from the creation of the target. */
cmListFileBacktrace const& GetBacktrace() const; cmListFileBacktrace const& GetBacktrace() const;
@ -464,16 +470,14 @@ private:
void SetPropertyDefault(const char* property, const char* default_value); void SetPropertyDefault(const char* property, const char* default_value);
// Get the full path to the target output directory. // Get the full path to the target output directory.
const char* GetOutputDir(bool implib); std::string GetOutputDir(bool implib);
std::string const& cmTarget::ComputeBaseOutputDir(bool implib);
const char* ImportedGetLocation(const char* config); const char* ImportedGetLocation(const char* config);
const char* NormalGetLocation(const char* config); const char* NormalGetLocation(const char* config);
std::string GetFullNameImported(const char* config, bool implib); std::string GetFullNameImported(const char* config, bool implib);
const char* ImportedGetDirectory(const char* config, bool implib);
const char* NormalGetDirectory(const char* config, bool implib);
std::string ImportedGetFullPath(const char* config, bool implib); std::string ImportedGetFullPath(const char* config, bool implib);
std::string NormalGetFullPath(const char* config, bool implib, std::string NormalGetFullPath(const char* config, bool implib,
bool realname); bool realname);
@ -500,9 +504,8 @@ private:
bool HaveInstallRule; bool HaveInstallRule;
std::string InstallPath; std::string InstallPath;
std::string RuntimeInstallPath; std::string RuntimeInstallPath;
std::string OutputDir; std::string BaseOutputDir;
std::string OutputDirImplib; std::string BaseOutputDirImplib;
std::string Directory;
std::string Location; std::string Location;
std::string ExportMacro; std::string ExportMacro;
std::set<cmStdString> Utilities; std::set<cmStdString> Utilities;

View File

@ -10,8 +10,11 @@ add_library(foo SHARED
fooNeither.h fooNeither.h
fooBoth.h fooBoth.h
test.lua test.lua
fooDeepPublic.h
)
set_property(SOURCE fooDeepPublic.h
PROPERTY MACOSX_PACKAGE_LOCATION Headers/Deep
) )
set(foo_ver ver4) set(foo_ver ver4)
set_target_properties(foo PROPERTIES set_target_properties(foo PROPERTIES
@ -20,6 +23,7 @@ set_target_properties(foo PROPERTIES
PRIVATE_HEADER "fooPrivate.h;fooBoth.h" PRIVATE_HEADER "fooPrivate.h;fooBoth.h"
PUBLIC_HEADER "foo.h;foo2.h;fooPublic.h;fooBoth.h" PUBLIC_HEADER "foo.h;foo2.h;fooPublic.h;fooBoth.h"
RESOURCE "test.lua" RESOURCE "test.lua"
INSTALL_NAME_DIR "@executable_path/../../../Library/Frameworks"
) )
# fooBoth.h is listed as both public and private... (private wins...) # fooBoth.h is listed as both public and private... (private wins...)
# fooNeither.h is listed as neither public nor private... # fooNeither.h is listed as neither public nor private...

View File

@ -0,0 +1 @@
fooDeepPublic