ENH: First pass at CPack generator for OSX X11 applications. This are applications that require X11 to work. This is not really installed but a bundle packager

This commit is contained in:
Andy Cedilnik 2007-01-10 15:30:26 -05:00
parent c2780e2c9a
commit de5540f7e5
10 changed files with 540 additions and 15 deletions

Binary file not shown.

View File

@ -0,0 +1,36 @@
<?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>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>@CPACK_PACKAGE_FILE_NAME@</string>
<key>CFBundleGetInfoString</key>
<string>@CPACK_APPLE_GUI_INFO_STRING@</string>
<key>CFBundleIconFile</key>
<string>@CPACK_APPLE_GUI_ICON@</string>
<key>CFBundleIdentifier</key>
<string>@CPACK_APPLE_GUI_IDENTIFIER@</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
<string>@CPACK_APPLE_GUI_LONG_VERSION_STRING@</string>
<key>CFBundleName</key>
<string>@CPACK_APPLE_GUI_BUNDLE_NAME@</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>@CPACK_APPLE_GUI_SHORT_VERSION_STRING@</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>@CPACK_APPLE_GUI_BUNDLE_VERSION@</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>LSRequiresCarbon</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>@CPACK_APPLE_GUI_COPYRIGHT@</string>
</dict>
</plist>

40
Modules/CPack.RuntimeScript.in Executable file
View File

@ -0,0 +1,40 @@
#!/bin/sh
#
# Modified from: Aaron Voisine <aaron@voisine.org>
CWD="`dirname \"$0\"`"
TMP=/tmp/$UID/TemporaryItems
ps -wx -ocommand | grep -e '[X]11.app' > /dev/null
if [ "$?" != "0" -a ! -f ~/.xinitrc ]; then
echo "rm -f ~/.xinitrc" > ~/.xinitrc
sed 's/xterm/# xterm/' /usr/X11R6/lib/X11/xinit/xinitrc >> ~/.xinitrc
fi
mkdir -p $TMP
cat << __END_OF_GETDISPLAY_SCRIPT__ > "$TMP/getdisplay.sh"
#!/bin/sh
mkdir -p "$TMP"
if [ "\$DISPLAY"x == "x" ]; then
echo :0 > "$TMP/display"
else
echo \$DISPLAY > "$TMP/display"
fi
__END_OF_GETDISPLAY_SCRIPT__
rm -f $TMP/display
open-x11 $TMP/getdisplay.sh || \
open -a XDarwin $TMP/getdisplay.sh || \
echo ":0" > $TMP/display
while [ "$?" == "0" -a ! -f $TMP/display ]; do sleep 1; done
export "DISPLAY=`cat $TMP/display`"
ps -wx -ocommand | grep -e '[X]11' > /dev/null || exit 11
cd ~/
echo "$@" > /tmp/arguments.log
if echo $1 | grep -- "^-psn_"; then
shift
fi
exec "$CWD/bin/@CPACK_EXECUTABLE_NAME@" "$@" > /tmp/slicer.output 2>&1

View File

@ -286,15 +286,16 @@ TARGET_LINK_LIBRARIES(CTestLib CMakeLib ${CMAKE_CURL_LIBRARIES} ${CMAKE_XMLRPC_L
#
SET(CPACK_SRCS
CPack/cmCPackGenerators.cxx
CPack/cmCPackSTGZGenerator.cxx
CPack/cmCPackTGZGenerator.cxx
CPack/cmCPackNSISGenerator.cxx
CPack/cmCPackPackageMakerGenerator.cxx
CPack/cmCPackZIPGenerator.cxx
CPack/cmCPackTarBZip2Generator.cxx
CPack/cmCPackTarCompressGenerator.cxx
CPack/cmCPackGenericGenerator.cxx
CPack/cmCPackLog.cxx
CPack/cmCPackNSISGenerator.cxx
CPack/cmCPackOSXX11Generator.cxx
CPack/cmCPackPackageMakerGenerator.cxx
CPack/cmCPackSTGZGenerator.cxx
CPack/cmCPackTGZGenerator.cxx
CPack/cmCPackTarBZip2Generator.cxx
CPack/cmCPackTarCompressGenerator.cxx
CPack/cmCPackZIPGenerator.cxx
)
# Build CPackLib
ADD_LIBRARY(CPackLib ${CPACK_SRCS})
@ -303,6 +304,10 @@ TARGET_LINK_LIBRARIES(CPackLib CMakeLib)
IF(APPLE)
ADD_EXECUTABLE(cmakexbuild cmakexbuild.cxx)
TARGET_LINK_LIBRARIES(cmakexbuild CMakeLib)
ADD_EXECUTABLE(OSXScriptLauncher
MACOSX_BUNDLE CPack/OSXScriptLauncher.cxx)
TARGET_LINK_LIBRARIES(OSXScriptLauncher cmsys)
TARGET_LINK_LIBRARIES(OSXScriptLauncher "-framework Carbon")
ENDIF(APPLE)
# Build CMake executable

View File

@ -0,0 +1,161 @@
#include <cmsys/SystemTools.hxx>
#include <cmsys/Process.h>
#include <cmsys/ios/fstream>
#include <cmsys/ios/iostream>
#include <Carbon/Carbon.h>
#include <CoreFoundation/CoreFoundation.h>
#define MaximumPathLength 1024
#define DebugError(x) \
ofs << x << cmsys_ios::endl; \
cmsys_ios::cout << x << cmsys_ios::endl
int main(int argc, char* argv[])
{
//if ( cmsys::SystemTools::FileExists(
cmsys_stl::string cwd = cmsys::SystemTools::GetCurrentWorkingDirectory();
cmsys_ios::ofstream ofs("/tmp/output.txt");
CFStringRef fileName;
CFBundleRef appBundle;
CFURLRef scriptFileURL;
FSRef fileRef;
FSSpec fileSpec;
UInt8 *path;
//get CF URL for script
if (! (appBundle = CFBundleGetMainBundle()))
{
DebugError("Cannot get main bundle");
return 1;
}
if (! (fileName = CFStringCreateWithCString(NULL, "RuntimeScript",
kCFStringEncodingASCII)))
{
DebugError("CFStringCreateWithCString failed");
return 1;
}
if (! (scriptFileURL = CFBundleCopyResourceURL(appBundle, fileName, NULL,
NULL)))
{
DebugError("CFBundleCopyResourceURL failed");
return 1;
}
//Get file reference from Core Foundation URL
if (! CFURLGetFSRef(scriptFileURL, &fileRef))
{
DebugError("CFURLGetFSRef failed");
return 1;
}
//dispose of the CF variables
CFRelease(scriptFileURL);
CFRelease(fileName);
//convert FSRef to FSSpec
if (FSGetCatalogInfo(&fileRef, kFSCatInfoNone, NULL, NULL, &fileSpec,
NULL))
{
DebugError("FSGetCatalogInfo failed");
return 1;
}
//create path string
if (! (path = new UInt8[MaximumPathLength]))
{
return 1;
}
OSErr err = noErr;
//create file reference from file spec
if (err = FSpMakeFSRef(&fileSpec, &fileRef)) return err;
// and then convert the FSRef to a path
if ( FSRefMakePath(&fileRef, path, MaximumPathLength) )
{
DebugError("FSRefMakePath failed");
return 1;
}
cmsys_stl::string fullScriptPath = reinterpret_cast<char*>(path);
delete [] path;
if (! cmsys::SystemTools::FileExists(fullScriptPath.c_str()))
{
return 1;
}
cmsys_stl::string scriptDirectory = cmsys::SystemTools::GetFilenamePath(
fullScriptPath);
ofs << fullScriptPath.c_str() << cmsys_ios::endl;
cmsys_stl::vector<const char*> args;
args.push_back(fullScriptPath.c_str());
int cc;
for ( cc = 1; cc < argc; ++ cc )
{
args.push_back(argv[cc]);
}
args.push_back(0);
cmsysProcess* cp = cmsysProcess_New();
cmsysProcess_SetCommand(cp, &*args.begin());
cmsysProcess_SetWorkingDirectory(cp, scriptDirectory.c_str());
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
cmsysProcess_SetTimeout(cp, 0);
cmsysProcess_Execute(cp);
std::vector<char> tempOutput;
char* data;
int length;
while(cmsysProcess_WaitForData(cp, &data, &length, 0))
{
// Translate NULL characters in the output into valid text.
// Visual Studio 7 puts these characters in the output of its
// build process.
for(int i=0; i < length; ++i)
{
if(data[i] == '\0')
{
data[i] = ' ';
}
}
cmsys_ios::cout.write(data, length);
}
cmsysProcess_WaitForExit(cp, 0);
bool result = true;
if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exited)
{
if ( cmsysProcess_GetExitValue(cp) != 0 )
{
result = false;
}
}
else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exception)
{
const char* exception_str = cmsysProcess_GetExceptionString(cp);
std::cerr << exception_str << std::endl;
result = false;
}
else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Error)
{
const char* error_str = cmsysProcess_GetErrorString(cp);
std::cerr << error_str << std::endl;
result = false;
}
else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Expired)
{
const char* error_str = "Process terminated due to timeout\n";
std::cerr << error_str << std::endl;
result = false;
}
cmsysProcess_Delete(cp);
return 0;
}

View File

@ -23,8 +23,13 @@
#include "cmCPackTarCompressGenerator.h"
#include "cmCPackZIPGenerator.h"
#include "cmCPackSTGZGenerator.h"
#include "cmCPackNSISGenerator.h"
#include "cmCPackPackageMakerGenerator.h"
#ifdef _WIN32
# include "cmCPackNSISGenerator.h"
#endif
#ifdef __APPLE__
# include "cmCPackPackageMakerGenerator.h"
# include "cmCPackOSXX11Generator.h"
#endif
#include "cmCPackLog.h"
@ -46,8 +51,10 @@ cmCPackGenerators::cmCPackGenerators()
this->RegisterGenerator("TZ", "Tar Compress compression",
cmCPackTarCompressGenerator::CreateGenerator);
#ifdef __APPLE__
this->RegisterGenerator("PackageMaker", "Mac OSX Package Maker compression",
this->RegisterGenerator("PackageMaker", "Mac OSX Package Maker installer",
cmCPackPackageMakerGenerator::CreateGenerator);
this->RegisterGenerator("OSXX11", "Mac OSX X11 bundle",
cmCPackOSXX11Generator::CreateGenerator);
#endif
}

View File

@ -152,8 +152,10 @@ int cmCPackGenericGenerator::InstallProject()
{
cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Install projects" << std::endl);
this->CleanTemporaryDirectory();
const char* tempInstallDirectory
std::string tempInstallDirectoryWithPostfix
= this->GetOption("CPACK_TEMPORARY_INSTALL_DIRECTORY");
tempInstallDirectoryWithPostfix += this->GetTemporaryInstallDirectoryPostfix();
const char* tempInstallDirectory = tempInstallDirectoryWithPostfix.c_str();
int res = 1;
if ( !cmsys::SystemTools::MakeDirectory(tempInstallDirectory))
{
@ -965,17 +967,19 @@ bool cmCPackGenericGenerator::ConfigureString(const std::string& inString,
//----------------------------------------------------------------------
bool cmCPackGenericGenerator::ConfigureFile(const char* inName,
const char* outName)
const char* outName, bool copyOnly /* = false */)
{
return this->MakefileMap->ConfigureFile(inName, outName,
false, true, false) == 1;
copyOnly, true, false) == 1;
}
//----------------------------------------------------------------------
int cmCPackGenericGenerator::CleanTemporaryDirectory()
{
const char* tempInstallDirectory
std::string tempInstallDirectoryWithPostfix
= this->GetOption("CPACK_TEMPORARY_INSTALL_DIRECTORY");
tempInstallDirectoryWithPostfix += this->GetTemporaryInstallDirectoryPostfix();
const char* tempInstallDirectory = tempInstallDirectoryWithPostfix.c_str();
if(cmsys::SystemTools::FileExists(tempInstallDirectory))
{
cmCPackLogger(cmCPackLog::LOG_OUTPUT,

View File

@ -100,9 +100,10 @@ protected:
const std::vector<std::string>& files);
virtual const char* GetInstallPath();
virtual const char* GetInstallPrefix() { return "/"; }
virtual const char* GetTemporaryInstallDirectoryPostfix() { return ""; }
virtual std::string FindTemplate(const char* name);
virtual bool ConfigureFile(const char* inName, const char* outName);
virtual bool ConfigureFile(const char* inName, const char* outName, bool copyOnly = false);
virtual bool ConfigureString(const std::string& input, std::string& output);
virtual int InitializeInternal();

View File

@ -0,0 +1,220 @@
/*=========================================================================
Program: CMake - Cross-Platform Makefile Generator
Module: $RCSfile$
Language: C++
Date: $Date$
Version: $Revision$
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
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "cmCPackOSXX11Generator.h"
#include "cmake.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmSystemTools.h"
#include "cmMakefile.h"
#include "cmGeneratedFileStream.h"
#include "cmCPackLog.h"
#include <cmsys/SystemTools.hxx>
#include <cmsys/Glob.hxx>
//----------------------------------------------------------------------
cmCPackOSXX11Generator::cmCPackOSXX11Generator()
{
}
//----------------------------------------------------------------------
cmCPackOSXX11Generator::~cmCPackOSXX11Generator()
{
}
//----------------------------------------------------------------------
int cmCPackOSXX11Generator::CompressFiles(const char* outFileName,
const char* toplevel,
const std::vector<std::string>& files)
{
(void) files; // TODO: Fix api to not need files.
(void) toplevel; // TODO: Use toplevel
const char* cpackPackageExecutables
= this->GetOption("CPACK_PACKAGE_EXECUTABLES");
if ( cpackPackageExecutables )
{
cmCPackLogger(cmCPackLog::LOG_DEBUG, "The cpackPackageExecutables: "
<< cpackPackageExecutables << "." << std::endl);
cmOStringStream str;
cmOStringStream deleteStr;
std::vector<std::string> cpackPackageExecutablesVector;
cmSystemTools::ExpandListArgument(cpackPackageExecutables,
cpackPackageExecutablesVector);
if ( cpackPackageExecutablesVector.size() % 2 != 0 )
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_PACKAGE_EXECUTABLES should contain pairs of <executable> and "
"<icon name>." << std::endl);
return 0;
}
std::vector<std::string>::iterator it;
for ( it = cpackPackageExecutablesVector.begin();
it != cpackPackageExecutablesVector.end();
++it )
{
std::string cpackExecutableName = *it;
++ it;
this->SetOptionIfNotSet("CPACK_EXECUTABLE_NAME",
cpackExecutableName.c_str());
}
}
std::string packageDirFileName = toplevel;
packageDirFileName += ".app";
std::string contentsDirectory = packageDirFileName + "/Contents";
std::string resourcesDirectory = contentsDirectory + "/Resources";
std::string appDirectory = contentsDirectory + "/MacOS";
const char* dir = resourcesDirectory.c_str();
const char* appdir = appDirectory.c_str();
const char* contDir = contentsDirectory.c_str();
if (
!this->CopyResourcePlistFile("RuntimeScript", dir) ||
!this->CopyResourcePlistFile("OSXX11.Info.plist", contDir,
"Info.plist" ) ||
!this->CopyResourcePlistFile("OSXScriptLauncher", appdir,
this->GetOption("CPACK_PACKAGE_FILE_NAME"), true)
)
{
cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying the resource files"
<< std::endl);
return 0;
}
std::string output;
std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
tmpFile += "/hdiutilOutput.log";
cmOStringStream dmgCmd;
dmgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM_DISK_IMAGE")
<< "\" create -ov -format UDZO -srcfolder \"" << packageDirFileName
<< "\" \"" << outFileName << "\"";
int retVal = 1;
bool res = cmSystemTools::RunSingleCommand(dmgCmd.str().c_str(), &output,
&retVal, 0, this->GeneratorVerbose, 0);
if ( !res || retVal )
{
cmGeneratedFileStream ofs(tmpFile.c_str());
ofs << "# Run command: " << dmgCmd.str().c_str() << std::endl
<< "# Output:" << std::endl
<< output.c_str() << std::endl;
cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running hdiutil command: "
<< dmgCmd.str().c_str() << std::endl
<< "Please check " << tmpFile.c_str() << " for errors" << std::endl);
return 0;
}
return 1;
}
//----------------------------------------------------------------------
int cmCPackOSXX11Generator::InitializeInternal()
{
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"cmCPackOSXX11Generator::Initialize()" << std::endl);
std::vector<std::string> path;
std::string pkgPath = cmSystemTools::FindProgram("hdiutil", path, false);
if ( pkgPath.empty() )
{
cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find hdiutil compiler"
<< std::endl);
return 0;
}
this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM_DISK_IMAGE",
pkgPath.c_str());
return this->Superclass::InitializeInternal();
}
//----------------------------------------------------------------------
/*
bool cmCPackOSXX11Generator::CopyCreateResourceFile(const char* name)
{
std::string uname = cmSystemTools::UpperCase(name);
std::string cpackVar = "CPACK_RESOURCE_FILE_" + uname;
const char* inFileName = this->GetOption(cpackVar.c_str());
if ( !inFileName )
{
cmCPackLogger(cmCPackLog::LOG_ERROR, "CPack option: " << cpackVar.c_str()
<< " not specified. It should point to "
<< (name ? name : "(NULL)")
<< ".rtf, " << name
<< ".html, or " << name << ".txt file" << std::endl);
return false;
}
if ( !cmSystemTools::FileExists(inFileName) )
{
cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find "
<< (name ? name : "(NULL)")
<< " resource file: " << inFileName << std::endl);
return false;
}
std::string ext = cmSystemTools::GetFilenameLastExtension(inFileName);
if ( ext != ".rtfd" && ext != ".rtf" && ext != ".html" && ext != ".txt" )
{
cmCPackLogger(cmCPackLog::LOG_ERROR, "Bad file extension specified: "
<< ext << ". Currently only .rtfd, .rtf, .html, and .txt files allowed."
<< std::endl);
return false;
}
std::string destFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
destFileName += "/Resources/";
destFileName += name + ext;
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: "
<< (inFileName ? inFileName : "(NULL)")
<< " to " << destFileName.c_str() << std::endl);
this->ConfigureFile(inFileName, destFileName.c_str());
return true;
}
*/
bool cmCPackOSXX11Generator::CopyResourcePlistFile(const char* name,
const char* dir, const char* outputFileName /* = 0 */,
bool copyOnly /* = false */)
{
std::string inFName = "CPack.";
inFName += name;
inFName += ".in";
std::string inFileName = this->FindTemplate(inFName.c_str());
if ( inFileName.empty() )
{
cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find input file: "
<< inFName << std::endl);
return false;
}
if ( !outputFileName )
{
outputFileName = name;
}
std::string destFileName = dir;
destFileName += "/";
destFileName += outputFileName;
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: "
<< inFileName.c_str() << " to " << destFileName.c_str() << std::endl);
this->ConfigureFile(inFileName.c_str(), destFileName.c_str(), copyOnly);
return true;
}

View File

@ -0,0 +1,51 @@
/*=========================================================================
Program: CMake - Cross-Platform Makefile Generator
Module: $RCSfile$
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) 2002 Kitware, Inc. 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
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef cmCPackOSXX11Generator_h
#define cmCPackOSXX11Generator_h
#include "cmCPackGenericGenerator.h"
/** \class cmCPackOSXX11Generator
* \brief A generator for OSX X11 modules
*
* Based on Gimp.app
*/
class cmCPackOSXX11Generator : public cmCPackGenericGenerator
{
public:
cmCPackTypeMacro(cmCPackOSXX11Generator, cmCPackGenericGenerator);
/**
* Construct generator
*/
cmCPackOSXX11Generator();
virtual ~cmCPackOSXX11Generator();
protected:
virtual int InitializeInternal();
int CompressFiles(const char* outFileName, const char* toplevel,
const std::vector<std::string>& files);
virtual const char* GetOutputExtension() { return "dmg"; }
virtual const char* GetInstallPrefix() { return ".app/Contents/Resources"; }
//bool CopyCreateResourceFile(const char* name, const char* dir);
bool CopyResourcePlistFile(const char* name, const char* dir,
const char* outputFileName = 0, bool copyOnly = false);
};
#endif