Last active
July 4, 2020 12:57
-
-
Save stertingen/76b0d9e5078674eff1fa086bb91fe8dd to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import os | |
import multiprocessing | |
import subprocess | |
import catkin_pkg | |
import rosdistro | |
DISTRO = 'noetic' | |
TEMPLATE_BASE = """# Maintainer: {maintainer} | |
_ros_repo='{repo_name}' | |
pkgdesc='{pkgdesc}' | |
url='{url}' | |
pkgbase='ros-{distro}-${{_ros_repo//_/-}}' | |
pkgname=( | |
{pkgnames} | |
) | |
pkgver='{pkgver}' | |
arch=('i686' 'x86_64' 'aarch64' 'armv7h' 'armv6h') | |
pkgrel=1 | |
license=({license}) | |
source=("${{pkgbase}}-${{pkgver}}.tar.gz"::"{source}/archive/${{pkgver}}.tar.gz") | |
sha256sums=('SKIP') | |
makedepends=( | |
{makedepends} | |
) | |
build() {{ | |
source /opt/ros/{distro}/setup.bash | |
catkin_make_isolated \\ | |
--directory ${{srcdir}} \\ | |
--source ${{srcdir}}/${{_ros_repo}}-${{pkgver}} \\ | |
--install-space /opt/ros/{distro} \\ | |
--cmake-args \\ | |
-DCMAKE_BUILD_TYPE=Release \\ | |
-DCATKIN_BUILD_BINARY_PACKAGE=ON \\ | |
-DPYTHON_EXECUTABLE=/usr/bin/python3 \\ | |
-DSETUPTOOLS_DEB_LAYOUT=OFF | |
}} | |
check() {{ | |
catkin_make_isolated \\ | |
--directory ${{srcdir}} \\ | |
--source ${{srcdir}}/${{_ros_repo}}-${{pkgver}} \\ | |
--install-space /opt/ros/{distro} \\ | |
--catkin-make-args run_tests | |
}} | |
""" | |
TEMPLATE_PKG = """ | |
package_{pkgname}() {{ | |
pkgdesc='{pkgdesc}' | |
url='{url}' | |
depends=( | |
{depends} | |
) | |
cd "${{srcdir}}/build_isolated/{ros_pkgname}" | |
make DESTDIR="${{pkgdir}}/" install | |
}} | |
""" | |
def get_description(pkg_xml): | |
desc = pkg_xml['description'].replace('\n', ' ').replace('\r', '').replace("'", '') | |
desc = ' '.join(desc.split()) | |
desc = desc.split('. ', maxsplit=1)[0] + '.' | |
return desc | |
def get_url(pkg_xml): | |
urls = dict([(url.type, url.url) for url in pkg_xml['urls']]) | |
url = urls.get('website', urls.get('repository', urls.get('bugtracker', ''))) | |
return url | |
def mk_arch_pkgname(pkgname): | |
return "ros-{}-{}".format(DISTRO, pkgname.replace('_', '-')) | |
def resolve_dep(dep_key): | |
if dep_key in dist.release_packages: | |
return mk_arch_pkgname(dep_key) | |
else: | |
return dep_key | |
def handle_pkgs(repo, pkg_xmls): | |
repo_name = repo.name | |
repo_packages = pkg_xmls.keys() | |
# Try to resolve metadata for the split package. | |
if repo_name in repo_packages: | |
# If there is a package inside the repository with the same name as the repository, | |
# use its metadata as metadata for the split package. | |
repo_version = pkg_xmls[repo_name]['version'] | |
repo_desc = get_description(pkg_xmls[repo_name]) | |
repo_url = get_url(pkg_xmls[repo_name]) | |
repo_licenses = set(pkg_xmls[repo_name]['licenses']) | |
else: | |
# If there is no such package, take any package. | |
any_pkg = next(iter(repo_packages)) | |
repo_version = pkg_xmls[any_pkg]['version'] | |
repo_licenses = set(pkg_xmls[any_pkg]['licenses']) | |
repo_desc = '' | |
repo_url = '' | |
make_deps = set() | |
for pkg_xml in pkg_xmls.values(): | |
make_deps.update([str(d) for d in pkg_xml['build_depends']]) | |
make_deps.update([str(d) for d in pkg_xml['buildtool_depends']]) | |
make_deps = [d for d in make_deps if d not in repo_packages] | |
if repo.source_repository is None: | |
return | |
repo_source_url = repo.source_repository.url | |
pkgbase = mk_arch_pkgname(repo_name) | |
os.makedirs(pkgbase, exist_ok=True) | |
with open(os.path.join(pkgbase, 'PKGBUILD'), mode='w') as pkgbuild: | |
pkgbuild.write(TEMPLATE_BASE.format( | |
maintainer='blubb', | |
pkgdesc=repo_desc, | |
url=repo_url, | |
pkgnames='\n '.join(["'{}'".format(mk_arch_pkgname(n)) for n in repo_packages]), | |
pkgver=repo_version, | |
license=' '.join(["'{}'".format(l) for l in repo_licenses]), | |
source=repo_source_url.replace('.git', ''), | |
makedepends='\n '.join(["'{}'".format(resolve_dep(d)) for d in make_deps]), | |
distro=DISTRO, | |
repo_name=repo_name | |
)) | |
for pkg_xml in pkg_xmls.values(): | |
deps = set() | |
deps.update([str(d) for d in pkg_xml['exec_depends']]) | |
deps.update([str(d) for d in pkg_xml['build_export_depends']]) | |
deps.update([str(d) for d in pkg_xml['buildtool_export_depends']]) | |
pkgbuild.write(TEMPLATE_PKG.format( | |
pkgname=mk_arch_pkgname(pkg_xml['name']), | |
pkgdesc=get_description(pkg_xml), | |
url=get_url(pkg_xml), | |
depends='\n '.join(["'{}'".format(resolve_dep(d)) for d in deps]), | |
ros_pkgname=pkg_xml['name'], | |
)) | |
subprocess.run(['/bin/sh', '-c', 'cd {} && sed -i "s/^sha256sums.*$/`makepkg -g 2>/dev/null`/g" PKGBUILD'.format(pkgbase)]) | |
def get_pkg_xmls(dist, repo): | |
xmls = dict() | |
for pkgname in repo.release_repository.package_names: | |
xmls[pkgname] = catkin_pkg.package.parse_package_string(dist.get_release_package_xml(pkgname)) | |
return xmls | |
def open_repo(repo): | |
print("Open repository '{}' ...".format(repo.name)) | |
if repo.release_repository is None: | |
return | |
num_pkgs = len(repo.release_repository.package_names) | |
if num_pkgs < 1: | |
return | |
handle_pkgs(repo, get_pkg_xmls(dist, repo)) | |
idx = rosdistro.get_index(rosdistro.DEFAULT_INDEX_URL) | |
dist = rosdistro.get_distribution(idx, DISTRO) | |
pool = multiprocessing.Pool(16) | |
pool.map(open_repo, dist.repositories.values()) | |
pool.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment