Merge topic 'better_looking_mac_package'
4bca9401 Improve appearance of CMake .dmg package on OS X c4b9ee18 CPack/DragNDrop: Update documentation to include new variables 167a4655 CPack/DragNDrop: Optionally run an AppleScript when making a package 9c1dfbfd CPack/DragNDrop: Place the background image file in a hidden folder 47302038 CPack/DragNDrop: Use source file extension for background image
This commit is contained in:
commit
9feb24e514
@ -183,6 +183,13 @@ if("${CPACK_GENERATOR}" STREQUAL "PackageMaker")
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if("${CPACK_GENERATOR}" STREQUAL "DragNDrop")
|
||||||
|
set(CPACK_DMG_BACKGROUND_IMAGE
|
||||||
|
"@CMake_SOURCE_DIR@/Packaging/CMakeDMGBackground.tif")
|
||||||
|
set(CPACK_DMG_DS_STORE_SETUP_SCRIPT
|
||||||
|
"@CMake_SOURCE_DIR@/Packaging/CMakeDMGSetup.scpt")
|
||||||
|
endif()
|
||||||
|
|
||||||
if("${CPACK_GENERATOR}" STREQUAL "WIX")
|
if("${CPACK_GENERATOR}" STREQUAL "WIX")
|
||||||
# Reset CPACK_PACKAGE_VERSION to deal with WiX restriction.
|
# Reset CPACK_PACKAGE_VERSION to deal with WiX restriction.
|
||||||
# But the file names still use the full CMake_VERSION value:
|
# But the file names still use the full CMake_VERSION value:
|
||||||
|
8
Help/release/dev/better-looking-mac-packages.rst
Normal file
8
Help/release/dev/better-looking-mac-packages.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
better-looking-mac-packages
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
* The :module:`CPackDMG` module learned new variable to specify AppleScript
|
||||||
|
file run to customize appearance of ``DragNDrop`` installer folder,
|
||||||
|
including background image setting using supplied PNG or multi-resolution
|
||||||
|
TIFF file. See the :variable:`CPACK_DMG_DS_STORE_SETUP_SCRIPT` and
|
||||||
|
:variable:`CPACK_DMG_BACKGROUND_IMAGE` variables.
|
@ -26,15 +26,25 @@
|
|||||||
# Path to a custom DS_Store file. This .DS_Store file e.g. can be used to
|
# Path to a custom DS_Store file. This .DS_Store file e.g. can be used to
|
||||||
# specify the Finder window position/geometry and layout (such as hidden
|
# specify the Finder window position/geometry and layout (such as hidden
|
||||||
# toolbars, placement of the icons etc.). This file has to be generated by
|
# toolbars, placement of the icons etc.). This file has to be generated by
|
||||||
# the Finder (either manually or through OSA-script) using a normal folder
|
# the Finder (either manually or through AppleScript) using a normal folder
|
||||||
# from which the .DS_Store file can then be extracted.
|
# from which the .DS_Store file can then be extracted.
|
||||||
#
|
#
|
||||||
|
# .. variable:: CPACK_DMG_DS_STORE_SETUP_SCRIPT
|
||||||
|
#
|
||||||
|
# Path to a custom AppleScript file. This AppleScript is used to generate
|
||||||
|
# a .DS_Store file which specifies the Finder window position/geometry and
|
||||||
|
# layout (such as hidden toolbars, placement of the icons etc.).
|
||||||
|
# By specifying a custom AppleScript there is no need to use
|
||||||
|
# CPACK_DMG_DS_STORE, as the .DS_Store that is generated by the AppleScript
|
||||||
|
# will be packaged.
|
||||||
|
#
|
||||||
# .. variable:: CPACK_DMG_BACKGROUND_IMAGE
|
# .. variable:: CPACK_DMG_BACKGROUND_IMAGE
|
||||||
#
|
#
|
||||||
# Path to a background image file. This file will be used as the background
|
# Path to an image file to be used as the background. This file will be
|
||||||
# for the Finder Window when the disk image is opened. By default no
|
# copied to .background/background.<ext>, where ext is the original image file
|
||||||
# background image is set. The background image is applied after applying the
|
# extension. The background image is installed into the image before
|
||||||
# custom .DS_Store file.
|
# CPACK_DMG_DS_STORE_SETUP_SCRIPT is executed or CPACK_DMG_DS_STORE is
|
||||||
|
# installed. By default no background image is set.
|
||||||
#
|
#
|
||||||
# .. variable:: CPACK_DMG_SLA_DIR
|
# .. variable:: CPACK_DMG_SLA_DIR
|
||||||
#
|
#
|
||||||
|
BIN
Packaging/CMakeDMGBackground.tif
Normal file
BIN
Packaging/CMakeDMGBackground.tif
Normal file
Binary file not shown.
42
Packaging/CMakeDMGSetup.scpt
Normal file
42
Packaging/CMakeDMGSetup.scpt
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
on run argv
|
||||||
|
set image_name to item 1 of argv
|
||||||
|
|
||||||
|
tell application "Finder"
|
||||||
|
tell disk image_name
|
||||||
|
|
||||||
|
-- open the image the first time and save a DS_Store with just
|
||||||
|
-- background and icon setup
|
||||||
|
open
|
||||||
|
set current view of container window to icon view
|
||||||
|
set theViewOptions to the icon view options of container window
|
||||||
|
set background picture of theViewOptions to file ".background:background.tif"
|
||||||
|
set arrangement of theViewOptions to not arranged
|
||||||
|
set icon size of theViewOptions to 128
|
||||||
|
delay 1
|
||||||
|
close
|
||||||
|
|
||||||
|
-- next setup the position of the app and Applications symlink
|
||||||
|
-- plus hide all the window decoration
|
||||||
|
open
|
||||||
|
update without registering applications
|
||||||
|
tell container window
|
||||||
|
set sidebar width to 0
|
||||||
|
set statusbar visible to false
|
||||||
|
set toolbar visible to false
|
||||||
|
set the bounds to { 400, 100, 900, 465 }
|
||||||
|
set position of item "CMake.app" to { 133, 200 }
|
||||||
|
set position of item "Applications" to { 378, 200 }
|
||||||
|
end tell
|
||||||
|
update without registering applications
|
||||||
|
delay 1
|
||||||
|
close
|
||||||
|
|
||||||
|
-- one last open and close so you can see everything looks correct
|
||||||
|
open
|
||||||
|
delay 5
|
||||||
|
close
|
||||||
|
|
||||||
|
end tell
|
||||||
|
delay 1
|
||||||
|
end tell
|
||||||
|
end run
|
@ -270,6 +270,28 @@ bool cmCPackDragNDropGenerator::CopyFile(std::ostringstream& source,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
bool cmCPackDragNDropGenerator::CreateEmptyFile(std::ostringstream& target,
|
||||||
|
size_t size)
|
||||||
|
{
|
||||||
|
cmsys::ofstream fout(target.str().c_str(),
|
||||||
|
std::ios::out | std::ios::binary);
|
||||||
|
if(!fout)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Seek to desired size - 1 byte
|
||||||
|
fout.seekp(size - 1, std::ios_base::beg);
|
||||||
|
char byte = 0;
|
||||||
|
// Write one byte to ensure file grows
|
||||||
|
fout.write(&byte, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
bool cmCPackDragNDropGenerator::RunCommand(std::ostringstream& command,
|
bool cmCPackDragNDropGenerator::RunCommand(std::ostringstream& command,
|
||||||
std::string* output)
|
std::string* output)
|
||||||
@ -331,6 +353,10 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
|
|||||||
this->GetOption("CPACK_DMG_LANGUAGES")
|
this->GetOption("CPACK_DMG_LANGUAGES")
|
||||||
? this->GetOption("CPACK_DMG_LANGUAGES") : "";
|
? this->GetOption("CPACK_DMG_LANGUAGES") : "";
|
||||||
|
|
||||||
|
const std::string cpack_dmg_ds_store_setup_script =
|
||||||
|
this->GetOption("CPACK_DMG_DS_STORE_SETUP_SCRIPT")
|
||||||
|
? this->GetOption("CPACK_DMG_DS_STORE_SETUP_SCRIPT") : "";
|
||||||
|
|
||||||
// only put license on dmg if is user provided
|
// only put license on dmg if is user provided
|
||||||
if(!cpack_license_file.empty() &&
|
if(!cpack_license_file.empty() &&
|
||||||
cpack_license_file.find("CPack.GenericLicense.txt") != std::string::npos)
|
cpack_license_file.find("CPack.GenericLicense.txt") != std::string::npos)
|
||||||
@ -399,13 +425,18 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Optionally add a custom background image ...
|
// Optionally add a custom background image ...
|
||||||
|
// Make sure the background file type is the same as the custom image
|
||||||
|
// and that the file is hidden so it doesn't show up.
|
||||||
if(!cpack_dmg_background_image.empty())
|
if(!cpack_dmg_background_image.empty())
|
||||||
{
|
{
|
||||||
|
const std::string extension =
|
||||||
|
cmSystemTools::GetFilenameLastExtension(cpack_dmg_background_image);
|
||||||
std::ostringstream package_background_source;
|
std::ostringstream package_background_source;
|
||||||
package_background_source << cpack_dmg_background_image;
|
package_background_source << cpack_dmg_background_image;
|
||||||
|
|
||||||
std::ostringstream package_background_destination;
|
std::ostringstream package_background_destination;
|
||||||
package_background_destination << staging.str() << "/background.png";
|
package_background_destination << staging.str()
|
||||||
|
<< "/.background/background" << extension;
|
||||||
|
|
||||||
if(!this->CopyFile(package_background_source,
|
if(!this->CopyFile(package_background_source,
|
||||||
package_background_destination))
|
package_background_destination))
|
||||||
@ -417,18 +448,22 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::ostringstream temp_background_hiding_command;
|
bool remount_image = !cpack_package_icon.empty() ||
|
||||||
temp_background_hiding_command << this->GetOption("CPACK_COMMAND_SETFILE");
|
!cpack_dmg_ds_store_setup_script.empty();
|
||||||
temp_background_hiding_command << " -a V \"";
|
|
||||||
temp_background_hiding_command << package_background_destination.str();
|
|
||||||
temp_background_hiding_command << "\"";
|
|
||||||
|
|
||||||
if(!this->RunCommand(temp_background_hiding_command))
|
// Create 1 MB dummy padding file in staging area when we need to remount
|
||||||
|
// image, so we have enough space for storing changes ...
|
||||||
|
if(remount_image)
|
||||||
|
{
|
||||||
|
std::ostringstream dummy_padding;
|
||||||
|
dummy_padding << staging.str() << "/.dummy-padding-file";
|
||||||
|
if(!this->CreateEmptyFile(dummy_padding, 1048576))
|
||||||
{
|
{
|
||||||
cmCPackLogger(cmCPackLog::LOG_ERROR,
|
cmCPackLogger(cmCPackLog::LOG_ERROR,
|
||||||
"Error setting attributes on disk volume background image."
|
"Error creating dummy padding file."
|
||||||
<< std::endl);
|
<< std::endl);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -457,10 +492,11 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optionally set the custom icon flag for the image ...
|
if(remount_image)
|
||||||
if(!cpack_package_icon.empty())
|
|
||||||
{
|
{
|
||||||
std::ostringstream temp_mount;
|
// Store that we have a failure so that we always unmount the image
|
||||||
|
// before we exit.
|
||||||
|
bool had_error = false;
|
||||||
|
|
||||||
std::ostringstream attach_command;
|
std::ostringstream attach_command;
|
||||||
attach_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
|
attach_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
|
||||||
@ -479,20 +515,57 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
|
|||||||
|
|
||||||
cmsys::RegularExpression mountpoint_regex(".*(/Volumes/[^\n]+)\n.*");
|
cmsys::RegularExpression mountpoint_regex(".*(/Volumes/[^\n]+)\n.*");
|
||||||
mountpoint_regex.find(attach_output.c_str());
|
mountpoint_regex.find(attach_output.c_str());
|
||||||
|
std::ostringstream temp_mount;
|
||||||
temp_mount << mountpoint_regex.match(1);
|
temp_mount << mountpoint_regex.match(1);
|
||||||
|
|
||||||
std::ostringstream setfile_command;
|
// Remove dummy padding file so we have enough space on RW image ...
|
||||||
setfile_command << this->GetOption("CPACK_COMMAND_SETFILE");
|
std::ostringstream dummy_padding;
|
||||||
setfile_command << " -a C";
|
dummy_padding << temp_mount.str() << "/.dummy-padding-file";
|
||||||
setfile_command << " \"" << temp_mount.str() << "\"";
|
if(!cmSystemTools::RemoveFile(dummy_padding.str()))
|
||||||
|
|
||||||
if(!this->RunCommand(setfile_command))
|
|
||||||
{
|
{
|
||||||
cmCPackLogger(cmCPackLog::LOG_ERROR,
|
cmCPackLogger(cmCPackLog::LOG_ERROR,
|
||||||
"Error assigning custom icon to temporary disk image."
|
"Error removing dummy padding file."
|
||||||
<< std::endl);
|
<< std::endl);
|
||||||
|
|
||||||
return 0;
|
had_error = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optionally set the custom icon flag for the image ...
|
||||||
|
if(!had_error && !cpack_package_icon.empty())
|
||||||
|
{
|
||||||
|
std::ostringstream 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);
|
||||||
|
|
||||||
|
had_error = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optionally we can execute a custom apple script to generate
|
||||||
|
// the .DS_Store for the volume folder ...
|
||||||
|
if(!had_error && !cpack_dmg_ds_store_setup_script.empty())
|
||||||
|
{
|
||||||
|
std::ostringstream setup_script_command;
|
||||||
|
setup_script_command << "osascript"
|
||||||
|
<< " \"" << cpack_dmg_ds_store_setup_script << "\""
|
||||||
|
<< " \"" << cpack_dmg_volume_name << "\"";
|
||||||
|
std::string error;
|
||||||
|
if(!this->RunCommand(setup_script_command, &error))
|
||||||
|
{
|
||||||
|
cmCPackLogger(cmCPackLog::LOG_ERROR,
|
||||||
|
"Error executing custom script on disk image." << std::endl
|
||||||
|
<< error
|
||||||
|
<< std::endl);
|
||||||
|
|
||||||
|
had_error = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostringstream detach_command;
|
std::ostringstream detach_command;
|
||||||
@ -508,6 +581,11 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(had_error)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!cpack_license_file.empty() || !slaDirectory.empty())
|
if(!cpack_license_file.empty() || !slaDirectory.empty())
|
||||||
|
@ -36,6 +36,7 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
bool CopyFile(std::ostringstream& source, std::ostringstream& target);
|
bool CopyFile(std::ostringstream& source, std::ostringstream& target);
|
||||||
|
bool CreateEmptyFile(std::ostringstream& target, size_t size);
|
||||||
bool RunCommand(std::ostringstream& command, std::string* output = 0);
|
bool RunCommand(std::ostringstream& command, std::string* output = 0);
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
|
Loading…
x
Reference in New Issue
Block a user