autobuild 1.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Changes.txt CHANGED
@@ -1,3 +1,10 @@
1
+ == Version 1.0.1
2
+ * The "test suites are there for something" release
3
+ * Fixes bugs introduced in the last version
4
+ * Added a real example in samples/openrobots.rb
5
+ * Fixed documentation in various places
6
+ * Fail more gracefully on circular dependencies
7
+
1
8
  == Version 1.0
2
9
 
3
10
  * Releasing 1.0. Autobuild is stable, and is in daily use at my work
data/Manifest.txt CHANGED
@@ -22,7 +22,7 @@ lib/autobuild/pkgconfig.rb
22
22
  lib/autobuild/reporting.rb
23
23
  lib/autobuild/subcommand.rb
24
24
  lib/autobuild/timestamps.rb
25
- samples/demo.rb
25
+ samples/openrobots.autobuild
26
26
  test/data/cvsroot.tar
27
27
  test/data/svnroot.tar
28
28
  test/data/tarimport.tar.gz
data/bin/autobuild CHANGED
@@ -45,6 +45,10 @@ begin
45
45
 
46
46
  Reporting.success
47
47
  end
48
+ rescue ThreadError
49
+ STDERR.puts "Rake failed with a ThreadError"
50
+ STDERR.puts "You may have a circular dependency in your packages"
48
51
  rescue Interrupt
52
+ STDERR.puts "interrupted"
49
53
  end
50
54
 
data/lib/autobuild.rb CHANGED
@@ -3,6 +3,6 @@ require 'autobuild/reporting'
3
3
  require 'autobuild/package'
4
4
 
5
5
  module Autobuild
6
- VERSION = "1.0" unless defined? Autobuild::VERSION
6
+ VERSION = "1.0.1" unless defined? Autobuild::VERSION
7
7
  end
8
8
 
@@ -1,3 +1,4 @@
1
+ require 'autobuild/importer'
1
2
  require 'open-uri'
2
3
 
3
4
  module Autobuild
@@ -77,13 +78,13 @@ module Autobuild
77
78
  # Sets the source URL and update +cachefile+ and +mode+ attributes accordingly.
78
79
  def url=(url)
79
80
  @url = URI.parse(url)
80
- raise ConfigException, "invalid URL #{url}" unless VALID_URI_SCHEMES.include?(url.scheme)
81
+ raise ConfigException, "invalid URL #{@url}" unless VALID_URI_SCHEMES.include?(@url.scheme)
81
82
 
82
83
  @mode = TarImporter.url_to_mode(url)
83
- if url.scheme == 'file'
84
- @cachefile = url
84
+ if @url.scheme == 'file'
85
+ @cachefile = @url.path
85
86
  else
86
- @cachefile = File.join(cachedir, File.basename(url.path))
87
+ @cachefile = File.join(cachedir, File.basename(@url.path))
87
88
  end
88
89
  end
89
90
 
@@ -95,10 +96,14 @@ module Autobuild
95
96
  attr_reader :mode
96
97
  # The directory in which remote files are cached
97
98
  def cachedir; @options[:cachedir] end
99
+ # The directory contained in the tar file
100
+ def tardir; @options[:tardir] end
98
101
 
99
102
  # Creates a new importer which downloads +url+ in +cachedir+ and unpacks it. The following options
100
103
  # are allowed:
101
104
  # [:cachedir] the cache directory. Defaults to "#{Autobuild.prefix}/cache"
105
+ # [:tardir] the directory contained in the tar file. If set, the importer will rename that directory
106
+ # to make it match Package#srcdir
102
107
  def initialize(url, options)
103
108
  @options = options.dup
104
109
  @options[:cachedir] ||= "#{Autobuild.prefix}/cache"
@@ -117,8 +122,11 @@ module Autobuild
117
122
  base_dir = File.dirname(package.srcdir)
118
123
  FileUtils.mkdir_p base_dir
119
124
  cmd = [ 'tar', "x#{TAR_OPTION[mode]}f", cachefile, '-C', base_dir ]
120
-
125
+
121
126
  Subprocess.run(package.name, :import, *cmd)
127
+ if tardir
128
+ File.mv File.join(base_dir, tardir), package.srcdir
129
+ end
122
130
 
123
131
  rescue OpenURI::HTTPError
124
132
  raise Autobuild::Exception.new(package.name, :import)
@@ -130,7 +138,7 @@ module Autobuild
130
138
 
131
139
  # Creates an importer which downloads a tarball from +source+ and unpacks
132
140
  # it. The allowed values in +options+ are described in TarImporter.new.
133
- def self.tar(source, options)
141
+ def self.tar(source, options = {})
134
142
  TarImporter.new(source, options)
135
143
  end
136
144
  end
@@ -4,148 +4,146 @@ require 'autobuild/subcommand'
4
4
 
5
5
  module Autobuild
6
6
  TARGETS = %w{import prepare build}
7
- end
8
-
9
- # Basic block for the autobuilder
10
- #
11
- # The build is done in three phases:
12
- # - import
13
- # - prepare
14
- # - build & install
15
- class Autobuild::Package
16
- @@packages = {}
17
- @@provides = {}
18
-
19
- # the package name
20
- attr_reader :name
21
- # set the source directory. If a relative path is given,
22
- # it is relative to Autobuild.srcdir. Defaults to #name
23
- attr_writer :srcdir
24
- # set the installation directory. If a relative path is given,
25
- # it is relative to Autobuild.prefix. Defaults to ''
26
- attr_writer :prefix
27
7
 
28
- # Sets importer object for this package. Defined for backwards compatibility.
29
- # Use the #importer attribute instead
30
- def import=(value)
31
- @importer = value
32
- end
33
- # Sets an importer object for this package
34
- attr_accessor :importer
8
+ # Basic block for the autobuilder
9
+ #
10
+ # The build is done in three phases:
11
+ # - import
12
+ # - prepare
13
+ # - build & install
14
+ class Package
15
+ @@packages = {}
16
+ @@provides = {}
17
+
18
+ # the package name
19
+ attr_reader :name
20
+ # set the source directory. If a relative path is given,
21
+ # it is relative to Autobuild.srcdir. Defaults to #name
22
+ attr_writer :srcdir
23
+ # set the installation directory. If a relative path is given,
24
+ # it is relative to Autobuild.prefix. Defaults to ''
25
+ attr_writer :prefix
26
+
27
+ # Sets importer object for this package. Defined for backwards compatibility.
28
+ # Use the #importer attribute instead
29
+ def import=(value)
30
+ @importer = value
31
+ end
32
+ # Sets an importer object for this package
33
+ attr_accessor :importer
34
+
35
+ # The list of packages this one depends upon
36
+ attr_reader :dependencies
37
+
38
+ # Absolute path to the source directory. See #srcdir=
39
+ def srcdir; File.expand_path(@srcdir || name, Autobuild.srcdir) end
40
+ # Absolute path to the installation directory. See #prefix=
41
+ def prefix; File.expand_path(@prefix || '', Autobuild.prefix) end
42
+
43
+ # The file which marks when the last sucessful install
44
+ # has finished. The path is absolute
45
+ #
46
+ # A package is sucessfully built when it is installed
47
+ def installstamp; "#{Autobuild.logdir}/#{name}-#{STAMPFILE}" end
48
+
49
+ def initialize(spec)
50
+ @dependencies = Array.new
51
+ @provides = Array.new
52
+
53
+ if Hash === spec
54
+ name, depends = spec.to_a.first
55
+ else
56
+ name, depends = spec, nil
57
+ end
35
58
 
36
- # The list of packages this one depends upon
37
- attr_reader :dependencies
59
+ name = name.to_s
60
+ @name = name
61
+ raise ConfigException, "package #{name} is already defined" if Autobuild::Package[name]
62
+ @@packages[name] = self
63
+
64
+ # Call the config block (if any)
65
+ yield(self) if block_given?
66
+
67
+ # Declare the installation stampfile
68
+ file installstamp do
69
+ Dir.chdir(srcdir) do
70
+ Autobuild.apply_post_install(@post_install)
71
+ end
72
+ end
73
+ task "#{name}-build" => installstamp
74
+ task :build => "#{name}-build"
38
75
 
39
- # Absolute path to the source directory. See #srcdir=
40
- def srcdir; File.expand_path(@srcdir || name, Autobuild.srcdir) end
41
- # Absolute path to the installation directory. See #prefix=
42
- def prefix; File.expand_path(@prefix || '', Autobuild.prefix) end
76
+ # Add dependencies declared in spec
77
+ depends_on *depends if depends
43
78
 
44
- # The file which marks when the last sucessful install
45
- # has finished. The path is absolute
46
- #
47
- # A package is sucessfully built when it is installed
48
- def installstamp; "#{Autobuild.logdir}/#{name}-#{STAMPFILE}" end
49
-
50
- def initialize(spec)
51
- @dependencies = Array.new
52
- @provides = Array.new
53
-
54
- if Hash === spec
55
- name, depends = spec.to_a.first
56
- else
57
- name, depends = spec, nil
58
- end
59
-
60
- name = name.to_s
61
- @name = name
62
- raise ConfigException, "package #{name} is already defined" if Package[name]
63
- @@packages[name] = self
64
-
65
- # Call the config block (if any)
66
- yield(self) if block_given?
67
-
68
- # Declare the installation stampfile
69
- file installstamp do
70
- Dir.chdir(srcdir) do
71
- Autobuild.apply_post_install(@post_install)
79
+ # Define the import task
80
+ task "#{name}-import" do import end
81
+ task :import => "#{name}-import"
82
+
83
+ # Define the prepare task
84
+ task "#{name}-prepare" do prepare end
85
+ task :prepare => "#{name}-prepare"
86
+
87
+ task(name) do
88
+ Rake::Task["#{name}-import"].invoke
89
+ Rake::Task["#{name}-prepare"].invoke
90
+ Rake::Task["#{name}-build"].invoke
72
91
  end
92
+ task :default => name
73
93
  end
74
- task "#{name}-build" => installstamp
75
- task :build => "#{name}-build"
76
-
77
- # Add dependencies declared in spec
78
- depends_on *depends if depends
79
-
80
- # Define the import task
81
- task "#{name}-import" do import end
82
- task :import => "#{name}-import"
83
-
84
- # Define the prepare task
85
- task "#{name}-prepare" do prepare end
86
- task :prepare => "#{name}-prepare"
87
-
88
- task(name) do
89
- Rake::Task["#{name}-import"].invoke
90
- Rake::Task["#{name}-prepare"].invoke
91
- Rake::Task["#{name}-build"].invoke
92
- end
93
- task :default => name
94
- end
95
94
 
96
- def import; @importer.import(self) if @importer end
97
- def prepare; end
95
+ def import; @importer.import(self) if @importer end
96
+ def prepare; end
98
97
 
99
- def post_install(*args, &block)
100
- if args.empty?
101
- @post_install = block
102
- elsif !block
103
- @post_install = args
104
- else
105
- raise ArgumentError, "cannot set both arguments and block"
98
+ def post_install(*args, &block)
99
+ if args.empty?
100
+ @post_install = block
101
+ elsif !block
102
+ @post_install = args
103
+ else
104
+ raise ArgumentError, "cannot set both arguments and block"
105
+ end
106
106
  end
107
- end
108
107
 
109
- # This package depends on +packages+
110
- def depends_on(*packages)
111
- packages.each do |p|
112
- p = p.to_s
113
- next if p == name
114
- unless Package[p]
115
- raise ConfigException.new(name), "package #{p} not defined"
116
- end
117
- file installstamp => Package[p].installstamp
118
- task "#{name}-import" => "#{p}-import"
119
- task "#{name}-prepare" => "#{p}-prepare"
120
- @dependencies << p
121
- end
122
- end
108
+ # This package depends on +packages+
109
+ def depends_on(*packages)
110
+ packages.each do |p|
111
+ p = p.to_s
112
+ next if p == name
113
+ unless Package[p]
114
+ raise ConfigException.new(name), "package #{p} not defined"
115
+ end
116
+ file installstamp => Package[p].installstamp
117
+ task "#{name}-import" => "#{p}-import"
118
+ task "#{name}-prepare" => "#{p}-prepare"
119
+ @dependencies << p
120
+ end
121
+ end
123
122
 
124
- # Declare that this package provides +packages+
125
- def provides(*packages)
126
- packages.each do |p|
127
- p = p.to_s
128
- @@provides[p] = self
129
- task p => name
130
- @provides << p
131
- end
132
- end
123
+ # Declare that this package provides +packages+
124
+ def provides(*packages)
125
+ packages.each do |p|
126
+ p = p.to_s
127
+ @@provides[p] = self
128
+ task p => name
129
+ @provides << p
130
+ end
131
+ end
133
132
 
134
- # Iterates on all available packages
135
- # if with_provides is true, includes the list
136
- # of package aliases
137
- def self.each(with_provides = false, &p)
138
- @@packages.each(&p)
139
- @@provides.each(&p) if with_provides
140
- end
133
+ # Iterates on all available packages
134
+ # if with_provides is true, includes the list
135
+ # of package aliases
136
+ def self.each(with_provides = false, &p)
137
+ @@packages.each(&p)
138
+ @@provides.each(&p) if with_provides
139
+ end
141
140
 
142
- # Gets a package from its name
143
- def self.[](name)
144
- @@packages[name.to_s] || @@provides[name.to_s]
141
+ # Gets a package from its name
142
+ def self.[](name)
143
+ @@packages[name.to_s] || @@provides[name.to_s]
144
+ end
145
145
  end
146
- end
147
146
 
148
- module Autobuild
149
147
  def self.package_set(spec)
150
148
  spec.each do |name, packages|
151
149
  Autobuild::TARGETS.each do |target|
@@ -14,18 +14,12 @@ module Autobuild
14
14
  # ==== Handles autotools-based packages
15
15
  #
16
16
  # == Used programs (see <tt>Autobuild.programs</tt>)
17
- # * aclocal
18
- # * autoheader
19
- # * autoconf
20
- # * automake
17
+ # Autotools will use the 'aclocal', 'autoheader', 'autoconf' and 'automake'
18
+ # programs defined on Autobuild.programs. autoheader is disabled by default,
19
+ # aclocal, autoconf and automake use are autodetected.
20
+ #
21
+ # To override this default behaviour on a per-package basis, use Autotools#use
21
22
  #
22
- # == Available options
23
- # * aclocal (default: true if autoconf is enabled, false otherwise) run aclocal
24
- # * autoconf (default: true)
25
- # * autoheader (default: false) run autoheader
26
- # * automake (default: autodetect) run automake. Will run automake if there is a
27
- # +Makefile.am+ in the source directory
28
- #
29
23
  class Autotools < Package
30
24
  attr_accessor :using
31
25
  attr_accessor :configureflags
@@ -61,6 +55,29 @@ module Autobuild
61
55
  Autobuild.update_environment(prefix)
62
56
  end
63
57
 
58
+ # Overrides the default behaviour w.r.t. autotools script generation
59
+ #
60
+ # Use it like that:
61
+ # * to force a generation step (skipping autodetection), do
62
+ # pkg.use <program> => true
63
+ # For instance, for aclocal
64
+ # pkg.use :aclocal => true
65
+ #
66
+ # * to force a generation step, overriding the program defined on Autobuild
67
+ # pkg.use <program> => true
68
+ # For instance, for autoconf
69
+ # pkg.use :autoconf => 'my_autoconf_program'
70
+ #
71
+ # * to disable a generation step, do
72
+ # pkg.use <program> => false
73
+ # For instance, for automake
74
+ # pkg.use :automake => false
75
+ #
76
+ # * to restore autodetection, do
77
+ # pkg.use <program> => nil
78
+ # For instance, for automake
79
+ # pkg.use :automake => nil
80
+ #
64
81
  def use(*programs)
65
82
  programs = *programs
66
83
  if !programs.kind_of?(Hash)
@@ -0,0 +1,78 @@
1
+ # This sample file installs a set of autotools packages from
2
+ # the OpenRobots suite of tools (http://softs.laas.fr/openrobots)
3
+ #
4
+ # The user (you) is asked about the installation directory (prefix). Then, the various packages
5
+ # are installed the following way:
6
+ # * sources are in prefix/src
7
+ # * installed packages are in prefix/bin, prefix/lib, prefix/include, ...
8
+ #
9
+ # This version uses the Tar importer to get the latest release
10
+ require 'autobuild'
11
+ require 'autobuild/packages/autotools'
12
+ require 'autobuild/import/tar'
13
+
14
+ Thread.abort_on_exception = true
15
+ STDOUT.sync = true
16
+
17
+ # Ask the user (you) where you want everything installed
18
+ default_prefix = "#{ENV['HOME']}/openrobots"
19
+ print "Where to intall openrobots ? [#{default_prefix}]"
20
+ answer = STDIN.readline
21
+ answer = default_prefix if answer == "\n"
22
+
23
+ # Set the root directory for sources import and package installation
24
+ Autobuild.srcdir = File.join(answer, "src")
25
+ Autobuild.prefix = answer
26
+
27
+ # Define a fake 'openrobots' package type which describes the common package
28
+ # configuration for packages from openrobots
29
+ #
30
+ # spec is either a name (the package name) or a name => dependencies hash
31
+ OPENROBOTS_DOWNLOAD_BASEURL = "http://softs.laas.fr/openrobots/php/download.php/"
32
+ def openrobots(version, spec)
33
+ Autobuild.autotools(spec) do |pkg|
34
+ # Install the sources in #{Autobuild.srcdir}/package_name
35
+ pkg.srcdir = pkg.name
36
+
37
+ # Build packages into #{package source dir}/build
38
+ pkg.builddir = "build"
39
+
40
+ # The importer object will download the file and decompress it into the
41
+ # specified source directory
42
+ #
43
+ # The tarballs contain a name-version directory. The :tardir option
44
+ # makes the tar importer rename that directory into 'name'
45
+ pkg.importer = Autobuild.tar(OPENROBOTS_DOWNLOAD_BASEURL + "#{pkg.name}-#{version}.tar.gz",
46
+ :tardir => "#{pkg.name}-#{version}")
47
+
48
+ # Do not autogenerate configure scripts, use the ones in the tarball instead
49
+ pkg.use :aclocal => false
50
+ pkg.use :autoconf => false
51
+ pkg.use :automake => false
52
+
53
+ # All openrobots package depend on mkdep
54
+ if pkg.name != "mkdep"
55
+ pkg.depends_on 'mkdep'
56
+ end
57
+ end
58
+ end
59
+
60
+ # You can override the version of aclocal/autoconf/automake used if needed
61
+ # Autotools.aclocal = "aclocal-1.9"
62
+ # Autotools.automake = "automake-1.9"
63
+
64
+ # Declare the packages themselves
65
+ openrobots "2.6", :mkdep
66
+ openrobots "2.2", :pocolibs
67
+
68
+ # Genom depends on pocolibs, declare that
69
+ openrobots "1.99.902", :genom => :pocolibs
70
+
71
+ # GDHE needs a X display to install. Check that the DISPLAY environment
72
+ # variable is set
73
+ if ENV['DISPLAY']
74
+ openrobots "3.7", :gdhe
75
+ else
76
+ STDERR.puts "GDHE installation requires a X display. Disabled"
77
+ end
78
+
metadata CHANGED
@@ -3,7 +3,7 @@ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: autobuild
5
5
  version: !ruby/object:Gem::Version
6
- version: "1.0"
6
+ version: 1.0.1
7
7
  date: 2007-06-22 00:00:00 +02:00
8
8
  summary: Rake-based utility to build and install multiple packages with dependencies
9
9
  require_paths:
@@ -53,7 +53,7 @@ files:
53
53
  - lib/autobuild/reporting.rb
54
54
  - lib/autobuild/subcommand.rb
55
55
  - lib/autobuild/timestamps.rb
56
- - samples/demo.rb
56
+ - samples/openrobots.autobuild
57
57
  - test/data/cvsroot.tar
58
58
  - test/data/svnroot.tar
59
59
  - test/data/tarimport.tar.gz
data/samples/demo.rb DELETED
@@ -1,25 +0,0 @@
1
- require 'autobuild'
2
-
3
- # Remove the need for the Autobuild. prefix in
4
- # front of everything
5
- include Autobuild
6
-
7
- # Define a common configuration routine
8
- openrobots_config = lambda { |pkg|
9
- pkg.import = cvs(openrobots, pkg.name)
10
- pkg.depends_on :mkdep
11
- }
12
-
13
- Autotools.aclocal = "aclocal-1.9"
14
- Autotools.automake = "automake-1.9"
15
-
16
- autotools(:mkdep, &openrobots_config)
17
- autotools(:gdhe, &openrobots_config)
18
- autotools(:pocolibs, &openrobots_config)
19
- autotools :genom do |pkg|
20
- openrobots_config[pkg]
21
- pkg.autoheader = true # Force usage of autoheader
22
- pkg.automake = 'automake' # use the default automake instead
23
- # of Autotools.automake
24
- end
25
-