-
-
Save RashikShahjahan/582654ec183c66d48c5d07838f4711b3 to your computer and use it in GitHub Desktop.
Script to build and install ROS Kinetic on Arch (for testing purposes)
This file contains 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 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") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment