#! /usr/bin/env python ''' This file is a Yabs programme that contains tests for Yabs, and also Yabs targets that build releases of Yabs. Run all tests with: ./make.py test ''' import yabs, yabs2, yabs3 import os, string, re, shutil, time, sys # import the example-1/make.py script. Targets in this script are built # directly in this programme by the test5 target, and also via separate # invocations of the example-1/make.py programme via os.system() in the # other tests. sys.path.insert( 0, 'example-1') import make def add_lineprefix( prefix, text): ''' Returns text with each line prefixed with . ''' ret = '' for line in text.split( '\n'): ret += prefix + line + '\n' return ret def do_clean(): #os.system( 'rm example-1/_yabs/*' + yabs.default_state.envstring + '*') os.system( 'rm example-1/_yabs/*' + yabs3._envstring() + '*') def check_same_text( prefix, testname, text1, text2): if text1 == text2: print prefix + testname + ' succeeded - output text unchanged:' print add_lineprefix( prefix + '> ', text1), else: print prefix + testname + ' failed:' print add_lineprefix( prefix + '1> ', text1), print prefix + 'is different from:' print add_lineprefix( prefix + '2> ', text2), raise Exception( testname + ' failed') rootdir = yabs.get_caller_directory() def test1( target, prereq, match, state): '''' Does a clean build and run of the executable in the example-1 directory. ''' print yabs.place(), 'test1' prefix = ' ' + target + ': ' do_clean() cmd = 'cd ' + os.path.join( rootdir, 'example-1') + ' && '\ + os.path.join( '.', 'make.py foo.exe -dd') #print add_lineprefix( prefix, 'running: ' + cmd) text = yabs.subprocess_text( cmd) #print add_lineprefix( prefix, 'make attempt returned:') #print add_lineprefix( prefix, text), text = yabs.subprocess_text( 'cd ' + os.path.join( rootdir, 'example-1') + ' && ' + os.path.join( '.', '_yabs', 'foo,' + yabs3._get_defaultbuild() + '.exe')) print add_lineprefix( prefix, text), print prefix + 'succeeded' def test2( target, prereq, match, state): ''' Checks that modifying a header forces a rebuild. ''' prefix = ' ' + target + ': ' do_clean() yabs.subprocess_text( 'cd ./example-1 && ./make.py foo.exe -e 31222') print prefix + 'building with main.cpp marked as new...' time.sleep(1) text1 = yabs.subprocess_text( 'cd ./example-1 && ./make.py foo.exe -W main.cpp -e 31222') print prefix + 'building with main.h marked as new - should give identical text...' time.sleep(1) text2 = yabs.subprocess_text( 'cd ./example-1 && ./make.py foo.exe -W main.h -e 31222') check_same_text( prefix, target, text1, text2) print prefix + 'succeeded' def test3( target, prereq, match, context): ''' Checks that modifying a cmd-file forces a rebuild of all sources. ''' prefix = ' ' + target + ': ' do_clean() text1 = yabs.subprocess_text( 'cd ./example-1 && ./make.py foo.exe -e 31222 --d0') cmdfile = 'example-1/_yabs/.cpp,' + yabs3._get_defaultbuild() + '.o' assert yabs.mtime_raw( cmdfile)>0 # append some text to the compiler-cmd file. this should force # recompiles of all source files. yabs.subprocess_text( 'echo "extra" >> ' + cmdfile, state=context.state) print prefix + 'building after altering command-file...' time.sleep( 1) text2 = yabs.subprocess_text( 'cd ./example-1 && ./make.py foo.exe -e 31222 --d0') check_same_text( prefix, target, text1, text2) print prefix + 'succeeded' def test4( target, prereq, match, context): ''' Checks that rebuild does nothing. ''' prefix = ' ' + target + ': ' text1 = yabs.subprocess_text( 'cd ./example-1 && ./make.py foo.exe -e 31222 -d', state=context.state) print prefix + 'rebuilding...' time.sleep( 1) text = yabs.subprocess_text( 'cd ./example-1 && ./make.py foo.exe -e 21333 -d') if text!='': print prefix + 'rebuild did not do nothing. output was:' print add_lineprefix( prefix + '> ', text), raise Exception( target + ' failed') print prefix + 'succeeded' def test5( target, prereq, match, context): ''' This tests Yabs's support for importing build scripts from a different directory, and dealing with the imported rules and targets without having to worry about absolute/relative paths. For example, we can send a target 'example-1/foo.exe' to yabs.make(), and it will be built by the rules in the imported example-1/make.py module. fixme: this is broken when run standalone - rebuilding can return changed. ''' #state = yabs.State() #yabs3.setup( state) #state.defaultbuild = '' #state.defaultbuild2 = '' #print 'test5: state=', state prefix = ' ' + target + ': ' target = 'example-1/_yabs/foo,' + yabs3._get_defaultbuild() + '.exe' print prefix + 'building ' + target result = yabs.make( target, prefix) print 'result1 was:', result #yabs.default_state.debug = 3 print prefix + 'rebuilding ' + target result = yabs.make( target, prefix) print 'result2 was:', result if result!=yabs.unchanged: raise Exception( prefix + 'direct rebuild didn\'t do nothing: ' + target) print prefix + 'rebuilding with source marked as changed and target cache unchanged: ' + target yabs.mtime_marknew( 'example-1/main.cpp') result = yabs.make( target, prefix) print 'result3 was:', result if result!=yabs.unchanged: raise Exception( prefix + 'direct rebuild without target-cache-flush didn\'t do nothing: ' + target) print prefix + 'rebuilding with source marked as changed and target cache cleared: ' + target yabs.default_state.targetcache = dict() yabs.mtime_marknew( 'example-1/main.cpp') #yabs.default_state.debug = 3 result = yabs.make( target, prefix) if result!=yabs.changed: raise Exception( prefix + 'direct rebuild with changed source and flushed target cache did nothing: ' + target) print prefix + 'succeeded' def test6( target, state): ''' This tests the patternrule in example-1/make.py which simply touches the file example-1/patterntest. When run from this directory, the patternrule mechanism has to ensure that the target is an absolute pathname when the patterrule's command is generated. ''' if target!='test6': return None f = os.path.join( yabs.get_caller_directory(1), 'example-1', 'patterntest') if yabs.mtime( f)>0: os.remove( f) yabs.mtime_flush( f) return 'echo test6 succeeded', [ os.path.join( 'example-1', 'patterntest')], [] test7_dir = os.path.join( yabs.get_caller_directory(), 'example-1') if os.name=='nt': yabs2.add_patternrule_phony( 'test7-helper', '', 'cd', root=test7_dir) else: yabs2.add_patternrule_phony( 'test7-helper', '', 'pwd', root=test7_dir) def test7( target, prereq, match, state): ''' Tests that commands are run in ruleroot directory. we run a new yabs build for the special target `test7-helper', which should output the current directory set by add_patternrule_phony's parameter. have to use -s flag, so that the only output is from the pwd command. ''' prefix = ' ' + target + ': ' text = yabs.subprocess_text( os.path.join( '.', 'make.py') + ' -e 21233 ' + os.path.join( 'example-1', 'test7-helper')) text = text.strip() print prefix + 'test7-helper target output was: ' + text if text != test7_dir: raise Exception( 'test7 failed - text=', text) print prefix + ' succeeded' yabs2.add_patternrule( 'test8-file', 'foobar.cantmake', '') def test8( target, prereq, match, state): ''' Tests that the last-resort yabs._file_rule() is not used when previous rules have failed due to failed prerequisites. ''' prefix = ' ' + target + ': ' yabs.subprocess_text( 'touch test8-file') yabs.subprocess_text( 'touch test8-file2') e = yabs.make( 'test8-file') if e==yabs.changed or e==yabs.unchanged: raise Exception( 'test8 failed - make of test8-file should not have succeeded') print prefix + 'build of test8-file failed, as it should' e = yabs.make( 'test8-file2') if e!=yabs.changed and e!=yabs.unchanged: raise Exception( 'test8 failed - make of test8-file2 should have succeeded') print prefix + ' succeeded' root=yabs.get_caller_directory() def test9_helper( target, state): if target != 'test9-foo': return None return 'touch ' + target, yabs.add_rule( test9_helper, root=root, autocmds='.cmdfile') def test9( target, prereq, match, state): ''' test9_helper is registered using yabs's built-in support for command files. this test checks that modifying the command file forces the target to be rebuilt. ''' prefix = ' ' + target + ': ' f = os.path.join( root, 'test9-foo') cmdfile = f + '.cmdfile' yabs.subprocess( 'rm ' + f) yabs.subprocess( 'rm ' + cmdfile) print prefix + 'calling make 1' e = yabs.make( f) if e!=yabs.changed and e!=yabs.unchanged: raise Exception( 'couldn\'t make ' + str(e)) print prefix + 'calling make 2' time.sleep(1) del yabs.default_state.targetcache[ f] del yabs.default_state.targetcache[ cmdfile] e = yabs.make( f) if e != yabs.unchanged: raise Exception( 'remake should have done nothing:' + str(e)) print prefix + 'calling make 3' time.sleep(1) del yabs.default_state.targetcache[ f] del yabs.default_state.targetcache[ cmdfile] yabs.subprocess( 'echo newtext >>' + cmdfile) yabs.subprocess( 'cat ' + cmdfile, echo=1) e = yabs.make( f) if e != yabs.changed: raise Exception( 'remake should have changed ' + f) print prefix + ' succeeded' yabs2.add_patternrule_phony( 'test1', '', test1) yabs2.add_patternrule_phony( 'test2', '', test2) yabs2.add_patternrule_phony( 'test3', '', test3) yabs2.add_patternrule_phony( 'test4', '', test4) yabs2.add_patternrule_phony( 'test5', '', test5) yabs.add_rule( test6, True, yabs.get_caller_directory(1)) yabs2.add_patternrule_phony( 'test7', '', test7) yabs2.add_patternrule_phony( 'test8', '', test8) yabs2.add_patternrule_phony( 'test9', '', test9) yabs2.add_patternrule( 'intercept.so', 'intercept.c', 'echo building $@\ngcc -W -Wall -c -o intercept.o intercept.c\n' + 'gcc -shared -fpic -o $@ intercept.o' ) def test10( target, prereq, match, state): ''' raw test of LD_PRELOAD. not used because it fails now. ''' try: os.remove( 'test10.deps') except OSError: pass yabs.command_run( 'export LD_PRELOAD=`pwd`/intercept.so YABS_AUTODEPS_FILENAME=`pwd`/test10.deps && cd . && ' 'gcc -c -o /dev/null intercept.c && echo $LD_PRELOAD', state) yabs.subprocess_text( 'cat test10.deps', state=state) yabs2.add_patternrule_phony( 'test10', 'intercept.so', test10) def test11( target, state): ''' This isn't really a test. it simply outputs the contents of the autodeps file created when running gcc. ''' if target!='test11': return None print 'test11: returning' return ( '-rm ' + target + '.dep\n' + 'echo "#include " > test11.c\n' + 'gcc -c -o /dev/null test11.c\n' + 'cat ' + target + '.dep', [], [ None], ) yabs.add_rule( test11, phony=True, root=yabs.caller, autodeps='.dep') def test12( target, prereq, match, state): ''' checks yabs.subprocess_text returns error/noerror as appropriate. ''' prefix = ' ' + target + ': ' n = 'ksjndv' if os.name=='nt': t = 'echo' f = 'cl asdasdasdasdasd' else: t = 'true' f = 'false' print prefix + 'running: ' + f e, text = yabs.subprocess( f, echo=True) if e==0: raise Exception( 'comand ' + f + ' should have returned error') print prefix + 'running: ' + n e, text = yabs.subprocess( n, echo=True) if e==0: raise Exception( 'comand ' + f + ' should have returned error') print prefix + 'running: ' + t e, text = yabs.subprocess( t, echo=True) if e!=0: raise Exception( 'comand ' + t + ' shoould not have returned error') print prefix + 'succeeded' yabs2.add_patternrule_phony( 'test12', '', test12) def simplecompile_rule( target, state): if not target.endswith( '.cpp.o'): return None src = target[ :-2] cmd = 'g++ -c -W -Wall -o ' + target + ' ' + src return cmd, [ src] yabs.add_rule( simplecompile_rule, autocmds='.cmds', autodeps='.deps') def simple_addexe( exe, src, root=None): if root==None: root=yabs.get_caller_directory() def rule( target, state): #print 'simple_addexe', exe, target if target!=exe: return None objs = [] for s in src: objs.append( s+'.o') return 'g++ -o ' + target + ' ' + string.join( objs, ' '), objs yabs.add_rule( rule, autocmds='.cmds', autodeps='.deps', root=root) simple_addexe( 'bar.exe', [ 'main.cpp'], root=os.path.join( yabs.get_caller_directory(), 'example-1')) def test13( target, state): ''' check that autodeps works - run compile/link, modify a .h file, and check that this forces a rebuild. ''' if target!='test13': return None def fn( state): print yabs.default_state.targetcache.has_key( '/home/jules/workingdir/top/home/jules/yabs/test') old_mtimecache = yabs.default_state.mtimecache old_rulecache = yabs.default_state.rulecache old_targetcache = yabs.default_state.targetcache try: prefix = ' ' + target + ': ' exe = os.path.join( root, 'example-1', 'bar.exe') yabs.default_state.mtimecache = yabs.MtimeCache() yabs.default_state.rulecache = {} yabs.default_state.targetcache = {} # force recompilation of main.cpp, so that the .deps file is created. try: os.remove( os.path.join( root, 'example-1', 'main.cpp.o')) except OSError: pass print prefix e = yabs.make( exe) assert e==yabs.changed or e==yabs.unchanged print prefix print prefix + 'remaking - should do nothing' yabs.default_state.mtimecache = yabs.MtimeCache() yabs.default_state.targetcache = {} yabs.default_state.rulecache = {} e = yabs.make( exe) assert e==yabs.unchanged, e time.sleep( 1) print prefix print prefix + 'remaking with header marked as new' yabs.default_state.mtimecache = yabs.MtimeCache() yabs.mtime_marknew( os.path.join( root, 'example-1', 'main.h')) yabs.default_state.targetcache = {} yabs.default_state.rulecache = {} e = yabs.make( exe) assert e==yabs.changed, repr( e) print prefix + 'succeeded' finally: yabs.default_state.mtimecache = old_mtimecache yabs.default_state.rulecache = old_rulecache yabs.default_state.targetcache = old_targetcache print yabs.default_state.targetcache.has_key( '/home/jules/workingdir/top/home/jules/yabs/test') return fn, yabs.add_rule( test13, root=root, phony=True) def test14_helper( target, state): if target!='test14.o': return None return ( 'echo test14-recompiling && gcc -Wall -W -I include-0 -I include-1 -c -o test14.o test14.c', 'test14.c', ) yabs.add_rule( test14_helper, root=root, autodeps='.deps') def test14( target, state): ''' test that autodeps works with multiple include-paths when a header file is created that previously failed to open. note that this test fails if we don't create the empty include-0 directory before the first build - unfortunately gcc doesn't attempt to open the header in a non-existant directory. Also, this test only works on openbsd, but not on linux - linux doesn't seem to support $LD_PRELOAD to the extent that openbsd does. ''' if target!='test14': return None def fn( context): cmd = ''' -rm -r include-0 2>/dev/null -rm -r include-1 2>/dev/null mkdir include-0 mkdir include-1 touch include-1/foo.h echo '#include "foo.h"' > test14.c echo 'int main( void) { return 0; }' >> test14.c ./make.py -e 31233 test14.o touch include-0/foo.h ./make.py -e 31233 test14.o ''' e, text = yabs.command_run( cmd, context.state, cwd=root) correct_text = 'test14-recompiling\n' if e!=0 or text.count( correct_text)!=2: raise Exception( 'test14 failed - expecting second build to recompile' + ', but output text was wrong:\n\n' + str( text) + '\nexpected two occurrencies of: \n' + repr(correct_text)) return fn, yabs.add_rule( test14, root=root,phony=True) yabs2.add_patternrule_phony( 'test15', '', 'echo hello && echo world 1>&2 && false') def test16( target, state): if target!='test16': return None def cmd( state): a = yabs.subprocess_text( 'echo hello 2>&1') b = yabs.subprocess_text( 'echo world 1>&2') print 'a=', a print 'b=', b return cmd, yabs.add_rule( test16, root=root, phony=True) # checks that we can build _yabs/test17.exe, which will be a copy of # _yabs/test17,.exe. this test requires that yabs3._singlebuild # be registered. yabs2.add_patternrule( 'test17.c', '', 'printf \'#include \\n' 'int main(void){\\n' ' printf("hello world\\\\n");\\n' ' return 0;\\n' '}\\n\' >$@') yabs3.add_exe( 'test17', 'test17.c') yabs2.add_patternrule_phony( 'test17', yabs3.default_target( 'test17.exe') + ' _yabs/test17.exe', '') yabs2.add_patternrule_phony( 'test18', '_yabs/test17,default.exe', '') yabs.add_rule( yabs.fn( ''' def ( target, state): if target!='test19': return None return 'touch ' + target, '''), root=yabs.caller) # test20: test that -k option works. yabs2.add_patternrule( 'test20c', '', 'touch $@') if 0: yabs2.add_patternrule( 'test20d', '', 'touch $@') yabs2.add_patternrule( 'test20e', '', 'asdasdasda') yabs2.add_patternrule( 'test20b', 'test20c test20d test20e', 'echo test20bcommand') def test20( target, state): if target!='test20': return None def command( context): e, text = yabs.command_run( './make.py -ks test20b test20d', context.state, cwd=root) #print 'e=', e #print 'text=', repr(text) #print 'text=\n\n', text, '\n\n' assert e assert re.search( 'target failed:.*_yabs_multiple_targets.*test20b.*test20d.*test20e', text, re.DOTALL) print target + ' succeeded' return command, yabs.add_rule( test20, root=yabs.caller, phony=True) def test21( target, state): if target!='test21': return assert locals() == yabs._uplocals(0) assert globals() == yabs._upglobals(0) return '', yabs.add_rule( test21, root=yabs.caller, phony=True) def test22( target, state): if target!='test22': return x = 45 f = yabs.fn( ''' def ( state): print 'test22.f():', test22 if 0: print 'test22.f(): x=', x # fails return '' ''') def g( state): print 'test22.g(): x=', x # ok return f, yabs.add_rule( test22, root=yabs.caller, phony=True) def test23_fn( target, state): if not target.endswith( '.test23'): return cmd = 'sleep 1\necho hello world >> ' + target + '\n' return 'echo > ' + target + '\n' + cmd*3, def test23( target, state): if target != 'test23': return return '', [ 'test23.test23', 'test23_2.test23'] yabs.add_rule( test23, root=yabs.caller, phony=True) def test24( target, state): ''' check that -j 2 makes test23 run much faster. ''' def commands( context): # do dummy build to minimise startup costs. e, text = yabs.command_run( './make.py -e 31222 test23 -j 2') t0 = time.time() e, text = yabs.command_run( './make.py -e 31222 test23') t1 = time.time() t_serial = t1-t0 print 't_serial=', t_serial e, text = yabs.command_run( './make.py -e 31222 test23 -j 2') t2 = time.time() t_mt = t2-t1 print 't_mt=', t_mt assert t_mt < 0.7*t_serial if target=='test24': return commands, yabs.add_rule( test24, root=yabs.caller, phony=True) def test25_( target, state): if target=='/test25_': return '', 'foo' def test25( target, state): def commands( context): e, text = yabs.command_run( './make.py /test25_') assert 'warning: rule returned a relative prerequisite' in text assert e print 'test25 succeeded' if target=='test25': return commands, yabs.add_rule( test25, root=yabs.caller, phony=True) def test26_( target, state): if target=='test26_': foo = test26_bar # deliberate error. def test26( target, state): def commands( context): print 'running test26_' e, text = yabs.command_run( './make.py test26_') assert text.count( 'rule failed:')==1 assert e e, text = yabs.command_run( './make.py test26_ -s') assert text.count( 'rule failed:')==1 assert e print 'test26 succeeded' if target=='test26': return commands, yabs.add_rule( test26, root=yabs.caller, phony=True) yabs.add_rule( test26_, root=yabs.caller, phony=True) def test27_foo( target, state): if target!='test27_foo': return return 'touch test27_bar', yabs.add_rule( test27_foo, root=yabs.caller) def test27( target, state): if target != 'test27': return def commands( context): e, text = yabs.command_run( './make.py test27_foo') print yabs.place(), e, repr(text) assert e print 'test27 succeeded' return commands, yabs.add_rule( test27, root=yabs.caller, phony=True) # a rule that deliberately generates an error. useful for # manually testing the error messages when -s and -e flags # are used. yabs2.add_patternrule_phony( 'error', '', 'g++ --- ij') yabs2.add_patternrule_phony( 'error2', 'error', 'echo ok') yabs2.add_patternrule_phony( 'hang', '', 'sleep 1000') yabs2.add_patternrule_phony( 'segv', yabs3.default_target( 'segv.c.exe'), '$<') yabs2.add_patternrule( 'error3', '', 'touch error4', phony=True, always=True) yabs2.add_patternrule( 'error4', '', 'touch -t 200001010101 error4', always=True) if os.name=='nt': # some targets don't work on windows - use gcc etc. yabs2.add_patternrule_phony( 'test', 'test6 test7 test12', '') else: tests = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 18, 19, 20, 21, 22, 24, 25, 26, 27] if os.uname()[0]=='Linux': tests.remove( 14) # following rule allows targets like `test3-6' - will depend on all # tests between 3 and 6 (both inclusive) that are in the global list # `tests'. Also, can do 'test-5', 'test6-' and 'test'. testrange_fn_regex = re.compile( '^test(?P[0-9]*)-(?P[0-9]*)$') def testrange_fn( target, state): if target=='test': begin = 0 end = 99999 else: match = testrange_fn_regex.match( target) #print 'testrange_fn_regex: match=', match if not match: return None begin = match.group('begin') if begin=='': begin = 0 else: begin = int( begin) end = match.group('end') if end=='': end = 99999 else: end = int( end) #print 'testrange_fn: ', begin, end prereq = [] for i in tests: if i>=begin and i<=end: prereq.append( 'test' + str( i)) return 'echo ' + target + ' succeded', prereq yabs.add_rule( testrange_fn, phony=True, root=yabs.caller) yabs2.add_patternrule_phony( 'run-%.exe', '%1.exe', '%1.exe') # two rules that build an executable from a single .c file, given a # target such as 'foo/bar.c.exe' def simple_exe_rule( target, state): suffix = '.c.exe' if target.endswith( suffix): name = target[ : -len(suffix)] exe = yabs3.default_target( name + '.c.exe') print 'simple_exe_rule: exe=', exe if exe is None: return None return '', [exe], [] def simple_exe_rule2( target, state): regex = re.compile( '^' + '(?P[^' + yabs2.separator + ']*)' + yabs2.separator + '(?P.*)' #+ state.envstring + yabs3._envstring( state) + '.exe' + '$' ) match = regex.match( target) if match is None: return None src = match.groupdict()[ 'name'] obj = yabs3.default_target( src + '.o', insert_subdir=False) if obj is None: return None print 'simple_exe_rule2, src=', src, 'obj=', obj return [ obj], [], 'g++ -W -Wall -o ' + target + ' ' + obj yabs.add_rule( simple_exe_rule, phony=True) yabs.add_rule( simple_exe_rule2) yabs2.add_patternrule( 'tags', '', 'ctags --c-kinds=+px *.c *.h *.S *.py', autocmds='.cmds') # things below here are for making releases of Yabs. version = '20' version_string = version release_file = 'yabs-' + version + '.tar.gz' website_dir = 'yabs-' + version + '-website' def processreadme( target, state): ''' insert correct version numbers in readme.html, and check version number at end of history.html. ''' if target != 'checkdocs': return None def process( state): date = time.strftime( '%Y %B %d') f = open( 'readme.html', 'r') out = '' for line in f.readlines(): line = re.sub( '^

Version: .*

$', '

Version: ' + version_string + '.

', line) line = re.sub( '^

Date: .*

$', '

Date: ' + date + '.

', line) line = re.sub( 'yabs-[0-9]*.tar.gz', lambda t: release_file, line) out += line f.close() # replace the options section with the actual output from # yabs2's -h: p = out.find( '
Yabs options are:\n')
        assert p>=0
        end = '
' q = out.find( end, p) assert q>=0 helptext = os.popen( './make.py -h').read() helptext = helptext.replace( '<', '<') helptext = helptext.replace( '>', '>') out = out[:p] + '
' + helptext + out[q:]
        
        f = open( 'readme.html-', 'w')
        f.write( out)
        f.close()
        os.system( 'diff readme.html readme.html-')
        shutil.copyfile( 'readme.html-', 'readme.html')
        os.unlink( 'readme.html-')
        
        f = open( 'history.html')
        h = f.read()
        end_text =(
            '\n'
            '

' + date + ': version ' + version + '.

\n' '
\n' '\n' '\n' '\n' '\n' ) if not h.endswith( end_text): print 'History file doesn\'t end with correct text: ' print '[' + end_text + ']' print 'history file ends with:' print '[' + h[-len(end_text):] + ']' raise Exception( 'History file doesn\'t end with correct text') return '' return process, yabs.add_rule( processreadme, True, yabs.get_caller_directory(1)) filelist = ''' __init__.py readme.html history.html yabs.py yabs2.py yabs3.py yabserrors.py yabs.html yabs2.html yabs3.html yabserrors.html make.py autodeps.c example-1/make.py example-1/foo.cpp example-1/main.cpp example-1/main.h ''' filelist = string.replace( filelist, '\n', ' ') yabs2.add_patternrule( release_file, 'always ' + filelist, '-~/htmlcontents/_yabs/foo\,debug\,gcc2.95.3\,os\=OpenBSD\,cpu\=i386\,osv\=3.6.exe -s readme.html\n' '-rm -r yabs-' + str( version) + '\n' 'mkdir -p yabs-' + str( version) + '/example-1\n' 'for i in ' + filelist + '; do cp -p $i yabs-' + str( version) + '/$i; done\n' 'tar -czf $@ yabs-' + str( version) + '\n' '-rm -r yabs-' + str( version) + '\n' ) yabs2.add_patternrule( website_dir, 'always checkdocs ' + release_file, '-rm -r $@\n' 'tar -xzf ' + release_file + '\n' 'mv yabs-' + str( version) + ' ' + website_dir + '\n' 'cp -p ' + release_file + ' ' + website_dir + '\n' ) pydoc = 'pydoc' yabs2.add_patternrule( 'yabs%.html', 'yabs%1.py', pydoc + ' -w yabs%1') yabs2.add_patternrule( 'make.html', 'make.py', pydoc + ' -w make') # we are careful to make this rule not apply to readme.html, otherwise # it would be attempted and fail because there is no file (or rule that # can generate) readme.py, and this would give a warning from yabs if # debugging is on. yabs2.add_patternrule_phony( 'release', release_file, '') yabs2.add_patternrule_phony( 'website', website_dir, '') yabs2.add_patternrule_phony( 'always', '', '') if 1: yabs2.add_rules( '^test.*$', phony=True) #yabs2.appmakeexit() yabs2.appmakeexit( default_params='-d') else: import hotshot, hotshot.stats prof = hotshot.Profile( 'make.prof') e = prof.runcall( yabs2.appmake) stats = hotshot.stats.load( 'make.prof') stats.strip_dirs() stats.sort_stats('time', 'calls') stats.print_stats() sys.exit( e)