367 lines
10 KiB
Python
Executable File
367 lines
10 KiB
Python
Executable File
#! /usr/bin/env python
|
|
# encoding: utf-8
|
|
# Thomas Nagy, 2005, 2006, 2007 (ita)
|
|
|
|
"""
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions
|
|
are met:
|
|
|
|
1. Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
2. Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
3. The name of the author may not be used to endorse or promote products
|
|
derived from this software without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
|
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
"""
|
|
|
|
import os, sys
|
|
if 'PSYCOWAF' in os.environ:
|
|
try:
|
|
import psyco
|
|
psyco.full()
|
|
except:
|
|
pass
|
|
|
|
VERSION="1.2.0"
|
|
REVISION="x"
|
|
INSTALL="x"
|
|
cwd = os.getcwd()
|
|
|
|
def decodeAscii85(s):
|
|
out=[]
|
|
app=out.append
|
|
s=''.join(s.split()).replace('z','!!!!!')
|
|
p1,p2=divmod(len(s), 5)
|
|
stop=5*p1
|
|
p3,p4=s[0:stop],s[stop:]
|
|
for i in range(p1):
|
|
off=i*5
|
|
a=ord(p3[off])-33
|
|
b=ord(p3[off+1])-33
|
|
c=ord(p3[off+2])-33
|
|
d=ord(p3[off+3])-33
|
|
e=ord(p3[off+4])-33
|
|
num=(52200625L*a)+(614125*b)+(7225*c)+(85*d)+e
|
|
x,p=divmod(num,256)
|
|
x,o=divmod(x,256)
|
|
m,n=divmod(x,256)
|
|
app(chr(m)+chr(n)+chr(o)+chr(p))
|
|
if p2:
|
|
while len(p4)<5: p4=p4+'!'
|
|
a=ord(p4[0])-33
|
|
b=ord(p4[1])-33
|
|
c=ord(p4[2])-33
|
|
d=ord(p4[3])-33
|
|
e=ord(p4[4])-33
|
|
num=(52200625L*a)+(614125*b)+(7225*c)+(85*d)+e
|
|
x,p=divmod(num,256)
|
|
x,o=divmod(x,256)
|
|
m,n=divmod(x, 256)
|
|
if p2==2: app(chr(m))
|
|
elif p2==3: app(chr(m)+chr(n))
|
|
elif p2==4: app(chr(m)+chr(n)+chr(o))
|
|
return ''.join(out)
|
|
|
|
# wafdir is needed to parse the command-line arguments or print the version number
|
|
wafdir=None # SPECIAL LINE
|
|
|
|
def uncompress_wafdir(newdir):
|
|
file = open(sys.argv[0], 'rb')
|
|
while 1:
|
|
line = file.readline()
|
|
if not line:
|
|
print "This is a stripped-down waf, there is no wafadmin directory available"
|
|
print "Please set WAFDIR to a directory containing a directory named wafadmin"
|
|
print "Or use the full waf version available freely at http://freehackers.org/~tnagy/bksys.html"
|
|
print "\033[91mNo wafadmin: cannot execute anything (error)\033[0m"
|
|
sys.exit(1)
|
|
line=line.rstrip()
|
|
if line=='# ===>BEGIN WOOF<===':
|
|
cnt = file.readline()
|
|
if not cnt:
|
|
print "Corrupted waf (1)"
|
|
sys.exit(1)
|
|
|
|
line = file.readline().rstrip()
|
|
if line!='# ===>END WOOF<===':
|
|
print "Corrupted waf (2)"
|
|
sys.exit(1)
|
|
break
|
|
if not cnt:
|
|
print "Corrupted waf (3)"
|
|
sys.exit(1)
|
|
|
|
cnt = decodeAscii85(cnt[1:])
|
|
|
|
# create wafadmin
|
|
import shutil
|
|
try: shutil.rmtree(newdir)
|
|
except OSError: pass
|
|
try: os.makedirs(newdir)
|
|
except OSError:
|
|
print "Could uncompress waf-local into %s"%newdir
|
|
print "Please install waf system-wide or move waf in a writeable directory"
|
|
sys.exit(1)
|
|
|
|
os.chdir(newdir)
|
|
file = open('wafadmin.tar.bz2', 'wb')
|
|
file.write(cnt)
|
|
file.close()
|
|
|
|
# now we have the tar file to open
|
|
import tarfile
|
|
tar = tarfile.open('wafadmin.tar.bz2')
|
|
for tarinfo in tar:
|
|
tar.extract(tarinfo)
|
|
tar.close()
|
|
|
|
# cleanup the tarfile and chdir to the previous directory
|
|
os.chmod('wafadmin', 0755)
|
|
os.chmod('wafadmin'+os.sep+'Tools', 0755)
|
|
os.unlink('wafadmin.tar.bz2')
|
|
os.chdir(cwd)
|
|
|
|
global wafdir
|
|
wafdir = newdir
|
|
|
|
def try_wafdir(dir):
|
|
global wafdir
|
|
if wafdir: return
|
|
try:
|
|
os.stat(os.path.join(dir, 'wafadmin'))
|
|
wafdir = os.path.abspath(dir)
|
|
except OSError:
|
|
pass
|
|
|
|
def find_wafadmin():
|
|
global wafdir
|
|
name = sys.argv[0]
|
|
|
|
# wafadmin may be in $WAFDIR (developers)
|
|
if 'WAFDIR' in os.environ:
|
|
try_wafdir(os.environ['WAFDIR'])
|
|
if wafdir: return
|
|
|
|
# waf-light is a special beast
|
|
if name[-5:] == 'light':
|
|
try_wafdir(os.path.dirname(os.path.abspath(name)))
|
|
if wafdir: return
|
|
print "\033[91mwaf-light in use, wafadmin not found -> export WAFDIR=/folder\033[0m"
|
|
sys.exit(1)
|
|
|
|
if not wafdir:
|
|
dir = "/lib/waf-%s-%s/" % (VERSION, REVISION)
|
|
for i in [INSTALL, '/usr', '/usr/local', '/opt']:
|
|
try_wafdir(i+dir)
|
|
if wafdir: return
|
|
|
|
# remove $HOME/.waf-version if asked to
|
|
if wafdir:
|
|
if "--nocache" in sys.argv:
|
|
import shutil
|
|
print "removing the local wafdir", wafdir
|
|
try: shutil.rmtree(wafdir)
|
|
except OSError: pass
|
|
try: os.stat(wafdir)
|
|
except OSError: wafdir=None
|
|
|
|
if wafdir: return
|
|
|
|
# look in the directory containing waf
|
|
if sys.platform == 'win32': s='waf-%s-%s'
|
|
else: s='.waf-%s-%s'
|
|
dir = os.path.join(os.path.dirname(os.path.abspath(name)), s % (VERSION, REVISION))
|
|
try_wafdir(dir)
|
|
if wafdir: return
|
|
|
|
# not found, uncompress
|
|
wafdir = dir
|
|
uncompress_wafdir(dir)
|
|
|
|
# run the test
|
|
find_wafadmin()
|
|
if "-vv" in sys.argv: print "wafdir is ", wafdir
|
|
|
|
# Update sys.path and import our modules
|
|
wafadmindir = os.path.join(wafdir, 'wafadmin')
|
|
tooldir = os.path.join(wafadmindir, 'Tools')
|
|
sys.path = [wafadmindir, tooldir] + sys.path
|
|
|
|
import Options, Params, Utils
|
|
from Params import fatal, warning
|
|
|
|
# Set the directory containing the tools
|
|
Params.g_tooldir = [tooldir]
|
|
Params.g_cwd_launch = cwd
|
|
|
|
if Params.g_version != VERSION:
|
|
fatal('version mismatch waf %s <-> wafadmin %s (wafdir %s)' % (VERSION, Params.g_version, wafdir))
|
|
|
|
# some command-line options can be processed immediately
|
|
if '--version' in sys.argv:
|
|
opt_obj = Options.Handler()
|
|
opt_obj.parse_args()
|
|
sys.exit(0)
|
|
|
|
# now find the wscript file
|
|
msg1 = 'Waf: *** Nothing to do! Please run waf from a directory containing a file named "wscript"'
|
|
|
|
# Some people want to configure their projects gcc-style:
|
|
# mkdir build && cd build && ../waf configure && ../waf
|
|
# check that this is really what is wanted
|
|
build_dir_override = None
|
|
candidate = None
|
|
|
|
lst = os.listdir(cwd)
|
|
xml = 0
|
|
#check if a wscript or a wscript_xml file is in current directory
|
|
if (not 'wscript' in lst) and (not 'wscript_xml' in lst):
|
|
if 'configure' in sys.argv:
|
|
#set the build directory with the current directory
|
|
build_dir_override = cwd
|
|
if 'wscript_build' in lst:
|
|
#try to find the wscript root
|
|
candidate = cwd
|
|
else:
|
|
#wscript or wscript_xml is in current directory, use this directory as candidate
|
|
candidate = cwd
|
|
|
|
try:
|
|
#check the following dirs for wscript or wscript_xml
|
|
search_for_candidate = True
|
|
if not candidate:
|
|
#check first the calldir if there is wscript or wscript_xml
|
|
#for example: /usr/src/configure the calldir would be /usr/src
|
|
calldir = os.path.abspath(os.path.dirname(sys.argv[0]))
|
|
lst_calldir = os.listdir(calldir)
|
|
if 'wscript' in lst_calldir:
|
|
candidate = calldir
|
|
search_for_candidate = False
|
|
if 'wscript_xml' in lst_calldir:
|
|
candidate = calldir
|
|
xml = 1
|
|
search_for_candidate = False
|
|
if "--make-waf" in sys.argv and candidate:
|
|
search_for_candidate = False
|
|
|
|
#check all directories above current dir for wscript or wscript_xml if still not found
|
|
while search_for_candidate:
|
|
if len(cwd) <= 3:
|
|
break # stop at / or c:
|
|
dirlst = os.listdir(cwd)
|
|
if 'wscript' in dirlst:
|
|
candidate = cwd
|
|
xml = 0
|
|
if 'wscript_xml' in dirlst:
|
|
candidate = cwd
|
|
xml = 1
|
|
break
|
|
if 'configure' in sys.argv and candidate:
|
|
break
|
|
if Params.g_lockfile in dirlst:
|
|
break
|
|
cwd = cwd[:cwd.rfind(os.sep)] # climb up
|
|
except:
|
|
fatal(msg1)
|
|
|
|
if not candidate:
|
|
# check if the user only wanted to display the help
|
|
if '-h' in sys.argv or '--help' in sys.argv:
|
|
warning('No wscript file found: the help message may be incomplete')
|
|
opt_obj = Options.Handler()
|
|
opt_obj.parse_args()
|
|
sys.exit(0)
|
|
else:
|
|
fatal(msg1)
|
|
|
|
# We have found wscript, but there is no guarantee that it is valid
|
|
os.chdir(candidate)
|
|
|
|
# xml -> jump to the parser
|
|
if xml:
|
|
from XMLScripting import compile
|
|
compile(candidate+os.sep+'wscript_xml')
|
|
else:
|
|
# define the main module containing the functions init, shutdown, ..
|
|
Utils.set_main_module(os.path.join(candidate, 'wscript'))
|
|
|
|
if build_dir_override:
|
|
d = getattr(Utils.g_module, 'blddir', None)
|
|
if d:
|
|
# test if user has set the blddir in wscript.
|
|
msg = 'Overriding build directory %s with %s' % (d, build_dir_override)
|
|
Params.niceprint(msg, 'WARNING', 'waf')
|
|
Utils.g_module.blddir = build_dir_override
|
|
|
|
# fetch the custom command-line options recursively and in a procedural way
|
|
opt_obj = Options.Handler()
|
|
opt_obj.sub_options('') # will look in wscript
|
|
opt_obj.parse_args()
|
|
|
|
# use the parser results
|
|
if Params.g_commands['dist']:
|
|
# try to use the user-defined dist function first, fallback to the waf scheme
|
|
fun = getattr(Utils.g_module, 'dist', None)
|
|
if fun: fun(); sys.exit(0)
|
|
|
|
appname = getattr(Utils.g_module, 'APPNAME', 'noname')
|
|
|
|
get_version = getattr(Utils.g_module, 'get_version', None)
|
|
if get_version: version = get_version()
|
|
else: version = getattr(Utils.g_module, 'VERSION', None)
|
|
if not version: version = '1.0'
|
|
|
|
from Scripting import Dist
|
|
Dist(appname, version)
|
|
sys.exit(0)
|
|
elif Params.g_commands['distclean']:
|
|
# try to use the user-defined distclean first, fallback to the waf scheme
|
|
fun = getattr(Utils.g_module, 'distclean', None)
|
|
if fun: fun(); sys.exit(0)
|
|
from Scripting import DistClean
|
|
DistClean()
|
|
sys.exit(0)
|
|
elif Params.g_commands['distcheck']:
|
|
# try to use the user-defined dist function first, fallback to the waf scheme
|
|
fun = getattr(Utils.g_module, 'dist', None)
|
|
if fun: fun(); sys.exit(0)
|
|
|
|
appname = getattr(Utils.g_module, 'APPNAME', 'noname')
|
|
|
|
get_version = getattr(Utils.g_module, 'get_version', None)
|
|
if get_version: version = get_version()
|
|
else: version = getattr(Utils.g_module, 'VERSION', None)
|
|
if not version: version = '1.0'
|
|
|
|
from Scripting import DistCheck
|
|
DistCheck(appname, version)
|
|
sys.exit(0)
|
|
|
|
fun=getattr(Utils.g_module, 'init', None)
|
|
if fun: fun()
|
|
|
|
import Scripting
|
|
try: Scripting.Main()
|
|
except KeyboardInterrupt: Params.fatal('build interrupted')
|
|
#import hotshot
|
|
#prof=hotshot.Profile("/tmp/proftest.txt")
|
|
#prof.runcall(Scripting.Main)
|
|
#prof.close()
|
|
|