Skip to content

Commit

Permalink
Moved the OSX package generation to SCons (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
ereOn committed Apr 18, 2015
1 parent b41e038 commit d580d3d
Show file tree
Hide file tree
Showing 19 changed files with 465 additions and 83 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@

# Vagrant
.vagrant

# Package files
*.pkg
8 changes: 8 additions & 0 deletions BUILD.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,11 @@ You will need Microsoft Visual Studio 2013 to compile freelan. All projects come
The root directory also contains a solution file (`.sln`) that references all the sub-projects.

The resulting binaries will be located in the [install](install) directory.

### Mac OSX

On Mac OSX, an additional SCons target exists to build the freelan installation package:

> scons package
The package will be generated at the root of the repository.
31 changes: 16 additions & 15 deletions SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -57,24 +57,25 @@ for x in Glob('apps/*'):

samples = []

for x in Glob('samples/*'):
libname = os.path.basename(str(x))
if env.mode != 'retail':
for x in Glob('samples/*'):
libname = os.path.basename(str(x))

if not sys.platform.startswith('linux'):
if libname in 'netlinkplus':
continue
if not sys.platform.startswith('linux'):
if libname in 'netlinkplus':
continue

for y in x.glob('*'):
sconscript_path = y.File('SConscript')
for y in x.glob('*'):
sconscript_path = y.File('SConscript')

if sconscript_path.exists():
name = 'sample_%s_%s' % (libname, os.path.basename(str(y)))
sample = SConscript(sconscript_path, exports='env dirs name')
samples.extend(sample)
if sconscript_path.exists():
name = 'sample_%s_%s' % (libname, os.path.basename(str(y)))
sample = SConscript(sconscript_path, exports='env dirs name')
samples.extend(sample)

if env.debug:
samples.extend(env.SymLink(y.File('%sd' % os.path.basename(str(y))).srcnode(), sample))
else:
samples.extend(env.SymLink(y.File(os.path.basename(str(y))).srcnode(), sample))
if env.mode == 'release':
samples.extend(env.SymLink(y.File('%sd' % os.path.basename(str(y))).srcnode(), sample))
else:
samples.extend(env.SymLink(y.File(os.path.basename(str(y))).srcnode(), sample))

Return('libraries includes apps samples configurations')
26 changes: 17 additions & 9 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,11 @@ class FreelanEnvironment(Environment):
A freelan specific environment class.
"""

def __init__(self, debug, prefix, **kwargs):
def __init__(self, mode, prefix, **kwargs):
"""
Initialize the environment.
:param debug: A boolean value that indicates whether to set debug flags
in the environment.
:param mode: The compilation mode.
:param prefix: The installation prefix.
"""
super(FreelanEnvironment, self).__init__(**kwargs)
Expand All @@ -71,7 +70,7 @@ class FreelanEnvironment(Environment):
if flag in os.environ:
self[flag] = Split(os.environ[flag])

self.debug = debug
self.mode = mode
self.prefix = prefix

if os.path.basename(self['CXX']) == 'clang++':
Expand All @@ -98,7 +97,7 @@ class FreelanEnvironment(Environment):
self.Append(CXXFLAGS=['--stdlib=libc++'])
self.Append(LDFLAGS=['--stdlib=libc++'])

if self.debug:
if self.mode == 'debug':
self.Append(CXXFLAGS=['-g'])
self.Append(CXXFLAGS='-DFREELAN_DEBUG=1')
else:
Expand Down Expand Up @@ -151,20 +150,29 @@ mode = GetOption('mode')
prefix = os.path.abspath(GetOption('prefix'))

if mode in ('all', 'release'):
env = FreelanEnvironment(debug=False, prefix=prefix)
libraries, includes, apps, samples, configurations = SConscript('SConscript', exports='env', variant_dir=os.path.join('build', 'release'))
env = FreelanEnvironment(mode='release', prefix=prefix)
libraries, includes, apps, samples, configurations = SConscript('SConscript', exports='env', variant_dir=os.path.join('build', env.mode))
install = env.Install(os.path.join(prefix, 'bin'), apps)
install.extend(env.Install(os.path.join(prefix, 'etc', 'freelan'), configurations))

Alias('install', install)
Alias('apps', apps)
Alias('samples', samples)
Alias('all', install + apps + samples)

if mode in ('all', 'debug'):
env = FreelanEnvironment(debug=True, prefix=prefix)
libraries, includes, apps, samples, configurations = SConscript('SConscript', exports='env', variant_dir=os.path.join('build', 'debug'))
env = FreelanEnvironment(mode='debug', prefix=prefix)
libraries, includes, apps, samples, configurations = SConscript('SConscript', exports='env', variant_dir=os.path.join('build', env.mode))
Alias('apps', apps)
Alias('samples', samples)
Alias('all', apps + samples)

if sys.platform.startswith('darwin'):
retail_prefix = '/usr/local'
env = FreelanEnvironment(mode='retail', prefix=retail_prefix)
libraries, includes, apps, samples, configurations = SConscript('SConscript', exports='env', variant_dir=os.path.join('build', env.mode))
package = SConscript('packaging/osx/SConscript', exports='env apps configurations retail_prefix')
install_package = env.Install('.', package)
Alias('package', install_package)

Default('install')
5 changes: 5 additions & 0 deletions defines.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ def version(self):

return self._version

@property
def version_str(self):
return '%s.%s' % (self.version.major, self.version.minor)

@property
def date(self):
if self._date is None:
Expand Down Expand Up @@ -125,6 +129,7 @@ def register_into(self, env):
action=self.action,
emitter=self.emitter,
)})
env.defines = self

def generate_defines(self, target):
"""
Expand Down
5 changes: 3 additions & 2 deletions packaging/osx/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
*.pkg
org.freelan.freelan
distribution.xml
root/
resources/conclusion.html
23 changes: 0 additions & 23 deletions packaging/osx/Makefile

This file was deleted.

4 changes: 3 additions & 1 deletion packaging/osx/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Mac OS X Installer

To build the Mac OS X package, just type "make".
To build the Mac OS X package, just type "scons -u .".

You can also build it from the repository root by typing "scons package".
104 changes: 104 additions & 0 deletions packaging/osx/SConscript
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import os
import pkgbuild
import productbuild
import plist
import generate_script
import template


def relative(path):
return path.lstrip('/')


Import('env apps configurations retail_prefix')

env = env.Clone()

for module in [pkgbuild, productbuild, plist, generate_script, template]:
module.generate(env)

root = env.Dir('root')
scripts = env.Dir('scripts')
options = {
'identifier': 'org.freelan.freelan',
'version': env.defines.version_str,
'ownership': 'recommended',
}
resources = env.Dir('resources')
distribution_template = env.File('distribution.xml.in')
conclusion_template = resources.File('conclusion.html.in')

bin_path = os.path.join(retail_prefix, 'bin')
etc_freelan_path = os.path.join(retail_prefix, 'etc/freelan')
share_freelan_path = os.path.join(retail_prefix, 'share/freelan')
uninstall_script = os.path.join(share_freelan_path, 'uninstall.sh')
launch_daemon_script = os.path.join(
'/Library/LaunchDaemons',
options['identifier'] + '.plist',
)

uninstall_script_source = env.Value([
'/bin/launchctl unload ' + launch_daemon_script,
'rm -f ' + launch_daemon_script,
'rm -f ' + os.path.join(bin_path, apps[0].name),
'rm -rf ' + etc_freelan_path,
])
launch_daemon_script_source = env.Value({
'Label': options['identifier'],
'ProgramArguments': [
os.path.join(bin_path, apps[0].name),
'-c',
os.path.join(etc_freelan_path, configurations[0].name),
'-f',
],
'RunAtLoad': True,
'KeepAlive': True,
})

env.Install(
root.Dir(relative(bin_path)),
apps,
)
env.Install(
root.Dir(relative(etc_freelan_path)),
configurations,
)
env.GenerateScript(
root.File(relative(uninstall_script)),
uninstall_script_source,
)
env.Plist(
root.File(relative(launch_daemon_script)),
launch_daemon_script_source,
)

package = env.PkgBuild(
target=options['identifier'] + '.pkg',
source=root,
PKGBUILD_OPTIONS=env.Value(options),
PKGBUILD_SCRIPTS=scripts,
)
distribution_file = env.Template(
source=distribution_template,
TEMPLATE_DICT=env.Value({'version': env.defines.version_str}),
)
conclusion_file = env.Template(
source=conclusion_template,
TEMPLATE_DICT=env.Value({
'configuration_file': os.path.join(
etc_freelan_path,
configurations[0].name,
)
}),
)
final_package = env.ProductBuild(
target='freelan_{version}.pkg'.format(version=env.defines.version_str),
source=distribution_file,
PRODUCTBUILD_OPTIONS=env.Value({
'version': env.defines.version_str,
}),
PRODUCTBUILD_RESOURCES=resources,
PRODUCTBUILD_PACKAGE_PATH=[env.Dir('.')],
)

Return('final_package')
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<installer-gui-script minSpecVersion="1">
<title>freelan 1.1</title>
<title>FreeLAN {version}</title>
<organization>org.freelan</organization>
<domains enable_localSystem="true"/>
<options customize="never" require-scripts="true" rootVolumeOnly="true" />
Expand All @@ -18,7 +18,7 @@
</choices-outline>

<!-- Define each choice above -->
<choice id="org.freelan.freelan" visible="false" title="freelan" description="The freelan daemon" start_selected="true">
<choice id="org.freelan.freelan" visible="false" title="FreeLAN" description="The FreeLAN binary" start_selected="true">
<pkg-ref id="org.freelan.freelan"/>
</choice>
</installer-gui-script>
36 changes: 36 additions & 0 deletions packaging/osx/generate_script.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""A SCons builder for plist files"""


def generate_script_emitter(target, source, env):
env.Depends(target, env.Value(env['GENERATE_SCRIPT_TEMPLATE']))

return (target, source)


def generate_script_action(target, source, env):
template = env['GENERATE_SCRIPT_TEMPLATE']

for targ in target:
with open(targ.abspath, 'w') as targf:
targf.write(
template.format(
commands='\n'.join(source[0].value),
),
)


def generate(env):
env.Append(GENERATE_SCRIPT_TEMPLATE="""#!/bin/sh
{commands}
""")

import SCons.Builder

generate_script_builder = SCons.Builder.Builder(
action=generate_script_action,
emitter=generate_script_emitter,
suffix='.sh',
)

env.Append(BUILDERS={'GenerateScript': generate_script_builder})
17 changes: 0 additions & 17 deletions packaging/osx/org.freelan.freelan.plist

This file was deleted.

Loading

0 comments on commit d580d3d

Please sign in to comment.