diff options
author | David Cole <david.cole@kitware.com> | 2009-01-22 17:12:44 (GMT) |
---|---|---|
committer | David Cole <david.cole@kitware.com> | 2009-01-22 17:12:44 (GMT) |
commit | 3a4f76949acb99b53380c738a25c7bae4ba317c9 (patch) | |
tree | 91ac7ec885812ca2199e628e87277c8490ed2ce9 /Source/CPack | |
parent | dfc181a1dc0baa3b4f36b64a0b64e68c1a2f636a (diff) | |
download | CMake-3a4f76949acb99b53380c738a25c7bae4ba317c9.zip CMake-3a4f76949acb99b53380c738a25c7bae4ba317c9.tar.gz CMake-3a4f76949acb99b53380c738a25c7bae4ba317c9.tar.bz2 |
BUG: Fix issue #8402. Add a drag and drop bundle generator to the Mac build of CPack. Add a test of it in the CPackComponents test. Thanks to Clinton Stimpson for the patch.
Diffstat (limited to 'Source/CPack')
-rw-r--r-- | Source/CPack/cmCPackBundleGenerator.cxx | 82 | ||||
-rw-r--r-- | Source/CPack/cmCPackBundleGenerator.h | 9 | ||||
-rw-r--r-- | Source/CPack/cmCPackDragNDropGenerator.cxx | 253 | ||||
-rw-r--r-- | Source/CPack/cmCPackDragNDropGenerator.h | 47 | ||||
-rw-r--r-- | Source/CPack/cmCPackGeneratorFactory.cxx | 3 |
5 files changed, 305 insertions, 89 deletions
diff --git a/Source/CPack/cmCPackBundleGenerator.cxx b/Source/CPack/cmCPackBundleGenerator.cxx index b37c267..d564308 100644 --- a/Source/CPack/cmCPackBundleGenerator.cxx +++ b/Source/CPack/cmCPackBundleGenerator.cxx @@ -32,40 +32,6 @@ cmCPackBundleGenerator::~cmCPackBundleGenerator() } //---------------------------------------------------------------------- -int cmCPackBundleGenerator::InitializeInternal() -{ - const std::string hdiutil_path = cmSystemTools::FindProgram("hdiutil", - std::vector<std::string>(), false); - if(hdiutil_path.empty()) - { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Cannot locate hdiutil command" - << std::endl); - return 0; - } - this->SetOptionIfNotSet("CPACK_COMMAND_HDIUTIL", hdiutil_path.c_str()); - - const std::string setfile_path = cmSystemTools::FindProgram("SetFile", - std::vector<std::string>(1, "/Developer/Tools"), false); - if(setfile_path.empty()) - { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Cannot locate SetFile command" - << std::endl); - return 0; - } - this->SetOptionIfNotSet("CPACK_COMMAND_SETFILE", setfile_path.c_str()); - - return this->Superclass::InitializeInternal(); -} - -//---------------------------------------------------------------------- -const char* cmCPackBundleGenerator::GetOutputExtension() -{ - return ".dmg"; -} - -//---------------------------------------------------------------------- const char* cmCPackBundleGenerator::GetPackagingInstallPrefix() { this->InstallPrefix = "/"; @@ -316,51 +282,3 @@ int cmCPackBundleGenerator::CompressFiles(const char* outFileName, return 1; } - -//---------------------------------------------------------------------- -bool cmCPackBundleGenerator::CopyFile(cmOStringStream& source, - cmOStringStream& target) -{ - if(!cmSystemTools::CopyFileIfDifferent( - source.str().c_str(), - target.str().c_str())) - { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error copying " - << source.str() - << " to " - << target.str() - << std::endl); - - return false; - } - - return true; -} - -//---------------------------------------------------------------------- -bool cmCPackBundleGenerator::RunCommand(cmOStringStream& command, - std::string* output) -{ - int exit_code = 1; - - bool result = cmSystemTools::RunSingleCommand( - command.str().c_str(), - output, - &exit_code, - 0, - this->GeneratorVerbose, - 0); - - if(!result || exit_code) - { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error executing: " - << command.str() - << std::endl); - - return false; - } - - return true; -} diff --git a/Source/CPack/cmCPackBundleGenerator.h b/Source/CPack/cmCPackBundleGenerator.h index 2a794f3..04c57b4 100644 --- a/Source/CPack/cmCPackBundleGenerator.h +++ b/Source/CPack/cmCPackBundleGenerator.h @@ -18,14 +18,14 @@ #ifndef cmCPackBundleGenerator_h #define cmCPackBundleGenerator_h -#include "cmCPackGenerator.h" +#include "cmCPackDragNDropGenerator.h" /** \class cmCPackBundleGenerator * \brief A generator for OSX bundles * * Based on Gimp.app */ -class cmCPackBundleGenerator : public cmCPackGenerator +class cmCPackBundleGenerator : public cmCPackDragNDropGenerator { public: cmCPackTypeMacro(cmCPackBundleGenerator, cmCPackGenerator); @@ -34,15 +34,10 @@ public: virtual ~cmCPackBundleGenerator(); protected: - virtual int InitializeInternal(); - virtual const char* GetOutputExtension(); virtual const char* GetPackagingInstallPrefix(); int CompressFiles(const char* outFileName, const char* toplevel, const std::vector<std::string>& files); - bool CopyFile(cmOStringStream& source, cmOStringStream& target); - bool RunCommand(cmOStringStream& command, std::string* output = 0); - std::string InstallPrefix; }; diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx new file mode 100644 index 0000000..40ade06 --- /dev/null +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -0,0 +1,253 @@ +/*========================================================================= + + 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 "cmCPackDragNDropGenerator.h" +#include "cmCPackLog.h" +#include "cmSystemTools.h" + +#include <cmsys/RegularExpression.hxx> + +//---------------------------------------------------------------------- +cmCPackDragNDropGenerator::cmCPackDragNDropGenerator() +{ +} + +//---------------------------------------------------------------------- +cmCPackDragNDropGenerator::~cmCPackDragNDropGenerator() +{ +} + +//---------------------------------------------------------------------- +int cmCPackDragNDropGenerator::InitializeInternal() +{ + const std::string hdiutil_path = cmSystemTools::FindProgram("hdiutil", + std::vector<std::string>(), false); + if(hdiutil_path.empty()) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Cannot locate hdiutil command" + << std::endl); + return 0; + } + this->SetOptionIfNotSet("CPACK_COMMAND_HDIUTIL", hdiutil_path.c_str()); + + const std::string setfile_path = cmSystemTools::FindProgram("SetFile", + std::vector<std::string>(1, "/Developer/Tools"), false); + if(setfile_path.empty()) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Cannot locate SetFile command" + << std::endl); + return 0; + } + this->SetOptionIfNotSet("CPACK_COMMAND_SETFILE", setfile_path.c_str()); + + return this->Superclass::InitializeInternal(); +} + +//---------------------------------------------------------------------- +const char* cmCPackDragNDropGenerator::GetOutputExtension() +{ + return ".dmg"; +} + +//---------------------------------------------------------------------- +int cmCPackDragNDropGenerator::CompressFiles(const char* outFileName, + const char* toplevel, const std::vector<std::string>& files) +{ + (void) files; + + // Get optional arguments ... + const std::string cpack_package_icon = this->GetOption("CPACK_PACKAGE_ICON") + ? this->GetOption("CPACK_PACKAGE_ICON") : ""; + + // The staging directory contains everything that will end-up inside the + // final disk image ... + cmOStringStream staging; + staging << toplevel; + + // Add a symlink to /Applications so users can drag-and-drop the bundle + // into it + cmOStringStream application_link; + application_link << staging.str() << "/Applications"; + cmSystemTools::CreateSymlink("/Applications", + application_link.str().c_str()); + + // Optionally add a custom volume icon ... + if(!cpack_package_icon.empty()) + { + cmOStringStream package_icon_source; + package_icon_source << cpack_package_icon; + + cmOStringStream package_icon_destination; + package_icon_destination << staging.str() << "/.VolumeIcon.icns"; + + if(!this->CopyFile(package_icon_source, package_icon_destination)) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error copying disk volume icon. " + "Check the value of CPACK_PACKAGE_ICON." + << std::endl); + + return 0; + } + } + + // Create a temporary read-write disk image ... + cmOStringStream temp_image; + temp_image << this->GetOption("CPACK_TOPLEVEL_DIRECTORY") << "/temp.dmg"; + + cmOStringStream temp_image_command; + temp_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL"); + temp_image_command << " create"; + temp_image_command << " -ov"; + temp_image_command << " -srcfolder \"" << staging.str() << "\""; + temp_image_command << " -volname \"" + << this->GetOption("CPACK_PACKAGE_FILE_NAME") << "\""; + temp_image_command << " -format UDRW"; + temp_image_command << " \"" << temp_image.str() << "\""; + + if(!this->RunCommand(temp_image_command)) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error generating temporary disk image." + << std::endl); + + return 0; + } + + // Optionally set the custom icon flag for the image ... + if(!cpack_package_icon.empty()) + { + cmOStringStream temp_mount; + + cmOStringStream attach_command; + attach_command << this->GetOption("CPACK_COMMAND_HDIUTIL"); + attach_command << " attach"; + attach_command << " \"" << temp_image.str() << "\""; + + std::string attach_output; + if(!this->RunCommand(attach_command, &attach_output)) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error attaching temporary disk image." + << std::endl); + + return 0; + } + + cmsys::RegularExpression mountpoint_regex(".*(/Volumes/[^\n]+)\n.*"); + mountpoint_regex.find(attach_output.c_str()); + temp_mount << mountpoint_regex.match(1); + + cmOStringStream setfile_command; + setfile_command << this->GetOption("CPACK_COMMAND_SETFILE"); + setfile_command << " -a C"; + setfile_command << " \"" << temp_mount.str() << "\""; + + if(!this->RunCommand(setfile_command)) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error assigning custom icon to temporary disk image." + << std::endl); + + return 0; + } + + cmOStringStream detach_command; + detach_command << this->GetOption("CPACK_COMMAND_HDIUTIL"); + detach_command << " detach"; + detach_command << " \"" << temp_mount.str() << "\""; + + if(!this->RunCommand(detach_command)) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error detaching temporary disk image." + << std::endl); + + return 0; + } + } + + // Create the final compressed read-only disk image ... + cmOStringStream final_image_command; + final_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL"); + final_image_command << " convert \"" << temp_image.str() << "\""; + final_image_command << " -format UDZO"; + final_image_command << " -imagekey"; + final_image_command << " zlib-level=9"; + final_image_command << " -o \"" << outFileName << "\""; + + if(!this->RunCommand(final_image_command)) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error compressing disk image." + << std::endl); + + return 0; + } + + return 1; +} + +//---------------------------------------------------------------------- +bool cmCPackDragNDropGenerator::CopyFile(cmOStringStream& source, + cmOStringStream& target) +{ + if(!cmSystemTools::CopyFileIfDifferent( + source.str().c_str(), + target.str().c_str())) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error copying " + << source.str() + << " to " + << target.str() + << std::endl); + + return false; + } + + return true; +} + +//---------------------------------------------------------------------- +bool cmCPackDragNDropGenerator::RunCommand(cmOStringStream& command, + std::string* output) +{ + int exit_code = 1; + + bool result = cmSystemTools::RunSingleCommand( + command.str().c_str(), + output, + &exit_code, + 0, + this->GeneratorVerbose, + 0); + + if(!result || exit_code) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error executing: " + << command.str() + << std::endl); + + return false; + } + + return true; +} diff --git a/Source/CPack/cmCPackDragNDropGenerator.h b/Source/CPack/cmCPackDragNDropGenerator.h new file mode 100644 index 0000000..0dd4e5a --- /dev/null +++ b/Source/CPack/cmCPackDragNDropGenerator.h @@ -0,0 +1,47 @@ +/*========================================================================= + + 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 cmCPackDragNDropGenerator_h +#define cmCPackDragNDropGenerator_h + +#include "cmCPackGenerator.h" + +/** \class cmCPackDragNDropGenerator + * \brief A generator for OSX drag-n-drop installs + */ +class cmCPackDragNDropGenerator : public cmCPackGenerator +{ +public: + cmCPackTypeMacro(cmCPackDragNDropGenerator, cmCPackGenerator); + + cmCPackDragNDropGenerator(); + virtual ~cmCPackDragNDropGenerator(); + +protected: + virtual int InitializeInternal(); + virtual const char* GetOutputExtension(); + int CompressFiles(const char* outFileName, const char* toplevel, + const std::vector<std::string>& files); + + bool CopyFile(cmOStringStream& source, cmOStringStream& target); + bool RunCommand(cmOStringStream& command, std::string* output = 0); + + std::string InstallPrefix; +}; + +#endif + diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx index d7b7271..4628339 100644 --- a/Source/CPack/cmCPackGeneratorFactory.cxx +++ b/Source/CPack/cmCPackGeneratorFactory.cxx @@ -25,6 +25,7 @@ #include "cmCPackSTGZGenerator.h" #include "cmCPackNSISGenerator.h" #ifdef __APPLE__ +# include "cmCPackDragNDropGenerator.h" # include "cmCPackBundleGenerator.h" # include "cmCPackPackageMakerGenerator.h" # include "cmCPackOSXX11Generator.h" @@ -67,6 +68,8 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory() this->RegisterGenerator("TZ", "Tar Compress compression", cmCPackTarCompressGenerator::CreateGenerator); #ifdef __APPLE__ + this->RegisterGenerator("DragNDrop", "Mac OSX Drag And Drop", + cmCPackDragNDropGenerator::CreateGenerator); this->RegisterGenerator("Bundle", "Mac OSX bundle", cmCPackBundleGenerator::CreateGenerator); this->RegisterGenerator("PackageMaker", "Mac OSX Package Maker installer", |