Skip to content

Instantly share code, notes, and snippets.

@gdlg
Created November 24, 2016 18:23
Show Gist options
  • Save gdlg/0baef40982b10999d0554ef58aa77535 to your computer and use it in GitHub Desktop.
Save gdlg/0baef40982b10999d0554ef58aa77535 to your computer and use it in GitHub Desktop.
Script to build and install ROS Kinetic on Arch (for testing purposes)
#! /usr/bin/env python2
# *-* encoding: utf-8 *-*
import rosdistro
import networkx as nx
import catkin_pkg.package
import subprocess
import glob
import os
import sys
if len(sys.argv) == 1:
print("Usage: rosbuild_pkgs.py <ROS packages...>")
print("e.g. rosbuild_pkgs.py desktop_full")
print("To fetch from my arch test release repositories, set the environment variable:")
print(" ROSDISTRO_INDEX_URL=https://raw.githubusercontent.com/gdlg-rosarch/rosdistro/master/index.yaml")
sys.exit(1)
required_packages = sys.argv[1:]
def execute_command(cmd):
print(" ".join(cmd))
return subprocess.call(cmd)
FNULL = open(os.devnull, 'w')
def execute_command_quiet(cmd):
return subprocess.call(cmd, stdout=FNULL)
print("Fetching distribution cache %s..." % rosdistro.get_index_url())
# Load the distribution cache for 'kinetic'
distribution_cache = rosdistro.get_distribution_cache(rosdistro.get_index(rosdistro.get_index_url()), "kinetic")
# Get the 'distribution.yaml' content from the cache
distribution = distribution_cache.distribution_file.get_data()
# Extract the list of repositories
repositories = distribution["repositories"]
print("Building dependency graph...")
# Build a mapping from ROS packages to release repositories
package_to_repo = {}
for (reponame,repo) in repositories.items():
if "release" in repo:
if "packages" in repo["release"]:
for package in repo["release"]["packages"]:
package_to_repo[package] = reponame
else:
package_to_repo[reponame] = reponame
# Build a graph of dependencies between ROS packages using the distribution cache
G = nx.DiGraph()
def get_deps(package):
xml = distribution_cache.release_package_xmls.get(package, None)
if xml is None:
return []
cpkg = catkin_pkg.package.parse_package_string(xml)
return list(set([d.name for d in cpkg.build_depends]
+ [d.name for d in cpkg.build_export_depends]
+ [d.name for d in cpkg.buildtool_depends]
+ [d.name for d in cpkg.buildtool_export_depends]
+ [d.name for d in cpkg.doc_depends]
+ [d.name for d in cpkg.exec_depends]
+ [d.name for d in cpkg.test_depends]))
def add_deps(package):
deps = get_deps(package)
for d in deps:
G.add_edge(d, package)
for reponame in repositories.keys():
repo = repositories[reponame]
if "release" in repo:
if "packages" in repo["release"]:
for package in repo["release"]["packages"]:
add_deps(package)
else:
add_deps(reponame)
print("Searching for dependencies for packages %s..." % ", ".join(required_packages))
# Find all the dependencies for the packages that we want to install
# and sort them by topological order
dependencies = set()
def add_dep(n):
dependencies.add(n)
for d in G.predecessors(n):
add_dep(d)
for pkg in required_packages:
add_dep(pkg)
Gdep = G.subgraph(dependencies)
sortedPackages = nx.topological_sort(Gdep)
# Find and install all the prerequisites using pacaur
print("Finding prerequisites...")
import rosdep2.catkin_support
view = rosdep2.catkin_support.get_catkin_view('kinetic', 'arch', 'latest')
installer = rosdep2.catkin_support.get_installer("pacman")
prerequisites = set()
for package in sortedPackages:
repo = package_to_repo.get(package,None)
if repo is None:
try:
prerequisites.update(
rosdep2.catkin_support.resolve_for_os(package, view, installer, "arch", "latest"))
except Exception as ex:
print(ex)
print("while processing prerequisite: %s" % package)
print("Found prerequisites: %s" % " ".join(prerequisites))
execute_command(["pacaur", "-S", "--needed", "--asdeps"]+list(prerequisites))
# Build and install all needed ROS packages
cwd = os.getcwd()
print("Building and installing ROS packages ...")
for package in sortedPackages:
reponame = package_to_repo.get(package,None)
if reponame is None:
continue
os.chdir(cwd)
repo = repositories[reponame]
repourl = repo['release']['url']
print("Package %s..." % package)
repogit = repourl.split('/')[-1].split('.')[-2]
# Don’t fetch the repository if it already exist.
# TODO: Update the repository if it already exist
if not os.path.exists(package):
execute_command(["git","clone",repourl,package])
os.chdir(package)
try:
# Don’t build the package if it already exist
# TODO: Check for precise version and rebuild if an older version is found.
pacman_file = max(glob.iglob('*.tar.xz'), key=os.path.getctime)
except:
# Checkout the latest PKGBUILD
execute_command(["git", "checkout", "arch/kinetic/latest/"+package])
# Build the package
execute_command(["makepkg", "-f"])
pacman_file = max(glob.iglob('*.tar.xz'), key=os.path.getctime)
# Install the package if it hasn’t been already installed.
if execute_command_quiet(["package-query","-Q", "ros-kinetic-%s" % package.replace('_','-')]) == 1:
execute_command(["sudo","pacman","-U","--noconfirm",pacman_file])
else:
print(" Skipping because the package is already installed")
@RashikShahjahan
Copy link

Hi! Did this end up working?

@RashikShahjahan
Copy link

How would I build a catkin workspace after that?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment