summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Source/cmGlobalGenerator.cxx22
-rw-r--r--Source/cmGlobalGenerator.h4
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx73
-rw-r--r--Source/cmInstallCommand.cxx176
-rw-r--r--Source/cmInstallTargetGenerator.cxx14
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx38
-rw-r--r--Source/cmMakefileTargetGenerator.cxx2
-rw-r--r--Source/cmOrderLinkDirectories.cxx35
-rw-r--r--Source/cmTarget.cxx110
-rw-r--r--Source/cmTarget.h21
-rw-r--r--Tests/CMakeLists.txt15
-rw-r--r--Tests/Framework/CMakeLists.txt38
12 files changed, 375 insertions, 173 deletions
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index a3b2cf3e59..b5323e1bf1 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1277,6 +1277,7 @@ cmLocalGenerator* cmGlobalGenerator::FindLocalGenerator(const char* start_dir)
}
+//----------------------------------------------------------------------------
cmTarget* cmGlobalGenerator::FindTarget(const char* project,
const char* name,
bool useImportedTargets)
@@ -1318,6 +1319,27 @@ cmTarget* cmGlobalGenerator::FindTarget(const char* project,
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)
{
if(s[0] == '\"' && s[s.size()-1] == '\"')
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index efc5fab7d9..d88ef0925d 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -187,6 +187,10 @@ public:
const char* name,
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
target in the project */
bool IsDependedOn(const char* project, cmTarget* target);
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 8c60b9b588..f4895d1b22 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -23,7 +23,6 @@ PURPOSE. See the above copyright notices for more information.
#include "cmake.h"
#include "cmGeneratedFileStream.h"
#include "cmSourceFile.h"
-#include "cmOrderLinkDirectories.h"
//----------------------------------------------------------------------------
#if defined(CMAKE_BUILD_WITH_CMAKE)
@@ -428,18 +427,6 @@ cmXCodeObject* cmGlobalXCodeGenerator
}
//----------------------------------------------------------------------------
-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 key(cmtarget.GetName());
@@ -449,8 +436,8 @@ cmStdString GetGroupMapKey(cmTarget& cmtarget, cmSourceFile* sf)
}
//----------------------------------------------------------------------------
-cmXCodeObject*
-cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
+cmXCodeObject*
+cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
cmSourceFile* sf,
cmTarget& cmtarget)
{
@@ -498,7 +485,8 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
// 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?
// Set the ATTRIBUTES attribute appropriately...
@@ -506,14 +494,14 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
if(cmtarget.GetType() == cmTarget::SHARED_LIBRARY &&
cmtarget.GetPropertyAsBool("FRAMEWORK"))
{
- if(sf->GetPropertyAsBool("FRAMEWORK_PRIVATE_HEADER"))
+ if(tsFlags.PrivateHeader)
{
cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST);
attrs->AddObject(this->CreateString("Private"));
settings->AddAttribute("ATTRIBUTES", attrs);
isResource = true;
}
- else if(sf->GetPropertyAsBool("FRAMEWORK_PUBLIC_HEADER"))
+ else if(tsFlags.PublicHeader)
{
cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST);
attrs->AddObject(this->CreateString("Public"));
@@ -693,6 +681,9 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
cmXCodeObject* filetype =
fr->GetObject()->GetObject("lastKnownFileType");
+ cmTarget::SourceFileFlags tsFlags =
+ cmtarget.GetTargetSourceFileFlags(*i);
+
if(strcmp(filetype->GetString(), "\"compiled.mach-o.objfile\"") == 0)
{
externalObjFiles.push_back(xsf);
@@ -701,7 +692,7 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
{
headerFiles.push_back(xsf);
}
- else if(IsResource(*i))
+ else if(tsFlags.Resource)
{
resourceFiles.push_back(xsf);
}
@@ -813,8 +804,8 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
}
copyFilesBuildPhase->AddAttribute("dstPath",
this->CreateString(ostr.str().c_str()));
- copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
- this->CreateString("0"));
+ copyFilesBuildPhase->AddAttribute(
+ "runOnlyForDeploymentPostprocessing", this->CreateString("0"));
buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
copyFilesBuildPhase->AddAttribute("files", buildFiles);
std::vector<cmSourceFile*>::iterator sfIt;
@@ -1418,6 +1409,14 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
productType = "com.apple.product-type.framework";
const char* version = target.GetProperty("FRAMEWORK_VERSION");
+ if(!version)
+ {
+ version = target.GetProperty("VERSION");
+ }
+ if(!version)
+ {
+ version = "A";
+ }
buildSettings->AddAttribute("FRAMEWORK_VERSION",
this->CreateString(version));
}
@@ -1501,7 +1500,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
for(std::vector<std::string>::iterator i = includes.begin();
i != includes.end(); ++i)
{
- if(cmSystemTools::IsPathToFramework(i->c_str()))
+ if(this->NameResolvesToFramework(i->c_str()))
{
std::string frameworkDir = *i;
frameworkDir += "/../";
@@ -1927,9 +1926,22 @@ void cmGlobalXCodeGenerator::AppendOrAddBuildSetting(cmXCodeObject* settings,
else
{
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 += value;
+
+ // SetString automatically escapes internal quotes and then surrounds
+ // the result with quotes if necessary...
attr->SetString(oldValue.c_str());
}
}
@@ -2098,8 +2110,8 @@ void cmGlobalXCodeGenerator
{
// now add the same one but append $(CONFIGURATION) to it:
linkDirs += " ";
- linkDirs += this->XCodeEscapePath(libDir->c_str());
- linkDirs += "/$(CONFIGURATION)";
+ linkDirs += this->XCodeEscapePath(
+ (*libDir + "/$(CONFIGURATION)").c_str());
}
linkDirs += " ";
linkDirs += this->XCodeEscapePath(libDir->c_str());
@@ -2506,8 +2518,8 @@ cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
// one more pass for external depend information not handled
// correctly by xcode
makefileStream << "# DO NOT EDIT\n";
- makefileStream << "# This makefile makes sure all linkable targets are \n";
- makefileStream << "# up-to-date with anything they link to,avoiding a "
+ makefileStream << "# This makefile makes sure all linkable targets are\n";
+ makefileStream << "# up-to-date with anything they link to, avoiding a "
"bug in XCode 1.5\n";
for(std::vector<std::string>::const_iterator
ct = this->CurrentConfigurationTypes.begin();
@@ -2826,10 +2838,13 @@ cmGlobalXCodeGenerator
{
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;
- newDir = dir.substr(0, pos);
+ std::string newDir = dir.substr(0, pos);
newDir += "/";
newDir += config;
dir = newDir;
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 3fd3fef621..6696629fcb 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -175,9 +175,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
cmCAStringVector runtimeArgVector (&argHelper, "RUNTIME", &group);
cmCAStringVector frameworkArgVector (&argHelper, "FRAMEWORK", &group);
cmCAStringVector bundleArgVector (&argHelper, "BUNDLE", &group);
- cmCAStringVector resourcesArgVector (&argHelper, "RESOURCE", &group);
- cmCAStringVector publicHeaderArgVector(&argHelper, "PUBLIC_HEADER", &group);
cmCAStringVector privateHeaderArgVector(&argHelper,"PRIVATE_HEADER", &group);
+ cmCAStringVector publicHeaderArgVector(&argHelper, "PUBLIC_HEADER", &group);
+ cmCAStringVector resourceArgVector (&argHelper, "RESOURCE", &group);
genericArgVector.Follows(0);
group.Follows(&genericArgVector);
@@ -197,18 +197,18 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
cmInstallCommandArguments runtimeArgs;
cmInstallCommandArguments frameworkArgs;
cmInstallCommandArguments bundleArgs;
- cmInstallCommandArguments resourcesArgs;
- cmInstallCommandArguments publicHeaderArgs;
cmInstallCommandArguments privateHeaderArgs;
+ cmInstallCommandArguments publicHeaderArgs;
+ cmInstallCommandArguments resourceArgs;
archiveArgs.Parse (&archiveArgVector.GetVector(), &unknownArgs);
libraryArgs.Parse (&libraryArgVector.GetVector(), &unknownArgs);
runtimeArgs.Parse (&runtimeArgVector.GetVector(), &unknownArgs);
frameworkArgs.Parse (&frameworkArgVector.GetVector(), &unknownArgs);
bundleArgs.Parse (&bundleArgVector.GetVector(), &unknownArgs);
- resourcesArgs.Parse (&resourcesArgVector.GetVector(), &unknownArgs);
- publicHeaderArgs.Parse (&publicHeaderArgVector.GetVector(), &unknownArgs);
privateHeaderArgs.Parse(&privateHeaderArgVector.GetVector(), &unknownArgs);
+ publicHeaderArgs.Parse (&publicHeaderArgVector.GetVector(), &unknownArgs);
+ resourceArgs.Parse (&resourceArgVector.GetVector(), &unknownArgs);
if(!unknownArgs.empty())
{
@@ -225,18 +225,18 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
runtimeArgs.SetGenericArguments(&genericArgs);
frameworkArgs.SetGenericArguments(&genericArgs);
bundleArgs.SetGenericArguments(&genericArgs);
- resourcesArgs.SetGenericArguments(&genericArgs);
- publicHeaderArgs.SetGenericArguments(&genericArgs);
privateHeaderArgs.SetGenericArguments(&genericArgs);
+ publicHeaderArgs.SetGenericArguments(&genericArgs);
+ resourceArgs.SetGenericArguments(&genericArgs);
success = success && archiveArgs.Finalize();
success = success && libraryArgs.Finalize();
success = success && runtimeArgs.Finalize();
success = success && frameworkArgs.Finalize();
success = success && bundleArgs.Finalize();
- success = success && resourcesArgs.Finalize();
- success = success && publicHeaderArgs.Finalize();
success = success && privateHeaderArgs.Finalize();
+ success = success && publicHeaderArgs.Finalize();
+ success = success && resourceArgs.Finalize();
if(!success)
{
@@ -299,9 +299,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
cmInstallTargetGenerator* runtimeGenerator = 0;
cmInstallTargetGenerator* frameworkGenerator = 0;
cmInstallTargetGenerator* bundleGenerator = 0;
- cmInstallFilesGenerator* resourcesGenerator = 0;
- cmInstallFilesGenerator* publicHeaderGenerator = 0;
cmInstallFilesGenerator* privateHeaderGenerator = 0;
+ cmInstallFilesGenerator* publicHeaderGenerator = 0;
+ cmInstallFilesGenerator* resourceGenerator = 0;
switch(target.GetType())
{
@@ -465,84 +465,98 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// if(target.GetProperty("ASSOCIATED_FILES");
- const char* files = target.GetProperty("PUBLIC_HEADER");
- if ((files) && (*files))
- {
- std::vector<std::string> relFiles;
- cmSystemTools::ExpandListArgument(files, relFiles);
- std::vector<std::string> absFiles;
- if (!this->MakeFilesFullPath("PUBLIC_HEADER", relFiles, absFiles))
- {
- return false;
- }
+ // These well-known sets of files are installed *automatically* for FRAMEWORK
+ // SHARED library targets on the Mac as part of installing the FRAMEWORK.
+ // For other target types or on other platforms, they are not installed
+ // automatically and so we need to create install files generators for them.
+ //
+ bool createInstallGeneratorsForTargetFileSets = true;
- // Create the files install generator.
- if (!publicHeaderArgs.GetDestination().empty())
- {
- publicHeaderGenerator = CreateInstallFilesGenerator(absFiles,
- publicHeaderArgs, false);
- }
- else
- {
- cmOStringStream e;
- e << "TARGETS given no PUBLIC_HEADER DESTINATION for header files\""
- << target.GetName() << "\".";
- this->SetError(e.str().c_str());
- return false;
- }
+ if(cmTarget::SHARED_LIBRARY == target.GetType() &&
+ target.GetPropertyAsBool("FRAMEWORK") &&
+ this->Makefile->IsOn("APPLE"))
+ {
+ createInstallGeneratorsForTargetFileSets = false;
}
- files = target.GetProperty("PRIVATE_HEADER");
- if ((files) && (*files))
+ if(createInstallGeneratorsForTargetFileSets)
{
- std::vector<std::string> relFiles;
- cmSystemTools::ExpandListArgument(files, relFiles);
- std::vector<std::string> absFiles;
- if (!this->MakeFilesFullPath("PRIVATE_HEADER", relFiles, absFiles))
+ const char* files = target.GetProperty("PRIVATE_HEADER");
+ if ((files) && (*files))
{
- 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.
- if (!privateHeaderArgs.GetDestination().empty())
- {
- privateHeaderGenerator = CreateInstallFilesGenerator(absFiles,
+ // Create the files install generator.
+ if (!privateHeaderArgs.GetDestination().empty())
+ {
+ privateHeaderGenerator = CreateInstallFilesGenerator(absFiles,
privateHeaderArgs, false);
+ }
+ else
+ {
+ cmOStringStream e;
+ e << "INSTALL TARGETS - target " << target.GetName() << " has "
+ << "PRIVATE_HEADER files but no PRIVATE_HEADER DESTINATION.";
+ cmSystemTools::Message(e.str().c_str(), "Warning");
+ }
}
- else
- {
- cmOStringStream e;
- e << "TARGETS given no PRIVATE_HEADER DESTINATION for header files\""
- << target.GetName() << "\".";
- this->SetError(e.str().c_str());
- 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))
+ files = target.GetProperty("PUBLIC_HEADER");
+ if ((files) && (*files))
{
- return false;
- }
+ std::vector<std::string> relFiles;
+ cmSystemTools::ExpandListArgument(files, relFiles);
+ std::vector<std::string> absFiles;
+ if (!this->MakeFilesFullPath("PUBLIC_HEADER", relFiles, absFiles))
+ {
+ return false;
+ }
- // Create the files install generator.
- if (!privateHeaderArgs.GetDestination().empty())
- {
- resourcesGenerator = CreateInstallFilesGenerator(absFiles,
- resourcesArgs, 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;
- e << "TARGETS given no RESOURCES DESTINATION for resource files\""
- << target.GetName() << "\".";
- this->SetError(e.str().c_str());
- return false;
+ std::vector<std::string> relFiles;
+ cmSystemTools::ExpandListArgument(files, relFiles);
+ std::vector<std::string> absFiles;
+ if (!this->MakeFilesFullPath("RESOURCE", relFiles, absFiles))
+ {
+ 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(frameworkGenerator);
this->Makefile->AddInstallGenerator(bundleGenerator);
- this->Makefile->AddInstallGenerator(publicHeaderGenerator);
this->Makefile->AddInstallGenerator(privateHeaderGenerator);
- this->Makefile->AddInstallGenerator(resourcesGenerator);
+ this->Makefile->AddInstallGenerator(publicHeaderGenerator);
+ this->Makefile->AddInstallGenerator(resourceGenerator);
if (!exports.GetString().empty())
{
@@ -577,11 +591,11 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
->AddInstallComponent(bundleArgs.GetComponent().c_str());
this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
- ->AddInstallComponent(resourcesArgs.GetComponent().c_str());
+ ->AddInstallComponent(privateHeaderArgs.GetComponent().c_str());
this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
->AddInstallComponent(publicHeaderArgs.GetComponent().c_str());
this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
- ->AddInstallComponent(privateHeaderArgs.GetComponent().c_str());
+ ->AddInstallComponent(resourceArgs.GetComponent().c_str());
return true;
}
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index 347d8fe3e9..abe9348963 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -238,8 +238,18 @@ cmInstallTargetGenerator
{
// Compute the build tree location of the framework directory
std::string from1 = fromDirConfig;
- // Remove trailing slashes
- cmSystemTools::ConvertToUnixSlashes(from1);
+ if(config && *config)
+ {
+ from1 += "/";
+ from1 += targetName;
+ from1 += ".framework";
+ }
+ else
+ {
+ // Remove trailing slashes... so that from1 ends with ".framework":
+ //
+ cmSystemTools::ConvertToUnixSlashes(from1);
+ }
files.push_back(from1);
type = cmTarget::INSTALL_DIRECTORY;
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 5f5cbee727..a2aedd56eb 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -252,16 +252,12 @@ void cmMakefileLibraryTargetGenerator::CreateFrameworkLinksAndDirs(
symlink2 = "Resources";
cmSystemTools::CreateSymlink(symlink.c_str(), symlink2.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
symlink = "Versions/Current/Headers";
symlink2 = "Headers";
cmSystemTools::CreateSymlink(symlink.c_str(), symlink2.c_str());
this->Makefile->AddCMakeOutputFile((outpath + "Headers").c_str());
+ // PrivateHeaders -> Versions/Current/PrivateHeaders
symlink = "Versions/Current/PrivateHeaders";
symlink2 = "PrivateHeaders";
cmSystemTools::CreateSymlink(symlink.c_str(), symlink2.c_str());
@@ -278,12 +274,14 @@ void cmMakefileLibraryTargetGenerator::CopyFrameworkSources(
const char* propertyName,
const char* subdir)
{
- std::string fullOutput= outpath + targetName;
+ std::string fullOutput = outpath + targetName;
cmCustomCommandLines commandLines;
std::vector<std::string> depends;
const std::vector<cmSourceFile*>& sources =
this->Target->GetSourceFiles();
+ std::string propName(propertyName);
+
for(std::vector<cmSourceFile*>::const_iterator i = sources.begin();
i != sources.end(); ++i)
{
@@ -296,16 +294,20 @@ void cmMakefileLibraryTargetGenerator::CopyFrameworkSources(
continue;
}
+ cmTarget::SourceFileFlags tsFlags =
+ this->Target->GetTargetSourceFileFlags(sf);
+
// If processing public headers, skip headers also marked with the private
// property. Private wins.
//
- if((std::string(propertyName) == "FRAMEWORK_PUBLIC_HEADER") &&
- sf->GetPropertyAsBool("FRAMEWORK_PRIVATE_HEADER"))
+ if(tsFlags.PrivateHeader && (propName == "PUBLIC_HEADER"))
{
continue;
}
- if(sf->GetPropertyAsBool(propertyName))
+ if(tsFlags.PrivateHeader && (propName == "PRIVATE_HEADER") ||
+ tsFlags.PublicHeader && (propName == "PUBLIC_HEADER") ||
+ tsFlags.Resource && (propName == "RESOURCE"))
{
cmCustomCommandLine line;
std::string dest = outpath + subdir + "/";
@@ -318,8 +320,7 @@ void cmMakefileLibraryTargetGenerator::CopyFrameworkSources(
line.push_back(dest);
commandLines.push_back(line);
// make sure the target gets rebuilt if any of the headers is removed
- this->GenerateExtraOutput(dest.c_str(),
- fullOutput.c_str());
+ this->GenerateExtraOutput(dest.c_str(), fullOutput.c_str());
}
}
@@ -345,12 +346,11 @@ void cmMakefileLibraryTargetGenerator::CreateFramework(
const char* version = this->Target->GetProperty("FRAMEWORK_VERSION");
if(!version)
{
+ version = this->Target->GetProperty("VERSION");
+ }
+ if(!version)
+ {
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
this->CreateFrameworkLinksAndDirs(targetName,
@@ -383,13 +383,13 @@ void cmMakefileLibraryTargetGenerator::CreateFramework(
false, false, false);
this->CopyFrameworkSources(targetName, outpath, version,
- "FRAMEWORK_PRIVATE_HEADER", "PrivateHeaders");
+ "PRIVATE_HEADER", "PrivateHeaders");
this->CopyFrameworkSources(targetName, outpath, version,
- "FRAMEWORK_PUBLIC_HEADER", "Headers");
+ "PUBLIC_HEADER", "Headers");
this->CopyFrameworkSources(targetName, outpath, version,
- "FRAMEWORK_RESOURCE", "Resources");
+ "RESOURCE", "Resources");
}
//----------------------------------------------------------------------------
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 569d76117f..f0b27805c4 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -1170,7 +1170,7 @@ std::string cmMakefileTargetGenerator::GetFrameworkFlags()
// will already have added a -F for the framework
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;
frameworkDir += "/../";
diff --git a/Source/cmOrderLinkDirectories.cxx b/Source/cmOrderLinkDirectories.cxx
index 5636657cec..57b747047f 100644
--- a/Source/cmOrderLinkDirectories.cxx
+++ b/Source/cmOrderLinkDirectories.cxx
@@ -466,28 +466,29 @@ bool cmOrderLinkDirectories::DetermineLibraryPathOrder()
// if it is a full path to an item then separate it from the path
// this only works with files and paths
cmStdString& item = this->RawLinkItems[i];
+
if(cmSystemTools::FileIsFullPath(item.c_str()))
{
- if(cmSystemTools::FileIsDirectory(item.c_str()))
+ if(cmSystemTools::IsPathToFramework(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)
{
- 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;
+ std::string fpath = "-F";
+ fpath += cmSystemTools::ConvertToOutputPath(path.c_str());
+ this->LinkItems.push_back(fpath);
}
- else
+ // 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(!framework)
{
// A full path to a directory was found as a link item
// warn user
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 0a2cda4bf5..ba7361558e 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -688,6 +688,83 @@ cmSourceFile* cmTarget::AddSource(const char* s)
}
//----------------------------------------------------------------------------
+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,
const char *selfname,
const LinkLibraryVectorType& libs )
@@ -816,10 +893,17 @@ void cmTarget::AddLinkLibrary(const std::string& lib,
}
//----------------------------------------------------------------------------
+bool cmTarget::NameResolvesToFramework(const std::string& libname)
+{
+ return this->GetMakefile()->GetLocalGenerator()->GetGlobalGenerator()->
+ NameResolvesToFramework(libname);
+}
+
+//----------------------------------------------------------------------------
bool cmTarget::AddFramework(const std::string& libname, LinkLibraryType llt)
{
(void)llt; // TODO: What is this?
- if(cmSystemTools::IsPathToFramework(libname.c_str()))
+ if(this->NameResolvesToFramework(libname.c_str()))
{
std::string frameworkDir = libname;
frameworkDir += "/../";
@@ -1239,7 +1323,8 @@ const char* cmTarget::NormalGetDirectory(const char* config, bool implib)
{
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.
this->Makefile->GetLocalGenerator()->GetGlobalGenerator()->
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
// libraries, and executables.
@@ -2332,18 +2417,27 @@ const char* cmTarget::GetOutputDir(bool implib)
}
#endif
- // Make sure the output path exists on disk.
- if(!cmSystemTools::MakeDirectory(out.c_str()))
+ // Optionally make sure the output path exists on disk.
+ if(create)
{
- cmSystemTools::Error("Error failed to create output directory:",
- out.c_str());
+ if(!cmSystemTools::MakeDirectory(out.c_str()))
+ {
+ cmSystemTools::Error("Error failed to create output directory: ",
+ out.c_str());
+ }
}
- }
+ }
return out.c_str();
}
//----------------------------------------------------------------------------
+const char* cmTarget::GetOutputDir(bool implib)
+{
+ return this->GetAndCreateOutputDir(implib, true);
+}
+
+//----------------------------------------------------------------------------
const char* cmTarget::GetExportMacro()
{
// Define the symbol for targets that export symbols.
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index be0ed658d3..44e0a051be 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -84,6 +84,23 @@ public:
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.
*/
void AddSources(std::vector<std::string> const& srcs);
@@ -109,6 +126,7 @@ public:
void ClearDependencyInformation(cmMakefile& mf, const char* target);
// 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);
void AddLinkLibrary(cmMakefile& mf,
const char *target, const char* lib,
@@ -360,6 +378,9 @@ private:
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.
const char* GetOutputDir(bool implib);
const char* ImportedGetLocation(const char* config);
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 930ac2524d..728f9068de 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -45,7 +45,6 @@ IF(BUILD_TESTING)
ADD_TEST_MACRO(LoadCommand LoadedCommand)
ADD_TEST_MACRO(LinkLine LinkLine)
ADD_TEST_MACRO(MacroTest miniMacroTest)
- ADD_TEST_MACRO(Framework bar)
ADD_TEST_MACRO(Properties Properties)
ADD_TEST_MACRO(Assembler HelloAsm)
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(CMAKE_BUILD_NIGHTLY_WINDOWS_TEST)
-
+
# 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}
--build-and-test
"${CMake_SOURCE_DIR}/Tests/TargetName"
diff --git a/Tests/Framework/CMakeLists.txt b/Tests/Framework/CMakeLists.txt
index 57028d75ba..4f42b97d05 100644
--- a/Tests/Framework/CMakeLists.txt
+++ b/Tests/Framework/CMakeLists.txt
@@ -10,26 +10,34 @@ add_library(foo SHARED
fooBoth.h
test.lua
)
+
+set(foo_ver ver4)
+
set_target_properties(foo PROPERTIES
FRAMEWORK TRUE
- FRAMEWORK_VERSION ver3
-)
-# fooNeither.h is marked neither public nor private...
-# fooBoth.h is marked both public and private... (private wins...)
-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
+ FRAMEWORK_VERSION ${foo_ver}
+ PRIVATE_HEADER "fooPrivate.h;fooBoth.h"
+ PUBLIC_HEADER "foo.h;foo2.h;fooPublic.h;fooBoth.h"
+ RESOURCE "test.lua"
)
+# 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)
target_link_libraries(bar foo)
install(TARGETS foo bar
- RUNTIME DESTINATION /Applications/CMakeTestsFramework/bin
- FRAMEWORK DESTINATION /Library/Frameworks
+ RUNTIME DESTINATION Applications/CMakeTestsFramework/bin
+ 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
@@ -53,3 +61,5 @@ set_target_properties(fooStatic PROPERTIES
)
add_executable(barStatic bar.cxx)
target_link_libraries(barStatic fooStatic)
+
+include(CPack)