8f4225c
#!/usr/bin/python3
8f4225c
#
8f4225c
# Makefile modificator
8f4225c
#
8f4225c
# Should help in building bin/tests/system tests standalone,
8f4225c
# linked to libraries installed into the system.
8f4225c
# TODO:
8f4225c
# - Fix top_srcdir, because dyndb/driver/Makefile uses $TOPSRC/mkinstalldirs
8f4225c
# - Fix conf.sh to contain paths to system tools
8f4225c
# - Export $TOP/version somewhere, where it would be used
8f4225c
# - system tests needs bin/tests code. Do not include just bin/tests/system
8f4225c
#
8f4225c
# Possible solution:
8f4225c
#
8f4225c
# sed -e 's/$TOP\/s\?bin\/\(delv\|confgen\|named\|nsupdate\|pkcs11\|python\|rndc\|check\|dig\|dnssec\|tools\)\/\([[:alnum:]-]\+\)/`type -p \2`/' conf.sh
8f4225c
# sed -e 's,../../../../\(isc-config.sh\),\1,' builtin/tests.sh
8f4225c
# or use: $NAMED -V | head -1 | cut -d ' ' -f 2
8f4225c
8f4225c
import re
8f4225c
import argparse
8f4225c
8f4225c
"""
8f4225c
Script for replacing Makefile ISC_INCLUDES with runtime flags.
8f4225c
8f4225c
Should translate part of Makefile to use isc-config.sh instead static linked sources.
8f4225c
ISC_INCLUDES = -I/home/pemensik/rhel/bind/bind-9.11.12/build/lib/isc/include \
8f4225c
        -I${top_srcdir}/lib/isc \
8f4225c
        -I${top_srcdir}/lib/isc/include \
8f4225c
        -I${top_srcdir}/lib/isc/unix/include \
8f4225c
        -I${top_srcdir}/lib/isc/pthreads/include \
8f4225c
        -I${top_srcdir}/lib/isc/x86_32/include
8f4225c
8f4225c
Should be translated to:
8f4225c
ISC_INCLUDES = $(shell isc-config.sh --cflags isc)
8f4225c
"""
8f4225c
8f4225c
def isc_config(mode, lib):
8f4225c
    if mode:
8f4225c
        return '$(shell isc-config.sh {mode} {lib})'.format(mode=mode, lib=lib)
8f4225c
    else:
8f4225c
        return ''
8f4225c
8f4225c
def check_match(match, debug=False):
8f4225c
    """
8f4225c
    Check this definition is handled by internal library
8f4225c
    """
8f4225c
    if not match:
8f4225c
        return False
8f4225c
    lib = match.group(2).lower()
8f4225c
    ok = not lib_filter or lib in lib_filter
8f4225c
    if debug:
8f4225c
        print('{status} {lib}: {text}'.format(status=ok, lib=lib, text=match.group(1)))
8f4225c
    return ok
8f4225c
8f4225c
def fix_line(match, mode):
8f4225c
    lib = match.group(2).lower()
8f4225c
    return match.group(1)+isc_config(mode, lib)+"\n"
8f4225c
8f4225c
def fix_file_lines(path, debug=False):
8f4225c
    """
8f4225c
    Opens file and scans fixes selected parameters
8f4225c
8f4225c
    Returns list of lines if something should be changed,
8f4225c
    None if no action is required
8f4225c
    """
8f4225c
    fixed = []
8f4225c
    changed = False
8f4225c
    with open(path, 'r') as fin:
8f4225c
        fout = None
8f4225c
8f4225c
        line = next(fin, None)
8f4225c
        while line:
8f4225c
            appended = False
8f4225c
            while line.endswith("\\\n"):
8f4225c
                line += next(fin, None)
8f4225c
8f4225c
            inc = re_includes.match(line)
8f4225c
            deplibs = re_deplibs.match(line)
8f4225c
            libs = re_libs.match(line)
8f4225c
            newline = None
8f4225c
            if check_match(inc, debug=debug):
8f4225c
                newline = fix_line(inc, '--cflags')
8f4225c
            elif check_match(deplibs, debug=debug):
8f4225c
                newline = fix_line(libs, None)
8f4225c
            elif check_match(libs, debug=debug):
8f4225c
                newline = fix_line(libs, '--libs')
8f4225c
8f4225c
            if newline and line != newline:
8f4225c
                changed = True
8f4225c
                line = newline
8f4225c
8f4225c
            fixed.append(line)
8f4225c
            line = next(fin, None)
8f4225c
8f4225c
    if not changed:
8f4225c
        return None
8f4225c
    else:
8f4225c
        return fixed
8f4225c
8f4225c
def write_lines(path, lines):
8f4225c
    fout = open(path, 'w')
8f4225c
    for line in lines:
8f4225c
        fout.write(line)
8f4225c
    fout.close()
8f4225c
8f4225c
def print_lines(lines):
8f4225c
    for line in lines:
8f4225c
        print(line, end='')
8f4225c
8f4225c
if __name__ == '__main__':
8f4225c
    parser = argparse.ArgumentParser(description='Makefile multiline include replacer')
8f4225c
    parser.add_argument('files', nargs='+')
8f4225c
    parser.add_argument('--filter', type=str,
8f4225c
            default='isc isccc isccfg dns lwres bind9 irs',
8f4225c
            help='List of libraries supported by isc-config.sh')
8f4225c
    parser.add_argument('--check', action='store_true',
8f4225c
            help='Test file only')
8f4225c
    parser.add_argument('--print', action='store_true',
8f4225c
            help='Print changed file only')
8f4225c
    parser.add_argument('--debug', action='store_true',
8f4225c
            help='Enable debug outputs')
8f4225c
8f4225c
    args = parser.parse_args()
8f4225c
    lib_filter = None
8f4225c
8f4225c
    re_includes = re.compile(r'^\s*((\w+)_INCLUDES\s+=\s*).*')
8f4225c
    re_deplibs = re.compile(r'^\s*((\w+)DEPLIBS\s*=).*')
8f4225c
    re_libs = re.compile(r'^\s*((\w+)LIBS\s*=).*')
8f4225c
8f4225c
    if args.filter:
8f4225c
        lib_filter = set(args.filter.split(' '))
8f4225c
        pass
8f4225c
8f4225c
    for path in args.files:
8f4225c
        lines = fix_file_lines(path, debug=args.debug)
8f4225c
        if lines:
8f4225c
            if args.print:
8f4225c
                print_lines(lines)
8f4225c
            elif not args.check:
8f4225c
                write_lines(path, lines)
8f4225c
                print('File {path} was fixed'.format(path=path))
8f4225c
        else:
8f4225c
            print('File {path} does not need fixing'.format(path=path))