Object
Processes source code files to produce intermediate object files.
# 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
Check if a header is available
# File lib/makeconf/compiler.rb, line 188 def check_header(path) test_compile("#include <" + path + ">") end
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
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
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
# 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
# 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
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
Run the link command
# File lib/makeconf/compiler.rb, line 208 def link throw 'Invalid linker' unless @ld.is_a?(Linker) throw 'One or more source files are required' unless @sources.length > 0 cmd = @ld.command log.debug "Invoking the linker: " + cmd rc = Platform.execute cmd log.debug "Linking complete; rc=#{rc.to_s}" rc end
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
# 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
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
# File lib/makeconf/compiler.rb, line 51 def quiet=(b) ld.quiet = b @quiet = b end
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
# 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
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
Generated with the Darkfish Rdoc Generator 2.