Compare commits

...
11 Commits
15 changed files with 250 additions and 62 deletions

No files matched your search

+22 -16
View File
@@ -1,32 +1,38 @@
GEM
remote: https://rubygems.org/
specs:
diff-lcs (1.4.4)
diff-lcs (1.5.0)
docile (1.1.5)
json (2.5.1)
json (2.6.1)
psych (4.0.3)
stringio
rake (13.0.6)
rdoc (6.3.2)
rdoc (6.4.0)
psych (>= 4.0.0)
redcarpet (3.5.1)
rspec (3.10.0)
rspec-core (~> 3.10.0)
rspec-expectations (~> 3.10.0)
rspec-mocks (~> 3.10.0)
rspec-core (3.10.1)
rspec-support (~> 3.10.0)
rspec-expectations (3.10.1)
rspec (3.11.0)
rspec-core (~> 3.11.0)
rspec-expectations (~> 3.11.0)
rspec-mocks (~> 3.11.0)
rspec-core (3.11.0)
rspec-support (~> 3.11.0)
rspec-expectations (3.11.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-mocks (3.10.2)
rspec-support (~> 3.11.0)
rspec-mocks (3.11.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-support (3.10.2)
rspec-support (~> 3.11.0)
rspec-support (3.11.0)
simplecov (0.15.1)
docile (~> 1.1.0)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.2)
stringio (3.0.1)
syntax (1.2.2)
yard (0.9.26)
webrick (1.7.0)
yard (0.9.27)
webrick (~> 1.7.0)
PLATFORMS
ruby
@@ -43,4 +49,4 @@ DEPENDENCIES
yard
BUNDLED WITH
2.1.4
2.2.31
+5 -2
View File
@@ -1,4 +1,7 @@
env(echo: :command) do |env|
env.Program('library.exe', ['lib.a', 'three.c'])
env.Library("lib.a", ['one.c', 'two.c'], 'CPPFLAGS' => ['-Dmake_lib'])
env["LIBS"] << "mylib"
env["LIBPATH"] << "."
env.Program("library.exe", "one.c")
env.depends("library.exe", "libmylib.a")
env.Library("libmylib.a", ["two.c", "three.c"], "CPPFLAGS" => ["-Dmake_lib"])
end
+5 -2
View File
@@ -1,8 +1,11 @@
#include <stdio.h>
#ifdef make_lib
void two();
void three();
int main(int argc, char *argv[])
{
two();
printf("Library\n");
three();
}
#endif
+1 -1
View File
@@ -1,4 +1,4 @@
env(echo: :command) do |env|
env["ARCMD"] = %w[ar rcf ${_TARGET} ${_SOURCES}]
env["ARCMD"] = %w[ar rc ${_TARGET} ${_SOURCES}]
env.Library("lib.a", glob("*.c"))
end
+3
View File
@@ -0,0 +1,3 @@
void three(void)
{
}
+3
View File
@@ -0,0 +1,3 @@
void two(void)
{
}
+5
View File
@@ -0,0 +1,5 @@
default do
env do |env|
env.Program('simple.exe', Dir['*.c'])
end
end
+1
View File
@@ -1,5 +1,6 @@
env(echo: :command) do |env|
env["LD"] = "gcc"
mkdir_p("libdir")
env["LIBPATH"] += ["libdir"]
env.Program('simple.exe', Dir['*.c'])
end
+3
View File
@@ -1,3 +1,6 @@
#ifdef ONE
#error ONE should not be defined
#endif
void two(void)
{
}
+112 -2
View File
@@ -787,7 +787,9 @@ Building target files is accomplished by using Environments.
Environments can be created at the top level of the build script, or from
within a task action block.
Environments are created with the `env` build script method.
Environments are created with the
[`env`](../yard/Rscons/Script/GlobalDsl.html#env-instance_method) build script
method.
Here is an example build script that creates an Environment and registers a
Program build target:
@@ -863,7 +865,7 @@ It also instructs the linker to link against the `m` library.
* uppercase strings - the default construction variables that Rscons uses
* strings beginning with "_" - set and used internally by builders
* strings with a ":" as "#{task_name}:#{parameter_name}" - set to task parameter values
* lowercase strings with a ":" as "#{task_name}:#{parameter_name}" - set to task parameter values
* symbols, lowercase strings - reserved as user-defined construction variables
###> Builders
@@ -1336,6 +1338,7 @@ The command `./rscons --variants kde,release` would build just "prog-kde-release
* `clean` (see ${#Clean Task})
* `configure` (see ${#Configure Task})
* `default` (see ${#Default Task})
* `download` (see ${#Downloading Files: The download Method})
* `distclean` (see ${#Distclean Task})
* `glob` (see ${#Finding Files: The glob Method})
* `install` (see ${#Install Task})
@@ -1401,6 +1404,31 @@ end
This example would build the `mytests` executable from all `.cc` source files
found recursively under the `src` or `test` directory.
###> Downloading Files: The download Method
The [`download`](../yard/Rscons/Script/GlobalDsl.html#download-instance_method)
method can be used to download a file from a given URL.
Example use:
```ruby
default do
download "https://ftp.gnu.org/gnu/gcc/gcc-#{gcc_version}/gcc-#{gcc_version}.tar.xz",
"#{build_dir}/gcc-#{gcc_version}.tar.xz",
sha256_sum: gcc_checksum
end
```
The `download` method downloads the file specified by the URL in the first
parameter, and writes it to the local file specified by the second parameter.
If the `:sha256sum` option is given, this causes two changes to the default
behavior:
* If Rscons finds the local file and it already has this checksum, then the
file will not be downloaded again.
* After downloading, Rscons verifies that the checksum matches what is given
and exits with an error if it does not.
###> PATH Management
`rscons` provides methods for management of the `PATH` environment variable.
@@ -1908,6 +1936,88 @@ env do |env|
end
```
### Example: GCC Cross Compiler
```ruby
binutils_version = "2.35"
binutils_checksum = "1b11659fb49e20e18db460d44485f09442c8c56d5df165de9461eb09c8302f85"
gcc_version = "10.2.0"
gcc_checksum = "b8dd4368bb9c7f0b98188317ee0254dd8cc99d1e3a18d0ff146c855fe16c1d8c"
install_path = File.expand_path("i686-elf-gcc")
target = "i686-elf"
path_prepend "#{install_path}/bin"
configure do
check_c_compiler "gcc"
check_program "make"
check_program "bison"
check_program "flex"
check_program "texi2any", on_fail: "Install the texinfo package"
check_program "wget"
check_lib "gmp", on_fail: "Install the libgmp-dev package"
check_lib "mpc", on_fail: "Install the libmpc-dev package"
check_lib "mpfr", on_fail: "Install the libmpfr-dev package"
end
default do
unless Dir.exist?(install_path)
# Download archives.
download "https://ftp.gnu.org/gnu/binutils/binutils-#{binutils_version}.tar.xz",
"#{build_dir}/binutils-#{binutils_version}.tar.xz",
sha256sum: binutils_checksum
download "https://ftp.gnu.org/gnu/gcc/gcc-#{gcc_version}/gcc-#{gcc_version}.tar.xz",
"#{build_dir}/gcc-#{gcc_version}.tar.xz",
sha256sum: gcc_checksum
# Extract archives.
sh "tar", "xJf", "binutils-#{binutils_version}.tar.xz",
chdir: build_dir
sh "tar", "xJf", "gcc-#{gcc_version}.tar.xz",
chdir: build_dir
# Build binutils.
rm_rf "#{build_dir}/build-binutils"
mkdir_p "#{build_dir}/build-binutils"
cd "#{build_dir}/build-binutils" do
sh %W[../binutils-#{binutils_version}/configure
--target=#{target} --prefix=#{install_path} --with-sysroot --disable-nls
--disable-werror]
sh "make"
sh "make install"
end
# Build gcc.
rm_rf "#{build_dir}/build-gcc"
mkdir_p "#{build_dir}/build-gcc"
cd "#{build_dir}/build-gcc" do
sh %W[../gcc-#{gcc_version}/configure
--target=#{target} --prefix=#{install_path} --disable-nls
--enable-languages=c,c++ --without-headers]
sh "make all-gcc"
sh "make all-target-libgcc"
sh "make install-gcc"
sh "make install-target-libgcc"
end
end
end
clean do
rm_f "#{build_dir}/binutils-#{binutils_version}.tar.xz"
rm_rf "#{build_dir}/binutils-#{binutils_version}"
rm_rf "#{build_dir}/build-binutils"
rm_f "#{build_dir}/gcc-#{gcc_version}.tar.xz"
rm_rf "#{build_dir}/gcc-#{gcc_version}"
rm_rf "#{build_dir}/build-gcc"
end
distclean do
rm_rf install_path
end
```
##> ./configure && make
You can make your Rscons-based project more familiar to users of
+11 -3
View File
@@ -42,6 +42,16 @@ module Rscons
@variant_groups = []
end
# Return if Rscons is in the task execution phase.
#
# @api private
#
# @return [Boolean]
# If Rscons is in the task execution phase.
def task_execution_phase?
@task_execution_phase
end
# Run the application.
#
# Execute user-specified tasks.
@@ -77,6 +87,7 @@ module Rscons
return 0
end
apply_task_params(tasks_and_params)
@task_execution_phase = true
if tasks_and_params.empty?
check_process_environments
if Task.tasks["default"]
@@ -194,9 +205,6 @@ module Rscons
#
# @api private
#
# @param options [Hash]
# Options.
#
# @return [void]
def configure
co = ConfigureOp.new(@script)
-18
View File
@@ -72,24 +72,6 @@ module Rscons
attr_reader :name
# Create an Environment object.
#
# @overload initialize(name, options)
# @overload initialize(options)
#
# @param name [String]
# Environment name. This determines the folder name used to store all
# environment build files under the top-level build directory.
# @param options [Hash]
# @option options [Symbol] :echo
# :command, :short, or :off (default :short)
# @option options [Boolean] :exclude_builders
# Whether to omit adding default builders (default false)
# @option options [String, Array<String>] :use
# Use flag(s). If specified, any configuration flags which were saved
# with a corresponding `:use` value will be applied to this Environment.
#
# 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(*args, &block)
@id = self.class.get_id
if args.first.is_a?(String)
+41 -1
View File
@@ -102,9 +102,49 @@ module Rscons
end
# Create an environment.
#
# @overload env(name, options)
# @param name [String]
# Environment name. This determines the folder name used to store all
# environment build files under the top-level build directory.
# @param options [Hash]
# @option options [Symbol] :echo
# :command, :short, or :off (default :short)
# @option options [Boolean] :exclude_builders
# Whether to omit adding default builders (default false)
# @option options [String, Array<String>] :use
# Use flag(s). If specified, any configuration flags which were saved
# with a corresponding `:use` value will be applied to this
# Environment.
#
# @overload env(options)
# @param options [Hash]
# @option options [Symbol] :echo
# :command, :short, or :off (default :short)
# @option options [Boolean] :exclude_builders
# Whether to omit adding default builders (default false)
# @option options [String, Array<String>] :use
# Use flag(s). If specified, any configuration flags which were saved
# with a corresponding `:use` value will be applied to this
# Environment.
#
# If a block is given it is immediately executed and passed the newly
# created Environment object as an argument.
# If the Environment is created in task context, the +process+ method is
# immediately called.
# Otherwise, the Environment is not processed until the task execution
# phase.
#
# @yield [env]
# @yieldparam env [Environment]
# The created environment.
def env(*args, &block)
Rscons.application.check_configure
Environment.new(*args, &block)
e = Environment.new(*args, &block)
if Rscons.application.task_execution_phase?
e.process
end
e
end
# Construct a task parameter.
+1 -1
View File
@@ -1,4 +1,4 @@
module Rscons
# Project version.
VERSION = "2.3.0"
VERSION = "3.0.0"
end
+37 -16
View File
@@ -195,6 +195,14 @@ EOF
expect(nr(`./simple.exe`)).to eq "This is a simple C program\n"
end
it "processes the environment when created within a task" do
test_dir("simple")
result = run_rscons(args: %w[-f env_in_task.rb])
expect(result.stderr).to eq ""
expect(File.exists?("build/e.1/simple.c.o")).to be_truthy
expect(nr(`./simple.exe`)).to eq "This is a simple C program\n"
end
it "uses the build directory specified with -b" do
test_dir("simple")
result = run_rscons(args: %w[-b b])
@@ -350,7 +358,7 @@ EOF
expect(result.stderr).to match /Could not find a registered build target "foo"/
end
context "clean operation" do
context "clean task" do
it 'cleans built files' do
test_dir("simple")
result = run_rscons
@@ -364,6 +372,17 @@ EOF
expect(File.exists?('simple.c')).to be_truthy
end
it "does not process environments" do
test_dir("simple")
result = run_rscons(args: %w[clean])
expect(result.stderr).to eq ""
expect(File.exists?('build/e.1/simple.c.o')).to be_falsey
expect(File.exists?('build/e.1')).to be_falsey
expect(File.exists?('simple.exe')).to be_falsey
expect(File.exists?('simple.c')).to be_truthy
expect(result.stdout).to eq ""
end
it 'does not clean created directories if other non-rscons-generated files reside there' do
test_dir("simple")
result = run_rscons
@@ -546,14 +565,16 @@ EOF
result = run_rscons
expect(result.stderr).to eq ""
verify_lines(lines(result.stdout), [
%r{gcc -c -o build/e.1/one.c.o -MMD -MF build/e.1/one.c.o.mf -Dmake_lib one.c},
%r{gcc -c -o build/e.1/two.c.o -MMD -MF build/e.1/two.c.o.mf -Dmake_lib two.c},
%r{ar rcs lib.a build/e.1/one.c.o build/e.1/two.c.o},
%r{gcc -c -o build/e.1/three.c.o -MMD -MF build/e.1/three.c.o.mf three.c},
%r{gcc -o library.exe lib.a build/e.1/three.c.o},
%r{gcc -c -o build/e.1/three.c.o -MMD -MF build/e.1/three.c.o.mf -Dmake_lib three.c},
%r{ar rcs libmylib.a build/e.1/two.c.o build/e.1/three.c.o},
%r{gcc -c -o build/e.1/one.c.o -MMD -MF build/e.1/one.c.o.mf one.c},
%r{gcc -o library.exe build/e.1/one.c.o -L. -lmylib},
])
expect(File.exists?("library.exe")).to be_truthy
expect(nr(`ar t lib.a`)).to eq "one.c.o\ntwo.c.o\n"
ar_t = nr(`ar t libmylib.a`)
expect(ar_t).to match %r{\btwo.c.o\b}
expect(ar_t).to match %r{\bthree.c.o\b}
end
it 'supports build hooks to override construction variables' do
@@ -1645,7 +1666,7 @@ EOF
test_dir("library")
result = run_rscons(args: %w[-f override_arcmd.rb])
expect(result.stderr).to eq ""
verify_lines(lines(result.stdout), [%r{ar rcf lib.a build/e.1/one.c.o build/e.1/three.c.o build/e.1/two.c.o}])
verify_lines(lines(result.stdout), [%r{ar rc lib.a build/e.1/one.c.o build/e.1/three.c.o build/e.1/two.c.o}])
end
it "allows passing object files as sources" do
@@ -1690,7 +1711,7 @@ EOF
])
expect(File.exist?("simple.exe")).to be_truthy
expect(File.exist?("simple.size")).to be_truthy
expect(File.read("simple.size")).to match /text.*data.*bss/
expect(File.read("simple.size")).to match /text.*data/i
end
end
@@ -1788,7 +1809,7 @@ EOF
end
end
context "configure operation" do
context "configure task" do
it "does not print configuring messages when no configure block and configure task not called" do
test_dir "configure"
result = run_rscons(args: %w[-f no_configure_output.rb])
@@ -1804,7 +1825,7 @@ EOF
expect(result.status).to_not eq 0
end
it "automatically runs the configure operation if the project is not yet configured in the given build directory" do
it "automatically runs the configure task if the project is not yet configured in the given build directory" do
test_dir "configure"
result = run_rscons(args: %w[-f check_c_compiler.rb])
@@ -2228,7 +2249,7 @@ EOF
context "check_cfg" do
context "when passed a package" do
it "stores flags and uses them during a build operation" do
it "stores flags and uses them during a build" do
test_dir "configure"
create_exe "pkg-config", "echo '-DMYPACKAGE'"
result = run_rscons(args: %w[-f check_cfg_package.rb configure])
@@ -2265,7 +2286,7 @@ EOF
end
context "when passed a program" do
it "stores flags and uses them during a build operation" do
it "stores flags and uses them during a build" do
test_dir "configure"
create_exe "my-config", "echo '-DMYCONFIG -lm'"
result = run_rscons(args: %w[-f check_cfg.rb configure])
@@ -2504,15 +2525,15 @@ EOF
end
end
context "install operation" do
it "invokes a configure operation if the project is not yet configured" do
context "install task" do
it "invokes the configure task if the project is not yet configured" do
test_dir "typical"
result = run_rscons(args: %w[-f install.rb install])
expect(result.stdout).to match /Configuring install_test/
end
it "invokes a build operation" do
it "invokes a build dependency" do
test_dir "typical"
Dir.mktmpdir do |prefix|
@@ -2572,7 +2593,7 @@ EOF
end
end
context "uninstall operation" do
context "uninstall task" do
it "removes installed files but not built files" do
test_dir "typical"