spec/build_tests_spec.rb in rscons-0.0.14 vs spec/build_tests_spec.rb in rscons-0.1.0

- old
+ new

@@ -1,49 +1,35 @@ require 'fileutils' describe Rscons do + BUILD_TEST_RUN_DIR = "build_test_run" + before(:all) do - FileUtils.rm_rf('build_tests_run') + FileUtils.rm_rf(BUILD_TEST_RUN_DIR) @owd = Dir.pwd end + before(:each) do + @output = "" + $stdout.stub(:write) do |content| + @output += content + end + $stderr.stub(:write) do |content| + @output += content + end + end + after(:each) do Dir.chdir(@owd) - FileUtils.rm_rf('build_tests_run') + FileUtils.rm_rf(BUILD_TEST_RUN_DIR) end - def build_testdir(build_script = "build.rb") - if File.exists?(build_script) - build_rb = File.read(build_script) - File.open(build_script, "w") do |fh| - fh.puts(<<EOF + build_rb) -require "simplecov" - -SimpleCov.start do - root("#{@owd}") - command_name("build_test_#{@build_test_name}") - add_filter("spec") -end - -require "rscons" -EOF - end - IO.popen(%{ruby -I #{@owd}/lib #{build_script}}) do |io| - io.readlines.reject do |line| - line =~ /^Coverage report/ - end - end.map(&:strip) - end + def test_dir(build_test_directory) + FileUtils.cp_r("build_tests/#{build_test_directory}", BUILD_TEST_RUN_DIR) + Dir.chdir(BUILD_TEST_RUN_DIR) end - def test_dir(build_test_directory, build_script = "build.rb") - @build_test_name = build_test_directory - FileUtils.cp_r("build_tests/#{build_test_directory}", 'build_tests_run') - Dir.chdir("build_tests_run") - build_testdir(build_script) - end - def file_sub(fname) contents = File.read(fname) replaced = '' contents.each_line do |line| replaced += yield(line) @@ -51,93 +37,136 @@ File.open(fname, 'w') do |fh| fh.write(replaced) end end + def lines + @output.lines.map(&:rstrip).tap do |v| + @output = "" + end + end + ########################################################################### # Tests ########################################################################### it 'builds a C program with one source file' do test_dir('simple') + Rscons::Environment.new do |env| + env.Program('simple', Dir['*.c']) + end File.exists?('simple.o').should be_true `./simple`.should == "This is a simple C program\n" end it 'prints commands as they are executed' do - lines = test_dir('simple') + test_dir('simple') + Rscons::Environment.new(echo: :command) do |env| + env["LD"] = "gcc" + env.Program('simple', Dir['*.c']) + end lines.should == [ 'gcc -c -o simple.o -MMD -MF simple.mf simple.c', 'gcc -o simple simple.o', ] end it 'prints short representations of the commands being executed' do - lines = test_dir('header') + test_dir('header') + Rscons::Environment.new do |env| + env.Program('header', Dir['*.c']) + end lines.should == [ 'CC header.o', 'LD header', ] end it 'builds a C program with one source file and one header file' do test_dir('header') + Rscons::Environment.new do |env| + env.Program('header', Dir['*.c']) + end File.exists?('header.o').should be_true `./header`.should == "The value is 2\n" end it 'rebuilds a C module when a header it depends on changes' do test_dir('header') + env = Rscons::Environment.new do |env| + env.Program('header', Dir['*.c']) + end `./header`.should == "The value is 2\n" file_sub('header.h') {|line| line.sub(/2/, '5')} - build_testdir + env.process `./header`.should == "The value is 5\n" end it 'does not rebuild a C module when its dependencies have not changed' do - lines = test_dir('header') + test_dir('header') + env = Rscons::Environment.new do |env| + env.Program('header', Dir['*.c']) + end `./header`.should == "The value is 2\n" lines.should == [ 'CC header.o', 'LD header', ] - lines = build_testdir + env.process lines.should == [] end it "does not rebuild a C module when only the file's timestampe has changed" do - lines = test_dir('header') + test_dir('header') + env = Rscons::Environment.new do |env| + env.Program('header', Dir['*.c']) + end `./header`.should == "The value is 2\n" lines.should == [ 'CC header.o', 'LD header', ] file_sub('header.c') {|line| line} - lines = build_testdir + env.process lines.should == [] end it 're-links a program when the link flags have changed' do - lines = test_dir('simple') + test_dir('simple') + Rscons::Environment.new(echo: :command) do |env| + env.Program('simple', Dir['*.c']) + end lines.should == [ 'gcc -c -o simple.o -MMD -MF simple.mf simple.c', 'gcc -o simple simple.o', ] - file_sub('build.rb') {|line| line.sub(/.*CHANGE.FLAGS.*/, ' env["LIBS"] += ["c"]')} - lines = build_testdir + Rscons::Environment.new(echo: :command) do |env| + env["LIBS"] += ["c"] + env.Program('simple', Dir['*.c']) + end lines.should == ['gcc -o simple simple.o -lc'] end it 'builds object files in a different build directory' do - lines = test_dir('build_dir') + test_dir('build_dir') + Rscons::Environment.new do |env| + env.append('CPPPATH' => Dir['src/**/*/']) + env.build_dir(%r{^src/([^/]+)/}, 'build_\\1/') + env.Program('build_dir', Dir['src/**/*.c']) + end `./build_dir`.should == "Hello from two()\n" File.exists?('build_one/one.o').should be_true File.exists?('build_two/two.o').should be_true end it 'cleans built files' do - lines = test_dir('build_dir') + test_dir('build_dir') + Rscons::Environment.new do |env| + env.append('CPPPATH' => Dir['src/**/*/']) + env.build_dir(%r{^src/([^/]+)/}, 'build_\\1/') + env.Program('build_dir', Dir['src/**/*.c']) + end `./build_dir`.should == "Hello from two()\n" File.exists?('build_one/one.o').should be_true File.exists?('build_two/two.o').should be_true Rscons.clean File.exists?('build_one/one.o').should be_false @@ -146,11 +175,16 @@ File.exists?('build_two').should be_false File.exists?('src/one/one.c').should be_true end it 'does not clean created directories if other non-rscons-generated files reside there' do - lines = test_dir('build_dir') + test_dir('build_dir') + Rscons::Environment.new do |env| + env.append('CPPPATH' => Dir['src/**/*/']) + env.build_dir(%r{^src/([^/]+)/}, 'build_\\1/') + env.Program('build_dir', Dir['src/**/*.c']) + end `./build_dir`.should == "Hello from two()\n" File.exists?('build_one/one.o').should be_true File.exists?('build_two/two.o').should be_true File.open('build_two/tmp', 'w') { |fh| fh.puts "dum" } Rscons.clean @@ -160,45 +194,86 @@ File.exists?('build_two').should be_true File.exists?('src/one/one.c').should be_true end it 'allows Ruby classes as custom builders to be used to construct files' do - lines = test_dir('custom_builder') + test_dir('custom_builder') + class MySource < Rscons::Builder + def run(target, sources, cache, env, vars = {}) + File.open(target, 'w') do |fh| + fh.puts <<EOF + #define THE_VALUE 5678 +EOF + end + target + end + end + + Rscons::Environment.new do |env| + env.add_builder(MySource.new) + env.MySource('inc.h', []) + env.Program('program', Dir['*.c']) + end + lines.should == ['CC program.o', 'LD program'] File.exists?('inc.h').should be_true `./program`.should == "The value is 5678\n" end it 'allows cloning Environment objects' do - lines = test_dir('clone_env') + test_dir('clone_env') + + debug = Rscons::Environment.new(echo: :command) do |env| + env.build_dir('src', 'debug') + env['CFLAGS'] = '-O2' + env['CPPFLAGS'] = '-DSTRING="Debug Version"' + env.Program('program-debug', Dir['src/*.c']) + end + + release = debug.clone('CPPFLAGS' => '-DSTRING="Release Version"') do |env| + env.build_dir('src', 'release') + env.Program('program-release', Dir['src/*.c']) + end + lines.should == [ %q{gcc -c -o debug/program.o -MMD -MF debug/program.mf '-DSTRING="Debug Version"' -O2 src/program.c}, %q{gcc -o program-debug debug/program.o}, %q{gcc -c -o release/program.o -MMD -MF release/program.mf '-DSTRING="Release Version"' -O2 src/program.c}, %q{gcc -o program-release release/program.o}, ] end it 'builds a C++ program with one source file' do test_dir('simple_cc') + Rscons::Environment.new do |env| + env.Program('simple', Dir['*.cc']) + end File.exists?('simple.o').should be_true `./simple`.should == "This is a simple C++ program\n" end it 'allows overriding construction variables for individual builder calls' do - lines = test_dir('two_sources') + test_dir('two_sources') + Rscons::Environment.new(echo: :command) do |env| + env.Object("one.o", "one.c", 'CPPFLAGS' => ['-DONE']) + env.Program('two_sources', ['one.o', 'two.c']) + end lines.should == [ 'gcc -c -o one.o -MMD -MF one.mf -DONE one.c', 'gcc -c -o two.o -MMD -MF two.mf two.c', 'gcc -o two_sources one.o two.o', ] File.exists?('two_sources').should be_true `./two_sources`.should == "This is a C program with two sources.\n" end it 'builds a static library archive' do - lines = test_dir('library') + test_dir('library') + Rscons::Environment.new(echo: :command) do |env| + env.Program('library', ['lib.a', 'three.c']) + env.Library("lib.a", ['one.c', 'two.c'], 'CPPFLAGS' => ['-Dmake_lib']) + end lines.should == [ 'gcc -c -o one.o -MMD -MF one.mf -Dmake_lib one.c', 'gcc -c -o two.o -MMD -MF two.mf -Dmake_lib two.c', 'ar rcs lib.a one.o two.o', 'gcc -c -o three.o -MMD -MF three.mf three.c', @@ -206,15 +281,41 @@ ] File.exists?('library').should be_true `ar t lib.a`.should == "one.o\ntwo.o\n" end - it 'supports tweakers to override construction variables' do - lines = test_dir("build_dir", "tweaker_build.rb") - `./tweaker`.should == "Hello from two()\n" + it 'supports build hooks to override construction variables' do + test_dir("build_dir") + Rscons::Environment.new(echo: :command) do |env| + env.append('CPPPATH' => Dir['src/**/*/']) + env.build_dir(%r{^src/([^/]+)/}, 'build_\\1/') + env.add_build_hook do |build_op| + if build_op[:target] =~ %r{build_one/.*\.o} + build_op[:vars]["CFLAGS"] << "-O1" + elsif build_op[:target] =~ %r{build_two/.*\.o} + build_op[:vars]["CFLAGS"] << "-O2" + end + end + env.Program('build_hook', Dir['src/**/*.c']) + end + `./build_hook`.should == "Hello from two()\n" lines.should =~ [ 'gcc -c -o build_one/one.o -MMD -MF build_one/one.mf -Isrc/one/ -Isrc/two/ -O1 src/one/one.c', 'gcc -c -o build_two/two.o -MMD -MF build_two/two.mf -Isrc/one/ -Isrc/two/ -O2 src/two/two.c', - 'gcc -o tweaker build_one/one.o build_two/two.o', + 'gcc -o build_hook build_one/one.o build_two/two.o', ] + end + + unless ENV["omit_gdc_tests"] + it "supports building D sources" do + test_dir("d") + Rscons::Environment.new(echo: :command) do |env| + env.Program("hello-d", Dir["*.d"]) + end + lines.should == [ + "gdc -c -o main.o main.d", + "gdc -o hello-d main.o", + ] + `./hello-d`.rstrip.should == "Hello from D!" + end end end