2006-12-19 02:25:50 +00:00
#SConstruct
# needed imports
2013-11-16 22:59:17 +00:00
import binascii
2014-07-26 17:40:12 +00:00
import errno
2013-11-16 22:59:17 +00:00
import subprocess
2006-12-19 02:25:50 +00:00
import sys
import os
2007-05-22 01:20:06 +00:00
import SCons . Util
2006-12-19 02:25:50 +00:00
2013-06-16 19:28:38 +00:00
def message ( program , msg ) :
print " %s : %s " % ( program . program_message_prefix , msg )
2013-02-25 00:02:01 +00:00
# endianess-checker
def checkEndian ( ) :
2013-03-23 02:46:45 +00:00
if ARGUMENTS . has_key ( ' endian ' ) :
r = ARGUMENTS [ ' endian ' ]
if r == " little " or r == " big " :
return r
raise SCons . Errors . UserError ( " Unknown endian value: %s " % r )
2013-02-25 00:02:01 +00:00
import struct
array = struct . pack ( ' cccc ' , ' \x01 ' , ' \x02 ' , ' \x03 ' , ' \x04 ' )
i = struct . unpack ( ' i ' , array )
if i == struct . unpack ( ' <i ' , array ) :
return " little "
elif i == struct . unpack ( ' >i ' , array ) :
return " big "
return " unknown "
2006-12-19 02:25:50 +00:00
2014-09-17 02:09:53 +00:00
def get_Werror_string ( l ) :
2014-09-27 00:32:22 +00:00
if l and ' -Werror ' in l :
2014-09-17 02:09:53 +00:00
return ' -W '
return ' -Werror= '
2013-06-27 02:35:22 +00:00
class ConfigureTests :
class Collector :
def __init__ ( self ) :
self . tests = [ ]
def __call__ ( self , f ) :
self . tests . append ( f . __name__ )
return f
2013-12-05 21:55:29 +00:00
class PreservedEnvironment :
def __init__ ( self , env , keys ) :
2014-01-04 17:44:04 +00:00
self . flags = { k : env . get ( k , [ ] ) [ : ] for k in keys }
2015-01-03 23:44:32 +00:00
# Do not distribute tests when run under ccache
# Assume distcc users also use ccache. Harmless when wrong,
# saves a bit of latency when right.
self . CCACHE_PREFIX = env [ ' ENV ' ] . pop ( ' CCACHE_PREFIX ' , None )
2013-12-05 21:55:29 +00:00
def restore ( self , env ) :
env . Replace ( * * self . flags )
2015-01-03 23:44:32 +00:00
if self . CCACHE_PREFIX :
env [ ' ENV ' ] [ ' CCACHE_PREFIX ' ] = CCACHE_PREFIX
2013-12-05 21:55:29 +00:00
def __getitem__ ( self , key ) :
return self . flags . __getitem__ ( key )
class ForceVerboseLog :
def __init__ ( self , env ) :
# Force verbose output to sconf.log
self . cc_env_strings = { }
for k in [ ' CXXCOMSTR ' ] :
try :
self . cc_env_strings [ k ] = env [ k ]
del env [ k ]
except KeyError :
pass
def restore ( self , env ) :
# Restore potential quiet build options
env . Replace ( * * self . cc_env_strings )
2014-07-19 22:25:27 +00:00
# Force test to report failure
sconf_force_failure = ' force-failure '
# Force test to report success, and modify flags like it
# succeeded
sconf_force_success = ' force-success '
# Force test to report success, do not modify flags
sconf_assume_success = ' assume-success '
2013-06-27 02:35:22 +00:00
_implicit_test = Collector ( )
_custom_test = Collector ( )
implicit_tests = _implicit_test . tests
custom_tests = _custom_test . tests
comment_not_supported = ' /* not supported */ '
2013-11-26 03:59:44 +00:00
__flags_Werror = { k : [ ' -Werror ' ] for k in [ ' CXXFLAGS ' ] }
2014-06-21 17:54:02 +00:00
_cxx_conformance_cxx11 = 11
2014-06-01 20:49:07 +00:00
_cxx_conformance_cxx14 = 14
2013-06-27 02:35:22 +00:00
def __init__ ( self , msgprefix , user_settings ) :
self . msgprefix = msgprefix
self . user_settings = user_settings
2013-11-09 17:22:11 +00:00
self . successful_flags = { }
2014-06-21 17:54:02 +00:00
self . __cxx_conformance = None
2013-06-27 02:35:22 +00:00
self . __automatic_compiler_tests = {
2013-11-09 23:01:38 +00:00
' .cpp ' : self . check_cxx_works ,
2013-06-27 02:35:22 +00:00
}
@classmethod
def describe ( cls , name ) :
f = getattr ( cls , name )
if f . __doc__ :
lines = f . __doc__ . rstrip ( ) . split ( ' \n ' )
if lines [ - 1 ] . startswith ( " help: " ) :
return lines [ - 1 ] [ 5 : ]
return None
2014-07-19 17:34:02 +00:00
@staticmethod
def _quote_macro_value ( v ) :
return v . strip ( ) . replace ( ' \n ' , ' \\ \n ' )
2013-06-27 02:35:22 +00:00
def _check_forced ( self , context , name ) :
return getattr ( self . user_settings , ' sconf_ %s ' % name )
def _check_macro ( self , context , macro_name , macro_value , test , * * kwargs ) :
2014-07-19 17:34:02 +00:00
macro_value = self . _quote_macro_value ( macro_value )
2013-06-27 02:35:22 +00:00
r = self . Compile ( context , text = """
#define {macro_name} {macro_value}
{ test }
""" .format(macro_name=macro_name, macro_value=macro_value, test=test), **kwargs)
if r :
context . sconf . Define ( macro_name , macro_value )
else :
context . sconf . Define ( macro_name , self . comment_not_supported )
def __compiler_test_already_done ( self , context ) :
pass
2013-12-05 21:55:29 +00:00
def _check_compiler_works ( self , context , ext ) :
2013-06-27 02:35:22 +00:00
self . __automatic_compiler_tests . pop ( ext , self . __compiler_test_already_done ) ( context )
2013-12-05 23:39:50 +00:00
def _extend_successflags ( self , k , v ) :
self . successful_flags . setdefault ( k , [ ] ) . extend ( v )
2013-12-05 21:55:29 +00:00
def Compile ( self , context , * * kwargs ) :
2014-06-29 23:26:05 +00:00
if self . user_settings . lto :
self . Compile = self . Link
return self . Link ( context , * * kwargs )
2013-12-05 21:55:29 +00:00
return self . _Test ( context , action = context . TryCompile , * * kwargs )
2013-12-05 22:47:43 +00:00
def Link ( self , context , * * kwargs ) :
return self . _Test ( context , action = context . TryLink , * * kwargs )
2014-09-27 23:14:50 +00:00
def _Test ( self , context , text , msg , action , main = ' ' , ext = ' .cpp ' , testflags = { } , successflags = { } , skipped = None , successmsg = None , failuremsg = None , expect_failure = False ) :
2013-12-05 21:55:29 +00:00
self . _check_compiler_works ( context , ext )
2013-06-27 02:35:22 +00:00
context . Message ( ' %s : checking %s ... ' % ( self . msgprefix , msg ) )
if skipped is not None :
context . Result ( ' (skipped) {skipped} ' . format ( skipped = skipped ) )
return
2014-09-17 02:11:43 +00:00
env_flags = self . PreservedEnvironment ( context . env , successflags . keys ( ) + testflags . keys ( ) + self . __flags_Werror . keys ( ) + [ ' CPPDEFINES ' ] )
2013-11-28 04:21:20 +00:00
context . env . Append ( * * successflags )
2013-06-27 02:35:22 +00:00
frame = None
2014-06-30 03:26:49 +00:00
forced = None
2013-06-27 02:35:22 +00:00
try :
1 / / 0
except ZeroDivisionError :
frame = sys . exc_info ( ) [ 2 ] . tb_frame . f_back
while frame is not None :
co_name = frame . f_code . co_name
if co_name [ 0 : 6 ] == ' check_ ' :
forced = self . _check_forced ( context , co_name [ 6 : ] )
break
frame = frame . f_back
2013-12-05 21:55:29 +00:00
caller_modified_env_flags = self . PreservedEnvironment ( context . env , self . __flags_Werror . keys ( ) + testflags . keys ( ) )
2013-06-27 02:35:22 +00:00
# Always pass -Werror
context . env . Append ( * * self . __flags_Werror )
2013-11-26 05:03:00 +00:00
context . env . Append ( * * testflags )
2014-06-30 03:26:49 +00:00
if forced is None :
cc_env_strings = self . ForceVerboseLog ( context . env )
2015-01-03 23:44:32 +00:00
undef_SDL_main = ' \n #undef main /* avoid -Dmain=SDL_main from libSDL */ \n '
r = action ( text + undef_SDL_main + ' int main(int argc,char**argv) { (void)argc;(void)argv; ' + main + ' ;} \n ' , ext )
2014-06-30 03:26:49 +00:00
if expect_failure :
r = not r
cc_env_strings . restore ( context . env )
context . Result ( ( successmsg if r else failuremsg ) or r )
else :
2014-07-19 22:25:27 +00:00
choices = ( self . sconf_force_failure , self . sconf_force_success , self . sconf_assume_success )
if forced not in choices :
try :
forced = choices [ int ( forced ) ]
except ValueError :
raise SCons . Errors . UserError ( " Unknown force value for sconf_ %s : %s " % ( co_name [ 6 : ] , forced ) )
except IndexError :
raise SCons . Errors . UserError ( " Out of range force value for sconf_ %s : %s " % ( co_name [ 6 : ] , forced ) )
if forced == self . sconf_force_failure :
r = False
elif forced == self . sconf_force_success or forced == self . sconf_assume_success :
r = True
else :
raise SCons . Errors . UserError ( " Unknown force value for sconf_ %s : %s " % ( co_name [ 6 : ] , forced ) )
2014-06-30 03:26:49 +00:00
if expect_failure :
2014-07-19 22:25:27 +00:00
r = not r
context . Result ( ' (forced) {inverted} {forced} ' . format ( forced = forced , inverted = ' (inverted) ' if expect_failure else ' ' ) )
2013-06-27 02:35:22 +00:00
# On success, revert to base flags + successflags
# On failure, revert to base flags
2014-07-19 22:25:27 +00:00
if r and forced != self . sconf_assume_success :
2013-12-05 21:55:29 +00:00
caller_modified_env_flags . restore ( context . env )
2013-12-04 21:47:42 +00:00
context . env . Replace ( CPPDEFINES = env_flags [ ' CPPDEFINES ' ] )
2015-03-22 18:49:21 +00:00
CPPDEFINES = [ ]
for v in successflags . pop ( ' CPPDEFINES ' , [ ] ) :
d = v
2013-12-04 21:47:42 +00:00
if isinstance ( d , str ) :
d = ( d , None )
2015-03-22 18:49:21 +00:00
if d [ 0 ] in ( ' _REENTRANT ' , ) :
# Blacklist defines that must not be moved to the
# configuration header.
CPPDEFINES . append ( v )
continue
2013-12-04 21:47:42 +00:00
context . sconf . Define ( d [ 0 ] , d [ 1 ] )
2015-03-22 18:49:21 +00:00
successflags [ ' CPPDEFINES ' ] = CPPDEFINES
2013-11-09 17:22:11 +00:00
for ( k , v ) in successflags . items ( ) :
2013-12-05 23:39:50 +00:00
self . _extend_successflags ( k , v )
2013-06-27 02:35:22 +00:00
else :
2013-12-05 21:55:29 +00:00
env_flags . restore ( context . env )
2013-06-27 02:35:22 +00:00
return r
2013-12-05 22:47:43 +00:00
def _check_system_library ( self , context , header , main , lib , successflags = { } ) :
include = ' \n ' . join ( [ ' #include < %s > ' % h for h in header ] )
# Test library. On success, good. On failure, test header to
# give the user more help.
2014-09-27 23:14:50 +00:00
if self . Link ( context , text = include , main = main , msg = ' for usable library ' + lib , successflags = successflags ) :
2013-12-05 22:47:43 +00:00
return
2014-09-27 23:14:50 +00:00
if self . Compile ( context , text = include , main = main , msg = ' for usable header ' + header [ - 1 ] ) :
2013-12-05 22:47:43 +00:00
raise SCons . Errors . StopError ( " Header %s is usable, but library %s is not usable. " % ( header [ - 1 ] , lib ) )
2014-09-27 23:14:50 +00:00
if self . Compile ( context , text = include , main = main , msg = ' for parseable header ' + header [ - 1 ] ) :
2013-12-05 22:47:43 +00:00
raise SCons . Errors . StopError ( " Header %s is parseable, but cannot compile the test program. " % ( header [ - 1 ] ) )
raise SCons . Errors . StopError ( " Header %s is missing or unusable. " % ( header [ - 1 ] ) )
@_custom_test
def check_libphysfs ( self , context ) :
self . _check_system_library ( context , header = [ ' physfs.h ' ] , main = '''
PHYSFS_File * f ;
char b [ 1 ] = { 0 } ;
PHYSFS_init ( " " ) ;
f = PHYSFS_openWrite ( " a " ) ;
PHYSFS_sint64 w = PHYSFS_write ( f , b , 1 , 1 ) ;
( void ) w ;
PHYSFS_close ( f ) ;
f = PHYSFS_openRead ( " a " ) ;
PHYSFS_sint64 r = PHYSFS_read ( f , b , 1 , 1 ) ;
( void ) r ;
PHYSFS_close ( f ) ;
''' ,
2015-01-03 23:44:32 +00:00
lib = ' physfs ' ,
successflags = { ' LIBS ' : ( ' physfs ' , ) }
2013-12-05 22:47:43 +00:00
)
2013-12-05 23:39:50 +00:00
@_custom_test
2015-01-03 23:44:32 +00:00
def check_libSDL ( self , context ) :
self . _check_system_library ( context , header = [ ' SDL.h ' ] , main = '''
SDL_RWops * ops = reinterpret_cast < SDL_RWops * > ( argv ) ;
SDL_Init ( SDL_INIT_JOYSTICK | SDL_INIT_CDROM | SDL_INIT_VIDEO | SDL_INIT_AUDIO ) ;
SDL_QuitSubSystem ( SDL_INIT_CDROM ) ;
SDL_FreeRW ( ops ) ;
SDL_Quit ( ) ;
''' ,
lib = ' SDL '
)
@_custom_test
2013-12-05 23:39:50 +00:00
def check_SDL_mixer ( self , context ) :
msg = ' whether to use SDL_mixer '
context . Display ( ' %s : checking %s ... ' % ( self . msgprefix , msg ) )
# SDL_mixer support?
context . Result ( self . user_settings . sdlmixer )
if not self . user_settings . sdlmixer :
return
self . _extend_successflags ( ' CPPDEFINES ' , [ ' USE_SDLMIXER ' ] )
successflags = { }
if self . user_settings . host_platform == ' darwin ' :
successflags [ ' FRAMEWORKS ' ] = [ ' SDL_mixer ' ]
2014-12-03 23:12:59 +00:00
successflags [ ' CPPPATH ' ] = [ os . path . join ( os . getenv ( " HOME " ) , ' Library/Frameworks/SDL_mixer.framework/Headers ' ) , ' /Library/Frameworks/SDL_mixer.framework/Headers ' ]
self . _check_system_library ( context , header = [ ' SDL_mixer.h ' ] , main = '''
2013-12-05 23:39:50 +00:00
int i = Mix_Init ( MIX_INIT_FLAC | MIX_INIT_OGG ) ;
( void ) i ;
Mix_Pause ( 0 ) ;
Mix_ResumeMusic ( ) ;
Mix_Quit ( ) ;
''' ,
lib = ' SDL_mixer ' , successflags = successflags )
2013-06-27 02:35:22 +00:00
@_implicit_test
2013-11-09 23:01:38 +00:00
def check_cxx_works ( self , context ) :
"""
help : assume C + + compiler works
"""
2014-09-27 23:14:50 +00:00
if self . Link ( context , text = ' ' , msg = ' whether C++ compiler and linker work ' ) :
2014-08-12 02:31:31 +00:00
return
2014-09-27 23:14:50 +00:00
if self . Compile ( context , text = ' ' , msg = ' whether C++ compiler works ' ) :
2014-08-12 02:31:31 +00:00
raise SCons . Errors . StopError ( " C++ compiler works, but C++ linker does not work. " )
raise SCons . Errors . StopError ( " C++ compiler does not work. " )
2013-06-27 02:35:22 +00:00
@_custom_test
2013-12-11 22:15:05 +00:00
def check_compiler_redundant_decl_warning ( self , context ) :
2014-09-17 02:09:53 +00:00
f = { ' CXXFLAGS ' : [ get_Werror_string ( context . env [ ' CXXFLAGS ' ] ) + ' redundant-decls ' ] }
2013-12-11 22:15:05 +00:00
# Test for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=15867
text = '''
template < typename >
struct A {
2014-09-27 23:14:50 +00:00
int a ( ) { return 0 ; }
2013-12-11 22:15:05 +00:00
} ;
template < >
2014-09-27 23:14:50 +00:00
int A < int > : : a ( ) { return 1 ; }
2013-12-11 22:15:05 +00:00
'''
2014-08-01 03:08:14 +00:00
if self . Compile ( context , text = text , msg = ' whether C++ compiler treats specializations as distinct ' , successflags = f ) :
return
2014-09-17 02:09:53 +00:00
if self . Compile ( context , text = ' int a();int a(); ' , msg = ' whether C++ compiler implements -Wredundant-decls ' , testflags = f , expect_failure = True ) :
2014-08-01 03:08:14 +00:00
return
2014-09-17 02:09:53 +00:00
self . Compile ( context , text = ' int a(); ' , msg = ' whether C++ compiler accepts -Wredundant-decls ' , testflags = f )
2013-12-11 22:15:05 +00:00
@_custom_test
2015-01-15 04:30:03 +00:00
def check_compiler_missing_field_initializers ( self , context ) :
f = { ' CXXFLAGS ' : [ get_Werror_string ( context . env [ ' CXXFLAGS ' ] ) + ' missing-field-initializers ' ] }
text = ' struct A { int a;}; '
main = ' A a {} ;(void)a; '
if not self . Cxx11Compile ( context , text = text , main = main , msg = ' whether C++ compiler warns for {} initialization ' , testflags = f , expect_failure = True ) or \
self . Cxx11Compile ( context , text = text , main = main , msg = ' whether C++ compiler understands -Wno-missing-field-initializers ' , successflags = { ' CXXFLAGS ' : [ ' -Wno-missing-field-initializers ' ] } ) or \
not self . Cxx11Compile ( context , text = text , main = main , msg = ' whether C++ compiler always errors for {} initialization ' , expect_failure = True ) :
return
raise SCons . Errors . StopError ( " C++ compiler errors on {} initialization, even with -Wno-missing-field-initializers " )
@_custom_test
2013-12-07 00:35:50 +00:00
def check_attribute_error ( self , context ) :
"""
help : assume compiler supports __attribute__ ( ( error ) )
"""
f = '''
void a ( ) __attribute__ ( ( __error__ ( " a called " ) ) ) ;
'''
2014-09-27 23:14:50 +00:00
if self . Compile ( context , text = f , main = ' if( " 0 " [0]== \' 1 \' )a(); ' , msg = ' whether compiler optimizes function __attribute__((__error__)) ' ) :
2013-12-07 00:35:50 +00:00
context . sconf . Define ( ' DXX_HAVE_ATTRIBUTE_ERROR ' )
context . sconf . Define ( ' __attribute_error(M) ' , ' __attribute__((__error__(M))) ' )
else :
2015-02-05 03:03:50 +00:00
self . Compile ( context , text = f , msg = ' whether compiler accepts function __attribute__((__error__)) ' ) and \
self . Compile ( context , text = f , main = ' a(); ' , msg = ' whether compiler understands function __attribute__((__error__)) ' , expect_failure = True )
2013-12-07 00:35:50 +00:00
context . sconf . Define ( ' __attribute_error(M) ' , self . comment_not_supported )
@_custom_test
2014-09-20 22:15:32 +00:00
def check_builtin_bswap ( self , context ) :
b = ' (void)__builtin_bswap {bits} (static_cast<uint {bits} _t>(argc)); '
2014-09-27 23:14:50 +00:00
include = '''
2014-09-20 22:15:32 +00:00
#include <cstdint>
2014-09-27 23:14:50 +00:00
'''
main = '''
2014-09-20 22:15:32 +00:00
{ b64 }
{ b32 }
#ifdef DXX_HAVE_BUILTIN_BSWAP16
{ b16 }
#endif
''' .format(
b64 = b . format ( bits = 64 ) ,
b32 = b . format ( bits = 32 ) ,
b16 = b . format ( bits = 16 ) ,
)
2014-09-27 23:14:50 +00:00
if self . Cxx11Compile ( context , text = include , main = main , msg = ' whether compiler implements __builtin_bswap { 16,32,64} functions ' , successflags = { ' CPPDEFINES ' : [ ' DXX_HAVE_BUILTIN_BSWAP ' , ' DXX_HAVE_BUILTIN_BSWAP16 ' ] } ) :
2014-09-20 22:15:32 +00:00
return
2014-09-27 23:14:50 +00:00
if self . Cxx11Compile ( context , text = include , main = main , msg = ' whether compiler implements __builtin_bswap { 32,64} functions ' , successflags = { ' CPPDEFINES ' : [ ' DXX_HAVE_BUILTIN_BSWAP ' ] } ) :
2014-09-20 22:15:32 +00:00
return
@_custom_test
2013-12-07 00:35:50 +00:00
def check_builtin_constant_p ( self , context ) :
"""
help : assume compiler supports compile - time __builtin_constant_p
"""
f = '''
int c ( int ) ;
2014-11-02 16:46:11 +00:00
static int a ( int b ) {
2013-12-07 00:35:50 +00:00
return __builtin_constant_p ( b ) ? 1 : % s ;
}
'''
2014-09-27 23:14:50 +00:00
main = ' return a(1) + a(2) '
if self . Link ( context , text = f % ' c(b) ' , main = main , msg = ' whether compiler optimizes __builtin_constant_p ' ) :
2013-12-07 00:35:50 +00:00
context . sconf . Define ( ' DXX_HAVE_BUILTIN_CONSTANT_P ' )
context . sconf . Define ( ' dxx_builtin_constant_p(A) ' , ' __builtin_constant_p(A) ' )
else :
2014-09-27 23:14:50 +00:00
self . Compile ( context , text = f % ' 2 ' , main = main , msg = ' whether compiler accepts __builtin_constant_p ' )
2013-12-07 00:35:50 +00:00
context . sconf . Define ( ' dxx_builtin_constant_p(A) ' , ' ((void)(A),0) ' )
@_custom_test
2015-01-12 00:26:03 +00:00
def check_builtin_expect ( self , context ) :
main = '''
return __builtin_expect ( argc == 1 , 1 ) ? 1 : 0 ;
'''
if self . Compile ( context , text = ' ' , main = main , msg = ' whether compiler accepts __builtin_expect ' ) :
context . sconf . Define ( ' likely(A) ' , ' __builtin_expect(!!(A), 1) ' )
context . sconf . Define ( ' unlikely(A) ' , ' __builtin_expect(!!(A), 0) ' )
else :
macro_value = ' (!!(A)) '
context . sconf . Define ( ' likely(A) ' , macro_value )
context . sconf . Define ( ' unlikely(A) ' , macro_value )
@_custom_test
2014-06-22 03:54:35 +00:00
def check_builtin_object_size ( self , context ) :
"""
help : assume compiler supports __builtin_object_size
"""
f = '''
int a ( ) ;
static inline int a ( char * c ) {
return __builtin_object_size ( c , 0 ) == 4 ? 1 : % s ;
}
2014-09-27 23:14:50 +00:00
'''
main = '''
2014-06-22 03:54:35 +00:00
char c [ 4 ] ;
return a ( c ) ;
'''
2014-09-27 23:14:50 +00:00
if self . Link ( context , text = f % ' a() ' , main = main , msg = ' whether compiler optimizes __builtin_object_size ' ) :
2014-06-22 03:54:35 +00:00
context . sconf . Define ( ' DXX_HAVE_BUILTIN_OBJECT_SIZE ' )
2014-08-01 03:08:14 +00:00
else :
2014-09-27 23:14:50 +00:00
self . Compile ( context , text = f % ' 2 ' , main = main , msg = ' whether compiler accepts __builtin_object_size ' )
2014-06-22 03:54:35 +00:00
@_custom_test
2014-07-31 02:44:14 +00:00
def check_embedded_compound_statement ( self , context ) :
f = '''
return ( { 1 + 2 ; } ) ;
'''
2014-09-27 23:14:50 +00:00
if self . Compile ( context , text = ' ' , main = f , msg = ' whether compiler understands embedded compound statements ' ) :
2014-07-31 02:44:14 +00:00
context . sconf . Define ( ' DXX_BEGIN_COMPOUND_STATEMENT ' , ' ' )
context . sconf . Define ( ' DXX_END_COMPOUND_STATEMENT ' , ' ' )
else :
context . sconf . Define ( ' DXX_BEGIN_COMPOUND_STATEMENT ' , ' [&] ' )
context . sconf . Define ( ' DXX_END_COMPOUND_STATEMENT ' , ' () ' )
context . sconf . Define ( ' DXX_ALWAYS_ERROR_FUNCTION(F,S) ' , r ' ( DXX_BEGIN_COMPOUND_STATEMENT { \
void F ( ) __attribute_error ( S ) ; \
F ( ) ; \
} DXX_END_COMPOUND_STATEMENT ) ' )
@_custom_test
2015-01-18 01:58:33 +00:00
def check_attribute_always_inline ( self , context ) :
"""
help : assume compiler supports __attribute__ ( ( always_inline ) )
"""
macro_name = ' __attribute_always_inline() '
macro_value = ' __attribute__((__always_inline__)) '
self . _check_macro ( context , macro_name = macro_name , macro_value = macro_value , test = macro_name + ' static inline void a() {} ' , main = ' a(); ' , msg = ' for function __attribute__((always_inline)) ' )
2015-01-25 05:32:45 +00:00
@_custom_test
2013-12-18 22:13:03 +00:00
def check_attribute_alloc_size ( self , context ) :
"""
help : assume compiler supports __attribute__ ( ( alloc_size ) )
"""
macro_name = ' __attribute_alloc_size(A,...) '
macro_value = ' __attribute__((alloc_size(A, ## __VA_ARGS__))) '
self . _check_macro ( context , macro_name = macro_name , macro_value = macro_value , test = """
char * a ( int ) __attribute_alloc_size ( 1 ) ;
char * b ( int , int ) __attribute_alloc_size ( 1 , 2 ) ;
""" , msg= ' for function __attribute__((alloc_size)) ' )
2014-12-24 03:34:33 +00:00
@_custom_test
def check_attribute_cold ( self , context ) :
"""
help : assume compiler supports __attribute__ ( ( cold ) )
"""
macro_name = ' __attribute_cold '
macro_value = ' __attribute__((cold)) '
self . _check_macro ( context , macro_name = macro_name , macro_value = macro_value , test = """
__attribute_cold char * a ( int ) ;
""" , msg= ' for function __attribute__((cold)) ' )
2013-12-18 22:13:03 +00:00
@_custom_test
2013-06-27 02:35:22 +00:00
def check_attribute_format_arg ( self , context ) :
"""
help : assume compiler supports __attribute__ ( ( format_arg ) )
"""
macro_name = ' __attribute_format_arg(A) '
macro_value = ' __attribute__((format_arg(A))) '
self . _check_macro ( context , macro_name = macro_name , macro_value = macro_value , test = """
char * a ( char * ) __attribute_format_arg ( 1 ) ;
""" , msg= ' for function __attribute__((format_arg)) ' )
2013-06-27 02:35:22 +00:00
@_custom_test
def check_attribute_format_printf ( self , context ) :
"""
help : assume compiler supports __attribute__ ( ( format ( printf ) ) )
"""
macro_name = ' __attribute_format_printf(A,B) '
macro_value = ' __attribute__((format(printf,A,B))) '
self . _check_macro ( context , macro_name = macro_name , macro_value = macro_value , test = """
int a ( char * , . . . ) __attribute_format_printf ( 1 , 2 ) ;
int b ( char * ) __attribute_format_printf ( 1 , 0 ) ;
""" , msg= ' for function __attribute__((format(printf))) ' )
2013-12-18 21:47:20 +00:00
@_custom_test
def check_attribute_malloc ( self , context ) :
"""
help : assume compiler supports __attribute__ ( ( malloc ) )
"""
macro_name = ' __attribute_malloc() '
macro_value = ' __attribute__((malloc)) '
self . _check_macro ( context , macro_name = macro_name , macro_value = macro_value , test = """
int * a ( ) __attribute_malloc ( ) ;
""" , msg= ' for function __attribute__((malloc)) ' )
2013-11-23 21:32:53 +00:00
@_custom_test
def check_attribute_nonnull ( self , context ) :
"""
help : assume compiler supports __attribute__ ( ( nonnull ) )
"""
macro_name = ' __attribute_nonnull(...) '
macro_value = ' __attribute__((nonnull __VA_ARGS__)) '
self . _check_macro ( context , macro_name = macro_name , macro_value = macro_value , test = """
int a ( int * ) __attribute_nonnull ( ) ;
int b ( int * ) __attribute_nonnull ( ( 1 ) ) ;
""" , msg= ' for function __attribute__((nonnull)) ' )
2013-10-27 22:13:04 +00:00
@_custom_test
def check_attribute_used ( self , context ) :
"""
help : assume compiler supports __attribute__ ( ( used ) )
"""
macro_name = ' __attribute_used '
macro_value = ' __attribute__((used)) '
self . _check_macro ( context , macro_name = macro_name , macro_value = macro_value , test = """
static void a ( ) __attribute_used ;
static void a ( ) { }
""" , msg= ' for function __attribute__((used)) ' )
2015-02-05 03:03:50 +00:00
@_custom_test
def check_attribute_unused ( self , context ) :
"""
help : assume compiler supports __attribute__ ( ( unused ) )
"""
macro_name = ' __attribute_unused '
macro_value = ' __attribute__((unused)) '
self . _check_macro ( context , macro_name = macro_name , macro_value = macro_value , test = """
__attribute_unused
static void a ( ) { }
""" , msg= ' for function __attribute__((unused)) ' )
2014-04-19 00:43:00 +00:00
@_custom_test
def check_attribute_warn_unused_result ( self , context ) :
"""
help : assume compiler supports __attribute__ ( ( warn_unused_result ) )
"""
macro_name = ' __attribute_warn_unused_result '
macro_value = ' __attribute__((warn_unused_result)) '
self . _check_macro ( context , macro_name = macro_name , macro_value = macro_value , test = """
int a ( ) __attribute_warn_unused_result ;
int a ( ) { return 0 ; }
""" , msg= ' for function __attribute__((warn_unused_result)) ' )
2013-11-09 23:01:38 +00:00
@_implicit_test
def check_cxx11 ( self , context ) :
"""
help : assume C + + compiler supports C + + 11
"""
2014-06-21 17:54:02 +00:00
return self . _check_cxx_std_flag ( context , ( ' -std=gnu++0x ' , ' -std=c++0x ' ) , self . _cxx_conformance_cxx11 )
2014-06-01 20:49:07 +00:00
@_implicit_test
def check_cxx14 ( self , context ) :
"""
help : assume C + + compiler supports C + + 14
"""
return self . _check_cxx_std_flag ( context , ( ' -std=gnu++14 ' , ' -std=c++14 ' ) , self . _cxx_conformance_cxx14 )
2014-06-21 17:54:02 +00:00
def _check_cxx_std_flag ( self , context , flags , level ) :
for f in flags :
2014-09-27 23:14:50 +00:00
r = self . Compile ( context , text = ' ' , msg = ' whether C++ compiler accepts {f} ' . format ( f = f ) , successflags = { ' CXXFLAGS ' : [ f ] } )
2013-11-09 23:01:38 +00:00
if r :
2014-06-21 17:54:02 +00:00
return level
return 0
def Cxx11Compile ( self , context , * args , * * kwargs ) :
kwargs . setdefault ( ' skipped ' , self . __skip_missing_cxx_std ( context , self . _cxx_conformance_cxx11 , ' no C++11 support ' ) )
return self . Compile ( context , * args , * * kwargs )
2014-06-01 20:49:07 +00:00
def Cxx14Compile ( self , context , * args , * * kwargs ) :
kwargs . setdefault ( ' skipped ' , self . __skip_missing_cxx_std ( context , self . _cxx_conformance_cxx14 , ' no C++14 support ' ) )
return self . Compile ( context , * args , * * kwargs )
2014-06-21 17:54:02 +00:00
def __skip_missing_cxx_std ( self , context , level , text ) :
if self . __cxx_conformance is None :
2014-06-01 20:49:07 +00:00
self . __cxx_conformance = self . check_cxx14 ( context ) or self . check_cxx11 ( context )
2014-06-21 17:54:02 +00:00
if self . __cxx_conformance < level :
return text
2013-11-09 23:01:38 +00:00
@_implicit_test
2014-09-27 23:14:50 +00:00
def check_boost_array ( self , context , * * kwargs ) :
2013-11-09 23:01:38 +00:00
"""
help : assume Boost . Array works
"""
2014-09-27 23:14:50 +00:00
return self . Compile ( context , msg = ' for Boost.Array ' , successflags = { ' CPPDEFINES ' : [ ' DXX_HAVE_BOOST_ARRAY ' ] } , * * kwargs )
2013-11-09 23:01:38 +00:00
@_implicit_test
2014-09-27 23:14:50 +00:00
def check_cxx_array ( self , context , * * kwargs ) :
2013-11-09 23:01:38 +00:00
"""
help : assume < array > works
"""
2014-09-27 23:14:50 +00:00
return self . Cxx11Compile ( context , msg = ' for <array> ' , successflags = { ' CPPDEFINES ' : [ ' DXX_HAVE_CXX_ARRAY ' ] } , * * kwargs )
2013-11-09 23:01:38 +00:00
@_implicit_test
2014-09-27 23:14:50 +00:00
def check_cxx_tr1_array ( self , context , * * kwargs ) :
2013-11-09 23:01:38 +00:00
"""
help : assume < tr1 / array > works
"""
2014-09-27 23:14:50 +00:00
return self . Compile ( context , msg = ' for <tr1/array> ' , successflags = { ' CPPDEFINES ' : [ ' DXX_HAVE_CXX_TR1_ARRAY ' ] } , * * kwargs )
2013-11-09 23:01:38 +00:00
@_custom_test
def _check_cxx_array ( self , context ) :
2014-09-27 23:14:50 +00:00
include = '''
2013-12-21 05:12:38 +00:00
#include "compiler-array.h"
2013-11-09 23:01:38 +00:00
'''
2014-09-27 23:14:50 +00:00
main = '''
array < int , 2 > b ;
b [ 0 ] = 1 ;
'''
how = self . check_cxx_array ( context , text = include , main = main ) or self . check_boost_array ( context , text = include , main = main ) or self . check_cxx_tr1_array ( context , text = include , main = main )
2013-11-09 23:01:38 +00:00
if not how :
raise SCons . Errors . StopError ( " C++ compiler does not support <array> or Boost.Array or <tr1/array>. " )
2013-11-16 00:42:04 +00:00
@_custom_test
2014-06-21 17:54:02 +00:00
def check_cxx11_function_auto ( self , context ) :
2013-11-16 00:42:04 +00:00
"""
help : assume compiler supports C + + 11 function declarator syntax
"""
f = '''
auto f ( ) - > int ;
'''
2014-06-21 17:54:02 +00:00
if not self . Cxx11Compile ( context , text = f , msg = ' for C++11 function declarator syntax ' ) :
raise SCons . Errors . StopError ( " C++ compiler does not support C++11 function declarator syntax. " )
def _check_static_assert_method ( self , context , msg , f , testflags = { } , _Compile = Compile , * * kwargs ) :
return _Compile ( self , context , text = f % ' true ' , msg = msg % ' true ' , testflags = testflags , * * kwargs ) and \
_Compile ( self , context , text = f % ' false ' , msg = msg % ' false ' , expect_failure = True , successflags = testflags , * * kwargs )
2013-11-26 05:03:00 +00:00
@_implicit_test
def check_boost_static_assert ( self , context , f ) :
"""
help : assume Boost . StaticAssert works
"""
return self . _check_static_assert_method ( context , ' for Boost.StaticAssert when %s ' , f , testflags = { ' CPPDEFINES ' : [ ' DXX_HAVE_BOOST_STATIC_ASSERT ' ] } )
@_implicit_test
def check_c_typedef_static_assert ( self , context , f ) :
"""
help : assume C typedef - based static assertion works
"""
return self . _check_static_assert_method ( context , ' for C typedef static assertion when %s ' , f , testflags = { ' CPPDEFINES ' : [ ' DXX_HAVE_C_TYPEDEF_STATIC_ASSERT ' ] } )
@_implicit_test
2014-06-21 17:54:02 +00:00
def check_cxx11_static_assert ( self , context , f ) :
2013-11-26 05:03:00 +00:00
"""
help : assume compiler supports C + + intrinsic static_assert
"""
2014-06-21 17:54:02 +00:00
return self . _check_static_assert_method ( context , ' for C++11 intrinsic static_assert when %s ' , f , testflags = { ' CPPDEFINES ' : [ ' DXX_HAVE_CXX11_STATIC_ASSERT ' ] } , _Compile = ConfigureTests . Cxx11Compile )
2013-11-26 05:03:00 +00:00
@_custom_test
def _check_static_assert ( self , context ) :
f = '''
2013-12-21 05:12:38 +00:00
#include "compiler-static_assert.h"
2013-11-26 05:03:00 +00:00
static_assert ( % s , " " ) ;
'''
how = self . check_cxx11_static_assert ( context , f ) or self . check_boost_static_assert ( context , f ) or self . check_c_typedef_static_assert ( context , f )
if not how :
raise SCons . Errors . StopError ( " C++ compiler does not support static_assert or Boost.StaticAssert or typedef-based static assertion. " )
2013-11-28 04:21:20 +00:00
@_implicit_test
2013-12-16 22:15:38 +00:00
def check_boost_type_traits ( self , context , f ) :
"""
help : assume Boost . TypeTraits works
"""
return self . Compile ( context , text = f , msg = ' for Boost.TypeTraits ' , ext = ' .cpp ' , successflags = { ' CPPDEFINES ' : [ ' DXX_HAVE_BOOST_TYPE_TRAITS ' ] } )
@_implicit_test
2014-06-21 17:54:02 +00:00
def check_cxx11_type_traits ( self , context , f ) :
2013-12-16 22:15:38 +00:00
"""
help : assume < type_traits > works
"""
2014-06-21 17:54:02 +00:00
return self . Cxx11Compile ( context , text = f , msg = ' for <type_traits> ' , ext = ' .cpp ' , successflags = { ' CPPDEFINES ' : [ ' DXX_HAVE_CXX11_TYPE_TRAITS ' ] } )
2013-12-16 22:15:38 +00:00
@_custom_test
def _check_type_traits ( self , context ) :
f = '''
2013-12-21 05:12:38 +00:00
#include "compiler-type_traits.h"
2013-12-16 22:15:38 +00:00
typedef tt : : conditional < true , int , long > : : type a ;
typedef tt : : conditional < false , int , long > : : type b ;
'''
if self . check_cxx11_type_traits ( context , f ) or self . check_boost_type_traits ( context , f ) :
context . sconf . Define ( ' DXX_HAVE_TYPE_TRAITS ' )
@_implicit_test
2014-09-27 23:14:50 +00:00
def check_boost_foreach ( self , context , * * kwargs ) :
2013-12-11 23:59:36 +00:00
"""
help : assume Boost . Foreach works
"""
2014-09-27 23:14:50 +00:00
return self . Compile ( context , msg = ' for Boost.Foreach ' , successflags = { ' CPPDEFINES ' : [ ' DXX_HAVE_BOOST_FOREACH ' ] } , * * kwargs )
2013-12-11 23:59:36 +00:00
@_implicit_test
2014-09-27 23:14:50 +00:00
def check_cxx11_range_for ( self , context , * * kwargs ) :
return self . Cxx11Compile ( context , msg = ' for C++11 range-based for ' , successflags = { ' CPPDEFINES ' : [ ' DXX_HAVE_CXX11_RANGE_FOR ' ] } , * * kwargs )
2013-12-11 23:59:36 +00:00
@_custom_test
def _check_range_based_for ( self , context ) :
2014-09-27 23:14:50 +00:00
include = '''
2013-12-21 05:12:38 +00:00
#include "compiler-range_for.h"
2013-12-11 23:59:36 +00:00
'''
2014-09-27 23:14:50 +00:00
main = '''
int b [ 2 ] ;
range_for ( int & c , b ) c = 0 ;
'''
if not self . check_cxx11_range_for ( context , text = include , main = main ) and not self . check_boost_foreach ( context , text = include , main = main ) :
2013-12-11 23:59:36 +00:00
raise SCons . Errors . StopError ( " C++ compiler does not support range-based for or Boost.Foreach. " )
2014-06-01 20:49:07 +00:00
@_custom_test
def check_cxx11_constexpr ( self , context ) :
f = '''
struct A { } ;
constexpr A a ( ) { return { } ; }
'''
if not self . Cxx11Compile ( context , text = f , msg = ' for C++11 constexpr ' , successflags = { ' CPPDEFINES ' : [ ' DXX_HAVE_CXX11_CONSTEXPR ' ] } ) :
context . sconf . Define ( ' constexpr ' , self . comment_not_supported )
2013-12-11 23:59:36 +00:00
@_implicit_test
2013-11-28 04:21:20 +00:00
def check_pch ( self , context ) :
for how in [ { ' CXXFLAGS ' : [ ' -x ' , ' c++-header ' ] } ] :
result = self . Compile ( context , text = ' ' , msg = ' whether compiler supports pre-compiled headers ' , testflags = how )
if result :
self . pch_flags = how
return result
@_custom_test
def _check_pch ( self , context ) :
self . pch_flags = None
msg = ' when to pre-compile headers '
context . Display ( ' %s : checking %s ... ' % ( self . msgprefix , msg ) )
if self . user_settings . pch :
count = int ( self . user_settings . pch )
else :
count = 0
if count < = 0 :
context . Result ( ' never ' )
return
context . Display ( ' if used at least %u time %s \n ' % ( count , ' s ' if count > 1 else ' ' ) )
if not self . check_pch ( context ) :
raise SCons . Errors . StopError ( " C++ compiler does not support pre-compiled headers. " )
2013-11-17 00:17:58 +00:00
@_custom_test
2014-06-21 17:54:02 +00:00
def check_cxx11_explicit_bool ( self , context ) :
2013-11-17 00:17:58 +00:00
"""
help : assume compiler supports explicit operator bool
"""
f = '''
struct A { explicit operator bool ( ) ; } ;
'''
2014-06-21 17:54:02 +00:00
r = self . Cxx11Compile ( context , text = f , msg = ' for explicit operator bool ' )
2013-11-17 00:17:58 +00:00
macro_name = ' dxx_explicit_operator_bool '
if r :
context . sconf . Define ( macro_name , ' explicit ' )
context . sconf . Define ( ' DXX_HAVE_EXPLICIT_OPERATOR_BOOL ' )
else :
context . sconf . Define ( macro_name , self . comment_not_supported )
@_custom_test
2014-06-21 17:54:02 +00:00
def check_cxx11_explicit_delete ( self , context ) :
2013-11-17 00:17:58 +00:00
"""
help : assume compiler supports explicitly deleted functions
"""
f = '''
int a ( ) = delete ;
'''
2014-06-21 17:54:02 +00:00
r = self . Cxx11Compile ( context , text = f , msg = ' for explicitly deleted functions ' )
2013-11-17 00:17:58 +00:00
macro_name = ' DXX_CXX11_EXPLICIT_DELETE '
if r :
context . sconf . Define ( macro_name , ' =delete ' )
context . sconf . Define ( ' DXX_HAVE_CXX11_EXPLICIT_DELETE ' )
else :
context . sconf . Define ( macro_name , self . comment_not_supported )
2013-12-24 04:53:59 +00:00
@_implicit_test
2014-09-27 23:14:50 +00:00
def check_cxx11_free_begin ( self , context , * * kwargs ) :
return self . Cxx11Compile ( context , msg = ' for C++11 functions begin(), end() ' , successflags = { ' CPPDEFINES ' : [ ' DXX_HAVE_CXX11_BEGIN ' ] } , * * kwargs )
2014-01-18 18:02:02 +00:00
@_implicit_test
2014-09-27 23:14:50 +00:00
def check_boost_free_begin ( self , context , * * kwargs ) :
return self . Compile ( context , msg = ' for Boost.Range functions begin(), end() ' , successflags = { ' CPPDEFINES ' : [ ' DXX_HAVE_BOOST_BEGIN ' ] } , * * kwargs )
2014-01-18 18:02:02 +00:00
@_custom_test
def _check_free_begin_function ( self , context ) :
f = '''
#include "compiler-begin.h"
struct A {
typedef int * iterator ;
typedef const int * const_iterator ;
2014-09-27 23:14:50 +00:00
iterator begin ( ) { return 0 ; }
iterator end ( ) { return 0 ; }
const_iterator begin ( ) const { return 0 ; }
const_iterator end ( ) const { return 0 ; }
2014-01-18 18:02:02 +00:00
} ;
2014-09-27 23:14:50 +00:00
#define F(C){\
C int a [ 1 ] { 0 } ; \
C A b { } ; \
if ( begin ( a ) | | end ( a ) | | begin ( b ) | | end ( b ) ) return 1 ; \
2014-01-18 18:02:02 +00:00
}
'''
2014-09-27 23:14:50 +00:00
main = ' F()F(const) '
if not self . check_cxx11_free_begin ( context , text = f , main = main ) and not self . check_boost_free_begin ( context , text = f , main = main ) :
2014-01-18 18:02:02 +00:00
raise SCons . Errors . StopError ( " C++ compiler does not support free functions begin() and end(). " )
@_implicit_test
2014-09-27 23:14:50 +00:00
def check_cxx11_addressof ( self , context , * * kwargs ) :
return self . Cxx11Compile ( context , msg = ' for C++11 function addressof() ' , successflags = { ' CPPDEFINES ' : [ ' DXX_HAVE_CXX11_ADDRESSOF ' ] } , * * kwargs )
2014-01-12 23:00:43 +00:00
@_implicit_test
2014-09-27 23:14:50 +00:00
def check_boost_addressof ( self , context , * * kwargs ) :
return self . Compile ( context , msg = ' for Boost.Utility function addressof() ' , successflags = { ' CPPDEFINES ' : [ ' DXX_HAVE_BOOST_ADDRESSOF ' ] } , * * kwargs )
2014-01-12 23:00:43 +00:00
@_custom_test
def _check_free_addressof_function ( self , context ) :
f = '''
#include "compiler-addressof.h"
struct A {
void operator & ( ) ;
} ;
'''
2014-09-27 23:14:50 +00:00
main = '''
A b ;
return addressof ( b ) != 0 ;
'''
if not self . check_cxx11_addressof ( context , text = f , main = main ) and not self . check_boost_addressof ( context , text = f , main = main ) :
2014-01-12 23:00:43 +00:00
raise SCons . Errors . StopError ( " C++ compiler does not support free function addressof(). " )
2014-06-01 20:49:07 +00:00
@_custom_test
2014-09-07 21:23:03 +00:00
def check_cxx14_exchange ( self , context ) :
f = '''
#include "compiler-exchange.h"
'''
2014-09-27 23:14:50 +00:00
self . Cxx14Compile ( context , text = f , main = ' return exchange(argc, 5) ' , msg = ' for C++14 exchange ' , successflags = { ' CPPDEFINES ' : [ ' DXX_HAVE_CXX14_EXCHANGE ' ] } )
2014-09-07 21:23:03 +00:00
@_custom_test
2014-06-01 20:49:07 +00:00
def check_cxx14_integer_sequence ( self , context ) :
f = '''
#include <utility>
using std : : integer_sequence ;
using std : : index_sequence ;
'''
self . Cxx14Compile ( context , text = f , msg = ' for C++14 integer_sequence ' , successflags = { ' CPPDEFINES ' : [ ' DXX_HAVE_CXX14_INTEGER_SEQUENCE ' ] } )
2014-08-16 04:15:16 +00:00
@_custom_test
def check_cxx14_make_unique ( self , context ) :
f = '''
#include "compiler-make_unique.h"
2014-09-27 23:14:50 +00:00
'''
main = '''
2014-08-16 04:15:16 +00:00
make_unique < int > ( 0 ) ;
make_unique < int [ ] > ( 1 ) ;
'''
2014-09-27 23:14:50 +00:00
self . Cxx14Compile ( context , text = f , main = main , msg = ' for C++14 make_unique ' , successflags = { ' CPPDEFINES ' : [ ' DXX_HAVE_CXX14_MAKE_UNIQUE ' ] } )
2014-01-12 23:00:43 +00:00
@_implicit_test
2014-09-27 23:14:50 +00:00
def check_cxx11_inherit_constructor ( self , context , text , fmtargs , * * kwargs ) :
2013-12-24 04:53:59 +00:00
"""
help : assume compiler supports inheriting constructors
"""
2014-07-19 17:34:02 +00:00
macro_value = self . _quote_macro_value ( '''
typedef B , ##__VA_ARGS__ _dxx_constructor_base_type;
using _dxx_constructor_base_type : : _dxx_constructor_base_type ; ''' )
2014-09-27 23:14:50 +00:00
if self . Cxx11Compile ( context , text = text . format ( macro_value = macro_value , * * fmtargs ) , msg = ' for C++11 inherited constructors ' , * * kwargs ) :
2013-12-24 04:53:59 +00:00
return macro_value
return None
@_implicit_test
2014-09-27 23:14:50 +00:00
def check_cxx11_variadic_forward_constructor ( self , context , text , fmtargs , * * kwargs ) :
2013-12-24 04:53:59 +00:00
"""
help : assume compiler supports variadic template - based constructor forwarding
"""
2014-07-19 17:34:02 +00:00
macro_value = self . _quote_macro_value ( '''
template < typename . . . Args >
D ( Args & & . . . args ) :
2014-11-26 02:57:36 +00:00
B , ##__VA_ARGS__{std::forward<Args>(args)...} {}
2014-07-19 17:34:02 +00:00
''' )
2014-09-27 23:14:50 +00:00
if self . Cxx11Compile ( context , text = ' #include <algorithm> \n ' + text . format ( macro_value = macro_value , * * fmtargs ) , msg = ' for C++11 variadic templates on constructors ' , * * kwargs ) :
2013-12-24 04:53:59 +00:00
return macro_value
return None
@_custom_test
def _check_forward_constructor ( self , context ) :
text = '''
#define {macro_name}{macro_parameters} {macro_value}
struct A { {
2014-09-27 23:14:50 +00:00
A ( int ) { { } }
2013-12-24 04:53:59 +00:00
} } ;
struct B : A { {
{ macro_name } ( B , A ) ;
} } ;
'''
macro_name = ' DXX_INHERIT_CONSTRUCTORS '
macro_parameters = ' (D,B,...) '
# C++03 support is possible with enumerated out template
# variations. If someone finds a worthwhile compiler without
# variadic templates, enumerated templates can be added.
2014-09-27 23:14:50 +00:00
for f in ( self . check_cxx11_inherit_constructor , self . check_cxx11_variadic_forward_constructor ) :
macro_value = f ( context , text = text , main = ' B(0) ' , fmtargs = { ' macro_name ' : macro_name , ' macro_parameters ' : macro_parameters } )
2013-12-24 04:53:59 +00:00
if macro_value :
break
if not macro_value :
raise SCons . Errors . StopError ( " C++ compiler does not support constructor forwarding. " )
context . sconf . Define ( macro_name + macro_parameters , macro_value )
2014-08-02 04:51:07 +00:00
@_custom_test
def check_cxx11_template_alias ( self , context ) :
text = '''
template < typename >
struct A ;
template < typename T >
using B = A < T > ;
2014-09-27 23:14:50 +00:00
'''
main = '''
2014-08-02 04:51:07 +00:00
A < int > * a = 0 ;
B < int > * b = a ;
( void ) b ;
'''
2014-09-27 23:14:50 +00:00
if self . Cxx11Compile ( context , text = text , main = main , msg = ' for C++11 template aliases ' ) :
2014-08-02 04:51:07 +00:00
context . sconf . Define ( ' DXX_HAVE_CXX11_TEMPLATE_ALIAS ' )
2014-08-20 01:08:12 +00:00
@_custom_test
2014-09-07 21:54:30 +00:00
def check_cxx11_ref_qualifier ( self , context ) :
text = '''
struct A {
int a ( ) & { return 1 ; }
int a ( ) & & { return 2 ; }
} ;
2014-09-27 23:14:50 +00:00
'''
main = '''
2014-09-07 21:54:30 +00:00
A a ;
return a . a ( ) != A ( ) . a ( ) ;
'''
2014-09-27 23:14:50 +00:00
if self . Cxx11Compile ( context , text = text , main = main , msg = ' for C++11 reference qualified methods ' ) :
2014-09-07 21:54:30 +00:00
context . sconf . Define ( ' DXX_HAVE_CXX11_REF_QUALIFIER ' )
@_custom_test
2014-08-20 01:08:12 +00:00
def check_deep_tuple ( self , context ) :
text = '''
#include <tuple>
static inline std : : tuple < { type } > make ( ) { {
return std : : make_tuple ( { value } ) ;
} }
2014-09-27 23:14:50 +00:00
static void a ( ) { {
2014-08-20 01:08:12 +00:00
std : : tuple < { type } > t = make ( ) ;
( void ) t ;
} }
'''
count = 20
2014-09-27 23:14:50 +00:00
if self . Compile ( context , text = text . format ( type = ' , ' . join ( ( ' int ' , ) * count ) , value = ' , ' . join ( ( ' 0 ' , ) * count ) ) , main = ' a() ' , msg = ' whether compiler handles 20-element tuples ' ) :
2014-08-20 01:08:12 +00:00
return
count = 2
2014-09-27 23:14:50 +00:00
if self . Compile ( context , text = text . format ( type = ' , ' . join ( ( ' int ' , ) * count ) , value = ' , ' . join ( ( ' 0 ' , ) * count ) ) , main = ' a() ' , msg = ' whether compiler handles 2-element tuples ' ) :
2014-08-20 01:08:12 +00:00
raise SCons . Errors . StopError ( " Compiler cannot handle tuples of 20 elements. Raise the template instantiation depth. " )
raise SCons . Errors . StopError ( " Compiler cannot handle tuples of 2 elements. " )
2014-09-07 19:26:17 +00:00
@_implicit_test
def check_poison_valgrind ( self , context ) :
2015-01-03 23:44:32 +00:00
'''
help : add Valgrind annotations ; wipe certain freed memory when running under Valgrind
'''
context . Message ( ' %s : checking %s ... ' % ( self . msgprefix , ' whether to use Valgrind poisoning ' ) )
r = ' valgrind ' in self . user_settings . poison
2014-09-07 19:26:17 +00:00
context . Result ( r )
if not r :
return
text = '''
#include "poison.h"
2014-09-27 23:14:50 +00:00
'''
main = '''
2014-09-07 19:26:17 +00:00
DXX_MAKE_MEM_UNDEFINED ( & argc , sizeof ( argc ) ) ;
'''
2014-09-27 23:14:50 +00:00
if self . Compile ( context , text = text , main = main , msg = ' whether Valgrind memcheck header works ' , successflags = { ' CPPDEFINES ' : [ ' DXX_HAVE_POISON_VALGRIND ' ] } ) :
2014-09-07 19:26:17 +00:00
return True
raise SCons . Errors . StopError ( " Valgrind poison requested, but <valgrind/memcheck.h> does not work. " )
2015-01-03 23:44:32 +00:00
@_implicit_test
def check_poison_overwrite ( self , context ) :
'''
help : always wipe certain freed memory
'''
context . Message ( ' %s : checking %s ... ' % ( self . msgprefix , ' whether to use overwrite poisoning ' ) )
r = ' overwrite ' in self . user_settings . poison
context . Result ( r )
if r :
context . sconf . Define ( ' DXX_HAVE_POISON_OVERWRITE ' )
return r
2014-09-07 19:26:17 +00:00
@_custom_test
def _check_poison_method ( self , context ) :
2015-01-03 23:44:32 +00:00
poison = None
for f in (
self . check_poison_valgrind ,
self . check_poison_overwrite ,
) :
if f ( context ) :
poison = True
if poison :
2014-09-07 19:26:17 +00:00
context . sconf . Define ( ' DXX_HAVE_POISON ' )
2015-01-12 00:26:03 +00:00
@_custom_test
def check_strcasecmp_present ( self , context ) :
main = '''
return ! strcasecmp ( argv [ 0 ] , argv [ 0 ] + 1 ) & & ! strncasecmp ( argv [ 0 ] + 1 , argv [ 0 ] , 1 ) ;
'''
self . Compile ( context , text = ' #include <cstring> ' , main = main , msg = ' for strcasecmp ' , successflags = { ' CPPDEFINES ' : [ ' DXX_HAVE_STRCASECMP ' ] } )
2013-06-27 02:35:22 +00:00
2013-05-04 23:58:14 +00:00
class LazyObjectConstructor :
2014-09-13 22:10:24 +00:00
def __get_lazy_object ( self , srcname , transform_target ) :
env = self . env
o = env . StaticObject ( target = ' %s %s %s ' % ( self . user_settings . builddir , transform_target ( self , srcname ) , env [ " OBJSUFFIX " ] ) , source = srcname )
if env . _dxx_pch_node :
env . Depends ( o , self . env . _dxx_pch_node )
return o
2013-05-04 23:58:14 +00:00
def __lazy_objects ( self , name , source ) :
try :
return self . __lazy_object_cache [ name ]
except KeyError as e :
def __strip_extension ( self , name ) :
return os . path . splitext ( name ) [ 0 ]
value = [ ]
for s in source :
if isinstance ( s , str ) :
s = { ' source ' : [ s ] }
transform_target = s . get ( ' transform_target ' , __strip_extension )
2014-09-13 22:10:24 +00:00
value . extend ( [ self . __get_lazy_object ( srcname , transform_target ) for srcname in s [ ' source ' ] ] )
2013-05-04 23:58:14 +00:00
self . __lazy_object_cache [ name ] = value
return value
@staticmethod
def create_lazy_object_getter ( sources ) :
name = repr ( sources )
return lambda s : s . __lazy_objects ( name , sources )
@classmethod
def create_lazy_object_property ( cls , sources ) :
return property ( cls . create_lazy_object_getter ( sources ) )
def __init__ ( self ) :
self . __lazy_object_cache = { }
2013-10-26 22:13:13 +00:00
class FilterHelpText :
def __init__ ( self ) :
self . visible_arguments = [ ]
2014-08-05 02:43:29 +00:00
self . _sconf_align = None
2013-10-26 22:13:13 +00:00
def FormatVariableHelpText ( self , env , opt , help , default , actual , aliases ) :
if not opt in self . visible_arguments :
return ' '
2014-08-05 02:43:29 +00:00
if not self . _sconf_align :
self . _sconf_align = len ( max ( ( s for s in self . visible_arguments if s [ : 6 ] == ' sconf_ ' ) , key = len ) )
2013-10-26 22:13:13 +00:00
l = [ ]
if default is not None :
if isinstance ( default , str ) and not default . isalnum ( ) :
default = ' " %s " ' % default
l . append ( " default: {default} " . format ( default = default ) )
actual = getattr ( self , opt , None )
if actual is not None :
if isinstance ( actual , str ) and not actual . isalnum ( ) :
actual = ' " %s " ' % actual
l . append ( " current: {current} " . format ( current = actual ) )
2014-08-05 02:43:29 +00:00
return ( " { opt: %u } {help} " % ( self . _sconf_align if opt [ : 6 ] == ' sconf_ ' else 15 ) ) . format ( opt = opt , help = help ) + ( " [ " + " ; " . join ( l ) + " ] " if l else ' ' ) + ' \n '
2013-10-26 22:13:13 +00:00
2013-05-04 23:58:14 +00:00
class DXXCommon ( LazyObjectConstructor ) :
2013-06-16 19:28:38 +00:00
__shared_program_instance = [ 0 ]
2014-11-17 04:02:25 +00:00
__shared_header_file_list = [ ]
2013-02-25 00:02:01 +00:00
__endian = checkEndian ( )
2013-06-16 19:28:38 +00:00
@property
def program_message_prefix ( self ) :
return ' %s . %d ' % ( self . PROGRAM_NAME , self . program_instance )
2013-05-11 23:52:32 +00:00
# Settings which affect how the files are compiled
class UserBuildSettings :
2013-05-05 18:52:00 +00:00
# Paths for the Videocore libs/includes on the Raspberry Pi
RPI_DEFAULT_VC_PATH = ' /opt/vc '
default_OGLES_LIB = ' GLES_CM '
2013-06-16 02:40:05 +00:00
_default_prefix = ' /usr/local '
2013-05-11 23:52:32 +00:00
def default_builddir ( self ) :
2013-06-16 02:40:05 +00:00
builddir_prefix = self . builddir_prefix
builddir_suffix = self . builddir_suffix
2013-05-11 23:52:32 +00:00
default_builddir = builddir_prefix or ' '
if builddir_prefix is not None or builddir_suffix is not None :
2013-07-04 02:27:50 +00:00
fields = [
self . host_platform ,
2013-11-26 03:59:44 +00:00
os . path . basename ( self . CXX ) if self . CXX else None ,
2013-07-04 02:27:50 +00:00
]
2013-11-26 03:59:44 +00:00
compiler_flags = ' \n ' . join ( ( getattr ( self , attr ) or ' ' ) . strip ( ) for attr in [ ' CPPFLAGS ' , ' CXXFLAGS ' ] )
2013-07-04 02:27:07 +00:00
if compiler_flags :
2013-11-26 03:59:44 +00:00
# Mix in CRC of CXXFLAGS to get reasonable uniqueness
2013-05-18 02:37:19 +00:00
# when flags are changed. A full hash is
# unnecessary here.
2013-07-04 02:27:07 +00:00
crc = binascii . crc32 ( compiler_flags )
2013-06-08 01:38:05 +00:00
if crc < 0 :
crc = crc + 0x100000000
2013-07-04 02:27:50 +00:00
fields . append ( ' {:08x} ' . format ( crc ) )
2013-11-28 04:21:20 +00:00
if self . pch :
fields . append ( ' p %s ' % self . pch )
2013-07-04 03:29:01 +00:00
fields . append ( ' ' . join ( a [ 1 ] if getattr ( self , a [ 0 ] ) else ( a [ 2 ] if len ( a ) > 2 else ' ' )
2013-05-11 23:52:32 +00:00
for a in (
( ' debug ' , ' dbg ' ) ,
2014-06-29 23:26:05 +00:00
( ' lto ' , ' lto ' ) ,
2013-05-11 23:52:32 +00:00
( ' profiler ' , ' prf ' ) ,
( ' editor ' , ' ed ' ) ,
2013-07-04 03:29:01 +00:00
( ' opengl ' , ' ogl ' , ' sdl ' ) ,
2013-05-11 23:52:32 +00:00
( ' opengles ' , ' es ' ) ,
( ' raspberrypi ' , ' rpi ' ) ,
2013-07-04 02:27:50 +00:00
) ) )
default_builddir + = ' - ' . join ( [ f for f in fields if f ] )
2013-05-11 23:52:32 +00:00
if builddir_suffix is not None :
default_builddir + = builddir_prefix
return default_builddir
2012-05-20 18:51:21 +00:00
def default_memdebug ( self ) :
return self . debug
2013-05-12 01:03:37 +00:00
# automatic setup for raspberrypi
def default_opengles ( self ) :
if self . raspberrypi :
2013-06-16 02:40:05 +00:00
return True
return False
2013-05-12 01:03:37 +00:00
def selected_OGLES_LIB ( self ) :
if self . raspberrypi :
return ' GLESv2 '
return self . default_OGLES_LIB
2013-06-16 02:40:05 +00:00
def __default_DATA_DIR ( self ) :
return self . prefix + ' /share/games/ ' + self . _program . target
@staticmethod
def _generic_variable ( key , help , default ) :
return ( key , help , default )
@staticmethod
def _enum_variable ( key , help , default , allowed_values ) :
return EnumVariable ( key , help , default , allowed_values )
def _options ( self ) :
return (
2013-06-27 02:35:22 +00:00
{
2014-07-19 22:25:27 +00:00
' variable ' : self . _enum_variable ,
2013-06-27 02:35:22 +00:00
' arguments ' : [
2014-07-19 22:25:27 +00:00
( ' sconf_ %s ' % name [ 6 : ] , None , ConfigureTests . describe ( name ) or ( ' assume result of %s ' % name ) , { ' allowed_values ' : [ ' 0 ' , ' 1 ' , ' 2 ' , ConfigureTests . sconf_force_failure , ConfigureTests . sconf_force_success , ConfigureTests . sconf_assume_success ] } ) for name in ConfigureTests . implicit_tests + ConfigureTests . custom_tests if name [ 0 ] != ' _ '
2013-06-27 02:35:22 +00:00
] ,
} ,
2013-06-16 02:40:05 +00:00
{
' variable ' : BoolVariable ,
' arguments ' : (
( ' raspberrypi ' , False , ' build for Raspberry Pi (automatically sets opengles and opengles_lib) ' ) ,
2014-07-26 17:40:12 +00:00
( ' git_describe_version ' , os . path . exists ( os . environ . get ( ' GIT_DIR ' , ' .git ' ) ) , ' include git --describe in extra_version ' ) ,
( ' git_status ' , True , ' include git status ' ) ,
2014-09-13 22:10:24 +00:00
( ' versid_depend_all ' , False , ' rebuild vers_id.cpp if any object file changes ' ) ,
2013-06-16 02:40:05 +00:00
) ,
} ,
{
' variable ' : self . _generic_variable ,
' arguments ' : (
( ' rpi_vc_path ' , self . RPI_DEFAULT_VC_PATH , ' directory for RPi VideoCore libraries ' ) ,
( ' opengles_lib ' , self . selected_OGLES_LIB , ' name of the OpenGL ES library to link against ' ) ,
( ' prefix ' , self . _default_prefix , ' installation prefix directory (Linux only) ' ) ,
( ' sharepath ' , self . __default_DATA_DIR , ' directory for shared game data (Linux only) ' ) ,
2013-10-25 23:58:05 +00:00
( ' pch ' , None , ' pre-compile headers used this many times ' ) ,
2013-05-12 03:16:24 +00:00
) ,
} ,
{
2013-06-16 02:40:05 +00:00
' variable ' : BoolVariable ,
2013-05-12 03:16:24 +00:00
' arguments ' : (
2014-11-17 04:02:25 +00:00
( ' check_header_includes ' , False , ' compile test each header (developer option) ' ) ,
2013-06-16 02:40:05 +00:00
( ' debug ' , False , ' build DEBUG binary which includes asserts, debugging output, cheats and more output ' ) ,
2012-05-20 18:51:21 +00:00
( ' memdebug ' , self . default_memdebug , ' build with malloc tracking ' ) ,
2014-06-29 23:26:05 +00:00
( ' lto ' , False , ' enable gcc link time optimization ' ) ,
2013-06-16 02:40:05 +00:00
( ' profiler ' , False , ' profiler build ' ) ,
( ' opengl ' , True , ' build with OpenGL support ' ) ,
( ' opengles ' , self . default_opengles , ' build with OpenGL ES support ' ) ,
( ' editor ' , False , ' include editor into build (!EXPERIMENTAL!) ' ) ,
( ' sdlmixer ' , True , ' build with SDL_Mixer support for sound and music (includes external music support) ' ) ,
( ' ipv6 ' , False , ' enable IPv6 compability ' ) ,
( ' use_udp ' , True , ' enable UDP support ' ) ,
( ' use_tracker ' , True , ' enable Tracker support (requires UDP) ' ) ,
( ' verbosebuild ' , False , ' print out all compiler/linker messages during building ' ) ,
2013-05-12 03:16:24 +00:00
) ,
} ,
{
2013-06-16 02:40:05 +00:00
' variable ' : self . _generic_variable ,
2013-05-12 03:16:24 +00:00
' arguments ' : (
2013-10-26 22:56:08 +00:00
( ' CHOST ' , os . environ . get ( ' CHOST ' ) , ' CHOST of output ' ) ,
2013-06-16 02:40:05 +00:00
( ' CXX ' , os . environ . get ( ' CXX ' ) , ' C++ compiler command ' ) ,
2013-11-14 23:01:25 +00:00
( ' PKG_CONFIG ' , os . environ . get ( ' PKG_CONFIG ' ) , ' PKG_CONFIG to run (Linux only) ' ) ,
( ' RC ' , os . environ . get ( ' RC ' ) , ' Windows resource compiler command ' ) ,
( ' extra_version ' , None , ' text to append to version, such as VCS identity ' ) ,
2015-01-03 23:44:32 +00:00
( ' ccache ' , None , ' path to ccache ' ) ,
( ' distcc ' , None , ' path to distcc ' ) ,
( ' distcc_hosts ' , os . environ . get ( ' DISTCC_HOSTS ' ) , ' hosts to distribute compilation ' ) ,
2013-11-14 23:01:25 +00:00
) ,
} ,
{
' variable ' : self . _generic_variable ,
' stack ' : ' ' ,
' arguments ' : (
2013-06-16 02:40:05 +00:00
( ' CPPFLAGS ' , os . environ . get ( ' CPPFLAGS ' ) , ' C preprocessor flags ' ) ,
( ' CXXFLAGS ' , os . environ . get ( ' CXXFLAGS ' ) , ' C++ compiler flags ' ) ,
( ' LDFLAGS ' , os . environ . get ( ' LDFLAGS ' ) , ' Linker flags ' ) ,
2013-06-01 23:46:05 +00:00
( ' LIBS ' , os . environ . get ( ' LIBS ' ) , ' Libraries to link ' ) ,
2013-05-12 03:16:24 +00:00
) ,
} ,
{
2013-06-16 02:40:05 +00:00
' variable ' : self . _enum_variable ,
' arguments ' : (
2013-12-05 23:01:34 +00:00
( ' host_platform ' , ' linux ' if sys . platform == ' linux2 ' else sys . platform , ' cross-compile to specified platform ' , { ' allowed_values ' : [ ' win32 ' , ' darwin ' , ' linux ' ] } ) ,
2015-01-03 23:44:32 +00:00
) ,
} ,
{
' variable ' : ListVariable ,
' arguments ' : (
( ' poison ' , ' none ' , ' method for poisoning free memory ' , { ' names ' : ( ' valgrind ' , ' overwrite ' ) } ) ,
2013-06-16 02:40:05 +00:00
) ,
} ,
{
' variable ' : self . _generic_variable ,
' arguments ' : (
( ' builddir_prefix ' , None , ' prefix to generated build directory ' ) ,
( ' builddir_suffix ' , None , ' suffix to generated build directory ' ) ,
2013-05-12 03:16:24 +00:00
# This must be last so that default_builddir will
# have access to other properties.
2013-06-16 02:40:05 +00:00
( ' builddir ' , self . default_builddir , ' build in specified directory ' ) ,
2013-05-12 03:16:24 +00:00
) ,
} ,
)
2013-10-26 22:15:14 +00:00
@staticmethod
def _names ( name , prefix ) :
2014-08-05 02:41:42 +00:00
return [ ' %s %s %s ' % ( p , ' _ ' if p else ' ' , name ) for p in prefix ]
2013-07-04 03:29:04 +00:00
def __init__ ( self , program = None ) :
self . _program = program
2013-10-26 18:13:28 +00:00
def register_variables ( self , prefix , variables ) :
self . known_variables = [ ]
2013-06-16 02:40:05 +00:00
for grp in self . _options ( ) :
variable = grp [ ' variable ' ]
2013-11-14 23:01:25 +00:00
stack = grp . get ( ' stack ' , None )
2013-06-16 02:40:05 +00:00
for opt in grp [ ' arguments ' ] :
( name , value , help ) = opt [ 0 : 3 ]
kwargs = opt [ 3 ] if len ( opt ) > 3 else { }
2014-08-05 02:41:42 +00:00
if name not in variables . keys ( ) :
filtered_help . visible_arguments . append ( name )
variables . Add ( variable ( key = name , help = help , default = None if callable ( value ) else value , * * kwargs ) )
2013-10-26 22:15:14 +00:00
names = self . _names ( name , prefix )
for n in names :
2013-07-04 03:29:04 +00:00
if n not in variables . keys ( ) :
variables . Add ( variable ( key = n , help = help , default = None , * * kwargs ) )
2014-08-05 02:41:42 +00:00
if not name in names :
names . append ( name )
self . known_variables . append ( ( names , name , value , stack ) )
2013-11-14 23:01:25 +00:00
if stack :
2014-08-05 02:41:42 +00:00
for n in names :
2013-11-14 23:01:25 +00:00
variables . Add ( self . _generic_variable ( key = ' %s _stop ' % n , help = None , default = None ) )
2013-10-26 18:13:28 +00:00
def read_variables ( self , variables , d ) :
2014-08-05 02:41:42 +00:00
for ( namelist , cname , dvalue , stack ) in self . known_variables :
2013-11-14 23:01:25 +00:00
value = None
found_value = False
2013-10-26 18:13:28 +00:00
for n in namelist :
try :
2013-11-14 23:01:25 +00:00
v = d [ n ]
found_value = True
if stack :
if callable ( v ) :
value = v ( dvalue = dvalue , value = value , stack = stack )
else :
if value :
value = stack . join ( [ value , v ] )
else :
value = v
if d . get ( n + ' _stop ' , None ) :
break
continue
value = v
2013-10-26 18:13:28 +00:00
break
except KeyError as e :
pass
2013-11-14 23:01:25 +00:00
if not found_value :
value = dvalue
2013-10-26 18:13:28 +00:00
if callable ( value ) :
value = value ( )
2014-08-05 02:41:42 +00:00
setattr ( self , cname , value )
2013-03-16 18:24:52 +00:00
if self . builddir != ' ' and self . builddir [ - 1 : ] != ' / ' :
self . builddir + = ' / '
2013-05-12 03:16:24 +00:00
def clone ( self ) :
clone = DXXCommon . UserBuildSettings ( None )
2013-06-16 02:40:05 +00:00
for grp in clone . _options ( ) :
2013-05-12 03:16:24 +00:00
for o in grp [ ' arguments ' ] :
name = o [ 0 ]
value = getattr ( self , name )
setattr ( clone , name , value )
return clone
2013-05-11 23:52:32 +00:00
class UserInstallSettings :
2013-06-16 02:40:05 +00:00
def _options ( self ) :
return (
{
' variable ' : self . _generic_variable ,
' arguments ' : (
( ' DESTDIR ' , None , ' installation stage directory ' ) ,
( ' program_name ' , None , ' name of built program ' ) ,
) ,
} ,
{
' variable ' : BoolVariable ,
' arguments ' : (
( ' register_install_target ' , True , ' report install target to SCons core ' ) ,
) ,
} ,
)
2013-05-11 23:52:32 +00:00
class UserSettings ( UserBuildSettings , UserInstallSettings ) :
2013-06-16 02:40:05 +00:00
def _options ( self ) :
return DXXCommon . UserBuildSettings . _options ( self ) + DXXCommon . UserInstallSettings . _options ( self )
2013-02-24 23:33:20 +00:00
# Base class for platform-specific settings processing
class _PlatformSettings :
2013-04-08 06:35:48 +00:00
tools = None
2013-03-16 23:15:01 +00:00
ogllibs = ' '
2013-05-05 04:01:03 +00:00
platform_objects = [ ]
2014-12-05 04:09:17 +00:00
__pkg_config_path = None
2014-12-05 02:36:34 +00:00
__pkg_config_cache = { }
2013-06-16 17:01:47 +00:00
def __init__ ( self , program , user_settings ) :
self . __program = program
self . user_settings = user_settings
@property
def env ( self ) :
return self . __program . env
2014-12-05 04:09:17 +00:00
@staticmethod
def get_pkg_config_name ( user_settings ) :
if user_settings . PKG_CONFIG :
return user_settings . PKG_CONFIG
2013-10-26 22:56:08 +00:00
else :
2014-12-05 04:09:17 +00:00
if user_settings . CHOST :
return ' %s -pkg-config ' % user_settings . CHOST
2013-10-26 22:56:08 +00:00
else :
2014-12-05 04:09:17 +00:00
return ' pkg-config '
@classmethod
def get_pkg_config_path ( cls , program ) :
if cls . __pkg_config_path :
return cls . __pkg_config_path [ 0 ]
pkgconfig = cls . get_pkg_config_name ( program . user_settings )
if pkgconfig [ 0 ] != ' / ' :
# Only valid on non-Windows
for p in os . environ . get ( ' PATH ' , ' ' ) . split ( ' : ' ) :
try :
fp = os . path . join ( p , pkgconfig )
os . close ( os . open ( fp , os . O_RDONLY ) )
pkgconfig = fp
break
except OSError as e :
if e . errno == errno . ENOENT or e . errno == errno . EACCES :
continue
raise
if pkgconfig [ 0 ] != ' / ' :
message ( program , " no usable pkg-config \" %s \" found in $PATH " % pkgconfig )
pkgconfig = None
else :
message ( program , " using pkg-config at %s " % pkgconfig )
cls . __pkg_config_path = ( pkgconfig , )
return pkgconfig
@classmethod
def _find_pkg_config ( cls , program , env , pkg , name ) :
pkgconfig = cls . get_pkg_config_path ( program )
if not pkgconfig :
message ( program , " skipping %s pkg-config settings " % name )
return { }
2014-12-04 03:31:07 +00:00
cmd = ' %s --cflags --libs %s ' % ( pkgconfig , pkg )
2014-12-05 02:36:34 +00:00
cache = cls . __pkg_config_cache
2013-10-26 22:56:08 +00:00
try :
2014-12-04 03:31:07 +00:00
return cache [ cmd ]
2013-10-26 22:56:08 +00:00
except KeyError as e :
if ( program . user_settings . verbosebuild != 0 ) :
2014-12-04 03:31:07 +00:00
message ( program , " reading %s settings from ` %s ` " % ( name , cmd ) )
2014-12-11 02:32:28 +00:00
try :
flags = env . ParseFlags ( ' ! ' + cmd )
except OSError as o :
message ( program , " pkg-config failed; user must add required flags via environment for ` %s ` " % cmd )
flags = { }
cache [ cmd ] = flags
2014-01-04 17:44:04 +00:00
return flags
2015-01-03 23:44:32 +00:00
@staticmethod
def _merge_pkg_config ( env , flags ) :
env . MergeFlags ( { k : flags [ k ] for k in flags . keys ( ) if k [ 0 ] == ' C ' or k [ 0 ] == ' L ' } )
2014-12-04 03:31:07 +00:00
def merge_SDL_mixer_config ( self , program , env ) :
2014-12-05 02:36:34 +00:00
self . _merge_pkg_config ( env , self . _find_pkg_config ( program , env , ' SDL_mixer ' , ' SDL_mixer ' ) )
2014-12-04 03:31:07 +00:00
def merge_sdl_config ( self , program , env ) :
2014-12-05 02:36:34 +00:00
self . _merge_pkg_config ( env , self . _find_pkg_config ( program , env , ' sdl ' , ' SDL ' ) )
2013-02-24 23:33:20 +00:00
# Settings to apply to mingw32 builds
class Win32PlatformSettings ( _PlatformSettings ) :
2013-04-08 06:35:48 +00:00
tools = [ ' mingw ' ]
2013-03-02 21:25:47 +00:00
def adjust_environment ( self , program , env ) :
2013-10-27 00:59:16 +00:00
env . Append ( CPPDEFINES = [ ' _WIN32 ' , ' HAVE_STRUCT_TIMEVAL ' , ' WIN32_LEAN_AND_MEAN ' ] )
2013-02-24 23:33:20 +00:00
class DarwinPlatformSettings ( _PlatformSettings ) :
2013-06-16 17:01:47 +00:00
def __init__ ( self , program , user_settings ) :
DXXCommon . _PlatformSettings . __init__ ( self , program , user_settings )
2013-03-02 21:25:47 +00:00
def adjust_environment ( self , program , env ) :
2013-02-24 23:33:20 +00:00
env . Append ( CPPDEFINES = [ ' HAVE_STRUCT_TIMESPEC ' , ' HAVE_STRUCT_TIMEVAL ' , ' __unix__ ' ] )
2013-12-06 03:55:58 +00:00
env . Append ( CPPPATH = [ os . path . join ( os . getenv ( " HOME " ) , ' Library/Frameworks/SDL.framework/Headers ' ) , ' /Library/Frameworks/SDL.framework/Headers ' ] )
2014-11-24 03:53:02 +00:00
env . Append ( FRAMEWORKS = [ ' ApplicationServices ' , ' Cocoa ' , ' SDL ' ] )
2013-04-20 23:56:13 +00:00
if ( self . user_settings . opengl == 1 ) or ( self . user_settings . opengles == 1 ) :
env . Append ( FRAMEWORKS = [ ' OpenGL ' ] )
2013-04-08 08:21:53 +00:00
env . Append ( FRAMEWORKPATH = [ os . path . join ( os . getenv ( " HOME " ) , ' Library/Frameworks ' ) , ' /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks ' ] )
2013-02-24 23:33:20 +00:00
# Settings to apply to Linux builds
class LinuxPlatformSettings ( _PlatformSettings ) :
2013-03-16 23:15:01 +00:00
__opengl_libs = [ ' GL ' , ' GLU ' ]
2013-03-17 03:29:48 +00:00
__pkg_config_sdl = { }
2013-06-16 17:01:47 +00:00
def __init__ ( self , program , user_settings ) :
DXXCommon . _PlatformSettings . __init__ ( self , program , user_settings )
2013-02-24 23:33:20 +00:00
if ( user_settings . opengles == 1 ) :
self . ogllibs = [ user_settings . opengles_lib , ' EGL ' ]
else :
2013-03-16 23:15:01 +00:00
self . ogllibs = self . __opengl_libs
2013-03-02 21:25:47 +00:00
def adjust_environment ( self , program , env ) :
2014-09-02 22:10:34 +00:00
env . Append ( CPPDEFINES = [ ' HAVE_STRUCT_TIMESPEC ' , ' HAVE_STRUCT_TIMEVAL ' ] )
2013-12-04 04:03:02 +00:00
env . Append ( CCFLAGS = [ ' -pthread ' ] )
2013-02-24 20:35:12 +00:00
2013-02-25 00:02:01 +00:00
def __init__ ( self ) :
2013-05-04 23:58:14 +00:00
LazyObjectConstructor . __init__ ( self )
2013-04-20 23:52:17 +00:00
self . sources = [ ]
2013-06-16 19:28:38 +00:00
self . __shared_program_instance [ 0 ] + = 1
self . program_instance = self . __shared_program_instance [ 0 ]
2013-02-25 00:02:01 +00:00
2013-10-25 23:58:05 +00:00
@staticmethod
def _collect_pch_candidates ( target , source , env ) :
for t in target :
scanner = t . get_source_scanner ( source [ 0 ] )
deps = scanner ( source [ 0 ] , env , scanner . path ( env ) )
for d in deps :
ds = str ( d )
env . __dxx_pch_candidates [ ds ] = env . __dxx_pch_candidates . get ( ds , 0 ) + 1
return ( target , source )
@staticmethod
def write_pch_inclusion_file ( target , source , env ) :
with open ( str ( target [ 0 ] ) , ' wt ' ) as f :
f . write ( ' /* BEGIN PCH GENERATED FILE \n * Threshold= %u \n */ \n ' % env . __dxx_pch_inclusion_count )
for ( name , count ) in env . __dxx_pch_candidates . items ( ) :
if count > = env . __dxx_pch_inclusion_count :
f . write ( ' #include " %s " \t /* %u */ \n ' % ( name , count ) )
env . Depends ( target , name )
f . write ( ' /* END PCH GENERATED FILE */ \n ' )
2014-11-17 04:02:25 +00:00
def create_header_targets ( self ) :
fs = SCons . Node . FS . get_default_fs ( )
builddir = self . user_settings . builddir
check_header_includes = os . path . join ( builddir , ' check_header_includes.cpp ' )
if not self . __shared_header_file_list :
open ( check_header_includes , ' wt ' )
git = subprocess . Popen ( [ ' git ' , ' ls-files ' , ' -z ' , ' -- ' , ' *.h ' ] , executable = ' /usr/bin/git ' , stdout = subprocess . PIPE , close_fds = True )
headers = git . communicate ( None ) [ 0 ]
excluded_directories = (
' common/arch/cocoa/ ' ,
' common/arch/carbon/ ' ,
)
self . __shared_header_file_list . extend ( [ h for h in headers . split ( ' \0 ' ) if h and not h . startswith ( excluded_directories ) ] )
dirname = os . path . join ( builddir , self . srcdir )
kwargs = {
' CXXFLAGS ' : self . env [ ' CXXFLAGS ' ] [ : ] ,
' source ' : check_header_includes
}
Depends = self . env . Depends
StaticObject = self . env . StaticObject
OBJSUFFIX = self . env [ ' OBJSUFFIX ' ]
for name in self . __shared_header_file_list :
if not name :
continue
if self . srcdir == ' common ' and not name . startswith ( ' common/ ' ) :
# Skip game-specific headers when testing common
continue
if self . srcdir [ 0 ] == ' d ' and name [ 0 ] == ' d ' and not name . startswith ( self . srcdir ) :
# Skip d1 in d2 and d2 in d1
continue
CPPFLAGS = self . env [ ' CPPFLAGS ' ] [ : ]
if name [ : 24 ] == ' common/include/compiler- ' :
CPPFLAGS . extend ( [ ' -include ' , ' dxxsconf.h ' ] )
CPPFLAGS . extend ( [ ' -include ' , name ] )
if self . user_settings . verbosebuild :
kwargs [ ' CXXCOMSTR ' ] = " Checking %s %s %s " % ( self . target , builddir , name )
Depends ( StaticObject ( target = os . path . join ( ' %s /chi/ %s %s ' % ( dirname , name , OBJSUFFIX ) ) , CPPFLAGS = CPPFLAGS , * * kwargs ) , fs . File ( name ) )
2013-11-28 04:21:20 +00:00
def create_pch_node ( self , dirname , configure_pch_flags ) :
2014-11-17 04:02:25 +00:00
if self . user_settings . check_header_includes :
self . create_header_targets ( )
2013-11-28 04:21:20 +00:00
if not configure_pch_flags :
self . env . _dxx_pch_node = None
return
2013-10-25 23:58:05 +00:00
dirname = os . path . join ( self . user_settings . builddir , dirname )
target = os . path . join ( dirname , ' pch.h.gch ' )
source = os . path . join ( dirname , ' pch.cpp ' )
2013-11-28 04:21:20 +00:00
self . env . _dxx_pch_node = self . env . StaticObject ( target = target , source = source , CXXFLAGS = self . env [ ' CXXFLAGS ' ] + configure_pch_flags [ ' CXXFLAGS ' ] )
self . env . Append ( CXXFLAGS = [ ' -include ' , str ( self . env . _dxx_pch_node [ 0 ] ) [ : - 4 ] , ' -Winvalid-pch ' ] )
2013-10-25 23:58:05 +00:00
self . env . __dxx_pch_candidates = { }
self . env . __dxx_pch_inclusion_count = int ( self . user_settings . pch )
self . env [ ' BUILDERS ' ] [ ' StaticObject ' ] . add_emitter ( ' .cpp ' , self . _collect_pch_candidates )
self . env . Command ( source , None , self . write_pch_inclusion_file )
2013-11-16 22:59:17 +00:00
def _quote_cppdefine ( self , s ) :
r = ' '
prior = False
for c in str ( s ) :
# No xdigit support in str
2014-09-02 22:09:44 +00:00
if c in ' ()*+,-./:=[]_ ' or ( c . isalnum ( ) and not ( prior and ( c . isdigit ( ) or c in ' abcdefABCDEF ' ) ) ) :
2013-11-16 22:59:17 +00:00
r + = c
2014-09-02 22:09:44 +00:00
elif c == ' \n ' :
r + = r ' \ n '
2013-11-16 22:59:17 +00:00
else :
r + = ' \\ \\ x ' + binascii . b2a_hex ( c )
prior = True
2014-09-02 22:09:44 +00:00
continue
prior = False
2013-11-16 22:59:17 +00:00
return ' \\ " ' + r + ' \\ " '
2013-02-25 00:02:01 +00:00
def prepare_environment ( self ) :
# Prettier build messages......
2015-01-11 05:08:30 +00:00
# Move target to end of C++ source command
2014-09-02 22:09:07 +00:00
target_string = ' -o $TARGET '
cxxcom = self . env [ ' CXXCOM ' ]
if target_string + ' ' in cxxcom :
2015-01-11 05:08:30 +00:00
cxxcom = cxxcom . replace ( target_string , ' ' ) + target_string
2015-01-11 05:08:30 +00:00
# Add ccache/distcc only for compile, not link
if self . user_settings . ccache :
cxxcom = self . user_settings . ccache + ' ' + cxxcom
if self . user_settings . distcc :
self . env [ ' ENV ' ] [ ' CCACHE_PREFIX ' ] = self . user_settings . distcc
elif self . user_settings . distcc :
cxxcom = self . user_settings . distcc + ' ' + cxxcom
2015-01-11 05:08:30 +00:00
self . env [ ' CXXCOM ' ] = cxxcom
# Move target to end of link command
linkcom = self . env [ ' LINKCOM ' ]
if target_string + ' ' in linkcom :
linkcom = linkcom . replace ( target_string , ' ' ) + target_string
# Add $CXXFLAGS to link command
cxxflags = ' $CXXFLAGS '
if ' ' + cxxflags not in linkcom :
linkflags = ' $LINKFLAGS '
linkcom = linkcom . replace ( linkflags , cxxflags + linkflags )
self . env [ ' LINKCOM ' ] = linkcom
2015-01-11 05:08:30 +00:00
# Custom DISTCC_HOSTS per target
distcc_hosts = self . user_settings . distcc_hosts
if distcc_hosts is not None :
self . env [ ' ENV ' ] [ ' DISTCC_HOSTS ' ] = distcc_hosts
2013-02-25 00:02:01 +00:00
if ( self . user_settings . verbosebuild == 0 ) :
2013-03-16 21:29:23 +00:00
builddir = self . user_settings . builddir if self . user_settings . builddir != ' ' else ' . '
self . env [ " CXXCOMSTR " ] = " Compiling %s %s $SOURCE " % ( self . target , builddir )
self . env [ " LINKCOMSTR " ] = " Linking %s $TARGET " % self . target
2013-02-25 00:02:01 +00:00
2013-03-03 01:03:33 +00:00
# Use -Wundef to catch when a shared source file includes a
# shared header that misuses conditional compilation. Use
# -Werror=undef to make this fatal. Both are needed, since
# gcc 4.5 silently ignores -Werror=undef. On gcc 4.5, misuse
# produces a warning. On gcc 4.7, misuse produces an error.
2014-09-17 02:09:53 +00:00
Werror = get_Werror_string ( self . user_settings . CXXFLAGS )
2015-03-22 18:49:21 +00:00
self . env . Append ( CCFLAGS = [ ' -Wall ' , Werror + ' missing-declarations ' , Werror + ' pointer-arith ' , Werror + ' undef ' , Werror + ' type-limits ' , Werror + ' uninitialized ' , Werror + ' empty-body ' , Werror + ' ignored-qualifiers ' , Werror + ' unused ' , ' -funsigned-char ' , Werror + ' format-security ' ] )
2013-06-27 02:35:22 +00:00
self . env . Append ( CPPPATH = [ ' common/include ' , ' common/main ' , ' . ' , self . user_settings . builddir ] )
2013-11-16 22:59:17 +00:00
self . env . Append ( CPPFLAGS = SCons . Util . CLVar ( ' -Wno-sign-compare ' ) )
2013-03-03 01:03:33 +00:00
if ( self . user_settings . editor == 1 ) :
self . env . Append ( CPPPATH = [ ' common/include/editor ' ] )
2013-02-25 00:02:01 +00:00
# Get traditional compiler environment variables
2015-01-11 05:08:30 +00:00
for cc in ( ' CXX ' , ' RC ' , ) :
2013-05-18 02:15:01 +00:00
value = getattr ( self . user_settings , cc )
if value is not None :
self . env [ cc ] = value
2013-11-26 03:59:44 +00:00
for flags in [ ' CPPFLAGS ' , ' CXXFLAGS ' , ' LIBS ' ] :
2013-05-18 02:15:01 +00:00
value = getattr ( self . user_settings , flags )
if value is not None :
2013-06-01 23:46:05 +00:00
self . env . Append ( * * { flags : SCons . Util . CLVar ( value ) } )
2013-06-01 23:46:05 +00:00
if self . user_settings . LDFLAGS :
self . env . Append ( LINKFLAGS = SCons . Util . CLVar ( self . user_settings . LDFLAGS ) )
2014-06-29 23:26:05 +00:00
if self . user_settings . lto :
f = [ ' -flto ' , ' -fno-fat-lto-objects ' ]
2015-01-11 05:08:30 +00:00
self . env . Append ( CXXFLAGS = f )
2013-02-25 00:02:01 +00:00
def check_endian ( self ) :
# set endianess
if ( self . __endian == " big " ) :
2013-06-16 19:28:38 +00:00
message ( self , " BigEndian machine detected " )
2013-03-03 00:53:35 +00:00
self . env . Append ( CPPDEFINES = [ ' WORDS_BIGENDIAN ' ] )
2013-02-25 00:02:01 +00:00
elif ( self . __endian == " little " ) :
2013-06-16 19:28:38 +00:00
message ( self , " LittleEndian machine detected " )
2013-02-25 00:02:01 +00:00
def check_platform ( self ) :
# windows or *nix?
2013-12-05 23:01:34 +00:00
platform_name = self . user_settings . host_platform
2013-06-16 19:07:58 +00:00
if self . _argument_prefix_list :
prefix = ' with prefix list %s ' % list ( self . _argument_prefix_list )
else :
prefix = ' '
2013-08-25 20:43:28 +00:00
message ( self , " compiling on %s for %s into %s %s " % ( sys . platform , platform_name , self . user_settings . builddir or ' . ' , prefix ) )
2013-04-28 18:04:06 +00:00
if platform_name == ' win32 ' :
2013-03-03 01:54:44 +00:00
platform = self . Win32PlatformSettings
2013-04-28 18:04:06 +00:00
elif platform_name == ' darwin ' :
2013-03-03 01:54:44 +00:00
platform = self . DarwinPlatformSettings
2013-02-25 00:02:01 +00:00
else :
2013-03-03 01:54:44 +00:00
platform = self . LinuxPlatformSettings
2013-06-16 17:01:47 +00:00
self . platform_settings = platform ( self , self . user_settings )
2013-04-08 06:35:48 +00:00
# Acquire environment object...
self . env = Environment ( ENV = os . environ , tools = platform . tools )
2013-10-26 22:56:08 +00:00
# On Linux hosts, always run this. It should work even when
# cross-compiling a Rebirth to run elsewhere.
2014-12-05 04:09:17 +00:00
if sys . platform == ' linux2 ' or sys . platform == ' darwin ' :
2014-01-04 17:44:04 +00:00
self . platform_settings . merge_sdl_config ( self , self . env )
2014-12-04 03:31:07 +00:00
if self . user_settings . sdlmixer :
self . platform_settings . merge_SDL_mixer_config ( self , self . env )
2013-04-08 06:35:48 +00:00
self . platform_settings . adjust_environment ( self , self . env )
2013-02-25 00:02:01 +00:00
def process_user_settings ( self ) :
env = self . env
# opengl or software renderer?
if ( self . user_settings . opengl == 1 ) or ( self . user_settings . opengles == 1 ) :
if ( self . user_settings . opengles == 1 ) :
2013-06-16 19:28:38 +00:00
message ( self , " building with OpenGL ES " )
2013-02-25 00:02:01 +00:00
env . Append ( CPPDEFINES = [ ' OGLES ' ] )
else :
2013-06-16 19:28:38 +00:00
message ( self , " building with OpenGL " )
2013-02-25 00:02:01 +00:00
env . Append ( CPPDEFINES = [ ' OGL ' ] )
# debug?
if ( self . user_settings . debug == 1 ) :
2013-06-16 19:28:38 +00:00
message ( self , " including: DEBUG " )
2013-09-22 23:28:06 +00:00
env . Prepend ( CXXFLAGS = [ ' -g ' ] )
2013-02-25 00:02:01 +00:00
else :
env . Append ( CPPDEFINES = [ ' NDEBUG ' , ' RELEASE ' ] )
2015-03-07 17:20:41 +00:00
env . Prepend ( CXXFLAGS = [ ' -O2 ' ] )
2012-05-20 18:51:21 +00:00
if self . user_settings . memdebug :
message ( self , " including: MEMDEBUG " )
env . Append ( CPPDEFINES = [ ' DEBUG_MEMORY_ALLOCATIONS ' ] )
2013-02-25 00:02:01 +00:00
# profiler?
if ( self . user_settings . profiler == 1 ) :
env . Append ( CPPFLAGS = [ ' -pg ' ] )
#editor build?
if ( self . user_settings . editor == 1 ) :
env . Append ( CPPDEFINES = [ ' EDITOR ' ] )
# IPv6 compability?
if ( self . user_settings . ipv6 == 1 ) :
env . Append ( CPPDEFINES = [ ' IPv6 ' ] )
# UDP support?
if ( self . user_settings . use_udp == 1 ) :
env . Append ( CPPDEFINES = [ ' USE_UDP ' ] )
# Tracker support? (Relies on UDP)
if ( self . user_settings . use_tracker == 1 ) :
env . Append ( CPPDEFINES = [ ' USE_TRACKER ' ] )
2013-03-03 00:53:35 +00:00
2013-05-03 22:52:57 +00:00
# Raspberry Pi?
if ( self . user_settings . raspberrypi == 1 ) :
2015-03-20 20:46:33 +00:00
message ( self , " Raspberry Pi: using VideoCore libs in \" %s \" " % self . user_settings . rpi_vc_path )
2013-05-03 22:52:57 +00:00
env . Append ( CPPDEFINES = [ ' RPI ' , ' WORDS_NEED_ALIGNMENT ' ] )
2015-03-20 23:56:18 +00:00
# use CPPFLAGS -isystem instead of CPPPATH because these those header files
2015-03-20 20:34:43 +00:00
# are not very clean and would trigger some warnings we usually consider as
# errors. Using them as system headers will make gcc ignoring any warnings.
2015-03-20 23:56:18 +00:00
env . Append ( CPPFLAGS = [
2015-03-20 20:34:43 +00:00
' -isystem= ' + self . user_settings . rpi_vc_path + ' /include ' ,
' -isystem= ' + self . user_settings . rpi_vc_path + ' /include/interface/vcos/pthreads ' ,
' -isystem= ' + self . user_settings . rpi_vc_path + ' /include/interface/vmcs_host/linux ' ] )
2013-06-01 23:46:05 +00:00
env . Append ( LIBPATH = self . user_settings . rpi_vc_path + ' /lib ' )
2013-06-01 23:46:05 +00:00
env . Append ( LIBS = [ ' bcm_host ' ] )
2013-05-03 22:52:57 +00:00
2013-03-03 01:03:33 +00:00
class DXXArchive ( DXXCommon ) :
srcdir = ' common '
target = ' dxx-common '
2013-05-05 04:01:03 +00:00
__objects_common = DXXCommon . create_lazy_object_property ( [ os . path . join ( srcdir , f ) for f in [
2012-11-11 22:12:51 +00:00
' 2d/2dsline.cpp ' ,
2012-11-11 22:12:51 +00:00
' 2d/bitblt.cpp ' ,
2012-11-11 22:12:51 +00:00
' 2d/bitmap.cpp ' ,
2012-11-11 22:12:51 +00:00
' 2d/box.cpp ' ,
2012-11-11 22:12:51 +00:00
' 2d/canvas.cpp ' ,
2012-11-11 22:12:51 +00:00
' 2d/circle.cpp ' ,
2012-11-11 22:12:51 +00:00
' 2d/disc.cpp ' ,
2012-11-11 22:12:51 +00:00
' 2d/gpixel.cpp ' ,
2012-11-11 22:12:51 +00:00
' 2d/line.cpp ' ,
2012-11-11 22:12:51 +00:00
' 2d/pixel.cpp ' ,
2012-11-11 22:12:51 +00:00
' 2d/rect.cpp ' ,
2012-11-11 22:12:51 +00:00
' 2d/rle.cpp ' ,
2012-11-11 22:12:51 +00:00
' 2d/scalec.cpp ' ,
2012-11-11 22:12:51 +00:00
' 3d/draw.cpp ' ,
2012-11-11 22:12:51 +00:00
' 3d/globvars.cpp ' ,
2012-11-11 22:12:51 +00:00
' 3d/instance.cpp ' ,
2012-11-11 22:12:51 +00:00
' 3d/matrix.cpp ' ,
2012-11-11 22:12:51 +00:00
' 3d/points.cpp ' ,
2012-11-11 22:12:51 +00:00
' 3d/rod.cpp ' ,
2012-11-11 22:12:51 +00:00
' 3d/setup.cpp ' ,
2012-11-11 22:12:51 +00:00
' arch/sdl/joy.cpp ' ,
2012-11-11 22:12:51 +00:00
' arch/sdl/rbaudio.cpp ' ,
2012-11-11 22:12:51 +00:00
' arch/sdl/window.cpp ' ,
2012-11-11 22:12:51 +00:00
' maths/fixc.cpp ' ,
2012-11-11 22:12:51 +00:00
' maths/rand.cpp ' ,
2012-11-11 22:12:51 +00:00
' maths/tables.cpp ' ,
2012-11-11 22:12:51 +00:00
' maths/vecmat.cpp ' ,
2012-11-11 22:12:51 +00:00
' misc/error.cpp ' ,
2012-11-11 22:12:51 +00:00
' misc/hmp.cpp ' ,
2012-11-11 22:12:51 +00:00
' misc/ignorecase.cpp ' ,
2012-11-11 22:12:51 +00:00
' misc/strutil.cpp ' ,
2012-11-11 22:12:51 +00:00
' texmap/ntmap.cpp ' ,
2012-11-11 22:12:51 +00:00
' texmap/scanline.cpp '
2013-03-03 01:03:33 +00:00
]
2013-03-24 23:03:46 +00:00
] )
objects_editor = DXXCommon . create_lazy_object_property ( [ os . path . join ( srcdir , f ) for f in [
2012-11-17 06:14:09 +00:00
' editor/func.cpp ' ,
2012-11-17 06:14:09 +00:00
' ui/button.cpp ' ,
2012-11-17 06:14:09 +00:00
' ui/checkbox.cpp ' ,
2012-11-17 06:14:09 +00:00
' ui/dialog.cpp ' ,
2012-11-17 06:14:09 +00:00
' ui/file.cpp ' ,
2012-11-17 06:14:09 +00:00
' ui/gadget.cpp ' ,
2012-11-17 06:14:09 +00:00
' ui/icon.cpp ' ,
2012-11-17 06:14:09 +00:00
' ui/inputbox.cpp ' ,
2012-11-17 06:14:09 +00:00
' ui/keypad.cpp ' ,
2012-11-17 06:14:09 +00:00
' ui/keypress.cpp ' ,
2012-11-17 06:14:09 +00:00
' ui/listbox.cpp ' ,
2012-11-17 06:14:09 +00:00
' ui/menu.cpp ' ,
2012-11-17 06:14:09 +00:00
' ui/menubar.cpp ' ,
2012-11-17 06:14:09 +00:00
' ui/message.cpp ' ,
2012-11-17 06:14:09 +00:00
' ui/radio.cpp ' ,
2012-11-17 06:14:09 +00:00
' ui/scroll.cpp ' ,
2012-11-17 06:14:09 +00:00
' ui/ui.cpp ' ,
2012-11-17 06:14:09 +00:00
' ui/uidraw.cpp ' ,
2012-11-17 06:14:09 +00:00
' ui/userbox.cpp '
2013-03-03 01:03:33 +00:00
]
2013-03-24 23:03:46 +00:00
] )
2013-03-03 01:03:33 +00:00
# for non-ogl
2013-03-24 23:03:46 +00:00
objects_arch_sdl = DXXCommon . create_lazy_object_property ( [ os . path . join ( srcdir , f ) for f in [
2014-11-16 19:14:51 +00:00
' 3d/clipper.cpp ' ,
2012-11-11 22:12:51 +00:00
' texmap/tmapflat.cpp '
2013-03-03 01:03:33 +00:00
]
2013-03-24 23:03:46 +00:00
] )
objects_arch_sdlmixer = DXXCommon . create_lazy_object_property ( [ os . path . join ( srcdir , f ) for f in [
2012-11-11 22:12:51 +00:00
' arch/sdl/digi_mixer_music.cpp ' ,
2013-03-03 01:03:33 +00:00
]
2013-03-24 23:03:46 +00:00
] )
2015-01-03 23:44:32 +00:00
class Win32PlatformSettings ( LazyObjectConstructor , DXXCommon . Win32PlatformSettings ) :
2013-05-05 04:01:03 +00:00
platform_objects = LazyObjectConstructor . create_lazy_object_property ( [
2012-11-11 22:12:51 +00:00
' common/arch/win32/messagebox.cpp '
2013-05-05 04:01:03 +00:00
] )
2013-06-16 17:01:47 +00:00
def __init__ ( self , program , user_settings ) :
2013-05-05 04:01:03 +00:00
LazyObjectConstructor . __init__ ( self )
2013-06-16 17:01:47 +00:00
DXXCommon . Win32PlatformSettings . __init__ ( self , program , user_settings )
2013-05-05 04:01:03 +00:00
self . user_settings = user_settings
2015-01-03 23:44:32 +00:00
class DarwinPlatformSettings ( LazyObjectConstructor , DXXCommon . DarwinPlatformSettings ) :
2014-11-23 12:25:42 +00:00
platform_objects = LazyObjectConstructor . create_lazy_object_property ( [
2014-11-24 03:53:02 +00:00
' common/arch/cocoa/messagebox.mm ' ,
2014-11-23 12:25:42 +00:00
' common/arch/cocoa/SDLMain.m '
] )
def __init__ ( self , program , user_settings ) :
LazyObjectConstructor . __init__ ( self )
DXXCommon . DarwinPlatformSettings . __init__ ( self , program , user_settings )
self . user_settings = user_settings
2013-05-05 04:01:03 +00:00
@property
def objects_common ( self ) :
objects_common = self . __objects_common
return objects_common + self . platform_settings . platform_objects
2013-05-12 03:16:24 +00:00
def __init__ ( self , user_settings ) :
2013-03-03 01:03:33 +00:00
self . PROGRAM_NAME = ' DXX-Archive '
2013-06-16 19:07:58 +00:00
self . _argument_prefix_list = None
2013-03-03 01:03:33 +00:00
DXXCommon . __init__ ( self )
2013-05-12 03:16:24 +00:00
self . user_settings = user_settings . clone ( )
2013-04-20 23:56:13 +00:00
self . check_platform ( )
2013-03-03 01:03:33 +00:00
self . prepare_environment ( )
self . check_endian ( )
self . process_user_settings ( )
2013-07-27 22:16:14 +00:00
self . configure_environment ( )
2013-11-28 04:21:20 +00:00
self . create_pch_node ( self . srcdir , self . configure_pch_flags )
2013-07-27 22:16:14 +00:00
def configure_environment ( self ) :
fs = SCons . Node . FS . get_default_fs ( )
builddir = fs . Dir ( self . user_settings . builddir or ' . ' )
tests = ConfigureTests ( self . program_message_prefix , self . user_settings )
log_file = fs . File ( ' sconf.log ' , builddir )
conf = self . env . Configure ( custom_tests = {
k : getattr ( tests , k ) for k in tests . custom_tests
} ,
conf_dir = fs . Dir ( ' .sconf_temp ' , builddir ) ,
log_file = log_file ,
config_h = fs . File ( ' dxxsconf.h ' , builddir ) ,
clean = False ,
help = False
)
2013-11-28 04:21:20 +00:00
self . configure_added_environment_flags = tests . successful_flags
self . configure_pch_flags = None
2013-07-27 22:16:14 +00:00
if not conf . env :
return
try :
for k in tests . custom_tests :
getattr ( conf , k ) ( )
except SCons . Errors . StopError as e :
raise SCons . Errors . StopError ( e . args [ 0 ] + ' See {log_file} for details. ' . format ( log_file = log_file ) , * e . args [ 1 : ] )
self . env = conf . Finish ( )
2013-11-28 04:21:20 +00:00
self . configure_pch_flags = tests . pch_flags
2013-03-03 01:03:33 +00:00
2013-03-03 00:53:35 +00:00
class DXXProgram ( DXXCommon ) :
# version number
VERSION_MAJOR = 0
2013-07-19 14:15:49 +00:00
VERSION_MINOR = 58
2013-08-03 12:16:05 +00:00
VERSION_MICRO = 1
2013-03-16 21:30:13 +00:00
static_archive_construction = { }
2014-07-26 17:40:12 +00:00
# None when unset. Tuple of one once cached.
_computed_extra_version = None
2013-03-24 23:03:46 +00:00
def _apply_target_name ( self , name ) :
return os . path . join ( os . path . dirname ( name ) , ' . %s . %s ' % ( self . target , os . path . splitext ( os . path . basename ( name ) ) [ 0 ] ) )
2013-04-21 19:49:59 +00:00
objects_similar_arch_ogl = DXXCommon . create_lazy_object_property ( [ {
' source ' : [ os . path . join ( ' similar ' , f ) for f in [
2012-11-11 22:12:51 +00:00
' arch/ogl/gr.cpp ' ,
2012-11-11 22:12:51 +00:00
' arch/ogl/ogl.cpp ' ,
2013-03-03 01:03:33 +00:00
]
2013-04-21 19:49:59 +00:00
] ,
' transform_target ' : _apply_target_name ,
} ] )
objects_similar_arch_sdl = DXXCommon . create_lazy_object_property ( [ {
' source ' : [ os . path . join ( ' similar ' , f ) for f in [
2012-11-11 22:12:51 +00:00
' arch/sdl/gr.cpp ' ,
2013-03-03 01:03:33 +00:00
]
2013-04-21 19:49:59 +00:00
] ,
' transform_target ' : _apply_target_name ,
} ] )
objects_similar_arch_sdlmixer = DXXCommon . create_lazy_object_property ( [ {
' source ' : [ os . path . join ( ' similar ' , f ) for f in [
2012-11-11 22:12:51 +00:00
' arch/sdl/digi_mixer.cpp ' ,
2012-11-11 22:12:51 +00:00
' arch/sdl/jukebox.cpp '
2013-03-03 01:03:33 +00:00
]
2013-04-21 19:49:59 +00:00
] ,
' transform_target ' : _apply_target_name ,
} ] )
2013-06-02 21:46:32 +00:00
__objects_common = DXXCommon . create_lazy_object_property ( [ {
2013-04-21 19:49:59 +00:00
' source ' : [ os . path . join ( ' similar ' , f ) for f in [
2012-11-11 22:12:51 +00:00
' 2d/font.cpp ' ,
2012-11-11 22:12:51 +00:00
' 2d/palette.cpp ' ,
2012-11-11 22:12:51 +00:00
' 2d/pcx.cpp ' ,
2012-11-11 22:12:51 +00:00
' 3d/interp.cpp ' ,
2012-11-11 22:12:51 +00:00
' arch/sdl/digi.cpp ' ,
2012-11-11 22:12:51 +00:00
' arch/sdl/digi_audio.cpp ' ,
2012-11-11 22:12:51 +00:00
' arch/sdl/event.cpp ' ,
2012-11-11 22:12:51 +00:00
' arch/sdl/init.cpp ' ,
2012-11-11 22:12:51 +00:00
' arch/sdl/key.cpp ' ,
2012-11-11 22:12:51 +00:00
' arch/sdl/mouse.cpp ' ,
2012-11-11 22:12:51 +00:00
' arch/sdl/timer.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/ai.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/aipath.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/automap.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/bm.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/cntrlcen.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/collide.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/config.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/console.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/controls.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/credits.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/digiobj.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/effects.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/endlevel.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/fireball.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/fuelcen.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/fvi.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/game.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/gamecntl.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/gamefont.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/gamemine.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/gamerend.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/gamesave.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/gameseg.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/gameseq.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/gauges.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/hostage.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/hud.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/iff.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/inferno.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/kconfig.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/kmatrix.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/laser.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/lighting.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/menu.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/mglobal.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/mission.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/morph.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/multi.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/multibot.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/newdemo.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/newmenu.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/object.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/paging.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/physics.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/piggy.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/player.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/playsave.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/polyobj.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/powerup.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/render.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/robot.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/scores.cpp ' ,
2014-10-04 17:53:09 +00:00
' main/segment.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/slew.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/songs.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/state.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/switch.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/terrain.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/texmerge.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/text.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/titles.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/vclip.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/wall.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/weapon.cpp ' ,
2012-11-11 22:12:51 +00:00
' mem/mem.cpp ' ,
2012-11-11 22:12:51 +00:00
' misc/args.cpp ' ,
2012-11-11 22:12:51 +00:00
' misc/hash.cpp ' ,
2012-11-11 22:12:51 +00:00
' misc/physfsx.cpp ' ,
2013-03-03 01:03:33 +00:00
]
2013-04-21 19:49:59 +00:00
] ,
' transform_target ' : _apply_target_name ,
} ] )
2013-04-21 17:59:38 +00:00
objects_editor = DXXCommon . create_lazy_object_property ( [ {
2013-04-21 19:49:59 +00:00
' source ' : [ os . path . join ( ' similar ' , f ) for f in [
2012-11-17 06:14:09 +00:00
' editor/autosave.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/centers.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/curves.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/dumpmine.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/eglobal.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/elight.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/eobject.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/eswitch.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/group.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/info.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/kbuild.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/kcurve.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/kfuncs.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/kgame.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/khelp.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/kmine.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/ksegmove.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/ksegsel.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/ksegsize.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/ktmap.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/kview.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/med.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/meddraw.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/medmisc.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/medrobot.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/medsel.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/medwall.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/mine.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/objpage.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/segment.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/seguvs.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/texpage.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/texture.cpp ' ,
2013-03-03 01:03:33 +00:00
]
2013-03-03 01:03:33 +00:00
] ,
' transform_target ' : _apply_target_name ,
} ] )
objects_use_udp = DXXCommon . create_lazy_object_property ( [ {
' source ' : [ os . path . join ( ' similar ' , f ) for f in [
2012-11-11 22:12:51 +00:00
' main/net_udp.cpp ' ,
2013-03-03 01:03:33 +00:00
]
2013-04-21 19:49:59 +00:00
] ,
' transform_target ' : _apply_target_name ,
} ] )
2013-03-03 00:53:35 +00:00
class UserSettings ( DXXCommon . UserSettings ) :
2013-07-04 03:29:02 +00:00
@property
def BIN_DIR ( self ) :
2013-03-03 00:53:35 +00:00
# installation path
2013-07-04 03:29:02 +00:00
return self . prefix + ' /bin '
2013-03-03 00:53:35 +00:00
# Settings to apply to mingw32 builds
2015-01-03 23:44:32 +00:00
class Win32PlatformSettings ( DXXCommon . Win32PlatformSettings ) :
2013-06-16 17:01:47 +00:00
def __init__ ( self , program , user_settings ) :
DXXCommon . Win32PlatformSettings . __init__ ( self , program , user_settings )
2013-03-03 00:53:35 +00:00
user_settings . sharepath = ' '
2013-06-02 21:46:32 +00:00
self . platform_objects = self . platform_objects [ : ]
2013-03-03 00:53:35 +00:00
def adjust_environment ( self , program , env ) :
DXXCommon . Win32PlatformSettings . adjust_environment ( self , program , env )
2013-06-02 21:46:32 +00:00
rcbasename = os . path . join ( program . srcdir , ' arch/win32/ %s ' % program . target )
self . platform_objects . append ( env . RES ( target = ' %s %s %s ' % ( program . user_settings . builddir , rcbasename , env [ " OBJSUFFIX " ] ) , source = ' %s .rc ' % rcbasename ) )
2013-04-21 20:40:05 +00:00
env . Append ( CPPPATH = [ os . path . join ( program . srcdir , ' arch/win32/include ' ) ] )
2013-06-01 23:46:05 +00:00
env . Append ( LINKFLAGS = ' -mwindows ' )
2013-06-01 23:46:05 +00:00
env . Append ( LIBS = [ ' glu32 ' , ' wsock32 ' , ' ws2_32 ' , ' winmm ' , ' mingw32 ' , ' SDLmain ' , ' SDL ' ] )
2013-03-03 00:53:35 +00:00
# Settings to apply to Apple builds
2015-01-03 23:44:32 +00:00
class DarwinPlatformSettings ( DXXCommon . DarwinPlatformSettings ) :
2013-06-16 17:01:47 +00:00
def __init__ ( self , program , user_settings ) :
DXXCommon . DarwinPlatformSettings . __init__ ( self , program , user_settings )
2013-03-03 00:53:35 +00:00
user_settings . sharepath = ' '
2014-11-23 12:25:42 +00:00
self . platform_objects = self . platform_objects [ : ]
2013-03-03 00:53:35 +00:00
def adjust_environment ( self , program , env ) :
DXXCommon . DarwinPlatformSettings . adjust_environment ( self , program , env )
2013-05-05 23:20:06 +00:00
VERSION = str ( program . VERSION_MAJOR ) + ' . ' + str ( program . VERSION_MINOR )
if ( program . VERSION_MICRO ) :
VERSION + = ' . ' + str ( program . VERSION_MICRO )
env [ ' VERSION_NUM ' ] = VERSION
env [ ' VERSION_NAME ' ] = program . PROGRAM_NAME + ' v ' + VERSION
2013-03-03 00:53:35 +00:00
# Settings to apply to Linux builds
2015-01-03 23:44:32 +00:00
class LinuxPlatformSettings ( DXXCommon . LinuxPlatformSettings ) :
2013-06-16 17:01:47 +00:00
def __init__ ( self , program , user_settings ) :
DXXCommon . LinuxPlatformSettings . __init__ ( self , program , user_settings )
2015-01-03 23:44:32 +00:00
if user_settings . sharepath and user_settings . sharepath [ - 1 ] != ' / ' :
user_settings . sharepath + = ' / '
2013-03-03 00:53:35 +00:00
2013-06-02 21:46:32 +00:00
@property
def objects_common ( self ) :
objects_common = self . __objects_common
2013-08-24 20:54:29 +00:00
if ( self . user_settings . use_udp == 1 ) :
objects_common = objects_common + self . objects_use_udp
2013-06-02 21:46:32 +00:00
return objects_common + self . platform_settings . platform_objects
2013-10-26 18:13:28 +00:00
def __init__ ( self , prefix , variables ) :
self . variables = variables
2013-06-16 19:07:58 +00:00
self . _argument_prefix_list = prefix
2013-03-03 00:53:35 +00:00
DXXCommon . __init__ ( self )
2013-04-21 20:42:15 +00:00
self . banner ( )
2013-07-04 03:29:04 +00:00
self . user_settings = self . UserSettings ( program = self )
2013-10-26 18:13:28 +00:00
self . user_settings . register_variables ( prefix = prefix , variables = self . variables )
def init ( self , substenv ) :
self . user_settings . read_variables ( self . variables , substenv )
2013-03-16 21:30:13 +00:00
if not DXXProgram . static_archive_construction . has_key ( self . user_settings . builddir ) :
2013-05-12 03:16:24 +00:00
DXXProgram . static_archive_construction [ self . user_settings . builddir ] = DXXArchive ( self . user_settings )
2013-03-03 00:53:35 +00:00
self . check_platform ( )
2013-03-03 00:53:35 +00:00
self . prepare_environment ( )
self . check_endian ( )
self . process_user_settings ( )
self . register_program ( )
def prepare_environment ( self ) :
DXXCommon . prepare_environment ( self )
2013-11-28 04:21:20 +00:00
archive = DXXProgram . static_archive_construction [ self . user_settings . builddir ]
self . env . Append ( * * archive . configure_added_environment_flags )
self . create_pch_node ( self . srcdir , archive . configure_pch_flags )
2014-09-17 02:45:32 +00:00
self . env . Append ( CPPDEFINES = [ ( ' DXX_VERSION_SEQ ' , ' , ' . join ( [ str ( self . VERSION_MAJOR ) , str ( self . VERSION_MINOR ) , str ( self . VERSION_MICRO ) ] ) ) ] )
2013-11-28 23:23:18 +00:00
# For PRIi64
self . env . Append ( CPPDEFINES = [ ( ' __STDC_FORMAT_MACROS ' , ) ] )
2013-05-11 18:35:01 +00:00
self . env . Append ( CPPPATH = [ os . path . join ( self . srcdir , f ) for f in [ ' include ' , ' main ' , ' arch/include ' ] ] )
2013-03-03 00:53:35 +00:00
def banner ( self ) :
2013-04-21 20:42:15 +00:00
VERSION_STRING = ' v ' + str ( self . VERSION_MAJOR ) + ' . ' + str ( self . VERSION_MINOR ) + ' . ' + str ( self . VERSION_MICRO )
print ' \n ===== ' + self . PROGRAM_NAME + VERSION_STRING + ' ===== \n '
2013-03-03 00:53:35 +00:00
def check_platform ( self ) :
DXXCommon . check_platform ( self )
env = self . env
# windows or *nix?
if sys . platform == ' darwin ' :
2013-05-05 23:20:06 +00:00
VERSION = str ( self . VERSION_MAJOR ) + ' . ' + str ( self . VERSION_MINOR )
if ( self . VERSION_MICRO ) :
VERSION + = ' . ' + str ( self . VERSION_MICRO )
2013-03-03 00:53:35 +00:00
env [ ' VERSION_NUM ' ] = VERSION
env [ ' VERSION_NAME ' ] = self . PROGRAM_NAME + ' v ' + VERSION
2013-12-05 22:47:43 +00:00
env . Append ( LIBS = [ ' m ' ] )
2013-03-03 00:53:35 +00:00
def process_user_settings ( self ) :
DXXCommon . process_user_settings ( self )
env = self . env
# opengl or software renderer?
# profiler?
if ( self . user_settings . profiler == 1 ) :
2013-06-01 23:46:05 +00:00
env . Append ( LINKFLAGS = ' -pg ' )
2013-03-03 00:53:35 +00:00
#editor build?
if ( self . user_settings . editor == 1 ) :
env . Append ( CPPPATH = [ os . path . join ( self . srcdir , ' include/editor ' ) ] )
2013-02-25 00:02:01 +00:00
env . Append ( CPPDEFINES = [ ( ' SHAREPATH ' , ' \\ " ' + str ( self . user_settings . sharepath ) + ' \\ " ' ) ] )
2013-12-04 01:43:19 +00:00
def register_program ( self ) :
self . _register_program ( self . shortname )
2014-07-26 17:40:12 +00:00
@classmethod
def compute_extra_version ( cls ) :
c = cls . _computed_extra_version
if c is None :
git = ( os . environ . get ( ' GIT ' , ' git ' ) ) . split ( )
v = s = None
if git :
v = cls . _compute_extra_version ( git )
if v :
g = subprocess . Popen ( git + [ ' status ' , ' --short ' , ' --branch ' ] , executable = git [ 0 ] , stdout = subprocess . PIPE , stderr = subprocess . PIPE )
( go , ge ) = g . communicate ( None )
if not g . wait ( ) :
s = go
cls . _computed_extra_version = c = ( v or ' ' , s )
return c
@classmethod
def _compute_extra_version ( cls , git ) :
try :
g = subprocess . Popen ( git + [ ' describe ' , ' --tags ' , ' --abbrev=8 ' ] , executable = git [ 0 ] , stdout = subprocess . PIPE , stderr = subprocess . PIPE )
except OSError as e :
if e . errno == errno . ENOENT :
return None
raise
( go , ge ) = g . communicate ( None )
if g . wait ( ) :
return None
g = subprocess . Popen ( git + [ ' diff ' , ' --quiet ' , ' --cached ' ] , executable = git [ 0 ] , stdout = subprocess . PIPE , stderr = subprocess . PIPE )
c = g . wait ( )
g = subprocess . Popen ( git + [ ' diff ' , ' --quiet ' ] , executable = git [ 0 ] , stdout = subprocess . PIPE , stderr = subprocess . PIPE )
d = g . wait ( )
return go . split ( ' \n ' ) [ 0 ] + ( ' + ' if c else ' ' ) + ( ' * ' if d else ' ' )
2013-03-10 19:33:57 +00:00
def _register_program ( self , dxxstr , program_specific_objects = [ ] ) :
env = self . env
exe_target = os . path . join ( self . srcdir , self . target )
2013-03-16 21:30:13 +00:00
static_archive_construction = self . static_archive_construction [ self . user_settings . builddir ]
2013-03-16 23:25:46 +00:00
objects = static_archive_construction . objects_common [ : ]
2013-10-25 02:46:21 +00:00
objects . extend ( self . objects_common )
2013-03-10 19:33:57 +00:00
objects . extend ( program_specific_objects )
2013-03-03 01:03:33 +00:00
if ( self . user_settings . sdlmixer == 1 ) :
2013-03-16 21:30:13 +00:00
objects . extend ( static_archive_construction . objects_arch_sdlmixer )
2013-03-16 23:25:46 +00:00
objects . extend ( self . objects_similar_arch_sdlmixer )
2013-03-03 01:03:33 +00:00
if ( self . user_settings . opengl == 1 ) or ( self . user_settings . opengles == 1 ) :
2013-06-01 23:46:05 +00:00
env . Append ( LIBS = self . platform_settings . ogllibs )
2013-03-16 23:25:46 +00:00
objects . extend ( self . objects_similar_arch_ogl )
2013-03-03 01:03:33 +00:00
else :
2013-06-16 19:28:38 +00:00
message ( self , " building with Software Renderer " )
2013-03-03 01:03:33 +00:00
objects . extend ( static_archive_construction . objects_arch_sdl )
2013-03-16 23:25:46 +00:00
objects . extend ( self . objects_similar_arch_sdl )
2013-03-03 01:03:33 +00:00
if ( self . user_settings . editor == 1 ) :
2013-03-24 23:03:46 +00:00
objects . extend ( self . objects_editor )
2013-03-16 02:02:24 +00:00
objects . extend ( static_archive_construction . objects_editor )
2013-05-05 22:44:22 +00:00
exe_target + = ' -editor '
2013-05-05 22:59:09 +00:00
if self . user_settings . program_name :
exe_target = self . user_settings . program_name
2014-09-13 22:10:24 +00:00
versid_build_environ = [ ' CXX ' , ' CPPFLAGS ' , ' CXXFLAGS ' , ' LINKFLAGS ' ]
versid_cppdefines = env [ ' CPPDEFINES ' ] [ : ]
2014-12-05 02:36:42 +00:00
versid_cppdefines . extend ( [ ( ' DESCENT_ %s ' % k , self . _quote_cppdefine ( env . get ( k , ' ' ) ) ) for k in versid_build_environ ] )
2014-09-13 22:10:24 +00:00
v = subprocess . Popen ( env [ ' CXX ' ] . split ( ' ' ) + [ ' --version ' ] , stdout = subprocess . PIPE , stderr = subprocess . PIPE )
2013-11-16 22:59:17 +00:00
( so , se ) = v . communicate ( None )
if not v . returncode and ( so or se ) :
v = ( so or se ) . split ( ' \n ' ) [ 0 ]
versid_cppdefines . append ( ( ' DESCENT_ %s ' % ' CXX_version ' , self . _quote_cppdefine ( v ) ) )
2014-07-26 17:40:12 +00:00
versid_build_environ . append ( ' CXX_version ' )
extra_version = self . user_settings . extra_version
if extra_version is None :
extra_version = ' v %u . %u ' % ( self . VERSION_MAJOR , self . VERSION_MINOR )
if self . VERSION_MICRO :
extra_version + = ' . %u ' % self . VERSION_MICRO
git_describe_version = ( self . compute_extra_version ( ) if self . user_settings . git_describe_version else ( ' ' , ' ' ) )
if git_describe_version [ 0 ] and not ( extra_version and ( extra_version == git_describe_version [ 0 ] or ( extra_version [ 0 ] == ' v ' and extra_version [ 1 : ] == git_describe_version [ 0 ] ) ) ) :
# Suppress duplicate output
if extra_version :
extra_version + = ' '
extra_version + = git_describe_version [ 0 ]
if extra_version :
versid_cppdefines . append ( ( ' DESCENT_VERSION_EXTRA ' , self . _quote_cppdefine ( extra_version ) ) )
versid_cppdefines . append ( ( ' DESCENT_git_status ' , self . _quote_cppdefine ( git_describe_version [ 1 ] ) ) )
versid_build_environ . append ( ' git_status ' )
2014-09-13 22:09:32 +00:00
versid_cppdefines . append ( ( ' DXX_RBE " (A) " ' , " ' " + ' ' . join ( [ ' A( %s ) ' % k for k in versid_build_environ ] ) + " ' " ) )
2015-01-03 23:44:32 +00:00
versid_environ = self . env [ ' ENV ' ] . copy ( )
# Direct mode conflicts with __TIME__
versid_environ [ ' CCACHE_NODIRECT ' ] = 1
versid_objlist = [ self . env . StaticObject ( target = ' %s %s %s ' % ( self . user_settings . builddir , self . _apply_target_name ( s ) , self . env [ " OBJSUFFIX " ] ) , source = s , CPPDEFINES = versid_cppdefines , ENV = versid_environ ) for s in [ ' similar/main/vers_id.cpp ' ] ]
2014-09-13 22:10:24 +00:00
if self . user_settings . versid_depend_all :
env . Depends ( versid_objlist [ 0 ] , objects )
if env . _dxx_pch_node :
env . Depends ( versid_objlist [ 0 ] , env . _dxx_pch_node )
2013-11-28 22:09:46 +00:00
objects . extend ( versid_objlist )
2013-03-10 19:33:57 +00:00
# finally building program...
2013-12-06 03:54:52 +00:00
exe_node = env . Program ( target = os . path . join ( self . user_settings . builddir , str ( exe_target ) ) , source = self . sources + objects )
2013-12-05 23:01:34 +00:00
if self . user_settings . host_platform != ' darwin ' :
2013-05-05 22:50:19 +00:00
if self . user_settings . register_install_target :
2013-12-06 03:54:52 +00:00
install_dir = ( self . user_settings . DESTDIR or ' ' ) + self . user_settings . BIN_DIR
env . Install ( install_dir , exe_node )
2013-05-05 22:55:16 +00:00
env . Alias ( ' install ' , install_dir )
2013-03-10 19:33:57 +00:00
else :
2013-05-05 23:20:06 +00:00
syspath = sys . path [ : ]
2013-03-03 01:03:33 +00:00
cocoa = ' common/arch/cocoa '
2013-05-05 23:20:06 +00:00
sys . path + = [ cocoa ]
2013-03-10 19:33:57 +00:00
import tool_bundle
2013-05-05 23:20:06 +00:00
sys . path = syspath
2013-03-10 19:33:57 +00:00
tool_bundle . TOOL_BUNDLE ( env )
2013-12-06 03:54:52 +00:00
env . MakeBundle ( os . path . join ( self . user_settings . builddir , self . PROGRAM_NAME + ' .app ' ) , exe_node ,
2014-12-05 01:27:06 +00:00
' free. %s -rebirth ' % dxxstr , os . path . join ( cocoa , ' Info.plist ' ) ,
2013-03-10 19:33:57 +00:00
typecode = ' APPL ' , creator = ' DCNT ' ,
2013-05-05 23:20:06 +00:00
icon_file = os . path . join ( cocoa , ' %s -rebirth.icns ' % dxxstr ) ,
2014-12-05 00:39:45 +00:00
resources = [ [ os . path . join ( self . srcdir , s ) , s ] for s in [ ' English.lproj/InfoPlist.strings ' ] ] )
2013-03-10 19:33:57 +00:00
2013-06-16 02:40:05 +00:00
def GenerateHelpText ( self ) :
return self . variables . GenerateHelpText ( self . env )
2013-03-02 20:53:47 +00:00
class D1XProgram ( DXXProgram ) :
PROGRAM_NAME = ' D1X-Rebirth '
target = ' d1x-rebirth '
srcdir = ' d1x-rebirth '
2013-12-04 01:43:19 +00:00
shortname = ' d1x '
2013-03-02 20:53:47 +00:00
def prepare_environment ( self ) :
DXXProgram . prepare_environment ( self )
# Flags and stuff for all platforms...
2014-12-20 04:36:11 +00:00
self . env . Append ( CPPDEFINES = [ ' DXX_BUILD_DESCENT_I ' ] )
2013-03-02 20:53:47 +00:00
# general source files
2013-04-21 17:58:04 +00:00
__objects_common = DXXCommon . create_lazy_object_property ( [ {
' source ' : [ os . path . join ( srcdir , f ) for f in [
2012-11-11 22:12:51 +00:00
' main/bmread.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/custom.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/snddecom.cpp ' ,
2013-03-02 20:53:47 +00:00
#'tracker/client/tracker_client.c'
]
2013-04-21 17:58:04 +00:00
] ,
} ] )
@property
def objects_common ( self ) :
return self . __objects_common + DXXProgram . objects_common . fget ( self )
2013-03-02 20:53:47 +00:00
# for editor
2013-04-21 17:59:38 +00:00
__objects_editor = DXXCommon . create_lazy_object_property ( [ {
' source ' : [ os . path . join ( srcdir , f ) for f in [
2012-11-11 22:12:51 +00:00
' main/hostage.cpp ' ,
2012-11-17 06:14:09 +00:00
' editor/ehostage.cpp ' ,
2013-03-02 20:53:47 +00:00
]
2013-04-21 17:59:38 +00:00
] ,
} ] )
@property
def objects_editor ( self ) :
return self . __objects_editor + DXXProgram . objects_editor . fget ( self )
2013-03-02 20:53:47 +00:00
2013-02-25 00:02:01 +00:00
class D2XProgram ( DXXProgram ) :
PROGRAM_NAME = ' D2X-Rebirth '
target = ' d2x-rebirth '
2013-03-02 20:53:47 +00:00
srcdir = ' d2x-rebirth '
2013-12-04 01:43:19 +00:00
shortname = ' d2x '
2013-02-25 00:02:01 +00:00
def prepare_environment ( self ) :
DXXProgram . prepare_environment ( self )
# Flags and stuff for all platforms...
2014-12-20 04:36:11 +00:00
self . env . Append ( CPPDEFINES = [ ' DXX_BUILD_DESCENT_II ' ] )
2013-03-02 22:41:05 +00:00
2013-02-25 00:02:01 +00:00
# general source files
2013-04-21 17:58:04 +00:00
__objects_common = DXXCommon . create_lazy_object_property ( [ {
' source ' : [ os . path . join ( srcdir , f ) for f in [
2012-11-11 22:12:51 +00:00
' libmve/decoder8.cpp ' ,
2012-11-11 22:12:51 +00:00
' libmve/decoder16.cpp ' ,
2012-11-11 22:12:51 +00:00
' libmve/mve_audio.cpp ' ,
2012-11-11 22:12:51 +00:00
' libmve/mvelib.cpp ' ,
2012-11-11 22:12:51 +00:00
' libmve/mveplay.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/escort.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/gamepal.cpp ' ,
2012-11-11 22:12:51 +00:00
' main/movie.cpp ' ,
2012-11-11 22:12:51 +00:00
' misc/physfsrwops.cpp ' ,
2013-03-03 02:20:54 +00:00
]
2013-04-21 17:58:04 +00:00
] ,
} ] )
@property
def objects_common ( self ) :
return self . __objects_common + DXXProgram . objects_common . fget ( self )
2006-12-19 02:25:50 +00:00
2013-02-25 00:02:01 +00:00
# for editor
2013-04-21 17:59:38 +00:00
__objects_editor = DXXCommon . create_lazy_object_property ( [ {
' source ' : [ os . path . join ( srcdir , f ) for f in [
2012-11-11 22:12:51 +00:00
' main/bmread.cpp ' ,
2013-03-03 02:20:54 +00:00
]
2013-04-21 17:59:38 +00:00
] ,
} ] )
@property
def objects_editor ( self ) :
return self . __objects_editor + DXXProgram . objects_editor . fget ( self )
2006-12-19 02:25:50 +00:00
2015-03-12 02:21:21 +00:00
variables = Variables ( [ v for ( k , v ) in ARGLIST if k == ' site ' ] or [ ' site-local.py ' ] , ARGUMENTS )
2013-10-26 18:13:28 +00:00
filtered_help = FilterHelpText ( )
variables . FormatVariableHelpText = filtered_help . FormatVariableHelpText
2014-10-16 01:56:30 +00:00
def _filter_duplicate_prefix_elements ( e , s ) :
r = e not in s
s . add ( e )
return r
2015-03-12 02:21:21 +00:00
def register_program ( program , other_program ) :
2013-12-04 01:43:19 +00:00
s = program . shortname
2013-05-18 03:08:05 +00:00
import itertools
2015-03-12 02:21:21 +00:00
l = [ v for ( k , v ) in ARGLIST if k == s or k == ' dxx ' ] or [ other_program . shortname not in ARGUMENTS ]
2013-05-05 23:12:52 +00:00
# Fallback case: build the regular configuration.
if len ( l ) == 1 :
try :
if int ( l [ 0 ] ) :
2013-12-04 02:21:27 +00:00
return [ program ( ( s , ' ' ) , variables ) ]
2013-06-16 02:40:05 +00:00
return [ ]
2013-05-05 23:12:52 +00:00
except ValueError :
# If not an integer, treat this as a configuration profile.
pass
2013-06-16 02:40:05 +00:00
r = [ ]
2013-12-04 02:18:43 +00:00
seen = set ( )
2013-05-05 23:12:52 +00:00
for e in l :
2013-05-18 03:08:05 +00:00
for prefix in itertools . product ( * [ v . split ( ' + ' ) for v in e . split ( ' , ' ) ] ) :
2014-10-16 01:56:30 +00:00
duplicates = set ( )
prefix = tuple ( p for p in prefix if _filter_duplicate_prefix_elements ( p , duplicates ) )
2013-12-04 02:18:43 +00:00
if prefix in seen :
continue
seen . add ( prefix )
2013-12-04 02:21:27 +00:00
prefix = [ ' %s %s %s ' % ( s , ' _ ' if p else ' ' , p ) for p in prefix ] + list ( prefix )
2013-10-26 18:13:28 +00:00
r . append ( program ( prefix , variables ) )
2013-06-16 02:40:05 +00:00
return r
2015-03-12 02:21:21 +00:00
d1x = register_program ( D1XProgram , D2XProgram )
d2x = register_program ( D2XProgram , D1XProgram )
2006-12-19 02:25:50 +00:00
# show some help when running scons -h
2013-06-16 02:40:05 +00:00
h = ' DXX-Rebirth, SConstruct file help: ' + """
2006-12-19 02:25:50 +00:00
Type ' scons ' to build the binary .
Type ' scons install ' to build ( if it hasn ' t been done) and install.
Type ' scons -c ' to clean up .
Extra options ( add them to command line , like ' scons extraoption=value ' ) :
2013-06-16 02:40:05 +00:00
d1x = [ 0 / 1 ] Disable / enable D1X - Rebirth
d1x = prefix - list Enable D1X - Rebirth with prefix - list modifiers
d2x = [ 0 / 1 ] Disable / enable D2X - Rebirth
d2x = prefix - list Enable D2X - Rebirth with prefix - list modifiers
2014-10-10 02:58:05 +00:00
dxx = VALUE Equivalent to d1x = VALUE d2x = VALUE
2013-03-02 20:53:47 +00:00
"""
2013-10-26 18:13:28 +00:00
substenv = SCons . Environment . SubstitutionEnvironment ( )
variables . Update ( substenv )
2013-06-16 02:40:05 +00:00
for d in d1x + d2x :
2013-10-26 18:13:28 +00:00
d . init ( substenv )
2013-06-16 02:40:05 +00:00
h + = d . PROGRAM_NAME + ( ' . %d : \n ' % d . program_instance ) + d . GenerateHelpText ( )
Help ( h )
2014-10-10 02:58:05 +00:00
unknown = variables . UnknownVariables ( )
# Delete known unregistered variables
unknown . pop ( ' d1x ' , None )
unknown . pop ( ' d2x ' , None )
unknown . pop ( ' dxx ' , None )
2015-03-12 02:21:21 +00:00
unknown . pop ( ' site ' , None )
2014-10-10 02:58:05 +00:00
ignore_unknown_variables = unknown . pop ( ' ignore_unknown_variables ' , ' 0 ' )
if unknown :
try :
ignore_unknown_variables = int ( ignore_unknown_variables )
except ValueError :
ignore_unknown_variables = False
if not ignore_unknown_variables :
raise SCons . Errors . StopError ( ' Unknown values specified on command line. ' +
' ' . join ( [ ' \n \t %s ' % k for k in unknown . keys ( ) ] ) +
' \n Remove unknown values or set ignore_unknown_variables=1 to continue. ' )
2013-02-21 00:20:26 +00:00
2006-12-19 02:25:50 +00:00
#EOF