summaryrefslogtreecommitdiffstats
path: root/make
diff options
context:
space:
mode:
authorkonablend <[email protected]>2009-03-08 22:50:57 +0000
committerkonablend <[email protected]>2009-03-08 22:50:57 +0000
commit083ba4898a662cd50a86d2a65ca5ebe765fe882d (patch)
treec2460805275e7b23dd03965df15beecc7ac4589b /make
parent92d511d944b059caaf6c5e85fcb5202642aa4553 (diff)
BuildSystem: general, configure and Xcode updates.
*** NOTICE: This changeset requires a clean build directory. Please issue 'make xclean' inside build dir(s) after 'svn up'. This will help ensure there are no unexpected results. *** GENERAL: - renamed makevar PROJECT/ -> SRC/ for clarity. - renamed makevar PREFIX.install/ -> PREFIX/ for clarity. - split custom GNUmakefile overrides into defs/rules files. - inserted optional level of make customization at SRC/ level; see docs. - dropped HB.repo.wcversion (svnversion is no longer used). - corrected several 'rm' usages to use -f flag which avoids some build errors. - refreshed generated 00-Building.*.txt docs; work still in progress on the wiki front. *** CONFIGURE: - made configure more robust; configure may now be run outside of build directory! - adding log recording of configure activities. - improved readability of default options for configure - added: --force overwrite existing build config --src=DIR specify top-level source dir [.] --build=DIR specify build scratch/output dir [.] --prefix=DIR specify install dir for products [/Applications] - dropped --launch-force (replaced by --force) - dropped --launch-dir (replaced by --build) - dropped --launch-log *** XCODE: - renamed pbxproj definition EXTERNAL_PROJECT -> EXTERNAL_SRC for clarity. - fixed all configurations to default to EXTERNAL_JOBS=1 . - enabled Xcode internal parallelization (libhb, HandBrakeCLI and HandBrake benefit). - make now tickles Xcode build files to cause Info.plist regeneration and posting to HandBrake.app output; ie: svn up; click build and HandBrake.app's about panel will reflect the new repository rev. *** DARWIN: - added support to build universal binaries; see docs. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@2242 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'make')
-rw-r--r--make/configure.py1670
-rw-r--r--make/include/contrib.defs14
-rw-r--r--make/include/main.defs20
-rw-r--r--make/include/main.rules18
-rw-r--r--make/variant/darwin.defs55
-rw-r--r--make/variant/darwin.rules2
-rw-r--r--make/variant/freebsd.defs5
-rwxr-xr-xmake/xcodemake4
8 files changed, 1102 insertions, 686 deletions
diff --git a/make/configure.py b/make/configure.py
index ce2884093..c984ccc3b 100644
--- a/make/configure.py
+++ b/make/configure.py
@@ -1,3 +1,12 @@
+###############################################################################
+##
+## This script is coded for minimum version of Python 2.4 .
+## Pyhthon3 is incompatible.
+##
+## Authors: konablend
+##
+###############################################################################
+
import fnmatch
import optparse
import os
@@ -13,408 +22,514 @@ from optparse import OptionParser
from sys import stderr
from sys import stdout
+class AbortError( Exception ):
+ def __init__( self, format, *args ):
+ self.value = format % args
+ def __str__( self ):
+ return self.value
+
###############################################################################
+##
+## Main configure object.
+##
+## dir = containing this configure script
+## cwd = current working dir at time of script launch
+##
+class Configure( object ):
+ OUT_QUIET = 0
+ OUT_INFO = 1
+ OUT_VERBOSE = 2
+
+ def __init__( self, verbose ):
+ self._log_info = []
+ self._log_verbose = []
+ self._record = False
+
+ self.verbose = verbose
+ self.dir = os.path.dirname( sys.argv[0] )
+ self.cwd = os.getcwd()
+
+ self.build_dir = '.'
+
+ ## compute src dir which is 2 dirs up from this script
+ self.src_dir = os.path.normpath( sys.argv[0] )
+ for i in range( 2 ):
+ self.src_dir = os.path.dirname( self.src_dir )
+ if len( self.src_dir ) == 0:
+ self.src_dir = os.curdir
+
+ def _final_dir( self, chdir, dir ):
+ dir = os.path.normpath( dir )
+ if not os.path.isabs( dir ):
+ if os.path.isabs( chdir ):
+ dir = os.path.normpath( os.path.abspath(dir ))
+ else:
+ dir = os.path.normpath( self.relpath( dir, chdir ))
+ return dir
+
+ ## output functions
+ def errln( self, format, *args ):
+ s = (format % args)
+ if re.match( '^.*[!?:;.]$', s ):
+ stderr.write( 'ERROR: %s configure stop.\n' % (s) )
+ else:
+ stderr.write( 'ERROR: %s; configure stop.\n' % (s) )
+ self.record_log()
+ sys.exit( 1 )
+ def infof( self, format, *args ):
+ line = format % args
+ self._log_verbose.append( line )
+ if cfg.verbose >= Configure.OUT_INFO:
+ self._log_info.append( line )
+ stdout.write( line )
+ def verbosef( self, format, *args ):
+ line = format % args
+ self._log_verbose.append( line )
+ if cfg.verbose >= Configure.OUT_VERBOSE:
+ stdout.write( line )
+
+ ## doc is ready to be populated
+ def doc_ready( self ):
+ ## compute final paths as they are after chdir into build
+ self.build_final = os.curdir
+ self.src_final = self._final_dir( self.build_dir, self.src_dir )
+ self.prefix_final = self._final_dir( self.build_dir, self.prefix_dir )
+
+ cfg.infof( 'compute: makevar SRC/ = %s\n', self.src_final )
+ cfg.infof( 'compute: makevar BUILD/ = %s\n', self.build_final )
+ cfg.infof( 'compute: makevar PREFIX/ = %s\n', self.prefix_final )
+
+ ## xcode does a chdir so we need appropriate values
+ macosx = os.path.join( self.src_dir, 'macosx' )
+ self.xcode_x_src = self._final_dir( macosx, self.src_dir )
+ self.xcode_x_build = self._final_dir( macosx, self.build_dir )
+ self.xcode_x_prefix = self._final_dir( macosx, self.prefix_dir )
+
+ ## perform chdir and enable log recording
+ def chdir( self ):
+ if os.path.abspath( self.build_dir ) == os.path.abspath( self.src_dir ):
+ cfg.errln( 'build (scratch) directory must not be the same as top-level source root!' )
+
+ if self.build_dir != os.curdir:
+ if os.path.exists( self.build_dir ):
+ if not options.force:
+ self.errln( 'build directory already exists: %s (use --force to overwrite)', self.build_dir )
+ else:
+ self.mkdirs( self.build_dir )
+ self.infof( 'chdir: %s\n', self.build_dir )
+ os.chdir( self.build_dir )
+
+ ## enable logging
+ self._record = True
+
+ def mkdirs( self, dir ):
+ if len(dir) and not os.path.exists( dir ):
+ self.infof( 'mkdir: %s\n', dir )
+ os.makedirs( dir )
+
+ def open( self, *args ):
+ dir = os.path.dirname( args[0] )
+ if len(args) > 1 and args[1].find('w') != -1:
+ self.mkdirs( dir )
+ m = re.match( '^(.*)\.tmp$', args[0] )
+ if m:
+ self.infof( 'write: %s\n', m.group(1) )
+ else:
+ self.infof( 'write: %s\n', args[0] )
-def errf( format, *args ):
- stderr.write( ('ERROR: ' + format + '\n') % args )
- sys.exit( 1 )
+ try:
+ return open( *args )
+ except Exception, x:
+ cfg.errln( 'open failure: %s', x )
-def outf( format, *args ):
- stdout.write( (format + '\n') % args )
+ def record_log( self ):
+ if not self._record:
+ return
+ self._record = False
+ self.verbose = Configure.OUT_QUIET
+ file = cfg.open( 'log/config.info.txt', 'w' )
+ for line in self._log_info:
+ file.write( line )
+ file.close()
+ file = cfg.open( 'log/config.verbose.txt', 'w' )
+ for line in self._log_verbose:
+ file.write( line )
+ file.close()
+
+ ## Find executable by searching path.
+ ## On success, returns full pathname of executable.
+ ## On fail, returns None.
+ def findExecutable( self, name ):
+ if len( os.path.split(name)[0] ):
+ if os.access( name, os.X_OK ):
+ return name
+ return 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
+
+ ## taken from python2.6 -- we need it
+ def relpath( self, path, start=os.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.curdir
+ return os.path.join(*rel_list)
+
+ ## update with parsed cli options
+ def update_cli( self, options ):
+ self.src_dir = os.path.normpath( options.src )
+ self.build_dir = os.path.normpath( options.build )
+ self.prefix_dir = os.path.normpath( options.prefix )
+
+ ## special case if src == build: add build subdir
+ if os.path.abspath( self.src_dir ) == os.path.abspath( self.build_dir ):
+ self.build_dir = os.path.join( self.build_dir, 'build' )
###############################################################################
-
-## Expand values of iterable object into a decent string representation.
##
-def expandValues( obj ):
- buf = ''
- for v in obj:
- buf += ', ' + v
- return '{ ' + buf[2:] + ' }'
+## abstract action
+##
+## pretext = text which immediately follows 'probe:' output prefix
+## abort = if true configure will exit on probe fail
+## head = if true probe session is stripped of all but first line
+## session = output from command, including stderr
+## fail = true if probe failed
+##
+class Action( object ):
+ actions = []
+
+ def __init__( self, category, pretext='unknown', abort=False, head=False ):
+ if self not in Action.actions:
+ Action.actions.append( self )
+
+ self.category = category
+ self.pretext = pretext
+ self.abort = abort
+ self.head = head
+ self.session = None
+
+ self.run_done = False
+ self.fail = True
+ self.msg_fail = 'fail'
+ self.msg_pass = 'pass'
+ self.msg_end = 'end'
+
+ def _actionBegin( self ):
+ cfg.infof( '%s: %s...', self.category, self.pretext )
+
+ def _actionEnd( self ):
+ if self.fail:
+ cfg.infof( '(%s) %s\n', self.msg_fail, self.msg_end )
+ if self.abort:
+ self._dumpSession( cfg.infof )
+ cfg.errln( 'unable to continue' )
+ self._dumpSession( cfg.verbosef )
+ else:
+ cfg.infof( '(%s) %s\n', self.msg_pass, self.msg_end )
+ self._dumpSession( cfg.verbosef )
-###############################################################################
+ def _dumpSession( self, printf ):
+ if self.session and len(self.session):
+ for line in self.session:
+ printf( ' : %s\n', line )
+ else:
+ printf( ' : <NO-OUTPUT>\n' )
+
+ def _parseSession( self ):
+ pass
+
+ def run( self ):
+ if self.run_done:
+ return
+ self.run_done = True
+ self._actionBegin()
+ self._action()
+ if not self.fail:
+ self._parseSession()
+ self._actionEnd()
-## Find executable by searching path.
-## On success, returns full pathname of executable.
-## On fail, returns None.
+###############################################################################
+##
+## base probe: anything which runs in shell.
+##
+## pretext = text which immediately follows 'probe:' output prefix
+## command = full command and arguments to pipe
+## abort = if true configure will exit on probe fail
+## head = if true probe session is stripped of all but first line
+## session = output from command, including stderr
+## fail = true if probe failed
##
-def findExecutable( name ):
- if len( os.path.split(name)[0] ):
- return name if os.access( name, os.X_OK ) else None
+class ShellProbe( Action ):
+ def __init__( self, pretext, command, abort=False, head=False ):
+ super( ShellProbe, self ).__init__( 'probe', pretext, abort, head )
+ self.command = command
- if not os.environ.has_key( 'PATH' ) or os.environ[ 'PATH' ] == '':
- path = os.defpath
- else:
- path = os.environ['PATH']
+ def _action( self ):
+ ## pipe and redirect stderr to stdout; effects communicate result
+ pipe = subprocess.Popen( self.command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
- for dir in path.split( os.pathsep ):
- f = os.path.join( dir, name )
- if os.access( f, os.X_OK ):
- return f
- return None
+ ## read data into memory buffers, only first element (stdout) data is used
+ data = pipe.communicate()
+ self.fail = pipe.returncode != 0
-###############################################################################
+ if data[0]:
+ self.session = data[0].splitlines()
+ else:
+ self.session = []
-def computeNumCPU():
- ## 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
+ if pipe.returncode:
+ self.msg_end = 'code %d' % (pipe.returncode)
+
+ def _dumpSession( self, printf ):
+ printf( ' + %s\n', self.command )
+ super( ShellProbe, self )._dumpSession( printf )
###############################################################################
+##
+## GNU host tuple probe: determine canonical platform type
+##
+## example results from various platforms:
+##
+## 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 HostTupleProbe( ShellProbe, list ):
+ GNU_TUPLE_RX = '([^-]+)-([^-]+)-([^0-9-]+)([^-]*)-?([^-]*)'
+
+ def __init__( self ):
+ super( HostTupleProbe, self ).__init__( 'host tuple', '%s/config.guess' % (cfg.dir), abort=True, head=True )
-## taken from python2.6 -- we need it
-def relpath(path, start=os.path.curdir):
- """Return a relative version of a path"""
+ def _parseSession( self ):
+ if len(self.session):
+ self.spec = self.session[0]
+ else:
+ self.spec = ''
- if not path:
- raise ValueError("no path specified")
+ ## grok GNU host tuples
+ m = re.match( HostTupleProbe.GNU_TUPLE_RX, self.spec )
+ if not m:
+ self.fail = True
+ self.msg_end = 'invalid host tuple: %s' % (self.spec)
+ return
- start_list = os.path.abspath(start).split(os.sep)
- path_list = os.path.abspath(path).split(os.sep)
+ self.msg_end = self.spec
- # Work out how much of the filepath is shared by start and path.
- i = len(os.path.commonprefix([start_list, path_list]))
+ ## assign tuple from regex
+ self[:] = m.groups()
- 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)
+ ## for clarity
+ self.machine = self[0]
+ self.vendor = self[1]
+ self.system = self[2]
+ self.release = self[3]
+ self.extra = self[4]
-###############################################################################
+ ## nice formal name for 'system'
+ self.systemf = platform.system()
-# 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
-initial_project_dir = project_dir
+ if self.match( '*-*-cygwin*' ):
+ self.systemf = self[2][0].upper() + self[2][1:]
+
+ ## glob-match against spec
+ def match( self, spec ):
+ return fnmatch.fnmatch( self.spec, spec )
###############################################################################
-## model gnu-autotools platform guess
+class BuildAction( Action, list ):
+ def __init__( self ):
+ super( BuildAction, self ).__init__( 'compute', 'build tuple', abort=True )
+
+ def _action( self ):
+ self.spec = arch.mode[arch.mode.mode]
+
+ ## grok GNU host tuples
+ m = re.match( HostTupleProbe.GNU_TUPLE_RX, self.spec )
+ if not m:
+ self.msg_end = 'invalid host tuple: %s' % (self.spec)
+ return
+
+ self.msg_end = self.spec
+
+ ## assign tuple from regex
+ self[:] = m.groups()
+
+ ## for clarity
+ self.machine = self[0]
+ self.vendor = self[1]
+ self.system = self[2]
+ self.release = self[3]
+ self.extra = self[4]
+ self.systemf = host.systemf
+
+ self.fail = False
+
+###############################################################################
##
-## native format:
-## (PROC)-(VENDOR)-(SYSTEM)(RELEASE)-(EXTRA)
+## platform conditional string; if specs do not match host:
##
-## 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)
+## - str value is blank
+## - evaluates to False
##
-class Guess:
- def __init__( self ):
- self.machine = 'unknown'
- self.vendor = 'unknown'
- self.system = 'unknown'
- self.systemc = 'Unknown'
- self.release = '0.0.0'
- self.extra = ''
-
- p_system = platform.system().lower()
- p_systemc = platform.system()
- p_release = platform.release().lower()
- p_processor = platform.processor().lower()
- p_machine = platform.machine().lower()
-
- if re.match( 'cygwin', p_system ):
- self.machine = p_machine
- self.vendor = 'pc'
- self.system = 'cygwin'
- self.systemc = 'Cygwin'
- self.release = ''
- self.extra = ''
- elif re.match( 'darwin', p_system ):
- self.machine = p_processor
- self.vendor = 'apple'
- self.system = p_system
- self.systemc = p_systemc
- self.release = p_release
- self.extra = ''
- elif re.match( 'linux', p_system ):
- self.machine = p_machine
- self.vendor = 'unknown'
- self.system = p_system
- self.systemc = p_systemc
- self.release = ''
- self.extra = 'gnu'
- self.title = 'Linux %s' % (p_machine)
- else:
- errf( 'unrecognized host system: %s', p_system )
-
+class IfHost( object ):
+ def __init__( self, value, *specs ):
+ self.value = ''
+ for spec in specs:
+ if host.match( spec ):
+ self.value = value
+ break
+
+ def __nonzero__( self ):
+ return len(self.value) != 0
+
def __str__( self ):
- if len(self.extra):
- return '%s-%s-%s%s-%s' % (self.machine,self.vendor,self.system,self.release,self.extra)
- else:
- return '%s-%s-%s%s' % (self.machine,self.vendor,self.system,self.release)
+ return self.value
- def match( self, spec ):
- return fnmatch.fnmatch( str(self), spec )
+###############################################################################
+##
+## platform conditional value; loops through list of tuples comparing
+## to first host match and sets value accordingly; the first value is
+## always default.
+##
+class ForHost( object ):
+ def __init__( self, default, *tuples ):
+ self.value = default
+ for tuple in tuples:
+ if host.match( tuple[1] ):
+ self.value = tuple[0]
+ break
+
+ def __str__( self ):
+ return self.value
###############################################################################
-# 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 )
+class ArchAction( Action ):
+ def __init__( self ):
+ super( ArchAction, self ).__init__( 'compute', 'available architectures', abort=True )
+ self.mode = SelectMode( 'architecture', (host.machine,host.spec) )
+
+ def _action( self ):
+ self.fail = False
+
+ ## some match on system should be made here; otherwise we signal a warning.
+ if host.match( '*-*-cygwin*' ):
+ pass
+ elif host.match( '*-*-darwin*' ):
+ self.mode['i386'] = 'i386-apple-darwin%s' % (host.release)
+ self.mode['x86_64'] = 'x86_64-apple-darwin%s' % (host.release)
+ self.mode['ppc'] = 'powerpc-apple-darwin%s' % (host.release)
+ self.mode['ppc64'] = 'powerpc64-apple-darwin%s' % (host.release)
+ elif host.match( '*-*-linux*' ):
+ pass
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 ))
+ self.msg_pass = 'WARNING'
+
+ self.msg_end = self.mode.toString()
+
+ ## glob-match against spec
+ def match( self, spec ):
+ return fnmatch.fnmatch( self.spec, spec )
###############################################################################
-class ToolSet:
+class CoreProbe( Action ):
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 )
+ super( CoreProbe, self ).__init__( 'probe', 'number of CPU cores' )
+ self.count = 1
-###############################################################################
+ def _action( self ):
+ if self.fail:
+ ## good for darwin9.6.0 and linux
+ try:
+ self.count = os.sysconf( 'SC_NPROCESSORS_ONLN' )
+ if self.count < 1:
+ self.count = 1
+ self.fail = False
+ except:
+ pass
+
+ if self.fail:
+ ## windows
+ try:
+ self.count = int( os.environ['NUMBER_OF_PROCESSORS'] )
+ if self.count < 1:
+ self.count = 1
+ self.fail = False
+ except:
+ pass
-class OptionMode( list ):
- def __init__( self, default, *items ):
- super( OptionMode, self ).__init__( items )
- self.default = items[default]
- self.mode = self.default
+ ## clamp
+ if self.count < 1:
+ self.count = 1
+ elif self.count > 32:
+ self.count = 32
- def __str__( self ):
- s = ''
- for a in self:
- if a == self.mode:
- s += ' *' + a
+ if options.launch:
+ if options.launch_jobs == 0:
+ self.jobs = core.count
else:
- s += ' ' + a
- return s[1:]
-
- def addToGroup( self, group, option, name ):
- group.add_option( '', option, help='select %s mode: %s' % (name,self), default=self.mode, metavar='MODE' )
+ self.jobs = options.launch_jobs
+ else:
+ self.jobs = core.count
- def setFromOption( self, name, mode ):
- if mode not in self:
- errf( 'invalid %s mode: %s', name, mode )
- self.mode = mode
+ self.msg_end = str(self.count)
###############################################################################
-## 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.machine )
-
-if guessHost.match( '*-*-darwin*' ):
- d_xcode = True
- d_prefix = '/Applications'
-else:
- d_xcode = False
- d_prefix = '/usr/local'
-
-## create parser
-parser = OptionParser( 'Usage: %prog' )
-
-## add hidden options
-parser.add_option( '', '--conf-method', default='terminal', action='store', help=optparse.SUPPRESS_HELP )
-
-## add install options
-group = OptionGroup( parser, 'Installation Options' )
-group.add_option( '', '--prefix', default=d_prefix, action='store',
- help='specify destination for final products (%s)' % (d_prefix) )
-parser.add_option_group( group )
-
-group = OptionGroup( parser, 'Feature Options' )
-if d_xcode:
- 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()
-
-exports = []
-for arg in args:
- m = re.match( '([^=]+)=(.*)', arg )
- if m:
- exports.append( m.groups() )
-
-## 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 = computeNumCPU()
- 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.machine = 'i386'
- elif archMode.mode == 'x86_64':
- guessBuild.machine = 'x86_64'
- elif archMode.mode == 'ppc':
- guessBuild.machine = 'powerpc'
- elif archMode.mode == 'ppc64':
- guessBuild.machine = 'powerpc64'
-else:
- guessBuild.machine = 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 )
+class SelectMode( dict ):
+ def __init__( self, descr, *modes, **kwargs ):
+ super( SelectMode, self ).__init__( modes )
+ self.descr = descr
+ self.modes = modes
+ self.default = kwargs.get('default',modes[0][0])
+ self.mode = self.default
+
+ def cli_add_option( self, parser, option ):
+ parser.add_option( '', option, default=self.mode, metavar='MODE',
+ help='select %s mode: %s' % (self.descr,self.toString()),
+ action='callback', callback=self.cli_callback, type='str' )
+
+ def cli_callback( self, option, opt_str, value, parser, *args, **kwargs ):
+ if value not in self:
+ raise optparse.OptionValueError( 'invalid %s mode: %s (choose from %s)'
+ % (self.descr,value,self.toString( True )) )
+ self.mode = value
+
+ def toString( self, nodefault=False ):
+ keys = self.keys()
+ keys.sort()
+ if len(self) == 1:
+ value = self.mode
+ elif nodefault:
+ value = ' '.join( keys )
+ else:
+ value = '%s [%s]' % (' '.join( keys ), self.mode )
+ return value
###############################################################################
-
+##
## Repository object.
## Holds information gleaned from subversion working dir.
##
@@ -427,62 +542,48 @@ for tool in tools.items:
## unofficial
## all other builds
##
-class Repository:
+class RepoProbe( ShellProbe ):
def __init__( self ):
+ super( RepoProbe, self ).__init__( 'svn info', 'svn info %s' % (cfg.src_dir) )
+
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 ' + initial_project_dir
- print 'attempting to probe subversion: %s' % (cmd)
- try:
- p = subprocess.Popen( cmd, shell=True, stdout=subprocess.PIPE )
- p.wait();
- if p.returncode:
- sys.exit( 1 )
- self.wcversion = p.stdout.readline().rstrip()
- except:
- pass
+ def _parseSession( self ):
+ for line in self.session:
+ ## grok fields
+ m = re.match( '([^:]+):\\s+(.+)', line )
+ if not m:
+ continue
- # parse output: svn info PROJECT_DIR
- cmd = 'svn info ' + initial_project_dir
- print 'attempting to probe subversion: %s' % (cmd)
- try:
- p = subprocess.Popen( cmd, shell=True, stdout=subprocess.PIPE )
- p.wait();
- if p.returncode:
- sys.exit( 1 )
- 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
+ (name,value) = m.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
+ ## grok branch
i = self.url.rfind( '/' )
if i != -1 and i < len(self.url)-1:
self.branch = self.url[i+1:]
- # official UUID behavior
+ # type-classification via repository UUID
if self.uuid == 'b64f7644-9d1e-0410-96f1-a4d463321fa5':
self.official = 1
m = re.match( '([^:]+)://([^/]+)/(.+)', self.url )
@@ -491,14 +592,19 @@ class Repository:
else:
self.type = 'developer'
-###############################################################################
+ self.msg_end = self.url
-## Project object.
+###############################################################################
+##
+## project object.
+##
## Contains manually updated version numbers consistent with HB releases
## and other project metadata.
##
-class Project:
+class Project( Action ):
def __init__( self ):
+ super( Project, self ).__init__( 'compute', 'project data' )
+
self.name = 'HandBrake'
self.acro_lower = 'hb'
self.acro_upper = 'HB'
@@ -513,6 +619,7 @@ class Project:
self.vminor = 9
self.vpoint = 4
+ def _action( self ):
appcastfmt = 'http://handbrake.fr/appcast%s.xml'
if repo.type == 'release':
@@ -527,48 +634,164 @@ class Project:
self.title = '%s svn%d (%s)' % (self.name,repo.rev,self.build)
else:
self.version = 'svn%d' % (repo.rev)
- self.version = '%d.%d.%d' % (self.vmajor,self.vminor,self.vpoint)
self.url_appcast = appcastfmt % ('_unofficial')
self.build = time.strftime('%Y%m%d') + '99'
self.title = 'Unofficial svn%d (%s)' % (repo.rev,self.build)
+ self.msg_end = '%s (%s)' % (self.name,repo.type)
+ self.fail = False
+
###############################################################################
-## Config object used to output gnu-make or gnu-m4 output.
+class ToolProbe( Action ):
+ tools = []
+
+ def __init__( self, var, *names, **kwargs ):
+ super( ToolProbe, self ).__init__( 'find', abort=kwargs.get('abort',True) )
+ if not self in ToolProbe.tools:
+ ToolProbe.tools.append( self )
+ self.var = var
+ self.names = []
+ self.kwargs = kwargs
+ for name in names:
+ if name:
+ self.names.append( str(name) )
+ self.name = self.names[0]
+ self.pretext = self.name
+ self.pathname = self.names[0]
+
+ def _action( self ):
+ self.session = []
+ for i,name in enumerate(self.names):
+ self.session.append( 'name[%d] = %s' % (i,name) )
+ for name in self.names:
+ f = cfg.findExecutable( name )
+ if f:
+ self.pathname = f
+ self.fail = False
+ self.msg_end = f
+ break
+ if self.fail:
+ self.msg_end = 'not found'
+
+ def cli_add_option( self, parser ):
+ parser.add_option( '', '--'+self.name, metavar='PROG',
+ help='[%s]' % (self.pathname),
+ action='callback', callback=self.cli_callback, type='str' )
+
+ def cli_callback( self, option, opt_str, value, parser, *args, **kwargs ):
+ self.__init__( self.var, value, **self.kwargs )
+ self.run()
+
+ def doc_add( self, doc ):
+ doc.add( self.var, self.pathname )
+
+###############################################################################
+
+class SelectTool( Action ):
+ selects = []
+
+ def __init__( self, var, name, *pool, **kwargs ):
+ super( SelectTool, self ).__init__( 'select', abort=kwargs.get('abort',True) )
+ self.pretext = name
+ if not self in SelectTool.selects:
+ SelectTool.selects.append( self )
+ self.var = var
+ self.name = name
+ self.pool = pool
+ self.kwargs = kwargs
+
+ def _action( self ):
+ self.session = []
+ for i,(name,tool) in enumerate(self.pool):
+ self.session.append( 'tool[%d] = %s (%s)' % (i,name,tool.pathname) )
+ for (name,tool) in self.pool:
+ if not tool.fail:
+ self.selected = name
+ self.fail = False
+ self.msg_end = '%s (%s)' % (name,tool.pathname)
+ break
+ if self.fail:
+ self.msg_end = 'not found'
+
+ def cli_add_option( self, parser ):
+ parser.add_option( '', '--'+self.name, metavar='MODE',
+ help='select %s mode: %s' % (self.name,self.toString()),
+ action='callback', callback=self.cli_callback, type='str' )
+
+ def cli_callback( self, option, opt_str, value, parser, *args, **kwargs ):
+ found = False
+ for (name,tool) in self.pool:
+ if name == value:
+ found = True
+ self.__init__( self.var, self.name, [name,tool], **kwargs )
+ self.run()
+ break
+ if not found:
+ raise optparse.OptionValueError( 'invalid %s mode: %s (choose from %s)'
+ % (self.name,value,self.toString( True )) )
+
+ def doc_add( self, doc ):
+ doc.add( self.var, self.selected )
+
+ def toString( self, nodefault=False ):
+ if len(self.pool) == 1:
+ value = self.pool[0][0]
+ else:
+ s = ''
+ for key,value in self.pool:
+ s += ' ' + key
+ if nodefault:
+ value = s[1:]
+ else:
+ value = '%s [%s]' % (s[1:], self.selected )
+ return value
+
+###############################################################################
##
-## 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.
+## config object used to output gnu-make or gnu-m4 output.
##
-class Config:
+## - add() to add NAME/VALUE pairs suitable for both make/m4.
+## - addBlank() to add a linefeed for both make/m4.
+## - addMake() to add a make-specific line.
+## - addM4() to add a m4-specific line.
+##
+class ConfigDocument:
def __init__( self ):
- self._items = []
+ self._elements = []
+
+ 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 ))
def add( self, name, value ):
- self._items.append( (name,value) )
+ self._elements.append( (name,value) )
def addBlank( self ):
- self._items.append( None )
+ self._elements.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) )
+ self._elements.append( ('?make',line) )
def addM4( self, line ):
- self._items.append( ('?m4',line) )
+ self._elements.append( ('?m4',line) )
def output( self, file, type ):
namelen = 0
- for item in self._items:
+ for item in self._elements:
if item == None or item[0].find( '?' ) == 0:
continue
if len(item[0]) > namelen:
namelen = len(item[0])
- for item in self._items:
+ for item in self._elements:
if item == None:
if type == 'm4':
file.write( 'dnl\n' )
@@ -585,226 +808,445 @@ class Config:
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 ))
+ def write( self, 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'
+ try:
+ try:
+ file = cfg.open( ftmp, 'w' )
+ self.output( file, type )
+ finally:
+ try:
+ file.close()
+ except:
+ pass
+ except Exception, x:
+ try:
+ os.remove( ftmp )
+ except Exception, x:
+ pass
+ cfg.errln( 'failed writing to %s\n%s', ftmp, x )
-## create configure line, stripping arg --launch, quoting others
-configure = []
-for arg in sys.argv[1:]:
- if arg == '--launch':
- continue
- configure.append( "'%s'" % (arg.replace("'", '%c%c%c%c%c' % (0x27,0x22,0x27,0x22,0x27))) )
-
-## 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.hex', '%04x%02x%02x%08x' % (project.vmajor,project.vminor,project.vpoint,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.machine', guessHost.machine )
-config.add( 'HOST.vendor', guessHost.vendor )
-config.add( 'HOST.system', guessHost.system )
-config.add( 'HOST.systemc', guessHost.systemc )
-config.add( 'HOST.release', guessHost.release )
-config.add( 'HOST.title', '%s %s' % (guessHost.systemc,archMode.default) )
-config.add( 'HOST.extra', guessHost.extra )
-config.add( 'HOST.ncpu', computeNumCPU() )
-
-config.addBlank()
-config.add( 'BUILD.spec', guessBuild )
-config.add( 'BUILD.machine', guessBuild.machine )
-config.add( 'BUILD.vendor', guessBuild.vendor )
-config.add( 'BUILD.system', guessBuild.system )
-config.add( 'BUILD.systemc', guessBuild.systemc )
-config.add( 'BUILD.release', guessBuild.release )
-config.add( 'BUILD.title', '%s %s' % (guessBuild.systemc,archMode.mode) )
-config.add( 'BUILD.extra', guessBuild.extra )
-config.add( 'BUILD.method', 'terminal' )
-config.add( 'BUILD.cross', guessBuild.cross )
-config.add( 'BUILD.date', time.strftime('%c') )
-config.add( 'BUILD.arch', archMode.mode )
-config.add( 'BUILD.jobs', computeNumCPU() )
-
-config.addBlank()
-config.add( 'CONF.method', options.conf_method )
-
-config.addBlank()
-config.add( 'BUILD/', os.curdir + os.sep )
-config.add( 'PROJECT/', project_dir + os.sep )
-
-config.addBlank()
-config.add( 'INSTALL.prefix', options.prefix )
-config.add( 'INSTALL.prefix/', '$(INSTALL.prefix)/' )
-
-config.addBlank()
-config.add( 'FEATURE.xcode', 0 if not hasattr(options, 'disable_xcode') or 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 )
-
-if len(exports):
- config.addBlank()
- for nv in exports:
- config.add( nv[0], nv[1] )
-
-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' )
+ try:
+ os.rename( ftmp, fname )
+ except Exception, x:
+ cfg.errln( 'failed writing to %s\n%s', fname, x )
###############################################################################
+##
+## create cli parser
+##
+def createCLI():
+ cli = OptionParser( 'usage: %prog [OPTIONS...] [TARGETS...]' )
+
+ cli.description = ''
+ cli.description += 'Configure %s build system.' % (project.name)
+
+ ## add hidden options
+ cli.add_option( '', '--conf-method', default='terminal', action='store', help=optparse.SUPPRESS_HELP )
+ cli.add_option( '', '--force', default=False, action='store_true', help='overwrite existing build config' )
+ cli.add_option( '', '--verbose', default=False, action='store_true', help='increase verbosity' )
+
+ ## add install options
+ grp = OptionGroup( cli, 'Directory Locations' )
+ grp.add_option( '', '--src', default=cfg.src_dir, action='store', metavar='DIR',
+ help='specify top-level source dir [%s]' % (cfg.src_dir) )
+ grp.add_option( '', '--build', default=cfg.build_dir, action='store', metavar='DIR',
+ help='specify build scratch/output dir [%s]' % (cfg.build_dir) )
+ grp.add_option( '', '--prefix', default=cfg.prefix_dir, action='store', metavar='DIR',
+ help='specify install dir for products [%s]' % (cfg.prefix_dir) )
+ cli.add_option_group( grp )
+
+ ## add feature options
+ grp = OptionGroup( cli, 'Feature Options' )
+ h = ForHost( optparse.SUPPRESS_HELP, ['disable Xcode (Darwin only)','*-*-darwin*'] ).value
+ grp.add_option( '', '--disable-xcode', default=False, action='store_true', help=h )
+ h = ForHost( optparse.SUPPRESS_HELP, ['disable GTK GUI (Linux only)','*-*-linux*'] ).value
+ grp.add_option( '', '--disable-gtk', default=False, action='store_true', help=h )
+ cli.add_option_group( grp )
+
+ ## add launch options
+ grp = OptionGroup( cli, 'Launch Options' )
+ grp.add_option( '', '--launch', default=False, action='store_true',
+ help='launch build, capture log and wait for completion' )
+ grp.add_option( '', '--launch-jobs', default=1, action='store', metavar='N', type='int',
+ help='allow N jobs at once; 0 to match CPU count [1]' )
+ grp.add_option( '', '--launch-args', default=None, action='store', metavar='ARGS',
+ help='specify additional ARGS for launch command' )
+ grp.add_option( '', '--launch-quiet', default=False, action='store_true',
+ help='do not echo build output' )
+ cli.add_option_group( grp )
+
+ ## add compile options
+ grp = OptionGroup( cli, 'Compiler Options' )
+ debugMode.cli_add_option( grp, '--debug' )
+ optimizeMode.cli_add_option( grp, '--optimize' )
+ arch.mode.cli_add_option( grp, '--arch' )
+ cli.add_option_group( grp )
+
+ ## add tool locations
+ grp = OptionGroup( cli, 'Tool Basenames and Locations' )
+ for tool in ToolProbe.tools:
+ tool.cli_add_option( grp )
+ cli.add_option_group( grp )
+
+ ## add tool modes
+ grp = OptionGroup( cli, 'Tool Options' )
+ for select in SelectTool.selects:
+ select.cli_add_option( grp )
+ cli.add_option_group( grp )
+ return cli
-# 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 )
+###############################################################################
+##
+## launcher - used for QuickStart method; launch; build and capture log.
+##
+class Launcher:
+ def __init__( self, targets ):
+ # open build logfile
+ self._file = cfg.open( 'log/build.txt', 'w' )
+
+ cmd = '%s -j%d' % (Tools.gmake.pathname,core.jobs)
+ if options.launch_args:
+ cmd += ' ' + options.launch_args
+ if len(targets):
+ cmd += ' ' + ' '.join(targets)
+
+ ## record begin
+ timeBegin = time.time()
+ self.infof( 'time begin: %s\n', time.asctime() )
+ self.infof( 'launch: %s\n', cmd )
+ if options.launch_quiet:
+ stdout.write( 'building to %s ...\n' % (os.path.abspath( cfg.build_final )))
+ else:
+ stdout.write( '%s\n' % ('-' * 79) )
- try:
+ ## launch/pipe
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 )
+ pipe = subprocess.Popen( cmd, shell=True, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
except Exception, x:
- pass
- errf( 'failed writing to %s\n%s', ftmp, x )
+ cfg.errln( 'launch failure: %s', x )
+ for line in pipe.stdout:
+ self.echof( '%s', line )
+ pipe.wait()
- try:
- os.rename( ftmp, fname )
- except Exception, x:
- errf( 'failed writing to %s\n%s', fname, x )
+ ## record end
+ timeEnd = time.time()
+ elapsed = timeEnd - timeBegin
-###############################################################################
+ if pipe.returncode:
+ result = 'FAILURE (code %d)' % pipe.returncode
+ else:
+ result = 'SUCCESS'
+
+ ## present duration in decent format
+ seconds = elapsed
+ hours = int(seconds / 3600)
+ seconds -= hours * 3600
+ minutes = int(seconds / 60)
+ seconds -= minutes * 60
+
+ segs = []
+ duration = ''
+
+ if hours == 1:
+ segs.append( '%d hour' % hours )
+ elif hours > 1:
+ segs.append( '%d hours' % hours )
+
+ if len(segs) or minutes == 1:
+ segs.append( '%d minute' % minutes )
+ elif len(segs) or minutes > 1:
+ segs.append( '%d minutes' % minutes )
+
+ if seconds == 1:
+ segs.append( '%d second' % seconds )
+ else:
+ segs.append( '%d seconds' % seconds )
-if not options.launch:
- generate( 'make' )
- generate( 'm4' )
- sys.exit( 0 )
+ if not options.launch_quiet:
+ stdout.write( '%s\n' % ('-' * 79) )
+ self.infof( 'time end: %s\n', time.asctime() )
+ self.infof( 'duration: %s (%.2fs)\n', ', '.join(segs), elapsed )
+ self.infof( 'result: %s\n', result )
-###############################################################################
+ ## cleanup
+ self._file.close()
-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 )
+ def echof( self, format, *args ):
+ line = format % args
+ self._file.write( line )
+ if not options.launch_quiet:
+ stdout.write( ' : %s' % line )
+ stdout.flush()
-outf( 'chdir %s', options.launch_dir )
-os.chdir( options.launch_dir )
-generate( 'make' )
-generate( 'm4' )
+ def infof( self, format, *args ):
+ line = format % args
+ self._file.write( line )
+ cfg.infof( '%s', line )
-outf( 'opening %s', options.launch_log )
+###############################################################################
+##
+## main program
+##
try:
- log = open( options.launch_log, 'w' )
-except Exception, x:
- errf( 'open failure: %s', x )
+ ## we need to pre-check argv for -h or --help or --verbose to deal with
+ ## initializing Configure correctly.
+ verbose = Configure.OUT_INFO
+ for arg in sys.argv:
+ if arg == '-h' or arg == '--help':
+ verbose = Configure.OUT_QUIET
+ break
+ if arg == '--verbose':
+ verbose = Configure.OUT_VERBOSE
+
+ ## create main objects; actions/probes run() is delayed.
+ ## if any actions must be run earlier (eg: for configure --help purposes)
+ ## then run() must be invoked earlier. subequent run() invocations
+ ## are ignored.
+ cfg = Configure( verbose )
+ host = HostTupleProbe(); host.run()
+
+ cfg.prefix_dir = ForHost( '/usr/local', ['/Applications','*-*-darwin*'] ).value
+
+ build = BuildAction()
+ arch = ArchAction(); arch.run()
+
+ ## create remaining main objects
+ core = CoreProbe()
+ repo = RepoProbe()
+ project = Project()
+
+ ## create tools in a scope
+ class Tools:
+ ar = ToolProbe( 'AR.exe', 'ar' )
+ cp = ToolProbe( 'CP.exe', 'cp' )
+ curl = ToolProbe( 'CURL.exe', 'curl', abort=False )
+ gcc = ToolProbe( 'GCC.gcc', 'gcc', IfHost('gcc-4','*-*-cygwin*') )
+
+ if host.match( '*-*-darwin*' ):
+ gmake = ToolProbe( 'GMAKE.exe', 'make', 'gmake' )
+ else:
+ gmake = ToolProbe( 'GMAKE.exe', 'gmake', 'make' )
+
+ m4 = ToolProbe( 'M4.exe', 'm4' )
+ mkdir = ToolProbe( 'MKDIR.exe', 'mkdir' )
+ patch = ToolProbe( 'PATCH.exe', 'gpatch', 'patch' )
+ rm = ToolProbe( 'RM.exe', 'rm' )
+ tar = ToolProbe( 'TAR.exe', 'gtar', 'tar' )
+ wget = ToolProbe( 'WGET.exe', 'wget', abort=False )
+
+ xcodebuild = ToolProbe( 'XCODEBUILD.exe', 'xcodebuild', abort=False )
+ lipo = ToolProbe( 'LIPO.exe', 'lipo', abort=False )
+
+ fetch = SelectTool( 'FETCH.select', 'fetch', ['wget',wget], ['curl',curl] )
+
+ ## run tool probes
+ for tool in ToolProbe.tools:
+ tool.run()
+ for select in SelectTool.selects:
+ select.run()
+
+ debugMode = SelectMode( 'debug', ('none','none'), ('min','min'), ('std','std'), ('max','max') )
+ optimizeMode = SelectMode( 'optimize', ('none','none'), ('speed','speed'), ('size','size'), default='speed' )
+
+ ## create CLI and parse
+ cli = createCLI()
+ (options,args) = cli.parse_args()
+
+ ## update cfg with cli directory locations
+ cfg.update_cli( options )
+
+ ## prepare list of targets and NAME=VALUE args to pass to make
+ targets = []
+ exports = []
+ rx_exports = re.compile( '([^=]+)=(.*)' )
+ for arg in args:
+ m = rx_exports.match( arg )
+ if m:
+ exports.append( m.groups() )
+ else:
+ targets.append( arg )
+
+ ## run delayed actions
+ for action in Action.actions:
+ action.run()
+
+ ## cfg hook before doc prep
+ cfg.doc_ready()
+
+ ## create document object
+ doc = ConfigDocument()
+ doc.addComment( 'generated by configure on %s', time.strftime( '%c' ))
+
+ ## add configure line for reconfigure purposes
+ doc.addBlank()
+ args = []
+ for arg in sys.argv[1:]:
+ if arg == '--launch':
+ continue
+ args.append( "'%s'" % (arg.replace("'", '%c%c%c%c%c' % (0x27,0x22,0x27,0x22,0x27))) )
+ doc.add( 'CONF.args', ' '.join( args ))
+
+ doc.addBlank()
+ doc.add( 'HB.title', project.title )
+ doc.add( 'HB.name', project.name )
+ doc.add( 'HB.name.lower', project.name_lower )
+ doc.add( 'HB.name.upper', project.name_upper )
+ doc.add( 'HB.acro.lower', project.acro_lower )
+ doc.add( 'HB.acro.upper', project.acro_upper )
+
+ doc.add( 'HB.url.website', project.url_website )
+ doc.add( 'HB.url.community', project.url_community )
+ doc.add( 'HB.url.irc', project.url_irc )
+ doc.add( 'HB.url.appcast', project.url_appcast )
+
+ doc.add( 'HB.version.major', project.vmajor )
+ doc.add( 'HB.version.minor', project.vminor )
+ doc.add( 'HB.version.point', project.vpoint )
+ doc.add( 'HB.version', project.version )
+ doc.add( 'HB.version.hex', '%04x%02x%02x%08x' % (project.vmajor,project.vminor,project.vpoint,repo.rev) )
+
+ doc.add( 'HB.build', project.build )
+
+ doc.add( 'HB.repo.url', repo.url )
+ doc.add( 'HB.repo.root', repo.root )
+ doc.add( 'HB.repo.branch', repo.branch )
+ doc.add( 'HB.repo.uuid', repo.uuid )
+ doc.add( 'HB.repo.rev', repo.rev )
+ doc.add( 'HB.repo.date', repo.date )
+ doc.add( 'HB.repo.official', repo.official )
+ doc.add( 'HB.repo.type', repo.type )
+
+ doc.addBlank()
+ doc.add( 'HOST.spec', host.spec )
+ doc.add( 'HOST.machine', host.machine )
+ doc.add( 'HOST.vendor', host.vendor )
+ doc.add( 'HOST.system', host.system )
+ doc.add( 'HOST.systemf', host.systemf )
+ doc.add( 'HOST.release', host.release )
+ doc.add( 'HOST.extra', host.extra )
+ doc.add( 'HOST.title', '%s %s' % (host.systemf,arch.mode.default) )
+ doc.add( 'HOST.ncpu', core.count )
+
+ doc.addBlank()
+ doc.add( 'BUILD.spec', build.spec )
+ doc.add( 'BUILD.machine', build.machine )
+ doc.add( 'BUILD.vendor', build.vendor )
+ doc.add( 'BUILD.system', build.system )
+ doc.add( 'BUILD.systemf', build.systemf )
+ doc.add( 'BUILD.release', build.release )
+ doc.add( 'BUILD.extra', build.extra )
+ doc.add( 'BUILD.title', '%s %s' % (build.systemf,arch.mode.mode) )
+ doc.add( 'BUILD.ncpu', core.count )
+ doc.add( 'BUILD.jobs', core.jobs )
+
+ doc.add( 'BUILD.cross', int(arch.mode.mode != arch.mode.default) )
+ doc.add( 'BUILD.method', 'terminal' )
+ doc.add( 'BUILD.date', time.strftime('%c') )
+ doc.add( 'BUILD.arch', arch.mode.mode )
+
+ doc.addBlank()
+ doc.add( 'CONF.method', options.conf_method )
+
+ doc.addBlank()
+ doc.add( 'SRC', cfg.src_final )
+ doc.add( 'SRC/', cfg.src_final + os.sep )
+ doc.add( 'BUILD', cfg.build_final )
+ doc.add( 'BUILD/', cfg.build_final + os.sep )
+ doc.add( 'PREFIX', cfg.prefix_final )
+ doc.add( 'PREFIX/', cfg.prefix_final + os.sep )
+
+ doc.addBlank()
+ doc.add( 'FEATURE.xcode', int( not (Tools.xcodebuild.fail or options.disable_xcode) ))
+ doc.add( 'FEATURE.gtk', int( not options.disable_gtk ))
+
+ if not Tools.xcodebuild.fail and not options.disable_xcode:
+ doc.addBlank()
+ doc.add( 'XCODE.external.src', cfg.xcode_x_src )
+ doc.add( 'XCODE.external.build', cfg.xcode_x_build )
+ doc.add( 'XCODE.external.prefix', cfg.xcode_x_prefix )
+
+ doc.addMake( '' )
+ doc.addMake( '## include definitions' )
+ doc.addMake( 'include $(SRC/)make/include/main.defs' )
+
+ doc.addBlank()
+ for tool in ToolProbe.tools:
+ tool.doc_add( doc )
+
+ doc.addBlank()
+ for select in SelectTool.selects:
+ select.doc_add( doc )
+
+ doc.addBlank()
+ if arch.mode.mode != arch.mode.default:
+ doc.add( 'GCC.archs', arch.mode.mode )
+ else:
+ doc.add( 'GCC.archs', '' )
+ doc.add( 'GCC.g', debugMode.mode )
+ doc.add( 'GCC.O', optimizeMode.mode )
+
+ ## add exports to make
+ if len(exports):
+ doc.addBlank()
+ doc.addComment( 'overrides via VARIABLE=VALUE on command-line' )
+ for nv in exports:
+ doc.add( nv[0], nv[1] )
+
+ doc.addMake( '' )
+ doc.addMake( '## include custom definitions' )
+ doc.addMake( '-include $(SRC/)custom.defs' )
+ doc.addMake( '-include $(BUILD/)GNUmakefile.custom.defs' )
+
+ doc.addMake( '' )
+ doc.addMake( '## include rules' )
+ doc.addMake( 'include $(SRC/)make/include/main.rules' )
+ doc.addMake( '-include $(SRC/)custom.rules' )
+ doc.addMake( '-include $(BUILD/)GNUmakefile.custom.rules' )
+
+ ## chdir
+ cfg.chdir()
+
+ ## perform
+ doc.write( 'make' )
+ doc.write( 'm4' )
+ if options.launch:
+ Launcher( targets )
+
+ cfg.record_log()
+
+ if os.path.normpath( cfg.build_dir ) == os.curdir:
+ nocd = True
+ else:
+ nocd = False
-cmd = '%s -j%d' % (makeTool.found,options.launch_jobs)
-if options.launch_args:
- cmd += ' ' + options.launch_args
+ stdout.write( '%s\n' % ('-' * 79) )
+ if options.launch:
+ stdout.write( 'Build is finished!\n' )
+ if nocd:
+ stdout.write( 'You may now examine the output.\n' )
+ else:
+ stdout.write( 'You may now cd into %s and examine the output.\n' % (cfg.build_dir) )
+ else:
+ stdout.write( 'Build is configured!\n' )
+ if nocd:
+ stdout.write( 'You may now run make (%s).\n' % (Tools.gmake.pathname) )
+ else:
+ stdout.write( 'You may now cd into %s and run make (%s).\n' % (cfg.build_dir,Tools.gmake.pathname) )
-## 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()
+except AbortError, x:
+ stderr.write( 'ERROR: %s\n' % (x) )
+ try:
+ cfg.record_log()
+ except:
+ pass
+ sys.exit( 1 )
-## 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/contrib.defs b/make/include/contrib.defs
index 3cd80303e..5f1f9e54b 100644
--- a/make/include/contrib.defs
+++ b/make/include/contrib.defs
@@ -1,5 +1,5 @@
CONTRIB.build/ = $(BUILD/)contrib/
-CONTRIB.download/ = $(PROJECT/)download/
+CONTRIB.download/ = $(SRC/)download/
CONTRIB.host = $(if $(filter 1,$(BUILD.cross)),$(BUILD.spec))
###############################################################################
@@ -17,7 +17,7 @@ define import.CONTRIB.defs
##
## common values useful across targets
##
- $(1).src/ = $$(PROJECT/)contrib/$($(1).name)/
+ $(1).src/ = $$(SRC/)contrib/$($(1).name)/
$(1).build/ = $$(CONTRIB.build/)$($(1).name)/
$(1).deps = $$(foreach n,$($(1).prerequisites),$$($$n.INSTALL.target))
@@ -209,7 +209,7 @@ $($(1).name).extract.touch:
$$(TOUCH.exe) $$($(1).EXTRACT.target)
$($(1).name).extract.untouch:
- $$(RM.exe) $$($(1).EXTRACT.target)
+ $$(RM.exe) -f $$($(1).EXTRACT.target)
##
## target: patch
@@ -224,7 +224,7 @@ $($(1).name).patch.touch:
$$(TOUCH.exe) $$($(1).PATCH.target)
$($(1).name).patch.untouch:
- $$(RM.exe) $$($(1).PATCH.target)
+ $$(RM.exe) -f $$($(1).PATCH.target)
##
## target: configure
@@ -240,7 +240,7 @@ $($(1).name).configure.touch:
$$(TOUCH.exe) $$($(1).CONFIGURE.target)
$($(1).name).configure.untouch:
- $$(RM.exe) $$($(1).CONFIGURE.target)
+ $$(RM.exe) -f $$($(1).CONFIGURE.target)
##
## target: build
@@ -256,7 +256,7 @@ $($(1).name).build.touch:
$$(TOUCH.exe) $$($(1).BUILD.target)
$($(1).name).build.untouch:
- $$(RM.exe) $$($(1).BUILD.target)
+ $$(RM.exe) -f $$($(1).BUILD.target)
##
## target: install
@@ -271,7 +271,7 @@ $($(1).name).install.touch:
$$(TOUCH.exe) $$($(1).INSTALL.target)
$($(1).name).install.untouch:
- $$(RM.exe) $$($(1).INSTALL.target)
+ $$(RM.exe) -f $$($(1).INSTALL.target)
##
## target: uninstall
diff --git a/make/include/main.defs b/make/include/main.defs
index 93271a365..f07678b79 100644
--- a/make/include/main.defs
+++ b/make/include/main.defs
@@ -1,10 +1,10 @@
-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
+include $(SRC/)make/include/base.defs
+include $(SRC/)make/include/contrib.defs
+include $(SRC/)make/include/function.defs
+include $(SRC/)make/include/gcc.defs
+include $(SRC/)make/include/select.defs
+include $(SRC/)make/include/target.defs
+include $(SRC/)make/include/tool.defs
###############################################################################
@@ -62,6 +62,6 @@ MODULES += doc
###############################################################################
-include $(MODULES:%=$(PROJECT/)%/module.defs)
-include $(PROJECT/)make/variant/$(HOST.system).defs
--include $(PROJECT/)make/variant/$(HOST.system).$(BUILD.machine).defs
+include $(MODULES:%=$(SRC/)%/module.defs)
+include $(SRC/)make/variant/$(HOST.system).defs
+-include $(SRC/)make/variant/$(HOST.system).$(BUILD.machine).defs
diff --git a/make/include/main.rules b/make/include/main.rules
index 4625ae9db..51460a35d 100644
--- a/make/include/main.rules
+++ b/make/include/main.rules
@@ -5,12 +5,12 @@
## file-wide conditional to use xcode rules if xcode=1 method=terminal
ifeq ($(FEATURE.xcode):$(BUILD.method),1:terminal)
- include $(PROJECT/)macosx/module.xcode
+ include $(SRC/)macosx/module.xcode
else
## only included using special report targets
ifneq (,$(REPORT))
- include $(PROJECT/)make/include/report.defs
+ include $(SRC/)make/include/report.defs
endif
###############################################################################
@@ -30,22 +30,22 @@ mrproper: xclean
###############################################################################
-include $(PROJECT/)make/include/base.rules
+include $(SRC/)make/include/base.rules
-include $(MODULES:%=$(PROJECT/)%/module.rules)
--include $(PROJECT/)make/variant/$(HOST.system).rules
--include $(PROJECT/)make/variant/$(HOST.system).$(BUILD.machine).rules
+include $(MODULES:%=$(SRC/)%/module.rules)
+-include $(SRC/)make/variant/$(HOST.system).rules
+-include $(SRC/)make/variant/$(HOST.system).$(BUILD.machine).rules
###############################################################################
## target which causes re-configure if project-root is svn update'd
-$(BUILD/)GNUmakefile: $(wildcard $(PROJECT/).svn/entries)
- $(PROJECT/)configure $(CONF.args)
+$(BUILD/)GNUmakefile: $(wildcard $(SRC/).svn/entries)
+ $(SRC/)configure $(CONF.args)
## target useful to force reconfigure; only helpful for build-system development
.PHONY: reconfigure
reconfigure:
- $(PROJECT/)configure $(CONF.args)
+ $(SRC/)configure $(CONF.args)
###############################################################################
diff --git a/make/variant/darwin.defs b/make/variant/darwin.defs
index 6f8f6729d..baffda595 100644
--- a/make/variant/darwin.defs
+++ b/make/variant/darwin.defs
@@ -1,40 +1,9 @@
-## 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.archs = i386 x86_64 ppc ppc64
+UB.builds = $(wildcard $(foreach n,$(UB.archs),$(SRC/)build.$n))
+UB.first = $(word 1,$(UB.archs))
+UB.other = $(wordlist 2,999,$(UB.archs))
-UB.BUILD = $(PROJECT/)configure --launch --launch-dir=ub.$(1) --arch=$(1)
+UB.BUILD = $(SRC/)configure --build=ub.$(1) --arch=$(1) --launch --launch-quiet
## linefeed is important
define UB.BUILD.item
@@ -43,19 +12,21 @@ define UB.BUILD.item
endef
define UB.BUILD.SERIAL
- $(foreach n,$(UB.archs.other),$(call UB.BUILD.item,$n))
+ $(foreach n,$(UB.archs),$(call UB.BUILD.item,$n))
endef
define UB.BUILD.PARALLEL
- $(call UB.BUILD,$(1)) 2>&1 > ub.$(1).log
+ $(call UB.BUILD,$(1)) >/dev/null 2>&1
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)
+ $(CP.exe) -R ub.$(UB.first)/HandBrake.app ub.combine/.
+ $(LIPO.exe) $(foreach n,$(UB.archs),ub.$n/$(1)) -create -output ub.combine/$(1)
+ @lipo -info ub.combine/$(1)
+ @sync
@echo ""
- @sync; lipo -info ub.combine/$(1)
- @du -sh ub.combine/$(1)
+ @echo "$@: { $(UB.archs) } combined -> ub.combine/HandBrake.app"
+ @echo "$@: UB executable size: `du -sh ub.combine/$(1) | awk '{ print $$1 }'`"
endef
diff --git a/make/variant/darwin.rules b/make/variant/darwin.rules
index c4f4f97a4..d59a222b4 100644
--- a/make/variant/darwin.rules
+++ b/make/variant/darwin.rules
@@ -5,7 +5,7 @@ ub.build.serial:
ub.build.parallel:
@set -e; \
- for arch in $(UB.archs.other); do \
+ for arch in $(UB.archs); do \
$(call UB.BUILD.PARALLEL,$$arch) & \
children="$$children $$!"; \
echo "pid $$!: $(call UB.BUILD.PARALLEL,$$arch)"; \
diff --git a/make/variant/freebsd.defs b/make/variant/freebsd.defs
index c58706ba1..9a807b8d4 100644
--- a/make/variant/freebsd.defs
+++ b/make/variant/freebsd.defs
@@ -2,3 +2,8 @@ TARGET.dylib.ext = .so
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
diff --git a/make/xcodemake b/make/xcodemake
index a75cd3ed6..fde684cdf 100755
--- a/make/xcodemake
+++ b/make/xcodemake
@@ -12,8 +12,6 @@ set -e
MAKEFLAGS=
MFLAGS=
-cd $EXTERNAL_BUILD
-
## re/configure if not configured by Xcode or if missing top-makefile
if [ $EXTERNAL_METHOD != 'xcode' -o ! -f $EXTERNAL_BUILD/GNUmakefile ]; then
## compute --arch value based on Xcode configuration naming convention
@@ -36,7 +34,7 @@ if [ $EXTERNAL_METHOD != 'xcode' -o ! -f $EXTERNAL_BUILD/GNUmakefile ]; then
esac
## invoke configure with (hidden) option which indicates conf performed by xcode
- $EXTERNAL_PROJECT/configure PATH=$PATH --conf-method=xcode $args
+ $EXTERNAL_SRC/configure --force --build=$EXTERNAL_BUILD --conf-method=xcode PATH=$PATH $args
fi
## safeguard against passing blank value which would result in unlimited jobs