Skip to content

Instantly share code, notes, and snippets.

@housel
Created October 5, 2011 06:15
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 housel/1263777 to your computer and use it in GitHub Desktop.
Save housel/1263777 to your computer and use it in GitHub Desktop.
Beginnings of code to generate OpenEmbedded Bitbake recipes for a ROS distro
#!/usr/bin/env python
# Software License Agreement (BSD License)
#
# Copyright Peter S. Housel
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of Willow Garage, Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import os
import os.path
import sys
import re
import urlparse;
import rospkg
import vcstools
from rospkg.distro import load_distro, distro_uri
ros_root = '/tmp/ros'
def make_layer(distro):
layername = 'meta-ros-' + distro
layerconfdir = os.path.join(layername, 'conf');
if not os.path.exists(layerconfdir):
os.makedirs(layerconfdir)
layerconf = os.path.join(layerconfdir, 'layer.conf')
lc = open(layerconf, 'w')
lc.write("# We have a conf and classes directory, append to BBPATH\n")
lc.write("BBPATH .= \":${LAYERDIR}\"\n\n")
lc.write("# We have a recipes directory, add to BBFILES\n")
lc.write("BBFILES += \"${LAYERDIR}/recipes*/*/*.bb ${LAYERDIR}/recipes*/*/*.bbappend\"\n\n")
lc.write("BBFILE_COLLECTIONS += \"%s\"\n" % layername)
lc.write("BBFILE_PATTERN_%s := \"^${LAYERDIR}/\"\n" % layername)
lc.write("BBFILE_PRIORITY_%s := \"10\"\n" % layername)
lc.close()
recipesdir = os.path.join(layername, 'recipes');
if not os.path.exists(recipesdir):
os.makedirs(recipesdir)
return recipesdir
def make_recipe(recipesdir, stack_info):
recipe_name = stack_info['stack_name'].replace('_', '-')
recipe_dir = os.path.join(recipesdir, recipe_name);
if not os.path.exists(recipe_dir):
os.makedirs(recipe_dir)
version = stack_info['version']
recipe_fn = os.path.join(recipe_dir, recipe_name + '_' + version + '.bb')
recipe = open(recipe_fn, 'w')
if stack_info['summary']:
recipe.write("SUMMARY = \"%s\"\n" % stack_info['summary'])
#recipe.write("DESCRIPTION = \"%s\"\n" % stack_info['description'])
if stack_info['url']:
recipe.write("HOMEPAGE = \"%s\"\n" % stack_info['url'])
recipe.write("LICENSE = \"%s\"\n" % stack_info['license'])
recipe.write("LIC_FILES_CHKSUM = \"\"\n\n")
o = urlparse.urlparse(stack_info['vcs_uri'])
scheme = o.scheme
if stack_info['vcs_type'] == 'svn':
src_uri = urlparse.urlunsplit(('svn', o.netloc, o.path, None, None))
src_uri += ';module=%s' % stack_info['stack_name']
src_uri += ';rev=%s' % stack_info['vcs_version'].replace('-r', '')
src_uri += ';proto=%s' % scheme
elif stack_info['vcs_type'] == 'git':
src_uri = urlparse.urlunsplit(('git', o.netloc, o.path, None, None))
src_uri += ';rev=%s' % stack_info['vcs_version']
src_uri += ';protocol=%s' % scheme
elif stack_info['vcs_type'] == 'hg':
if scheme == 'https': scheme = 'http' # FIXME
head, tail = os.path.split(o.path)
src_uri = urlparse.urlunsplit(('hg', o.netloc, head, None, None))
src_uri += ';module=%s' % tail # stack_info['stack_name']
src_uri += ';rev=%s' % stack_info['vcs_version']
src_uri += ';proto=%s' % scheme
else:
sys.stderr.write('no ' + stack_info['vcs_type'] + "\n")
sys.exit(1)
recipe.write("SRC_URI = \"%s\"\n" % src_uri)
recipe.close()
def stack_checkout(stack_info):
vcspath = os.path.join(ros_root, stack_info['stack_name'])
vcsclient = vcstools.VcsClient(stack_info['vcs_type'], vcspath)
if not vcsclient.path_exists():
if stack_info['vcs_tag']:
vcsclient.checkout(stack_info['vcs_uri'], stack_info['vcs_tag'])
else:
vcsclient.checkout(stack_info['vcs_uri'])
if vcsclient.path_exists():
stack_info['vcs_version'] = vcsclient.get_version()
def distro_recipes_main():
from optparse import OptionParser
distro = sys.argv[1]
uri = distro_uri(distro)
d = load_distro(uri)
if not os.path.exists(ros_root):
os.makedirs(ros_root)
stack_info = {}
#os.makedirs("recipes-ros-" + distro)
# Check out everything in the distro variant
for variant_name in ['robot']:
variant = d.variants[variant_name]
for stack_name in variant.stack_names:
stack = d.stacks[stack_name]
vcs_config = stack.vcs_config
branch = 'distro'
uri, version_tag = vcs_config.get_branch(branch, True)
stack_info[stack_name] = {
'stack_name' : stack_name,
'vcs_type' : vcs_config.type,
'vcs_uri' : uri,
'vcs_tag' : version_tag,
}
stack_checkout(stack_info[stack_name])
rosstack = rospkg.RosStack(ros_root=ros_root, ros_package_path='')
rospack = rospkg.RosPack(ros_root=ros_root, ros_package_path='')
recipesdir = make_layer(distro)
for stack_name in rosstack.list():
path = rosstack.get_path(stack_name)
info = stack_info[stack_name]
print "stack " + stack_name
info['depends'] = rosstack.get_depends(stack_name, implicit=True)
stack_manifest = rosstack.get_manifest(stack_name)
info['url'] = stack_manifest.url
info['license'] = stack_manifest.license
info['summary'] = stack_manifest.brief
info['version'] = stack_manifest.version
# Find the version if it's not already in the stack manifest
if not info['version']:
cmf = open(os.path.join(path, 'CMakeLists.txt'), 'r')
for line in cmf:
m = re.search('^rosbuild_make_distribution\((.*)\)', line)
if m:
info['version'] = m.group(1)
cmf.close()
for package_name in rosstack.packages_of(stack_name):
print " package: " + package_name
package_manifest = rospack.get_manifest(package_name)
print " author: " + (package_manifest.author or 'None')
print " license: " + package_manifest.license
#print " license url: " + package_manifest.license_url
#print " description: " + package_manifest.description
print " depends: " + (', '.join(rospack.get_depends(package_name, implicit=True)))
print " rosdeps: " + (', '.join(rospack.get_rosdeps(package_name)))
print " exports: ", package_manifest.exports
#print " rosbuild2: ", package_manifest.rosbuild2
make_recipe(recipesdir, info)
sys.exit(0)
if __name__ == '__main__':
distro_recipes_main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment