Compare commits

..
6 Commits
9 changed files with 118 additions and 34 deletions

No files matched your search

+16
View File
@@ -22,4 +22,20 @@ module Rscons
class BuildError < Exception
end
# Remove all generated files
def self.clean
cache = Cache.new
# remove all built files
cache.targets.each do |target|
FileUtils.rm_f(target)
end
# remove all created directories if they are empty
cache.directories.sort {|a, b| b.size <=> a.size}.each do |directory|
if (Dir.entries(directory) - ['.', '..']).empty?
Dir.rmdir(directory) rescue nil
end
end
Cache.clear
end
end
+15
View File
@@ -1,3 +1,5 @@
require "fileutils"
module Rscons
# Class to hold an object that knows how to build a certain type of file.
class Builder
@@ -16,5 +18,18 @@ module Rscons
def produces?(target, source, env)
false
end
# Check if the cache is up to date for the target and if not execute the
# build command.
# Return the name of the target or false on failure.
def standard_build(short_cmd_string, target, command, sources, env, cache)
unless cache.up_to_date?(target, command, sources)
cache.mkdir_p(File.dirname(target))
FileUtils.rm_f(target)
return false unless env.execute(short_cmd_string, command)
cache.register_build(target, command, sources)
end
target
end
end
end
+4 -9
View File
@@ -8,7 +8,7 @@ module Rscons
'AR' => 'ar',
'LIBSUFFIX' => '.a',
'ARFLAGS' => [],
'ARCOM' => ['$AR', 'rcs', '$ARFLAGS', '$TARGET', '$SOURCES']
'ARCOM' => ['$AR', 'rcs', '$ARFLAGS', '$_TARGET', '$_SOURCES']
}
end
@@ -17,16 +17,11 @@ module Rscons
objects = env.build_sources(sources, [env['OBJSUFFIX'], env['LIBSUFFIX']].flatten, cache, vars)
if objects
vars = vars.merge({
'TARGET' => target,
'SOURCES' => objects,
'_TARGET' => target,
'_SOURCES' => objects,
})
command = env.build_command(env['ARCOM'], vars)
unless cache.up_to_date?(target, command, objects)
FileUtils.rm_f(target)
return false unless env.execute("AR #{target}", command)
cache.register_build(target, command, objects)
end
target
standard_build("AR #{target}", target, command, objects, env, cache)
end
end
end
+14 -12
View File
@@ -11,8 +11,8 @@ module Rscons
'ASSUFFIX' => '.S',
'ASPPPATH' => '$CPPPATH',
'ASPPFLAGS' => '$CPPFLAGS',
'ASDEPGEN' => ['-MMD', '-MF', '$DEPFILE'],
'ASCOM' => ['$AS', '-c', '-o', '$TARGET', '$ASDEPGEN', '-I$[ASPPPATH]', '$ASPPFLAGS', '$ASFLAGS', '$SOURCES'],
'ASDEPGEN' => ['-MMD', '-MF', '$_DEPFILE'],
'ASCOM' => ['$AS', '-c', '-o', '$_TARGET', '$ASDEPGEN', '-I$[ASPPPATH]', '$ASPPFLAGS', '$ASFLAGS', '$_SOURCES'],
'CPPFLAGS' => [],
'CPPPATH' => [],
@@ -20,14 +20,14 @@ module Rscons
'CC' => 'gcc',
'CFLAGS' => [],
'CSUFFIX' => '.c',
'CCDEPGEN' => ['-MMD', '-MF', '$DEPFILE'],
'CCCOM' => ['$CC', '-c', '-o', '$TARGET', '$CCDEPGEN', '-I$[CPPPATH]', '$CPPFLAGS', '$CFLAGS', '$SOURCES'],
'CCDEPGEN' => ['-MMD', '-MF', '$_DEPFILE'],
'CCCOM' => ['$CC', '-c', '-o', '$_TARGET', '$CCDEPGEN', '-I$[CPPPATH]', '$CPPFLAGS', '$CFLAGS', '$_SOURCES'],
'CXX' => 'g++',
'CXXFLAGS' => [],
'CXXSUFFIX' => '.cc',
'CXXDEPGEN' => ['-MMD', '-MF', '$DEPFILE'],
'CXXCOM' =>['$CXX', '-c', '-o', '$TARGET', '$CXXDEPGEN', '-I$[CPPPATH]', '$CPPFLAGS', '$CXXFLAGS', '$SOURCES'],
'CXXDEPGEN' => ['-MMD', '-MF', '$_DEPFILE'],
'CXXCOM' =>['$CXX', '-c', '-o', '$_TARGET', '$CXXDEPGEN', '-I$[CPPPATH]', '$CPPFLAGS', '$CXXFLAGS', '$_SOURCES'],
}
end
@@ -40,9 +40,9 @@ module Rscons
def run(target, sources, cache, env, vars = {})
vars = vars.merge({
'TARGET' => target,
'SOURCES' => sources,
'DEPFILE' => target.set_suffix('.mf'),
'_TARGET' => target,
'_SOURCES' => sources,
'_DEPFILE' => target.set_suffix('.mf'),
})
com_prefix = if sources.first.has_suffix?(env['ASSUFFIX'])
'AS'
@@ -55,11 +55,13 @@ module Rscons
end
command = env.build_command(env["#{com_prefix}COM"], vars)
unless cache.up_to_date?(target, command, sources)
cache.mkdir_p(File.dirname(target))
FileUtils.rm_f(target)
return false unless env.execute("#{com_prefix} #{target}", command)
deps = sources
if File.exists?(vars['DEPFILE'])
deps += env.parse_makefile_deps(vars['DEPFILE'], target)
FileUtils.rm_f(vars['DEPFILE'])
if File.exists?(vars['_DEPFILE'])
deps += env.parse_makefile_deps(vars['_DEPFILE'], target)
FileUtils.rm_f(vars['_DEPFILE'])
end
cache.register_build(target, command, deps.uniq)
end
+4 -8
View File
@@ -10,7 +10,7 @@ module Rscons
'LDFLAGS' => [],
'LIBPATH' => [],
'LIBS' => [],
'LDCOM' => ['$LD', '-o', '$TARGET', '$LDFLAGS', '$SOURCES', '-L$[LIBPATH]', '-l$[LIBS]']
'LDCOM' => ['$LD', '-o', '$_TARGET', '$LDFLAGS', '$_SOURCES', '-L$[LIBPATH]', '-l$[LIBS]']
}
end
@@ -23,16 +23,12 @@ module Rscons
end.any?
ld_alt = use_cxx ? env['CXX'] : env['CC']
vars = vars.merge({
'TARGET' => target,
'SOURCES' => objects,
'_TARGET' => target,
'_SOURCES' => objects,
'LD' => env['LD'] || ld_alt,
})
command = env.build_command(env['LDCOM'], vars)
unless cache.up_to_date?(target, command, objects)
return false unless env.execute("LD #{target}", command)
cache.register_build(target, command, objects)
end
target
standard_build("LD #{target}", target, command, objects, env, cache)
end
end
end
+31
View File
@@ -36,6 +36,11 @@ module Rscons
# ]
# }
# }
# directories: {
# 'build' => true,
# 'build/one' => true,
# 'build/two' => true,
# }
# }
class Cache
#### Constants
@@ -57,6 +62,7 @@ module Rscons
def initialize
@cache = YAML.load(File.read(CACHE_FILE)) rescue {
targets: {},
directories: {},
version: VERSION,
}
@lookup_checksums = {}
@@ -132,6 +138,31 @@ module Rscons
}
end
# Return a list of targets that have been built
def targets
@cache[:targets].keys
end
# Make any needed directories and record the ones that are created for
# removal upon a "clean" operation.
def mkdir_p(path)
parts = path.split(/[\\\/]/)
(0..parts.size).each do |i|
subpath = File.join(*parts[0, i + 1])
unless File.exists?(subpath)
FileUtils.mkdir(subpath)
unless @cache[:directories].include?(subpath)
@cache[:directories][subpath] = true
end
end
end
end
# Return a list of directories which were created as a part of the build
def directories
@cache[:directories].keys
end
# Private Instance Methods
private
+4 -4
View File
@@ -11,9 +11,10 @@ module Rscons
# Create an Environment object.
# @param variables [Hash]
# The variables hash can contain both construction variables, which are
# uppercase strings (such as "CC" or "LDFLAGS"), and RScons options,
# which are lowercase symbols (such as :echo).
# The variables hash can contain construction variables, which are
# uppercase strings (such as "CC" or "LDFLAGS"), user variables, which
# are lowercase strings (such as "sources"), and RScons options, which
# are lowercase symbols (such as :echo).
# If a block is given, the Environment object is yielded to the block and
# when the block returns, the {#process} method is automatically called.
def initialize(variables = {})
@@ -95,7 +96,6 @@ module Rscons
end
build_fname.gsub!('\\', '/')
end
FileUtils.mkdir_p(File.dirname(build_fname))
build_fname
end
+1 -1
View File
@@ -1,4 +1,4 @@
module Rscons
# gem version
VERSION = "0.0.6"
VERSION = "0.0.8"
end
+29
View File
@@ -120,6 +120,35 @@ describe Rscons do
File.exists?('build/two/two.o').should be_true
end
it 'cleans built files' do
lines = test_dir('build_dir')
`./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
File.exists?('build/two/two.o').should be_false
File.exists?('build/one').should be_false
File.exists?('build/two').should be_false
File.exists?('build').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')
`./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
File.exists?('build/one/one.o').should be_false
File.exists?('build/two/two.o').should be_false
File.exists?('build/one').should be_false
File.exists?('build/two').should be_true
File.exists?('build').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')
lines.should == ['CC program.o', 'LD program']