--- a/moz.configure
+++ b/moz.configure
@@ -249,24 +249,30 @@ check_prog('DOXYGEN', ('doxygen',), allo
check_prog('XARGS', ('xargs',))
@depends(target)
def extra_programs(target):
if target.kernel == 'Darwin':
return namespace(
DSYMUTIL=('dsymutil', 'llvm-dsymutil'),
GENISOIMAGE=('genisoimage',),
+ MKFSHFS=('newfs_hfs', 'mkfs.hfsplus'),
+ HFS_TOOL=('hfsplus',)
)
if target.os == 'GNU' and target.kernel == 'Linux':
return namespace(RPMBUILD=('rpmbuild',))
check_prog('DSYMUTIL', delayed_getattr(extra_programs, 'DSYMUTIL'),
allow_missing=True)
check_prog('GENISOIMAGE', delayed_getattr(extra_programs, 'GENISOIMAGE'),
allow_missing=True)
+check_prog('MKFSHFS', delayed_getattr(extra_programs, 'MKFSHFS'),
+ allow_missing=True)
+check_prog('HFS_TOOL', delayed_getattr(extra_programs, 'HFS_TOOL'),
+ allow_missing=True)
check_prog('RPMBUILD', delayed_getattr(extra_programs, 'RPMBUILD'),
allow_missing=True)
option('--enable-system-hunspell',
help="Use system hunspell (located with pkgconfig)")
@depends('--enable-system-hunspell', compile_environment)
def check_for_hunspell(value, compile_env):
--- a/python/mozbuild/mozpack/dmg.py
+++ b/python/mozbuild/mozpack/dmg.py
@@ -1,21 +1,23 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+import buildconfig
import errno
import mozfile
import os
import platform
import shutil
import subprocess
is_linux = platform.system() == 'Linux'
+
def mkdir(dir):
if not os.path.isdir(dir):
try:
os.makedirs(dir)
except OSError as e:
if e.errno != errno.EEXIST:
raise
@@ -29,60 +31,91 @@ def rsync(source, dest):
'rsync the contents of directory source into directory dest'
# Ensure a trailing slash so rsync copies the *contents* of source.
if not source.endswith('/'):
source += '/'
subprocess.check_call(['rsync', '-a', '--copy-unsafe-links',
source, dest])
-def set_folder_icon(dir):
+def set_folder_icon(dir, tmpdir):
'Set HFS attributes of dir to use a custom icon'
if not is_linux:
- #TODO: bug 1197325 - figure out how to support this on Linux
subprocess.check_call(['SetFile', '-a', 'C', dir])
+ else:
+ hfs = os.path.join(tmpdir, 'staged.hfs')
+ subprocess.check_call([
+ buildconfig.substs['HFS_TOOL'], hfs, 'attr', '/', 'C'])
+
+
+def generate_hfs_file(stagedir, tmpdir, volume_name):
+ '''
+ When cross compiling, we zero fill an hfs file, that we will turn into
+ a DMG. To do so we test the size of the staged dir, and add some slight
+ padding to that.
+ '''
+ if is_linux:
+ hfs = os.path.join(tmpdir, 'staged.hfs')
+ output = subprocess.check_output(['du', '-s', stagedir])
+ size = (int(output.split()[0]) / 1000) # Get in MB
+ size = int(size * 1.02) # Bump the used size slightly larger.
+ # Setup a proper file sized out with zero's
+ subprocess.check_call(['dd', 'if=/dev/zero', 'of={}'.format(hfs),
+ 'bs=1M', 'count={}'.format(size)])
+ subprocess.check_call([
+ buildconfig.substs['MKFSHFS'], '-v', volume_name,
+ hfs])
+
+
+def create_app_symlink(stagedir, tmpdir):
+ '''
+ Make a symlink to /Applications. The symlink name is a space
+ so we don't have to localize it. The Applications folder icon
+ will be shown in Finder, which should be clear enough for users.
+ '''
+ if is_linux:
+ hfs = os.path.join(tmpdir, 'staged.hfs')
+ subprocess.check_call([
+ buildconfig.substs['HFS_TOOL'], hfs, 'symlink',
+ '/ ', '/Applications'])
+ else:
+ os.symlink('/Applications', os.path.join(stagedir, ' '))
def create_dmg_from_staged(stagedir, output_dmg, tmpdir, volume_name):
'Given a prepared directory stagedir, produce a DMG at output_dmg.'
if not is_linux:
# Running on OS X
hybrid = os.path.join(tmpdir, 'hybrid.dmg')
subprocess.check_call(['hdiutil', 'makehybrid', '-hfs',
'-hfs-volume-name', volume_name,
'-hfs-openfolder', stagedir,
'-ov', stagedir,
'-o', hybrid])
subprocess.check_call(['hdiutil', 'convert', '-format', 'UDBZ',
'-imagekey', 'bzip2-level=9',
'-ov', hybrid, '-o', output_dmg])
else:
- import buildconfig
- uncompressed = os.path.join(tmpdir, 'uncompressed.dmg')
+ hfs = os.path.join(tmpdir, 'staged.hfs')
subprocess.check_call([
- buildconfig.substs['GENISOIMAGE'],
- '-V', volume_name,
- '-D', '-R', '-apple', '-no-pad',
- '-o', uncompressed,
- stagedir
- ])
+ buildconfig.substs['HFS_TOOL'], hfs, 'addall', stagedir])
subprocess.check_call([
buildconfig.substs['DMG_TOOL'],
- 'dmg',
- uncompressed,
+ 'build',
+ hfs,
output_dmg
],
# dmg is seriously chatty
stdout=open(os.devnull, 'wb'))
+
def check_tools(*tools):
'''
Check that each tool named in tools exists in SUBSTS and is executable.
'''
- import buildconfig
for tool in tools:
path = buildconfig.substs[tool]
if not path:
raise Exception('Required tool "%s" not found' % tool)
if not os.path.isfile(path):
raise Exception('Required tool "%s" not found at path "%s"' % (tool, path))
if not os.access(path, os.X_OK):
raise Exception('Required tool "%s" at path "%s" is not executable' % (tool, path))
@@ -95,27 +128,25 @@ def create_dmg(source_directory, output_
Use volume_name as the disk image volume name, and
use extra_files as a list of tuples of (filename, relative path) to copy
into the disk image.
'''
if platform.system() not in ('Darwin', 'Linux'):
raise Exception("Don't know how to build a DMG on '%s'" % platform.system())
if is_linux:
- check_tools('DMG_TOOL', 'GENISOIMAGE')
+ check_tools('DMG_TOOL', 'GENISOIMAGE', 'MKFSHFS', 'HFS_TOOL')
with mozfile.TemporaryDirectory() as tmpdir:
stagedir = os.path.join(tmpdir, 'stage')
os.mkdir(stagedir)
# Copy the app bundle over using rsync
rsync(source_directory, stagedir)
# Copy extra files
for source, target in extra_files:
full_target = os.path.join(stagedir, target)
mkdir(os.path.dirname(full_target))
shutil.copyfile(source, full_target)
- # Make a symlink to /Applications. The symlink name is a space
- # so we don't have to localize it. The Applications folder icon
- # will be shown in Finder, which should be clear enough for users.
- os.symlink('/Applications', os.path.join(stagedir, ' '))
+ generate_hfs_file(stagedir, tmpdir, volume_name)
+ create_app_symlink(stagedir, tmpdir)
# Set the folder attributes to use a custom icon
- set_folder_icon(stagedir)
+ set_folder_icon(stagedir, tmpdir)
chmod(stagedir)
create_dmg_from_staged(stagedir, output_dmg, tmpdir, volume_name)