## x86_64-unknown-linux-gnu (Linux, Fedora 10 x86_64)
##
class HostTupleProbe( ShellProbe, list ):
- GNU_TUPLE_RX = '([^-]+)-([^-]+)-([^0-9-]+)([^-]*)-?([^-]*)'
+ GNU_TUPLE_RE = '([^-]+)-?([^-]*)-([^0-9-]+)([^-]*)-?([^-]*)'
def __init__( self ):
super( HostTupleProbe, self ).__init__( 'host tuple', '%s/config.guess' % (cfg.dir), abort=True, head=True )
self.spec = ''
## grok GNU host tuples
- m = re.match( HostTupleProbe.GNU_TUPLE_RX, self.spec )
+ m = re.match( HostTupleProbe.GNU_TUPLE_RE, self.spec )
if not m:
self.fail = True
self.msg_end = 'invalid host tuple: %s' % (self.spec)
self.systemf = self[2][0].upper() + self[2][1:]
## glob-match against spec
- def match( self, spec ):
- return fnmatch.fnmatch( self.spec, spec )
+ def match( self, *specs ):
+ for spec in specs:
+ if fnmatch.fnmatch( self.spec, spec ):
+ return True
+ return False
###############################################################################
super( BuildAction, self ).__init__( 'compute', 'build tuple', abort=True )
def _action( self ):
- self.spec = arch.mode[arch.mode.mode]
+ ## check if --cross spec was used; must maintain 5-tuple compatibility with regex
+ if options.cross:
+ self.spec = os.path.basename( options.cross ).rstrip( '-' )
+ else:
+ self.spec = arch.mode[arch.mode.mode]
## grok GNU host tuples
- m = re.match( HostTupleProbe.GNU_TUPLE_RX, self.spec )
+ m = re.match( HostTupleProbe.GNU_TUPLE_RE, self.spec )
if not m:
self.msg_end = 'invalid host tuple: %s' % (self.spec)
return
self.extra = self[4]
self.systemf = host.systemf
+ ## when cross we need switch for platforms
+ if options.cross:
+ if self.match( '*mingw*' ):
+ self.systemf = 'MinGW'
+ elif self.systemf:
+ self.systemf[0] = self.systemf[0].upper()
+ self.title = '%s %s' % (build.systemf,self.machine)
+ else:
+ self.title = '%s %s' % (build.systemf,arch.mode.mode)
self.fail = False
+ ## glob-match against spec
+ def match( self, *specs ):
+ for spec in specs:
+ if fnmatch.fnmatch( self.spec, spec ):
+ return True
+ return False
+
###############################################################################
##
-## platform conditional string; if specs do not match host:
+## value wrapper; value is accepted only if one of host specs matcheds
+## otherwise it is None (or a keyword-supplied val)
##
-## - str value is blank
-## - evaluates to False
+## result is attribute 'value'
##
class IfHost( object ):
- def __init__( self, value, *specs ):
- self.value = ''
+ def __init__( self, value, *specs, **kwargs ):
+ self.value = kwargs.get('none',None)
for spec in specs:
if host.match( spec ):
self.value = value
break
def __nonzero__( self ):
- return len(self.value) != 0
+ return self.value != None
def __str__( self ):
return self.value
+
###############################################################################
##
## platform conditional value; loops through list of tuples comparing
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)
+
+ ## special cases in that powerpc does not match gcc -arch value
+ ## which we like to use; so it has to be removed.
+ ## note: we don't know if apple will release Ssnow Leopad/ppc64 yet; just a guess.
+ if 'powerpc' in self.mode:
+ del self.mode['powerpc']
+ self.mode.mode = 'ppc'
+ elif 'powerpc64' in self.mode:
+ del self.mode['powerpc64']
+ self.mode.mode = 'ppc64'
elif host.match( '*-*-linux*' ):
pass
else:
self.mode = self.default
def cli_add_option( self, parser, option ):
- parser.add_option( '', option, default=self.mode, metavar='MODE',
+ 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' )
self.vpoint = 4
def _action( self ):
- appcastfmt = 'http://handbrake.fr/appcast%s.xml'
+ ## add architecture to URL only for Mac
+ if fnmatch.fnmatch( build.spec, '*-*-darwin*' ):
+ url_arch = '.%s' % (arch.mode.mode)
+ else:
+ url_arch = ''
if repo.type == 'release':
self.version = '%d.%d.%d' % (self.vmajor,self.vminor,self.vpoint)
- self.url_appcast = appcastfmt % ('')
+ url_ctype = ''
+ url_ntype = 'stable'
self.build = time.strftime('%Y%m%d') + '00'
self.title = '%s %s (%s)' % (self.name,self.version,self.build)
elif repo.type == 'developer':
self.version = 'svn%d' % (repo.rev)
- self.url_appcast = appcastfmt % ('_unstable')
+ url_ctype = '_unstable'
+ url_ntype = 'unstable'
self.build = time.strftime('%Y%m%d') + '01'
self.title = '%s svn%d (%s)' % (self.name,repo.rev,self.build)
else:
- self.version = 'svn%d' % (repo.rev)
- self.url_appcast = appcastfmt % ('_unofficial')
+ self.version = 'rev%d' % (repo.rev)
+ url_ctype = '_unofficial'
+ url_ntype = 'unofficial'
self.build = time.strftime('%Y%m%d') + '99'
- self.title = 'Unofficial svn%d (%s)' % (repo.rev,self.build)
+ self.title = '%s rev%d (%s)' % (self.name,repo.rev,self.build)
+
+ self.url_appcast = 'http://handbrake.fr/appcast%s%s.xml' % (url_ctype,url_arch)
+ self.url_appnote = 'http://handbrake.fr/appcast/%s.html' % (url_ntype)
self.msg_end = '%s (%s)' % (self.name,repo.type)
self.fail = False
self.msg_end = 'not found'
def cli_add_option( self, parser ):
- parser.add_option( '', '--'+self.name, metavar='PROG',
+ parser.add_option( '--'+self.name, metavar='PROG',
help='[%s]' % (self.pathname),
action='callback', callback=self.cli_callback, type='str' )
self.msg_end = 'not found'
def cli_add_option( self, parser ):
- parser.add_option( '', '--'+self.name, metavar='MODE',
+ 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 __init__( self ):
self._elements = []
- def _outputMake( self, file, namelen, name, value ):
- file.write( '%-*s = %s\n' % (namelen, name, value ))
+ def _outputMake( self, file, namelen, name, value, append ):
+ if append:
+ if value == None or len(str(value)) == 0:
+ file.write( '%-*s +=\n' % (namelen, name) )
+ else:
+ file.write( '%-*s += %s\n' % (namelen, name, value) )
+ else:
+ if value == None or len(str(value)) == 0:
+ file.write( '%-*s =\n' % (namelen, name) )
+ else:
+ 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._elements.append( (name,value) )
+ def add( self, name, value, append=False ):
+ self._elements.append( [name,value,append] )
def addBlank( self ):
self._elements.append( None )
if type == 'm4':
self._outputM4( file, namelen, item[0], item[1] )
else:
- self._outputMake( file, namelen, item[0], item[1] )
+ self._outputMake( file, namelen, item[0], item[1], item[2] )
+
+ def update( self, name, value ):
+ for item in self._elements:
+ if item == None:
+ continue
+ if item[0] == name:
+ item[1] = value
+ return
+ raise ValueError( 'element not found: %s' % (name) )
def write( self, type ):
if type == 'make':
##
## create cli parser
##
+
+## class to hook options and create CONF.args list
+class Option( optparse.Option ):
+ conf_args = []
+
+ def _conf_record( self, opt, value ):
+ ## skip conf,force,launch
+ if re.match( '^--(conf|force|launch).*$', opt ):
+ return
+
+ ## remove duplicates (last duplicate wins)
+ for i,arg in enumerate( Option.conf_args ):
+ if opt == arg[0]:
+ del Option.conf_args[i]
+ break
+
+ if value:
+ Option.conf_args.append( [opt,'%s=%s' % (opt,value)] )
+ else:
+ Option.conf_args.append( [opt,'%s' % (opt)] )
+
+ def take_action( self, action, dest, opt, value, values, parser ):
+ self._conf_record( opt, value )
+ return optparse.Option.take_action( self, action, dest, opt, value, values, parser )
+
def createCLI():
cli = OptionParser( 'usage: %prog [OPTIONS...] [TARGETS...]' )
+ cli.option_class = Option
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' )
+ 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',
+ 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',
+ 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',
+ 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 )
+
+ h = IfHost( 'enable assembly code in non-contrib modules', 'NOMATCH*-*-darwin*', 'NOMATCH*-*-linux*', none=optparse.SUPPRESS_HELP ).value
+ grp.add_option( '--enable-asm', default=False, action='store_true', help=h )
+
+ h = IfHost( 'disable GTK GUI', '*-*-linux*', none=optparse.SUPPRESS_HELP ).value
+ grp.add_option( '--disable-gtk', default=False, action='store_true', help=h )
+ h = IfHost( 'enable GTK GUI (mingw)', '*-*-mingw*', none=optparse.SUPPRESS_HELP ).value
+ grp.add_option( '--enable-gtk-mingw', default=False, action='store_true', help=h )
+
+ h = IfHost( 'disable Xcode', '*-*-darwin*', none=optparse.SUPPRESS_HELP ).value
+ grp.add_option( '--disable-xcode', 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',
+ 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',
+ 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',
+ 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' )
+ grp.add_option( '--launch-quiet', default=False, action='store_true',
+ help='do not echo build output while waiting' )
cli.add_option_group( grp )
## add compile options
debugMode.cli_add_option( grp, '--debug' )
optimizeMode.cli_add_option( grp, '--optimize' )
arch.mode.cli_add_option( grp, '--arch' )
+ grp.add_option( '--cross', default=None, action='store', metavar='SPEC',
+ help='specify GCC cross-compilation spec' )
cli.add_option_group( grp )
## add tool locations
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*') )
+ 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 )
+ m4 = ToolProbe( 'M4.exe', 'm4' )
+ mkdir = ToolProbe( 'MKDIR.exe', 'mkdir' )
+ patch = ToolProbe( 'PATCH.exe', 'gpatch', 'patch' )
+ rm = ToolProbe( 'RM.exe', 'rm' )
+ ranlib = ToolProbe( 'RANLIB.exe', 'ranlib' )
+ strip = ToolProbe( 'STRIP.exe', 'strip' )
+ tar = ToolProbe( 'TAR.exe', 'gtar', 'tar' )
+ wget = ToolProbe( 'WGET.exe', 'wget', abort=False )
+ yasm = ToolProbe( 'YASM.exe', 'yasm', abort=False )
xcodebuild = ToolProbe( 'XCODEBUILD.exe', 'xcodebuild', abort=False )
lipo = ToolProbe( 'LIPO.exe', 'lipo', abort=False )
else:
targets.append( arg )
+ ## re-run tools with cross-compilation needs
+ if options.cross:
+ for tool in ( Tools.ar, Tools.gcc, Tools.ranlib, Tools.strip ):
+ tool.__init__( tool.var, '%s-%s' % (options.cross,tool.name), **tool.kwargs )
+ tool.run()
+
## run delayed actions
for action in Action.actions:
action.run()
## 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))) )
+ for arg in Option.conf_args:
+ args.append( arg[1] )
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.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.url.appnote', project.url_appnote )
doc.add( 'HB.version.major', project.vmajor )
doc.add( 'HB.version.minor', project.vminor )
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.title', build.title )
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.add( 'BUILD.cross', int(options.cross != None or arch.mode.mode != arch.mode.default) )
+ if options.cross:
+ doc.add( 'BUILD.cross.prefix', '%s-' % (options.cross) )
+ else:
+ doc.add( 'BUILD.cross.prefix', '' )
+
+ 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.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.asm', 'disabled' )
doc.add( 'FEATURE.gtk', int( not options.disable_gtk ))
+ doc.add( 'FEATURE.gtk.mingw', int( options.enable_gtk_mingw ))
+ doc.add( 'FEATURE.xcode', int( not (Tools.xcodebuild.fail or options.disable_xcode or options.cross) ))
if not Tools.xcodebuild.fail and not options.disable_xcode:
doc.addBlank()
doc.add( 'GCC.g', debugMode.mode )
doc.add( 'GCC.O', optimizeMode.mode )
+ if options.enable_asm and not Tools.yasm.fail:
+ asm = ''
+ if build.match( 'i?86-*' ):
+ asm = 'x86'
+ doc.add( 'LIBHB.GCC.D', 'HAVE_MMX', append=True )
+ doc.add( 'LIBHB.YASM.D', 'ARCH_X86', append=True )
+ if build.match( '*-*-darwin*' ):
+ doc.add( 'LIBHB.YASM.f', 'macho32' )
+ else:
+ doc.add( 'LIBHB.YASM.f', 'elf32' )
+ doc.add( 'LIBHB.YASM.m', 'x86' )
+ elif build.match( 'x86_64-*' ):
+ asm = 'x86'
+ doc.add( 'LIBHB.GCC.D', 'HAVE_MMX ARCH_X86_64', append=True )
+ if build.match( '*-*-darwin*' ):
+ doc.add( 'LIBHB.YASM.D', 'ARCH_X86_64 PIC', append=True )
+ doc.add( 'LIBHB.YASM.f', 'macho64' )
+ else:
+ doc.add( 'LIBHB.YASM.D', 'ARCH_X86_64', append=True )
+ doc.add( 'LIBHB.YASM.f', 'elf64' )
+ doc.add( 'LIBHB.YASM.m', 'amd64' )
+ doc.update( 'FEATURE.asm', asm )
+
## add exports to make
if len(exports):
doc.addBlank()