Class: Rake::Builder

Inherits:
Object
  • Object
show all
Defined in:
lib/rake/builder.rb,
lib/rake/builder/error.rb,
lib/rake/builder/version.rb,
lib/rake/builder/installer.rb,
lib/rake/builder/configure_ac.rb,
lib/rake/builder/local_config.rb,
lib/rake/builder/autoconf/version.rb,
lib/rake/builder/logger/formatter.rb,
lib/rake/builder/task_definers/builder_task_definer.rb,
lib/rake/builder/presenters/makefile_am/builder_collection_presenter.rb

Direct Known Subclasses

QtBuilder

Defined Under Namespace

Modules: Autoconf, Logger, Presenters, VERSION Classes: BuildFailure, BuilderCollectionTaskDefiner, BuilderTaskDefiner, ConfigureAc, Error, Installer, LocalConfig

Constant Summary collapse

TARGET_TYPES =

The types of file that can be built

[ :executable, :static_library, :shared_library ]
KNOWN_LANGUAGES =

Programmaing languages that Rake::Builder can handle

{
  'c' => {
    :source_file_extension => 'c',
    :compiler              => 'gcc',
    :linker                => 'gcc',
    :ar                    => 'ar',
    :ranlib                => 'ranlib'
  },
  'c++' => {
    :source_file_extension => 'cpp',
    :compiler              => 'g++',
    :linker                => 'g++',
    :ar                    => 'ar',
    :ranlib                => 'ranlib'
  },
  'objective-c' => {
    :source_file_extension => 'm',
    :compiler              => 'gcc',
    :linker                => 'gcc',
    :ar                    => 'ar',
    :ranlib                => 'ranlib'
  },
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(&block) ⇒ Builder

Returns a new instance of Builder


195
196
197
198
199
200
201
202
203
# File 'lib/rake/builder.rb', line 195

def initialize(&block)
  raise 'No block given' if block.nil?
  save_rakefile_info(block)
  set_defaults
  block.call(self)
  configure
  BuilderTaskDefiner.new(self).run
  self.class.instances << self
end

Instance Attribute Details

#arObject

Toolchain setting - ar


77
78
79
# File 'lib/rake/builder.rb', line 77

def ar
  @ar
end

#architectureObject

processor type: 'i386', 'x86_64', 'ppc' or 'ppc64'.


37
38
39
# File 'lib/rake/builder.rb', line 37

def architecture
  @architecture
end

#compilation_optionsObject

Array of extra options to pass to the compiler


139
140
141
# File 'lib/rake/builder.rb', line 139

def compilation_options
  @compilation_options
end

#compilerObject

The compiler that will be used


71
72
73
# File 'lib/rake/builder.rb', line 71

def compiler
  @compiler
end

#compiler_dataObject

Returns the value of attribute compiler_data


39
40
41
# File 'lib/rake/builder.rb', line 39

def compiler_data
  @compiler_data
end

#default_taskObject

Name of the default task


130
131
132
# File 'lib/rake/builder.rb', line 130

def default_task
  @default_task
end

#generated_filesObject

Temporary files generated during compilation and linking


163
164
165
# File 'lib/rake/builder.rb', line 163

def generated_files
  @generated_files
end

#header_file_extensionObject

Extension of header files (default 'h')


86
87
88
# File 'lib/rake/builder.rb', line 86

def header_file_extension
  @header_file_extension
end

#include_pathsObject

Additional include directories for compilation


142
143
144
# File 'lib/rake/builder.rb', line 142

def include_paths
  @include_paths
end

#install_pathObject

The directory where 'rake install' will copy the target file


154
155
156
# File 'lib/rake/builder.rb', line 154

def install_path
  @install_path
end

#installable_headersObject

Directories/file globs to search for header files to be installed with libraries. When static libraries are installed, headers are installed too. During installation, the destination path is:

/usr/local/include + the relative path

This 'relative path' is calculated as follows:

  1. Any files named in installable_headers are installed directly under /usr/local/include

  2. The contents of any directory named in installable_headers are also installed directly under /usr/local/include

  3. Files found by glob have the fixed part of the glob removed and

the relative path calculated:

E.g. files found with './include/*/' will have './include' removed to calculate the

relative path.

So, ./include/my_lib/foo.h' produces a relative path of 'my_lib' so the file will be installed as '/usr/local/include/my_lib/foo.h'


114
115
116
# File 'lib/rake/builder.rb', line 114

def installable_headers
  @installable_headers
end

#library_dependenciesObject

Libraries to be linked


151
152
153
# File 'lib/rake/builder.rb', line 151

def library_dependencies
  @library_dependencies
end

#library_pathsObject

Additional library directories for linking


145
146
147
# File 'lib/rake/builder.rb', line 145

def library_paths
  @library_paths
end

#linkerObject

The linker that will be used


74
75
76
# File 'lib/rake/builder.rb', line 74

def linker
  @linker
end

#linker_optionsObject

extra options to pass to the linker


148
149
150
# File 'lib/rake/builder.rb', line 148

def linker_options
  @linker_options
end

#local_configObject (readonly)

The file containing local settings such as include paths


160
161
162
# File 'lib/rake/builder.rb', line 160

def local_config
  @local_config
end

#loggerObject

Each instance has its own logger


166
167
168
# File 'lib/rake/builder.rb', line 166

def logger
  @logger
end

#makedepend_fileObject (readonly)

Name of the generated file containing source - header dependencies


157
158
159
# File 'lib/rake/builder.rb', line 157

def makedepend_file
  @makedepend_file
end

#objects_pathObject

Directory to be used for object files


136
137
138
# File 'lib/rake/builder.rb', line 136

def objects_path
  @objects_path
end

#programming_languageObject

The programming language: 'c++', 'c' or 'objective-c' (default 'c++') This also sets defaults for source_file_extension


43
44
45
# File 'lib/rake/builder.rb', line 43

def programming_language
  @programming_language
end

#rakefileObject (readonly)

The Rakefile The file is not necessarily called 'Rakefile' It is the file which calls to Rake::Builder.new


95
96
97
# File 'lib/rake/builder.rb', line 95

def rakefile
  @rakefile
end

#rakefile_pathObject (readonly)

The path of the Rakefile All paths are relative to this


90
91
92
# File 'lib/rake/builder.rb', line 90

def rakefile_path
  @rakefile_path
end

#ranlibObject

Toolchain setting - ranlib


80
81
82
# File 'lib/rake/builder.rb', line 80

def ranlib
  @ranlib
end

#source_file_extensionObject

Extension of source files (default 'cpp' for C++ and 'c' for C)


83
84
85
# File 'lib/rake/builder.rb', line 83

def source_file_extension
  @source_file_extension
end

#source_search_pathsObject

Directories/file globs to search for project source files


98
99
100
# File 'lib/rake/builder.rb', line 98

def source_search_paths
  @source_search_paths
end

#targetObject

The file to be built


26
27
28
# File 'lib/rake/builder.rb', line 26

def target
  @target
end

#target_parametersObject

Command line parameters to pass to the target when it is executed with the `run` task. Default: []


170
171
172
# File 'lib/rake/builder.rb', line 170

def target_parameters
  @target_parameters
end

#target_prerequisitesObject

Tasks which the target file depends upon


133
134
135
# File 'lib/rake/builder.rb', line 133

def target_prerequisites
  @target_prerequisites
end

#target_typeObject

The type of file to be built One of: :executable, :static_library, :shared_library If not set, this is deduced from the target.


31
32
33
# File 'lib/rake/builder.rb', line 31

def target_type
  @target_type
end

#task_namespaceObject

(Optional) namespace for tasks


127
128
129
# File 'lib/rake/builder.rb', line 127

def task_namespace
  @task_namespace
end

Class Method Details

.create_autoconf(project_title, version, source_file) ⇒ Object


180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/rake/builder.rb', line 180

def self.create_autoconf(project_title, version, source_file)
  raise "Please supply a project_title parameter" if project_title.nil?
  version = Rake::Builder::Autoconf::Version.new(version).decide
  if File.exist?('configure.ac')
    raise "The file 'configure.ac' already exists"
  end
  if File.exist?('Makefile.am')
    raise "The file 'Makefile.am' already exists"
  end
  ConfigureAc.new(project_title, version, source_file).save
  Presenters::MakefileAm::BuilderCollectionPresenter.new(instances).save
end

.instancesObject


176
177
178
# File 'lib/rake/builder.rb', line 176

def self.instances
  @instances
end

Instance Method Details

#buildObject

main actions

Raises:


208
209
210
211
212
213
214
215
216
# File 'lib/rake/builder.rb', line 208

def build
  logger.debug "Building '#{target}'"
  File.unlink(target) if File.exist?(target)
  build_commands.each do |command|
    stdout, stderr = shell(command)
    raise BuildFailure.new("Error: command '#{command}' failed: #{stderr} #{stdout}") if not $?.success?
  end
  raise BuildFailure.new("'#{target}' not created") if not File.exist?(target)
end

#cleanObject


235
236
237
238
239
# File 'lib/rake/builder.rb', line 235

def clean
  generated_files.each do |file|
    File.unlink(file) if File.exist?(file)
  end
end

#compile(source, object) ⇒ Object

Raises:


324
325
326
327
328
329
# File 'lib/rake/builder.rb', line 324

def compile(source, object)
  logger.add(::Logger::DEBUG, "Compiling '#{source}'")
  command = "#{compiler} -c #{compiler_flags} -o #{object} #{source}"
  stdout, stderr = shell(command)
  raise BuildFailure.new("Error: command '#{command}' failed: #{stderr} #{stdout}") if not $?.success?
end

#compiler_flagsObject


370
371
372
373
374
375
376
# File 'lib/rake/builder.rb', line 370

def compiler_flags
  flags = include_path
  options = compilation_options.join(' ')
  flags << ' ' + options             if options != ''
  flags << ' ' + architecture_option if RUBY_PLATFORM =~ /darwin/i
  flags
end

#create_local_configObject


316
317
318
319
320
321
322
# File 'lib/rake/builder.rb', line 316

def create_local_config
  logger.debug "Creating file '#{local_config}'"
  added_includes = compiler_data.include_paths(missing_headers)
  config = Rake::Builder::LocalConfig.new(local_config)
  config.include_paths = added_includes
  config.save
end

#create_makedepend_fileObject

helpers invoked by tasks


255
256
257
258
259
260
261
262
263
264
265
266
# File 'lib/rake/builder.rb', line 255

def create_makedepend_file
  logger.debug 'Creating makedepend file'
  system('which makedepend >/dev/null')
  raise 'makedepend not found' unless $?.success?
  command =
    "makedepend -f- " \
    "-- #{compiler_flags} "\
    "-- #{file_list(source_files)} " \
    "2>/dev/null " \
    "> #{makedepend_file}"
  shell command
end

#ensure_headersObject

Raises an error if there are missing headers

Raises:


301
302
303
304
305
306
307
# File 'lib/rake/builder.rb', line 301

def ensure_headers
  missing = missing_headers
  return if missing.size == 0

  message = "Compilation cannot proceed as the following header files are missing:\n" + missing.join("\n") 
  raise Error.new(message)
end

#generated_headersObject


296
297
298
# File 'lib/rake/builder.rb', line 296

def generated_headers
  []
end

#header_search_pathsObject


116
117
118
119
# File 'lib/rake/builder.rb', line 116

def header_search_paths
  warn 'Deprecation notice: Rake::Builder#header_search_paths has been replaced by Rake::Builder#installable_headers'
  installable_headers
end

#header_search_paths=(paths) ⇒ Object


121
122
123
124
# File 'lib/rake/builder.rb', line 121

def header_search_paths=(paths)
  warn 'Deprecation notice: Rake::Builder#header_search_paths has been replaced by Rake::Builder#installable_headers'
  installable_headers = paths
end

#installObject


241
242
243
244
245
# File 'lib/rake/builder.rb', line 241

def install
  destination = File.join(install_path, target_basename)
  Rake::Builder::Installer.new.install target, destination
  install_headers if target_type == :static_library
end

#is_library?Boolean

public attributes

Returns:

  • (Boolean)

334
335
336
# File 'lib/rake/builder.rb', line 334

def is_library?
  [:static_library, :shared_library].include?(target_type)
end

#labelObject


346
347
348
# File 'lib/rake/builder.rb', line 346

def label
  target_path.gsub(%r(\.), '_')
end

#library_dependencies_listObject


384
385
386
# File 'lib/rake/builder.rb', line 384

def library_dependencies_list
  @library_dependencies.map { |lib| "-l#{lib}" }.join(' ')
end

378
379
380
381
382
# File 'lib/rake/builder.rb', line 378

def link_flags
  flags = [ @linker_options, library_paths_list, library_dependencies_list ]
  flags << architecture_option if RUBY_PLATFORM =~ /darwin/i
  flags.join( " " )
end

#load_local_configObject


309
310
311
312
313
314
# File 'lib/rake/builder.rb', line 309

def load_local_config
  config = Rake::Builder::LocalConfig.new(local_config)
  config.load
  @include_paths       += config.include_paths
  @compilation_options += config.compilation_options
end

#load_makedependObject


268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
# File 'lib/rake/builder.rb', line 268

def load_makedepend
  content = File.read(makedepend_file)
  # Replace old-style files with full paths
  if content =~ %r(^/)
    create_makedepend_file
    return load_makedepend
  end

  # makedepend assumes each .o files will be in the same path as its source
  real_object_path = source_files.inject({}) do |a, source|
    source_path_object = source.gsub('.' + source_file_extension, '.o')
    correct_path_object = object_path(source)
    a[source_path_object] = correct_path_object
    a
  end

  object_header_dependencies = Hash.new { |h, v| h[v] = [] }
  content.each_line do |line|
    next if line !~ /:\s/
    source_path_object = $`
    header_files = $'.chomp
    object_path_name = real_object_path[source_path_object]
    object_header_dependencies[object_path_name] += header_files.split(' ')
  end

  object_header_dependencies
end

#makefile_nameObject


388
389
390
391
392
393
394
395
# File 'lib/rake/builder.rb', line 388

def makefile_name
  extension = if ! task_namespace.nil? && ! task_namespace.to_s.empty?
                '.' + task_namespace.to_s
              else
                ''
              end
  "Makefile#{ extension }"
end

#object_filesObject


361
362
363
# File 'lib/rake/builder.rb', line 361

def object_files
  source_files.map { |file| object_path(file) }
end

#object_path(source_path_name) ⇒ Object


365
366
367
368
# File 'lib/rake/builder.rb', line 365

def object_path(source_path_name)
  o_name = File.basename(source_path_name).gsub('.' + source_file_extension, '.o')
  File.join(objects_path, o_name)
end

#runObject


218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/rake/builder.rb', line 218

def run
  old_dir = Dir.pwd
  Dir.chdir rakefile_path
  command = File.join('.', target)
  if target_parameters.size > 0
    command << " " << target_parameters.join(" ")
  end
  begin
    output, error = shell(command, ::Logger::INFO)
    $stdout.print output
    $stderr.print error
    raise Exception.new("Running #{command} failed with status #{$?.exitstatus}") if ! $?.success?
  ensure
    Dir.chdir old_dir
  end
end

#source_filesObject

Source files found in source_search_paths


351
352
353
354
355
356
357
358
359
# File 'lib/rake/builder.rb', line 351

def source_files
  return @source_files if @source_files

  old_dir = Dir.pwd
  Dir.chdir @rakefile_path
  @source_files = Rake::Path.find_files(@source_search_paths, source_file_extension).uniq.sort
  Dir.chdir old_dir
  @source_files
end

#target_basenameObject


338
339
340
# File 'lib/rake/builder.rb', line 338

def target_basename
  File.basename(@target)
end

#target_pathObject


342
343
344
# File 'lib/rake/builder.rb', line 342

def target_path
  target.sub(/^\.\//, '') # Remove current directory from name
end

#uninstallObject


247
248
249
250
# File 'lib/rake/builder.rb', line 247

def uninstall
  destination = File.join(install_path, target_basename)
  Rake::Builder::Installer.new.uninstall destination
end