ENH: Cleanup building of OS X bundle content

- Fixes repeated rebuild of bundles by Makefile generators
 - Add special rules to copy sources to their
   MACOSX_PACKAGE_LOCATION bundle directory
 - Remove MacOSX_Content language hack
   - Remove EXTRA_CONTENT property
   - Remove MACOSX_CONTENT
   - Remove corresponding special cases in object names
This commit is contained in:
Brad King 2008-02-15 11:22:23 -05:00
parent 6ea4eea183
commit ed76198b84
8 changed files with 107 additions and 161 deletions

View File

@ -109,8 +109,6 @@ ENDIF(XCODE)
# line works around the problem. # line works around the problem.
SET(CMAKE_LINK_DEPENDENT_LIBRARY_FILES 1) SET(CMAKE_LINK_DEPENDENT_LIBRARY_FILES 1)
SET(CMAKE_MacOSX_Content_COMPILE_OBJECT "\"${CMAKE_COMMAND}\" -E copy_if_different <SOURCE> <OBJECT>")
SET(CMAKE_C_CREATE_SHARED_LIBRARY_FORBIDDEN_FLAGS -w) SET(CMAKE_C_CREATE_SHARED_LIBRARY_FORBIDDEN_FLAGS -w)
SET(CMAKE_CXX_CREATE_SHARED_LIBRARY_FORBIDDEN_FLAGS -w) SET(CMAKE_CXX_CREATE_SHARED_LIBRARY_FORBIDDEN_FLAGS -w)
SET(CMAKE_C_CREATE_SHARED_LIBRARY SET(CMAKE_C_CREATE_SHARED_LIBRARY

View File

@ -1887,74 +1887,32 @@ cmLocalUnixMakefileGenerator3
std::string* nameWithoutTargetDir, std::string* nameWithoutTargetDir,
bool* hasSourceExtension) bool* hasSourceExtension)
{ {
if(const char* fileTargetDirectory = // Make sure we never hit this old case.
source.GetProperty("MACOSX_PACKAGE_LOCATION")) if(source.GetProperty("MACOSX_PACKAGE_LOCATION"))
{ {
// Special handling for OSX package files. abort();
std::string objectName =
this->GetObjectFileNameWithoutTarget(source, 0,
hasSourceExtension);
if(nameWithoutTargetDir)
{
*nameWithoutTargetDir = objectName;
}
objectName = cmSystemTools::GetFilenameName(objectName.c_str());
std::string targetName;
std::string targetNameReal;
std::string targetNameImport;
std::string targetNamePDB;
target.GetExecutableNames(targetName, targetNameReal, targetNameImport,
targetNamePDB, this->ConfigurationName.c_str());
std::string obj;
// Construct the full path version of the names.
//
// If target is a MACOSX_BUNDLE target, then the package location is
// relative to "${targetDir}/${targetName}.app/Contents"... else it is
// relative to "${targetDir}"...
//
obj = target.GetDirectory();
obj += "/";
if ( target.GetPropertyAsBool("MACOSX_BUNDLE") )
{
obj += targetName + ".app/Contents/";
}
else
{
// Emit warning here...? MACOSX_PACKAGE_LOCATION is "most useful" in a
// MACOSX_BUNDLE...
}
obj += fileTargetDirectory;
// Object names are specified relative to the current build dir.
obj = this->Convert(obj.c_str(), START_OUTPUT);
obj += "/";
obj += objectName;
return obj;
} }
else
// Start with the target directory.
std::string obj = this->GetTargetDirectory(target);
obj += "/";
// Get the object file name without the target directory.
std::string::size_type dir_len = 0;
dir_len += strlen(this->Makefile->GetCurrentOutputDirectory());
dir_len += 1;
dir_len += obj.size();
std::string objectName =
this->GetObjectFileNameWithoutTarget(source, dir_len,
hasSourceExtension);
if(nameWithoutTargetDir)
{ {
// Start with the target directory. *nameWithoutTargetDir = objectName;
std::string obj = this->GetTargetDirectory(target);
obj += "/";
// Get the object file name without the target directory.
std::string::size_type dir_len = 0;
dir_len += strlen(this->Makefile->GetCurrentOutputDirectory());
dir_len += 1;
dir_len += obj.size();
std::string objectName =
this->GetObjectFileNameWithoutTarget(source, dir_len,
hasSourceExtension);
if(nameWithoutTargetDir)
{
*nameWithoutTargetDir = objectName;
}
// Append the object name to the target directory.
obj += objectName;
return obj;
} }
// Append the object name to the target directory.
obj += objectName;
return obj;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View File

@ -83,11 +83,6 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
obj != this->Objects.end(); ++obj) obj != this->Objects.end(); ++obj)
{ {
objTarget = relPath; objTarget = relPath;
// Handle extra content on Mac bundles
if ( this->ExtraContent.find(*obj) != this->ExtraContent.end() )
{
objTarget = "";
}
objTarget += *obj; objTarget += *obj;
depends.push_back(objTarget); depends.push_back(objTarget);
} }
@ -120,8 +115,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
// Construct the full path version of the names. // Construct the full path version of the names.
std::string outpath = this->Target->GetDirectory(); std::string outpath = this->Target->GetDirectory();
outpath += "/"; outpath += "/";
#ifdef __APPLE__ if(this->Target->IsAppBundleOnApple())
if(this->Target->GetPropertyAsBool("MACOSX_BUNDLE"))
{ {
// Compute bundle directory names. // Compute bundle directory names.
std::string macdir = outpath; std::string macdir = outpath;
@ -132,27 +126,6 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
cmSystemTools::MakeDirectory(outpath.c_str()); cmSystemTools::MakeDirectory(outpath.c_str());
outpath += "/"; outpath += "/";
// Make bundle directories
std::vector<cmSourceFile*>::const_iterator sourceIt;
for ( sourceIt = this->Target->GetSourceFiles().begin();
sourceIt != this->Target->GetSourceFiles().end();
++ sourceIt )
{
const char* subDir =
(*sourceIt)->GetProperty("MACOSX_PACKAGE_LOCATION");
if ( subDir )
{
std::string newDir = macdir;
newDir += subDir;
if ( !cmSystemTools::MakeDirectory(newDir.c_str()) )
{
cmSystemTools::Error("Cannot create a subdirectory for \"",
newDir.c_str(), "\".");
return;
}
}
}
// Configure the Info.plist file. Note that it needs the executable name // Configure the Info.plist file. Note that it needs the executable name
// to be set. // to be set.
std::string plist = macdir + "Info.plist"; std::string plist = macdir + "Info.plist";
@ -160,7 +133,6 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
targetName.c_str(), targetName.c_str(),
plist.c_str()); plist.c_str());
} }
#endif
std::string outpathImp; std::string outpathImp;
if(relink) if(relink)
{ {

View File

@ -150,6 +150,11 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
} }
} }
} }
else if(const char* pkgloc =
(*source)->GetProperty("MACOSX_PACKAGE_LOCATION"))
{
this->WriteMacOSXContentRules(*(*source), pkgloc);
}
else if(!(*source)->GetPropertyAsBool("HEADER_FILE_ONLY")) else if(!(*source)->GetPropertyAsBool("HEADER_FILE_ONLY"))
{ {
if(!this->GlobalGenerator->IgnoreFile if(!this->GlobalGenerator->IgnoreFile
@ -313,6 +318,62 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
} }
} }
//----------------------------------------------------------------------------
void cmMakefileTargetGenerator::WriteMacOSXContentRules(cmSourceFile& source,
const char* pkgloc)
{
// Skip OS X bundle content when not building a bundle.
if(!this->Target->IsAppBundleOnApple()) { return; }
// Create the directory in which the content is to be placed.
std::string targetName;
std::string targetNameReal;
std::string targetNameImport;
std::string targetNamePDB;
this->Target->GetExecutableNames
(targetName, targetNameReal, targetNameImport, targetNamePDB,
this->LocalGenerator->ConfigurationName.c_str());
std::string macdir = this->Target->GetDirectory();
macdir += "/";
macdir += targetName;
macdir += ".app/Contents/";
macdir += pkgloc;
cmSystemTools::MakeDirectory(macdir.c_str());
// Get the input file location.
std::string input = source.GetFullPath();
// Get the output file location.
std::string output = macdir;
output += "/";
output += cmSystemTools::GetFilenameName(input);
this->CleanFiles.push_back(this->Convert(output.c_str(),
cmLocalGenerator::START_OUTPUT));
output = this->Convert(output.c_str(), cmLocalGenerator::HOME_OUTPUT);
// Create a rule to copy the content into the bundle.
std::vector<std::string> depends;
std::vector<std::string> commands;
depends.push_back(input);
std::string copyEcho = "Copying Bundle content ";
copyEcho += output;
this->LocalGenerator->AppendEcho(commands, copyEcho.c_str(),
cmLocalUnixMakefileGenerator3::EchoBuild);
std::string copyCommand = "$(CMAKE_COMMAND) -E copy ";
copyCommand += this->Convert(input.c_str(),
cmLocalGenerator::NONE,
cmLocalGenerator::SHELL);
copyCommand += " ";
copyCommand += this->Convert(output.c_str(),
cmLocalGenerator::NONE,
cmLocalGenerator::SHELL);
commands.push_back(copyCommand);
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
output.c_str(),
depends, commands, false);
this->ExtraFiles.insert(output);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile& source) void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile& source)
{ {
@ -356,10 +417,6 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile& source)
(this->LocalGenerator->ConvertToFullPath(dir).c_str()); (this->LocalGenerator->ConvertToFullPath(dir).c_str());
// Save this in the target's list of object files. // Save this in the target's list of object files.
if ( source.GetPropertyAsBool("EXTRA_CONTENT") )
{
this->ExtraContent.insert(obj);
}
this->Objects.push_back(obj); this->Objects.push_back(obj);
this->CleanFiles.push_back(obj); this->CleanFiles.push_back(obj);
@ -417,10 +474,6 @@ cmMakefileTargetGenerator
this->WriteObjectDependRules(source, depends); this->WriteObjectDependRules(source, depends);
std::string relativeObj = this->LocalGenerator->GetHomeRelativeOutputPath(); std::string relativeObj = this->LocalGenerator->GetHomeRelativeOutputPath();
if ( source.GetPropertyAsBool("MACOSX_CONTENT") )
{
relativeObj = "";
}
relativeObj += obj; relativeObj += obj;
// Write the build rule. // Write the build rule.
@ -1143,10 +1196,6 @@ cmMakefileTargetGenerator
for(std::vector<std::string>::const_iterator i = this->Objects.begin(); for(std::vector<std::string>::const_iterator i = this->Objects.begin();
i != this->Objects.end(); ++i) i != this->Objects.end(); ++i)
{ {
if ( this->ExtraContent.find(i->c_str()) != this->ExtraContent.end() )
{
continue;
}
*this->BuildFileStream << " " << lineContinue << "\n"; *this->BuildFileStream << " " << lineContinue << "\n";
if(objName) if(objName)
{ {
@ -1277,10 +1326,6 @@ cmMakefileTargetGenerator
for(std::vector<std::string>::const_iterator i = this->Objects.begin(); for(std::vector<std::string>::const_iterator i = this->Objects.begin();
i != this->Objects.end(); ++i) i != this->Objects.end(); ++i)
{ {
if ( this->ExtraContent.find(i->c_str()) != this->ExtraContent.end() )
{
continue;
}
helper.Feed(*i); helper.Feed(*i);
} }
for(std::vector<std::string>::const_iterator i = for(std::vector<std::string>::const_iterator i =
@ -1328,6 +1373,13 @@ void cmMakefileTargetGenerator::WriteTargetDriverRule(const char* main_output,
{ {
this->DriveCustomCommands(depends); this->DriveCustomCommands(depends);
} }
// Make sure the extra files are built.
for(std::set<cmStdString>::const_iterator i = this->ExtraFiles.begin();
i != this->ExtraFiles.end(); ++i)
{
depends.push_back(*i);
}
} }
// Write the driver rule. // Write the driver rule.

View File

@ -82,6 +82,9 @@ protected:
// write the depend rules for this target // write the depend rules for this target
void WriteTargetDependRules(); void WriteTargetDependRules();
// write rules for Mac OS X Application Bundle content.
void WriteMacOSXContentRules(cmSourceFile& source, const char* pkgloc);
// write the rules for an object // write the rules for an object
void WriteObjectRuleFiles(cmSourceFile& source); void WriteObjectRuleFiles(cmSourceFile& source);
@ -178,11 +181,13 @@ protected:
// objects used by this target // objects used by this target
std::vector<std::string> Objects; std::vector<std::string> Objects;
std::vector<std::string> ExternalObjects; std::vector<std::string> ExternalObjects;
std::set<std::string> ExtraContent;
// Set of object file names that will be built in this directory. // Set of object file names that will be built in this directory.
std::set<cmStdString> ObjectFiles; std::set<cmStdString> ObjectFiles;
// Set of extra output files to be driven by the build.
std::set<cmStdString> ExtraFiles;
typedef std::map<cmStdString, cmStdString> MultipleOutputPairsType; typedef std::map<cmStdString, cmStdString> MultipleOutputPairsType;
MultipleOutputPairsType MultipleOutputPairs; MultipleOutputPairsType MultipleOutputPairs;

View File

@ -295,11 +295,6 @@ bool cmSetPropertyCommand::HandleSource(cmSourceFile* sf)
{ {
sf->SetProperty(name, this->PropertyValue.c_str()); sf->SetProperty(name, this->PropertyValue.c_str());
} }
// TODO: MACOSX_PACKAGE_LOCATION special case in
// cmSetSourceFilesPropertiesCommand
// The logic should be moved to cmSourceFile.
return true; return true;
} }

View File

@ -119,7 +119,6 @@ bool cmSetSourceFilesPropertiesCommand
{ {
// now loop through the rest of the arguments, new style // now loop through the rest of the arguments, new style
++j; ++j;
bool dontPush = false;
while (j != propend) while (j != propend)
{ {
propertyPairs.push_back(*j); propertyPairs.push_back(*j);
@ -131,26 +130,6 @@ bool cmSetSourceFilesPropertiesCommand
generated = true; generated = true;
} }
} }
else if(*j == "MACOSX_PACKAGE_LOCATION")
{
++j;
if(j == propend)
{
errors = "called with incorrect number of arguments "
"MACOSX_PACKAGE_LOCATION with no flags";
return false;
}
propertyPairs.push_back(*j);
propertyPairs.push_back("EXTRA_CONTENT");
propertyPairs.push_back("1");
propertyPairs.push_back("MACOSX_CONTENT");
propertyPairs.push_back("1");
propertyPairs.push_back("KEEP_EXTENSION");
propertyPairs.push_back("1");
propertyPairs.push_back("LANGUAGE");
propertyPairs.push_back("MacOSX_Content");
dontPush = true;
}
else else
{ {
++j; ++j;
@ -160,12 +139,8 @@ bool cmSetSourceFilesPropertiesCommand
errors = "called with incorrect number of arguments."; errors = "called with incorrect number of arguments.";
return false; return false;
} }
if ( !dontPush ) propertyPairs.push_back(*j);
{
propertyPairs.push_back(*j);
}
++j; ++j;
dontPush = false;
} }
// break out of the loop because j is already == end // break out of the loop because j is already == end
break; break;

View File

@ -421,13 +421,6 @@ void cmSourceFile::DefineProperties(cmake *cm)
"is really an object file and should not be compiled. " "is really an object file and should not be compiled. "
"It will still be linked into the target though."); "It will still be linked into the target though.");
cm->DefineProperty
("EXTRA_CONTENT", cmProperty::SOURCE_FILE,
"Is this file part of a target's extra content.",
"If this property is set, the source file will be added to the "
"target's list of extra content. This is used by makefile "
"generators for some sort of Mac budle framework support.");
cm->DefineProperty cm->DefineProperty
("GENERATED", cmProperty::SOURCE_FILE, ("GENERATED", cmProperty::SOURCE_FILE,
"Is this source file generated as part of the build process.", "Is this source file generated as part of the build process.",
@ -467,17 +460,15 @@ void cmSourceFile::DefineProperties(cmake *cm)
cm->DefineProperty cm->DefineProperty
("MACOSX_PACKAGE_LOCATION", cmProperty::SOURCE_FILE, ("MACOSX_PACKAGE_LOCATION", cmProperty::SOURCE_FILE,
"Location for MACOSX bundles and frameworks.", "Place a source file inside a Mac OS X application bundle.",
"MACOSX_PACKAGE_LOCATION is the property of a file within a mac osx " "Executable targets with the MACOSX_BUNDLE property set are built "
"bundle or framework that specifies where this file should be " "as Mac OS X application bundles on Apple platforms. "
"copied. This makes sense for things like icons and other " "Source files specified for the target with the "
"resources."); "MACOSX_PACKAGE_LOCATION property set will be placed in the "
"application bundle Contents folder under the directory specified "
cm->DefineProperty "by the value of the property. "
("MACOSX_CONTENT", cmProperty::SOURCE_FILE, "Typically this is set to \"Resources\" for icon files and other "
"If true then this is part of a MACOSX bundle or framework.", "bundle resources.");
"MACOSX_CONTENT is a flag that if true this file will be copied "
"to the bundle or framework.");
cm->DefineProperty cm->DefineProperty
("OBJECT_DEPENDS", cmProperty::SOURCE_FILE, ("OBJECT_DEPENDS", cmProperty::SOURCE_FILE,