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.
@@ -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
+
@@ -0,0 +1,3 @@
1
+ module Autoproj
2
+ VERSION = "1.0.0"
3
+ end
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>
@@ -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
@@ -0,0 +1,8 @@
1
+ sources:
2
+ - ./local
3
+ - git:remote1.git
4
+ - type: git
5
+ url: remote2.git
6
+ branch: next
7
+
8
+