diff --git a/Modules/CPack.OSXScriptLauncher.in b/Modules/CPack.OSXScriptLauncher.in new file mode 100755 index 000000000..a3e1737e9 Binary files /dev/null and b/Modules/CPack.OSXScriptLauncher.in differ diff --git a/Modules/CPack.OSXX11.Info.plist.in b/Modules/CPack.OSXX11.Info.plist.in new file mode 100644 index 000000000..30ce2de8b --- /dev/null +++ b/Modules/CPack.OSXX11.Info.plist.in @@ -0,0 +1,36 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + @CPACK_PACKAGE_FILE_NAME@ + CFBundleGetInfoString + @CPACK_APPLE_GUI_INFO_STRING@ + CFBundleIconFile + @CPACK_APPLE_GUI_ICON@ + CFBundleIdentifier + @CPACK_APPLE_GUI_IDENTIFIER@ + CFBundleInfoDictionaryVersion + 6.0 + CFBundleLongVersionString + @CPACK_APPLE_GUI_LONG_VERSION_STRING@ + CFBundleName + @CPACK_APPLE_GUI_BUNDLE_NAME@ + CFBundlePackageType + APPL + CFBundleShortVersionString + @CPACK_APPLE_GUI_SHORT_VERSION_STRING@ + CFBundleSignature + ???? + CFBundleVersion + @CPACK_APPLE_GUI_BUNDLE_VERSION@ + CSResourcesFileMapped + + LSRequiresCarbon + + NSHumanReadableCopyright + @CPACK_APPLE_GUI_COPYRIGHT@ + + diff --git a/Modules/CPack.RuntimeScript.in b/Modules/CPack.RuntimeScript.in new file mode 100755 index 000000000..9195d525c --- /dev/null +++ b/Modules/CPack.RuntimeScript.in @@ -0,0 +1,40 @@ +#!/bin/sh +# +# Modified from: Aaron Voisine + +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 diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index ab2c77edb..46b600657 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -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 diff --git a/Source/CPack/OSXScriptLauncher.cxx b/Source/CPack/OSXScriptLauncher.cxx new file mode 100644 index 000000000..d09c12e03 --- /dev/null +++ b/Source/CPack/OSXScriptLauncher.cxx @@ -0,0 +1,161 @@ +#include +#include +#include +#include + +#include +#include + +#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(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 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 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; +} diff --git a/Source/CPack/cmCPackGenerators.cxx b/Source/CPack/cmCPackGenerators.cxx index 3515e0e58..4d0dc6839 100644 --- a/Source/CPack/cmCPackGenerators.cxx +++ b/Source/CPack/cmCPackGenerators.cxx @@ -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 } diff --git a/Source/CPack/cmCPackGenericGenerator.cxx b/Source/CPack/cmCPackGenericGenerator.cxx index 52b2e14db..0f0ddadfe 100644 --- a/Source/CPack/cmCPackGenericGenerator.cxx +++ b/Source/CPack/cmCPackGenericGenerator.cxx @@ -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, diff --git a/Source/CPack/cmCPackGenericGenerator.h b/Source/CPack/cmCPackGenericGenerator.h index afe79c0e2..27d5098f6 100644 --- a/Source/CPack/cmCPackGenericGenerator.h +++ b/Source/CPack/cmCPackGenericGenerator.h @@ -100,9 +100,10 @@ protected: const std::vector& 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(); diff --git a/Source/CPack/cmCPackOSXX11Generator.cxx b/Source/CPack/cmCPackOSXX11Generator.cxx new file mode 100644 index 000000000..95e280180 --- /dev/null +++ b/Source/CPack/cmCPackOSXX11Generator.cxx @@ -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 +#include + +//---------------------------------------------------------------------- +cmCPackOSXX11Generator::cmCPackOSXX11Generator() +{ +} + +//---------------------------------------------------------------------- +cmCPackOSXX11Generator::~cmCPackOSXX11Generator() +{ +} + +//---------------------------------------------------------------------- +int cmCPackOSXX11Generator::CompressFiles(const char* outFileName, + const char* toplevel, + const std::vector& 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 cpackPackageExecutablesVector; + cmSystemTools::ExpandListArgument(cpackPackageExecutables, + cpackPackageExecutablesVector); + if ( cpackPackageExecutablesVector.size() % 2 != 0 ) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "CPACK_PACKAGE_EXECUTABLES should contain pairs of and " + "." << std::endl); + return 0; + } + std::vector::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 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; +} + diff --git a/Source/CPack/cmCPackOSXX11Generator.h b/Source/CPack/cmCPackOSXX11Generator.h new file mode 100644 index 000000000..8720e79b4 --- /dev/null +++ b/Source/CPack/cmCPackOSXX11Generator.h @@ -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& 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