autoproj 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+