Starting some large user guide updates

This commit is contained in:
Josh Holtrop 2022-01-29 11:27:45 -05:00
parent 7771d4c038
commit c8a4accd12
2 changed files with 353 additions and 208 deletions

View File

@ -11,6 +11,7 @@ It supports the following features:
* compatible with Windows, Linux, OS X, and FreeBSD * compatible with Windows, Linux, OS X, and FreeBSD
* colorized output with build progress * colorized output with build progress
* build hooks * build hooks
* user-defined tasks with dependencies and custom parameters
At its core, Rscons is mainly an engine to: At its core, Rscons is mainly an engine to:
@ -22,7 +23,16 @@ Along the way, Rscons provides a concise syntax for specifying common types of
build operations, but also provides an extensible framework for performing build operations, but also provides an extensible framework for performing
custom build operations as well. custom build operations as well.
Rscons is written in Ruby, and is inspired by [SCons](https://scons.org/) and [waf](https://waf.io/). Rscons takes inspiration from:
* [SCons](https://scons.org/)
* [waf](https://waf.io/)
* [rake](https://github.com/ruby/rake)
* [CMake](https://cmake.org/)
* [Autoconf](https://www.gnu.org/software/autoconf/)
Rscons is written in Ruby.
The only requirement to run Rscons is that the system has a Ruby interpreter
installed.
${remove} ${remove}
WARNING: This user guide is meant to be preprocessed and rendered by a custom WARNING: This user guide is meant to be preprocessed and rendered by a custom
@ -131,75 +141,44 @@ version control systems):
#> Command-Line Operation #> Command-Line Operation
Rscons is typically invoked from the command-line as `./rscons`. Rscons is typically invoked from the command-line as `./rscons`.
Rscons supports several build *operations*:
* configure ./rscons [global options] [[task] [task options] ...]
* build
* clean
* distclean
* install
* uninstall
##> Configure Operation Global options:
-b BUILD, --build=BUILD Set build directory (default: build)
-f FILE Use FILE as Rsconscript
-F, --show-failure Show failed command log from previous build and exit
-h, --help Show rscons help and exit
-j N, --nthreads=N Set number of threads
-r COLOR, --color=COLOR Set color mode (off, auto, force)
-v, --verbose Run verbosely
--version Show rscons version and exit
The `configure` operation will initialize the Rscons cache file and build The user can list any number of tasks on the command line.
directory. Any parameters beginning with a "-" that follow a task are interpreted as task
It will also perform any configuration checks requested by the build script. arguments until another parameter is seen that does not begin with "-".
Such configuration checks can include: For example:
* verifying operation of a compiler ./rscons -v build1 --build1-opt=val1 --flag build2
* loading compilation/linker flags from a config program (e.g. `pkg-config`)
* verifying presence of a C/C++ header file
* verifying presence of a D import
* verifying presence of a library
* verifying presence of an executable
* any custom user-supplied configuration check
##> Build Operation The above command line is interpreted as follows:
If a `build` operation is requested and a `configure` operation has not yet * The user is passing the -v global option to run verbosely.
been performed, a `configure` operation will be automatically invoked. * The user requests to run task build1 with task parameters "--build1-opt=val1" and "--flag".
* The user requests to run task build2 with no task parameters.
The `build` operation will execute all builders registered to produce build If no tasks are specified on the command line, Rscons executes the `default`
targets. task.
If a `build` operation fails (e.g. due to a compilation failure), Rscons will If a task fails due to a command failure (e.g. compilation or linking failed),
log the failed commands. Rscons will log the failed commands.
By default Rscons does not print the failed commands to the console so that it By default Rscons does not print the failed commands to the console so that it
is easier for the user to focus on the actual compiler failure messages rather is easier for the user to focus on the actual compiler failure messages rather
than the compilation command itself. than the compilation command itself.
However, if the user wishes to see the compilation commands, rscons can be The user can run `./rscons -F` to see the command that failed on the prior
invoked with the `-v` command-line option to show all complilation commands Rscons execution.
while building, or, alternatively, following a compilation failure, the user The user can also invoke Rscons with the `-v` global command-line option which
can invoke rscons with the -F option which will not rebuild but will show the will cause Rscons to print each command it is executing.
failed command log from the previous build operation.
##> Clean Operation
A `clean` operation will remove all built target files.
It will not remove items installed by an `install` operation.
It will not remove the cached configuration options.
##> Distclean Operation
A `distclean` operation will remove all built target files and all cached
configuration options.
Generally it will get the project directory back to the state it was in when
unpacked before any configuration or build operations took place.
It will not removed items installed by an `install` operation.
##> Install Operation
An `install` operation will perform a `build` (and if necessary, first a
`configure` as well).
In addition it will execute any `Install` or `InstallDirectory` builders to
install items into the specified install directory.
##> Uninstall Operation
An `uninstall` operation will remove any items installed by an `install`
operation.
It will not remove all built target files, just the installed copies.
#> The Build Script #> The Build Script
@ -208,7 +187,7 @@ called `Rsconscript` (or `Rsconscript.rb`).
Here is a simple example `Rsconscript` file: Here is a simple example `Rsconscript` file:
```ruby ```ruby
build do default do
Environment.new do |env| Environment.new do |env|
env.Program("myprog.exe", glob("src/**/*.c")) env.Program("myprog.exe", glob("src/**/*.c"))
end end
@ -221,172 +200,163 @@ called `myprog.exe` which is to be built from all C source files found
The `Rsconscript` file is a Ruby script. The `Rsconscript` file is a Ruby script.
##> Build Script Methods ##> Tasks
`rscons` provides several methods that a build script can use. Tasks are the high-level user interface for performing functionality in a build
* `glob` (see ${#Finding Files: The glob Method})
* `path_append` (see ${#PATH Management})
* `path_components` (see ${#PATH Management})
* `path_prepend` (see ${#PATH Management})
* `path_set` (see ${#PATH Management})
* `rscons` (see ${#Using Subsidiary Build Scripts: The rscons Method})
* `sh` (see (${#Executing Commands: The sh Method})
Additionally, the following methods from the Ruby
[FileUtils](https://ruby-doc.org/stdlib-3.1.0/libdoc/fileutils/rdoc/FileUtils.html)
module are made available for the build script to call directly:
* `cd`
* `chmod`
* `chmod_R`
* `chown`
* `chown_R`
* `cp`
* `cp_lr`
* `cp_r`
* `install`
* `ln`
* `ln_s`
* `ln_sf`
* `mkdir`
* `mkdir_p`
* `mv`
* `pwd`
* `rm`
* `rm_f`
* `rm_r`
* `rm_rf`
* `rmdir`
* `touch`
###> Finding Files: The glob Method
The [`glob`](../yard/Rscons/Script/GlobalDsl.html#glob-instance_method) method can be
used to find files matching the patterns specified.
It supports a syntax similar to the Ruby [Dir.glob method](https://ruby-doc.org/core-3.1.0/Dir.html#method-c-glob) but operates more deterministically.
Example use:
```ruby
build do
Environment.new do |env|
env.Program("mytests", glob("src/**/*.cc", "test/**/*.cc"))
end
end
```
This example would build the `mytests` executable from all `.cc` source files
found recursively under the `src` or `test` directory.
###> PATH Management
`rscons` provides methods for management of the `PATH` environment variable.
The
[`path_append`](../yard/Rscons/Script/GlobalDsl.html#path_append-instance_method)
and
[`path_prepend`](../yard/Rscons/Script/GlobalDsl.html#path_prepend-instance_method)
methods can be used to append or prepend a path to the `PATH` environment
variable.
```ruby
path_prepend "i686-elf-gcc/bin"
```
The
[`path_set`](../yard/Rscons/Script/GlobalDsl.html#path_set-instance_method)
method sets the `PATH` environment variable to the given Array or String.
The
[`path_components`](../yard/Rscons/Script/GlobalDsl.html#path_components-instance_method)
method returns an Array of the components in the `PATH`
environment variable.
###> Using Subsidiary Build Scripts: The rscons Method
The
[`rscons`](../yard/Rscons/Script/GlobalDsl.html#rscons-instance_method)
build script method can be used to invoke an rscons subprocess to
perform an operation using a subsidiary rscons build script.
This can be used, for example, when a subproject is imported and a top-level
`configure` or `build` operation should also perform the same operation in the
subproject directory.
The first argument to the `rscons` method specifies either a directory name, or
the path to the subsidiary Rsconscript file to execute.
Any additional arguments are passed to `rscons` when it executes the subsidiary
script. script.
`rscons` will change working directories to the directory containing the
subsidiary script when executing it.
###> Task Parameters
###> Tasks with Special Meaning
Rscons recognizes special meaning for a few tasks:
* configure
* default
* clean
* distclean
* install
* uninstall
For each of these tasks, a shortcut method of the same name as the task is
provided which is equivalent to calling the `task()` method with the first
argument (task name) automatically filled in by the shortcut method.
For example: For example:
```ruby ```ruby
default deps: "unpack_compiler" do
puts "default task"
end
```
is equivalent to:
```ruby
task "default", deps: "unpack_compiler" do
puts "default task"
end
```
####> Configure Task
The `configure` task allows Rscons to perform any one-time setup operations
required by a project, for example locating compilers and setting any initial
construction variable values based on the host environment in use.
It will also perform any configuration checks requested by the build script.
Such configuration checks can include:
* verifying operation of a compiler
* loading compilation/linker flags from a config program (e.g. `pkg-config`)
* verifying presence of a C/C++ header file
* verifying presence of a D import
* verifying presence of a library
* verifying presence of an executable
* any custom user-supplied configuration check
The configure task is implicitly a dependency of every other task unless that
task is configured with its `autoconf` option set to `false`.
The global build script `autoconf` setting can also be set to `false` to
disable automatic invocation of the configure task.
For example:
```ruby
autoconf false
configure do configure do
rscons "subproject", "configure" puts "configure"
end end
build do default do
rscons "subproject/Rsconscript", "build" puts "default"
end end
``` ```
It is also perfectly valid to perform a different operation in the subsidiary With the above Rsconscript, even if the project has not yet been configured,
script from the one being performed in the top-level script. a configure operation would not take place when the default task is executed.
For example, in a project that requires a particular cross compiler, the The user would have to explicitly request the configure task from the command
top-level `configure` script could build the necessary cross compiler using a line.
subsidiary build script.
This could look something like: The build script method `project_name` can be used to set the project name
which will be reported to the user during a configure operation.
For example:
```ruby ```ruby
project_name "My awesome project"
configure do configure do
rscons "cross/Rsconscript" check_d_compiler
check_c_compiler "i686-elf-gcc"
end end
``` ```
This would build, and if necessary first configure, using the cross/Rsconscript See ${#Configuring the Project} for more details on how to make use of the
subsidiary build script. configuration functionality that Rscons provides.
Subsidiary build scripts are executed from within the directory containing the
build script.
###> Executing Commands: The sh Method ####> Default Task
The The `default` task is special in that Rscons will execute it if no other task
[`sh`](../yard/Rscons/Script/GlobalDsl.html#sh-instance_method) has been requested by the user on the command line.
build script method can be used to directly execute commands. It is entirely feasible for the default task to be the only task defined for a
The `sh` method accepts either a single String argument or an Array of Strings. project, and simple projects may wish to do just that.
When an Array is given, if the array length is greater than 1, then the command
will not be executed and interpreted by the system shell.
Otherwise, it will be executed and interpreted by the system shell.
The default task can also be used to declare a dependency on another task that
would effectively become the default.
For example: For example:
```ruby ```ruby
build do task "build" do
# Run "make" in imported "subcomponent" directory. ...
sh "cd subcomponent; make"
# Move a file around.
sh "mv", "subcomponent/file with spaces.txt", "new_name.txt"
end end
task "flash" do
...
end
default deps: "build"
``` ```
If the command fails, rscons will normally print the error and terminate Then when the user runs `./rscons` the "build" task will be executed.
execution.
If the `:continue` option is set, then rscons will not terminate execution. ####> Clean Task
The `clean` task is built-in to Rscons.
It removes all built target files.
It will not remove items installed by an Install builder.
It will not remove the cached configuration options.
####> Distclean Task
The `distclean` task is built-in to Rscons.
It removes all built target files and all cached configuration options.
Generally it will get the project directory back to the state it was in when
unpacked before any configuration or build operations took place.
It will not remove items installed by an Install builder.
####> Install Task
The `install` task is not built-in to Rscons but rather is just a convention
for the build script author to use.
The suggested use is for the `install` task to invoke any `Install` or
`InstallDirectory` builders to install items into the specified installation
directory.
The `install` shortcut method can be used.
For example: For example:
```ruby ```ruby
build do install do
# This command will fail and a message will be printed. env.Install("${prefix}/bin", "app.exe")
sh "false", continue: true env.Install("${prefix}/share", "share")
# However, due to the :continue option being set, execution will continue.
sh "echo hi"
end end
``` ```
##> Configuration Operations ####> Uninstall Task
The `uninstall` task is built-in to Rscons.
It removes any items installed by an Install builder.
It will not remove all built target files, just the installed copies.
##> Configuring the Project
A `configure` block is optional. A `configure` block is optional.
It can be used to perform various checks and setup operations for a project. It can be used to perform various checks and setup operations for a project.
@ -647,7 +617,7 @@ end
If set, a build define of the specified String will be added to the If set, a build define of the specified String will be added to the
`CPPDEFINES` construction variable array if the requested package is found. `CPPDEFINES` construction variable array if the requested package is found.
##> Build Operations ##> Building Targets
The `build` block is used to create Environments and register build targets. The `build` block is used to create Environments and register build targets.
An Rscons build script would not be very useful without a `build` block. An Rscons build script would not be very useful without a `build` block.
@ -655,7 +625,7 @@ An Rscons build script would not be very useful without a `build` block.
Here is an example `build` block demonstrating how to register a build target: Here is an example `build` block demonstrating how to register a build target:
```ruby ```ruby
build do default do
Environment.new do |env| Environment.new do |env|
env.Program("myprog.exe", glob("src/**/*.c")) env.Program("myprog.exe", glob("src/**/*.c"))
end end
@ -687,7 +657,7 @@ to produce a user-specified build target.
For example, for the `Rsconscript`: For example, for the `Rsconscript`:
```ruby ```ruby
build do default do
Environment.new(name: "myproj") do |env| Environment.new(name: "myproj") do |env|
env.Program("myprog.exe", glob("src/**/*.c")) env.Program("myprog.exe", glob("src/**/*.c"))
end end
@ -711,7 +681,7 @@ construction variables.
Example: Example:
```ruby ```ruby
build do default do
Environment.new do |env| Environment.new do |env|
env["CCFLAGS"] += %w[-O2 -Wall] env["CCFLAGS"] += %w[-O2 -Wall]
env["LIBS"] += %w[m] env["LIBS"] += %w[m]
@ -1046,7 +1016,7 @@ build target or source file names.
Example: Example:
```ruby ```ruby
build do default do
Environment.new do |env| Environment.new do |env|
env["CFLAGS"] << "-Wall" env["CFLAGS"] << "-Wall"
env.add_build_hook do |builder| env.add_build_hook do |builder|
@ -1080,6 +1050,181 @@ In other words, build targets are not parallelized across a barrier.
env.barrier env.barrier
``` ```
##> Other Build Script Methods
`rscons` provides several methods that a build script can use.
* `autoconf` (see ${#Configure Task})
* `clean` (see ${#Clean Task})
* `configure` (see ${#Configure Task})
* `default` (see ${#Default Task})
* `distclean` (see ${#Distclean Task})
* `glob` (see ${#Finding Files: The glob Method})
* `install` (see ${#Install Task})
* `param` (see ${#Task Parameters})
* `path_append` (see ${#PATH Management})
* `path_components` (see ${#PATH Management})
* `path_prepend` (see ${#PATH Management})
* `path_set` (see ${#PATH Management})
* `project_name` (see ${#Configure Task})
* `rscons` (see ${#Using Subsidiary Build Scripts: The rscons Method})
* `sh` (see (${#Executing Commands: The sh Method})
* `task` (see ${#Tasks})
* `uninstall` (see ${#Uninstall Task})
Additionally, the following methods from the Ruby
[FileUtils](https://ruby-doc.org/stdlib-3.1.0/libdoc/fileutils/rdoc/FileUtils.html)
module are made available for the build script to call directly:
* `cd`
* `chmod`
* `chmod_R`
* `chown`
* `chown_R`
* `cp`
* `cp_lr`
* `cp_r`
* `install`
* `ln`
* `ln_s`
* `ln_sf`
* `mkdir`
* `mkdir_p`
* `mv`
* `pwd`
* `rm`
* `rm_f`
* `rm_r`
* `rm_rf`
* `rmdir`
* `touch`
###> Finding Files: The glob Method
The [`glob`](../yard/Rscons/Script/GlobalDsl.html#glob-instance_method) method can be
used to find files matching the patterns specified.
It supports a syntax similar to the Ruby [Dir.glob method](https://ruby-doc.org/core-3.1.0/Dir.html#method-c-glob) but operates more deterministically.
Example use:
```ruby
default do
Environment.new do |env|
env.Program("mytests", glob("src/**/*.cc", "test/**/*.cc"))
end
end
```
This example would build the `mytests` executable from all `.cc` source files
found recursively under the `src` or `test` directory.
###> PATH Management
`rscons` provides methods for management of the `PATH` environment variable.
The
[`path_append`](../yard/Rscons/Script/GlobalDsl.html#path_append-instance_method)
and
[`path_prepend`](../yard/Rscons/Script/GlobalDsl.html#path_prepend-instance_method)
methods can be used to append or prepend a path to the `PATH` environment
variable.
```ruby
path_prepend "i686-elf-gcc/bin"
```
The
[`path_set`](../yard/Rscons/Script/GlobalDsl.html#path_set-instance_method)
method sets the `PATH` environment variable to the given Array or String.
The
[`path_components`](../yard/Rscons/Script/GlobalDsl.html#path_components-instance_method)
method returns an Array of the components in the `PATH`
environment variable.
###> Using Subsidiary Build Scripts: The rscons Method
The
[`rscons`](../yard/Rscons/Script/GlobalDsl.html#rscons-instance_method)
build script method can be used to invoke an rscons subprocess to
perform an operation using a subsidiary rscons build script.
This can be used, for example, when a subproject is imported and a top-level
`configure` or `build` operation should also perform the same operation in the
subproject directory.
The first argument to the `rscons` method specifies either a directory name, or
the path to the subsidiary Rsconscript file to execute.
Any additional arguments are passed to `rscons` when it executes the subsidiary
script.
`rscons` will change working directories to the directory containing the
subsidiary script when executing it.
For example:
```ruby
configure do
rscons "subproject", "configure"
end
default do
rscons "subproject/Rsconscript", "build"
end
```
It is also perfectly valid to perform a different operation in the subsidiary
script from the one being performed in the top-level script.
For example, in a project that requires a particular cross compiler, the
top-level `configure` script could build the necessary cross compiler using a
subsidiary build script.
This could look something like:
```ruby
configure do
rscons "cross/Rsconscript"
check_c_compiler "i686-elf-gcc"
end
```
This would build, and if necessary first configure, using the cross/Rsconscript
subsidiary build script.
Subsidiary build scripts are executed from within the directory containing the
build script.
###> Executing Commands: The sh Method
The
[`sh`](../yard/Rscons/Script/GlobalDsl.html#sh-instance_method)
build script method can be used to directly execute commands.
The `sh` method accepts either a single String argument or an Array of Strings.
When an Array is given, if the array length is greater than 1, then the command
will not be executed and interpreted by the system shell.
Otherwise, it will be executed and interpreted by the system shell.
For example:
```ruby
default do
# Run "make" in imported "subcomponent" directory.
sh "cd subcomponent; make"
# Move a file around.
sh "mv", "subcomponent/file with spaces.txt", "new_name.txt"
end
```
If the command fails, rscons will normally print the error and terminate
execution.
If the `:continue` option is set, then rscons will not terminate execution.
For example:
```ruby
default do
# This command will fail and a message will be printed.
sh "false", continue: true
# However, due to the :continue option being set, execution will continue.
sh "echo hi"
end
```
##> Extending Rscons ##> Extending Rscons
### Adding New Languages ### Adding New Languages
@ -1131,7 +1276,7 @@ For example:
class Rscons::Builders::Mine < Rscons::Builder class Rscons::Builders::Mine < Rscons::Builder
end end
build do default do
Environment.new do |env| Environment.new do |env|
env.add_builder(Rscons::Builders::Mine) env.add_builder(Rscons::Builders::Mine)
end end
@ -1154,7 +1299,7 @@ Rscons::DEFAULT_BUILDERS << :Special
#Rsconscript #Rsconscript
load "SpecialBuilder.rb" load "SpecialBuilder.rb"
build do default do
Environment.new do |env| Environment.new do |env|
# A build target using the "Special" builder can be registered. # A build target using the "Special" builder can be registered.
env.Special("target", "source") env.Special("target", "source")
@ -1383,7 +1528,7 @@ ${include lib/rscons/default_construction_variables.rb}
### Example: Building a C Program ### Example: Building a C Program
```ruby ```ruby
build do default do
Environment.new do |env| Environment.new do |env|
env["CFLAGS"] << "-Wall" env["CFLAGS"] << "-Wall"
env.Program("program", glob("src/**/*.c")) env.Program("program", glob("src/**/*.c"))
@ -1394,7 +1539,7 @@ end
### Example: Building a D Program ### Example: Building a D Program
```ruby ```ruby
build do default do
Environment.new do |env| Environment.new do |env|
env["DFLAGS"] << "-Wall" env["DFLAGS"] << "-Wall"
env.Program("program", glob("src/**/*.d")) env.Program("program", glob("src/**/*.d"))
@ -1405,7 +1550,7 @@ end
### Example: Cloning an Environment ### Example: Cloning an Environment
```ruby ```ruby
build do default do
main_env = Environment.new do |env| main_env = Environment.new do |env|
env["CFLAGS"] = ["-DSOME_DEFINE", "-O3"] env["CFLAGS"] = ["-DSOME_DEFINE", "-O3"]
env["LIBS"] = ["SDL"] env["LIBS"] = ["SDL"]
@ -1436,7 +1581,7 @@ EOF
end end
end end
build do default do
Environment.new do |env| Environment.new do |env|
env.add_builder(GenerateFoo) env.add_builder(GenerateFoo)
env.GenerateFoo("foo.h", []) env.GenerateFoo("foo.h", [])
@ -1448,7 +1593,7 @@ end
### Example: Using different compilation flags for some sources ### Example: Using different compilation flags for some sources
```ruby ```ruby
build do default do
Environment.new do |env| Environment.new do |env|
env["CFLAGS"] = ["-O3", "-Wall"] env["CFLAGS"] = ["-O3", "-Wall"]
env.add_build_hook do |build_op| env.add_build_hook do |build_op|
@ -1464,7 +1609,7 @@ end
### Example: Creating a static library ### Example: Creating a static library
```ruby ```ruby
build do default do
Environment.new do |env| Environment.new do |env|
env.Library("mylib.a", glob("src/**/*.c")) env.Library("mylib.a", glob("src/**/*.c"))
end end
@ -1474,7 +1619,7 @@ end
### Example: Creating a C++ parser source from a Yacc/Bison input file ### Example: Creating a C++ parser source from a Yacc/Bison input file
```ruby ```ruby
build do default do
Environment.new do |env| Environment.new do |env|
env.CFile("^/parser.tab.cc", "parser.yy") env.CFile("^/parser.tab.cc", "parser.yy")
end end

View File

@ -161,7 +161,7 @@ module Rscons
def usage def usage
usage = <<EOF usage = <<EOF
Usage: #{$0} [global options] [task] [task options] Usage: #{$0} [global options] [[task] [task options] ...]
Global options: Global options:
-b BUILD, --build=BUILD Set build directory (default: build) -b BUILD, --build=BUILD Set build directory (default: build)