Commit 40272a16 authored by Andy Cedilnik's avatar Andy Cedilnik

ENH: Add support for adding content to bundles

parent 5d722df2
......@@ -47,6 +47,8 @@ IF(NOT XCODE)
SET(CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG "-install_name")
ENDIF(NOT XCODE)
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_CXX_CREATE_SHARED_LIBRARY_FORBIDDEN_FLAGS -w)
SET(CMAKE_C_CREATE_SHARED_LIBRARY
......
......@@ -1542,15 +1542,54 @@ cmLocalUnixMakefileGenerator3
{
objectName = objectName.substr(0, dot_pos);
}
objectName +=
this->GlobalGenerator->GetLanguageOutputExtensionFromExtension(
source.GetSourceExtension().c_str());
if ( source.GetPropertyAsBool("KEEP_EXTENSION") )
{
if ( !source.GetSourceExtension().empty() )
{
objectName += "." + source.GetSourceExtension();
}
}
else
{
objectName +=
this->GlobalGenerator->GetLanguageOutputExtensionFromExtension(
source.GetSourceExtension().c_str());
}
// Convert to a safe name.
objectName = this->CreateSafeUniqueObjectFileName(objectName.c_str());
// Prepend the target directory.
std::string obj = this->GetTargetDirectory(target);
std::string obj;
const char* fileTargetDirectory = source.GetProperty("MACOSX_PACKAGE_LOCATION");
if ( fileTargetDirectory )
{
std::string targetName;
std::string targetNameReal;
target.GetExecutableNames(targetName, targetNameReal,
this->ConfigurationName.c_str());
if ( target.GetPropertyAsBool("MACOSX_BUNDLE") )
{
// Construct the full path version of the names.
obj = this->ExecutableOutputPath;
if(obj.empty())
{
obj = this->Makefile->GetStartOutputDirectory();
obj += "/";
}
obj += targetName + ".app/Contents/";
obj += fileTargetDirectory;
}
else
{
// Framework not handled yet
abort();
}
}
else
{
obj = this->GetTargetDirectory(target);
}
obj += "/";
obj += objectName;
if(nameWithoutTargetDir)
......@@ -1763,6 +1802,11 @@ const char*
cmLocalUnixMakefileGenerator3
::GetSourceFileLanguage(const cmSourceFile& source)
{
const char* lang = source.GetProperty("LANGUAGE");
if ( lang )
{
return lang;
}
// Identify the language of the source file.
return (this->GlobalGenerator
->GetLanguageFromExtension(source.GetSourceExtension().c_str()));
......
......@@ -28,7 +28,7 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
{
// create the build.make file and directory, put in the common blocks
this->CreateRuleFile();
// Add in any rules for custom commands
this->WriteCustomCommandsForTarget();
......@@ -82,8 +82,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
// Add a dependency on the rule file itself.
this->LocalGenerator->AppendRuleDepend(depends,
this->BuildFileNameFull.c_str());
for(std::vector<std::string>::const_iterator obj =
for(std::vector<std::string>::const_iterator obj =
this->ExternalObjects.begin();
obj != this->ExternalObjects.end(); ++obj)
{
......@@ -111,13 +111,13 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
// Make bundle directories
outpath += targetName;
outpath += ".app/Contents/MacOS/";
std::string f1 =
std::string f1 =
this->Makefile->GetModulesFile("MacOSXBundleInfo.plist.in");
if ( f1.size() == 0 )
{
cmSystemTools::Error("could not find Mac OSX bundle template file.");
}
std::string macdir =
std::string macdir =
this->Makefile->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
if ( macdir.size() == 0 )
{
......@@ -130,6 +130,25 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
macdir += targetName;
macdir += ".app/Contents/";
std::vector<cmSourceFile*>::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
// to be set.
std::string f2 = macdir + "Info.plist";
......@@ -232,7 +251,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
cmLocalGenerator::START_OUTPUT,
cmLocalGenerator::UNCHANGED));
}
}
}
// Add a command to remove any existing files for this executable.
std::vector<std::string> commands1;
......@@ -240,7 +259,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
*this->Target, "target");
this->LocalGenerator->CreateCDCommand(commands1,
this->Makefile->GetStartOutputDirectory(),
this->Makefile->GetHomeOutputDirectory());
this->Makefile->GetHomeOutputDirectory());
commands.insert(commands.end(), commands1.begin(), commands1.end());
commands1.clear();
......@@ -257,7 +276,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
std::string linkRuleVar = "CMAKE_";
linkRuleVar += linkLanguage;
linkRuleVar += "_LINK_EXECUTABLE";
std::string linkRule =
std::string linkRule =
this->Makefile->GetRequiredDefinition(linkRuleVar.c_str());
cmSystemTools::ExpandListArgument(linkRule, commands1);
this->LocalGenerator->CreateCDCommand
......@@ -317,9 +336,9 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
}
// Write the build rule.
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream,
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream,
0,
targetFullPathReal.c_str(),
targetFullPathReal.c_str(),
depends, commands, false);
// The symlink name for the target should depend on the real target
......@@ -331,7 +350,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
commands.clear();
depends.push_back(targetFullPathReal.c_str());
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
targetFullPath.c_str(),
targetFullPath.c_str(),
depends, commands, false);
}
......@@ -341,11 +360,11 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
dir += this->LocalGenerator->GetTargetDirectory(*this->Target);
std::string buildTargetRuleName = dir;
buildTargetRuleName += relink?"/preinstall":"/build";
buildTargetRuleName =
buildTargetRuleName =
this->Convert(buildTargetRuleName.c_str(),
cmLocalGenerator::HOME_OUTPUT,
cmLocalGenerator::MAKEFILE);
this->LocalGenerator->WriteConvenienceRule(*this->BuildFileStream,
this->LocalGenerator->WriteConvenienceRule(*this->BuildFileStream,
targetFullPath.c_str(),
buildTargetRuleName.c_str());
......
......@@ -237,8 +237,6 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
}
}
//----------------------------------------------------------------------------
void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile& source)
{
......@@ -282,6 +280,10 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile& source)
(this->LocalGenerator->ConvertToFullPath(dir).c_str());
// Save this in the target's list of object files.
if ( source.GetPropertyAsBool("EXTRA_CONTENT") )
{
this->ExtraContent.insert(obj);
}
this->Objects.push_back(obj);
std::string relativeObj = this->LocalGenerator->GetHomeRelativeOutputPath();
relativeObj += obj;
......@@ -587,6 +589,7 @@ void cmMakefileTargetGenerator
}
}
//----------------------------------------------------------------------------
void cmMakefileTargetGenerator::WriteCustomCommands()
{
// add custom commands to the clean rules?
......@@ -667,6 +670,10 @@ cmMakefileTargetGenerator
for(std::vector<std::string>::const_iterator i = this->Objects.begin();
i != this->Objects.end(); ++i)
{
if ( this->ExtraContent.find(i->c_str()) != this->ExtraContent.end() )
{
continue;
}
*this->BuildFileStream << " " << lineContinue << "\n";
if(objName)
{
......
......@@ -34,7 +34,7 @@ class cmSourceFile;
* \brief Support Routines for writing makefiles
*
*/
class cmMakefileTargetGenerator
class cmMakefileTargetGenerator
{
public:
// constructor to set the ivars
......@@ -49,12 +49,12 @@ public:
/* the main entry point for this class. Writes the Makefiles associated
with this target */
virtual void WriteRuleFiles() = 0;
protected:
// create the file and directory etc
void CreateRuleFile();
// outputs the rules for any custom commands used by this target
void WriteCustomCommandsForTarget();
......@@ -75,38 +75,38 @@ protected:
// write the build rule for an object
void WriteObjectBuildFile(std::string &obj,
const char *lang,
const char *lang,
cmSourceFile& source,
std::vector<std::string>& depends);
// write the depend.make file for an object
void WriteObjectDependRules(cmSourceFile& source,
std::vector<std::string>& depends);
// this is responsible for writing all of the rules for all this
// directories custom commands (but not utility targets)
void WriteCustomCommands();
void GenerateCustomRuleFile(const cmCustomCommand& cc);
// write out the variable that lists the objects for this target
void WriteObjectsVariable(std::string& variableName,
std::string& variableNameExternal);
// Return the a string with -F flags on apple
std::string GetFrameworkFlags();
// append intertarget dependencies
void AppendTargetDepends(std::vector<std::string>& depends);
virtual void CloseFileStreams();
void RemoveForbiddenFlags(const char* flagVar, const char* linkLang,
void RemoveForbiddenFlags(const char* flagVar, const char* linkLang,
std::string& linkFlags);
cmStdString TargetName;
cmTarget *Target;
cmLocalUnixMakefileGenerator3 *LocalGenerator;
cmGlobalGenerator *GlobalGenerator;
cmMakefile *Makefile;
// the full path to the build file
std::string BuildFileName;
std::string BuildFileNameFull;
......@@ -132,19 +132,20 @@ protected:
// objects used by this target
std::vector<std::string> Objects;
std::vector<std::string> ExternalObjects;
std::set<std::string> ExtraContent;
// Set of object file names that will be built in this directory.
std::set<cmStdString> ObjectFiles;
//==================================================================
// Convenience routines that do nothing more than forward to
// Convenience routines that do nothing more than forward to
// implementaitons
std::string Convert(const char* source,
cmLocalGenerator::RelativeRoot relative,
cmLocalGenerator::OutputFormat output =
std::string Convert(const char* source,
cmLocalGenerator::RelativeRoot relative,
cmLocalGenerator::OutputFormat output =
cmLocalGenerator::UNCHANGED,
bool optional = false)
bool optional = false)
{
return this->LocalGenerator->Convert(source, relative, output, optional);
}
......
......@@ -9,8 +9,8 @@
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
......@@ -63,7 +63,8 @@ bool cmSetSourceFilesPropertiesCommand::InitialPass(
++j;
if(j == args.end())
{
this->SetError("called with incorrect number of arguments COMPILE_FLAGS with no flags");
this->SetError("called with incorrect number of arguments "
"COMPILE_FLAGS with no flags");
return false;
}
propertyPairs.push_back(*j);
......@@ -85,6 +86,7 @@ bool cmSetSourceFilesPropertiesCommand::InitialPass(
{
// now loop through the rest of the arguments, new style
++j;
bool dontPush = false;
while (j != args.end())
{
propertyPairs.push_back(*j);
......@@ -96,6 +98,25 @@ bool cmSetSourceFilesPropertiesCommand::InitialPass(
generated = true;
}
}
else if(*j == "MACOSX_PACKAGE_LOCATION")
{
doingFiles = false;
++j;
if(j == args.end())
{
this->SetError("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("KEEP_EXTENSION");
propertyPairs.push_back("1");
propertyPairs.push_back("LANGUAGE");
propertyPairs.push_back("MacOSX_Content");
dontPush = true;
}
else
{
++j;
......@@ -105,8 +126,12 @@ bool cmSetSourceFilesPropertiesCommand::InitialPass(
this->SetError("called with incorrect number of arguments.");
return false;
}
propertyPairs.push_back(*j);
if ( !dontPush )
{
propertyPairs.push_back(*j);
}
++j;
dontPush = false;
}
// break out of the loop because j is already == end
break;
......@@ -117,16 +142,17 @@ bool cmSetSourceFilesPropertiesCommand::InitialPass(
}
else
{
this->SetError("called with illegal arguments, maybe missing a PROPERTIES specifier?");
this->SetError("called with illegal arguments, maybe missing a "
"PROPERTIES specifier?");
return false;
}
}
// now loop over all the files
int i;
unsigned int k;
for(i = 0; i < numFiles; ++i)
{
{
// get the source file
cmSourceFile* sf =
this->Makefile->GetOrCreateSource(args[i].c_str(), generated);
......
PROJECT(BundleTest)
SET(MACOSX_BUNDLE_INFO_STRING "bundle_info_string")
SET(CMAKE_MacOSX_Content_COMPILE_OBJECT "\"${CMAKE_COMMAND}\" -E copy_if_different <SOURCE> <OBJECT>")
ADD_CUSTOM_COMMAND(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/randomResourceFile.plist"
COMMAND /bin/cp
ARGS "${CMAKE_CURRENT_SOURCE_DIR}/randomResourceFile.plist.in"
"${CMAKE_CURRENT_BINARY_DIR}/randomResourceFile.plist")
SET_SOURCE_FILES_PROPERTIES(
"${CMAKE_CURRENT_BINARY_DIR}/randomResourceFile.plist"
PROPERTIES
MACOSX_PACKAGE_LOCATION Resources
)
SET_SOURCE_FILES_PROPERTIES(
SomeRandomFile.txt
PROPERTIES
MACOSX_PACKAGE_LOCATION MacOS
)
SET(EXECUTABLE_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}/foobar")
# Test building a bundle linking to a shared library.
ADD_LIBRARY(BundleTestLib SHARED BundleLib.cxx)
ADD_EXECUTABLE(BundleTest MACOSX_BUNDLE BundleTest.cxx)
ADD_EXECUTABLE(BundleTest
MACOSX_BUNDLE
BundleTest.cxx
SomeRandomFile.txt
"${CMAKE_CURRENT_BINARY_DIR}/randomResourceFile.plist"
)
TARGET_LINK_LIBRARIES(BundleTest BundleTestLib)
# Test bundle installation.
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Package</key>
<string>CMake</string>
</dict>
</plist>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment