From d424facf7f1076e200f9c75b99720b5d9d20477a Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Tue, 15 Apr 2014 15:21:55 -0400 Subject: [PATCH] Add Preprocess and Disassemble builders --- lib/rscons.rb | 4 ++++ lib/rscons/builders/disassemble.rb | 25 +++++++++++++++++++++++++ lib/rscons/builders/library.rb | 2 +- lib/rscons/builders/preprocess.rb | 25 +++++++++++++++++++++++++ lib/rscons/builders/program.rb | 2 +- spec/build_tests_spec.rb | 30 ++++++++++++++++++++++++++++++ 6 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 lib/rscons/builders/disassemble.rb create mode 100644 lib/rscons/builders/preprocess.rb diff --git a/lib/rscons.rb b/lib/rscons.rb index 81d6135..a12a372 100644 --- a/lib/rscons.rb +++ b/lib/rscons.rb @@ -6,16 +6,20 @@ require_relative "rscons/version" # default builders require_relative "rscons/builders/cfile" +require_relative "rscons/builders/disassemble" require_relative "rscons/builders/library" require_relative "rscons/builders/object" +require_relative "rscons/builders/preprocess" require_relative "rscons/builders/program" # Namespace module for rscons classes module Rscons DEFAULT_BUILDERS = [ :CFile, + :Disassemble, :Library, :Object, + :Preprocess, :Program, ] diff --git a/lib/rscons/builders/disassemble.rb b/lib/rscons/builders/disassemble.rb new file mode 100644 index 0000000..cd85b0a --- /dev/null +++ b/lib/rscons/builders/disassemble.rb @@ -0,0 +1,25 @@ +module Rscons + module Builders + # The Disassemble builder produces a disassembly listing of a source file. + class Disassemble < Builder + def default_variables(env) + { + "OBJDUMP" => "objdump", + "DISASM_CMD" => ["${OBJDUMP}", "${DISASM_FLAGS}", "${_SOURCES}"], + "DISASM_FLAGS" => ["--disassemble", "--source"], + } + end + + def run(target, sources, cache, env, vars) + vars = vars.merge("_SOURCES" => sources) + command = env.build_command(env["DISASM_CMD"], vars) + unless cache.up_to_date?(target, command, sources, env) + cache.mkdir_p(File.dirname(target)) + return false unless env.execute("Disassemble #{target}", command, options: {out: target}) + cache.register_build(target, command, sources, env) + end + target + end + end + end +end diff --git a/lib/rscons/builders/library.rb b/lib/rscons/builders/library.rb index 867b507..4a397fc 100644 --- a/lib/rscons/builders/library.rb +++ b/lib/rscons/builders/library.rb @@ -1,7 +1,7 @@ module Rscons module Builders # A default Rscons builder that produces a static library archive. - class Rscons::Builders::Library < Rscons::Builder + class Library < Builder def default_variables(env) { 'AR' => 'ar', diff --git a/lib/rscons/builders/preprocess.rb b/lib/rscons/builders/preprocess.rb new file mode 100644 index 0000000..a1f7f7e --- /dev/null +++ b/lib/rscons/builders/preprocess.rb @@ -0,0 +1,25 @@ +module Rscons + module Builders + # The Preprocess builder invokes the C preprocessor + class Preprocess < Builder + def default_variables(env) + { + "CPP_CMD" => ["${_PREPROCESS_CC}", "-E", "-o", "${_TARGET}", "-I${CPPPATH}", "${CPPFLAGS}", "${CFLAGS}", "${_SOURCES}"], + } + end + + def run(target, sources, cache, env, vars) + pp_cc = if sources.find {|s| s.end_with?(*env["CXXSUFFIX"])} + env["CXX"] + else + env["CC"] + end + vars = vars.merge("_PREPROCESS_CC" => pp_cc, + "_TARGET" => target, + "_SOURCES" => sources) + command = env.build_command(env["CPP_CMD"], vars) + standard_build("Preprocess #{target}", target, command, sources, env, cache) + end + end + end +end diff --git a/lib/rscons/builders/program.rb b/lib/rscons/builders/program.rb index 481c1f5..86f72fb 100644 --- a/lib/rscons/builders/program.rb +++ b/lib/rscons/builders/program.rb @@ -2,7 +2,7 @@ module Rscons module Builders # A default Rscons builder that knows how to link object files into an # executable program. - class Rscons::Builders::Program < Rscons::Builder + class Program < Builder def default_variables(env) { 'LD' => nil, diff --git a/spec/build_tests_spec.rb b/spec/build_tests_spec.rb index a83a731..6783cea 100644 --- a/spec/build_tests_spec.rb +++ b/spec/build_tests_spec.rb @@ -454,4 +454,34 @@ EOF `./hello-d`.rstrip.should == "Hello from D!" end end + + it "supports disassembling object files" do + test_dir("simple") + Rscons::Environment.new do |env| + env.Object("simple.o", "simple.c") + env.Disassemble("simple.txt", "simple.o") + end + File.exists?("simple.txt").should be_true + File.read("simple.txt").should =~ /Disassembly of section .text:/ + end + + it "supports preprocessing C sources" do + test_dir("simple") + Rscons::Environment.new do |env| + env.Preprocess("simplepp.c", "simple.c") + env.Program("simple", "simplepp.c") + end + File.read("simplepp.c").should =~ /# \d+ "simple.c"/ + `./simple`.should == "This is a simple C program\n" + end + + it "supports preprocessing C++ sources" do + test_dir("simple_cc") + Rscons::Environment.new do |env| + env.Preprocess("simplepp.cc", "simple.cc") + env.Program("simple", "simplepp.cc") + end + File.read("simplepp.cc").should =~ /# \d+ "simple.cc"/ + `./simple`.should == "This is a simple C++ program\n" + end end