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