self.src_dir = os.path.normpath( options.src )
self.build_dir = os.path.normpath( options.build )
self.prefix_dir = os.path.normpath( options.prefix )
+ if options.sysroot != None:
+ self.sysroot_dir = os.path.normpath( options.sysroot )
+ else:
+ self.sysroot_dir = ""
+
+ if options.minver != None:
+ self.minver = options.minver
+ else:
+ self.minver = ""
## special case if src == build: add build subdir
if os.path.abspath( self.src_dir ) == os.path.abspath( self.build_dir ):
###############################################################################
##
+## Compile test probe: determine if compile time feature is supported
+##
+## returns true if feature successfully compiles
+##
+##
+class CCProbe( Action ):
+ def __init__( self, pretext, command, test_file ):
+ super( CCProbe, self ).__init__( 'probe', pretext )
+ self.command = command
+ self.test_file = test_file
+
+ def _action( self ):
+ ## write program file
+ file = open( 'conftest.c', 'w' )
+ file.write( self.test_file )
+ file.close()
+ ## pipe and redirect stderr to stdout; effects communicate result
+ pipe = subprocess.Popen( '%s -c -o conftest.o conftest.c' % self.command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
+
+ ## 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 = []
+
+ if pipe.returncode:
+ self.msg_end = 'code %d' % (pipe.returncode)
+ os.remove( 'conftest.c' )
+ if not self.fail:
+ os.remove( 'conftest.o' )
+
+ def _dumpSession( self, printf ):
+ printf( ' + %s\n', self.command )
+ super( CCProbe, self )._dumpSession( printf )
+
+
+###############################################################################
+##
+## Compile test probe: determine if compile time feature is supported
+##
+## returns true if feature successfully compiles
+##
+##
+class LDProbe( Action ):
+ def __init__( self, pretext, command, lib, test_file ):
+ super( LDProbe, self ).__init__( 'probe', pretext )
+ self.command = command
+ self.test_file = test_file
+ self.lib = lib
+
+ def _action( self ):
+ ## write program file
+ file = open( 'conftest.c', 'w' )
+ file.write( self.test_file )
+ file.close()
+ ## pipe and redirect stderr to stdout; effects communicate result
+ pipe = subprocess.Popen( '%s -o conftest conftest.c %s' % (self.command, self.lib), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
+
+ ## 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 = []
+
+ if pipe.returncode:
+ self.msg_end = 'code %d' % (pipe.returncode)
+
+ os.remove( 'conftest.c' )
+ if not self.fail:
+ os.remove( 'conftest' )
+
+ def _dumpSession( self, printf ):
+ printf( ' + %s\n', self.command )
+ super( LDProbe, self )._dumpSession( printf )
+
+
+###############################################################################
+##
## GNU host tuple probe: determine canonical platform type
##
## example results from various platforms:
## 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)
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
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' )
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 )):
+ if m and re.match( '.*tags/.*', m.group( 3 )):
self.type = 'release'
else:
self.type = 'developer'
self.vmajor = 0
self.vminor = 9
- self.vpoint = 4
+ self.vpoint = 5
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 _outputMake( self, file, namelen, name, value, append ):
if append:
- file.write( '%-*s += %s\n' % (namelen, name, value ))
+ if value == None or len(str(value)) == 0:
+ file.write( '%-*s +=\n' % (namelen, name) )
+ else:
+ file.write( '%-*s += %s\n' % (namelen, name, value) )
else:
- file.write( '%-*s = %s\n' % (namelen, name, value ))
+ 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
##
## 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',
+ h = IfHost( 'specify sysroot (e.g. for Leopard builds from Snow Leapard)', '*-*-darwin*', none=optparse.SUPPRESS_HELP ).value
+ grp.add_option( '--sysroot', default=None, action='store', metavar='DIR',
+ help=h )
+ 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 )
grp = OptionGroup( cli, 'Feature Options' )
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 )
+ 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 )
+ grp.add_option( '--disable-gtk', default=False, action='store_true', help=h )
+ h = IfHost( 'disable GTK GUI update checks', '*-*-linux*', none=optparse.SUPPRESS_HELP ).value
+ grp.add_option( '--disable-gtk-update-checks', 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 )
+ 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',
+ grp.add_option( '--launch-quiet', default=False, action='store_true',
help='do not echo build output while waiting' )
cli.add_option_group( grp )
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' )
+ h = IfHost( 'Min OS X Version', '*-*-darwin*', none=optparse.SUPPRESS_HELP ).value
+ grp.add_option( '--minver', default=None, action='store', metavar='VER',
+ help=h )
cli.add_option_group( grp )
## add tool locations
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 )
- yasm = ToolProbe( 'YASM.exe', 'yasm', 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()
+ if build.system == 'mingw':
+ dlfcn_test = """
+#include <dlfcn.h>
+#include <stdio.h>
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, RTLD_GLOBAL|RTLD_NOW);
+ int status = 1;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = 0;
+ else if (dlsym( self,"_fnord")) status = 0;
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ return status;
+}
+"""
+ dlfcn = LDProbe( 'static dlfcn', '%s -static' % Tools.gcc.pathname, '-ldl', dlfcn_test )
+ dlfcn.run()
+
+ pthread_test = """
+#include <stdio.h>
+#include <pthread.h>
+int main ()
+{
+ pthread_t thread;
+ pthread_create (&thread, NULL, NULL, NULL);
+ return 0;
+}
+"""
+ pthread = LDProbe( 'static pthread', '%s -static' % Tools.gcc.pathname, '-lpthreadGC2', pthread_test )
+ pthread.run()
+
+ bz2_test = """
+#include <stdio.h>
+#include <bzlib.h>
+int main ()
+{
+ BZ2_bzReadOpen(NULL, NULL, 0, 0, NULL, 0);
+ return 0;
+}
+"""
+ bz2 = LDProbe( 'static bz2', '%s -static' % Tools.gcc.pathname, '-lbz2', bz2_test )
+ bz2.run()
+
+ libz_test = """
+#include <stdio.h>
+#include <zlib.h>
+int main ()
+{
+ compress(NULL, NULL, NULL, 0);
+ return 0;
+}
+"""
+ libz = LDProbe( 'static zlib', '%s -static' % Tools.gcc.pathname, '-lz', libz_test )
+ libz.run()
+
+ iconv_test = """
+#include <stdio.h>
+#include <iconv.h>
+int main ()
+{
+ iconv_open(NULL, NULL);
+ return 0;
+}
+"""
+ iconv = LDProbe( 'static iconv', '%s -static' % Tools.gcc.pathname, '-liconv', iconv_test )
+ iconv.run()
+
## cfg hook before doc prep
cfg.doc_ready()
## add configure line for reconfigure purposes
doc.addBlank()
args = []
- for arg in sys.argv[1:]:
- if arg == '--launch':
- continue
- args.append( arg )
+ 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.addBlank()
doc.add( 'FEATURE.asm', 'disabled' )
doc.add( 'FEATURE.gtk', int( not options.disable_gtk ))
- doc.add( 'FEATURE.xcode', int( not (Tools.xcodebuild.fail or options.disable_xcode) ))
+ doc.add( 'FEATURE.gtk.update.checks', int( not options.disable_gtk_update_checks ))
+ 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( 'XCODE.external.build', cfg.xcode_x_build )
doc.add( 'XCODE.external.prefix', cfg.xcode_x_prefix )
+ doc.addBlank()
+ if build.system == 'mingw':
+ if not dlfcn.fail:
+ doc.add( 'HAS.dlfcn', 1 )
+ if not pthread.fail:
+ doc.add( 'HAS.pthread', 1 )
+ if not bz2.fail:
+ doc.add( 'HAS.bz2', 1 )
+ if not libz.fail:
+ doc.add( 'HAS.libz', 1 )
+ if not iconv.fail:
+ doc.add( 'HAS.iconv', 1 )
+
doc.addMake( '' )
+ doc.addMake( '## define debug mode before other includes' )
+ doc.addMake( '## since it is tested in some module.defs' )
+ doc.add( 'GCC.g', debugMode.mode )
+ doc.addBlank()
doc.addMake( '## include definitions' )
doc.addMake( 'include $(SRC/)make/include/main.defs' )
select.doc_add( doc )
doc.addBlank()
- if arch.mode.mode != arch.mode.default:
+ if build.match( '*-*-darwin*' ):
doc.add( 'GCC.archs', arch.mode.mode )
+ doc.add( 'GCC.sysroot', cfg.sysroot_dir )
+ doc.add( 'GCC.minver', cfg.minver )
else:
doc.add( 'GCC.archs', '' )
- doc.add( 'GCC.g', debugMode.mode )
+ doc.add( 'GCC.sysroot', '' )
+ doc.add( 'GCC.minver', '' )
+ doc.add( 'GCC.ldsysroot', '$(GCC.sysroot)' )
+ doc.add( 'GCC.ldminver', '$(GCC.minver)' )
doc.add( 'GCC.O', optimizeMode.mode )
if options.enable_asm and not Tools.yasm.fail: