Skip to content

Instantly share code, notes, and snippets.

@stertingen
Last active July 4, 2020 12:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stertingen/76b0d9e5078674eff1fa086bb91fe8dd to your computer and use it in GitHub Desktop.
Save stertingen/76b0d9e5078674eff1fa086bb91fe8dd to your computer and use it in GitHub Desktop.
#!/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