Parent

Compiler

Processes source code files to produce intermediate object files.

Attributes

ld[RW]
output[RW]
path[R]
platform_cflags[RW]
sysroot[RW]
vendor[R]

Public Class Methods

new(language, extension) click to toggle source
# File lib/makeconf/compiler.rb, line 10
def initialize(language, extension)
  @language = language
  @extension = extension
  @ld = Linker.new()
  windows_init if Platform.is_windows?
  @flags = []
  @sources = []     # List of input files
  @output = nil
  @platform_cflags = []   # Cflags required by the SystemType
  @sysroot = nil
  @quiet = false          # If true, output will be suppressed
  @vendor = 'Unknown'

  # TODO:
  # If true, all source files will be passed to the compiler at one time.
  # This will also combine the link and compilation phases.
  # See: the -combine option in GCC
  #@combine = false

end

Public Instance Methods

cflags() click to toggle source
# File lib/makeconf/compiler.rb, line 38
def cflags
  @flags
end
check_header(path) click to toggle source

Check if a header is available

# File lib/makeconf/compiler.rb, line 188
def check_header(path)
  test_compile("#include <" + path + ">")
end
command() click to toggle source

Return the complete command line to compile an object

# File lib/makeconf/compiler.rb, line 69
  def command
    log.debug self.pretty_inspect

    throw 'Invalid linker' unless @ld.is_a?(Linker)
    throw 'One or more source files are required' unless @sources.length > 0
#      cflags = default_flags
#      cflags.concat @flags
#    end
#    throw cflags

#    topdir = h[:topdir] || ''
#    ld = @ld
#    ldadd = h[:ldadd]
#    ld.flags = h[:ldflags]
#    ld.output = Platform.pathspec(h[:output])
#    ld.rpath = h[:rpath] if h[:rpath].length > 0

#    inputs = h[:sources]
#    inputs = [ inputs ] if inputs.is_a? String
#    inputs = inputs.map { |x| Platform.pathspec(topdir + x) }
#    throw 'One or more sources are required' unless inputs.count

#TODO:if @combine
# return [ @path, cflags, '-combine', ldflags, inputs, ldadd ].flatten.join(' ')
#
    
    cmd = [ @path, '-DHAVE_CONFIG_H', '-I.', @platform_cflags, flags, '-c', @sources ].flatten.join(' ')

    cmd += Platform.dev_null if @quiet

    log.debug "Compiler command: #{cmd}"

    cmd
  end
compile() click to toggle source

Run the compilation command

# File lib/makeconf/compiler.rb, line 198
  def compile
    cmd = self.command
#puts ' + ' + cmd
    log.debug "Invoking the compiler"
    rc = Platform.execute cmd
    log.debug "Compilation complete; rc=#{rc.to_s}"
    rc
  end
default_flags() click to toggle source

Try to determine a usable default set of compiler flags

# File lib/makeconf/compiler.rb, line 249
def default_flags
  cflags = []

  # GCC on Solaris 10 produces 32-bit code by default, so add -m64
  # when running in 64-bit mode.
  if Platform.is_solaris? and Platform.word_size == 64
     cflags.push '-m64'
  end

  cflags
end
flags() click to toggle source
# File lib/makeconf/compiler.rb, line 105
def flags
  tok = @flags.clone

  # KLUDGE: remove things that CL.EXE doesn't understand
  if @vendor == 'Microsoft'
    tok = tok.flatten.map do |t|
      t.gsub!(/^-Wall$/, ' ') #  /Wall generates too much noise
      t.gsub!(/^-Werror$/, ' ')  # Could use /WX here
      t.gsub!(/^-W$/, ' ')
      t.gsub!(/^-Wno-.*?/, ' ')
      t.gsub!(/^-Wextra$/, ' ')
      t.gsub!(/^-fPIC$/, ' ')
      t.gsub!(/^-std=.*?$/, ' ')
      t.gsub!(/^-pedantic$/, ' ')
    end
  end

  # Set the output path
  unless @output.nil?
    outfile = Platform.pathspec(@output)
    if @vendor == 'Microsoft'
      tok.push '"-IC:\Program Files\Microsoft Visual Studio 10.0\VC\include"' # XXX-HARDCODED
      tok.push '/Fo' + outfile
      tok.push '/MD'
    else
      tok.push '-o', outfile
    end
  end

  if @ld.shared_library 
    if Platform.is_windows?
      throw 'FIXME'
    else
      tok.push('-fPIC', '-DPIC') unless is_mingw?
    end
  end

  tok.push '--sysroot=' + @sysroot unless @sysroot.nil?

  tok.join(' ')
end
flags=(s) click to toggle source
# File lib/makeconf/compiler.rb, line 147
def flags=(s)
  if s.kind_of?(String)
    @flags = s.split(' ') # FIXME: need to handle quoted strings w/ spaces
  elsif s.kind_of?(Array)
    @flags = s.clone
  else
    raise ArgumentError, "invalid flag type"
  end
end
has_option(opt) click to toggle source

Test if the compiler supports a command line option

# File lib/makeconf/compiler.rb, line 175
  def has_option(opt)

    # Create a simple test file
    f = Tempfile.new(['test_has_option', @extension]);
    f.puts 'int main() { }'
    f.flush

#FIXME: /dev/null not portable
    cmd = [ @path, opt, '-o /dev/null', '-c', f.path ].join(' ') + Platform.dev_null
    Platform.execute cmd
  end
makedepends(source_file) click to toggle source

Return the list of dependencies to pass to make(1)

# File lib/makeconf/compiler.rb, line 262
def makedepends(source_file)
  res = []

  if @vendor == 'GNU'
    flags = @flags.join ' '
    cmd = "#{@path} -I. #{includedirs()} #{flags} -MM #{source_file}"
    #warn "Generating dependencies for #{source_file}..\n + #{cmd}" 
    tmp = `#{cmd}`
    return [] if tmp.nil?
    tmp.sub!(/^.*\.o: /, '')
    return [] if tmp.nil?
    tmp.gsub!(/\\\n/, ' ')
    res = tmp.split(/\s+/)
  else
    throw 'Not supported -- need to use a fallback method'
  end

  res.push 'GNUmakefile'
  res
end
makefile() click to toggle source
# File lib/makeconf/compiler.rb, line 56
def makefile
  m = Makefile.new
  m.define_variable('CC', '=', @path)
  m.define_variable('LD', '=', @ld.path)
  return m
end
object_files(sources) click to toggle source

Return the intermediate object files for each source file

# File lib/makeconf/compiler.rb, line 43
def object_files(sources)
  res = []
  sources.sort.each do |s|
    res.push s.sub(/.c$/, Platform.object_extension)
  end
  res
end
quiet=(b) click to toggle source
# File lib/makeconf/compiler.rb, line 51
def quiet=(b)
  ld.quiet = b
  @quiet = b
end
rule() click to toggle source

Return the command formatted as a Makefile rule

# File lib/makeconf/compiler.rb, line 64
def rule
  [ '$(CC)', '-DHAVE_CONFIG_H', '-I.', flags, '$(CFLAGS)', '-c', @sources ].flatten.join(' ')
end
shared_library=(b) click to toggle source

Enable compiler and linker options to create a shared library

# File lib/makeconf/compiler.rb, line 158
def shared_library=(b)
  case b
  when true
    if Platform.is_windows?
      # noop
    else
      @flags.push '-fpic'
      @ld.shared_library = true
    end
  when false
    # noop
  else
    throw 'Invalid value'
  end
end
sources=(a) click to toggle source
# File lib/makeconf/compiler.rb, line 31
def sources=(a)
  a = [ a ] if a.kind_of?(String)
  throw 'Array input required' unless a.kind_of?(Array)
  @sources = a
  @ld.objects = a.map { |x| x.sub(/\.c$/, Platform.object_extension) } #FIXME: hardcoded to C
end
test_compile(code, stage = :compile) click to toggle source

Compile a test program

# File lib/makeconf/compiler.rb, line 219
def test_compile(code, stage = :compile)
  log.debug "Testing compilation of:\n" + code

  # Write the code to a temporary source file
  f = Tempfile.new(['test_compile', @extension]);
  f.print code
  f.flush

  # Run the compiler
  cc = self  # KLUDGE, testing
  cc.sources = f.path
  cc.output = f.path.sub(/\.c$/, Platform.object_extension)
  cc.quiet = ENV['MAKECONF_DEBUG'].nil?
  rc = cc.compile

  # (Optional) Run the linker
  if (rc == true and stage == :combined)
    cc.ld.quiet = true
    rc = cc.link
    File.unlink(cc.ld.output) if File.exist? cc.ld.output
  end

  # Delete the output file(s)
  File.unlink(cc.output) if File.exist? cc.output

  return rc
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.