summaryrefslogtreecommitdiffstats
path: root/build/mixxx.py
diff options
context:
space:
mode:
authorRJ Ryan <rryan@mixxx.org>2013-06-19 00:46:54 -0400
committerRJ Ryan <rryan@mixxx.org>2013-06-19 00:46:54 -0400
commit25d57b59dff3947212909634864dd82365c9606b (patch)
treef0d0f8a048f8ed2f45c5ff015fc96891662f72f1 /build/mixxx.py
parente50f9f168fa08f2be6d0f13e8a225bbcc9de09bb (diff)
Moving mixxx/* to the root. A new era begins!
Diffstat (limited to 'build/mixxx.py')
-rw-r--r--build/mixxx.py390
1 files changed, 390 insertions, 0 deletions
diff --git a/build/mixxx.py b/build/mixxx.py
new file mode 100644
index 0000000000..0da9bde6bb
--- /dev/null
+++ b/build/mixxx.py
@@ -0,0 +1,390 @@
+# -*- coding: utf-8 -*-
+import logging
+import platform
+import sys
+import os
+import re
+import shutil
+
+import SCons
+from SCons import Script
+
+import util
+
+class MixxxBuild(object):
+
+ def __init__(self, target, machine, build, toolchain, available_features=[]):
+ self.available_features = available_features
+ self.host_platform = self.detect_platform()
+ self.host_machine = self.detect_machine()
+ self.flags = {}
+
+ if target is None:
+ target = self.host_platform
+
+ if machine is None:
+ machine = self.host_machine
+
+ if toolchain is None:
+ if self.host_platform == 'windows':
+ raise Exception('must specify toolchain on Windows (msvs or gnu)')
+ else:
+ toolchain = 'gnu'
+
+ if build is None:
+ build = 'debug'
+
+ if not build in ['debug', 'release']:
+ raise Exception("invalid build type")
+
+ if target not in ['windows', 'osx', 'linux', 'bsd']:
+ raise Exception("invalid target platform")
+
+ if machine not in ['x86_64', 'x86', 'i686', 'i586',
+ 'alpha', 'hppa', 'mips', 'mipsel', 's390',
+ 'sparc', 'ia64', 'armel', 'armhf', 'hurd-i386',
+ 'sh3', 'sh4',
+ 'kfreebsd-amd64', 'kfreebsd-i386',
+ 'i486', 'i386', 'powerpc', 'powerpc64',
+ 'powerpcspe', 's390x',
+ 'amd64', 'AMD64', 'EM64T', 'INTEL64']:
+ raise Exception("invalid machine type")
+
+ if toolchain not in ['gnu', 'msvs']:
+ raise Exception('invalid toolchain type')
+
+ if toolchain == 'msvs' and self.host_platform != 'windows':
+ raise Exception('cannot use msvs toolchain on non-windows platform')
+
+ self.platform = target
+ self.platform_is_posix = self.platform in ['linux', 'osx', 'bsd']
+ self.platform_is_linux = self.platform == 'linux'
+ self.platform_is_osx = self.platform == 'osx'
+ self.platform_is_bsd = self.platform == 'bsd'
+ self.platform_is_windows = self.platform == 'windows'
+
+ self.machine = machine
+ self.build = build
+ self.build_is_debug = build == 'debug'
+ self.build_is_release = build == 'release'
+
+ self.toolchain = toolchain
+ self.toolchain_is_gnu = self.toolchain == 'gnu'
+ self.toolchain_is_msvs = self.toolchain == 'msvs'
+
+ self.crosscompile = self.host_platform != self.platform
+
+ flags_force32 = int(Script.ARGUMENTS.get('force32', 0))
+ flags_force64 = int(Script.ARGUMENTS.get('force64', 0))
+ if flags_force32 and flags_force64:
+ logging.error('Both force32 and force64 cannot be enabled at once')
+ Script.Exit(1)
+
+ if flags_force32:
+ if self.machine in ['powerpc', 'powerpc64']:
+ self.machine = 'powerpc'
+ else:
+ self.machine = 'x86'
+ elif flags_force64:
+ if self.machine in ['powerpc', 'powerpc64']:
+ self.machine = 'powerpc64'
+ else:
+ self.machine = 'x86_64'
+ self.machine_is_64bit = self.machine in ['x86_64', 'powerpc64', 'AMD64', 'EM64T', 'INTEL64']
+ self.bitwidth = 64 if self.machine_is_64bit else 32
+ self.architecture_is_x86 = self.machine.lower() in ['x86', 'x86_64', 'i386', 'i486', 'i586', 'i686', 'EM64T', 'INTEL64']
+ self.architecture_is_powerpc = self.machine.lower() in ['powerpc', 'powerpc64']
+
+ self.build_dir = util.get_build_dir(self.platform, self.bitwidth)
+
+ # Currently this only works for Windows
+ self.static_dependencies = int(Script.ARGUMENTS.get('staticlibs', 0))
+ self.msvcdebug = int(Script.ARGUMENTS.get('msvcdebug', 0))
+
+ logging.info("Target Platform: %s" % self.platform)
+ logging.info("Target Machine: %s" % self.machine)
+ logging.info("Build: %s" % self.build)
+ logging.info("Toolchain: %s" % self.toolchain)
+ logging.info("Crosscompile: %s" % ("YES" if self.crosscompile else "NO"))
+ if self.platform_is_windows:
+ logging.info("Static dependencies: %s" % ("YES" if self.static_dependencies else "NO"))
+ logging.info("MSVC Debug build: %s" % ("YES" if self.msvcdebug else "NO"))
+
+ if self.crosscompile:
+ logging.info("Host Platform: %s" % self.host_platform)
+ logging.info("Host Machine: %s" % self.host_machine)
+
+ if self.crosscompile and self.host_platform != 'linux':
+ raise Exception('Cross-compiling on a non-Linux host not currently supported')
+
+ tools = ['default']
+ toolpath = ['#build/']
+ extra_arguments = {}
+ tools.append('qt4')
+ tools.append('protoc')
+
+ # Ugly hack to check the qtdir argument
+ import depends
+ default_qtdir = depends.Qt.DEFAULT_QTDIRS.get(self.platform, '')
+ qtdir = Script.ARGUMENTS.get('qtdir',
+ os.environ.get('QTDIR', default_qtdir))
+
+ # Validate the specified qtdir exists
+ if not os.path.exists(qtdir):
+ logging.error("QT path does not exist or QT4 is not installed.")
+ logging.error("Please specify your QT path by running 'scons qtdir=[path]'")
+ Script.Exit(1)
+ # And that it doesn't contain qt3
+ elif qtdir.find("qt3") != -1 or qtdir.find("qt/3") != -1:
+ logging.error("Mixxx now requires QT4 instead of QT3 - please use your QT4 path with the qtdir build flag.")
+ Script.Exit(1)
+ logging.info("Qt path: %s" % qtdir)
+
+ # Previously this wasn't done for OSX, but I'm not sure why
+ # -- rryan 6/8/2011
+ extra_arguments['QTDIR'] = qtdir
+
+ if self.platform == 'osx':
+ tools.append('OSConsX')
+ toolpath.append('#/build/osx/')
+ if self.platform_is_windows and self.toolchain == 'msvs':
+ toolpath.append('msvs')
+ extra_arguments['VCINSTALLDIR'] = os.getenv('VCInstallDir') # TODO(XXX) Why?
+ extra_arguments['QT_LIB'] = '' # TODO(XXX) Why?
+
+ # Setup the appropriate toolchains for cross-compiling
+ if self.crosscompile:
+ if self.platform_is_windows:
+ tools.append('crossmingw')
+ if self.platform == 'osx':
+ tools.append('crossosx')
+
+ self.env = Script.Environment(tools=tools, toolpath=toolpath, ENV=os.environ,
+ **extra_arguments)
+
+ self.read_environment_variables()
+
+ if self.toolchain_is_gnu:
+ if flags_force32:
+ self.env.Append(CCFLAGS = '-m32')
+ elif flags_force64:
+ self.env.Append(CCFLAGS = '-m64')
+
+ if self.platform == 'osx':
+ if self.machine == 'powerpc':
+ self.env.Append(CCFLAGS = '-arch ppc')
+ self.env.Append(LINKFLAGS = '-arch ppc')
+ else:
+ if self.bitwidth == 32:
+ self.env.Append(CCFLAGS = '-arch i386')
+ self.env.Append(LINKFLAGS = '-arch i386')
+ elif self.bitwidth == 64:
+ self.env.Append(CCFLAGS = '-arch x86_64')
+ self.env.Append(LINKFLAGS = '-arch x86_64')
+
+ if self.crosscompile:
+ crosscompile_root = Script.ARGUMENTS.get('crosscompile_root', '')
+
+ if crosscompile_root == '':
+ print "Your build setup indicates this is a cross-compile, but you did not specify 'crosscompile_root', which is required."
+ Script.Exit(1)
+
+ crosscompile_root = os.path.abspath(crosscompile_root)
+ self.env.Append(CPPPATH=os.path.join(crosscompile_root, 'include'))
+ self.env.Append(LIBPATH=os.path.join(crosscompile_root, 'lib'))
+ self.env.Append(LIBPATH=os.path.join(crosscompile_root, 'bin'))
+
+ self.install_options()
+ self.virtualize_build_dir()
+
+ def detect_platform(self):
+ if os.name == 'nt' or sys.platform == 'win32':
+ return 'windows'
+ # Should cover {Net,Open,Free,DragonFly}BSD, but only tested on OpenBSD
+ if 'bsd' in sys.platform:
+ return 'bsd'
+ if sys.platform in ['linux2', 'linux3']:
+ return 'linux'
+ if sys.platform == 'darwin':
+ return 'osx'
+ logging.error("Couldn't determine platform. os.name: %s sys.platform: %s"
+ % (os.name, sys.platform))
+ return 'invalid'
+
+ def detect_machine(self):
+ return platform.machine()
+
+ def read_environment_variables(self):
+ # Import environment variables from the terminal. Note that some
+ # variables correspond to variables inside the SCons env with different
+ # names, eg. the shell's "CFLAGS" ---> SCons' "CCFLAGS".
+ if os.environ.has_key('CC'):
+ self.env['CC'] = os.environ['CC']
+ if os.environ.has_key('CFLAGS'):
+ self.env['CFLAGS'] += SCons.Util.CLVar(os.environ['CFLAGS'])
+ if os.environ.has_key('CXX'):
+ self.env['CXX'] = os.environ['CXX']
+ if os.environ.has_key('CXXFLAGS'):
+ self.env['CXXFLAGS'] += SCons.Util.CLVar(os.environ['CXXFLAGS'])
+ if os.environ.has_key('LDFLAGS'):
+ self.env['LINKFLAGS'] += SCons.Util.CLVar(os.environ['LDFLAGS'])
+
+ # Initialize this as a list, fixes a bug where first CPPDEFINE would get
+ # mangled
+ self.env['CPPDEFINES'] = []
+ self.env['LIBS'] = []
+ self.env['LIBPATH'] = []
+
+ def get_cache_dir(self):
+ # Global cache directory Put all project files in it so a rm -rf cache
+ # will clean up the config
+ if not self.env.has_key('CACHEDIR'):
+ self.env['CACHEDIR'] = str(Script.Dir('#cache/'))
+ if not os.path.isdir(self.env['CACHEDIR']):
+ os.mkdir(self.env['CACHEDIR'])
+ return str(self.env['CACHEDIR'])
+
+ def install_options(self):
+ cachefile = os.path.join(self.get_cache_dir(), 'custom.py')
+ vars = Script.Variables(cachefile)
+ vars.Add('prefix', 'Set to your install prefix', '/usr/local')
+ vars.Add('qtdir', 'Set to your QT4 directory', '/usr/share/qt4')
+ if self.platform_is_windows:
+ vars.Add('sqlitedll', 'Set to 1 to enable including QSQLite.dll.\
+\n Set to 0 if SQLite support is compiled into QtSQL.dll.', 1)
+ vars.Add('target', 'Set the build target for cross-compiling (windows, osx, linux, bsd).', '')
+ vars.Add('machine', 'Set the machine type for cross-compiling (x86_64, x86, powerpc, powerpc64).', '')
+ vars.Add('toolchain', 'Specify the toolchain to use for building (gnu, msvs). Default is gnu.', 'gnu')
+ vars.Add('crosscompile_root', 'Set the path to the root of a cross-compile sandbox.', '')
+ vars.Add('force32', 'Force a 32-bit compile', 0)
+ vars.Add('force64', 'Force a 64-bit compile', 0)
+
+ for feature_class in self.available_features:
+ # Instantiate the feature
+ feature = feature_class()
+
+ # Add the feature to the feature list
+ feature.add_options(self, vars)
+
+ vars.Update(self.env)
+ Script.Help(vars.GenerateHelpText(self.env))
+
+ #Save the options to cache
+ vars.Save(cachefile, self.env)
+
+ def virtualize_build_dir(self):
+ # Symlinks don't work on Windows.
+ if self.host_platform == 'windows':
+ return
+
+ should_virtualize = int(Script.ARGUMENTS.get('virtualize', 1))
+ if not should_virtualize:
+ return
+
+ branch_name = util.get_branch_name()
+ if not branch_name:
+ return
+ # TODO(rryan) what other branch name characters aren't allowed in
+ # filenames?
+ branch_name = re.sub('[/<>|"]', '_', branch_name).lower()
+
+ branch_build_dir = os.path.join(self.get_cache_dir(), branch_name)
+
+ # Write sconsign.dblite files to branch_build_dir so that the file
+ # signatures are kept separate across branches.
+ sconsign_file = os.path.join(branch_build_dir, 'sconsign.dblite')
+ self.env.SConsignFile(sconsign_file)
+
+ try:
+ print "os.makedirs", branch_build_dir
+ os.makedirs(branch_build_dir)
+ except:
+ # os.makedirs throws an exception if branch_build_dir already
+ # exists.
+ pass
+ virtual_build_dir = os.path.join(branch_build_dir, self.build_dir)
+
+ # If build_dir is a symlink, check that it points to virtual_build_dir.
+ if os.path.islink(self.build_dir):
+ # Make sure virtual_build_dir exists. This happens if we are
+ # building for a new branch.
+ try:
+ print "os.makedirs", virtual_build_dir
+ os.makedirs(virtual_build_dir)
+ except:
+ # os.makedirs throws an exception if branch_build_dir already
+ # exists.
+ pass
+
+ # Get the path build_dir points to.
+ build_dir_path = os.readlink(self.build_dir)
+
+ # If it does not point to virtual_build_dir then unlink and link it
+ # to virtual_build_dir.
+ if os.path.abspath(build_dir_path) != os.path.abspath(virtual_build_dir):
+ print "os.unlink", self.build_dir
+ os.unlink(self.build_dir)
+ print "os.symlink", virtual_build_dir, self.build_dir
+ os.symlink(virtual_build_dir, self.build_dir)
+ elif os.path.isdir(self.build_dir):
+ # If build_dir is a directory, move it to virtual_build_dir.
+ print "shutil.move", self.build_dir, branch_build_dir
+ shutil.move(self.build_dir, branch_build_dir)
+ print "os.symlink", virtual_build_dir, self.build_dir
+ os.symlink(virtual_build_dir, self.build_dir)
+ else:
+ # Make sure virtual_build_dir exists. This happens if we are
+ # building for a new branch.
+ try:
+ print "os.makedirs", virtual_build_dir
+ os.makedirs(virtual_build_dir)
+ except:
+ # os.makedirs throws an exception if branch_build_dir already
+ # exists.
+ pass
+ print "os.symlink", virtual_build_dir, self.build_dir
+ os.symlink(virtual_build_dir, self.build_dir)
+
+ def get_features(self):
+ return self.available_features
+
+class Dependence(object):
+
+ def _get_name(self):
+ return self.__class__.__name__
+ name = property(_get_name)
+
+ def sources(self, build):
+ return []
+
+ def satisfy(self):
+ pass
+
+ def depends(self, build):
+ return []
+
+ def configure(self, build, conf):
+ pass
+
+ def post_dependency_check_configure(self, build, conf):
+ pass
+
+class Feature(Dependence):
+
+ def _get_name(self):
+ return self.__class__.__name__
+ name = property(_get_name)
+ status = ""
+
+ def satisfy(self, build):
+ raise NotImplementedError()
+
+ def description(self):
+ raise NotImplementedError()
+
+ def enabled(self, build):
+ return False
+
+ def add_options(self, build, vars):
+ pass
+