add direct mode to Program builder - close #61

This commit is contained in:
Josh Holtrop 2019-04-14 12:35:28 -04:00
parent 9bf4b8fa96
commit ea2b1e73d1
17 changed files with 146 additions and 23 deletions

View File

@ -0,0 +1,5 @@
build do
Environment.new do |env|
env.Program("test.exe", Rscons.glob("*.c"), direct: true)
end
end

View File

@ -0,0 +1,7 @@
build do
Environment.new do |env|
lib = env.SharedLibrary("mylib", ["two.c", "three.c"], direct: true)
program = env.Program("test.exe", "main.c", "LIBS" => ["mylib"], "LIBPATH" => ["."])
env.depends(program, lib)
end
end

View File

@ -0,0 +1,7 @@
#include "two.h"
int main(int argc, char * argv[])
{
two();
return 0;
}

View File

@ -0,0 +1,7 @@
#include "three.h"
#include <stdio.h>
void three(void)
{
printf("three\n");
}

View File

@ -0,0 +1 @@
void three(void);

7
build_tests/direct/two.c Normal file
View File

@ -0,0 +1,7 @@
#include "two.h"
#include "three.h"
void two(void)
{
three();
}

1
build_tests/direct/two.h Normal file
View File

@ -0,0 +1 @@
void two(void);

View File

@ -1,2 +1,2 @@
Rscons::Builders::Object.register(command: "${ASCMD}", suffix: "${ASSUFFIX}", short_description: "Assembling")
Rscons::Builders::SharedObject.register(command: "${ASCMD}", suffix: "${ASSUFFIX}", short_description: "Assembling")
Rscons::Builders::Object.register(command: "${ASCMD}", direct_command: "${ASCMD:direct}", suffix: "${ASSUFFIX}", short_description: "Assembling")
Rscons::Builders::SharedObject.register(command: "${ASCMD}", direct_command: "${ASCMD:direct}", suffix: "${ASSUFFIX}", short_description: "Assembling")

View File

@ -1,2 +1,2 @@
Rscons::Builders::Object.register(command: "${CCCMD}", suffix: "${CSUFFIX}")
Rscons::Builders::SharedObject.register(command: "${SHCCCMD}", suffix: "${CSUFFIX}")
Rscons::Builders::Object.register(command: "${CCCMD}", direct_command: "${CCCMD:direct}", suffix: "${CSUFFIX}")
Rscons::Builders::SharedObject.register(command: "${SHCCCMD}", direct_command: "${SHCCCMD:direct}", suffix: "${CSUFFIX}")

View File

@ -1,2 +1,2 @@
Rscons::Builders::Object.register(command: "${CXXCMD}", suffix: "${CXXSUFFIX}", preferred_ld: "${CXX}")
Rscons::Builders::SharedObject.register(command: "${SHCXXCMD}", suffix: "${CXXSUFFIX}", preferred_ld: "${SHCXX}")
Rscons::Builders::Object.register(command: "${CXXCMD}", direct_command: "${CXXCMD:direct}", suffix: "${CXXSUFFIX}", preferred_ld: "${CXX}")
Rscons::Builders::SharedObject.register(command: "${SHCXXCMD}", direct_command: "${SHCXXCMD:direct}", suffix: "${CXXSUFFIX}", preferred_ld: "${SHCXX}")

View File

@ -1,2 +1,2 @@
Rscons::Builders::Object.register(command: "${DCCMD}", suffix: "${DSUFFIX}", preferred_ld: "${DC}")
Rscons::Builders::SharedObject.register(command: "${SHDCCMD}", suffix: "${DSUFFIX}", preferred_ld: "${SHDC}")
Rscons::Builders::Object.register(command: "${DCCMD}", direct_command: "${DCCMD:direct}", suffix: "${DSUFFIX}", preferred_ld: "${DC}")
Rscons::Builders::SharedObject.register(command: "${SHDCCMD}", direct_command: "${SHDCCMD:direct}", suffix: "${DSUFFIX}", preferred_ld: "${SHDC}")

View File

@ -55,7 +55,12 @@ module Rscons
unless build_params
raise "Unknown input file type: #{@sources.first.inspect}"
end
@command_template = build_params[:command]
@command_template =
if @vars[:direct]
build_params[:direct_command]
else
build_params[:command]
end
@short_description = build_params[:short_description] || "Compiling"
@preferred_ld = build_params[:preferred_ld]
end
@ -67,10 +72,21 @@ module Rscons
else
@vars["_TARGET"] = @target
@vars["_SOURCES"] = @sources
@vars["_DEPFILE"] = Rscons.set_suffix(target, env.expand_varref("${DEPFILESUFFIX}", vars))
depfilesuffix = @env.expand_varref("${DEPFILESUFFIX}", vars)
@vars["_DEPFILE"] =
if @vars[:direct]
@env.get_build_fname(target, depfilesuffix, self.class)
else
Rscons.set_suffix(target, depfilesuffix)
end
@cache.mkdir_p(File.dirname(@vars["_DEPFILE"]))
command = @env.build_command(@command_template, @vars)
@env.produces(@target, @vars["_DEPFILE"])
message = "#{@short_description} #{Util.short_format_paths(@sources)}"
if @vars[:direct]
message = "#{@short_description}/Linking #{Util.short_format_paths(@sources)} => #{@target}"
else
message = "#{@short_description} #{Util.short_format_paths(@sources)}"
end
standard_command(message, command)
end
end

View File

@ -7,12 +7,22 @@ module Rscons
include Mixins::ObjectDeps
include Mixins::Program
class << self
def new(options, *more)
unless File.basename(options[:target])["."]
options[:target] += options[:env].expand_varref("${PROGSUFFIX}", options[:vars])
end
if options[:vars][:direct]
Object.new(options, *more)
else
super
end
end
end
# Create an instance of the Builder to build a target.
def initialize(options)
super(options)
unless File.basename(@target)["."]
@target += @env.expand_varref("${PROGSUFFIX}", @vars)
end
@objects = register_object_deps(Object)
end

View File

@ -7,16 +7,26 @@ module Rscons
include Mixins::ObjectDeps
include Mixins::Program
class << self
def new(options, *more)
libprefix = options[:env].expand_varref("${SHLIBPREFIX}", options[:vars])
unless File.basename(options[:target]).start_with?(libprefix)
options[:target] = options[:target].sub!(%r{^(.*/)?([^/]+)$}, "\\1#{libprefix}\\2")
end
unless File.basename(options[:target])["."]
options[:target] += options[:env].expand_varref("${SHLIBSUFFIX}", options[:vars])
end
if options[:vars][:direct]
SharedObject.new(options, *more)
else
super
end
end
end
# Create an instance of the Builder to build a target.
def initialize(options)
super(options)
libprefix = @env.expand_varref("${SHLIBPREFIX}", @vars)
unless File.basename(@target).start_with?(libprefix)
@target = @target.sub!(%r{^(.*/)?([^/]+)$}, "\\1#{libprefix}\\2")
end
unless File.basename(@target)["."]
@target += @env.expand_varref("${SHLIBSUFFIX}", @vars)
end
@objects = register_object_deps(SharedObject)
end

View File

@ -10,6 +10,7 @@ module Rscons
"ARFLAGS" => %w[rcs],
"AS" => "${CC}",
"ASCMD" => %w[${AS} -c -o ${_TARGET} ${ASDEPGEN} ${INCPREFIX}${ASPPPATH} ${ASPPFLAGS} ${ASFLAGS} ${_SOURCES}],
"ASCMD:direct" => %w[${AS} -o ${_TARGET} ${ASDEPGEN} ${INCPREFIX}${ASPPPATH} ${ASPPFLAGS} ${ASFLAGS} ${LDFLAGS} ${_SOURCES} ${LIBDIRPREFIX}${LIBPATH} ${LIBLINKPREFIX}${LIBS}],
"ASDEPGEN" => %w[-MMD -MF ${_DEPFILE}],
"ASFLAGS" => [],
"ASPPFLAGS" => "${CPPFLAGS}",
@ -17,6 +18,7 @@ module Rscons
"ASSUFFIX" => %w[.S],
"CC" => "gcc",
"CCCMD" => %w[${CC} -c -o ${_TARGET} ${CCDEPGEN} ${INCPREFIX}${CPPPATH} ${CPPFLAGS} ${CFLAGS} ${CCFLAGS} ${_SOURCES}],
"CCCMD:direct" => %w[${CC} -o ${_TARGET} ${CCDEPGEN} ${INCPREFIX}${CPPPATH} ${CPPFLAGS} ${CFLAGS} ${CCFLAGS} ${LDFLAGS} ${_SOURCES} ${LIBDIRPREFIX}${LIBPATH} ${LIBLINKPREFIX}${LIBS}],
"CCDEPGEN" => %w[-MMD -MF ${_DEPFILE}],
"CCFLAGS" => [],
"CFLAGS" => [],
@ -28,11 +30,13 @@ module Rscons
"CSUFFIX" => %w[.c],
"CXX" => "g++",
"CXXCMD" => %w[${CXX} -c -o ${_TARGET} ${CXXDEPGEN} ${INCPREFIX}${CPPPATH} ${CPPFLAGS} ${CXXFLAGS} ${CCFLAGS} ${_SOURCES}],
"CXXCMD:direct" => %w[${CXX} -o ${_TARGET} ${CXXDEPGEN} ${INCPREFIX}${CPPPATH} ${CPPFLAGS} ${CXXFLAGS} ${CCFLAGS} ${LDFLAGS} ${_SOURCES} ${LIBDIRPREFIX}${LIBPATH} ${LIBLINKPREFIX}${LIBS}],
"CXXDEPGEN" => %w[-MMD -MF ${_DEPFILE}],
"CXXFLAGS" => [],
"CXXSUFFIX" => %w[.cc .cpp .cxx .C],
"DC" => "gdc",
"DCCMD" => %w[${DC} -c -o ${_TARGET} ${DDEPGEN} ${INCPREFIX}${D_IMPORT_PATH} ${DFLAGS} ${_SOURCES}],
"DCCMD:direct" => %w[${DC} -o ${_TARGET} ${DDEPGEN} ${INCPREFIX}${D_IMPORT_PATH} ${DFLAGS} ${LDFLAGS} ${_SOURCES} ${LIBDIRPREFIX}${LIBPATH} ${LIBLINKPREFIX}${LIBS}],
"DDEPGEN" => %w[-MMD -MF ${_DEPFILE}],
"DEPFILESUFFIX" => ".mf",
"DFLAGS" => [],
@ -58,13 +62,16 @@ module Rscons
"PROGSUFFIX" => on_windows ? ".exe" : "",
"SHCC" => "${CC}",
"SHCCCMD" => %w[${SHCC} -c -o ${_TARGET} ${CCDEPGEN} ${INCPREFIX}${CPPPATH} ${CPPFLAGS} ${SHCFLAGS} ${SHCCFLAGS} ${_SOURCES}],
"SHCCCMD:direct" => %w[${SHCC} -o ${_TARGET} ${CCDEPGEN} ${INCPREFIX}${CPPPATH} ${CPPFLAGS} ${SHCFLAGS} ${SHCCFLAGS} ${SHLDFLAGS} ${_SOURCES} ${LIBDIRPREFIX}${LIBPATH} ${LIBLINKPREFIX}${LIBS}],
"SHCCFLAGS" => %w[${CCFLAGS}] + pic_flags,
"SHCFLAGS" => %w[${CFLAGS}],
"SHCXX" => "${CXX}",
"SHCXXCMD" => %w[${SHCXX} -c -o ${_TARGET} ${CXXDEPGEN} ${INCPREFIX}${CPPPATH} ${CPPFLAGS} ${SHCXXFLAGS} ${SHCCFLAGS} ${_SOURCES}],
"SHCXXCMD:direct" => %w[${SHCXX} -o ${_TARGET} ${CXXDEPGEN} ${INCPREFIX}${CPPPATH} ${CPPFLAGS} ${SHCXXFLAGS} ${SHCCFLAGS} ${SHLDFLAGS} ${_SOURCES} ${LIBDIRPREFIX}${LIBPATH} ${LIBLINKPREFIX}${LIBS}],
"SHCXXFLAGS" => %w[${CXXFLAGS}],
"SHDC" => "gdc",
"SHDCCMD" => %w[${SHDC} -c -o ${_TARGET} ${INCPREFIX}${D_IMPORT_PATH} ${SHDFLAGS} ${_SOURCES}],
"SHDCCMD:direct" => %w[${SHDC} -o ${_TARGET} ${INCPREFIX}${D_IMPORT_PATH} ${SHDFLAGS} ${SHLDFLAGS} ${_SOURCES} ${LIBDIRPREFIX}${LIBPATH} ${LIBLINKPREFIX}${LIBS}],
"SHDFLAGS" => %w[${DFLAGS}] + pic_flags,
"SHLD" => nil,
"SHLDCMD" => %w[${SHLD} -o ${_TARGET} ${SHLDFLAGS} ${_SOURCES} ${SHLIBDIRPREFIX}${LIBPATH} ${SHLIBLINKPREFIX}${LIBS}],

View File

@ -314,7 +314,7 @@ module Rscons
end
target = expand_path(expand_varref(target))
sources = Array(sources).map do |source|
source = source.target if sources.is_a?(Builder)
source = source.target if source.is_a?(Builder)
expand_path(expand_varref(source))
end.flatten
builder = @builders[method.to_s].new(
@ -507,7 +507,7 @@ module Rscons
# @param short_description [String]
# Builder short description, printed if the echo mode is :short, or if
# there is no command.
# @param command [Array<String>]
# @param command [Array<String>, nil]
# Builder command, printed if the echo mode is :command.
#
# @return [void]

View File

@ -2079,4 +2079,49 @@ EOF
end
end
context "direct mode" do
it "allows calling Program builder in direct mode and passes all sources to the C compiler" do
test_dir("direct")
result = run_rscons(rsconscript: "c_program.rb")
expect(result.stderr).to eq ""
expect(result.stdout).to match %r{Compiling/Linking}
expect(File.exists?("test.exe")).to be_truthy
expect(`./test.exe`).to match /three/
result = run_rscons(rsconscript: "c_program.rb")
expect(result.stdout).to eq ""
three_h = File.read("three.h", mode: "rb")
File.open("three.h", "wb") do |fh|
fh.write(three_h)
fh.puts("#define FOO 42")
end
result = run_rscons(rsconscript: "c_program.rb")
expect(result.stdout).to match %r{Compiling/Linking}
end
it "allows calling SharedLibrary builder in direct mode and passes all sources to the C compiler" do
test_dir("direct")
result = run_rscons(rsconscript: "c_shared_library.rb")
expect(result.stderr).to eq ""
expect(result.stdout).to match %r{Compiling/Linking}
expect(File.exists?("test.exe")).to be_truthy
ld_library_path_prefix = (RUBY_PLATFORM =~ /mingw/ ? "" : "LD_LIBRARY_PATH=. ")
expect(`#{ld_library_path_prefix}./test.exe`).to match /three/
result = run_rscons(rsconscript: "c_shared_library.rb")
expect(result.stdout).to eq ""
three_h = File.read("three.h", mode: "rb")
File.open("three.h", "wb") do |fh|
fh.write(three_h)
fh.puts("#define FOO 42")
end
result = run_rscons(rsconscript: "c_shared_library.rb")
expect(result.stdout).to match %r{Compiling/Linking}
end
end
end