""" The SConstruct file. Works on all UNIX-like operating systems. """ import os import sys import SCons.Errors from fnmatch import fnmatch # This file is local. from defines import Defines AddOption( '--mode', dest='mode', nargs=1, action='store', choices=('all', 'debug', 'release'), default='all', help='The compilation mode.', ) AddOption( '--mongoose', dest='mongoose', nargs=1, action='store', choices=('yes', 'no'), default='no', help='Build webserver with mongoose (warning: it will violate GPLv3 license to distribute binaries built with this switch turned on!)', ) AddOption( '--upnp', dest='upnp', nargs=1, action='store', choices=('yes', 'no'), default='yes', help='Build FreeLAN with UPnP support.', ) class FreelanEnvironment(Environment): """ A freelan specific environment class. """ def __init__(self, mode, prefix, bin_prefix=None, **kwargs): """ Initialize the environment. :param mode: The compilation mode. :param prefix: The installation prefix. """ super(FreelanEnvironment, self).__init__(**kwargs) # Inherit the environment from the context. self['ENV'] = os.environ self.defines = Defines() self.defines.register_into(self) for flag in [ 'CC', 'CXX', 'AR', 'LINK', ]: if flag in os.environ: self[flag] = os.environ[flag] for flag in [ 'CFLAGS', 'CXXFLAGS', 'CPPFLAGS', 'ARFLAGS', 'LDFLAGS', 'LINKFLAGS', 'LIBS', ]: if flag in os.environ: self[flag] = Split(os.environ[flag]) self.mode = mode self.prefix = prefix self.bin_prefix = bin_prefix if bin_prefix else prefix self.destdir = self['ENV'].get('DESTDIR', '') self.mongoose = mongoose self.upnp = upnp if self.destdir: self.install_prefix = os.path.normpath( os.path.abspath(self.destdir), ) + self.prefix self.bin_install_prefix = os.path.normpath( os.path.abspath(self.destdir), ) + self.bin_prefix else: self.install_prefix = self.prefix self.bin_install_prefix = self.bin_prefix if self['CXX'] is None: raise SCons.Errors.BuildError( errstr=( "Failed to detect C++ compiler : CXX environment variable not set." "\nIs g++ or clang++ available in your PATH ?" "\nIf you have no idea what this is about," "\ntry installing the 'build-essential' package")) else: if os.path.basename(self['CXX']) == 'clang++': self.Append(CXXFLAGS=['-Qunused-arguments']) self.Append(CXXFLAGS=['-fcolor-diagnostics']) elif os.path.basename(self['CXX']).startswith('g++'): self.Append(CXXFLAGS=['-Wno-missing-field-initializers']) self.Append(CXXFLAGS=['--std=c++11']) self.Append(CXXFLAGS=['-Wall']) self.Append(CXXFLAGS=['-Wextra']) self.Append(CXXFLAGS=['-Werror']) self.Append(CXXFLAGS=['-pedantic']) #self.Append(CXXFLAGS=['-Wshadow']) self.Append(LDFLAGS=['--std=c++11']) if sys.platform.startswith('darwin'): self.Append(CXXFLAGS=['-arch', 'x86_64']) self.Append(CXXFLAGS=['-DBOOST_ASIO_DISABLE_KQUEUE']) self.Append(CXXFLAGS=['--stdlib=libc++']) self.Append(CXXFLAGS=['-I/usr/local/opt/openssl/include']) self.Append(CFLAGS=['-I/usr/local/opt/openssl/include']) self.Append(LDFLAGS=['--stdlib=libc++']) self.Append(LDFLAGS=['-L/usr/local/opt/openssl/lib']) self.Append(LIBPATH=['/usr/local/opt/openssl/lib']) if sys.platform.startswith('freebsd'): self.Append(CXXFLAGS=['-I/usr/local/include', '-Wno-shadow', '-Wno-nested-anon-types', '-Wno-unused-parameter']) self.Append(CFLAGS=['-I/usr/local/include', '-Wno-shadow', '-Wno-nested-anon-types', '-Wno-unused-parameter']) self.Append(LDFLAGS=['-L/usr/local/lib']) self.Append(LIBPATH=['/usr/local/lib']) if sys.platform.startswith('openbsd'): self.Append(CXXFLAGS=['-I/usr/local/include', '-pthread', '-Wno-shadow', '-Wno-nested-anon-types', '-Wno-unused-parameter', '-Wno-unused-local-typedef']) self.Append(CFLAGS=['-I/usr/local/include', '-pthread', '-Wno-shadow', '-Wno-nested-anon-types', '-Wno-unused-parameter', '-Wno-unused-local-typedef']) self.Append(LDFLAGS=['-L/usr/local/lib']) self.Append(LIBPATH=['/usr/local/lib']) if sys.platform.startswith('netbsd'): self.Append(CXXFLAGS=['-I/usr/pkg/include', '-Wno-shadow', '-Wno-unused', '-Wno-uninitialized']) self.Append(CFLAGS=['-I/usr/pkg/include', '-Wno-shadow', '-Wno-unused', '-Wno-uninitialized']) self.Append(LIBPATH=['/usr/pkg/lib']) if self.mode == 'debug': self.Append(CXXFLAGS=['-g']) self.Append(CXXFLAGS='-DFREELAN_DEBUG=1') else: self.Append(CXXFLAGS='-O3') if self.mongoose == 'yes': self.Append(CXXFLAGS=['-DUSE_MONGOOSE']) if self.upnp == 'yes': self.Append(CXXFLAGS=['-DUSE_UPNP']) self.Append(CPPDEFINES=r'FREELAN_INSTALL_PREFIX="\"%s\""' % self.prefix) def RGlob(self, path, patterns=None): """ Returns a list of file objects that match the specified patterns. """ if isinstance(patterns, str): patterns = [patterns] path = str(path) result = [] abspath = Dir(path).srcnode().abspath for root, ds, fs in os.walk(abspath): prefix = os.path.relpath(root, abspath) for f in fs: if not patterns or any(fnmatch(f, pattern) for pattern in patterns): result.append(File(os.path.join(path, prefix, f))) return result def RInstall(self, target, source, patterns=None): """ Install a directory, keeping its structure. """ files = self.RGlob(source, patterns) result = [] for f in files: result.append(self.Install(os.path.join(str(target), os.path.dirname(str(f))), f)) return result def SymLink(self, target, source): def create_symlink(target, source, env): os.symlink(os.path.abspath(str(source[0])), os.path.abspath(str(target[0]))) return self.Command(target, source, create_symlink) mode = GetOption('mode') mongoose = GetOption('mongoose') upnp = GetOption('upnp') prefix = os.path.normpath(os.path.abspath(ARGUMENTS.get('prefix', './install'))) if 'bin_prefix' in ARGUMENTS: bin_prefix = os.path.normpath(os.path.abspath(ARGUMENTS['bin_prefix'])) else: bin_prefix = None if mode in ('all', 'release'): env = FreelanEnvironment(mode='release', prefix=prefix, bin_prefix=bin_prefix, mongoose=mongoose, upnp=upnp) libraries, includes, apps, samples, configurations, help = SConscript('SConscript', exports='env', variant_dir=os.path.join('build', env.mode)) install = env.Install(os.path.join(env.bin_install_prefix, 'bin'), apps) install.extend(env.Install(os.path.join(env.bin_install_prefix, 'share/man', 'man1'), help)) install.extend(env.Install(os.path.join(env.install_prefix, 'etc', 'freelan'), configurations)) Alias('install', install) Alias('apps', apps + help) Alias('samples', samples) Alias('all', install + apps + help + samples) if mode in ('all', 'debug'): env = FreelanEnvironment(mode='debug', prefix=prefix, mongoose=mongoose, upnp=upnp) libraries, includes, apps, samples, configurations, help = SConscript('SConscript', exports='env', variant_dir=os.path.join('build', env.mode)) Alias('apps', apps + help) Alias('samples', samples) Alias('all', apps + help + samples) if sys.platform.startswith('darwin'): retail_prefix = '/usr/local' env = FreelanEnvironment(mode='retail', prefix=retail_prefix, mongoose=mongoose, upnp=upnp) libraries, includes, apps, samples, configurations, help = SConscript('SConscript', exports='env', variant_dir=os.path.join('build', env.mode)) package = SConscript('packaging/osx/SConscript', exports='env apps configurations retail_prefix help') install_package = env.Install('.', package) Alias('package', install_package) Default('install')