2010-02-26 14:21:50 +03:00
# a waf tool to add autoconf-like macros to the configure section
# and for SAMBA_ macros for building libraries, binaries etc
import Build , os , Logs , sys , Configure , Options , string , Task , Utils , optparse
2010-02-28 09:34:43 +03:00
from TaskGen import feature , before
2010-02-26 14:21:50 +03:00
from Configure import conf
from Logs import debug
from TaskGen import extension
LIB_PATH = " shared "
2010-02-28 09:34:43 +03:00
##########################################################
# create a node with a new name, based on an existing node
def NEW_NODE ( node , name ) :
ret = node . parent . find_or_declare ( [ name ] )
ASSERT ( node , ret is not None , " Unable to find new target with name ' %s ' from ' %s ' " % (
name , node . name ) )
return ret
#############################################################
# set a value in a local cache
# return False if it's already set
def SET_TARGET_TYPE ( ctx , target , value ) :
cache = LOCAL_CACHE ( ctx , ' TARGET_TYPE ' )
if target in cache :
ASSERT ( ctx , cache [ target ] == value ,
" Target ' %s ' re-defined as %s - was %s " % ( target , value , cache [ target ] ) )
debug ( " task_gen: Skipping duplicate target %s (curdir= %s ) " % ( target , ctx . curdir ) )
return False
assumed = LOCAL_CACHE ( ctx , ' ASSUMED_TARGET ' )
if target in assumed :
#if assumed[target] != value:
# print "Target '%s' was assumed of type '%s' but is '%s'" % (target, assumed[target], value)
ASSERT ( ctx , assumed [ target ] == value ,
" Target ' %s ' was assumed of type ' %s ' but is ' %s ' " % ( target , assumed [ target ] , value ) )
predeclared = LOCAL_CACHE ( ctx , ' PREDECLARED_TARGET ' )
if target in predeclared :
ASSERT ( ctx , predeclared [ target ] == value ,
" Target ' %s ' was predeclared of type ' %s ' but is ' %s ' " % ( target , predeclared [ target ] , value ) )
LOCAL_CACHE_SET ( ctx , ' TARGET_TYPE ' , target , value )
debug ( " task_gen: Target ' %s ' created of type ' %s ' in %s " % ( target , value , ctx . curdir ) )
return True
2010-02-26 14:21:50 +03:00
######################################################
# this is used as a decorator to make functions only
# run once. Based on the idea from
# http://stackoverflow.com/questions/815110/is-there-a-decorator-to-simply-cache-function-return-values
runonce_ret = { }
def runonce ( function ) :
def wrapper ( * args ) :
if args in runonce_ret :
return runonce_ret [ args ]
else :
ret = function ( * args )
runonce_ret [ args ] = ret
return ret
return wrapper
################################################################
# magic rpath handling
#
# we want a different rpath when installing and when building
# Note that this should really check if rpath is available on this platform
# and it should also honor an --enable-rpath option
def set_rpath ( bld ) :
if Options . is_install :
if bld . env [ ' RPATH_ON_INSTALL ' ] :
bld . env [ ' RPATH ' ] = [ ' -Wl,-rpath= %s /lib ' % bld . env . PREFIX ]
else :
bld . env [ ' RPATH ' ] = [ ]
else :
rpath = os . path . normpath ( ' %s / %s ' % ( bld . env [ ' BUILD_DIRECTORY ' ] , LIB_PATH ) )
bld . env . append_value ( ' RPATH ' , ' -Wl,-rpath= %s ' % rpath )
Build . BuildContext . set_rpath = set_rpath
#############################################################
# return a named build cache dictionary, used to store
# state inside the following functions
@conf
def LOCAL_CACHE ( ctx , name ) :
if name in ctx . env :
return ctx . env [ name ]
ctx . env [ name ] = { }
return ctx . env [ name ]
#############################################################
# set a value in a local cache
@conf
def LOCAL_CACHE_SET ( ctx , cachename , key , value ) :
cache = LOCAL_CACHE ( ctx , cachename )
cache [ key ] = value
#############################################################
# a build assert call
@conf
def ASSERT ( ctx , expression , msg ) :
if not expression :
sys . stderr . write ( " ERROR: %s \n " % msg )
raise AssertionError
Build . BuildContext . ASSERT = ASSERT
################################################################
# create a list of files by pre-pending each with a subdir name
def SUBDIR ( bld , subdir , list ) :
ret = ' '
for l in list . split ( ) :
ret = ret + subdir + ' / ' + l + ' '
return ret
Build . BuildContext . SUBDIR = SUBDIR
##############################################
# remove .. elements from a path list
def NORMPATH ( bld , ilist ) :
return " " . join ( [ os . path . normpath ( p ) for p in ilist . split ( " " ) ] )
Build . BuildContext . NORMPATH = NORMPATH
#######################################################
# d1 += d2
def dict_concat ( d1 , d2 ) :
for t in d2 :
if t not in d1 :
d1 [ t ] = d2 [ t ]
############################################################
# this overrides the 'waf -v' debug output to be in a nice
# unix like format instead of a python list.
# Thanks to ita on #waf for this
def exec_command ( self , cmd , * * kw ) :
import Utils , Logs
_cmd = cmd
if isinstance ( cmd , list ) :
_cmd = ' ' . join ( cmd )
debug ( ' runner: %s ' % _cmd )
if self . log :
self . log . write ( ' %s \n ' % cmd )
kw [ ' log ' ] = self . log
try :
if not kw . get ( ' cwd ' , None ) :
kw [ ' cwd ' ] = self . cwd
except AttributeError :
self . cwd = kw [ ' cwd ' ] = self . bldnode . abspath ( )
return Utils . exec_command ( cmd , * * kw )
Build . BuildContext . exec_command = exec_command
##########################################################
# add a new top level command to waf
def ADD_COMMAND ( opt , name , function ) :
Utils . g_module . __dict__ [ name ] = function
opt . name = function
Options . Handler . ADD_COMMAND = ADD_COMMAND
2010-02-28 09:34:43 +03:00
@feature ( ' cprogram cc ' )
@before ( ' apply_core ' )
def process_depends_on ( self ) :
''' The new depends_on attribute for build rules
allow us to specify a dependency on output from
a source generation rule '''
if getattr ( self , ' depends_on ' , None ) :
lst = self . to_list ( self . depends_on )
for x in lst :
y = self . bld . name_to_obj ( x , self . env )
y . post ( )
2010-02-26 14:21:50 +03:00
#import TaskGen, Task
#
#old_post_run = Task.Task.post_run
#def new_post_run(self):
# self.cached = True
# return old_post_run(self)
#
#for y in ['cc', 'cxx']:
# TaskGen.classes[y].post_run = new_post_run