autoproj 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +2 -0
- data/Manifest.txt +37 -0
- data/README.txt +79 -0
- data/Rakefile +84 -0
- data/bin/autoproj +465 -0
- data/doc/guide/config.yaml +30 -0
- data/doc/guide/ext/init.rb +17 -0
- data/doc/guide/ext/previous_next.rb +40 -0
- data/doc/guide/ext/rdoc_links.rb +33 -0
- data/doc/guide/src/autobuild.page +111 -0
- data/doc/guide/src/autoproj_bootstrap +218 -0
- data/doc/guide/src/default.css +325 -0
- data/doc/guide/src/default.template +74 -0
- data/doc/guide/src/htmldoc.metainfo +4 -0
- data/doc/guide/src/images/bodybg.png +0 -0
- data/doc/guide/src/images/contbg.png +0 -0
- data/doc/guide/src/images/footerbg.png +0 -0
- data/doc/guide/src/images/gradient1.png +0 -0
- data/doc/guide/src/images/gradient2.png +0 -0
- data/doc/guide/src/index.page +79 -0
- data/doc/guide/src/source_yml.page +139 -0
- data/doc/guide/src/structure.page +153 -0
- data/lib/autoproj.rb +23 -0
- data/lib/autoproj/autobuild.rb +173 -0
- data/lib/autoproj/default.osdeps +12 -0
- data/lib/autoproj/manifest.rb +697 -0
- data/lib/autoproj/options.rb +137 -0
- data/lib/autoproj/osdeps.rb +134 -0
- data/lib/autoproj/system.rb +66 -0
- data/lib/autoproj/version.rb +3 -0
- data/samples/manifest +9 -0
- data/samples/manifest.xml +20 -0
- data/samples/osdeps.yml +65 -0
- data/test/data/test_manifest/autoproj/local/local.autobuild +0 -0
- data/test/data/test_manifest/autoproj/manifest +8 -0
- data/test/test_debian.rb +16 -0
- data/test/test_manifest.rb +40 -0
- metadata +199 -0
@@ -0,0 +1,137 @@
|
|
1
|
+
module Autoproj
|
2
|
+
class InputError < RuntimeError; end
|
3
|
+
|
4
|
+
class BuildOption
|
5
|
+
attr_reader :name
|
6
|
+
attr_reader :type
|
7
|
+
attr_reader :options
|
8
|
+
|
9
|
+
attr_reader :validator
|
10
|
+
|
11
|
+
TRUE_STRINGS = %w{on yes y true}
|
12
|
+
FALSE_STRINGS = %w{off no n false}
|
13
|
+
def initialize(name, type, options, validator)
|
14
|
+
@name, @type, @options = name.to_str, type.to_str, options.to_hash
|
15
|
+
@validator = validator.to_proc if validator
|
16
|
+
if !BuildOption.respond_to?("validate_#{type}")
|
17
|
+
raise ConfigError, "invalid option type #{type}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def doc
|
22
|
+
options[:doc] || "#{name} (no documentation for this option)"
|
23
|
+
end
|
24
|
+
|
25
|
+
def ask(current_value)
|
26
|
+
default_value = if current_value then current_value
|
27
|
+
else options[:default]
|
28
|
+
end
|
29
|
+
|
30
|
+
STDERR.print " #{doc} [#{default_value}] "
|
31
|
+
answer = STDIN.readline.chomp
|
32
|
+
if answer == ''
|
33
|
+
answer = default_value
|
34
|
+
end
|
35
|
+
validate(answer)
|
36
|
+
|
37
|
+
rescue InputError => e
|
38
|
+
STDERR.puts Autoproj.console.color("invalid value: #{e.message}", :red)
|
39
|
+
retry
|
40
|
+
end
|
41
|
+
|
42
|
+
def validate(value)
|
43
|
+
value = BuildOption.send("validate_#{type}", value, options)
|
44
|
+
if validator
|
45
|
+
value = validator[value]
|
46
|
+
end
|
47
|
+
value
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.validate_boolean(value, options)
|
51
|
+
if TRUE_STRINGS.include?(value.downcase)
|
52
|
+
true
|
53
|
+
elsif FALSE_STRINGS.include?(value.downcase)
|
54
|
+
false
|
55
|
+
else
|
56
|
+
raise InputError, "invalid boolean value '#{value}', accepted values are '#{TRUE_STRINGS.join(", ")}' for true, and '#{FALSE_STRINGS.join(", ")} for false"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.validate_string(value, options)
|
61
|
+
if possible_values = options[:possible_values]
|
62
|
+
if !possible_values.include?(value)
|
63
|
+
raise InputError, "invalid value '#{value}', accepted values are '#{possible_values.join(", ")}'"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
value
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
@user_config = Hash.new
|
71
|
+
|
72
|
+
def self.option_set
|
73
|
+
@user_config.inject(Hash.new) do |h, (k, v)|
|
74
|
+
h[k] = v.first
|
75
|
+
h
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.user_config(key)
|
80
|
+
value, seen = @user_config[key]
|
81
|
+
|
82
|
+
if value.nil? || (!seen && Autoproj.reconfigure?)
|
83
|
+
value = configure(key)
|
84
|
+
else
|
85
|
+
if !seen
|
86
|
+
STDERR.puts " #{@declared_options[key].doc}: #{value}"
|
87
|
+
@user_config[key] = [value, true]
|
88
|
+
end
|
89
|
+
value
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
@declared_options = Hash.new
|
94
|
+
def self.configuration_option(name, type, options, &validator)
|
95
|
+
@declared_options[name] = BuildOption.new(name, type, options, validator)
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.configure(option_name)
|
99
|
+
if opt = @declared_options[option_name]
|
100
|
+
if current_value = @user_config[option_name]
|
101
|
+
current_value = current_value.first
|
102
|
+
end
|
103
|
+
value = opt.ask(current_value)
|
104
|
+
@user_config[option_name] = [value, true]
|
105
|
+
value
|
106
|
+
else
|
107
|
+
raise ConfigError, "undeclared option '#{option_name}'"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.save_config
|
112
|
+
File.open(File.join(Autoproj.config_dir, "config.yml"), "w") do |io|
|
113
|
+
config = Hash.new
|
114
|
+
@user_config.each_key do |key|
|
115
|
+
config[key] = @user_config[key].first
|
116
|
+
end
|
117
|
+
|
118
|
+
io.write YAML.dump(config)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def self.load_config
|
123
|
+
config_file = File.join(Autoproj.config_dir, "config.yml")
|
124
|
+
if File.exists?(config_file)
|
125
|
+
config = YAML.load(File.read(config_file))
|
126
|
+
config.each do |key, value|
|
127
|
+
@user_config[key] = [value, false]
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
class << self
|
133
|
+
attr_accessor :reconfigure
|
134
|
+
end
|
135
|
+
def self.reconfigure?; @reconfigure end
|
136
|
+
end
|
137
|
+
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
module Autoproj
|
3
|
+
class OSDependencies
|
4
|
+
def self.load(file)
|
5
|
+
OSDependencies.new(YAML.load(File.read(file)))
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :definitions
|
9
|
+
def initialize(defs = Hash.new)
|
10
|
+
@definitions = defs.to_hash
|
11
|
+
end
|
12
|
+
|
13
|
+
def merge(info)
|
14
|
+
@definitions = definitions.merge(info.definitions)
|
15
|
+
end
|
16
|
+
|
17
|
+
def operating_system
|
18
|
+
if File.exists?('/etc/debian_version')
|
19
|
+
codename = File.read('/etc/debian_version').chomp
|
20
|
+
['debian', codename]
|
21
|
+
else
|
22
|
+
raise ConfigError, "Unknown operating system"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
GAIN_ROOT_ACCESS = <<-EOSCRIPT
|
27
|
+
if test `id -u` != "0"; then
|
28
|
+
exec sudo /bin/bash $0 "$@"
|
29
|
+
|
30
|
+
fi
|
31
|
+
EOSCRIPT
|
32
|
+
|
33
|
+
OS_PACKAGE_INSTALL = {
|
34
|
+
'debian' => 'apt-get install -y %s'
|
35
|
+
}
|
36
|
+
|
37
|
+
def generate_os_script(dependencies)
|
38
|
+
os_name, os_version = operating_system
|
39
|
+
shell_snippets = ""
|
40
|
+
os_packages = []
|
41
|
+
dependencies.each do |name|
|
42
|
+
dep_def = definitions[name]
|
43
|
+
if !dep_def
|
44
|
+
raise ConfigError, "I don't know how to install '#{name}'"
|
45
|
+
elsif !dep_def[os_name]
|
46
|
+
raise ConfigError, "I don't know how to install '#{name}' on #{os_name}"
|
47
|
+
end
|
48
|
+
|
49
|
+
data = dep_def[os_name]
|
50
|
+
if data.kind_of?(Hash)
|
51
|
+
data = data[os_version]
|
52
|
+
if !data
|
53
|
+
raise ConfigError, "I don't know how to install '#{name}' on this specific version of #{os_name} (#{os_version})"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
if data.respond_to?(:to_ary)
|
58
|
+
os_packages.concat data.to_ary
|
59
|
+
elsif data.to_str =~ /\w+/
|
60
|
+
os_packages << data.to_str
|
61
|
+
else
|
62
|
+
shell_snippets << "\n" << data << "\n"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
"#! /bin/bash\n" +
|
67
|
+
GAIN_ROOT_ACCESS + "\n" +
|
68
|
+
(OS_PACKAGE_INSTALL[os_name] % [os_packages.join(" ")]) +
|
69
|
+
"\n" + shell_snippets
|
70
|
+
end
|
71
|
+
|
72
|
+
def partition_packages(package_set)
|
73
|
+
package_set = package_set.to_set
|
74
|
+
osdeps, gems = [], []
|
75
|
+
package_set.to_set.each do |name|
|
76
|
+
pkg_def = definitions[name]
|
77
|
+
if !pkg_def
|
78
|
+
raise ConfigError, "I know nothing about a prepackaged '#{name}' software"
|
79
|
+
end
|
80
|
+
|
81
|
+
if pkg_def.respond_to?(:to_str)
|
82
|
+
case(pkg_def.to_str)
|
83
|
+
when "gem" then
|
84
|
+
gems << name
|
85
|
+
else
|
86
|
+
raise ConfigError, "unknown OS-independent package management type #{pkg_def}"
|
87
|
+
end
|
88
|
+
else
|
89
|
+
osdeps << name
|
90
|
+
end
|
91
|
+
end
|
92
|
+
return osdeps, gems
|
93
|
+
end
|
94
|
+
|
95
|
+
def install(packages)
|
96
|
+
osdeps, gems = partition_packages(packages)
|
97
|
+
|
98
|
+
# Ideally, we would feed the OS dependencies to rosdep.
|
99
|
+
# Unfortunately, this is C++ code and I don't want to install the
|
100
|
+
# whole ROS stack just for rosdep ...
|
101
|
+
#
|
102
|
+
# So, for now, reimplement rosdep by ourselves. Given how things
|
103
|
+
# are done, this is actually not so hard.
|
104
|
+
shell_script = generate_os_script(osdeps)
|
105
|
+
if Autoproj.verbose
|
106
|
+
STDERR.puts "Installing non-ruby OS dependencies with"
|
107
|
+
STDERR.puts shell_script
|
108
|
+
end
|
109
|
+
|
110
|
+
File.open('osdeps.sh', 'w') do |file|
|
111
|
+
file.write shell_script
|
112
|
+
end
|
113
|
+
Autobuild::Subprocess.run 'autoproj', 'osdeps', 'bash', './osdeps.sh'
|
114
|
+
FileUtils.rm_f 'osdeps.sh'
|
115
|
+
|
116
|
+
# Don't install gems that are already there ...
|
117
|
+
gems.delete_if do |name|
|
118
|
+
version_requirements = Gem::Requirement.default
|
119
|
+
available = Gem.source_index.find_name(name, version_requirements)
|
120
|
+
!available.empty?
|
121
|
+
end
|
122
|
+
|
123
|
+
# Now install what is left
|
124
|
+
if !gems.empty?
|
125
|
+
if Autoproj.verbose
|
126
|
+
STDERR.puts "Installing rubygems dependencies with"
|
127
|
+
STDERR.puts "gem install #{gems.join(" ")}"
|
128
|
+
end
|
129
|
+
Autobuild::Subprocess.run 'autoproj', 'osdeps', 'gem', 'install', *gems
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Autoproj
|
2
|
+
BASE_DIR = File.expand_path(File.join('..', '..'), File.dirname(__FILE__))
|
3
|
+
|
4
|
+
class UserError < RuntimeError; end
|
5
|
+
|
6
|
+
def self.root_dir
|
7
|
+
dir = Dir.pwd
|
8
|
+
while dir != "/" && !File.directory?(File.join(dir, "autoproj"))
|
9
|
+
dir = File.dirname(dir)
|
10
|
+
end
|
11
|
+
if dir == "/"
|
12
|
+
raise UserError, "not in a Autoproj installation"
|
13
|
+
end
|
14
|
+
dir
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.config_dir
|
18
|
+
File.join(root_dir, "autoproj")
|
19
|
+
end
|
20
|
+
def self.build_dir
|
21
|
+
File.join(root_dir, "build")
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.config_file(file)
|
25
|
+
File.join(config_dir, file)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.run_as_user(*args)
|
29
|
+
if !system(*args)
|
30
|
+
raise "failed to run #{args.join(" ")}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.run_as_root(*args)
|
35
|
+
if !system('sudo', *args)
|
36
|
+
raise "failed to run #{args.join(" ")} as root"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.set_initial_env
|
41
|
+
gem_home = File.join(Autoproj.config_dir, "gems")
|
42
|
+
Autoproj.env_set 'RUBYOPT', "-rubygems"
|
43
|
+
Autoproj.env_set 'GEM_HOME', gem_home
|
44
|
+
Autoproj.env_set_path 'PATH', "#{gem_home}/bin", "/usr/local/bin", "/usr/bin", "/bin"
|
45
|
+
Autoproj.env_set 'PKG_CONFIG_PATH'
|
46
|
+
Autoproj.env_set 'RUBYLIB'
|
47
|
+
Autoproj.env_inherit 'PATH', 'PKG_CONFIG_PATH', 'RUBYLIB'
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.export_env_sh(subdir)
|
51
|
+
File.open(File.join(Autoproj.root_dir, subdir, "env.sh"), "w") do |io|
|
52
|
+
Autobuild.environment.each do |name, value|
|
53
|
+
shell_line = "export #{name}=#{value.join(":")}"
|
54
|
+
if Autoproj.env_inherit?(name)
|
55
|
+
if value.empty?
|
56
|
+
next
|
57
|
+
else
|
58
|
+
shell_line << ":$#{name}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
io.puts shell_line
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
data/samples/manifest
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
sources:
|
2
|
+
# Example source from a git repository
|
3
|
+
# - type: git
|
4
|
+
# url: git://github.com/doudou/autoproj.orocos.git
|
5
|
+
#
|
6
|
+
# If you want to enable only a subset of the listed sources,
|
7
|
+
# list their names in the following section. Note that the
|
8
|
+
# name is given in the source's source.yml file
|
9
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<package>
|
2
|
+
<description brief="one line of text">
|
3
|
+
long description goes here,
|
4
|
+
<em>XHTML is allowed</em>
|
5
|
+
</description>
|
6
|
+
<author>Alice/alice@somewhere.bar, Bob/bob@nowhere.foo</author>
|
7
|
+
<license>BSD</license>
|
8
|
+
<url>http://pr.willowgarage.com/</url>
|
9
|
+
<logo>http://pr.willowgarage.com/blog/photos/sensor_head1_500.jpg</logo>
|
10
|
+
|
11
|
+
<depend package="pkgname"/>
|
12
|
+
<depend package="common"/>
|
13
|
+
<rosdep name="python" />
|
14
|
+
<versioncontrol type="svn" url="https://playerstage.svn.sourceforge.net/svnroot/playerstage/code/player/trunk"/>
|
15
|
+
<export>
|
16
|
+
<cpp cflags="-I${prefix}/include" lflags="-L${prefix}/lib -lros"/>
|
17
|
+
<cpp os="osx" cflags="-I${prefix}/include" lflags="-L${prefix}/lib -Wl,-rpath,-L${prefix}lib -lrosthread -framework CoreServices"/>
|
18
|
+
</export>
|
19
|
+
|
20
|
+
</package>
|
data/samples/osdeps.yml
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
wxpython:
|
2
|
+
ubuntu: python-wxgtk2.8
|
3
|
+
arch: wxpython
|
4
|
+
centos: wxPython-devel
|
5
|
+
debian: python-wxgtk2.8
|
6
|
+
log4cxx:
|
7
|
+
ubuntu:
|
8
|
+
9.04: liblog4cxx10-dev
|
9
|
+
8.10: |
|
10
|
+
if [ ! -f /opt/ros/lib/liblog4cxx.so.10 ] ; then
|
11
|
+
mkdir -p ~/ros/ros-deps
|
12
|
+
cd ~/ros/ros-deps
|
13
|
+
wget --tries=10 http://pr.willowgarage.com/downloads/apache-log4cxx-0.10.0-wg_patched.tar.gz
|
14
|
+
tar xzf apache-log4cxx-0.10.0-wg_patched.tar.gz
|
15
|
+
cd apache-log4cxx-0.10.0
|
16
|
+
./configure --prefix=/opt/ros
|
17
|
+
make
|
18
|
+
sudo make install
|
19
|
+
fi
|
20
|
+
8.04: |
|
21
|
+
if [ ! -f /opt/ros/lib/liblog4cxx.so.10 ] ; then
|
22
|
+
mkdir -p ~/ros/ros-deps
|
23
|
+
cd ~/ros/ros-deps
|
24
|
+
wget --tries=10 http://pr.willowgarage.com/downloads/apache-log4cxx-0.10.0-wg_patched.tar.gz
|
25
|
+
tar xzf apache-log4cxx-0.10.0-wg_patched.tar.gz
|
26
|
+
cd apache-log4cxx-0.10.0
|
27
|
+
./configure --prefix=/opt/ros
|
28
|
+
make
|
29
|
+
sudo make install
|
30
|
+
fi
|
31
|
+
debian:
|
32
|
+
squeeze/sid: liblog4cxx10-dev
|
33
|
+
lenny: |
|
34
|
+
if [ ! -f /opt/ros/lib/liblog4cxx.so.10 ] ; then
|
35
|
+
mkdir -p ~/ros/ros-deps
|
36
|
+
cd ~/ros/ros-deps
|
37
|
+
wget --tries=10 http://pr.willowgarage.com/downloads/apache-log4cxx-0.10.0-wg_patched.tar.gz
|
38
|
+
tar xzf apache-log4cxx-0.10.0-wg_patched.tar.gz
|
39
|
+
cd apache-log4cxx-0.10.0
|
40
|
+
./configure --prefix=/opt/ros
|
41
|
+
make
|
42
|
+
sudo make install
|
43
|
+
fi
|
44
|
+
fedora: log4cxx-devel
|
45
|
+
arch: |
|
46
|
+
if [ ! -f /usr/lib/liblog4cxx.so.10 ] ; then
|
47
|
+
mkdir -p ~/ros/ros-deps
|
48
|
+
cd ~/ros/ros-deps
|
49
|
+
wget --tries=10 http://aur.archlinux.org/packages/log4cxx/log4cxx.tar.gz
|
50
|
+
tar xzf log4cxx.tar.gz
|
51
|
+
cd log4cxx
|
52
|
+
makepkg
|
53
|
+
sudo pacman -U log4cxx-*.pkg.tar.gz
|
54
|
+
fi
|
55
|
+
macports: |
|
56
|
+
if [ ! -f /opt/ros/lib/liblog4cxx.so.10 ] ; then
|
57
|
+
mkdir -p ~/ros/ros-deps
|
58
|
+
cd ~/ros/ros-deps
|
59
|
+
wget --tries=10 http://pr.willowgarage.com/downloads/apache-log4cxx-0.10.0-wg_patched.tar.gz
|
60
|
+
tar xzf apache-log4cxx-0.10.0-wg_patched.tar.gz
|
61
|
+
cd apache-log4cxx-0.10.0
|
62
|
+
./configure --prefix=/opt/ros
|
63
|
+
make
|
64
|
+
sudo make install
|
65
|
+
fi
|
File without changes
|