import string, os, glob, sys, importlib
def is_in_path(program):
def is_exe(fpath):
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
fpath, fname = os.path.split(program)
if fpath:
return is_exe(program)
else:
for path in os.environ["PATH"].split(os.pathsep):
path = path.strip('"')
exe_file = os.path.join(path, program)
if is_exe(exe_file):
return True
return False
platform = sys.platform
if platform == 'linux2':
platform = 'linux'
os.system('rm -rf testing-flags');
os.mkdir('testing-flags');
with open('testing-flags/test.c', 'w') as f:
f.write("""int main() {
return 0;
}
""")
cc = 'gcc'
cflags = '$CFLAGS'
for flag in ['-O2', '-Wall', '-Werror', '-std=c99', '-g', '-mtune=native', '-fpic']:
if not os.system('cd testing-flags && %s %s %s -c test.c' %
(cc, cflags, flag)):
cflags += ' ' + flag
else:
print('# %s cannot use flag: %s' % (cc, flag))
print('# cc=', repr(cc)) print('# cflags=', repr(cflags))
print("""
| %s %s -c bigbro-%s.c
< syscalls/linux.h
> bigbro-%s.o
# We need to remove libbigbro.a before running ar, because otherwise
# it will be added to, rather than replaced.
| rm -f libbigbro.a && ${AR-ar} rc libbigbro.a bigbro-%s.o && ${RANLIB-ranlib} libbigbro.a
< bigbro-%s.o
> libbigbro.a
""" % (cc, cflags, platform, platform, platform, platform))
print("""
| %s %s -static -o bigbro -L. fileaccesses.c -lbigbro
< libbigbro.a
> bigbro
""" % (cc, cflags))
print("""
| %s %s -shared -o libbigbro.so bigbro-%s.o
< bigbro-%s.o
> libbigbro.so
""" % (cc, cflags, platform, platform))
winlibraryfiles = ['bigbro-windows.c', 'win32/inject.c',
'win32/queue.c', 'win32/create_dlls.c', 'win32/dll_paths.c']
wincfiles = winlibraryfiles + ['fileaccesses.c']
dll_cfiles = ['win32/inject.c', 'win32/dll.c', 'win32/patch.c', 'win32/hooks.c',
'win32/queue.c', 'win32/dll_paths.c']
if is_in_path('i686-w64-mingw32-gcc'):
print('\n# We have a 32-bit mingw compiler, so let us cross-compile for windows!\n')
cflags = ''
for flag in ['-Wall', '-Werror', '-std=c99', '-g', '-O2']:
if not os.system('cd testing-flags && i686-w64-mingw32-gcc %s %s -c test.c' %
(cflags, flag)):
cflags += ' ' + flag
else:
print('# i686-w64-mingw32-gcc cannot use flag: %s' % flag)
print('''
# first build the helper executable
| i686-w64-mingw32-gcc %s -c -o win32/helper32.obj win32/helper.c
| i686-w64-mingw32-gcc -o win32/helper.exe win32/helper32.obj
< win32/helper32.obj
# now convert this executable into a header file
| python3 build/binary2header.py win32/helper.exe win32/helper.h helper
< win32/helper.exe
''' % (cflags))
for c in dll_cfiles:
print("""
| i686-w64-mingw32-gcc %s -c -o %s32.obj %s
""" % (cflags, c[:-2], c))
print('''
| i686-w64-mingw32-gcc -shared -o bigbro32.dll %s -lntdll -lpsapi'''
% ' '.join([c[:-2]+'32.obj' for c in dll_cfiles]))
for c in dll_cfiles:
print("< %s32.obj" % c[:-2])
if is_in_path('x86_64-w64-mingw32-gcc'):
print('\n# We have a 64-bit mingw compiler, so let us cross-compile for windows!\n')
cflags = ''
for flag in ['-Wall', '-Werror', '-std=c99', '-g', '-O2']:
if not os.system('cd testing-flags && x86_64-w64-mingw32-gcc %s %s -c test.c' %
(cflags, flag)):
cflags += ' ' + flag
else:
print('# x86_64-w64-mingw32-gcc cannot use flag: %s' % flag)
for c in set(dll_cfiles+wincfiles):
print("""
| x86_64-w64-mingw32-gcc %s -c -o %s.obj %s
> %s.obj
""" % (cflags, c[:-2], c, c[:-2]))
if c == 'win32/create_dlls.c':
print('< win32/bigbro32.h')
print('< win32/bigbro64.h')
print('< win32/helper.h')
print('''
| x86_64-w64-mingw32-gcc -shared -o bigbro64.dll %s -lntdll -lpsapi'''
% ' '.join([c[:-2]+'.obj' for c in dll_cfiles]))
for c in dll_cfiles:
print("< %s.obj" % c[:-2])
print('''
# convert the dlls into into header files
| python3 build/binary2header.py bigbro32.dll win32/bigbro32.h bigbro32dll
< bigbro32.dll
| python3 build/binary2header.py bigbro64.dll win32/bigbro64.h bigbro64dll
< bigbro64.dll
''')
print("""
| x86_64-w64-mingw32-gcc -o bigbro.exe fileaccesses.obj libbigbro-windows.a
< fileaccesses.obj
< libbigbro-windows.a
""")
for c in wincfiles:
print("< %s.obj" % c[:-2])
print("""
# We need to remove libbigbro.a before running ar, because otherwise
# it will be added to, rather than replaced.
| rm -f libbigbro-windows.a && x86_64-w64-mingw32-gcc-ar rc libbigbro-windows.a %s && x86_64-w64-mingw32-gcc-ranlib libbigbro-windows.a
> libbigbro-windows.a
""" % (' '.join([c[:-1]+'obj' for c in winlibraryfiles])))
for c in winlibraryfiles:
print("< %s.obj" % c[:-2])
for c in glob.glob('tests/*.c'):
base = c[:-2]
m = importlib.import_module('tests.'+base[6:])
if 'skip_windows' in dir(m):
print('# skipping test', base, 'not supported by windows')
else:
print("""
| x86_64-w64-mingw32-gcc %s -o %s-test.exe %s"""
% (cflags, c[:-2], c))
os.system('rm -rf testing-flags')
if is_in_path('sass'):
print('''
| sass -I. web/style.scss web/style.css
> web/style.css
C .sass-cache
''')
else:
print("# no sass, so we won't build style.css")
if is_in_path('doxygen'):
print('''
| doxygen build/Doxyfile
> web/doxy/bigbro_8h.html
< build/doxy/header.html
| cp web/doxy/bigbro_8h.html web/documentation.html
< web/doxy/bigbro_8h.html
> web/documentation.html
''')
def cargo_cmd(cmd, inps, outs):
print('\n| {}'.format(cmd))
for i in inps:
print("< {}".format(i))
for o in outs:
print("> {}".format(o))
print('''c ~
c #
c .tum
c .pyc
c .gcda
c .gcno
c .gcov
c -bigbro
c Cargo.lock
C bench
C tests
C target
C web''')
if is_in_path('cargo'):
cargo_cmd("cargo build && cp target/debug/test-bigbro .",
["syscalls/linux.h"],
["test-bigbro"])
cargo_cmd("cargo doc --no-deps && cp -a target/doc web/", [],
["web/doc/bigbro/index.html"])
cargo_cmd("cargo build --release && cp target/release/test-bigbro release-bigbro",
["syscalls/linux.h"],
["release-bigbro"])
else:
print('# no cargo, so cannot build using rust')