Class: Autobuild::Autotools

Inherits:
Configurable show all
Defined in:
lib/autobuild/packages/autotools.rb

Overview

Handles autotools-based packages

Used programs (see Autobuild.programs)

Autotools will use the ‘aclocal’, ‘autoheader’, ‘autoconf’, ‘automake’ and ‘bear’ programs defined on Autobuild.programs. autoheader and bear are disabled by default, aclocal, autoconf and automake use are autodetected.

To override this default behaviour on a per-package basis, use Autotools#use

Direct Known Subclasses

GenomModule

Defined Under Namespace

Classes: UnexpectedConfigStatusOutput

Constant Summary collapse

@@enable_bear_globally =
false

Instance Attribute Summary collapse

Attributes inherited from Configurable

#source_tree_excludes

Attributes inherited from Package

#dependencies, #env, #failures, #importdir, #importer, #logdir, #name, #prefix, #srcdir, #statistics, #update, #updated, #utilities

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Configurable

builddir, #builddir, builddir=, #builddir=, #buildstamp, #ensure_dependencies_installed, #prepare_for_rebuild

Methods inherited from Package

[], #add_env_op, #add_stat, #all_dependencies, #applied_post_install?, #apply_env, #apply_post_install, #checked_out?, clear, #depends_on, #depends_on?, #disable, #disable_doc, #disable_phases, #disabled?, #doc_dir, #doc_dir=, #doc_disabled, #doc_target_dir, #doc_target_dir=, #doc_task, each, #enable_doc, #env_add, #env_add_path, #env_add_prefix, #env_set, #env_source_after, #error, #failed?, #file, #find_in_path, #fingerprint, #full_env, #generates_doc?, #has_doc?, #import=, #import_invoked?, #imported?, #in_dir, #inspect, #install_doc, #install_invoked?, #installed?, #installstamp, #isolate_errors, #message, #method_missing, #parallel_build_level, #parallel_build_level=, #post_install, #prepare_for_rebuild, #process_formatting_string, #progress, #progress_done, #progress_start, #provides, #resolve_dependency_env, #resolved_env, #respond_to_missing?, #run, #self_fingerprint, #source_tree, #task, #to_s, #update?, #update_environment, #updated?, #utility, #warn, #working_directory

Constructor Details

#initialize(options) ⇒ Autotools

Returns a new instance of Autotools.



44
45
46
47
48
49
50
51
52
53
54
# File 'lib/autobuild/packages/autotools.rb', line 44

def initialize(options)
    @using = Hash.new
    @configureflags = []
    @aclocal_flags    = Array.new
    @autoheader_flags = Array.new
    @autoconf_flags   = Array.new
    @automake_flags   = Array.new
    @bear_flags       = ['-a']

    super
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Autobuild::Package

Instance Attribute Details

#aclocal_flagsObject

Returns the value of attribute aclocal_flags.



20
21
22
# File 'lib/autobuild/packages/autotools.rb', line 20

def aclocal_flags
  @aclocal_flags
end

#autoconf_flagsObject

Returns the value of attribute autoconf_flags.



20
21
22
# File 'lib/autobuild/packages/autotools.rb', line 20

def autoconf_flags
  @autoconf_flags
end

#autoheader_flagsObject

Returns the value of attribute autoheader_flags.



20
21
22
# File 'lib/autobuild/packages/autotools.rb', line 20

def autoheader_flags
  @autoheader_flags
end

#automake_flagsObject

Returns the value of attribute automake_flags.



20
21
22
# File 'lib/autobuild/packages/autotools.rb', line 20

def automake_flags
  @automake_flags
end

#bear_flagsObject

Returns the value of attribute bear_flags.



20
21
22
# File 'lib/autobuild/packages/autotools.rb', line 20

def bear_flags
  @bear_flags
end

#configureflagsObject

Returns the value of attribute configureflags.



20
21
22
# File 'lib/autobuild/packages/autotools.rb', line 20

def configureflags
  @configureflags
end

#force_config_statusObject

If set to true, configure will be called with –no-create and ./config.status will be started each time before “make”

In general, you should not need that.



233
234
235
# File 'lib/autobuild/packages/autotools.rb', line 233

def force_config_status
  @force_config_status
end

#usingObject

Returns the value of attribute using.



20
21
22
# File 'lib/autobuild/packages/autotools.rb', line 20

def using
  @using
end

Class Method Details

.enable_bear_globally=(flag) ⇒ Object



30
31
32
# File 'lib/autobuild/packages/autotools.rb', line 30

def self.enable_bear_globally=(flag)
    @@enable_bear_globally = flag
end

.enable_bear_globally?Boolean

Returns:

  • (Boolean)


26
27
28
# File 'lib/autobuild/packages/autotools.rb', line 26

def self.enable_bear_globally?
    @@enable_bear_globally
end

Instance Method Details

#buildObject

Do the build in builddir



318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/autobuild/packages/autotools.rb', line 318

def build
    in_dir(builddir) do
        progress_start "building %s [progress not available]",
                       done_message: 'built %s' do
            run('build', './config.status') if force_config_status

            build_options = []
            if using_bear?
                build_tool = tool_program(:bear)
                build_options = bear_flags
                build_options << Autobuild.tool(:make)
            else
                build_tool = Autobuild.tool(:make)
            end
            build_options << "-j#{parallel_build_level}"

            run('build', build_tool, *build_options)
        end
    end
    Autobuild.touch_stamp(buildstamp)
end

#common_utility_handling(utility, target) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/autobuild/packages/autotools.rb', line 56

def common_utility_handling(utility, target)
    utility.task do
        progress_start "generating documentation for %s",
                       done_message: 'generated documentation for %s' do
            if internal_doxygen_mode?
                run_doxygen
            else
                run(utility.name,
                    Autobuild.tool(:make), "-j#{parallel_build_level}",
                    target, working_directory: builddir)
            end
            yield if block_given?
        end
    end
end

#configureObject

Configure the builddir directory before starting make



303
304
305
306
307
308
309
310
311
312
313
314
315
# File 'lib/autobuild/packages/autotools.rb', line 303

def configure
    super do
        command = ["#{srcdir}/configure"]
        command << "--no-create" if force_config_status
        command << "--prefix=#{prefix}"
        command += configureflags.flatten

        progress_start "configuring autotools for %s",
                       done_message: 'configured autotools for %s' do
            run('configure', *command, working_directory: builddir)
        end
    end
end

#configurestampObject



40
41
42
# File 'lib/autobuild/packages/autotools.rb', line 40

def configurestamp
    "#{builddir}/config.status"
end

#create_regen_target(confsource = nil) ⇒ Object

Adds a target to rebuild the autotools environment



261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/autobuild/packages/autotools.rb', line 261

def create_regen_target(confsource = nil)
    conffile = "#{srcdir}/configure"
    if confsource
        file conffile => confsource
    elsif (confext = %w[.ac .in].find { |ext| File.exist?("#{conffile}#{ext}") })
        file conffile => "#{conffile}#{confext}"
    elsif using[:autoconf]
        raise PackageException.new(self, 'prepare'),
              "neither configure.ac nor configure.in present in #{srcdir}"
    end

    file conffile do
        isolate_errors do
            progress_start "generating autotools for %s",
                           done_message: 'generated autotools for %s' do
                regen
            end
        end
    end

    conffile
end

#import(**options) ⇒ Object



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/autobuild/packages/autotools.rb', line 141

def import(**options)
    # We force a regen after the first checkout. The issue is that
    # autotools is less robust than it should, and very often it is
    # better to generate the build system for the system on which we
    # must build
    #
    # When we are doing a fresh checkout, a file is touched in the
    # source directory. That file is then deleted after #prepare gets
    # called
    is_checking_out = !File.directory?(srcdir)

    super
ensure
    if is_checking_out && File.directory?(srcdir)
        FileUtils.touch File.join(srcdir, ".fresh_checkout")
    end
end

#installObject

Install the result in prefix



341
342
343
344
345
346
347
348
349
# File 'lib/autobuild/packages/autotools.rb', line 341

def install
    in_dir(builddir) do
        progress_start "installing %s", :done_message => 'installed %s' do
            run('install', Autobuild.tool(:make), 'install')
        end
    end

    super
end

#prepareObject



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/autobuild/packages/autotools.rb', line 161

def prepare
    super
    autodetect_needed_stages

    fresh_checkout_mark = File.join(srcdir, '.fresh_checkout')
    if File.file?(fresh_checkout_mark)
        prepare_for_forced_build
        FileUtils.rm_f fresh_checkout_mark
    end

    # Check if config.status has been generated with the
    # same options than the ones in configureflags
    #
    # If it is not the case, remove it to force reconfiguration
    if File.exist?(configurestamp)
        output = run('prepare', configurestamp, '--version').
            grep(/with options/).first
        if output && (match = /with options "(.*)"/.match(output))
            options = Shellwords.shellwords(match[1])
        else
            raise UnexpectedConfigStatusOutput, "invalid output of "\
                "config.status --version, expected a line with "\
                "`with options \"OPTIONS\"`"
        end

        # Add the --prefix option to the configureflags array
        testflags = ["--prefix=#{prefix}"] + configureflags.flatten
        old_opt = options.find do |o|
            if testflags.include?(o)
                false
            elsif o =~ /^-/
                # Configuration option that is not specified, have to
                # reconfigure
                true
            else
                # This is an envvar entry. Ignore it if it is not
                # explicitely given in configureflags
                varname, = o.split("=").first
                if (current_flag = testflags.find { |fl| fl =~ /^#{varname}=/ })
                    current_flag != o
                else
                    false
                end
            end
        end
        new_opt = testflags.find { |o| !options.include?(o) }
        if old_opt || new_opt
            if Autobuild.verbose
                Autobuild.message "forcing reconfiguration of #{name} "\
                    "(#{old_opt} != #{new_opt})"
            end
            FileUtils.rm_f configurestamp # to force reconfiguration
        end
    end

    regen_target = create_regen_target
    file configurestamp => regen_target
end

#prepare_for_forced_buildObject



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/autobuild/packages/autotools.rb', line 124

def prepare_for_forced_build
    super

    autodetect_needed_stages
    if using[:autoconf] || using[:autogen]
        FileUtils.rm_f File.join(srcdir, 'configure')
    end

    if using[:automake]
        Find.find(srcdir) do |path|
            FileUtils.rm_f(path) if File.basename(path) == "Makefile.in"
        end
    end

    FileUtils.rm_f configurestamp
end

#regenObject



284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
# File 'lib/autobuild/packages/autotools.rb', line 284

def regen
    if using[:libtool]
        run 'configure', Autobuild.tool('libtoolize'), '--copy',
            working_directory: srcdir
    end
    if using[:autogen]
        run 'configure', File.expand_path(using[:autogen], srcdir),
            working_directory: srcdir
    else
        %i[aclocal autoconf autoheader automake].each do |tool|
            next unless using[tool]

            run 'configure', tool_program(tool), *send("#{tool}_flags"),
                working_directory: srcdir
        end
    end
end

#tool_program(tool) ⇒ Object



220
221
222
223
224
225
226
227
# File 'lib/autobuild/packages/autotools.rb', line 220

def tool_program(tool)
    tool_flag = using[tool.to_sym]
    if tool_flag.respond_to?(:to_str)
        tool_flag.to_str
    else
        Autobuild.tool(tool)
    end
end

#use(*programs) ⇒ Object

Overrides the default behaviour w.r.t. autotools script generation

Use it like that:

  • to force a generation step (skipping autodetection), do

    pkg.use <program> => true
    

    For instance, for aclocal

    pkg.use :aclocal => true
    
  • to force a generation step, overriding the program defined on Autobuild

    pkg.use <program> => true
    

    For instance, for autoconf

    pkg.use :autoconf => 'my_autoconf_program'
    
  • to disable a generation step, do

    pkg.use <program> => false
    

    For instance, for automake

    pkg.use :automake => false
    
  • to restore autodetection, do

    pkg.use <program> => nil
    

    For instance, for automake

    pkg.use :automake => nil
    


104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/autobuild/packages/autotools.rb', line 104

def use(*programs)
    programs =
        if programs.size == 1
            programs.first
        else
            programs
        end

    unless programs.kind_of?(Hash)
        programs = Array[*programs].each_with_object({}) do |spec, progs|
            progs[spec.first] = spec.last
        end
    end
    programs.each do |name, opt|
        using[name.to_sym] = opt
    end

    nil
end

#using_bear?Boolean

Returns:

  • (Boolean)


34
35
36
37
38
# File 'lib/autobuild/packages/autotools.rb', line 34

def using_bear?
    return Autotools.enable_bear_globally? if using[:bear].nil?

    using[:bear]
end

#with_doc(target = 'doc', &block) ⇒ Object

Declare that the given target can be used to generate documentation



73
74
75
# File 'lib/autobuild/packages/autotools.rb', line 73

def with_doc(target = 'doc', &block)
    common_utility_handling(doc_utility, target, &block)
end

#with_tests(target = 'test', &block) ⇒ Object



77
78
79
# File 'lib/autobuild/packages/autotools.rb', line 77

def with_tests(target = 'test', &block)
    common_utility_handling(test_utility, target, &block)
end