#!/usr/bin/env python
#
# Copyright 2017 Ettus Research (National Instruments)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
"""
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())