Class: Compiler
- Inherits:
-
Object
- Object
- Compiler
- Defined in:
- lib/makeconf/compiler.rb
Overview
Processes source code files to produce intermediate object files.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#ld ⇒ Object
readonly
Returns the value of attribute ld.
-
#output ⇒ Object
Returns the value of attribute output.
-
#sysroot ⇒ Object
Returns the value of attribute sysroot.
Instance Method Summary collapse
- #cflags ⇒ Object
-
#check_header(path) ⇒ Object
Check if a header is available.
- #clone ⇒ Object
-
#command ⇒ Object
Return the complete command line to compile an object.
-
#compile ⇒ Object
Run the compilation command.
-
#default_flags ⇒ Object
Try to determine a usable default set of compiler flags.
- #flags ⇒ Object
- #flags=(s) ⇒ Object
-
#has_option(opt) ⇒ Object
Test if the compiler supports a command line option.
-
#initialize(language, extension) ⇒ Compiler
constructor
A new instance of Compiler.
-
#link ⇒ Object
Run the link command.
- #makefile ⇒ Object
-
#object_files(sources) ⇒ Object
Return the intermediate object files for each source file.
- #quiet=(b) ⇒ Object
-
#rule ⇒ Object
Return the command formatted as a Makefile rule.
-
#shared_library=(b) ⇒ Object
Enable compiler and linker options to create a shared library.
- #sources=(a) ⇒ Object
-
#test_compile(code, stage = :compile) ⇒ Object
Compile a test program.
-
#test_link(code) ⇒ Object
Compile and link a test program.
Constructor Details
#initialize(language, extension) ⇒ Compiler
Returns a new instance of Compiler.
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
# 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 @sysroot = nil @quiet = false # If true, output will be suppressed # 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 |
Instance Attribute Details
#ld ⇒ Object (readonly)
Returns the value of attribute ld.
8 9 10 |
# File 'lib/makeconf/compiler.rb', line 8 def ld @ld end |
#output ⇒ Object
Returns the value of attribute output.
7 8 9 |
# File 'lib/makeconf/compiler.rb', line 7 def output @output end |
#sysroot ⇒ Object
Returns the value of attribute sysroot.
7 8 9 |
# File 'lib/makeconf/compiler.rb', line 7 def sysroot @sysroot end |
Instance Method Details
#cflags ⇒ Object
36 37 38 |
# File 'lib/makeconf/compiler.rb', line 36 def cflags @flags end |
#check_header(path) ⇒ Object
Check if a header is available
183 184 185 |
# File 'lib/makeconf/compiler.rb', line 183 def check_header(path) test_compile("#include <" + path + ">") end |
#clone ⇒ Object
40 41 42 |
# File 'lib/makeconf/compiler.rb', line 40 def clone Marshal.load(Marshal.dump(self)) end |
#command ⇒ Object
Return the complete command line to compile an object
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/makeconf/compiler.rb', line 71 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.clone # 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', flags, '-c', @sources ].flatten.join(' ') cmd += Platform.dev_null if @quiet log.debug "Compiler command: #{cmd}" cmd end |
#compile ⇒ Object
Run the compilation command
193 194 195 196 197 198 199 200 |
# File 'lib/makeconf/compiler.rb', line 193 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 ⇒ Object
Try to determine a usable default set of compiler flags
244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/makeconf/compiler.rb', line 244 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 ⇒ Object
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/makeconf/compiler.rb', line 106 def flags tok = @flags # KLUDGE: remove things that CL.EXE doesn't understand # if @path.match(/cl.exe$/i) # cflags += ' ' # cflags.gsub!(/ -Wall /, ' ') # /Wall generates too much noise # cflags.gsub!(/ -Werror /, ' ') # Could use /WX here # cflags.gsub!(/ -W /, ' ') # cflags.gsub!(/ -Wno-.*? /, ' ') # cflags.gsub!(/ -Wextra /, ' ') # cflags.gsub!(/ -fpic /, ' ') # cflags.gsub!(/ -std=.*? /, ' ') # cflags.gsub!(/ -pedantic /, ' ') # 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' unless is_mingw? end end tok.push '--sysroot=' + @sysroot unless @sysroot.nil? tok.join(' ') end |
#flags=(s) ⇒ Object
147 148 149 150 |
# File 'lib/makeconf/compiler.rb', line 147 def flags=(s) @flags = s @flags = @flags.split(' ') if @flags.kind_of?(String) end |
#has_option(opt) ⇒ Object
Test if the compiler supports a command line option
170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/makeconf/compiler.rb', line 170 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 |
#link ⇒ Object
Run the link command
203 204 205 206 207 208 209 210 211 |
# File 'lib/makeconf/compiler.rb', line 203 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 |
#makefile ⇒ Object
58 59 60 61 62 63 |
# File 'lib/makeconf/compiler.rb', line 58 def makefile m = Makefile.new m.define_variable('CC', ':=', @path) m.define_variable('LD', ':=', @ld.path) return m end |
#object_files(sources) ⇒ Object
Return the intermediate object files for each source file
45 46 47 48 49 50 51 |
# File 'lib/makeconf/compiler.rb', line 45 def object_files(sources) res = [] sources.sort.each do |s| res.push s.sub(/.c$/, Platform.object_extension) end res end |
#quiet=(b) ⇒ Object
53 54 55 56 |
# File 'lib/makeconf/compiler.rb', line 53 def quiet=(b) ld.quiet = b @quiet = b end |
#rule ⇒ Object
Return the command formatted as a Makefile rule
66 67 68 |
# File 'lib/makeconf/compiler.rb', line 66 def rule [ '$(CC)', '-DHAVE_CONFIG_H', flags, '$(CFLAGS)', '-c', @sources ].flatten.join(' ') end |
#shared_library=(b) ⇒ Object
Enable compiler and linker options to create a shared library
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/makeconf/compiler.rb', line 153 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) ⇒ Object
29 30 31 32 33 34 |
# File 'lib/makeconf/compiler.rb', line 29 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$/, '.o') } #FIXME: hardcoded to C end |
#test_compile(code, stage = :compile) ⇒ Object
Compile a test program
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
# File 'lib/makeconf/compiler.rb', line 214 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.clone cc.sources = f.path cc.output = f.path.sub(/\.c$/, '.o') cc.quiet = true 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 |
#test_link(code) ⇒ Object
Compile and link a test program
188 189 190 |
# File 'lib/makeconf/compiler.rb', line 188 def test_link(code) test_compile(code, :combined) end |