#!/usr/bin/env python # # Copyright 2017 Ettus Research, a National Instruments Company # # SPDX-License-Identifier: GPL-3.0 # """ Tool to import external dependency rpclib into UHD tree """ import argparse from distutils.dir_util import copy_tree import os import re import shutil import subprocess import tempfile from mako.template import Template IMPORTANT_FILES = [ "lib", "include", "LICENSE.md", "README.md", "CHANGELOG.md" ] REPLACE_EXPR = [ ("RPCLIB_ASIO", "boost::asio"), ("\"asio.hpp\"", ""), ("std::error_code", "boost::system::error_code") ] def fix_naming(workdir): """ Applies all the REPLACE_EXPR in all the files """ for root, dirs, files in os.walk(workdir): for cur_file in files: if re.match(".*[hc](?:c?|\.in)|inl",cur_file): new_file = tempfile.NamedTemporaryFile() with new_file as new: with open(os.path.join(root,cur_file), "r") as old: for line in old: for repl in REPLACE_EXPR: line = line.replace(*repl) new.write(line) new.truncate() shutil.copyfile(new_file.name, os.path.join(root, cur_file)) def extract_rpclib_version(rpclib_root): """ match version definition in rpclib cmakelists """ with open(os.path.join(rpclib_root, "CMakeLists.txt")) as rpclib_cmake: version_dict = {} for line in rpclib_cmake: version_match =re.match("^.*RPCLIB_VERSION_(?PMAJOR|MINOR|PATCH) (?P[0-9]+).*$", line) if version_match: version_dict[version_match.group("which").lower()] = int(version_match.group("number")) if not set(version_dict.keys()).issuperset(set(["major", "minor", "patch"])): raise Exception("couldn't find right version definitions in CMakeLists.txt") return (version_dict["major"], version_dict["minor"], version_dict["patch"]) def copy_important_files(target_root, rpclib_root): """ copy files/subdirs we consider important (see IMPORTANT_FILES) """ for rpc_file in os.listdir(rpclib_root): if rpc_file in IMPORTANT_FILES: if os.path.isdir(os.path.join(rpclib_root, rpc_file)): copy_tree( os.path.join(rpclib_root, rpc_file), os.path.join(target_root, rpc_file) ) else: shutil.copyfile( os.path.join(rpclib_root, rpc_file), os.path.join(target_root, rpc_file) ) def patch_rpclib(rpclib_root): """ applies all *.patch files in the same directory as the script """ curr_dir = os.path.dirname(os.path.realpath(__file__)) for rpc_patch in (patch for patch in sorted(os.listdir(curr_dir)) if patch.endswith("patch")): print("patching with: {0}".format(rpc_patch)) patch = open(os.path.join(curr_dir, rpc_patch), "r") patch_proc = subprocess.Popen(['patch', '--quiet', '-p1'], stdin=patch, cwd=rpclib_root) def extract_rpclib(args): """ THE extraction function """ workdir = tempfile.mkdtemp() rpclib_root = args.rpclib_root new_rpclib_root = tempfile.mkdtemp() copy_tree(rpclib_root, new_rpclib_root) patch_rpclib(new_rpclib_root) copy_important_files(workdir, new_rpclib_root) version = extract_rpclib_version(new_rpclib_root) shutil.rmtree(new_rpclib_root) cmake_template = Template( filename=os.path.join(os.path.dirname(os.path.realpath(__file__)), "rpc_CMakeLists.txt")) real_cmake_file = cmake_template.render( rpclib_major_version=version[0], rpclib_minor_version=version[1], rpclib_patch_version=version[2] ) with open(os.path.join(workdir, "CMakeLists.txt"), "w") as cmake_file: cmake_file.write(real_cmake_file) cmake_file.truncate() fix_naming(workdir) copy_tree(workdir, args.rpclib_target, update=True) shutil.rmtree(workdir) def parse_args(): """ parse cmdline arguments """ parser = argparse.ArgumentParser() parser.add_argument("rpclib_root") parser.add_argument('rpclib_target') return parser.parse_args() def main(): """ Execute this tool """ args = parse_args() extract_rpclib(args) return True if __name__ == "__main__": exit(not main())