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.



52
53
54
55
56
57
58
59
60
61
62
# File 'lib/autobuild/packages/autotools.rb', line 52

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.



28
29
30
# File 'lib/autobuild/packages/autotools.rb', line 28

def aclocal_flags
  @aclocal_flags
end

#autoconf_flagsObject

Returns the value of attribute autoconf_flags.



28
29
30
# File 'lib/autobuild/packages/autotools.rb', line 28

def autoconf_flags
  @autoconf_flags
end

#autoheader_flagsObject

Returns the value of attribute autoheader_flags.



28
29
30
# File 'lib/autobuild/packages/autotools.rb', line 28

def autoheader_flags
  @autoheader_flags
end

#automake_flagsObject

Returns the value of attribute automake_flags.



28
29
30
# File 'lib/autobuild/packages/autotools.rb', line 28

def automake_flags
  @automake_flags
end

#bear_flagsObject

Returns the value of attribute bear_flags.



28
29
30
# File 'lib/autobuild/packages/autotools.rb', line 28

def bear_flags
  @bear_flags
end

#configureflagsObject

Returns the value of attribute configureflags.



28
29
30
# File 'lib/autobuild/packages/autotools.rb', line 28

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.



241
242
243
# File 'lib/autobuild/packages/autotools.rb', line 241

def force_config_status
  @force_config_status
end

#usingObject

Returns the value of attribute using.



28
29
30
# File 'lib/autobuild/packages/autotools.rb', line 28

def using
  @using
end

Class Method Details

.enable_bear_globally=(flag) ⇒ Object



38
39
40
# File 'lib/autobuild/packages/autotools.rb', line 38

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

.enable_bear_globally?Boolean

Returns:

  • (Boolean)


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

def self.enable_bear_globally?
    @@enable_bear_globally
end

Instance Method Details

#buildObject

Do the build in builddir



326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
# File 'lib/autobuild/packages/autotools.rb', line 326

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



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/autobuild/packages/autotools.rb', line 64

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



311
312
313
314
315
316
317
318
319
320
321
322
323
# File 'lib/autobuild/packages/autotools.rb', line 311

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



48
49
50
# File 'lib/autobuild/packages/autotools.rb', line 48

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

#create_regen_target(confsource = nil) ⇒ Object

Adds a target to rebuild the autotools environment



269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
# File 'lib/autobuild/packages/autotools.rb', line 269

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



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/autobuild/packages/autotools.rb', line 149

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



349
350
351
352
353
354
355
356
357
# File 'lib/autobuild/packages/autotools.rb', line 349

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



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
219
220
221
222
223
224
225
226
# File 'lib/autobuild/packages/autotools.rb', line 169

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



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/autobuild/packages/autotools.rb', line 132

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



292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
# File 'lib/autobuild/packages/autotools.rb', line 292

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



228
229
230
231
232
233
234
235
# File 'lib/autobuild/packages/autotools.rb', line 228

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
    


112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/autobuild/packages/autotools.rb', line 112

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)


42
43
44
45
46
# File 'lib/autobuild/packages/autotools.rb', line 42

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



81
82
83
# File 'lib/autobuild/packages/autotools.rb', line 81

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

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



85
86
87
# File 'lib/autobuild/packages/autotools.rb', line 85

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