ENH: Finish up the Framework creation code restructuring. Frameworks build and install now. More work needed on the packaging step. See Tests/Framework for example use.

This commit is contained in:
David Cole 2007-10-10 11:06:15 -04:00
parent aa9ba5c3ef
commit 8e4c7b99e1
12 changed files with 377 additions and 175 deletions

View File

@ -1277,6 +1277,7 @@ cmLocalGenerator* cmGlobalGenerator::FindLocalGenerator(const char* start_dir)
} }
//----------------------------------------------------------------------------
cmTarget* cmGlobalGenerator::FindTarget(const char* project, cmTarget* cmGlobalGenerator::FindTarget(const char* project,
const char* name, const char* name,
bool useImportedTargets) bool useImportedTargets)
@ -1318,6 +1319,27 @@ cmTarget* cmGlobalGenerator::FindTarget(const char* project,
return 0; return 0;
} }
//----------------------------------------------------------------------------
bool cmGlobalGenerator::NameResolvesToFramework(const std::string& libname)
{
if(cmSystemTools::IsPathToFramework(libname.c_str()))
{
return true;
}
if(cmTarget* tgt = this->FindTarget(0, libname.c_str(), true))
{
if(tgt->GetType() == cmTarget::SHARED_LIBRARY &&
tgt->GetPropertyAsBool("FRAMEWORK"))
{
return true;
}
}
return false;
}
//----------------------------------------------------------------------------
inline std::string removeQuotes(const std::string& s) inline std::string removeQuotes(const std::string& s)
{ {
if(s[0] == '\"' && s[s.size()-1] == '\"') if(s[0] == '\"' && s[s.size()-1] == '\"')

View File

@ -187,6 +187,10 @@ public:
const char* name, const char* name,
bool useImportedTargets); bool useImportedTargets);
/** Determine if a name resolves to a framework on disk or a built target
that is a framework. */
bool NameResolvesToFramework(const std::string& libname);
/** If check to see if the target is linked to by any other /** If check to see if the target is linked to by any other
target in the project */ target in the project */
bool IsDependedOn(const char* project, cmTarget* target); bool IsDependedOn(const char* project, cmTarget* target);

View File

@ -23,7 +23,6 @@ PURPOSE. See the above copyright notices for more information.
#include "cmake.h" #include "cmake.h"
#include "cmGeneratedFileStream.h" #include "cmGeneratedFileStream.h"
#include "cmSourceFile.h" #include "cmSourceFile.h"
#include "cmOrderLinkDirectories.h"
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
#if defined(CMAKE_BUILD_WITH_CMAKE) #if defined(CMAKE_BUILD_WITH_CMAKE)
@ -427,18 +426,6 @@ cmXCodeObject* cmGlobalXCodeGenerator
return obj; return obj;
} }
//----------------------------------------------------------------------------
bool IsResource(cmSourceFile* sf)
{
const char* location = sf->GetProperty("MACOSX_PACKAGE_LOCATION");
bool isResource =
(sf->GetPropertyAsBool("FRAMEWORK_RESOURCE") ||
(location && cmStdString(location) == "Resources"));
return isResource;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmStdString GetGroupMapKey(cmTarget& cmtarget, cmSourceFile* sf) cmStdString GetGroupMapKey(cmTarget& cmtarget, cmSourceFile* sf)
{ {
@ -449,8 +436,8 @@ cmStdString GetGroupMapKey(cmTarget& cmtarget, cmSourceFile* sf)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmXCodeObject* cmXCodeObject*
cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg, cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
cmSourceFile* sf, cmSourceFile* sf,
cmTarget& cmtarget) cmTarget& cmtarget)
{ {
@ -498,7 +485,8 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
// Is this a resource file in this target? Add it to the resources group... // Is this a resource file in this target? Add it to the resources group...
// //
bool isResource = IsResource(sf); cmTarget::SourceFileFlags tsFlags = cmtarget.GetTargetSourceFileFlags(sf);
bool isResource = tsFlags.Resource;
// Is this a "private" or "public" framework header file? // Is this a "private" or "public" framework header file?
// Set the ATTRIBUTES attribute appropriately... // Set the ATTRIBUTES attribute appropriately...
@ -506,14 +494,14 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
if(cmtarget.GetType() == cmTarget::SHARED_LIBRARY && if(cmtarget.GetType() == cmTarget::SHARED_LIBRARY &&
cmtarget.GetPropertyAsBool("FRAMEWORK")) cmtarget.GetPropertyAsBool("FRAMEWORK"))
{ {
if(sf->GetPropertyAsBool("FRAMEWORK_PRIVATE_HEADER")) if(tsFlags.PrivateHeader)
{ {
cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST); cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST);
attrs->AddObject(this->CreateString("Private")); attrs->AddObject(this->CreateString("Private"));
settings->AddAttribute("ATTRIBUTES", attrs); settings->AddAttribute("ATTRIBUTES", attrs);
isResource = true; isResource = true;
} }
else if(sf->GetPropertyAsBool("FRAMEWORK_PUBLIC_HEADER")) else if(tsFlags.PublicHeader)
{ {
cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST); cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST);
attrs->AddObject(this->CreateString("Public")); attrs->AddObject(this->CreateString("Public"));
@ -693,6 +681,9 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
cmXCodeObject* filetype = cmXCodeObject* filetype =
fr->GetObject()->GetObject("lastKnownFileType"); fr->GetObject()->GetObject("lastKnownFileType");
cmTarget::SourceFileFlags tsFlags =
cmtarget.GetTargetSourceFileFlags(*i);
if(strcmp(filetype->GetString(), "\"compiled.mach-o.objfile\"") == 0) if(strcmp(filetype->GetString(), "\"compiled.mach-o.objfile\"") == 0)
{ {
externalObjFiles.push_back(xsf); externalObjFiles.push_back(xsf);
@ -701,7 +692,7 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
{ {
headerFiles.push_back(xsf); headerFiles.push_back(xsf);
} }
else if(IsResource(*i)) else if(tsFlags.Resource)
{ {
resourceFiles.push_back(xsf); resourceFiles.push_back(xsf);
} }
@ -813,8 +804,8 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
} }
copyFilesBuildPhase->AddAttribute("dstPath", copyFilesBuildPhase->AddAttribute("dstPath",
this->CreateString(ostr.str().c_str())); this->CreateString(ostr.str().c_str()));
copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", copyFilesBuildPhase->AddAttribute(
this->CreateString("0")); "runOnlyForDeploymentPostprocessing", this->CreateString("0"));
buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
copyFilesBuildPhase->AddAttribute("files", buildFiles); copyFilesBuildPhase->AddAttribute("files", buildFiles);
std::vector<cmSourceFile*>::iterator sfIt; std::vector<cmSourceFile*>::iterator sfIt;
@ -1418,6 +1409,14 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
productType = "com.apple.product-type.framework"; productType = "com.apple.product-type.framework";
const char* version = target.GetProperty("FRAMEWORK_VERSION"); const char* version = target.GetProperty("FRAMEWORK_VERSION");
if(!version)
{
version = target.GetProperty("VERSION");
}
if(!version)
{
version = "A";
}
buildSettings->AddAttribute("FRAMEWORK_VERSION", buildSettings->AddAttribute("FRAMEWORK_VERSION",
this->CreateString(version)); this->CreateString(version));
} }
@ -1501,7 +1500,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
for(std::vector<std::string>::iterator i = includes.begin(); for(std::vector<std::string>::iterator i = includes.begin();
i != includes.end(); ++i) i != includes.end(); ++i)
{ {
if(cmSystemTools::IsPathToFramework(i->c_str())) if(this->NameResolvesToFramework(i->c_str()))
{ {
std::string frameworkDir = *i; std::string frameworkDir = *i;
frameworkDir += "/../"; frameworkDir += "/../";
@ -1927,9 +1926,22 @@ void cmGlobalXCodeGenerator::AppendOrAddBuildSetting(cmXCodeObject* settings,
else else
{ {
std::string oldValue = attr->GetString(); std::string oldValue = attr->GetString();
cmSystemTools::ReplaceString(oldValue, "\"", "");
// unescape escaped quotes internal to the string:
cmSystemTools::ReplaceString(oldValue, "\\\"", "\"");
// remove surrounding quotes, if any:
std::string::size_type len = oldValue.length();
if(oldValue[0] == '\"' && oldValue[len-1] == '\"')
{
oldValue = oldValue.substr(1, len-2);
}
oldValue += " "; oldValue += " ";
oldValue += value; oldValue += value;
// SetString automatically escapes internal quotes and then surrounds
// the result with quotes if necessary...
attr->SetString(oldValue.c_str()); attr->SetString(oldValue.c_str());
} }
} }
@ -2098,8 +2110,8 @@ void cmGlobalXCodeGenerator
{ {
// now add the same one but append $(CONFIGURATION) to it: // now add the same one but append $(CONFIGURATION) to it:
linkDirs += " "; linkDirs += " ";
linkDirs += this->XCodeEscapePath(libDir->c_str()); linkDirs += this->XCodeEscapePath(
linkDirs += "/$(CONFIGURATION)"; (*libDir + "/$(CONFIGURATION)").c_str());
} }
linkDirs += " "; linkDirs += " ";
linkDirs += this->XCodeEscapePath(libDir->c_str()); linkDirs += this->XCodeEscapePath(libDir->c_str());
@ -2506,8 +2518,8 @@ cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
// one more pass for external depend information not handled // one more pass for external depend information not handled
// correctly by xcode // correctly by xcode
makefileStream << "# DO NOT EDIT\n"; makefileStream << "# DO NOT EDIT\n";
makefileStream << "# This makefile makes sure all linkable targets are \n"; makefileStream << "# This makefile makes sure all linkable targets are\n";
makefileStream << "# up-to-date with anything they link to,avoiding a " makefileStream << "# up-to-date with anything they link to, avoiding a "
"bug in XCode 1.5\n"; "bug in XCode 1.5\n";
for(std::vector<std::string>::const_iterator for(std::vector<std::string>::const_iterator
ct = this->CurrentConfigurationTypes.begin(); ct = this->CurrentConfigurationTypes.begin();
@ -2826,10 +2838,13 @@ cmGlobalXCodeGenerator
{ {
if(dir.find(".framework") != dir.npos) 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::size_type pos = dir.rfind("/");
std::string framework = dir.substr(pos); std::string framework = dir.substr(pos);
std::string newDir; std::string newDir = dir.substr(0, pos);
newDir = dir.substr(0, pos);
newDir += "/"; newDir += "/";
newDir += config; newDir += config;
dir = newDir; dir = newDir;

View File

@ -175,9 +175,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
cmCAStringVector runtimeArgVector (&argHelper, "RUNTIME", &group); cmCAStringVector runtimeArgVector (&argHelper, "RUNTIME", &group);
cmCAStringVector frameworkArgVector (&argHelper, "FRAMEWORK", &group); cmCAStringVector frameworkArgVector (&argHelper, "FRAMEWORK", &group);
cmCAStringVector bundleArgVector (&argHelper, "BUNDLE", &group); cmCAStringVector bundleArgVector (&argHelper, "BUNDLE", &group);
cmCAStringVector resourcesArgVector (&argHelper, "RESOURCE", &group);
cmCAStringVector publicHeaderArgVector(&argHelper, "PUBLIC_HEADER", &group);
cmCAStringVector privateHeaderArgVector(&argHelper,"PRIVATE_HEADER", &group); cmCAStringVector privateHeaderArgVector(&argHelper,"PRIVATE_HEADER", &group);
cmCAStringVector publicHeaderArgVector(&argHelper, "PUBLIC_HEADER", &group);
cmCAStringVector resourceArgVector (&argHelper, "RESOURCE", &group);
genericArgVector.Follows(0); genericArgVector.Follows(0);
group.Follows(&genericArgVector); group.Follows(&genericArgVector);
@ -197,18 +197,18 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
cmInstallCommandArguments runtimeArgs; cmInstallCommandArguments runtimeArgs;
cmInstallCommandArguments frameworkArgs; cmInstallCommandArguments frameworkArgs;
cmInstallCommandArguments bundleArgs; cmInstallCommandArguments bundleArgs;
cmInstallCommandArguments resourcesArgs;
cmInstallCommandArguments publicHeaderArgs;
cmInstallCommandArguments privateHeaderArgs; cmInstallCommandArguments privateHeaderArgs;
cmInstallCommandArguments publicHeaderArgs;
cmInstallCommandArguments resourceArgs;
archiveArgs.Parse (&archiveArgVector.GetVector(), &unknownArgs); archiveArgs.Parse (&archiveArgVector.GetVector(), &unknownArgs);
libraryArgs.Parse (&libraryArgVector.GetVector(), &unknownArgs); libraryArgs.Parse (&libraryArgVector.GetVector(), &unknownArgs);
runtimeArgs.Parse (&runtimeArgVector.GetVector(), &unknownArgs); runtimeArgs.Parse (&runtimeArgVector.GetVector(), &unknownArgs);
frameworkArgs.Parse (&frameworkArgVector.GetVector(), &unknownArgs); frameworkArgs.Parse (&frameworkArgVector.GetVector(), &unknownArgs);
bundleArgs.Parse (&bundleArgVector.GetVector(), &unknownArgs); bundleArgs.Parse (&bundleArgVector.GetVector(), &unknownArgs);
resourcesArgs.Parse (&resourcesArgVector.GetVector(), &unknownArgs);
publicHeaderArgs.Parse (&publicHeaderArgVector.GetVector(), &unknownArgs);
privateHeaderArgs.Parse(&privateHeaderArgVector.GetVector(), &unknownArgs); privateHeaderArgs.Parse(&privateHeaderArgVector.GetVector(), &unknownArgs);
publicHeaderArgs.Parse (&publicHeaderArgVector.GetVector(), &unknownArgs);
resourceArgs.Parse (&resourceArgVector.GetVector(), &unknownArgs);
if(!unknownArgs.empty()) if(!unknownArgs.empty())
{ {
@ -225,18 +225,18 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
runtimeArgs.SetGenericArguments(&genericArgs); runtimeArgs.SetGenericArguments(&genericArgs);
frameworkArgs.SetGenericArguments(&genericArgs); frameworkArgs.SetGenericArguments(&genericArgs);
bundleArgs.SetGenericArguments(&genericArgs); bundleArgs.SetGenericArguments(&genericArgs);
resourcesArgs.SetGenericArguments(&genericArgs);
publicHeaderArgs.SetGenericArguments(&genericArgs);
privateHeaderArgs.SetGenericArguments(&genericArgs); privateHeaderArgs.SetGenericArguments(&genericArgs);
publicHeaderArgs.SetGenericArguments(&genericArgs);
resourceArgs.SetGenericArguments(&genericArgs);
success = success && archiveArgs.Finalize(); success = success && archiveArgs.Finalize();
success = success && libraryArgs.Finalize(); success = success && libraryArgs.Finalize();
success = success && runtimeArgs.Finalize(); success = success && runtimeArgs.Finalize();
success = success && frameworkArgs.Finalize(); success = success && frameworkArgs.Finalize();
success = success && bundleArgs.Finalize(); success = success && bundleArgs.Finalize();
success = success && resourcesArgs.Finalize();
success = success && publicHeaderArgs.Finalize();
success = success && privateHeaderArgs.Finalize(); success = success && privateHeaderArgs.Finalize();
success = success && publicHeaderArgs.Finalize();
success = success && resourceArgs.Finalize();
if(!success) if(!success)
{ {
@ -299,9 +299,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
cmInstallTargetGenerator* runtimeGenerator = 0; cmInstallTargetGenerator* runtimeGenerator = 0;
cmInstallTargetGenerator* frameworkGenerator = 0; cmInstallTargetGenerator* frameworkGenerator = 0;
cmInstallTargetGenerator* bundleGenerator = 0; cmInstallTargetGenerator* bundleGenerator = 0;
cmInstallFilesGenerator* resourcesGenerator = 0;
cmInstallFilesGenerator* publicHeaderGenerator = 0;
cmInstallFilesGenerator* privateHeaderGenerator = 0; cmInstallFilesGenerator* privateHeaderGenerator = 0;
cmInstallFilesGenerator* publicHeaderGenerator = 0;
cmInstallFilesGenerator* resourceGenerator = 0;
switch(target.GetType()) switch(target.GetType())
{ {
@ -465,84 +465,98 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// if(target.GetProperty("ASSOCIATED_FILES"); // if(target.GetProperty("ASSOCIATED_FILES");
const char* files = target.GetProperty("PUBLIC_HEADER"); // These well-known sets of files are installed *automatically* for FRAMEWORK
if ((files) && (*files)) // SHARED library targets on the Mac as part of installing the FRAMEWORK.
{ // For other target types or on other platforms, they are not installed
std::vector<std::string> relFiles; // automatically and so we need to create install files generators for them.
cmSystemTools::ExpandListArgument(files, relFiles); //
std::vector<std::string> absFiles; bool createInstallGeneratorsForTargetFileSets = true;
if (!this->MakeFilesFullPath("PUBLIC_HEADER", relFiles, absFiles))
{
return false;
}
// Create the files install generator. if(cmTarget::SHARED_LIBRARY == target.GetType() &&
if (!publicHeaderArgs.GetDestination().empty()) target.GetPropertyAsBool("FRAMEWORK") &&
{ this->Makefile->IsOn("APPLE"))
publicHeaderGenerator = CreateInstallFilesGenerator(absFiles, {
publicHeaderArgs, false); createInstallGeneratorsForTargetFileSets = false;
}
else
{
cmOStringStream e;
e << "TARGETS given no PUBLIC_HEADER DESTINATION for header files\""
<< target.GetName() << "\".";
this->SetError(e.str().c_str());
return false;
}
} }
files = target.GetProperty("PRIVATE_HEADER"); if(createInstallGeneratorsForTargetFileSets)
if ((files) && (*files))
{ {
std::vector<std::string> relFiles; const char* files = target.GetProperty("PRIVATE_HEADER");
cmSystemTools::ExpandListArgument(files, relFiles); if ((files) && (*files))
std::vector<std::string> absFiles;
if (!this->MakeFilesFullPath("PRIVATE_HEADER", relFiles, absFiles))
{ {
return false; std::vector<std::string> relFiles;
} cmSystemTools::ExpandListArgument(files, relFiles);
std::vector<std::string> absFiles;
if (!this->MakeFilesFullPath("PRIVATE_HEADER", relFiles, absFiles))
{
return false;
}
// Create the files install generator. // Create the files install generator.
if (!privateHeaderArgs.GetDestination().empty()) if (!privateHeaderArgs.GetDestination().empty())
{ {
privateHeaderGenerator = CreateInstallFilesGenerator(absFiles, privateHeaderGenerator = CreateInstallFilesGenerator(absFiles,
privateHeaderArgs, false); privateHeaderArgs, false);
} }
else else
{ {
cmOStringStream e; cmOStringStream e;
e << "TARGETS given no PRIVATE_HEADER DESTINATION for header files\"" e << "INSTALL TARGETS - target " << target.GetName() << " has "
<< target.GetName() << "\"."; << "PRIVATE_HEADER files but no PRIVATE_HEADER DESTINATION.";
this->SetError(e.str().c_str()); cmSystemTools::Message(e.str().c_str(), "Warning");
return false; }
}
}
files = target.GetProperty("RESOURCE_FILES");
if ((files) && (*files))
{
std::vector<std::string> relFiles;
cmSystemTools::ExpandListArgument(files, relFiles);
std::vector<std::string> absFiles;
if (!this->MakeFilesFullPath("RESOURCE_FILES", relFiles, absFiles))
{
return false;
} }
// Create the files install generator. files = target.GetProperty("PUBLIC_HEADER");
if (!privateHeaderArgs.GetDestination().empty()) if ((files) && (*files))
{ {
resourcesGenerator = CreateInstallFilesGenerator(absFiles, std::vector<std::string> relFiles;
resourcesArgs, false); cmSystemTools::ExpandListArgument(files, relFiles);
std::vector<std::string> absFiles;
if (!this->MakeFilesFullPath("PUBLIC_HEADER", relFiles, absFiles))
{
return false;
}
// Create the files install generator.
if (!publicHeaderArgs.GetDestination().empty())
{
publicHeaderGenerator = CreateInstallFilesGenerator(absFiles,
publicHeaderArgs, false);
}
else
{
cmOStringStream e;
e << "INSTALL TARGETS - target " << target.GetName() << " has "
<< "PUBLIC_HEADER files but no PUBLIC_HEADER DESTINATION.";
cmSystemTools::Message(e.str().c_str(), "Warning");
}
} }
else
files = target.GetProperty("RESOURCE");
if ((files) && (*files))
{ {
cmOStringStream e; std::vector<std::string> relFiles;
e << "TARGETS given no RESOURCES DESTINATION for resource files\"" cmSystemTools::ExpandListArgument(files, relFiles);
<< target.GetName() << "\"."; std::vector<std::string> absFiles;
this->SetError(e.str().c_str()); if (!this->MakeFilesFullPath("RESOURCE", relFiles, absFiles))
return false; {
return false;
}
// Create the files install generator.
if (!resourceArgs.GetDestination().empty())
{
resourceGenerator = CreateInstallFilesGenerator(absFiles,
resourceArgs, false);
}
else
{
cmOStringStream e;
e << "INSTALL TARGETS - target " << target.GetName() << " has "
<< "RESOURCE files but no RESOURCE DESTINATION.";
cmSystemTools::Message(e.str().c_str(), "Warning");
}
} }
} }
@ -551,9 +565,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
this->Makefile->AddInstallGenerator(runtimeGenerator); this->Makefile->AddInstallGenerator(runtimeGenerator);
this->Makefile->AddInstallGenerator(frameworkGenerator); this->Makefile->AddInstallGenerator(frameworkGenerator);
this->Makefile->AddInstallGenerator(bundleGenerator); this->Makefile->AddInstallGenerator(bundleGenerator);
this->Makefile->AddInstallGenerator(publicHeaderGenerator);
this->Makefile->AddInstallGenerator(privateHeaderGenerator); this->Makefile->AddInstallGenerator(privateHeaderGenerator);
this->Makefile->AddInstallGenerator(resourcesGenerator); this->Makefile->AddInstallGenerator(publicHeaderGenerator);
this->Makefile->AddInstallGenerator(resourceGenerator);
if (!exports.GetString().empty()) if (!exports.GetString().empty())
{ {
@ -577,11 +591,11 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
this->Makefile->GetLocalGenerator()->GetGlobalGenerator() this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
->AddInstallComponent(bundleArgs.GetComponent().c_str()); ->AddInstallComponent(bundleArgs.GetComponent().c_str());
this->Makefile->GetLocalGenerator()->GetGlobalGenerator() this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
->AddInstallComponent(resourcesArgs.GetComponent().c_str()); ->AddInstallComponent(privateHeaderArgs.GetComponent().c_str());
this->Makefile->GetLocalGenerator()->GetGlobalGenerator() this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
->AddInstallComponent(publicHeaderArgs.GetComponent().c_str()); ->AddInstallComponent(publicHeaderArgs.GetComponent().c_str());
this->Makefile->GetLocalGenerator()->GetGlobalGenerator() this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
->AddInstallComponent(privateHeaderArgs.GetComponent().c_str()); ->AddInstallComponent(resourceArgs.GetComponent().c_str());
return true; return true;
} }

View File

@ -238,8 +238,18 @@ 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 if(config && *config)
cmSystemTools::ConvertToUnixSlashes(from1); {
from1 += "/";
from1 += targetName;
from1 += ".framework";
}
else
{
// Remove trailing slashes... so that from1 ends with ".framework":
//
cmSystemTools::ConvertToUnixSlashes(from1);
}
files.push_back(from1); files.push_back(from1);
type = cmTarget::INSTALL_DIRECTORY; type = cmTarget::INSTALL_DIRECTORY;

View File

@ -252,16 +252,12 @@ void cmMakefileLibraryTargetGenerator::CreateFrameworkLinksAndDirs(
symlink2 = "Resources"; symlink2 = "Resources";
cmSystemTools::CreateSymlink(symlink.c_str(), symlink2.c_str()); cmSystemTools::CreateSymlink(symlink.c_str(), symlink2.c_str());
this->Makefile->AddCMakeOutputFile((outpath + "Resources").c_str()); this->Makefile->AddCMakeOutputFile((outpath + "Resources").c_str());
// Libraries -> Versions/Current/Libraries
//symlink = "Versions/Current/Libraries";
//symlink2 = "Libraries";
//cmSystemTools::CreateSymlink(symlink.c_str(), symlink2.c_str());
//this->Makefile->AddCMakeOutputFile((outpath + "Libraries").c_str());
// Headers -> Versions/Current/Headers // Headers -> Versions/Current/Headers
symlink = "Versions/Current/Headers"; symlink = "Versions/Current/Headers";
symlink2 = "Headers"; symlink2 = "Headers";
cmSystemTools::CreateSymlink(symlink.c_str(), symlink2.c_str()); cmSystemTools::CreateSymlink(symlink.c_str(), symlink2.c_str());
this->Makefile->AddCMakeOutputFile((outpath + "Headers").c_str()); this->Makefile->AddCMakeOutputFile((outpath + "Headers").c_str());
// PrivateHeaders -> Versions/Current/PrivateHeaders
symlink = "Versions/Current/PrivateHeaders"; symlink = "Versions/Current/PrivateHeaders";
symlink2 = "PrivateHeaders"; symlink2 = "PrivateHeaders";
cmSystemTools::CreateSymlink(symlink.c_str(), symlink2.c_str()); cmSystemTools::CreateSymlink(symlink.c_str(), symlink2.c_str());
@ -278,12 +274,14 @@ void cmMakefileLibraryTargetGenerator::CopyFrameworkSources(
const char* propertyName, const char* propertyName,
const char* subdir) const char* subdir)
{ {
std::string fullOutput= outpath + targetName; std::string fullOutput = outpath + targetName;
cmCustomCommandLines commandLines; cmCustomCommandLines commandLines;
std::vector<std::string> depends; std::vector<std::string> depends;
const std::vector<cmSourceFile*>& sources = const std::vector<cmSourceFile*>& sources =
this->Target->GetSourceFiles(); this->Target->GetSourceFiles();
std::string propName(propertyName);
for(std::vector<cmSourceFile*>::const_iterator i = sources.begin(); for(std::vector<cmSourceFile*>::const_iterator i = sources.begin();
i != sources.end(); ++i) i != sources.end(); ++i)
{ {
@ -296,16 +294,20 @@ void cmMakefileLibraryTargetGenerator::CopyFrameworkSources(
continue; continue;
} }
cmTarget::SourceFileFlags tsFlags =
this->Target->GetTargetSourceFileFlags(sf);
// If processing public headers, skip headers also marked with the private // If processing public headers, skip headers also marked with the private
// property. Private wins. // property. Private wins.
// //
if((std::string(propertyName) == "FRAMEWORK_PUBLIC_HEADER") && if(tsFlags.PrivateHeader && (propName == "PUBLIC_HEADER"))
sf->GetPropertyAsBool("FRAMEWORK_PRIVATE_HEADER"))
{ {
continue; continue;
} }
if(sf->GetPropertyAsBool(propertyName)) if(tsFlags.PrivateHeader && (propName == "PRIVATE_HEADER") ||
tsFlags.PublicHeader && (propName == "PUBLIC_HEADER") ||
tsFlags.Resource && (propName == "RESOURCE"))
{ {
cmCustomCommandLine line; cmCustomCommandLine line;
std::string dest = outpath + subdir + "/"; std::string dest = outpath + subdir + "/";
@ -318,8 +320,7 @@ void cmMakefileLibraryTargetGenerator::CopyFrameworkSources(
line.push_back(dest); line.push_back(dest);
commandLines.push_back(line); commandLines.push_back(line);
// make sure the target gets rebuilt if any of the headers is removed // make sure the target gets rebuilt if any of the headers is removed
this->GenerateExtraOutput(dest.c_str(), this->GenerateExtraOutput(dest.c_str(), fullOutput.c_str());
fullOutput.c_str());
} }
} }
@ -343,14 +344,13 @@ void cmMakefileLibraryTargetGenerator::CreateFramework(
{ {
std::string macdir = outpath; std::string macdir = outpath;
const char* version = this->Target->GetProperty("FRAMEWORK_VERSION"); const char* version = this->Target->GetProperty("FRAMEWORK_VERSION");
if(!version)
{
version = this->Target->GetProperty("VERSION");
}
if(!version) if(!version)
{ {
version = "A"; version = "A";
//std::string message =
// "Warning: FRAMEWORK_VERSION property not found on ";
//message += targetName;
//message += ". Default to version A.";
//cmSystemTools::Message(message.c_str());
} }
// create the symbolic links and directories // create the symbolic links and directories
this->CreateFrameworkLinksAndDirs(targetName, this->CreateFrameworkLinksAndDirs(targetName,
@ -383,13 +383,13 @@ void cmMakefileLibraryTargetGenerator::CreateFramework(
false, false, false); false, false, false);
this->CopyFrameworkSources(targetName, outpath, version, this->CopyFrameworkSources(targetName, outpath, version,
"FRAMEWORK_PRIVATE_HEADER", "PrivateHeaders"); "PRIVATE_HEADER", "PrivateHeaders");
this->CopyFrameworkSources(targetName, outpath, version, this->CopyFrameworkSources(targetName, outpath, version,
"FRAMEWORK_PUBLIC_HEADER", "Headers"); "PUBLIC_HEADER", "Headers");
this->CopyFrameworkSources(targetName, outpath, version, this->CopyFrameworkSources(targetName, outpath, version,
"FRAMEWORK_RESOURCE", "Resources"); "RESOURCE", "Resources");
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View File

@ -1170,7 +1170,7 @@ std::string cmMakefileTargetGenerator::GetFrameworkFlags()
// will already have added a -F for the framework // will already have added a -F for the framework
for(i = includes.begin(); i != includes.end(); ++i) for(i = includes.begin(); i != includes.end(); ++i)
{ {
if(cmSystemTools::IsPathToFramework(i->c_str())) if(this->Target->NameResolvesToFramework(i->c_str()))
{ {
std::string frameworkDir = *i; std::string frameworkDir = *i;
frameworkDir += "/../"; frameworkDir += "/../";

View File

@ -466,28 +466,29 @@ bool cmOrderLinkDirectories::DetermineLibraryPathOrder()
// if it is a full path to an item then separate it from the path // if it is a full path to an item then separate it from the path
// this only works with files and paths // this only works with files and paths
cmStdString& item = this->RawLinkItems[i]; cmStdString& item = this->RawLinkItems[i];
if(cmSystemTools::FileIsFullPath(item.c_str())) if(cmSystemTools::FileIsFullPath(item.c_str()))
{ {
if(cmSystemTools::IsPathToFramework(item.c_str()))
{
this->SplitFramework.find(item.c_str());
cmStdString path = this->SplitFramework.match(1);
// Add the -F path if we have not yet done so
if(this->EmittedFrameworkPaths.insert(path).second)
{
std::string fpath = "-F";
fpath += cmSystemTools::ConvertToOutputPath(path.c_str());
this->LinkItems.push_back(fpath);
}
// now add the -framework option
std::string frame = "-framework ";
frame += this->SplitFramework.match(2);
this->LinkItems.push_back(frame);
framework = true;
}
if(cmSystemTools::FileIsDirectory(item.c_str())) if(cmSystemTools::FileIsDirectory(item.c_str()))
{ {
if(cmSystemTools::IsPathToFramework(item.c_str())) if(!framework)
{
this->SplitFramework.find(item.c_str());
cmStdString path = this->SplitFramework.match(1);
// Add the -F path if we have not yet done so
if(this->EmittedFrameworkPaths.insert(path).second)
{
std::string fpath = "-F";
fpath += cmSystemTools::ConvertToOutputPath(path.c_str());
this->LinkItems.push_back(fpath);
}
// now add the -framework option
std::string frame = "-framework ";
frame += this->SplitFramework.match(2);
this->LinkItems.push_back(frame);
framework = true;
}
else
{ {
// A full path to a directory was found as a link item // A full path to a directory was found as a link item
// warn user // warn user

View File

@ -687,6 +687,83 @@ cmSourceFile* cmTarget::AddSource(const char* s)
return sf; return sf;
} }
//----------------------------------------------------------------------------
struct cmTarget::SourceFileFlags
cmTarget::GetTargetSourceFileFlags(const cmSourceFile* sf)
{
struct SourceFileFlags flags;
const char* files;
std::vector<std::string>::iterator it;
flags.PrivateHeader = false;
flags.PublicHeader = false;
flags.Resource = false;
files = this->GetProperty("PRIVATE_HEADER");
if ((files) && (*files))
{
std::vector<std::string> relFiles;
cmSystemTools::ExpandListArgument(files, relFiles);
for(it = relFiles.begin(); it != relFiles.end(); ++it)
{
if(sf == this->GetMakefile()->GetSource(it->c_str()))
{
flags.PrivateHeader = true;
break;
}
}
}
// Only consider marking it as a public header if it is *NOT* already marked
// as a private header:
//
if(!flags.PrivateHeader)
{
files = this->GetProperty("PUBLIC_HEADER");
if ((files) && (*files))
{
std::vector<std::string> relFiles;
cmSystemTools::ExpandListArgument(files, relFiles);
for(it = relFiles.begin(); it != relFiles.end(); ++it)
{
if(sf == this->GetMakefile()->GetSource(it->c_str()))
{
flags.PublicHeader = true;
break;
}
}
}
}
const char* location = sf->GetProperty("MACOSX_PACKAGE_LOCATION");
if(location && cmStdString(location) == "Resources")
{
flags.Resource = true;
}
// Don't bother with the loop if it's already marked as a resource:
//
if(!flags.Resource)
{
files = this->GetProperty("RESOURCE");
if ((files) && (*files))
{
std::vector<std::string> relFiles;
cmSystemTools::ExpandListArgument(files, relFiles);
for(it = relFiles.begin(); it != relFiles.end(); ++it)
{
if(sf == this->GetMakefile()->GetSource(it->c_str()))
{
flags.Resource = true;
break;
}
}
}
}
return flags;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTarget::MergeLinkLibraries( cmMakefile& mf, void cmTarget::MergeLinkLibraries( cmMakefile& mf,
const char *selfname, const char *selfname,
@ -815,11 +892,18 @@ void cmTarget::AddLinkLibrary(const std::string& lib,
this->LinkLibraries.push_back(tmp); this->LinkLibraries.push_back(tmp);
} }
//----------------------------------------------------------------------------
bool cmTarget::NameResolvesToFramework(const std::string& libname)
{
return this->GetMakefile()->GetLocalGenerator()->GetGlobalGenerator()->
NameResolvesToFramework(libname);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool cmTarget::AddFramework(const std::string& libname, LinkLibraryType llt) bool cmTarget::AddFramework(const std::string& libname, LinkLibraryType llt)
{ {
(void)llt; // TODO: What is this? (void)llt; // TODO: What is this?
if(cmSystemTools::IsPathToFramework(libname.c_str())) if(this->NameResolvesToFramework(libname.c_str()))
{ {
std::string frameworkDir = libname; std::string frameworkDir = libname;
frameworkDir += "/../"; frameworkDir += "/../";
@ -1239,7 +1323,8 @@ const char* cmTarget::NormalGetDirectory(const char* config, bool implib)
{ {
if(config && *config) if(config && *config)
{ {
this->Directory = this->GetOutputDir(implib); // Do not create the directory when config is given:
this->Directory = this->GetAndCreateOutputDir(implib, false);
// Add the configuration's subdirectory. // Add the configuration's subdirectory.
this->Makefile->GetLocalGenerator()->GetGlobalGenerator()-> this->Makefile->GetLocalGenerator()->GetGlobalGenerator()->
AppendDirectoryForConfig("/", config, "", this->Directory); AppendDirectoryForConfig("/", config, "", this->Directory);
@ -2199,7 +2284,7 @@ std::string cmTarget::GetInstallNameDirForInstallTree(const char*)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
const char* cmTarget::GetOutputDir(bool implib) const char* cmTarget::GetAndCreateOutputDir(bool implib, bool create)
{ {
// 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.
@ -2332,17 +2417,26 @@ const char* cmTarget::GetOutputDir(bool implib)
} }
#endif #endif
// Make sure the output path exists on disk. // Optionally make sure the output path exists on disk.
if(!cmSystemTools::MakeDirectory(out.c_str())) if(create)
{ {
cmSystemTools::Error("Error failed to create output directory:", if(!cmSystemTools::MakeDirectory(out.c_str()))
out.c_str()); {
cmSystemTools::Error("Error failed to create output directory: ",
out.c_str());
}
} }
} }
return out.c_str(); return out.c_str();
} }
//----------------------------------------------------------------------------
const char* cmTarget::GetOutputDir(bool implib)
{
return this->GetAndCreateOutputDir(implib, true);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
const char* cmTarget::GetExportMacro() const char* cmTarget::GetExportMacro()
{ {

View File

@ -83,6 +83,23 @@ public:
{return this->SourceFiles;} {return this->SourceFiles;}
void AddSourceFile(cmSourceFile* sf) { this->SourceFiles.push_back(sf); } void AddSourceFile(cmSourceFile* sf) { this->SourceFiles.push_back(sf); }
/**
* Flags for a given source file as used in this target. Typically assigned
* via SET_TARGET_PROPERTIES when the property is a list of source files.
*/
struct SourceFileFlags
{
bool PrivateHeader; // source is in "PRIVATE_HEADER" target property
bool PublicHeader; // source is in "PUBLIC_HEADER" target property
bool Resource; // source is in "RESOURCE" target property *or*
// source has MACOSX_PACKAGE_LOCATION=="Resources"
};
/**
* Get the flags for a given source file as used in this target
*/
struct SourceFileFlags GetTargetSourceFileFlags(const cmSourceFile* sf);
/** /**
* Add sources to the target. * Add sources to the target.
*/ */
@ -109,6 +126,7 @@ public:
void ClearDependencyInformation(cmMakefile& mf, const char* target); void ClearDependencyInformation(cmMakefile& mf, const char* target);
// Check to see if a library is a framework and treat it different on Mac // Check to see if a library is a framework and treat it different on Mac
bool NameResolvesToFramework(const std::string& libname);
bool AddFramework(const std::string& lib, LinkLibraryType llt); bool AddFramework(const std::string& lib, LinkLibraryType llt);
void AddLinkLibrary(cmMakefile& mf, void AddLinkLibrary(cmMakefile& mf,
const char *target, const char* lib, const char *target, const char* lib,
@ -359,6 +377,9 @@ private:
// If the variable is not defined use the given default instead. // If the variable is not defined use the given default instead.
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.
const char* GetAndCreateOutputDir(bool implib, bool create);
// Get the full path to the target output directory. // Get the full path to the target output directory.
const char* GetOutputDir(bool implib); const char* GetOutputDir(bool implib);

View File

@ -45,7 +45,6 @@ IF(BUILD_TESTING)
ADD_TEST_MACRO(LoadCommand LoadedCommand) ADD_TEST_MACRO(LoadCommand LoadedCommand)
ADD_TEST_MACRO(LinkLine LinkLine) ADD_TEST_MACRO(LinkLine LinkLine)
ADD_TEST_MACRO(MacroTest miniMacroTest) ADD_TEST_MACRO(MacroTest miniMacroTest)
ADD_TEST_MACRO(Framework bar)
ADD_TEST_MACRO(Properties Properties) ADD_TEST_MACRO(Properties Properties)
ADD_TEST_MACRO(Assembler HelloAsm) ADD_TEST_MACRO(Assembler HelloAsm)
ADD_TEST_MACRO(SourceGroups SourceGroups) ADD_TEST_MACRO(SourceGroups SourceGroups)
@ -64,8 +63,20 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=CVS -P ${CMake_SOURCE_DIR}/Utilities/Rel
ENDIF(COMMAND SET_TESTS_PROPERTIES AND COMMAND GET_TEST_PROPERTY) ENDIF(COMMAND SET_TESTS_PROPERTIES AND COMMAND GET_TEST_PROPERTY)
ENDIF(CMAKE_BUILD_NIGHTLY_WINDOWS_TEST) ENDIF(CMAKE_BUILD_NIGHTLY_WINDOWS_TEST)
# add tests with more complex invocations # add tests with more complex invocations
ADD_TEST(Framework ${CMAKE_CTEST_COMMAND}
--build-and-test
"${CMake_SOURCE_DIR}/Tests/Framework"
"${CMake_BINARY_DIR}/Tests/Framework"
--build-two-config
--build-generator ${CMAKE_TEST_GENERATOR}
--build-makeprogram ${CMAKE_TEST_MAKEPROGRAM}
--build-project Framework
--build-options
"-DCMAKE_INSTALL_PREFIX:PATH=${CMake_BINARY_DIR}/Tests/Framework/Install"
--test-command bar)
ADD_TEST(TargetName ${CMAKE_CTEST_COMMAND} ADD_TEST(TargetName ${CMAKE_CTEST_COMMAND}
--build-and-test --build-and-test
"${CMake_SOURCE_DIR}/Tests/TargetName" "${CMake_SOURCE_DIR}/Tests/TargetName"

View File

@ -10,26 +10,34 @@ add_library(foo SHARED
fooBoth.h fooBoth.h
test.lua test.lua
) )
set(foo_ver ver4)
set_target_properties(foo PROPERTIES set_target_properties(foo PROPERTIES
FRAMEWORK TRUE FRAMEWORK TRUE
FRAMEWORK_VERSION ver3 FRAMEWORK_VERSION ${foo_ver}
) PRIVATE_HEADER "fooPrivate.h;fooBoth.h"
# fooNeither.h is marked neither public nor private... PUBLIC_HEADER "foo.h;foo2.h;fooPublic.h;fooBoth.h"
# fooBoth.h is marked both public and private... (private wins...) RESOURCE "test.lua"
set_source_files_properties(foo.h foo2.h fooPublic.h fooBoth.h PROPERTIES
FRAMEWORK_PUBLIC_HEADER TRUE
)
set_source_files_properties(fooPrivate.h fooBoth.h PROPERTIES
FRAMEWORK_PRIVATE_HEADER TRUE
)
set_source_files_properties(test.lua PROPERTIES
FRAMEWORK_RESOURCE TRUE
) )
# fooBoth.h is listed as both public and private... (private wins...)
# fooNeither.h is listed as neither public nor private...
add_executable(bar bar.cxx) add_executable(bar bar.cxx)
target_link_libraries(bar foo) target_link_libraries(bar foo)
install(TARGETS foo bar install(TARGETS foo bar
RUNTIME DESTINATION /Applications/CMakeTestsFramework/bin RUNTIME DESTINATION Applications/CMakeTestsFramework/bin
FRAMEWORK DESTINATION /Library/Frameworks FRAMEWORK DESTINATION Library/Frameworks
# These are ignored on the Mac... and things are automatically placed in
# their appropriate Framework sub-folder at build time. (And then the built
# framework is copied recursively when it is installed.)
PRIVATE_HEADER DESTINATION share/foo-${foo_ver}/PrivateHeaders
PUBLIC_HEADER DESTINATION include/foo-${foo_ver}
RESOURCE DESTINATION share/foo-${foo_ver}/Resources
# But they are required to be present so that installing a framework on other
# other platforms will install the pieces of the framework without having to
# duplicate install rules for the pieces of the framework.
) )
# Make a static library and apply the framework properties to it to verify # Make a static library and apply the framework properties to it to verify
@ -53,3 +61,5 @@ set_target_properties(fooStatic PROPERTIES
) )
add_executable(barStatic bar.cxx) add_executable(barStatic bar.cxx)
target_link_libraries(barStatic fooStatic) target_link_libraries(barStatic fooStatic)
include(CPack)