autoproj 1.2.6 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -54,7 +54,7 @@ cmake_package "package_name" do |pkg|
54
54
  end
55
55
  {coderay}
56
56
 
57
- The doc\_dir assignment above is needed if the package installs its documentation
57
+ The <tt>doc_dir</tt> assignment above is needed if the package installs its documentation
58
58
  elsewhere than "doc".
59
59
 
60
60
  Defining dependencies
@@ -65,7 +65,7 @@ Removing packages from the build
65
65
  --------------------------------
66
66
  Instead of having to list all packages that you do want to build, it is possible
67
67
  to list the packages that you don't want to build. Simply list them in the
68
- <tt>exclude\_packages</tt> section of the manifest file. In the following example, all
68
+ <tt>exclude_packages</tt> section of the manifest file. In the following example, all
69
69
  of the rubim.orocos package set will be built *but* the pocosim-log package.
70
70
 
71
71
  {coderay:: yaml}
@@ -81,7 +81,7 @@ Using packages that are already installed
81
81
 
82
82
  If some packages are already installed elsewhere, and you want to use that
83
83
  version instead of the one listed in the package sets, list them in the
84
- <tt>ignore\_packages</tt> section of the manifest. In the following example, the
84
+ <tt>ignore_packages</tt> section of the manifest. In the following example, the
85
85
  <tt>orocos/rtt</tt> package will *not* be built by autoproj.
86
86
 
87
87
  {coderay:: yaml}
@@ -95,9 +95,9 @@ ignore_packages:
95
95
  - orocos/rtt
96
96
  {coderay}
97
97
 
98
- This differs from the <tt>exclude\_packages</tt> mechanism: packages listed in
99
- <tt>ignore\_packages</tt> are assumed to be present even though autoproj does not manage
100
- them, while packages in <tt>exclude\_packages</tt> are assumed to be absent and therefore
98
+ This differs from the <tt>exclude_packages</tt> mechanism: packages listed in
99
+ <tt>ignore_packages</tt> are assumed to be present even though autoproj does not manage
100
+ them, while packages in <tt>exclude_packages</tt> are assumed to be absent and therefore
101
101
  issue an error if another package in the installation depend on them.
102
102
 
103
103
  Local overrides of version control information
@@ -0,0 +1,16 @@
1
+ ---
2
+ title: Understanding autoproj error messages
3
+ sort_info: 800
4
+ ---
5
+
6
+ I know nothing about a prepackaged package called 'XXXX', ...
7
+ ------------------------------------------
8
+ _Short explanation_: an OS dependency is listed by one of the packages, but no
9
+ definition exists in one of the osdeps files.
10
+
11
+ _Long explanation_: XXXX is listed as an operating system dependency by one of
12
+ the packages that you requested to build. Two solutions: (i) the package should
13
+ *not* depend on it, and you should modify the package's manifest.xml file. (ii)
14
+ the package should depend on it and you should list the OS package in [the
15
+ relevant osdeps file](osdeps.html)
16
+
@@ -32,14 +32,16 @@ Components of an Autoproj installation
32
32
  -------------------------------------
33
33
  A autoproj installation is seeded by _package sets_. A package set is a local or remote
34
34
  directory in which there is:
35
- * autobuild scripts that describe what can be built and how it should be built.
36
- These scripts an also list a set of configuration options that allow to
37
- parametrize the build. In general, there should be only a limited number of
38
- such options.
39
- * a source.yml file which describes the package set itself, and where the software
40
- packages are located (what version control system and what URL).
41
- * optionally, a file that describe prepackaged dependencies that can be
42
- installed by using the operating system package management system.
35
+
36
+ * a list of available packages, and information on how to build these packages.
37
+ This list, and the build information, are Ruby scripts that use the autobuild
38
+ API. [More ...](autobuild.html)
39
+ * version control information: where to get the source code for each of the
40
+ packages defined in the set.
41
+
42
+ Then, an autoproj configuration is simply a list of package sets (i.e. a list of
43
+ packages that are available to build), and a file that selects which packages
44
+ should be built. This file is the <tt>manifest</tt>.
43
45
 
44
46
  Bootstrapping
45
47
  -------------
@@ -59,7 +61,28 @@ The canonical way is the following:
59
61
  ruby autoproj\_bootstrap
60
62
  {.cmdline}
61
63
 
62
- * follow the instructions printed by the script above :)
64
+ * follow the instructions printed by the script<tt>manifest</tt>.
65
+
66
+ Additionally, if you are given a reference to a source code repository in which
67
+ an autoproj configuration is stored (i.e. a directory in which a manifest is
68
+ present), you can bootstrap this configuration directly:
69
+
70
+ wget http://doudou.github.com/autoproj/autoproj\_bootstrap <br />
71
+ ruby autoproj\_bootstrap VCS
72
+ {.cmdline}
73
+
74
+ For instance, to build all packages made available by the RubyInMotion project,
75
+ do
76
+
77
+ wget http://doudou.github.com/autoproj/autoproj\_bootstrap <br />
78
+ ruby autoproj\_bootstrap git git://github.com/doudou/rubim.all.git
79
+ {.cmdline}
80
+
81
+ Additional options can be given for the version control system. For instance,
82
+
83
+ wget http://doudou.github.com/autoproj/autoproj\_bootstrap <br />
84
+ ruby autoproj\_bootstrap git git://github.com/doudou/rubim.all.git branch=stable
85
+ {.cmdline}
63
86
 
64
87
  Software packages in Autoproj
65
88
  -----------------------------
@@ -15,7 +15,7 @@ Starting a new package set
15
15
  Create a subdirectory in autoproj/ and add a source.yml file that looks like:
16
16
 
17
17
  {coderay:: yaml}
18
- name my_package_set_name
18
+ name: my_package_set_name
19
19
  {coderay}
20
20
 
21
21
  Et voila ! You have a new empty package set
@@ -40,7 +40,13 @@ orogen_package "my/package" # for orogen packages
40
40
  The package name will be used to refer to this particular package later on --
41
41
  especially for version control definition. If subdirectories are used, like "my"
42
42
  in the above example, the package source will be checked out and built in the
43
- corresponding subdirectory.
43
+ corresponding subdirectory. For instance, with
44
+
45
+ {coderay:: ruby}
46
+ cmake_package "drivers/hokuyo"
47
+ {coderay}
48
+
49
+ the hokuyo driver will _always_ be built in a <tt>drivers/</tt> subdirectory.
44
50
 
45
51
  Now that the package is declared, we need to add version control information to
46
52
  the source.yml file. This needs to be done in the version\_control section of
@@ -62,6 +68,14 @@ version_control:
62
68
  url: svn+ssh://svnhosting.com/blabla/trunk/my/package
63
69
  {coderay}
64
70
 
71
+ For testing purposes, it is possible to tell autoproj to *not* take into account
72
+ any VCS information:
73
+
74
+ {coderay:: yaml}
75
+ version_control:
76
+ - my/package: none
77
+ {coderay}
78
+
65
79
  The remaining of this page is a more in-depth description of this process.
66
80
 
67
81
  Autobuild scripts
@@ -107,9 +121,14 @@ The name field gives a name for the set. It is arbitrary, but the guideline
107
121
  is to give a name that is java-like for namespaces, i.e. origin.name.
108
122
 
109
123
  The <tt>constants:</tt> section lists values that can be reused for different
110
- packages. Autoproj defines the HOME constant which is the user's home directory,
111
- and the PACKAGE constant that is the actual package name. We will see later that
112
- these values can also be configuration variables that are asked to the user.
124
+ packages. Autoproj defines two constants:
125
+
126
+ * HOME is the user's home directory,
127
+ * PACKAGE is the actual package name, useful when using wildcards in package
128
+ names (see below)
129
+
130
+ It is also possible to use configuration variables, that get asked to the user
131
+ during the build (see below).
113
132
 
114
133
  Finally, the <tt>version_control:</tt> section describes how to import each
115
134
  software package. Its general format is:
@@ -119,11 +138,10 @@ package_name:
119
138
  url: repository_url
120
139
  {coderay}
121
140
 
122
- Where package\_name is a regular expression that matches the package name, i.e.
123
- use ".\*" to match all packages for instance. The package name is the one given
124
- to the <tt>blabla_package</tt> stanza in the autobuild file. In the above
125
- autobuild example, the package names are for instance "orocos/rtt" and
126
- "drivers/imu".
141
+ Where package\_name is a regular expression that matches the package name (for
142
+ instance, ".\*" will match all packages and "drivers/.\*" will match packages
143
+ whose name starts with 'drivers'). The package name is the one given to the
144
+ <tt>blabla_package</tt> stanza in the autobuild file.
127
145
 
128
146
  For the git importer, one of 'branch' or 'tag' options can be provided as well:
129
147
  {coderay:: yaml}
@@ -132,18 +150,18 @@ package_name:
132
150
  tag: tag_to_stick_to # it is branch OR tag
133
151
  {coderay}
134
152
 
135
- The options are applied in order, meaning that the toplevel options override the
136
- lower level ones. In general, one will have a ".\*" entry to give options for all
137
- packages, and then override for specific packages:
153
+ The options are applied in order, meaning that the top entries will be overriden
154
+ by the lower ones. In general, one will have a ".\*" entry to give options for
155
+ all packages, and then override for specific packages:
138
156
 
139
157
  {coderay:: yaml}
140
158
  version_control:
141
- - "modules/logger": # we don't follow master on this module
142
- branch: imoby
143
-
144
159
  - .*: # common options for all packages
145
160
  type: git
146
161
  url: $ROOT_DIR/$PACKAGE.git
162
+
163
+ - "modules/logger": # we don't follow master on this module
164
+ branch: imoby
147
165
  {coderay}
148
166
 
149
167
  Interaction between package sets definition files
@@ -179,13 +197,16 @@ where the option\_type field can either be "string" or "boolean".
179
197
 
180
198
  Then, you can use the option\_name as an expansion in the source.yml file.
181
199
 
182
- For instance, with an init.rb looking like:
200
+ For instance, at my lab we are using an share filesystem to store the git
201
+ repositories. Our project's init.rb file has the following option definition:
183
202
  {coderay:: ruby}
184
203
  configuration_option "MOUNT_POINT", "string",
185
204
  :default => "$HOME/nfs",
186
205
  :doc => "mount point of the NFS server"
187
206
  {coderay}
188
207
 
208
+ And the source.yml uses it with:
209
+
189
210
  {coderay:: yaml}
190
211
  version_control:
191
212
  ".*":
@@ -34,7 +34,7 @@ generated to set up your shell for the use of the installed software.
34
34
 
35
35
  Listing and adding package sets
36
36
  -------------------------------
37
- Package sets are listed in the <tt>package\_sets</tt> section of
37
+ Package sets are listed in the <tt>package_sets</tt> section of
38
38
  <tt>autoproj/manifest</tt> file. This section looks like this:
39
39
 
40
40
  {coderay:: yaml}
@@ -1,6 +1,12 @@
1
1
  require 'autobuild'
2
2
  require 'set'
3
3
 
4
+ class Autobuild::Package
5
+ def autoproj_name
6
+ srcdir.gsub /^#{Regexp.quote(Autoproj.root_dir)}\//, ''
7
+ end
8
+ end
9
+
4
10
  module Autoproj
5
11
  class Reporter < Autobuild::Reporter
6
12
  def error(error)
@@ -1,4 +1,6 @@
1
1
  # The following definitions are needed to bootstrap autoproj
2
+ none: ignore
3
+
2
4
  ruby:
3
5
  debian,ubuntu:
4
6
  - ruby1.8-dev
@@ -42,5 +44,9 @@ lsb_release:
42
44
  debian,ubuntu: lsb-release
43
45
  gentoo: sys-apps/lsb-release
44
46
 
47
+ archive:
48
+ debian,ubuntu: [tar, unzip]
49
+ gentoo: [app-arch/tar, app-arch/unzip]
50
+
45
51
  # vim: expandtab
46
52
 
@@ -95,7 +95,17 @@ module Autoproj
95
95
  Autobuild.send(type, url, options)
96
96
  end
97
97
 
98
- def to_s; "#{type}:#{url}" end
98
+ def to_s
99
+ if type == "none"
100
+ "none"
101
+ else
102
+ desc = "#{type}:#{url}"
103
+ if !options.empty?
104
+ desc = "#{desc} #{options.map { |key, value| "#{key}=#{value}" }.join(" ")}"
105
+ end
106
+ desc
107
+ end
108
+ end
99
109
  end
100
110
 
101
111
  def self.vcs_definition_to_hash(spec)
@@ -126,7 +136,7 @@ module Autoproj
126
136
  # This method normalizes the three forms into a VCSDefinition object
127
137
  def self.normalize_vcs_definition(spec)
128
138
  spec = vcs_definition_to_hash(spec)
129
- if !(spec[:type] && spec[:url])
139
+ if !(spec[:type] && (spec[:type] == 'none' || spec[:url]))
130
140
  raise ConfigError, "the source specification #{spec.inspect} misses either the VCS type or an URL"
131
141
  end
132
142
 
@@ -167,7 +177,9 @@ module Autoproj
167
177
  # True if this source defines nothing
168
178
  def empty?
169
179
  !source_definition['version_control'] &&
170
- !each_package.find { true }
180
+ !each_package.find { true } &&
181
+ !File.exists?(File.join(local_dir, "overrides.rb")) &&
182
+ !File.exists?(File.join(local_dir, "init.rb"))
171
183
  end
172
184
 
173
185
  # The directory in which data for this source will be checked out
@@ -342,16 +354,24 @@ module Autoproj
342
354
  spec = { $1 => spec }
343
355
  name = name.gsub(/ \w+$/, '')
344
356
  end
357
+
358
+ if spec.respond_to?(:to_str)
359
+ if spec == "none"
360
+ spec = { :type => "none" }
361
+ else
362
+ raise ConfigError, "invalid VCS specification '#{name}: #{spec}'"
363
+ end
364
+ end
345
365
  end
346
366
 
347
- if Regexp.new(name) =~ package_name
367
+ if Regexp.new("^" + name) =~ package_name
348
368
  vcs_spec = vcs_spec.merge(spec)
349
369
  end
350
370
  end
351
371
  end
352
372
 
353
373
  if !vcs_spec.empty?
354
- expansions = Hash["PACKAGE" => package_name]
374
+ expansions = Hash["PACKAGE" => package_name, "PACKAGE_BASENAME" => File.basename(package_name)]
355
375
 
356
376
  vcs_spec = expand(vcs_spec, expansions)
357
377
  vcs_spec = Autoproj.vcs_definition_to_hash(vcs_spec)
@@ -407,7 +427,28 @@ module Autoproj
407
427
  end
408
428
 
409
429
  class Manifest
410
- FakePackage = Struct.new :name, :srcdir
430
+ FakePackage = Struct.new :text_name, :name, :srcdir, :importer
431
+ class FakePackage
432
+ def autoproj_name; name end
433
+ def import
434
+ importer.import(self)
435
+ end
436
+
437
+ def progress(msg)
438
+ Autobuild.progress(msg % [text_name])
439
+ end
440
+
441
+ # Display a progress message, and later on update it with a progress
442
+ # value. %s in the string is replaced by the package name
443
+ def progress_with_value(msg)
444
+ Autobuild.progress_with_value(msg % [text_name])
445
+ end
446
+
447
+ def progress_value(value)
448
+ Autobuild.progress_value(value)
449
+ end
450
+ end
451
+
411
452
  def self.load(file)
412
453
  begin
413
454
  data = YAML.load(File.read(file))
@@ -478,7 +519,7 @@ module Autoproj
478
519
  #
479
520
  # And honestly I don't think someone will have 20 000 package sets
480
521
  done_something = false
481
- each_source do |source|
522
+ each_source(false) do |source|
482
523
  next if source_name && source.name != source_name
483
524
  done_something = true
484
525
 
@@ -561,8 +602,6 @@ module Autoproj
561
602
  return @sources.each(&block)
562
603
  end
563
604
 
564
- return if !data['package_sets']
565
-
566
605
  # Load the local source first ...
567
606
  local = LocalSource.new
568
607
  if load_description
@@ -572,22 +611,27 @@ module Autoproj
572
611
  end
573
612
  if load_description
574
613
  if !local.empty?
575
- yield(local)
576
- if load_description
577
- @sources = [local]
578
- end
614
+ @sources = [local]
615
+ else
616
+ @sources = []
579
617
  end
580
- @sources ||= []
581
618
  else
582
619
  yield(local)
583
620
  end
584
621
 
622
+ return if !data['package_sets']
623
+
585
624
  data['package_sets'].each do |spec|
586
625
  source = source_from_spec(spec, load_description)
587
626
  if load_description
588
627
  @sources << source
628
+ else
629
+ yield(source)
589
630
  end
590
- yield(source)
631
+ end
632
+
633
+ if load_description
634
+ @sources.each(&block)
591
635
  end
592
636
  end
593
637
 
@@ -611,36 +655,70 @@ module Autoproj
611
655
  packages.each_value { |package, _| yield(package) }
612
656
  end
613
657
 
614
- def self.update_remote_source(source)
615
- importer = source.vcs.create_autobuild_importer
616
- return if !importer # updates have been disabled
617
- fake_package = FakePackage.new(source.automatic_name, source.local_dir)
658
+ # The VCS object for the main configuration itself
659
+ attr_reader :vcs
660
+
661
+ def each_configuration_source
662
+ if !block_given?
663
+ return enum_for(:each_configuration_source)
664
+ end
618
665
 
619
- importer.import(fake_package)
620
- rescue Autobuild::ConfigException => e
621
- raise ConfigError, e.message, e.backtrace
666
+ if vcs
667
+ yield(vcs, "autoproj main configuration", "autoproj_config", Autoproj.config_dir)
668
+ end
669
+
670
+ each_remote_source(false) do |source|
671
+ yield(source.vcs, source.name || source.vcs.url, source.automatic_name, source.local_dir)
672
+ end
673
+ self
622
674
  end
623
675
 
624
- attr_reader :vcs
625
- def self.import_whole_installation(vcs, into)
676
+ def self.create_autobuild_package(vcs, text_name, pkg_name, into)
626
677
  importer = vcs.create_autobuild_importer
627
- return if !importer # updates have been disabled
628
- fake_package = FakePackage.new('autoproj main configuration', into)
629
- importer.import(fake_package)
678
+ return if !importer # updates have been disabled by using the 'none' type
679
+
680
+ fake_package = FakePackage.new(text_name, pkg_name, into)
681
+ fake_package.importer = importer
682
+ fake_package
683
+
684
+ rescue Autobuild::ConfigException => e
685
+ raise ConfigError, "cannot import #{name}: #{e.message}", e.backtrace
686
+ end
687
+
688
+ def self.update_source(vcs, text_name, pkg_name, into)
689
+ fake_package = create_autobuild_package(vcs, text_name, pkg_name, into)
690
+ fake_package.import
691
+
630
692
  rescue Autobuild::ConfigException => e
631
- raise ConfigError, "cannot import autoproj configuration: #{e.message}", e.backtrace
693
+ raise ConfigError, "cannot import #{name}: #{e.message}", e.backtrace
632
694
  end
633
695
 
634
696
  def update_yourself
635
- Manifest.import_whole_installation(vcs, Autoproj.config_dir)
697
+ Manifest.update_source(vcs, "autoproj main configuration", "autoproj_conf", Autoproj.config_dir)
636
698
  end
637
699
 
638
700
  def update_remote_sources
639
701
  # Iterate on the remote sources, without loading the source.yml
640
702
  # file (we're not ready for that yet)
641
703
  each_remote_source(false) do |source|
642
- Manifest.update_remote_source(source)
704
+ Manifest.update_source(source.vcs, source.name || source.vcs.url, source.automatic_name, source.local_dir)
705
+ end
706
+ end
707
+
708
+ def importer_definition_for(package_name, package_source = nil)
709
+ if !package_source
710
+ _, package_source, _ = packages.values.find { |pkg, pkg_source, _| pkg.name == package_name }
711
+ end
712
+
713
+ each_source.each do |source|
714
+ vcs = source.importer_definition_for(package_name)
715
+ if vcs
716
+ return vcs
717
+ elsif package_source.name == source.name
718
+ return
719
+ end
643
720
  end
721
+ nil
644
722
  end
645
723
 
646
724
  # Sets up the package importers based on the information listed in
@@ -661,14 +739,7 @@ module Autoproj
661
739
  # by S1
662
740
  def load_importers
663
741
  packages.each_value do |package, package_source, package_source_file|
664
- vcs = each_source.find do |source|
665
- vcs = source.importer_definition_for(package.name)
666
- if vcs
667
- break(vcs)
668
- elsif package_source.name == source.name
669
- break
670
- end
671
- end
742
+ vcs = importer_definition_for(package.name, package_source)
672
743
 
673
744
  if vcs
674
745
  Autoproj.add_build_system_dependency vcs.type
@@ -728,7 +799,7 @@ module Autoproj
728
799
 
729
800
  # Looks into the layout setup in the manifest, and yields each layout
730
801
  # and sublayout in order
731
- def each_package_set(selection, layout_name = '/', layout_def = data['layout'], &block)
802
+ def each_package_set(selection = nil, layout_name = '/', layout_def = data['layout'], &block)
732
803
  if !layout_def
733
804
  yield(layout_name, default_packages, default_packages)
734
805
  return nil
@@ -756,6 +827,36 @@ module Autoproj
756
827
  end
757
828
  end
758
829
 
830
+ def in_sublayout(name, packages)
831
+ srcdir = File.join(Autoproj.root_dir, name)
832
+ prefix = File.join(Autoproj.build_dir, name)
833
+ logdir = File.join(prefix, "log")
834
+ Autobuild.logdir = logdir
835
+ packages.each do |pkg_name|
836
+ pkg = Autobuild::Package[pkg_name]
837
+ pkg.srcdir = File.join(srcdir, pkg_name)
838
+ pkg.prefix = prefix
839
+ pkg.logdir = logdir
840
+ end
841
+
842
+ yield
843
+ end
844
+
845
+ def handle_enabled_packages(selected_packages)
846
+ handled_packages = Set.new
847
+ each_package_set(selected_packages) do |name, packages, enabled_packages|
848
+ packages -= handled_packages
849
+ enabled_packages -= handled_packages
850
+
851
+ in_sublayout(name, packages) do
852
+ if !packages.empty?
853
+ yield(name, packages, enabled_packages)
854
+ end
855
+ end
856
+ handled_packages |= packages
857
+ end
858
+ end
859
+
759
860
  def default_packages
760
861
  names = if layout = data['layout']
761
862
  layout_packages(layout, true)
@@ -821,16 +922,20 @@ module Autoproj
821
922
  end
822
923
 
823
924
  def install_os_dependencies(packages)
824
- osdeps = known_os_packages
825
925
 
826
926
  required_os_packages = Set.new
927
+ package_os_deps = Hash.new { |h, k| h[k] = Array.new }
827
928
  packages.each do |pkg_name|
828
929
  if manifest = package_manifests[pkg_name]
829
- required_os_packages |= manifest.each_os_dependency.to_set
930
+ pkg_osdeps = manifest.each_os_dependency.to_set
931
+ pkg_osdeps.each do |osdep_name|
932
+ package_os_deps[osdep_name] << pkg_name
933
+ end
934
+ required_os_packages |= pkg_osdeps
830
935
  end
831
936
  end
832
937
 
833
- osdeps.install(required_os_packages)
938
+ known_os_packages.install(required_os_packages, package_os_deps)
834
939
  end
835
940
 
836
941
  # Package selection can be done in three ways: