lib/autoproj/autobuild.rb in autoproj-2.0.0.rc37 vs lib/autoproj/autobuild.rb in autoproj-2.0.0.rc38
- old
+ new
@@ -1,748 +1,19 @@
-require 'find'
-require 'fileutils'
-require 'autobuild'
-require 'set'
+require 'autoproj/autobuild_extensions/package'
+require 'autoproj/autobuild_extensions/archive_importer'
+require 'autoproj/autobuild_extensions/git'
+require 'autoproj/autobuild_extensions/svn'
+require 'autoproj/autobuild_extensions/dsl'
-module Autoproj
- def self.ruby_executable
- Autoproj.workspace.config.ruby_executable
- end
-
- module CmdLine
- def self.ruby_executable
- Autoproj.workspace.config.ruby_executable
- end
- end
+Autobuild::Package.class_eval do
+ prepend Autoproj::AutobuildExtensions::Package
end
-
-def explicit_osdeps_selection(name, config = Autoproj.config)
- if !config.declared?("osdeps_#{name}")
- if config.has_value_for?("osdeps_#{name}")
- doc_string = "install #{name} from source ?"
- else
- # Declare the option
- doc_string =<<-EOT
-The #{name} package is listed as a dependency of #{self.name}. It is listed as an operating
-system package for other operating systems than yours, and is also listed as a source package.
-Since you requested manual updates, I have to ask you:
-
-Do you want me to build #{name} from source ? If you say 'no', you will have to install it yourself.
- EOT
- end
-
- config.declare(
- "osdeps_#{name}", "boolean",
- :default => "yes",
- :doc => doc_string)
- end
- !config.get("osdeps_#{name}")
+Autobuild::ArchiveImporter.class_eval do
+ prepend Autoproj::AutobuildExtensions::ArchiveImporter
end
-
-module Autobuild
- class Package
- attr_writer :ws
- def ws
- @ws ||= Autoproj.workspace
- end
-
- # The Autoproj::PackageManifest object that describes this package
- attr_accessor :description
- # The set of tags for this package. This is an union of the tags
- # contained in +description+ and the ones explicitely added with
- # #add_tag
- def tags
- result = (@added_tags || Set.new)
- if description
- result |= description.tags.to_set
- end
- result
- end
- # Tags explicitely added with #add_tag
- attr_reader :added_tags
- # Add a tag to the package. Use this if you don't want the tag to be
- # shared with everyone that uses the package (i.e. cannot go in
- # manifest.xml)
- def add_tag(tag)
- @added_tags ||= Set.new
- @added_tags << tag
- end
-
- # True if this package is tagged with the given tag string
- def has_tag?(tag)
- tags.include?(tag.to_s)
- end
-
- # Asks autoproj to remove references to the given obsolete oroGen
- # package
- def remove_obsolete_installed_orogen_package(name)
- post_install do
- path = File.join(prefix, 'lib', 'pkgconfig')
- Dir.glob(File.join(path, "#{name}-*.pc")) do |pcfile|
- Autoproj.message " removing obsolete file #{pcfile}", :bold
- FileUtils.rm_f pcfile
- end
- pcfile = File.join(path, "orogen-project-#{name}.pc")
- if File.exist?(pcfile)
- Autoproj.message " removing obsolete file #{pcfile}", :bold
- FileUtils.rm_f pcfile
- end
- end
- end
-
- # Asks autoproj to remove the given file in the package's installation
- # prefix
- def remove_obsolete_installed_file(*path)
- post_install do
- path = File.join(prefix, *path)
- if File.exist?(path)
- Autoproj.message " removing obsolete file #{path}", :bold
- FileUtils.rm_f path
- end
- end
- end
-
- # Ask autoproj to run the given block after this package has been
- # imported
- def post_import(&block)
- Autoproj.post_import(self, &block)
- end
-
- def autoproj_name # :nodoc:
- srcdir.gsub(/^#{Regexp.quote(Autoproj.root_dir)}\//, '')
- end
-
- alias __depends_on__ depends_on
- def depends_on(name)
- if name.respond_to?(:name) # probably a Package object
- name = name.name
- end
-
- @os_packages ||= Set.new
- pkg_autobuild, pkg_os = partition_package(name)
- pkg_autobuild.each do |pkg|
- __depends_on__(pkg)
- end
- @os_packages |= pkg_os.to_set
- end
-
- def depends_on_os_package(name)
- depends_on(name)
- end
-
- def remove_dependency(name)
- dependencies.delete name
- optional_dependencies.delete name
- os_packages.delete name
- end
-
- def optional_dependency(name)
- optional_dependencies << name
- end
-
- def partition_package(pkg_name)
- pkg_autobuild, pkg_osdeps = [], []
- ws.manifest.resolve_package_name(pkg_name).each do |type, dep_name|
- if type == :osdeps
- pkg_osdeps << dep_name
- elsif type == :package
- pkg_autobuild << dep_name
- else raise Autoproj::InternalError, "expected package type to be either :osdeps or :package, got #{type.inspect}"
- end
- end
- return pkg_autobuild, pkg_osdeps
- end
-
- def partition_optional_dependencies
- packages, osdeps = [], []
- optional_dependencies.each do |name|
- begin
- pkg_autobuild, pkg_osdeps = partition_package(name)
- packages.concat(pkg_autobuild)
- osdeps.concat(pkg_osdeps)
- rescue Autoproj::PackageNotFound
- # Simply ignore non-existent optional dependencies
- end
- end
- return packages, osdeps
- end
-
- def resolve_optional_dependencies
- packages, osdeps = partition_optional_dependencies
- packages.each { |pkg| __depends_on__(pkg) }
- os_packages.merge(osdeps.to_set)
- end
-
- def optional_dependencies
- @optional_dependencies ||= Set.new
- end
-
- def os_packages
- @os_packages ||= Set.new
- end
- end
-
- class Git
- # Reconfigures this importer to use an already existing checkout located
- # in the given autoproj root
- #
- # @param [Autobuild::Package] the package we are dealing with
- # @param [Autoproj::InstallationManifest] the other root's installation
- # manifest
- def pick_from_autoproj_root(package, installation_manifest)
- other_pkg = installation_manifest[package.name]
- return if !other_pkg || !File.directory?(other_pkg.srcdir)
- self.relocate(other_pkg.srcdir)
- true
- end
- end
-
- class ArchiveImporter
- # Reconfigures this importer to use an already existing checkout located
- # in the given autoproj root
- #
- # @param [Autobuild::Package] the package we are dealing with
- # @param [Autoproj::InstallationManifest] the other root's installation
- # manifest
- def pick_from_autoproj_root(package, installation_manifest)
- # Get the cachefile w.r.t. the autoproj root
- cachefile = Pathname.new(self.cachefile).
- relative_path_from(Pathname.new(Autoproj.root_dir)).to_s
-
- # The cachefile in the other autoproj installation
- other_cachefile = File.join(installation_manifest.path, cachefile)
- if File.file?(other_cachefile)
- self.relocate("file://" + other_cachefile)
- true
- end
- end
- end
+Autobuild::Git.class_eval do
+ prepend Autoproj::AutobuildExtensions::Git
end
-
-module Autoproj
- @file_stack = Array.new
-
- def self.package_name_from_options(spec)
- if spec.kind_of?(Hash)
- spec.to_a.first.first.to_str
- else
- spec.to_str
- end
- end
-
- # @deprecated use Autoproj.workspace.in_package_set or add a proper Loader object to your
- # class
- def self.in_package_set(package_set, path, &block)
- Autoproj.workspace.in_package_set(package_set, path, &block)
- end
- # @deprecated use Autoproj.workspace.current_file or add a proper Loader object to your
- # class
- def self.current_file
- Autoproj.workspace.current_file
- end
- # @deprecated use Autoproj.workspace.current_package_set or add a proper Loader object to your
- # class
- def self.current_package_set
- Autoproj.workspace.current_package_set
- end
-
- def self.define(package_type, spec, &block)
- package = Autobuild.send(package_type, spec)
- Autoproj.workspace.manifest.register_package(package, block, *current_file)
- package
- end
-
- def self.loaded_autobuild_files
- Autoproj.workspace.loaded_autobuild_files
- end
-
- def self.import_autobuild_file(package_set, path)
- Autoproj.workspace.import_autobuild_file(package_set, path)
- end
-
- def self.find_topmost_directory_containing(dir, glob_pattern = nil)
- result = nil
- while dir != "/"
- match = false
- if glob_pattern
- if !Dir.glob(File.join(dir, glob_pattern)).empty?
- match = true
- end
- end
-
- if !match && block_given? && yield(dir)
- match = true
- end
- if !match && result
- return result
- elsif match
- result = dir
- end
-
- dir = File.dirname(dir)
- end
- end
-
- # Tries to find a handler automatically for 'full_path'
- def self.package_handler_for(full_path)
- if !Dir.enum_for(:glob, File.join(full_path, "*.orogen")).to_a.empty?
- return "orogen_package", full_path
- elsif File.file?(File.join(full_path, "CMakeLists.txt"))
- toplevel_dir = find_topmost_directory_containing(full_path) do |dir|
- cmakelists = File.join(dir, 'CMakeLists.txt')
- File.file?(cmakelists) &&
- (File.read(cmakelists) =~ /PROJECT/i)
- end
- toplevel_dir ||= find_topmost_directory_containing(full_path, 'CMakeLists.txt')
-
- return "cmake_package", toplevel_dir
- elsif dir = find_topmost_directory_containing(full_path, "Rakefile") ||
- find_topmost_directory_containing(full_path, "lib/*.rb")
-
- return "ruby_package", dir
- end
- end
-end
-
-def ignore(*paths)
- paths.each do |p|
- Autobuild.ignore(p)
- end
-end
-
-# Adds a new setup block to an existing package
-def setup_package(package_name, &block)
- if !block
- raise ConfigError.new, "you must give a block to #setup_package"
- end
-
- package_definition = Autoproj.workspace.manifest.package(package_name)
- if !package_definition
- raise ConfigError.new, "#{package_name} is not a known package"
- elsif package_definition.autobuild.kind_of?(Autobuild::DummyPackage)
- # Nothing to do!
- else
- package_definition.add_setup_block(block)
- end
-end
-
-# Common setup for packages
-def package_common(package_type, spec, &block)
- package_name = Autoproj.package_name_from_options(spec)
-
- if Autobuild::Package[package_name]
- current_file = Autoproj.current_file[1]
- old_file = Autoproj.workspace.manifest.definition_file(package_name)
- Autoproj.warn "#{package_name} from #{current_file} is overridden by the definition in #{old_file}"
-
- return Autobuild::Package[package_name]
- end
-
- pkg = Autoproj.define(package_type, spec, &block)
- pkg.srcdir = pkg.name
- pkg
-end
-
-def import_package(options, &block)
- package_common(:import, options, &block)
-end
-
-def common_make_based_package_setup(pkg)
- unless pkg.has_doc? && pkg.doc_dir
- pkg.with_doc do
- doc_html = File.join(pkg.builddir, 'doc', 'html')
- if File.directory?(doc_html)
- pkg.doc_dir = doc_html
- end
- end
- end
- if !pkg.test_utility.has_task?
- if !pkg.test_utility.source_dir
- test_dir = File.join(pkg.srcdir, 'test')
- if File.directory?(test_dir)
- pkg.test_utility.source_dir = test_dir
- end
- end
-
- if pkg.test_utility.source_dir
- pkg.with_tests
- end
- end
-end
-
-# Define a cmake package
-#
-# Example:
-#
-# cmake_package 'package_name' do |pkg|
-# pkg.define "CMAKE_BUILD_TYPE", "Release"
-# end
-#
-# +pkg+ is an Autobuild::CMake instance. See the Autobuild API for more
-# information.
-def cmake_package(options, &block)
- package_common(:cmake, options) do |pkg|
- pkg.depends_on 'cmake'
- common_make_based_package_setup(pkg)
- yield(pkg) if block_given?
- end
-end
-
-# Define an autotools package
-#
-# Example:
-# autotools_package 'package_name' do |pkg|
-# pkg.configureflags << "--enable-llvm"
-# end
-#
-# +pkg+ is an Autobuild::Autotools instance. See the Autobuild API for more
-# information.
-def autotools_package(options, &block)
- package_common(:autotools, options) do |pkg|
- pkg.depends_on 'autotools'
- common_make_based_package_setup(pkg)
- yield(pkg) if block_given?
- end
-end
-
-def env_set(name, value)
- Autoproj.env.set(name, value)
-end
-def env_add(name, value)
- Autoproj.env.add(name, value)
-end
-
-
-# Defines a Ruby package
-#
-# Example:
-#
-# ruby_package 'package_name' do |pkg|
-# pkg.doc_target = 'doc'
-# end
-#
-# +pkg+ is an Autobuild::Importer instance. See the Autobuild API for more
-# information.
-def ruby_package(options)
- package_common(:ruby, options) do |pkg|
- # Documentation code. Ignore if the user provided its own documentation
- # task, or disabled the documentation generation altogether by setting
- # rake_doc_task to nil
- if !pkg.has_doc? && pkg.rake_doc_task
- pkg.with_doc
- end
- if !pkg.test_utility.has_task?
- if !pkg.test_utility.source_dir
- test_dir = File.join(pkg.srcdir, 'test')
- if File.directory?(test_dir)
- pkg.test_utility.source_dir = test_dir
- end
- end
-
- if pkg.test_utility.source_dir
- pkg.with_tests
- end
- end
-
- yield(pkg) if block_given?
- end
-end
-
-# Defines an oroGen package. By default, autoproj will look for an orogen file
-# called package_basename.orogen if the package is called dir/package_basename
-#
-# Example:
-# orogen_package 'package_name' do |pkg|
-# pkg.orogen_file = "my.orogen"
-# pkg.corba = false
-# end
-#
-# +pkg+ is an Autobuild::Orogen instance. See the Autobuild API for more
-# information.
-def orogen_package(options, &block)
- package_common(:orogen, options) do |pkg|
- common_make_based_package_setup(pkg)
- yield(pkg) if block_given?
- end
-end
-
-# Declare that the packages declared in the block should be built only on the
-# given operating system. OS descriptions are space-separated strings containing
-# OS name and version.
-#
-# The block will simply be ignored if run on another architecture
-def only_on(*architectures)
- architectures = architectures.map do |name|
- if name.respond_to?(:to_str)
- [name]
- else name
- end
- end
-
- os_names, os_versions = Autoproj.workspace.operating_system
- matching_archs = architectures.find_all { |arch| os_names.include?(arch[0].downcase) }
- if matching_archs.empty?
- return
- elsif matching_archs.none? { |arch| !arch[1] || os_versions.include?(arch[1].downcase) }
- return
- end
-
- yield
-end
-
-# Declare that the packages declared in the block should not be built in the
-# given operating system. OS descriptions are space-separated strings containing
-# OS name and version.
-#
-# An error will occur if the user tries to build it on one of those
-# architectures
-def not_on(*architectures)
- architectures = architectures.map do |name|
- if name.respond_to?(:to_str)
- [name]
- else name
- end
- end
-
- os_names, os_versions = Autoproj.workspace.operating_system
- matching_archs = architectures.find_all { |arch| os_names.include?(arch[0].downcase) }
- if matching_archs.empty?
- return yield
- elsif matching_archs.all? { |arch| arch[1] && !os_versions.include?(arch[1].downcase) }
- return yield
- end
-
- # Simply get the current list of packages, yield the block, and exclude all
- # packages that have been added
- current_packages = Autobuild::Package.each(true).map(&:last).map(&:name).to_set
- yield
- new_packages = Autobuild::Package.each(true).map(&:last).map(&:name).to_set -
- current_packages
-
- new_packages.each do |pkg_name|
- Autoproj.workspace.manifest.add_exclusion(pkg_name, "#{pkg_name} is disabled on this operating system")
- end
-end
-
-# Defines an import-only package, i.e. a package that is simply checked out but
-# not built in any way
-def source_package(options)
- package_common(options) do |pkg|
- pkg.srcdir = pkg.name
- yield(pkg) if block_given?
- end
-end
-
-# Define a configuration option
-#
-# @see Autoproj::Configuration#declare
-def configuration_option(*opts, &block)
- Autoproj.config.declare(*opts, &block)
-end
-
-# Retrieves the configuration value for the given option
-#
-# See Autoproj.user_config
-def user_config(key)
- Autoproj.user_config(key)
-end
-
-class Autobuild::Git
- # Get version information
- #
- # @option options [Boolean] local (true) whether the snapshot should access
- # the remote repository to determine if the local commit is there, and
- # determine what would be the best remote branch, or stick to information
- # that is present locally
- # @option options [Boolean] exact_state (true) whether the snapshot should
- # point to a specific commit (either with a tag or with a commit ID), or
- # only override the branch
- # @return [Hash] the snapshot information, in a format that can be used by
- # {#relocate}
- def snapshot(package, target_dir = nil, only_local: true, exact_state: true)
- if only_local
- snapshot_local(package, exact_state: exact_state)
- else
- snapshot_against_remote(package, exact_state: exact_state)
- end
- end
-
- def normalize_branch_name(name)
- if name =~ /^refs\/heads\//
- return name
- else
- "refs/heads/#{name}"
- end
- end
-
- # Returns true if the given snapshot information is different from the
- # configured importer state
- #
- # It tests only against the parameters returned by {#snapshot}
- def snapshot_overrides?(snapshot)
- # We have to normalize the branch and tag names
- if snapshot_local = (snapshot['local_branch'] || snapshot['branch'])
- snapshot_local = normalize_branch_name(snapshot_local)
- local_branch = normalize_branch_name(self.local_branch)
- return true if snapshot_local != local_branch
- end
- if snapshot_remote = (snapshot['remote_branch'] || snapshot['branch'])
- snapshot_remote = normalize_branch_name(snapshot_remote)
- remote_branch = normalize_branch_name(self.remote_branch)
- return true if snapshot_remote != remote_branch
- end
- if snapshot_id = snapshot['commit']
- return true if self.commit != snapshot_id
- end
- false
- end
-
- # @api private
- def snapshot_against_remote(package, options = Hash.new)
- info = Hash['tag' => nil, 'commit' => nil]
- remote_revname = describe_commit_on_remote(package, 'HEAD', tags: options[:exact_state])
-
- case remote_revname
- when /^refs\/heads\/(.*)/
- remote_branch = $1
- if local_branch == remote_branch
- info['branch'] = local_branch
- else
- info['local_branch'] = local_branch
- info['remote_branch'] = remote_branch
- end
- when /^refs\/tags\/(.*)/
- info['tag'] = $1
- else
- info['local_branch'] = local_branch
- info['remote_branch'] = remote_revname
- end
-
- if options[:exact_state] && !info['tag']
- info['commit'] = rev_parse(package, 'HEAD')
- end
- info
- end
-
- # @api private
- def snapshot_local(package, options = Hash.new)
- info = Hash.new
- if local_branch != remote_branch
- info['local_branch'] = local_branch
- info['remote_branch'] = remote_branch
- else
- info['branch'] = branch
- end
-
- if options[:exact_state]
- has_tag, described = describe_rev(package, 'HEAD')
- if has_tag
- info.merge('tag' => described, 'commit' => nil)
- else
- info.merge('tag' => nil, 'commit' => described)
- end
- else
- info
- end
- end
-end
-
-class Autobuild::SVN
- def snapshot(package, target_dir = nil, options = Hash.new)
- version = svn_revision(package)
- Hash['revision' => version]
- end
-end
-
-class Autobuild::ArchiveImporter
- def snapshot(package, target_dir = nil, options = Hash.new)
- result = Hash[
- 'mode' => mode,
- 'no_subdirectory' => !has_subdirectory?,
- 'archive_dir' => archive_dir || tardir]
-
- if target_dir
- archive_dir = File.join(target_dir, 'archives')
- FileUtils.mkdir_p archive_dir
- FileUtils.cp @cachefile, archive_dir
-
- result['url'] = "file://$AUTOPROJ_SOURCE_DIR/archives/#{File.basename(@cachefile)}"
- else
- result['url'] = @url.to_s
- end
-
- result
- end
-end
-
-def package(name)
- Autoproj.workspace.manifest.find_autobuild_package(name)
-end
-
-# Returns true if +name+ is a valid package and is neither excluded nor ignored
-# from the build
-def package_selected?(name)
- Autoproj.workspace.manifest.package_selected?(name, false)
-end
-
-# Returns true if +name+ is a valid package and is included in the build
-def package_enabled?(name)
- Autoproj.workspace.manifest.package_enabled?(name, false)
-end
-
-# If used in init.rb, allows to disable automatic imports from specific package
-# sets
-def disable_imports_from(name)
- Autoproj.workspace.manifest.disable_imports_from(name)
-end
-
-# Moves the given package to a new subdirectory
-def move_package(name, new_dir)
- Autoproj.workspace.manifest.move_package(name, new_dir)
-end
-
-# Removes all the packages currently added from the given metapackage
-#
-# Calling this function will make sure that the given metapackage is now empty.
-def clear_metapackage(name)
- meta = Autoproj.workspace.manifest.metapackage(name)
- meta.packages.clear
-end
-
-# Declares a new metapackage, or adds packages to an existing one
-def metapackage(name, *packages)
- Autoproj.workspace.manifest.metapackage(name, *packages)
-end
-
-# This can be used only during the load of a package set
-#
-# It defines the set of packages that will be built if 'package_set_name' is
-# used. By default, all of the package set's packages are included. After a call
-# to default_packages, only the packages listed (and their dependencies) are.
-def default_packages(*names)
- pkg_set = Autoproj.current_package_set
- clear_metapackage(pkg_set.name)
- metapackage(pkg_set.name, *names)
-end
-
-# This can be used only during the load of a package set
-#
-# It removes the given packages from the set of packages that will be built if
-# 'package_set_name' is used. By default, all of the package set's packages are
-# included. After a call to default_packages, only the packages listed (and
-# their dependencies) are.
-def remove_from_default(*names)
- pkg_set = Autoproj.current_package_set
- Autoproj.workspace.manifest.metapackage(pkg_set.name).packages.delete_if do |pkg|
- names.include?(pkg.name)
- end
-end
-
-def renamed_package(current_name, old_name, options)
- if options[:obsolete] && !Autoproj.workspace.manifest.explicitely_selected_in_layout?(old_name)
- import_package old_name
- Autoproj.workspace.manifest.add_exclusion old_name, "#{old_name} has been renamed to #{current_name}, you still have the option of using the old name by adding '- #{old_name}' explicitely in the layout in autoproj/manifest, but be warned that the name will stop being usable at all in the near future"
- else
- metapackage old_name, current_name
- end
+Autobuild::SVN.class_eval do
+ prepend Autoproj::AutobuildExtensions::SVN
end