diff options
author | konablend <[email protected]> | 2009-03-01 17:03:11 +0000 |
---|---|---|
committer | konablend <[email protected]> | 2009-03-01 17:03:11 +0000 |
commit | 4dbce6b69967c1e14092637aa95b6c31855a81fc (patch) | |
tree | 516c17095967698eeb419c70ce72dbd2c11bf754 /make | |
parent | c47939541ccec1e5e57753b16b28baed2613f586 (diff) |
BuildSystem: conversion from jam-based to make-based system.
KNOWN ISSUES:
1. OSX + Xcode builds do not support parallel builds; attempting to
use them may cause unbounded number of jobs. However, disabling
via configure --disable-xcode avoids the issue.
2. OSX ppc binary produces binary which has audio-scan problems.
3. OSX ppc64 binary has not been runtime tested.
ADDED:
00-BuildUserGuide.txt
contrib/*/module.*
doc/
make/
libhb/module.*
test/module.*
macos/module.*
gtk/module.*
DROPPED:
BUILD
BuildContribDarwin.sh
DownloadMacOsXContribBinaries.sh
Jamfile
Jamrules
MacOsXContribBinariesVersion.txt
Makefile
Makefile.config
jam
libhb/Jamefile
libhb/Makefile
test/BUILDSHARED
test/Makefile
contrib/Jamfile
contrib/Makefile
contrib/patch-ffmpeg.patch
contrib/patch-x264-idr.patch
contrib/patch-x264-linux.patch
RENAMED:
contrib/*.patch -> contrib/MODULE/[AP]??-*.patch
macosx/HandBrake.plist -> macosx/Info.plist
MODIFIED: libhb/decavcodec.c
Patched to use cleaner include "libavcodec/audioconvert".
Second part to support this cleanup is ffmpeg A02-audioconvert.patch .
MODIFIED: libhb/hb.c
MODIFIED: libhb/hb.h
MODIFIED: libhb/muxmkv.c
MODIFIED: libhb/muxmp4.c
MODIFIED: libhb/update.c
Patched to use "project.h" for project metadata.
Renamed HB_BUILD -> HB_PROJECT_BUILD.
Renamed HB_VERSION -> HB_PROJECT_VERSION.
MODIFIED: test/test.c:
Patched HandBrakeCLI to support I/O on Mac OS X ZFS filesystems.
Reference r1803 as similar patch for HandBrake.app .
Unpatched behavior is crash/buserror when using ZFS.
MODIFIED: macosx/Growl.framework/
Upgraded 0.7.6 (i386,ppc) -> 1.1.2 (i386,x86_64,ppc,ppc64).
New architectures facilitate x86_64 and ppc64 builds.
MODIFIED: macosx/HandBrake.xcodeproj/
Bumped compatibilty mode from 2.4 -> 3.1 .
Dumped old configurations Deployment, Developer.
Added configurations standard, sebug as replacements.
Added standard.i386, standard.x86_64, standard.ppc, standard.ppc64 .
for explicit architecture build.
All configurations settings cleaned up and normalized.
Build output directories adjusted to support new build system.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@2180 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'make')
-rw-r--r-- | make/configure.py | 752 | ||||
-rw-r--r-- | make/include/base.defs | 50 | ||||
-rw-r--r-- | make/include/contrib.defs | 276 | ||||
-rw-r--r-- | make/include/function.defs | 19 | ||||
-rw-r--r-- | make/include/gcc.defs | 146 | ||||
-rw-r--r-- | make/include/main.defs | 75 | ||||
-rw-r--r-- | make/include/main.rules | 39 | ||||
-rw-r--r-- | make/include/report.defs | 53 | ||||
-rw-r--r-- | make/include/select.defs | 12 | ||||
-rw-r--r-- | make/include/target.defs | 14 | ||||
-rw-r--r-- | make/include/tool.defs | 10 | ||||
-rw-r--r-- | make/variant/cygwin.defs | 8 | ||||
-rw-r--r-- | make/variant/darwin.defs | 61 | ||||
-rw-r--r-- | make/variant/darwin.rules | 20 | ||||
-rw-r--r-- | make/variant/darwin.x86_64.defs | 3 | ||||
-rw-r--r-- | make/variant/freebsd.defs | 4 | ||||
-rw-r--r-- | make/variant/linux.defs | 11 |
17 files changed, 1553 insertions, 0 deletions
diff --git a/make/configure.py b/make/configure.py new file mode 100644 index 000000000..1aa85bd39 --- /dev/null +++ b/make/configure.py @@ -0,0 +1,752 @@ +import fnmatch +import optparse +import os +import platform +import re +import subprocess +import sys +import time + +from optparse import OptionGroup +from optparse import OptionGroup +from optparse import OptionParser +from sys import stderr +from sys import stdout + +############################################################################### + +def errf( format, *args ): + stderr.write( ('ERROR: ' + format + '\n') % args ) + sys.exit( 1 ) + +def outf( format, *args ): + stdout.write( (format + '\n') % args ) + +############################################################################### + +## Expand values of iterable object into a decent string representation. +## +def expandValues( obj ): + buf = '' + for v in obj: + buf += ', ' + v + return '{ ' + buf[2:] + ' }' + +############################################################################### + +## Find executable by searching path. +## On success, returns full pathname of executable. +## On fail, returns None. +## +def findExecutable( name ): + if len( os.path.split(name)[0] ): + return name if os.access( name, os.X_OK ) else None + + if not os.environ.has_key( 'PATH' ) or os.environ[ 'PATH' ] == '': + path = os.defpath + else: + path = os.environ['PATH'] + + for dir in path.split( os.pathsep ): + f = os.path.join( dir, name ) + if os.access( f, os.X_OK ): + return f + return None + +############################################################################### + +def computeDefaultMakeJobs(): + ## good for darwin9.6.0 and linux + try: + n = os.sysconf( 'SC_NPROCESSORS_ONLN' ) + if n < 1: + n = 1 + return n + except: + pass + ## windows + try: + n = int( os.environ['NUMBER_OF_PROCESSORS'] ) + if n < 1: + n = 1 + return n + except: + pass + return 1 + +############################################################################### + +## taken from python2.6 -- we need it +def relpath(path, start=os.path.curdir): + """Return a relative version of a path""" + + if not path: + raise ValueError("no path specified") + + start_list = os.path.abspath(start).split(os.sep) + path_list = os.path.abspath(path).split(os.sep) + + # Work out how much of the filepath is shared by start and path. + i = len(os.path.commonprefix([start_list, path_list])) + + rel_list = [os.pardir] * (len(start_list)-i) + path_list[i:] + if not rel_list: + return os.path.curdir + return os.path.join(*rel_list) + +############################################################################### + +# compute project dir which should be 2 dirs below this script +build_dir = os.curdir +project_dir = os.path.normpath( sys.argv[0] ) +for i in range( 2 ): + project_dir = os.path.dirname( project_dir ) +if len( project_dir ) == 0: + project_dir = os.curdir + +############################################################################### + +## model gnu-autotools platform guess +## +## native format: +## (PROC)-(VENDOR)-(SYSTEM)(RELEASE)-(EXTRA) +## +## examples: +## i386-apple-darwin9.6.0 (Mac OS X 10.5.6 Intel) +## powerpc-apple-darwin9.6.0 (Mac OS X 10.5.6 PPC) +## i686-pc-cygwin (Cygwin, Microsoft Vista) +## x86_64-unknown-linux-gnu (Linux, Fedora 10 x86_64) +## +class Guess: + def __init__( self ): + self.proc = 'unknown' + self.vendor = 'unknown' + self.system = 'unknown' + self.release = '0.0.0' + self.extra = '' + + p_system = platform.system().lower() + p_release = platform.release().lower() + p_processor = platform.processor().lower() + p_machine = platform.machine().lower() + + if re.match( 'cygwin', p_system ): + self.proc = p_machine + self.vendor = 'pc' + self.system = 'cygwin' + self.release = '' + self.extra = '' + elif re.match( 'darwin', p_system ): + self.proc = p_machine + self.vendor = 'apple' + self.system = p_system + self.release = p_release + self.extra = '' + elif re.match( 'linux', p_system ): + self.proc = p_machine + self.vendor = 'unknown' + self.system = p_system + self.release = '' + self.extra = 'gnu' + else: + errf( 'unrecognized host system: %s', p_system ) + + def __str__( self ): + if len(self.extra): + return '%s-%s-%s%s-%s' % (self.proc,self.vendor,self.system,self.release,self.extra) + else: + return '%s-%s-%s%s' % (self.proc,self.vendor,self.system,self.release) + + def match( self, spec ): + return fnmatch.fnmatch( str(self), spec ) + +############################################################################### + +# a tool represents a command-line tool which may be searched for in PATH +class Tool: + def __init__( self, parent, optional, var, *pool ): + self.name = pool[0] + self.optional = optional + self.var = var + self.pool = pool + self.found = None + if parent: + parent.register( self ) + + def addToConfig( self, config ): + config.add( self.var, self.found ) + + def addToGroup( self, group ): + group.add_option( '', '--' + self.name, help='specify %s location' % (self.name), default=None, metavar='EXE' ) + + def locate( self, options ): + spec = options.__dict__[self.name] + pool = self.pool if not spec else [spec] + for p in pool: + self.found = findExecutable( p ) + if self.found: + outf( 'located %s: %s', self.name, self.found ) + return + if self.optional: + outf( 'missing: %s (optional)', self.name ) + else: + errf( 'unable to locate tool: %s', self.name ) + +## a select tool picks first found from a list of tools +class SelectTool( Tool ): + def __init__( self, parent, var, name, *pool ): + self.var = var + self.name = name + self.pool = pool + self.found = None + + self.poolMap = {} + for p in self.pool: + self.poolMap[p.name] = p + if parent: + parent.register( self ) + + def addToConfig( self, config ): + config.add( self.var, self.found ) + + def addToGroup( self, group ): + group.add_option( '', '--' + self.name, help='select %s mode: %s' % (self.name,expandValues(self.poolMap)), + default=self.name, metavar='MODE' ) + + def locate( self, options ): + spec = options.__dict__[self.name] + if spec in self.poolMap: + self.found = spec + return + for p in self.pool: + if p.found: + self.found = p.name + outf( 'selected %s: %s', self.name, self.found ) + return + errf( 'require at least one location of: %s', expandValues( self.poolMap )) + +############################################################################### + +class ToolSet: + def __init__( self ): + self.items = [] + Tool( self, False, 'AR.exe', 'ar' ) + Tool( self, False, 'CP.exe', 'cp' ) + Tool( self, True, 'CURL.exe', 'curl' ) + Tool( self, False, 'GCC.gcc', 'gcc', 'gcc-4' ) + Tool( self, False, 'M4.exe', 'm4' ) + Tool( self, False, 'MKDIR.exe', 'mkdir' ) + Tool( self, False, 'PATCH.exe', 'patch' ) + Tool( self, False, 'RM.exe', 'rm' ) + Tool( self, False, 'TAR.exe', 'tar' ) + Tool( self, True, 'WGET.exe', 'wget' ) + + SelectTool( self, 'FETCH.select', 'fetch', self.wget, self.curl ) + + def register( self, item ): + self.__dict__[item.name] = item + self.items.append( item ) + +############################################################################### + +class OptionMode( list ): + def __init__( self, default, *items ): + super( OptionMode, self ).__init__( items ) + self.default = items[default] + self.mode = self.default + + def __str__( self ): + return ' '.join( self ).replace( self.mode, '*'+self.mode ) + + def addToGroup( self, group, option, name ): + group.add_option( '', option, help='select %s mode: %s' % (name,self), default=self.mode, metavar='MODE' ) + + def setFromOption( self, name, mode ): + if mode not in self: + errf( 'invalid %s mode: %s', name, mode ) + self.mode = mode + +############################################################################### + +## create singletons +guessHost = Guess() +guessBuild = Guess() + +makeTool = Tool( None, False, 'CONF.make', 'gmake', 'make' ) +tools = ToolSet() + +debugMode = OptionMode( 0, 'none', 'min', 'std', 'max' ) +optimizeMode = OptionMode( 1, 'none', 'speed', 'size' ) + +## populate platform-specific architecture modes +if guessHost.match( 'i386-*-darwin8.*' ): + archMode = OptionMode( 0, 'i386', 'ppc' ) +elif guessHost.match( 'powerpc-*-darwin8.*' ): + archMode = OptionMode( 1, 'i386', 'ppc' ) +elif guessHost.match( 'i386-*-darwin9.*' ): + archMode = OptionMode( 0, 'i386', 'x86_64', 'ppc', 'ppc64' ) +elif guessHost.match( 'powerpc-*-darwin9.*' ): + archMode = OptionMode( 2, 'i386', 'x86_64', 'ppc', 'ppc64' ) +else: + archMode = OptionMode( 0, guessHost.proc ) + +## create parser +parser = OptionParser( 'Usage: %prog' ) + +group = OptionGroup( parser, 'Feature Options' ) +group.add_option( '', '--disable-xcode', default=False, action='store_true', + help='disable Xcode (Darwin only)' ) +group.add_option( '', '--disable-gtk', default=False, action='store_true', + help='disable GTK GUI (Linux only)' ) +parser.add_option_group( group ) + +## add launch options +group = OptionGroup( parser, 'Launch Options' ) +group.add_option( '', '--launch', default=False, action='store_true', + help='launch build, capture log and wait for completion' ) +group.add_option( '', '--launch-jobs', default=1, action='store', metavar='N', + help='allow N jobs at once; 0 to match CPU count (1)' ) +group.add_option( '', '--launch-args', default=None, action='store', metavar='ARGS', + help='specify additional ARGS for launch command' ) +group.add_option( '', '--launch-dir', default='build', action='store', metavar='DIR', + help='specify scratch DIR to use for build (build)' ) +group.add_option( '', '--launch-force', default=False, action='store_true', + help='force use of scratch directory even if exists' ) +group.add_option( '', '--launch-log', default='log.txt', action='store', metavar='FILE', + help='specify log FILE (log.txt)' ) +group.add_option( '', '--launch-quiet', default=False, action='store_true', + help='do not echo build output' ) +parser.add_option_group( group ) + +## add compile options +group = OptionGroup( parser, 'Compiler Options' ) +debugMode.addToGroup( group, '--debug', 'debug' ) +optimizeMode.addToGroup( group, '--optimize', 'optimize' ) +archMode.addToGroup( group, '--arch', 'architecutre' ) +parser.add_option_group( group ) + +## add tool options +group = OptionGroup( parser, 'Tool Options' ) +makeTool.addToGroup( group ) +for tool in tools.items: + tool.addToGroup( group ) +parser.add_option_group( group ) + +(options, args) = parser.parse_args() + +## recompute values when launch mode +if options.launch: + options.launch_jobs = int(options.launch_jobs) + build_dir = options.launch_dir + if os.path.isabs( build_dir ): + project_dir = os.getcwd() + else: + project_dir = os.path.normpath( relpath( project_dir, build_dir )) + if options.launch_jobs == 0: + options.launch_jobs = computeDefaultMakeJobs() + if options.launch_jobs < 1: + options.launch_jobs = 1 + elif options.launch_jobs > 8: + options.launch_jobs = 8 + +## make sure configure does not run in source root +if os.path.abspath( project_dir ) == os.path.abspath( build_dir ): + errf( 'scratch (build) directory must not be the same as source root' ) + +## validate modes +debugMode.setFromOption( 'debug', options.debug ) +optimizeMode.setFromOption( 'optimize', options.optimize ) +archMode.setFromOption( 'architecture', options.arch ) + +## update guessBuild as per architecture mode +if guessHost.match( '*-*-darwin*' ): + if archMode.mode == 'i386': + guessBuild.proc = 'i386' + elif archMode.mode == 'x86_64': + guessBuild.proc = 'x86_64' + elif archMode.mode == 'ppc': + guessBuild.proc = 'powerpc' + elif archMode.mode == 'ppc64': + guessBuild.proc = 'powerpc64' +else: + guessBuild.proc = archMode.mode +guessBuild.cross = 0 if archMode.default == archMode.mode else 1 + +# locate tools +makeTool.locate( options ) +for tool in tools.items: + tool.locate( options ) + +############################################################################### + +## Repository object. +## Holds information gleaned from subversion working dir. +## +## Builds are classed into one of the following types: +## +## release +## must be built from official svn with '/tags/' in the url +## developer +## must be built from official svn but is not a release +## unofficial +## all other builds +## +class Repository: + def __init__( self ): + self.url = 'svn://nowhere.com/project/unknown' + self.root = 'svn://nowhere.com/project' + self.branch = 'unknown' + self.uuid = '00000000-0000-0000-0000-000000000000'; + self.rev = 0 + self.date = '0000-00-00 00:00:00 -0000' + self.wcversion = 'exported' + self.official = 0 + self.type = 'unofficial' + + # parse output: svnversion PROJECT_DIR + cmd = 'svnversion ' + project_dir + print 'running: %s' % (cmd) + try: + p = subprocess.Popen( cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) + p.wait(); + if p.returncode == 0: + self.wcversion = p.stdout.readline().rstrip() + except: + pass + + # parse output: svn info PROJECT_DIR + cmd = 'svn info ' + project_dir + print 'running: %s' % (cmd) + try: + p = subprocess.Popen( cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) + p.wait(); + if p.returncode == 0: + for line in p.stdout: + (name,value) = re.match( '([^:]+):\\s+(.+)', line.rstrip() ).groups() + if name == 'URL': + self.url = value + elif name == 'Repository Root': + self.root = value + elif name == 'Repository UUID': + self.uuid = value + elif name == 'Revision': + self.rev = int( value ) + elif name == 'Last Changed Date': + # strip chars in parens + if value.find( ' (' ): + self.date = value[0:value.find(' (')] + else: + self.date = value + except: + pass + + i = self.url.rfind( '/' ) + if i != -1 and i < len(self.url)-1: + self.branch = self.url[i+1:] + + # official UUID behavior + if self.uuid == 'b64f7644-9d1e-0410-96f1-a4d463321fa5': + self.official = 1 + m = re.match( '([^:]+)://([^/]+)/(.+)', self.url ) + if m and re.match( 'tags/', m.group( 3 )): + self.type = 'release' + else: + self.type = 'developer' + +############################################################################### + +## Project object. +## Contains manually updated version numbers consistent with HB releases +## and other project metadata. +## +class Project: + def __init__( self ): + self.name = 'HandBrake' + self.name_lower = self.name.lower() + self.name_upper = self.name.upper() + self.acro_lower = 'hb' + self.acro_upper = 'HB' + self.url_website = 'http://handbrake.fr' + self.url_community = 'http://forum.handbrake.fr' + self.url_irc = 'irc://irc.freenode.net/handbrake' + + self.vmajor = 0 + self.vminor = 9 + self.vpoint = 3 + + self.version = '%d.%d.%d' % (self.vmajor,self.vminor,self.vpoint) + appcastfmt = 'http://handbrake.fr/appcast%s.xml' + + if repo.type == 'release': + self.version_formal = '%s Release' % (self.version) + self.url_appcast = appcastfmt % ('') + elif repo.type == 'developer': + self.version_formal = '%s Developer ' % (self.version) + self.url_appcast = appcastfmt % ('_unstable') + else: + self.version_formal = '%s Unnofficial ' % (self.version) + self.url_appcast = appcastfmt % ('_unofficial') + + self.title = '%s %s' % (self.name,self.version) + self.build = time.strftime('%Y%m%d') + '01' + +############################################################################### + +## Config object used to output gnu-make or gnu-m4 output. +## +## Use add() to add NAME/VALUE pairs suitable for both make/m4. +## Use addBlank() to add a linefeed for both make/m4. +## Use addMake() to add a make-specific line. +## Use addM4() to add a m4-specific line. +## +class Config: + def __init__( self ): + self._items = [] + + def add( self, name, value ): + self._items.append( (name,value) ) + + def addBlank( self ): + self._items.append( None ) + + def addComment( self, format, *args ): + self.addMake( '## ' + format % args ) + self.addM4( 'dnl ' + format % args ) + + def addMake( self, line ): + self._items.append( ('?make',line) ) + + def addM4( self, line ): + self._items.append( ('?m4',line) ) + + def output( self, file, type ): + namelen = 0 + for item in self._items: + if item == None or item[0].find( '?' ) == 0: + continue + if len(item[0]) > namelen: + namelen = len(item[0]) + for item in self._items: + if item == None: + if type == 'm4': + file.write( 'dnl\n' ) + else: + file.write( '\n' ) + continue + if item[0].find( '?' ) == 0: + if item[0].find( type, 1 ) == 1: + file.write( '%s\n' % (item[1]) ) + continue + + if type == 'm4': + self._outputM4( file, namelen, item[0], item[1] ) + else: + self._outputMake( file, namelen, item[0], item[1] ) + + def _outputMake( self, file, namelen, name, value ): + file.write( '%-*s = %s\n' % (namelen, name, value )) + + def _outputM4( self, file, namelen, name, value ): + namelen += 7 + name = '<<__%s>>,' % name.replace( '.', '_' ) + file.write( 'define(%-*s <<%s>>)dnl\n' % (namelen, name, value )) + +############################################################################### + +## create configure line, stripping arg --launch, quoting others +configure = [] +for arg in sys.argv[1:]: + #if arg.find( '--launch' ) == 0: + # continue + if arg == '--launch': + continue + configure.append( '"%s"' % (arg.replace('"', '\\"')) ) + +## create singletones +repo = Repository() +project = Project() +config = Config() + +config.addComment( 'generated by configure on %s', time.strftime( '%c' )) + +config.addBlank() +config.add( 'CONF.args', ' '.join( configure )) + +config.addBlank() +config.add( 'HB.title', project.title ) +config.add( 'HB.name', project.name ) +config.add( 'HB.name.lower', project.name_lower ) +config.add( 'HB.name.upper', project.name_upper ) +config.add( 'HB.acro.lower', project.acro_lower ) +config.add( 'HB.acro.upper', project.acro_upper ) + +config.add( 'HB.url.website', project.url_website ) +config.add( 'HB.url.community', project.url_community ) +config.add( 'HB.url.irc', project.url_irc ) +config.add( 'HB.url.appcast', project.url_appcast ) + +config.add( 'HB.version.major', project.vmajor ) +config.add( 'HB.version.minor', project.vminor ) +config.add( 'HB.version.point', project.vpoint ) +config.add( 'HB.version', project.version ) +config.add( 'HB.version.formal', project.version_formal ) +config.add( 'HB.version.hex', '%04x%02x%02x%02x%06x' % (project.vmajor,project.vminor,project.vpoint,0,repo.rev) ) + +config.add( 'HB.build', project.build ) + +config.add( 'HB.repo.url', repo.url ) +config.add( 'HB.repo.root', repo.root ) +config.add( 'HB.repo.branch', repo.branch ) +config.add( 'HB.repo.uuid', repo.uuid ) +config.add( 'HB.repo.rev', repo.rev ) +config.add( 'HB.repo.date', repo.date ) +config.add( 'HB.repo.wcversion', repo.wcversion ) +config.add( 'HB.repo.official', repo.official ) +config.add( 'HB.repo.type', repo.type ) + +config.addBlank() +config.add( 'HOST.spec', guessHost ) +config.add( 'HOST.proc', guessHost.proc ) +config.add( 'HOST.vendor', guessHost.vendor ) +config.add( 'HOST.system', guessHost.system ) +config.add( 'HOST.release', guessHost.release ) +config.add( 'HOST.extra', guessHost.extra ) + +config.addBlank() +config.add( 'BUILD.spec', guessBuild ) +config.add( 'BUILD.proc', guessBuild.proc ) +config.add( 'BUILD.vendor', guessBuild.vendor ) +config.add( 'BUILD.system', guessBuild.system ) +config.add( 'BUILD.release', guessBuild.release ) +config.add( 'BUILD.extra', guessBuild.extra ) +config.add( 'BUILD.cross', guessBuild.cross ) +config.add( 'BUILD.date', time.strftime('%c') ) +config.add( 'BUILD.arch', archMode.mode ) + +config.addBlank() +config.add( 'BUILD/', os.curdir + os.sep ) +config.add( 'PROJECT/', project_dir + os.sep ) + +config.addBlank() +config.add( 'FEATURE.xcode', 0 if options.disable_xcode else 1 ) +config.add( 'FEATURE.gtk', 0 if options.disable_gtk else 1 ) + +config.addMake( '' ) +config.addMake( '## include main definitions' ) +config.addMake( 'include $(PROJECT/)make/include/main.defs' ) + +config.addBlank() +for tool in tools.items: + tool.addToConfig( config ) + +config.addBlank() +config.add( 'GCC.archs', archMode.mode if guessBuild.cross else '' ) +config.add( 'GCC.g', options.debug ) +config.add( 'GCC.O', options.optimize ) + +config.addMake( '' ) +config.addMake( '## include (optional) customization file' ) +config.addMake( '-include $(BUID/)GNUmakefile.custom' ) + +config.addMake( '' ) +config.addMake( '## include main rules' ) +config.addMake( 'include $(PROJECT/)make/include/main.rules' ) + +############################################################################### + +# generate make or m4 file +def generate( type ): + if type == 'make': + fname = 'GNUmakefile' + elif type == 'm4': + fname = os.path.join( 'project', project.name_lower + '.m4' ) + else: + raise ValueError, 'unknown file type: ' + type + + ftmp = fname + '.tmp' + + pdir = os.path.dirname( fname ) + if pdir: + if not os.path.exists( pdir ): + os.makedirs( pdir ) + + try: + try: + outf( 'generating %s', fname ) + file = open( ftmp, 'w' ) + config.output( file, type ) + finally: + try: + file.close() + except: + pass + except Exception, x: + try: + os.remove( ftmp ) + except Exception, x: + pass + errf( 'failed writing to %s\n%s', ftmp, x ) + + try: + os.rename( ftmp, fname ) + except Exception, x: + errf( 'failed writing to %s\n%s', fname, x ) + +############################################################################### + +if not options.launch: + generate( 'make' ) + generate( 'm4' ) + sys.exit( 0 ) + +############################################################################### + +if os.path.exists( options.launch_dir ): + if not options.launch_force: + errf( 'scratch directory already exists: %s', options.launch_dir ) +else: + outf( 'creating %s', options.launch_dir ) + os.makedirs( options.launch_dir ) + +outf( 'chdir %s', options.launch_dir ) +os.chdir( options.launch_dir ) +generate( 'make' ) +generate( 'm4' ) + +outf( 'opening %s', options.launch_log ) +try: + log = open( options.launch_log, 'w' ) +except Exception, x: + errf( 'open failure: %s', x ) + +cmd = '%s -j%d' % (makeTool.found,options.launch_jobs) +if options.launch_args: + cmd += ' ' + options.launch_args + +## record begin +timeBegin = time.time() +s = '###\n### TIME: %s\n### launch: %s\n###\n' % (time.asctime(),cmd) +stdout.write( s ); stdout.flush() +log.write( s ); log.flush() + +## launch/pipe +try: + pipe = subprocess.Popen( cmd, shell=True, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.STDOUT ) +except Exception, x: + errf( 'launch failure: %s', x ) +for line in pipe.stdout: + if not options.launch_quiet: + stdout.write( line ); stdout.flush() + log.write( line ); log.flush() +pipe.wait() + +## record end +timeEnd = time.time() +elapsed = timeEnd - timeBegin +result = '%s (exit code %d)' % ('success' if pipe.returncode == 0 else 'failed',pipe.returncode) +s = '###\n### TIME: %s\n### finished: %.2f seconds\n### %s\n###\n' % (time.asctime(),elapsed,result) +stdout.write( s ); stdout.flush() +log.write( s ); log.flush() + +log.close() +sys.exit( 0 ) diff --git a/make/include/base.defs b/make/include/base.defs new file mode 100644 index 000000000..3b4e666f3 --- /dev/null +++ b/make/include/base.defs @@ -0,0 +1,50 @@ +## Define module metadata. +## It is mandatory for every module to use this template. +## +## $(1) module name (uppercase) +## $(2) module name (lowercase) +## $(3) list of prerequisite modules (uppercase) +## +define import.MODULE.defs + ## indicates module is defined; useful for conditionals + $(1).enabled = 1 + + ## module name (lowercase) + $(1).name = $(2) + + ## list of prerequisite modules (uppercase) + $(1).prerequisites = $(3) + + ## add to global list of modules + MODULES.NAMES += $(1) + MODULES.names += $(2) +endef + +## +## $(1) module name (uppercase) +## +define import.MODULE.rules +$($(1).name).report: + @$(MAKE) report.true REPORT=module REPORT.module=$(1) + +## aggregate +report.modules:: $($(1).name).report + +endef + +.PHONY: report.main report.gcc report.modules + +report.modules:: + +.PHONY: report.main +report.main: + @$(MAKE) report.true REPORT=main + +.PHONY: report.gcc +report.gcc: + @$(MAKE) report.true REPORT=gcc + +## needed for nested make (which drives each report) +.PHONY: report.true +report.true: + @true diff --git a/make/include/contrib.defs b/make/include/contrib.defs new file mode 100644 index 000000000..772258c37 --- /dev/null +++ b/make/include/contrib.defs @@ -0,0 +1,276 @@ +CONTRIB.build/ = $(BUILD/)contrib/ +CONTRIB.download/ = $(PROJECT/)download/ +CONTRIB.host = $(if $(filter 1,$(BUILD.cross)),$(BUILD.spec)) + +############################################################################### + +## +## $(1) = module name (uppercase) +## +define import.CONTRIB.defs + ## + ## import gcc/g++ support mainly so we can force contrib choice of + ## gcc executable, and debug/optimization flags. + ## + $$(eval $$(call import.GCC,$(1))) + + ## + ## common values useful across targets + ## + $(1).src/ = $$(PROJECT/)contrib/$($(1).name)/ + $(1).build/ = $$(CONTRIB.build/)$($(1).name)/ + $(1).deps = $$(foreach n,$($(1).prerequisites),$$($$n.INSTALL.target)) + + ## + ## target: fetch + ## + $(1).FETCH.tar = $$(CONTRIB.download/)$$(notdir $$($(1).FETCH.url)) + $(1).FETCH.url = FETCH_IS_UNDEFINED + $(1).FETCH.target = $$($(1).FETCH.tar) + define $(1).FETCH + $$(call FETCH,$$@,$$($(1).FETCH.url)) + endef + + ## + ## target: extract + ## + $(1).EXTRACT.tarbase = $$(patsubst %.tar.gz,%,$$(notdir $$($(1).FETCH.url))) + $(1).EXTRACT.target/ = $$($(1).build/)$$($(1).EXTRACT.tarbase)/ + define $(1).EXTRACT + $$(TAR.exe) xfC $$($(1).FETCH.tar) $$($(1).build/) + endef + + ## + ## target: patch + ## + $(1).PATCH.srcs = $$(wildcard \ + $$($(1).src/)A??-*.patch \ + $$($(1).src/)P??-$$(BUILD.system)*.patch ) + + # extra line feed is required + define $(1).PATCH.item + $$(PATCH.exe) -t -p1 -d $$(1) < $$(2) + + endef + + $(1).PATCH.target = $$($(1).build/).stamp.patch + define $(1).PATCH + $$(foreach p,$$($(1).PATCH.srcs),$$(call $(1).PATCH.item,$$($(1).EXTRACT.target/),$$(p))) + endef + + ## + ## target: configure + ## + $(1).CONFIGURE.sete = set -e; + $(1).CONFIGURE.dir = $$($(1).EXTRACT.target/) + $(1).CONFIGURE.bootstrap = + $(1).CONFIGURE.exe = ./configure + $(1).CONFIGURE.host = $$(CONTRIB.host) + $(1).CONFIGURE.prefix = $$(call fn.ABSOLUTE,$$(CONTRIB.build/)) + $(1).CONFIGURE.deps = --disable-dependency-tracking + $(1).CONFIGURE.shared = --disable-shared + $(1).CONFIGURE.static = --enable-static + $(1).CONFIGURE.extra = + + $(1).CONFIGURE.args.dir = cd $$(1); + $(1).CONFIGURE.args.host = --host=$$(1) + $(1).CONFIGURE.args.prefix = --prefix=$$(1) + + $(1).CONFIGURE.args = !sete @dir !bootstrap !env !exe @host @prefix !deps !shared !static !extra + + $(1).CONFIGURE.env.CC = CC=$$($(1).GCC.gcc) + $(1).CONFIGURE.env.CFLAGS = CFLAGS="$$(call fn.ARGS,$(1).GCC,*archs)" + $(1).CONFIGURE.env.CXX = CXX=$$($(1).GCC.gxx) + $(1).CONFIGURE.env.CXXFLAGS = CXXFLAGS="$$(call fn.ARGS,$(1).GCC,*archs)" + $(1).CONFIGURE.env.CPPFLAGS = CPPFLAGS="$$(call fn.ARGS,$(1).GCC,*archs)" + $(1).CONFIGURE.env.LDFLAGS = LDFLAGS="$$(call fn.ARGS,$(1).GCC,*archs)" + + $(1).CONFIGURE.env.args = !CC !CFLAGS !CXX !CXXFLAGS !CPPFLAGS !LDFLAGS + $(1).CONFIGURE.env = $$(call fn.ARGS,$(1).CONFIGURE.env,$$($(1).CONFIGURE.env.args)) + + $(1).CONFIGURE.target = $$($(1).build/).stamp.configure + define $(1).CONFIGURE + $$(call fn.ARGS,$(1).CONFIGURE,$$($(1).CONFIGURE.args)) + endef + + ## + ## target: build + ## + $(1).BUILD.make = $$(MAKE) + $(1).BUILD.dir = $$($(1).EXTRACT.target/) + $(1).BUILD.extra = + $(1).BUILD.ntargets = + + $(1).BUILD.args = !make @dir !extra !ntargets + $(1).BUILD.args.dir = -C $$(1) + + $(1).BUILD.target = $$($(1).build/).stamp.build + define $(1).BUILD + $$(call fn.ARGS,$(1).BUILD,$$($(1).BUILD.args)) + endef + + ## + ## target: install + ## + + $(1).INSTALL.make = $$(MAKE) + $(1).INSTALL.dir = $$($(1).EXTRACT.target/) + $(1).INSTALL.extra = + $(1).INSTALL.ntargets = + + $(1).INSTALL.args = !make @dir !extra !ntargets + $(1).INSTALL.args.dir = -C $$(1) install + + $(1).INSTALL.target = $$($(1).build/).stamp.install + define $(1).INSTALL + $$(call fn.ARGS,$(1).INSTALL,$$($(1).INSTALL.args)) + endef + + ## + ## target: uninstall + ## + $(1).UNINSTALL.make = $$(MAKE) + $(1).UNINSTALL.dir = $$($(1).EXTRACT.target/) + $(1).UNINSTALL.extra = + $(1).UNINSTALL.ntargets = uninstall + + $(1).UNINSTALL.args = !make @dir !extra !ntargets + $(1).UNINSTALL.args.dir = -C $$(1) + + define $(1).UNINSTALL + $$(call fn.ARGS,$(1).UNINSTALL,$$($(1).UNINSTALL.args)) + endef + + ## + ## target: clean + ## + $(1).CLEAN.make = $$(MAKE) + $(1).CLEAN.dir = $$($(1).EXTRACT.target/) + $(1).CLEAN.extra = + $(1).CLEAN.ntargets = clean + + $(1).CLEAN.args = !make @dir !extra !ntargets + $(1).CLEAN.args.dir = -C $$(1) + + define $(1).CLEAN + $$(call fn.ARGS,$(1).CLEAN,$$($(1).CLEAN.args)) + endef + + ## other values used to aid prerequisite dirs and cleanup + ## + $(1).out += $$($(1).build/) + $(1).out += $$($(1).FETCH.target) + $(1).out += $$($(1).PATCH.target) + $(1).out += $$($(1).CONFIGURE.target) + $(1).out += $$($(1).ALL.target) + $(1).out += $$($(1).INSTALL.target) + + BUILD.out += $$($(1).out) +endef + +############################################################################### + +## +## $(1) = module name +## +define import.CONTRIB.rules + +## +## target: fetch +## +$($(1).name).fetch: $$($(1).FETCH.target) + +$$($(1).FETCH.target): | $$(dir $$($(1).FETCH.target)) + $$($(1).FETCH) + +## +## target: extract +## must touch dir after extraction because old timestamp is restored via tar. +## +$($(1).name).extract: | $$($(1).EXTRACT.target/) + +$$($(1).EXTRACT.target/): | $$(dir $$($(1).build/)) +$$($(1).EXTRACT.target/): $$($(1).FETCH.target) + $$($(1).EXTRACT) + $$(TOUCH.exe) $$@ + +## +## target: patch +## +$($(1).name).patch: $$($(1).PATCH.target) + +$$($(1).PATCH.target): | $$(dir $$($(1).PATCH.target)) +$$($(1).PATCH.target): | $$($(1).EXTRACT.target/) + $$($(1).PATCH) + $$(TOUCH.exe) $$@ + +## +## target: configure +## +$($(1).name).configure: $$($(1).CONFIGURE.target) + +$$($(1).CONFIGURE.target): | $$(dir $$($(1).CONFIGURE.target)) +$$($(1).CONFIGURE.target): $$($(1).deps) +$$($(1).CONFIGURE.target): $$($(1).PATCH.target) + $$($(1).CONFIGURE) + $$(TOUCH.exe) $$@ + +## +## target: build +## +$($(1).name).build: $$($(1).BUILD.target) + +$$($(1).BUILD.target): | $$(dir $$($(1).BUILD.target)) +$$($(1).BUILD.target): $$($(1).CONFIGURE.target) + +$$($(1).BUILD) + $$(TOUCH.exe) $$@ + +## +## target: install +## +$($(1).name).install: $$($(1).INSTALL.target) + +$$($(1).INSTALL.target): | $$(dir $$($(1).INSTALL.target)) +$$($(1).INSTALL.target): $$($(1).BUILD.target) + $$($(1).INSTALL) + $$(TOUCH.exe) $$@ + +## +## target: uninstall +## +$($(1).name).uninstall: + -$$($(1).UNINSTALL) + $$(RM.exe) -f $$($(1).INSTALL.target) + +## +## target: clean +## +$($(1).name).clean: + -$$($(1).CLEAN) + $$(RM.exe) -f $$($(1).BUILD.target) + +## +## target: xclean +## +$($(1).name).xclean: $($(1).name).uninstall + $$(RM.exe) -fr $$($(1).build/) + +## +## alias: module name is same as build +## +$($(1).name): $($(1).name).build + +## +## participate with global convenience targets +## +contrib.fetch: $($(1).name).fetch +contrib.extract: $($(1).name).extract +contrib.patch: $($(1).name).patch +contrib.configure: $($(1).name).configure +contrib.build: $($(1).name).build +contrib.install: $($(1).name).install +contrib.uninstall: $($(1).name).uninstall +contrib.clean: $($(1).name).clean +contrib.xclean: $($(1).name).xclean + +endef diff --git a/make/include/function.defs b/make/include/function.defs new file mode 100644 index 000000000..5bf5aaa89 --- /dev/null +++ b/make/include/function.defs @@ -0,0 +1,19 @@ +fn.ERROR1 = ERROR: $(1) +fn.ERROR2 = ERROR: $(1): $(2) + +fn.HEADER = @echo "$(1): $(2)" +fn.DIVIDER = @echo "======================================================================" + +fn.ABSOLUTE = $(if $(filter /%,$(1)),$(1),$(subst /./,/,$(CURDIR)/$(1))) + +fn.ARGS = $(strip $(foreach a,$(2), \ + $($(1).$(patsubst !%,%,$(filter !%,$(a)))) \ + $(foreach x,$(patsubst ?%,%,$(filter ?%,$(a))),$(if $(filter 1,$($(1).$(x))),$($(1).args.$(x)))) \ + $(foreach x,$(patsubst .%,%,$(filter .%,$(a))),$($(1).args.$(x).$($(1).$(x)))) \ + $(foreach x,$(patsubst @%,%,$(filter @%,$(a))),$(if $($(1).$(x)),$(call $(1).args.$(x),$($(1).$(x))))) \ + $(foreach x,$(patsubst *%,%,$(filter *%,$(a))),$(foreach i,$($(1).$(x)),$(call $(1).args.$(x),$(i)))) \ + )) + +fn.VARS = $(foreach v,$($(1).vars),$(v)="$($(1).vars.$(v))") + +fn.TARGET = $(TARGET.$(2).prefix)$(1)$(TARGET.$(2).suffix)$(TARGET.$(2).ext) diff --git a/make/include/gcc.defs b/make/include/gcc.defs new file mode 100644 index 000000000..4ed746392 --- /dev/null +++ b/make/include/gcc.defs @@ -0,0 +1,146 @@ +GCC.gcc = gcc +GCC.gxx = $(dir $(GCC.gcc))$(subst gcc,g++,$(notdir $(GCC.gcc))) + +GCC.strip = $$(if $$(filter none,$$(GCC.g)),1) +GCC.dylib = 1 +GCC.pipe = 1 +GCC.ML = 1 +GCC.H = 0 +GCC.W = all +GCC.archs = +GCC.vis = 0 +GCC.pic = 0 +GCC.g = none +GCC.O = none +GCC.D = +GCC.I = +GCC.muldefs = 0 +GCC.start = 0 +GCC.a = +GCC.F = +GCC.f = +GCC.L = +GCC.l = +GCC.end = 0 + +GCC.args.pipe = -pipe +GCC.args.strip = -Wl,-S +GCC.args.dylib = -dynamiclib +GCC.args.ML = -fmessage-length=0 +GCC.args.H = -H +GCC.args.W = -W$(1) +GCC.args.archs = -arch $(1) +GCC.args.vis = -fvisibility=hidden +GCC.args.pic = -fPIC +GCC.args.g.none = -g0 +GCC.args.g.min = -gdwarf-2 -g1 +GCC.args.g.std = -gdwarf-2 +GCC.args.g.max = -gdwarf-2 -g3 +GCC.args.O.none = -O0 +GCC.args.O.size = -Os +GCC.args.O.speed = -O3 +GCC.args.D = -D$(1) +GCC.args.I = -I$(1) +GCC.args.muldefs = -Wl,--allow-multiple-definition +GCC.args.start = -Wl,--start-group +GCC.args.F = -F$(1) +GCC.args.f = -framework $(1) +GCC.args.L = -L$(1) +GCC.args.l = -l$(1) +GCC.args.end = -Wl,--end-group + +############################################################################### + +define import.GCC + $(1).GCC.gcc = $$(GCC.gcc) + $(1).GCC.gxx = $$(dir $$($(1).GCC.gcc))$$(subst gcc,g++,$$(notdir $$($(1).GCC.gcc))) + + $(1).GCC.pipe = $$(GCC.pipe) + $(1).GCC.strip = $$(if $$(filter none,$$($(1).GCC.g)),1) + $(1).GCC.dylib = $$(GCC.dylib) + $(1).GCC.ML = $$(GCC.ML) + $(1).GCC.H = $$(GCC.H) + $(1).GCC.W = $$(GCC.W) + $(1).GCC.archs = $$(GCC.archs) + $(1).GCC.vis = $$(GCC.vis) + $(1).GCC.pic = $$(GCC.pic) + $(1).GCC.g = $$(GCC.g) + $(1).GCC.O = $$(GCC.O) + $(1).GCC.D = $$(GCC.D) + $(1).GCC.I = $$(GCC.I) + $(1).GCC.muldefs = $$(GCC.muldefs) + $(1).GCC.start = $$(GCC.start) + $(1).GCC.a = $$(GCC.a) + $(1).GCC.F = $$(GCC.F) + $(1).GCC.f = $$(GCC.f) + $(1).GCC.L = $$(GCC.L) + $(1).GCC.l = $$(GCC.l) + $(1).GCC.end = $$(GCC.end) + + $(1).GCC.args.pipe = $$(GCC.args.pipe) + $(1).GCC.args.strip = $$(GCC.args.strip) + $(1).GCC.args.dylib = $$(GCC.args.dylib) + $(1).GCC.args.ML = $$(GCC.args.ML) + $(1).GCC.args.H = $$(GCC.args.H) + $(1).GCC.args.W = $$(GCC.args.W) + $(1).GCC.args.archs = $$(GCC.args.archs) + $(1).GCC.args.vis = $$(GCC.args.vis) + $(1).GCC.args.pic = $$(GCC.args.pic) + $(1).GCC.args.g.none = $$(GCC.args.g.none) + $(1).GCC.args.g.min = $$(GCC.args.g.min) + $(1).GCC.args.g.std = $$(GCC.args.g.std) + $(1).GCC.args.g.max = $$(GCC.args.g.max ) + $(1).GCC.args.O.none = $$(GCC.args.O.none) + $(1).GCC.args.O.size = $$(GCC.args.O.size) + $(1).GCC.args.O.speed = $$(GCC.args.O.speed) + $(1).GCC.args.D = $$(GCC.args.D) + $(1).GCC.args.I = $$(GCC.args.I) + $(1).GCC.args.muldefs = $$(GCC.args.muldefs) + $(1).GCC.args.start = $$(GCC.args.start) + $(1).GCC.args.F = $$(GCC.args.F) + $(1).GCC.args.f = $$(GCC.args.f) + $(1).GCC.args.L = $$(GCC.args.L) + $(1).GCC.args.l = $$(GCC.args.l) + $(1).GCC.args.end = $$(GCC.args.end) + + ########################################################################### + + $(1).GCC.c = -c $$(4) + $(1).GCC.o = -o $$(3) + + # FUNCTION: C precompiled headers + $(1).GCC.H_O.args = !gcc ?pipe ?ML ?H *W *archs ?vis ?pic .g .O *D *I !c !o + $(1).GCC.H_O = $$(call fn.ARGS,$(1).GCC,$$($(1).GCC.H_O.args),$$(1),$$(2)) + + # FUNCTION: C compile source + $(1).GCC.C_O.args = !gcc ?pipe ?ML ?H *W *archs ?vis ?pic .g .O *D *I !c !o + $(1).GCC.C_O = $$(call fn.ARGS,$(1).GCC,$$($(1).GCC.C_O.args),$$(1),$$(2)) + + # FUNCTION: C++ precompile headers + $(1).GCC.HPP_O.args = !gxx ?pipe ?ML ?H *W *archs ?vis ?pic .g .O *D *I !c !o + $(1).GCC.HPP_O = $$(call fn.ARGS,$(1).GCC,$$($(1).GCC.HPP_O.args),$$(1),$$(2)) + + # FUNCTION: C++ compile source + $(1).GCC.CPP_O.args = !gxx ?pipe ?ML ?H *W *archs ?vis ?pic .g .O *D *I !c !o + $(1).GCC.CPP_O = $$(call fn.ARGS,$(1).GCC,$$($(1).GCC.CPP_O.args),$$(1),$$(2)) + + ########################################################################### + + $(1).GCC.i = $$(4) + + # FUNCTION: C link dynamic-lib + $(1).GCC.DYLIB.args = !gcc ?pipe ?strip ?dylib ?ML *W *archs ?vis ?pic .g .O *D *I !o ?muldefs ?start !i *F *f *L *l *i !a ?end + $(1).GCC.DYLIB = $$(call fn.ARGS,$(1).GCC,$$($(1).GCC.DYLIB.args),$$(1),$$(2)) + + # FUNCTION: C link executable + $(1).GCC.EXE.args = !gcc ?pipe ?strip ?ML *W *archs ?vis ?pic .g .O *D *I !o ?muldefs ?start !i *F *f *L *l *i !a ?end + $(1).GCC.EXE = $$(call fn.ARGS,$(1).GCC,$$($(1).GCC.EXE.args),$$(1),$$(2)) + + # FUNCTION: C++ link dynamic-lib + $(1).GCC.DYLIB++.args = !gxx ?pipe ?strip ?dylib ?ML *W *archs ?vis ?pic .g .O *D *I !o ?muldefs ?start !i *F *f *L *l *i !a ?end + $(1).GCC.DYLIB++ = $$(call fn.ARGS,$(1).GCC,$$($(1).GCC.DYLIB++.args),$$(1),$$(2)) + + # FUNCTION: C++ link executable + $(1).GCC.EXE++.args = !gxx ?pipe ?strip ?ML *W *archs ?vis ?pic .g .O *D *I !o ?muldefs ?start !i *F *f *L *l *i !a ?end + $(1).GCC.EXE++ = $$(call fn.ARGS,$(1).GCC,$$($(1).GCC.EXE++.args),$$(1),$$(2)) +endef diff --git a/make/include/main.defs b/make/include/main.defs new file mode 100644 index 000000000..c40e2b62a --- /dev/null +++ b/make/include/main.defs @@ -0,0 +1,75 @@ +.DELETE_ON_ERROR: +.SUFFIXES: + +.PHONY: build +build: + +############################################################################### + +include $(PROJECT/)make/include/base.defs +include $(PROJECT/)make/include/contrib.defs +include $(PROJECT/)make/include/function.defs +include $(PROJECT/)make/include/gcc.defs +include $(PROJECT/)make/include/select.defs +include $(PROJECT/)make/include/target.defs +include $(PROJECT/)make/include/tool.defs + +############################################################################### + +MODULES += contrib/a52dec + +ifneq (,$(filter $(BUILD.system),cygwin)) + MODULES += contrib/bzip2 +endif + +MODULES += contrib/faac +MODULES += contrib/faad2 +MODULES += contrib/ffmpeg +MODULES += contrib/lame +MODULES += contrib/libdca +MODULES += contrib/libdvdread +MODULES += contrib/libmkv +MODULES += contrib/libmp4v2 +MODULES += contrib/libogg +MODULES += contrib/libsamplerate +MODULES += contrib/libtheora +MODULES += contrib/libvorbis +MODULES += contrib/mpeg2dec +MODULES += contrib/x264 +MODULES += contrib/xvidcore + +ifneq (,$(filter $(BUILD.system),cygwin)) + MODULES += contrib/zlib +endif + +## these must come after contrib since some contrib modules are optional +MODULES += libhb + +############################################################################### + +## test module is replaced with macosx when Darwin+Xcode +ifneq (,$(filter $(BUILD.system),darwin)) + ifeq (1,$(FEATURE.xcode)) + MODULES += macosx + else + MODULES += test + endif +else + MODULES += test +endif + +ifneq (,$(filter $(BUILD.system),linux)) + ifeq (1,$(FEATURE.gtk)) + MODULES += gtk + endif +endif + +############################################################################### + +MODULES += doc + +############################################################################### + +include $(MODULES:%=$(PROJECT/)%/module.defs) +include $(PROJECT/)make/variant/$(HOST.system).defs +-include $(PROJECT/)make/variant/$(HOST.system).$(BUILD.proc).defs diff --git a/make/include/main.rules b/make/include/main.rules new file mode 100644 index 000000000..f46d22398 --- /dev/null +++ b/make/include/main.rules @@ -0,0 +1,39 @@ +## only included using special report targets +ifneq (,$(REPORT)) + include $(PROJECT/)make/include/report.defs +endif + +############################################################################### + +.PHONY: clean xclean doc report + +clean: +xclean: contrib.xclean clean +doc: +report:: report.main report.modules + +## legacy +mrproper: xclean + +############################################################################### + +include $(MODULES:%=$(PROJECT/)%/module.rules) +include $(PROJECT/)make/variant/$(HOST.system).rules +-include $(PROJECT/)make/variant/$(HOST.system).$(BUILD.proc).rules + +############################################################################### + +## target which causes re-configure if project-root is svn update'd +$(BUILD/)GNUmakefile: $(wildcard $(PROJECT/).svn/entries) + $(PROJECT/)configure $(CONF.args) + +## target useful to force reconfigure; only helpful for build-system development +.PHONY: reconfigure +reconfigure: + $(PROJECT/)configure $(CONF.args) + +############################################################################### + +## target to build all dependency dirs +$(sort $(dir $(BUILD.out))): + $(MKDIR.exe) -p $@ diff --git a/make/include/report.defs b/make/include/report.defs new file mode 100644 index 000000000..6ff71dc99 --- /dev/null +++ b/make/include/report.defs @@ -0,0 +1,53 @@ +## function: print a var's name, definition and expanded value +## +## $(1) = name of variable +## +define fn.PRINTVAR + +$(1) + ORIGIN = $(origin $(1)) + FLAVOR = $(flavor $(1)) + DEFINITION = $(value $(1)) + EXPANDED = $($(1)) +endef + +## report: module +## +## REPORT.module = module name (uppercase) +## +ifeq (module,$(REPORT)) +$(info ###############################################################################) +$(info ##) +$(info ## MODULE: $(REPORT.module)) +$(info ##) +$(info ###############################################################################) +$(info $(foreach v,$(sort $(filter $(REPORT.module).%,$(.VARIABLES))),$(call fn.PRINTVAR,$v))) +$(info ) +endif + +## report: main +## +ifeq (main,$(REPORT)) +$(info ###############################################################################) +$(info ##) +$(info ## MAIN) +$(info ##) +$(info ###############################################################################) +$(info $(foreach v,$(sort $(filter HB.%,$(.VARIABLES))),$(call fn.PRINTVAR,$v))) +$(info $(foreach v,$(sort $(filter HOST.%,$(.VARIABLES))),$(call fn.PRINTVAR,$v))) +$(info $(foreach v,$(sort $(filter BUILD.%,$(.VARIABLES))),$(call fn.PRINTVAR,$v))) +$(info $(foreach v,$(sort $(filter CONTRIB.%,$(.VARIABLES))),$(call fn.PRINTVAR,$v))) +$(info ) +endif + +## report: gcc +## +ifeq (gcc,$(REPORT)) +$(info ###############################################################################) +$(info ##) +$(info ## GCC) +$(info ##) +$(info ###############################################################################) +$(info $(foreach v,$(sort $(filter GCC.%,$(.VARIABLES))),$(call fn.PRINTVAR,$v))) +$(info ) +endif diff --git a/make/include/select.defs b/make/include/select.defs new file mode 100644 index 000000000..32a652523 --- /dev/null +++ b/make/include/select.defs @@ -0,0 +1,12 @@ +## +## fetch a file from the web via well-known anonymous protocols such as HTTP. +## +## $(1) = output filename +## $(2) = URL +## +FETCH = $(FETCH.$(FETCH.select)) + +FETCH.select = MISSING +FETCH.MISSING = $(error one of the following tools is required: wget, curl) +FETCH.curl = $(CURL.exe) -q -L -o $(1) $(2) +FETCH.wget = $(WGET.exe) -O $(1) $(2) diff --git a/make/include/target.defs b/make/include/target.defs new file mode 100644 index 000000000..64bdde434 --- /dev/null +++ b/make/include/target.defs @@ -0,0 +1,14 @@ +TARGET.dylib.prefix = lib +TARGET.dylib.suffix = +TARGET.dylib.ext = .dylib +TARGET.dylib = $(TARGET.dylib.prefix)$(1)$(TARGET.dylib.suffix)$(TARGET.dylib.ext) + +TARGET.archive.prefix = lib +TARGET.archive.suffix = +TARGET.archive.ext = .a +TARGET.archive = $(TARGET.archive.prefix)$(1)$(TARGET.archive.suffix)$(TARGET.archive.ext) + +TARGET.exe.prefix = +TARGET.exe.suffix = +TARGET.exe.ext = +TARGET.exe = $(TARGET.exe.prefix)$(1)$(TARGET.exe.suffix)$(TARGET.exe.ext) diff --git a/make/include/tool.defs b/make/include/tool.defs new file mode 100644 index 000000000..0ccccd728 --- /dev/null +++ b/make/include/tool.defs @@ -0,0 +1,10 @@ +AR.exe = ar +CP.exe = cp +CURL.exe = curl +M4.exe = m4 +MKDIR.exe = mkdir +PATCH.exe = patch +RM.exe = rm +TAR.exe = tar +TOUCH.exe = touch +WGET.exe = wget diff --git a/make/variant/cygwin.defs b/make/variant/cygwin.defs new file mode 100644 index 000000000..bab73c6ca --- /dev/null +++ b/make/variant/cygwin.defs @@ -0,0 +1,8 @@ +GCC.muldefs = 1 +GCC.start = 1 +GCC.end = 1 + +GCC.args.g.none = -g0 +GCC.args.g.min = -g1 +GCC.args.g.default = -g2 +GCC.args.g.max = -g3 diff --git a/make/variant/darwin.defs b/make/variant/darwin.defs new file mode 100644 index 000000000..6f8f6729d --- /dev/null +++ b/make/variant/darwin.defs @@ -0,0 +1,61 @@ +## UB build support +## +## PROCEDURE: +## +## 1. Perform a build (let us call it arch-X). +## 2. cd into arch-X's build/ driectory. +## 3. Launch builds of the remaining architectures. +## We compute $(UB.archs.other) to be the remaining archs to build. +## The entire list is defined $(UB.archs) . +## 4. Combine other architectures into arch-X's binaries. +## +## EXAMPLE: serial method, archs: i386,x86_64,ppc,ppc64 +## +## ./configure --launch +## cd build/ +## make ub.build.serial +## make ub.combine +## +## EXAMPLE: parallel method, archs: i386,x86_64,ppc,ppc64 +## +## ./configure --launch +## cd build/ +## make ub.build.parallel +## make ub.combine +## +## EXAMPLE: serial, archs: i386,x86_64 (assuming i386 is native) +## +## ./configure --launch +## cd build/ +## make ub.build.parallel UB.archs="i386 x86_64" +## make ub.combine UB.archs="i386 x86_64" +## +UB.archs = i386 x86_64 ppc ppc64 +UB.archs.other = $(filter-out $(BUILD.arch),$(UB.archs)) +UB.builds = $(wildcard $(foreach n,$(UB.archs.other),$(PROJECT/)build.$n)) + +UB.BUILD = $(PROJECT/)configure --launch --launch-dir=ub.$(1) --arch=$(1) + +## linefeed is important +define UB.BUILD.item + $(call UB.BUILD,$(1)) + +endef + +define UB.BUILD.SERIAL + $(foreach n,$(UB.archs.other),$(call UB.BUILD.item,$n)) +endef + +define UB.BUILD.PARALLEL + $(call UB.BUILD,$(1)) 2>&1 > ub.$(1).log +endef + +define UB.COMBINE + $(RM.exe) -fr ub.combine + $(MKDIR.exe) -p ub.combine + $(CP.exe) -R HandBrake.app ub.combine/. + lipo $(1) $(foreach n,$(UB.archs.other),ub.$n/$(1)) -create -output ub.combine/$(1) + @echo "" + @sync; lipo -info ub.combine/$(1) + @du -sh ub.combine/$(1) +endef diff --git a/make/variant/darwin.rules b/make/variant/darwin.rules new file mode 100644 index 000000000..c4f4f97a4 --- /dev/null +++ b/make/variant/darwin.rules @@ -0,0 +1,20 @@ +.PHONY: ub.build ub.combine ub.clean + +ub.build.serial: + @$(UB.BUILD.SERIAL) + +ub.build.parallel: + @set -e; \ + for arch in $(UB.archs.other); do \ + $(call UB.BUILD.PARALLEL,$$arch) & \ + children="$$children $$!"; \ + echo "pid $$!: $(call UB.BUILD.PARALLEL,$$arch)"; \ + done; \ + echo "waiting for background jobs to complete:$$children"; \ + wait + +ub.combine: + $(call UB.COMBINE,HandBrake.app/Contents/MacOS/HandBrake) + +ub.clean: + $(RM.EXE) -fr $(foreach n,$(UB.archs.other),ub.$n) diff --git a/make/variant/darwin.x86_64.defs b/make/variant/darwin.x86_64.defs new file mode 100644 index 000000000..c6e856476 --- /dev/null +++ b/make/variant/darwin.x86_64.defs @@ -0,0 +1,3 @@ +## can enable asm if we replace .rept pseudo op with standard pre-processor macros +## since darwin's as doesn't support them. for now just disable. +LIBTHEORA.CONFIGURE.extra += --disable-asm diff --git a/make/variant/freebsd.defs b/make/variant/freebsd.defs new file mode 100644 index 000000000..c58706ba1 --- /dev/null +++ b/make/variant/freebsd.defs @@ -0,0 +1,4 @@ +TARGET.dylib.ext = .so + +GCC.args.dylib = -shared +GCC.args.pic = 1 diff --git a/make/variant/linux.defs b/make/variant/linux.defs new file mode 100644 index 000000000..f0babe87c --- /dev/null +++ b/make/variant/linux.defs @@ -0,0 +1,11 @@ +TARGET.dylib.ext = .so + +GCC.start = 1 +GCC.end = 1 +GCC.args.dylib = -shared +GCC.args.pic = 1 + +GCC.args.g.none = -g0 +GCC.args.g.min = -g1 +GCC.args.g.default = -g2 +GCC.args.g.max = -g3 |