Rscons is an open-source build system for developers. It supports the following features:
At its core, Rscons is mainly an engine to:
Along the way, Rscons provides a concise syntax for specifying common types of build steps, but also provides an extensible framework for performing custom build operations as well.
Rscons takes inspiration from:
Rscons is written in Ruby. The only requirement to run Rscons is that the system has a Ruby interpreter installed.
The number one design principle in Rscons is build correctness. This means that a target will be built when Rscons cannot determine that a build target is already up-to-date. A build target will be built whenever:
Importantly, Rscons uses the content of a source (dependency) file to determine whether a rebuild is necessary, not simply the timestamp of the file. This is because relying solely on the timestamp of the file can lead to an incorrect decision being made to not rebuild when a rebuild is necessary.
Rscons supports multiple configurations of compilation flags or build options across multiple environments or build variants to build output files in different ways according to the user's desire. For example, the same source files can be built into a release executable, but also compiled with different compilation flags or build options into a test executable. Rscons also supports build hooks, which allow the user to further fine-tune the build system's operation. A build hook, for example, can be used to set a build option for only source files coming from a particular source directory.
Rscons will automatically determine the number of threads to use based on the host CPU configuration, and will schedule jobs as efficiently as possible across the available threads in order to complete the build in as little time as possible. As development occurs and builders are executed, Rscons makes use of a cache file in order to avoid rebuilding a target when it is already up to date.
Rscons was designed to store temporary build artifacts (for example, object files, dependency files, etc...) and build system metadata in a "build directory". This keeps files generated by the build cleanly separated from user-controlled source files.
In contrast to other build systems or build system generators, rscons executes from the project base directory (up to the user) rather than executing from within the build directory. This keeps any file paths printed by compilers (such as in warning or error messages) accurate relative to the project directory, so that the user does not need to translate any paths to the correct path within a terminal or editor application, for example.
By default a build directory named "build" is used, but this can be overridden
by the user by using the -b
/--build
command-line option.
To use Rscons on your project, you must:
rscons
script in your project (See Installation).Rsconscript
build script for your project (See The Build Script).rscons
command in your project (See Command-Line Operation).Rscons is designed to be distributed as a stand-alone single file script that
can be copied into and versioned in a project's source tree.
The only requirement to run Rscons is that the system has a Ruby interpreter
installed.
The latest release can be downloaded from https://github.com/holtrop/rscons/releases.
Simply copy the rscons
executable script into the desired location within
the project to be built (typically the root of the repository) and mark it
executable.
The following files should be added to source control:
rscons
Rsconscript
Add the following contents to .gitignore
(or the equivalent thereof for
different version control systems):
/.rscons* /build/
Rscons is typically invoked from the command-line as ./rscons
.
Usage: ./rscons [global options] [[task] [task options] ...]
Global options:
-A, --all
Show all tasks (even those without descriptions) in task list. Use in
conjunction with the -T argument.
-b BUILD, --build=BUILD
Set build directory (default: build).
-e VS, --variants=VS
Enable or disable variants. VS is a comma-separated list of variant
entries. If the entry begins with "-" the variant is disabled instead of
enabled. If the full list begins with "+" or "-" then it modifies the
variants that are enabled by default by only enabling or disabling the
listed variants. Otherwise, the enabled set of variants is as given and
any variants not listed are disabled. The set of enabled variants is
remembered from when the project is configured.
-f FILE
Use FILE as Rsconscript.
-F, --show-failure
Show failed command log from previous build and exit (does not load build
script).
-h, --help
Show rscons help and exit (does not load build script).
-j N, --nthreads=N
Set number of threads (local default: 16).
-r COLOR, --color=COLOR
Set color mode (off, auto, force).
-T, --tasks
Show task list and parameters and exit (loads build script). By default
only tasks with a description are listed. Use -AT to show all tasks whether
they have a description or not.
-v, --verbose
Run verbosely. This causes Rscons to print the full build command used by
each builder.
--version
Show rscons version and exit (does not load build script).
The user can list any number of tasks on the command line. Any parameters beginning with a "-" that follow a task are interpreted as task arguments until another parameter is seen that does not begin with "-". For example:
./rscons -v build1 --build1-opt=val1 --flag build2
The above command line is interpreted as follows:
If no tasks are specified on the command line, Rscons executes the default
task.
If a task fails due to a command failure (e.g. compilation or linking failed),
Rscons will log the failed commands.
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
than the compilation command itself.
The user can run ./rscons -F
to see the command that failed on the prior
Rscons execution.
The user can also invoke Rscons with the -v
global command-line option which
will cause Rscons to print each command it is executing.
When Rscons executes, it performs the following phases:
configure
task if necessary (the
project has not yet been configured, autoconf is set to true, and the user
is requesting to execute a task that is marked with autoconf set to true)Rscons looks for instructions for what to build by reading a build script file
called Rsconscript
(or Rsconscript.rb
).
Here is a simple example Rsconscript
file:
env do |env| env.Program("myprog.exe", glob("src/**/*.c")) end
This Rsconscript
file would instruct Rscons to produce a Program target
called myprog.exe
which is to be built from all C source files found
(recursively) under the src
directory.
The Rsconscript
file is a Ruby script.
Tasks are a high-level user interface for performing functionality in a build script. Tasks can create Environments that perform compilation/linking steps. Tasks can also execute arbitrary commands or perform any miscellaneous logic.
Tasks can have dependencies, which are specified as names of other tasks that should be executed before this task executes.
Tasks can have action blocks. When a task is executed, all of its action blocks are called in the order in which they were added.
Example:
task "build" do env do |env| env.Program("^^/proj.elf", glob("src/**/*.c")) end end task "flash", deps: "build" do sh "nrfjprog", "-f", "NRF52", "--program", env.expand("^^/proj.elf") end
In this example, the flash
task depends on the build
task.
So if the project had not yet been built, and the user executes
./rscons flash
, the project would first be built and then flashed to the
target.
If the task
method is called again with the name of an already existing task,
the task is not overwritten, but rather modified.
Any newly specified dependencies are added to the current dependencies.
Any action block is appended to the task's list of action blocks to execute
when the task is executed.
Note that for a simple project, the build script may not need to define any tasks at all and could just make use of the Rscons built-in default task (see Default Task).
Tasks can accept parameters. Parameters are defined by the build script author, and have default values. The user can override parameter values on the command line.
Task parameters are defined by passing a parameter constructed with the Rscons
param()
method to the :params
argument of the task()
method.
The signature of the param
method is:
def param(name, value, takes_arg, description)
For example:
task "build", params: [ param("myparam", "defaultvalue", true, "My special parameter"), param("xyz", nil, false, "Enable the xyz feature"), ] do |task, params| env do |env| env["CPPDEFINES"] << "SOMEMACRO=#{params["myparam"]}" if params["flag"] env["CPPDEFINES"] << "ENABLE_FEATURE_XYZ" end end end
With the above Rsconscript
, the user could invoke Rscons as:
./rscons build --myparam=pvalue --xyz
This would pass in "pvalue" as the value to the "myparam" parameter, and a truthy value ("--xyz") as the value of the "xyz" parameter.
As seen above, task parameter values can be accessed within a task's action
block by using the second parameter (params
) to the action block.
Task parameter values can also be accessed with the Task#[]
method on any
task object.
This allows accessing the parameter values of any task object, not just the
task owning the action block being executed.
Example:
task "one", params: param("flag", nil, false, "Enable a flag") task "two" do puts "Task one's flag #{Task["one"]["flag"] ? "is" : "is not"} set" end
Task parameters can also be referenced via construction variables. Each task parameter is stored in a construction variable. The name for the construction variable is created by joining the task name and the parameter name with a ":" character. For example:
task "build", params: [ param("heap-size", "1024", true, "Set heap size"), ] do env["CPPDEFINES"] << "HEAP_SIZE=${build:heap-size}" env.Program("^/myprog", glob("src/**/*.c")) env.Install("${configure:prefix}/bin/myprog", "^/myprog") end
Rscons recognizes special meaning for a few tasks:
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:
default deps: "unpack_compiler" do puts "default task" end
is equivalent to:
task "default", deps: "unpack_compiler" do puts "default task" end
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:
pkg-config
)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:
autoconf false configure do puts "configure" end default do puts "default" end
With the above Rsconscript, even if the project has not yet been configured, a configure operation would not take place when the default task is executed. The user would have to explicitly request the configure task from the command line.
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:
project_name "My awesome project" configure do check_d_compiler end
See Configuring the Project for more details on how to make use of the configuration functionality that Rscons provides.
Configure blocks must be defined in the Rsconscript file before any environments are created.
The default
task is special in that Rscons will execute it if no other task
has been requested by the user on the command line.
The default task can also be used to declare a dependency on another task that would effectively become the default. For example:
task "build" do ... end task "flash" do ... end default deps: "build"
Then when the user runs ./rscons
the "build" task will be executed.
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.
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 or checked out, before any configuration or build operations took
place.
It will not remove items installed by an Install builder.
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:
install do env.Install("${prefix}/bin", "app.exe") env.Install("${prefix}/share", "share") end
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.
Configure task actions can be used to perform various checks and setup
operations for a project.
Example configure
action block:
configure do check_cxx_compiler check_c_header "getopt.h" end
If any configure task action blocks are present, they will be execute when the
configure operation is performed.
This happens if the user requests the configure
task from the command line.
It also happens if all of the following are true:
autoconf
set to false
is being executed.autoconf
setting has not been set to false
.See Configure Task for more information about autoconf
.
The following methods can be used within a configure
block to check for a
working compiler:
check_c_compiler
check_cxx_compiler
check_d_compiler
Each of these methods can take an optional list of compilers to check for. If such a list is supplied, the compilers are tested in the order listed. The first compiler option found which passes a compilation test is used.
Here are example calls which also show the default compiler list for each supported language:
configure do check_c_compiler "gcc", "clang" check_cxx_compiler "g++", "clang++" check_d_compiler "gdc", "ldc2" end
Global configuration options may be supplied to the compiler checks as well. Example:
configure do check_c_compiler "x86_64-elf-gcc", on_fail: "Install x86_64-elf cross toolchain first!" end
The following methods can be used to check for the presence of a header file:
check_c_header
will check for a C header to be presentcheck_cxx_header
will check for a C++ header to be presentEach of these methods take the name of the header file to check for as the first argument, and take an optional Hash of arguments as the second argument.
Example calls:
configure do check_c_header "getopt.h", set_define: "HAVE_GETOPT_H" check_c_header "FreeType2.h" check_cxx_header "memory" end
:check_cpppath
Optionally specifies an array of paths to look for the header file in.
The check_d_import
method can be used to check for the presence of D import.
This method takes the name of the import to check for as the first argument.
Example calls:
configure do check_d_import "std.stdio" check_d_import "std.numeric" end
:check_d_import_path
Optionally specifies an array of paths to look for the module in.
The check_lib
method can be used to check for the presence of a library.
This method takes the name of the library to check for as the first argument, and take an optional Hash of arguments as the second argument.
Example calls:
configure do check_lib "kpty", fail: false, set_define: "HAVE_LIBKPTY" check_lib "GL" end
:check_libpath
Optionally specifies an array of paths to look for the library in.
:use
If not set, the library will be used by default in all Environment
objects.
If set, the library will only be used in Environment
objects that have a
matching :use
flag set.
The check_program
method can check for the existence of an executable in the
host operating system environment.
Example call:
configure do check_program "xxd" end
The check_cfg
method can be used to check for the existence of a package as
well as import any build options (e.g. include path, defines, libraries to link
against, etc...) required to use the package.
This method takes a Hash of options as its only argument.
Example calls:
configure do check_cfg package: "zlib" check_cfg program: "freetype-config", fail: false, set_define: "HAVE_FREETYPE" end
:package
If the :package
option is set to a value, the pkg-config
program will be
used to look for package configuration flags for the specified package.
:program
If the :program
option is given, the program specified will be used to look
for configuration flags.
:use
If not set, the library will be used by default in all Environment
objects.
If set, the library will only be used in Environment
objects that have a
matching :use
flag set.
The Rsconscript
author can add custom configuration checks to be performed
during the rscons configure
operation.
Here is an example from build_tests/configure/custom_config_check.rb
showing
a custom configuration check:
configure do custom_check("Checking 'grep' version") do |op| stdout, stderr, status = op.log_and_test_command(%w[grep --version]) should_fail = true if status != 0 fail_message = "error executing grep" elsif stdout =~ /^grep \(GNU grep\) 1\./ fail_message = "too old!" status = 1 elsif stdout =~ /^grep \(GNU grep\) 2\./ fail_message = "we'll work with it but you should upgrade" status = 1 should_fail = false op.store_merge("CPPDEFINES" => "GREP_WORKAROUND") else op.store_append("CPPDEFINES" => "GREP_FULL") end op.complete(status, success_message: "good!", fail_message: fail_message, fail: should_fail) end custom_check("Checking sed -E flag") do |op| stdout, stderr, status = op.log_and_test_command(%w[sed -E -e s/ab+/rep/], stdin: "abbbc") op.complete(stdout =~ /repc/ ? 0 : 1, success_message: "good", fail_message: "fail") end end env do |env| puts env["CPPDEFINES"] end
A custom configuration check is created by calling the custom_check
method
and passing a block.
The contents of the block should perform the custom configuration checking
logic.
This logic can include executing a test command or other arbitrary operations.
An argument op
is passed to the block.
This object is an instance of the ConfigureOp
class
class and provides several methods that can be used to aid with the custom
configuration check.
The log_and_test_command
method can be used to execute a test command and retrieve its results.
The command and its output are also logged to the config.log file.
The store_merge
,
store_append
,
and store_parse
methods can be used to store construction variables to be used in Environments
created later.
Finally, the complete
method can be used to complete the configuration check and indicate a success
or failure.
While performing a custom configuration check, it can sometimes be useful to
be able to construct an Environment to use the set of default construction
variables as defined so far in the configuration block, for example to expand
construction variables to build a test command.
The normal Environment
class cannot be used within the configure
block,
however the BasicEnvironment
class
can be used for such a purpose.
For example, to expand the current ${CCCMD}
value:
configure do custom_check("Checking something to do with CCCMD") do command = BasicEnvironment.new.expand_varref("${CCCMD}") # ... end end
:fail
If the :fail
option is set to false
, then the absence of the package or
program requested will not result in the configure option failing.
The :fail
option defaults to true
if the :set_define
option is not
defined, and defaults to false
if the :set_define
option is defined.
:on_fail
The :on_fail
option can be set to a String or a Proc object. If the
configuration operation fails (or would fail), the given message is printed
or the Proc is called.
Examples:
configure do check_c_compiler "special-gcc", on_fail: "First install special gcc!" end configure do package_hint = lambda do puts "The following packages must be installed to build this project:" puts "- libsdl2-dev" puts "- libsdl2-image-dev" puts "- libsdl2-net-dev" end check_lib "SDL2", on_fail: package_hint check_lib "SDL2_image", on_fail: package_hint check_lib "SDL2_net", on_fail: package_hint end
:set_define
If set, a build define of the specified String will be added to the
CPPDEFINES
construction variable array if the requested package is found.
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.
Here is an example build script that creates an Environment and registers a
Program build target:
env do |env| env.Program("myprog.exe", glob("src/**/*.c")) end
This Rsconscript
would build an executable called myprog.exe
from all C
source files found recursively under the src
directory.
An Environment includes:
All build targets must be registered within an Environment
.
If the user does not specify a name for the environment, a name will be
automatically generated based on the Environment's internal ID, for example
"e.1".
The Environment's build root is a directory with the same name as the
Environment, created within the top-level Rscons build directory.
By default it holds all intermediate files generated by Rscons that are needed
to produce a user-specified build target.
For example, for the Rsconscript
:
env "myproj" do |env| env.Program("myprog.exe", glob("src/**/*.c")) end
Rscons will place an object file and dependency file corresponding to each C source file under the Environment's build root. Assuming a top-level build directory of "build", the Environment's build root would be "build/myproj". This keeps the intermediate generated build artifacts separate from the source files. Source and target paths passed to a Builder (e.g. Program) can begin with "^/" to indicate that Rscons should expand those paths to be relative to the Environment's build root. If a source or target path passed to a Builder begins with "^^/", it is expanded to be relative to the Rscons top-level build directory (but outside the Environment's build root).
Construction variables are values assigned to keys within an Environment. Construction variables are used by Builders to produce output files. See Default Construction Variables for a reference of all built-in construction variables.
Example:
env do |env| env["CCFLAGS"] += %w[-O2 -Wall] env["LIBS"] += %w[m] end
This example modifies the CCFLAGS
construction variable to add -O2
and
-Wall
to the compilation commands used for C and C++ source files.
It also instructs the linker to link against the m
library.
Rscons uses builder objects to produce target output files from source
input files.
A build target to be built using a builder is registered by calling a method on
the Environment
object that matches the builder's name.
For example, a Program
build target is registered by calling the
env.Program
method.
The general syntax for registering a build target using a builder is:
env.BuilderName(target, sources, vars = {})
The target
parameter is the path to the output file or directory.
The sources
parameter is the path or paths to the input file(s) to be used
by the builder.
In the target
and sources
parameters, the user can explicitly refer to a
path within the Environment's build root by beginning the path with "^/", or to
a path within the Rscons top-level built directory by beginning with "^^/".
The vars
parameter is an optional Hash which can include construction
variables to be used for this build target.
Any construction variable values specified in this parameter will override
those assigned to the Environment.
There are several default builders that are built-in to Rscons:
Command
, which executes a user-defined command to produce the target.Copy
, which copies files or directories to a specified destination.CFile
, which builds a C or C++ source file from a lex or yacc input file.Directory
, which creates a directory.Disassemble
, which disassembles an object file to a disassembly listing.Install
, which installs files or directories to a specified destination.InstallDirectory
, which creates a directory in an install destination.Library
, which collects object files into a static library archive file.Object
, which compiles source files to produce an object file.Preprocess
, which invokes the C/C++ preprocessor on a source file.Program
, which links object files to produce an executable.SharedLibrary
, which links object files to produce a dynamically loadable
library.SharedObject
, which compiles source files to produce an object file, in a
way that is able to be used to create a shared library.Size
, which runs the 'size' utility on an executable file.env.Command(target, sources, "CMD" => command) # Example env.Command("user_guide.html", "user_guide.md", "CMD" => ["pandoc", "-fmarkdown", "-thtml", "-o${_TARGET}", "${_SOURCES}"], "CMD_DESC" => "Generating user guide:")
The Command
builder executes a user-defined command in order to produce the
desired target file based on the provided source files.
The Command
builder supports the following construction variables:
CMD
(required) specifies the command to execute (an array of strings).
CMD
is expanded for variable references, so the tokens ${_TARGET}
and
${_SOURCES}
can be used, for example.CMD_DESC
(optional) specifies the short text description to print when
the builder executes. The given description is followed by the target file
name.CMD_STDOUT
(optional) specifies a file to redirect standard output to.
CMD_STDOUT
is expanded for variable references, so the token ${_TARGET}
can be used, for example.env.CFile(target, source) # Example env.CFile("^/parser/parser.c", "parser.y")
The CFile
builder will generate a C or C++ source file from a lex (.l, .ll)
or yacc (.y, .yy) input file.
env.Copy(destination, sources) # Example env.Copy("mytests", "^/mytests") env.Copy("^/dist/share", "share")
The Copy
builder can copy files or directories to a target location.
env.Directory(target) # Example env.Directory("^/tests")
The Directory
builder can be used to explicitly create a directory.
This can also disambiguate whether the target for a subsequent builder
(e.g. Copy
) refers to a file path or directory path.
env.Disassemble(target, source) # Example env.Disassemble("module.dis", "module.o")
The Disassemble
builder generates a disassembly listing using objdump from
and object file.
env.Install(destination, sources) # Example env.Install("${prefix}/bin", "app.exe") env.Install("${prefix}/share", "share")
The Install
builder can install files or directories to their installation
target location.
It functions almost identically to the Copy
builder.
The only difference relates to the clean
and uninstall
tasks.
The clean
task removes targets created by the Copy
builder but not by
the Install
builder.
The uninstall
task removes targets created by the Install
builder but not
by the Copy
builder.
env.InstallDirectory(target) # Example env.InstallDirectory("${prefix}/share")
The InstallDirectory
builder can be used to explicitly create a directory in
an installation location.
This can also disambiguate whether the target for a subsequent builder
(e.g. Install
) refers to a file path or directory path.
It functions almost identically to the Directory
builder.
The only difference relates to the clean
and uninstall
tasks.
The clean
task removes targets created by the Directory
builder but not by
the InstallDirectory
builder.
The uninstall
task removes targets created by the InstallDirectory
builder
but not by the Directory
builder.
env.Library(target, sources) # Example env.Library("lib.a", Rscons.glob("src/**/*.c"))
The Library
builder creates a static library archive from the given source
files.
env.Object(target, sources) # Example env.Object("module.o", "module.c")
The Object
builder compiles the given sources to an object file.
Although it can be called explicitly, it is more commonly implicitly called by
the Program
builder.
env.Preprocess(target, source) # Example env.Preprocess("module-preprocessed.cc", "module.cc")
The Preprocess
builder invokes either ${CC}
or ${CXX}
(depending on if
the source contains an extension in ${CXXSUFFIX}
or not) and writes the
preprocessed output to the target file.
env.Program(target, sources) # Example env.Program("myprog", Rscons.glob("src/**/*.cc"))
The Program
builder compiles and links the given sources to an executable
file.
Object files, static library files, or source files can be given as sources
.
A platform-dependent program suffix will be appended to the target name if one
is not specified.
This can be controlled with the PROGSUFFIX
construction variable.
The Program builder supports a "direct" mode which is activated by specifying
the :direct
option.
In the direct mode, all source files are passed directly to the compiler
together and compiled and linked in one step, rather than being individually
compiled to separate object files first.
This mode allows taking advantage of any multi-file compilation capabilities
of the compiler.
However, it also requires recompiling all source files when any one of them
has changed.
Example use:
env.Program("myprog", Rscons.glob("src/**/*.c"), direct: true)
env.SharedLibrary(target, sources) # Example env.SharedLibrary("mydll", Rscons.glob("src/**/*.cc"))
The SharedLibrary
builder compiles and links the given sources to a
dynamically loadable library.
Object files or source files can be given as sources
.
A platform-dependent prefix and suffix will be appended to the target name if
they are not specified by the user.
These values can be controlled by overriding the SHLIBPREFIX
and
SHLIBSUFFIX
construction variables.
The SharedLibrary builder supports a "direct" mode which is activated by
specifying the :direct
option.
In the direct mode, all source files are passed directly to the compiler
together and compiled and linked in one step, rather than being individually
compiled to separate object files first.
This mode allows taking advantage of any multi-file compilation capabilities
of the compiler.
However, it also requires recompiling all source files when any one of them
has changed.
Example use:
env.SharedLibrary("mydll", Rscons.glob("src/**/*.c"), direct: true)
env.SharedObject(target, sources) # Example env.SharedObject("lib_module.o", "lib_module.c")
The SharedObject
builder compiles the given sources to an object file.
Any compilation flags necessary to build the object file in a manner that
allows it to be used to create a shared library are added.
Although it can be called explicitly, it is more commonly implicitly called by
the SharedLibrary
builder.
env.Size(target, sources) # Example env.Program("program.exe", glob("*.c")) env.Size("program.size", "program.exe")
The Size
builder runs the "size" executable on the given source file and
stores its output in the target file.
The size executable can be specified with the SIZE
construction variable,
and flags can be specified with SIZEFLAGS
.
Rscons supports phony build targets. Normally, a builder produces an output file, and executes whenever the input files or command have changed. A phony build target can be used to register a builder that does not produce an output file. A custom builder can take some action when the input files change even if it does not produce an output file. Such a builder could perform verification or run a test on its source files, possibly failing if some conditions are not met. It could also simply output something to the console, such as an analysis of the source file, whenever it changes. A phony target is signified by passing a Symbol instead of a String as the first parameter (target) to a builder method.
A target can be marked as depending on another file that Rscons would not
otherwise know about via the Environment#depends
function. For example,
to force the linker to re-link a Program output when a linker script changes:
env.Program("a.out", "foo.c", "LDFLAGS" => %w[-T linker_script.ld]) env.depends("a.out", "linker_script.ld")
You can pass multiple dependency files to Environment#depends
:
env.depends("my_app", "config/link.ld", "README.txt", *glob("assets/**/*"))
A build hook is a Ruby block that is called whenever Rscons is about to invoke a builder to produce a build target. Rscons also supports post-build hooks which are called after the builder has produced the build target. A build hook can be used to modify construction variables depending on the build target or source file names.
Example:
env do |env| env["CFLAGS"] << "-Wall" env.add_build_hook do |builder| # Compile sources from under src/tests without the -Wall flag. if builder.sources.first =~ %r{src/tests/} builder.vars["CFLAGS"] -= %w[-Wall] end end env.Program("program.exe", glob("src/**/*.c")) end
This example script would compile all C sources under the src
directory with
the -Wall
flag except for sources under the src/tests
directory.
A post-build hook can be added with env.add_post_build_hook
.
Post-build hooks are only invoked if the build step was a success.
Build hooks and post-build hooks can register new build targets.
Normally Rscons will parallelize all builders executed within an Environment. A barrier can be used to separate sets of build targets. All build targets registered before the barrier is created will be built before Rscons will schedule any build targets after the barrier. In other words, build targets are not parallelized across a barrier.
env.barrier
Rscons supports build variants. Variants can be used to built multiple variations of the same item with a specific change. For example, a desktop application with the same sources could be built to target KDE or GNOME using build variants. It is up to the build script author to define the variants and what effect they have on the build.
This build script defines "kde" and "gnome" variants:
variant "kde" variant "gnome" with_variants do env "prog" do |env| if variant "kde" env["CPPDEFINES"] << "KDE" end if variant "gnome" env["CPPDEFINES"] << "GNOME" end env.Program("^/prog.exe", "src/**/*.cpp") end end
The variant
build script method has two uses:
with_variants
block, it queries for whether the given variant is
active.The with_variants
build script method allows the power of variants to be
harnessed.
It iterates through each enabled variant and calls the given block.
In this example, the block would be called twice, once with the "kde" variant
active, and the second time with the "gnome" variant active.
Each env()
call creates an Environment, so two environments are created.
When an Environment is created within a with_variants
block, the
Environment's name has the active variant(s) appended to the given Environment
name (if any), and separated by a "-".
In this example, a "prog-kde" Environment would be created with build root build/prog-kde and -DKDE would be passed to the compiler when compiling each source. Next a "prog-gnome" Environment would be created with build root build/prog-gnome and -DGNOME would be passed to the compiler when compiling the sources.
Variants are enabled by default, but can be disabled by passing a false
value
to the :default
option of the variant
method.
For example:
variant "debug", default: false variant "release" with_variants do env "prog" do |env| env.Program("^/prog.exe", "prog.c") end end
The rscons
command line interface provides a -e
/--variants
argument which
allows the user to enable a different set of variants from those enabled by
default according to the build script author.
This argument accepts a comma-separated list of variants to enable.
Each entry in the list can begin with "-" to disable the variant instead of
enable it.
If the list begins with "+" or "-", then the entire given list modifies the
defaults given in the build script.
Otherwise, it exactly specifies which variants should be enabled, and any
variant not listed is disabled.
When the project is configured, the set of enabled variants is recorded and
remembered for later Rscons invocations.
This way, a user working on a single variant of a project does not need to
specify the -e
/--variants
option on each build operation.
The variant_enabled?
build script method can be called to query whether the
given variant is enabled.
Variants may be grouped, which allows the build script author to define multiple combinations of desired variations to build with. For example:
variant_group "desktop-environment" do variant "kde" variant "gnome" end variant_group "debug" do variant "debug" variant "release" end with_variants do env "prog" do |env| if variant("kde") env["CPPDEFINES"] << "KDE" end if variant("gnome") env["CPPDEFINES"] << "GNOME" end if variant("debug") env["CPPDEFINES"] << "DEBUG" end if variant("release") env["CPPDEFINES"] << "NDEBUG" end env.Program("^/prog.exe", "prog.c") end end
This build script executes the block given to with_variants
four times and
results in four Environments being created:
The command ./rscons -e-debug
would build just "prog-kde-release" and "prog-gnome-release".
The command ./rscons --variants kde,release
would build just "prog-kde-release".
rscons
provides several methods that a build script can use.
autoconf
(see Configure Task)build_dir
which returns the path to the top-level Rscons build directoryclean
(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)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)variant
(see Variants)variant_enabled?
(see Variant Groups)variant_group
(see Variant Groups)with_variants
(see Variant Groups)Additionally, the following methods from the Ruby FileUtils 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
The glob
method
can be used to find files matching the patterns specified.
It supports a syntax similar to the Ruby
Dir.glob method
but operates more deterministically (results are ordered based on file names
rather than file system directory ordering).
Example use:
env do |env| env.Program("mytests", glob("src/**/*.cc", "test/**/*.cc")) end
This example would build the mytests
executable from all .cc
source files
found recursively under the src
or test
directory.
The download
method can be used to download a file from a given URL.
Example use:
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:
rscons
provides methods for management of the PATH
environment variable.
The
path_append
and
path_prepend
methods can be used to append or prepend a path to the PATH
environment
variable.
path_prepend "i686-elf-gcc/bin"
The
path_set
method sets the PATH
environment variable to the given Array or String.
The
path_components
method returns an Array of the components in the PATH
environment variable.
The
rscons
build script method can be used to invoke an rscons subprocess using a
subsidiary rscons build script.
This can be used, for example, when a subproject is imported and a top-level
configure
or build
task should also perform the same task 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:
configure do rscons "subproject", "configure" end task "build" do rscons "subproject/Rsconscript", "build" end
It is also perfectly valid to perform different task(s) 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:
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.
The
sh
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:
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:
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
Options that Ruby's spawn
method accepts can also be passed in to the sh
method.
For example, to execute the given command with a different working directory,
the :chdir
option can be specified:
default do # Execute 'ls' from within the 'src' directory: sh "ls", chdir: "src" end
The Object
and SharedObject
builders that ship with Rscons have an API that
allows the user to register extra languages that can be suppored by the
builders.
In fact, the built-in support for assembly, C, C++, and D compilation all make
use of this built-in API.
To see an example of how this API is used, see the
lib/rscons/builders/lang/*.rb
files in the Rscons source repository.
For example, here is how the C++ language is registered:
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}")
There are also default construction variables registered to go along with the
language registration as specified above.
New default construction variables can be registered globally by assigning to
the Rscons::DEFAULT_CONSTRUCTION_VARIABLES
Hash.
For example:
Rscons::DEFAULT_CONSTRUCTION_VARIABLES["CXXCMD"] = %w[${CXX} -c -o ${_TARGET} ${CXXDEPGEN} ${INCPREFIX}${CPPPATH} ${CPPFLAGS} ${CXXFLAGS} ${CCFLAGS} ${_SOURCES}]
It is also possible to extend Rscons with new builders. This is the most flexible method to extend Rscons. Builders can execute a command line program, call another builder, or just use plain Ruby code to produce an output file.
A builder is a class that inherits from the Rscons::Builder
base class.
Rscons provides a Rscons::Builders
namespacing module which contains the
built-in builder classes.
User-provided custom builder classes can also reside in the Rscons::Builders
namespacing module, but this is not required.
The user can add a builder class to an Environment with the env.add_builder
method.
For example:
class Rscons::Builders::Mine < Rscons::Builder end default do env do |env| env.add_builder(Rscons::Builders::Mine) end end
Alternatively, the builder author can add the name of the custom builder to the
Rscons::DEFAULT_BUILDERS
array and then Rscons will automatically add the
custom builder to every Environment.
This method only works if the custom builder class is contained within the
Rscons::Builders
namespacing module.
For example:
#SpecialBuilder.rb class Rscons::Builders::Special < Rscons::Builder end Rscons::DEFAULT_BUILDERS << :Special #Rsconscript load "SpecialBuilder.rb" default do env do |env| # A build target using the "Special" builder can be registered. env.Special("target", "source") end end
By default, the builder name is taken from the last component of the class name.
For example, a class called Rscons::Builders::Mine
would be usable in the
Rsconscript with env.Mine()
.
A builder author can override the builder name by defining a class method
within the builder class called name
.
For example, with the following builder definition:
class Rscons::Builders::MySpecialBuilder < Rscons::Builder def self.name "Special" end end
This builder would be registered in the Rsconscript with env.Special()
.
It is optional for a custom builder to provide an initialize
method.
If an initialize
method is provided, it must call super
to invoke the
base Rscons::Builder
class's constructor.
A single Hash parameter is passed to the builder constructor.
This Hash contains many parameters describing how the build target was
registered by the user.
The base constructor will set several instance attributes within the builder:
@target
will contain the path to the build target@sources
will contain the path(s) to the build source(s)@cache
will contain a reference to the Rscons::Cache
object used for
the build@env
will contain a reference to the Environment object that registered
the build target using the builder@vars
will contain any user-specified construction variable values that
should be used for the builder execution (overriding any Environment-wide
construction variable values)In order for a builder to run, the builder class must implement a the
Builder#run()
method.
Generally, the run()
method will use the source file(s) to produce the target
file.
Here is an example of a trivial builder:
class Rscons::Builders::Custom < Rscons::Builder def run(options) File.open(@target, "w") do |fh| fh.write("Target file created.") end true end end
If the builder has completed and failed, the run
method should return
false
.
In this case, generally the command executed or the builder itself would be
expected to output something to $stderr
indicating the reason for the build
failure.
If the builder has completed successfully, the run
method should
return true
.
If the builder is not yet complete and is waiting on other steps, the run
method should return the return value from the Builder#wait_for
method.
See Custom Builder Parallelization.
A builder should print a status line when it produces a build target.
The Builder#print_run_message
method can be used to print the builder status
line.
This method supports a limited markup syntax to identify and color code the
build target and/or source(s).
Here is our Custom builder example extended to print its status:
class Rscons::Builders::Custom < Rscons::Builder def run(options) print_run_message("Creating <target>#{@target}<reset> from Custom builder", nil) File.open(@target, "w") do |fh| fh.write("Target file created.") end true end end
Whenever possible, a builder should keep track of information necessary to
know whether the target file(s) need to be rebuilt.
The Rscons::Cache
object is the mechanism by which to keep track of this
information.
The Cache object provides two methods: #up_to_date?
and #register_build
which can be used to check if a built file is still up-to-date, and to
register build information for a subsequent check.
Here is a Custom builder which combines its source files similar to what the
cat
command would do:
class Rscons::Builders::Custom < Rscons::Builder def run(options) unless @cache.up_to_date?(@target, nil, @sources, @env) print_run_message("Combining <source>#{Util.short_format_paths(@sources)}<reset> => <target>#{@target}<reset>", nil) File.open(@target, "wb") do |fh| @sources.each do |source| fh.write(File.read(source, mode: "rb")) end end @cache.register_build(@target, nil, @sources, @env) end true end end
This builder would rebuild the target file and print its run message if the target file or any of the source file(s) were changed, but otherwise would be silent and not re-combine the source files.
Note that generally the same arguments should be passed to
@cache.register_build
and @cache.up_to_date?
.
The Rscons scheduler can parallelize builders to take advantage of multiple
processor cores.
Taking advantage of this ability to parallelize requires the builder author to
author the builder in a particular way.
The #run()
method of each builder is called from Rscons in the main program
thread.
However, the builder may execute a subcommand, spawn a thread, or register
other builders to execute as a part of doing its job.
In any of these cases, the builder's run
method should make use of
Builder#wait_for
to "sleep" until one of the items being waited for has
completed.
Here is an example of using a Ruby thread to parallelize a builder:
class MyBuilder < Rscons::Builder def run(options) if @thread true else print_run_message("#{name} #{target}", nil) @thread = Thread.new do sleep 2 FileUtils.touch(@target) end wait_for(@thread) end end end env do |env| env.add_builder(MyBuilder) env.MyBuilder("foo") end
It is up to the author of the thread logic to only perform actions that are
thread-safe.
It is not safe to call other Rscons methods, for example, registering other
builders or using the Cache, from a thread other than the one that calls the
#run()
method.
It is a very common case that a builder will execute a subcommand which
produces the build target.
This is how most of the built-in Rscons builders execute.
A low-level way to handle this is for the builder to construct an instance of
the Rscons::Command
class and then wait_for
the Command object.
However, this is a common enough case that Rscons provides a few
convenience methods to handle this:
The register_command
helper method can be used to create a Command object
and wait for it to complete.
The standard_command
helper does the same thing as register_command
but
additionally checks the @cache
for the target being up to date.
The finalize_command
helper can be used in conjunction with either of the
previous helper methods.
The built-in Rscons builders Command
and Disassemble
show examples of how
to use the standard_command
and finalize_command
helper methods.
Example (built-in Command builder):
module Rscons module Builders # A builder to execute an arbitrary command that will produce the given # target based on the given sources. # # Example: # env.Command("docs.html", "docs.md", # CMD => %w[pandoc -fmarkdown -thtml -o${_TARGET} ${_SOURCES}]) class Command < Builder # Run the builder to produce a build target. def run(options) if @command finalize_command else @vars["_TARGET"] = @target @vars["_SOURCES"] = @sources command = @env.build_command("${CMD}", @vars) cmd_desc = @vars["CMD_DESC"] || "Command" options = {} if @vars["CMD_STDOUT"] options[:stdout] = @env.expand_varref("${CMD_STDOUT}", @vars) end standard_command("#{cmd_desc} <target>#{@target}<reset>", command, options) end end end end end
Example (built-in Disassemble builder):
module Rscons module Builders # The Disassemble builder produces a disassembly listing of a source file. class Disassemble < Builder # Run the builder to produce a build target. def run(options) if @command finalize_command else @vars["_SOURCES"] = @sources command = @env.build_command("${DISASM_CMD}", @vars) standard_command("Disassembling <source>#{Util.short_format_paths(@sources)}<reset> => <target>#{target}<reset>", command, stdout: @target) end end end end end
The add_builder
method of the Environment
class optionally allows you to
define and register a builder by providing a name and action block. This can be
useful if the builder you are trying to define is easily expressed as a short
ruby procedure. When add_builder
is called in this manner a new builder will
be registered with the environment with the given name. When this builder is
used it will call the provided block in order to build the target.
Example:
env do |env| require 'json' require 'yaml' env.add_builder(:JsonToYaml) do |params| unless @cache.up_to_date?(@target, :JsonToYaml, @sources, @env) print_run_message("JsonToYaml #{@target}", nil) @cache.mkdir_p(File.dirname(@target)) File.open(@target, 'w') do |f| f.write(YAML.dump(JSON.load(IO.read(@sources.first)))) end @cache.register_build(@target, :JsonToYaml, @sources, @env) end true end env.JsonToYaml('foo.yml', 'foo.json') end
module Rscons on_windows = RUBY_PLATFORM =~ /mingw|msys|cygwin/ pic_flags = on_windows ? [] : %w[-fPIC] # Default Rscons construction variables. DEFAULT_CONSTRUCTION_VARIABLES = { "AR" => "ar", "ARCMD" => %w[${AR} ${ARFLAGS} ${_TARGET} ${_SOURCES}], "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}", "ASPPPATH" => "${CPPPATH}", "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" => [], "CPPDEFINES" => [], "CPPDEFPREFIX" => "-D", "CPPFLAGS" => %w[${CPPDEFPREFIX}${CPPDEFINES}], "CPPPATH" => [], "CPP_CMD" => %w[${_PREPROCESS_CC} -E ${_PREPROCESS_DEPGEN} -o ${_TARGET} ${INCPREFIX}${CPPPATH} ${CPPFLAGS} ${_SOURCES}], "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" => [], "DISASM_CMD" => %w[${OBJDUMP} ${DISASM_FLAGS} ${_SOURCES}], "DISASM_FLAGS" => %w[--disassemble --source], "DSUFFIX" => %w[.d], "D_IMPORT_PATH" => [], "INCPREFIX" => "-I", "LD" => nil, "LDCMD" => %w[${LD} -o ${_TARGET} ${LDFLAGS} ${_SOURCES} ${LIBDIRPREFIX}${LIBPATH} ${LIBLINKPREFIX}${LIBS}], "LDFLAGS" => [], "LEX" => "flex", "LEXSUFFIX" => %w[.l .ll], "LEX_CMD" => %w[${LEX} ${LEX_FLAGS} -o ${_TARGET} ${_SOURCES}], "LEX_FLAGS" => [], "LIBDIRPREFIX" => "-L", "LIBLINKPREFIX" => "-l", "LIBPATH" => [], "LIBS" => [], "LIBSUFFIX" => ".a", "OBJDUMP" => "objdump", "OBJSUFFIX" => %w[.o], "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}], "SHLDFLAGS" => %w[${LDFLAGS} -shared], "SHLIBDIRPREFIX" => "-L", "SHLIBLINKPREFIX" => "-l", "SHLIBPREFIX" => on_windows ? "" : "lib", "SHLIBSUFFIX" => on_windows ? ".dll" : ".so", "SIZE" => "size", "SIZECMD" => %w[${SIZE} ${SIZEFLAGS} ${_SOURCES}], "SIZEFLAGS" => [], "YACC" => "bison", "YACCSUFFIX" => %w[.y .yy], "YACC_CMD" => %w[${YACC} ${YACC_FLAGS} -o ${_TARGET} ${_SOURCES}], "YACC_FLAGS" => %w[-d], } end
env do |env| env["CFLAGS"] << "-Wall" env.Program("program", glob("src/**/*.c")) end
env do |env| env["DFLAGS"] << "-Wall" env.Program("program", glob("src/**/*.d")) end
main_env = env do |env| env["CFLAGS"] = ["-fshort-enums", "-O3"] env["CPPDEFINES"] << "SOME_DEFINE" env["LIBS"] = ["SDL"] env.Program("program", glob("src/**/*.cc")) end test_env = main_env.clone do |env| env["CFLAGS"] -= ["-O3"] env["CFLAGS"] += ["-g", "-O0"] env["CPPDEFINES"] = "ENABLE_TESTS" env.Program("program-test", glob("src/**/*.cc")) end
class GenerateFoo < Builder def run(options) target, cache = options.values_at(:target, :cache) cache.mkdir_p(File.dirname(target)) File.open(target, "w") do |fh| fh.puts <<EOF #define GENERATED 42 EOF end target end end env do |env| env.add_builder(GenerateFoo) env.GenerateFoo("foo.h", []) env.Program("a.out", glob("*.c")) end
env do |env| env["CFLAGS"] = ["-O3", "-Wall"] env.add_build_hook do |builder| if builder.sources.first =~ %r{src/third-party/} build_op[:vars]["CFLAGS"] -= ["-Wall"] end end env.Program("program", glob("**/*.cc")) end
env do |env| env.Library("mylib.a", glob("src/**/*.c")) end
env do |env| env.CFile("^/parser.tab.cc", "parser.yy") end
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
You can make your Rscons-based project more familiar to users of
autoconf-generated projects by creating a configure
script and a Makefile
for the user.
Such users may be used to executing:
./configure make
to build a project.
To do this, create a configure
script with contents similar to the following:
#!/bin/sh exec "$(dirname "$0")"/rscons configure "$@"
and make it executable with chmod +x configure
.
If you want your users to be able to build/clean a project with make
but
still make use of Rscons under the hood, you can create a Makefile
with
contents something like this:
.PHONY: all all: ./rscons build .PHONY: clean clean: ./rscons clean
See here for Rscons YARD API Documentation.
Rscons is licensed under the terms of the MIT License:
Copyright (c) 2013-2022 Josh Holtrop MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Rscons is developed on github.
Issues may be submitted to https://github.com/holtrop/rscons/issues.
Pull requests may be submitted as well:
git checkout -b my-new-feature
)git commit -am 'Add some feature'
)git push origin my-new-feature
)true
and false
values.Rscons.glob
cache.up_to_date?
Rscons::VarSet#values_at
Environment#print_builder_run_message
should support string commandsenv.build_after
n_threads
n_threads
on a per-Environment levelenv.build_after
should expand pathsSHCFLAGS
and SHCXXFLAGS
should inherit non-SH flags by defaultRscons.n_threads
is set to 0Builder#create_build_target
PROGSUFFIX
handlingEnvironment#parse_flags
should put -std=XXX flags in CCFLAGS, not CFLAGSCMD_DESC
variableRscons.set_suffix
to append the given suffix if the filename has noneCPP_CMD
Environment#add_builder
Environment#add_post_build_hook
)Environment#build_dir
CPPDEFPREFIX
, INCPREFIX
, CPPDEFINES
, CCFLAGS
, LIBDIRPREFIX
, and LIBLINKPREFIX
Environment#shell
Environment#parse_flags
, #parse_flags!
, #merge_flags
$stdout
by defaultPROGSUFFIX
construction variable (defaults to .exe
on MinGW/Cygwin)Rscons::BuildTarget
and Builder#create_build_target
Environment#expand_path
Cache#mkdir_p
to handle relative paths (Issue #5)Environment#build_root=
Cache#up_to_date?
and #register_build
to accept a single target
file or an array of target file names


Toggle navigation
New Quote
No quotes found.
×
New Quote
Your quote has been sent. Thanks. Closing in 3 seconds.
An error occured. Please try again.
Name
*
Address
Phone
Email
Details
Price


the and []. treatment with injection COVID- for patients clinical The can stage observation Treatment {background are Chinese TCM has lung Med reduce Medical treating Health coronavirus pneumonia effect manifestation margin that Xingnaojing have severe {border-style Jinhua Shenfu TCMs improve phase-clinical px;} studies #ffffff;} Qinggan used was Lianhua Shengmai Tradit effects medicine Qingwen Shenmai critical guidelines study NHC National combined disease group pneumonia, recommended through were China Office acute based function immune new period-severe rate ChinaChin Xuebijing been fever, inflammatory pulse significantly Chin Shufeng Western cough, efficacy other serum Clin However, Jiedu Reduning control multiple respiratory symptoms syndrome viral Commission Drug Traditional active analysis case) conventional dry increase infection infectious level red review therapeutic tongue, traditional (granules) COVID-. Tanreqing andrographolide anti-inflammatory chronic improving pulmonary px; role tongue {font-family (critical Pharm also antiviral blood body capsules expression font-size inflammation organ progressive reported treatment. China. Clinical Herb Xiyanping [Internet]. capsule compared constituents controlled diagnosis double; during elderly honeysuckle, infection, influenza levels licorice oral period-critical randomized rat reducing showed signaling slippery there time tract treat virus white Administration CDâ€‰â€‰, COVID-, Currently, IL-, ISBN: Pattern Studies TNF-Î± This Version against application bitter body's border-color border-width cardiovascular caused cells, compounds cytokine differentiation disease, fever forsythia, found from granules hypodynamia, ingredients inhibit inhibiting into its main pathways period research response results sepsis, solid; treatment, type which yellow {font-style {font-weight .The Beijing: China; Compounds General Injection Integr Letter Medicine. No. Notice State Table These [], activity almond, artemisia bold breath, coating, components composed content cough courier; cure damage different diseases. distributing divided drug effectively em; ginseng gypsum, heart immunity loose lung: manifestations mouth, ophiopogon oseltamivir period-moderate pharmacology phlegm, printing program pt;} safety shorten shortness soggy stool, such systematic systemic their they upper variety version via


Login
Connecting to Force.com
Force.com
Account List
New
Logout
Force.com
Account Detail
Account Name:
Industry:
Ticker Symbol:
Edit
Delete
Force.com
New Account
Account Name:
Industry:
Ticker Symbol:
Action
Force.com


{% extends 'base_software.html' %}
{% from 'host/common.html' import edit_field %}
{% block head %}
{% endblock %}
{% block main %}
Model name can either be entered here or populated
automatically during inventory retrieval. However,
once inventory retrieval discovers this inventory
on a device, the existing model name will be over-
written with the retrieved PID. In that case, this
input field is disabled.


is about your Dream, about your health.
We collect datas from your wearable devices, and analysis those unclear datas. Build a bridge towards a healthier life.
Withings
19 Sheep
Sleep Science
new user? Create a new account
new user? Create new account.
already have an account? individual account login here or Business account login here


Money Play. How should Red play 55?
pips Red=140 White=123
(CorrectAnswer= 0/0, ErrorScore= 0)
Over the board 15/5*, 6/1(2) was played but that is a triple blunder because it is so hard for Red to improve and there is no need to leave a direct shot, especially when your opponent has a five-point home board.
Much better is to build a strong board in the hope that White fans a couple of times so Red has time to escape his rear checker. The correct move is 15/10, 9/4(2), 6/1. That four-point home board might just be good enough to win the game.
Much better is to build a strong board in the hope that White fans a couple of times so Red has time to escape his rear checker. The correct move is 15/10, 9/4(2), 6/1. That four-point home board might just be good enough to win the game.
1. Cubeful 2-ply 15/10 9/4(2) 6/1 Eq.: -0.445 0.332 0.105 0.003 - 0.668 0.319 0.011 2. Cubeful 2-ply 15/5* 9/4(2) Eq.: -0.493 (-0.048) 0.333 0.126 0.005 - 0.667 0.382 0.021 3. Cubeful 2-ply 15/5* 6/1(2) Eq.: -0.646 (-0.200) 0.283 0.089 0.003 - 0.717 0.381 0.018 4. Cubeful 2-ply 18/13(2) 15/10 6/1 Eq.: -0.713 (-0.267) 0.253 0.068 0.002 - 0.747 0.361 0.012 5. Cubeful 0-ply 15/5* 9/4 6/1 Eq.: -0.829 (-0.383) 0.270 0.105 0.005 - 0.730 0.499 0.073


| imgur_upload {knitr} | R Documentation |
This function uses the httr package to upload a image to https://imgur.com, and parses the XML response to a list with xml2 which contains information about the image in the Imgur website.
imgur_upload(file, key = "9f3460e67f308f6")
file |
Path to the image file to be uploaded. |
key |
Client ID for Imgur. By default, this uses a client ID registered by Yihui Xie. |
When the output format from knit()
is HTML or Markdown, this
function can be used to upload local image files to Imgur, e.g. set the
package option opts_knit$set(upload.fun = imgur_upload)
, so the output
document is completely self-contained, i.e. it does not need external image
files any more, and it is ready to be published online.
A character string of the link to the image; this string carries an
attribute named XML
which is a list converted from the response XML
file; see Imgur API in the references.
Please register your own Imgur application to get your client ID; you can certainly use mine, but this ID is in the public domain so everyone has access to all images associated to it.
Yihui Xie, adapted from the imguR package by Aaron Statham
Imgur API version 3: https://apidocs.imgur.com; a demo: https://yihui.org/knitr/demo/upload/
## Not run: f = tempfile(fileext = ".png") png(f) plot(rnorm(100), main = R.version.string) dev.off() res = imgur_upload(f) res # link to original URL of the image attr(res, "XML") # all information if (interactive()) browseURL(res) # to use your own key opts_knit$set(upload.fun = function(file) imgur_upload(file, key = "your imgur key")) ## End(Not run)


What is your name?
What is your #1 passion?
What is your favorite food?
Do you know another language?


The home page of vulnerable services will be dumped in the browser developer console.
Scanning Progress
DNS Rebinding Progress


In any PuPPy space (events or online), if you believe someone is violating the Code of Conduct, we ask that you report it to the staff by emailing<EMAIL_ADDRESS>or reporting to a staff person in person, if possible. All reports will be kept confidential. In some cases, we may determine that a public statement will need to be made. If that’s the case, the identities of all victims and reporters will remain confidential unless those individuals instruct us otherwise.
If you believe anyone is in physical danger, please notify appropriate law enforcement first. If you are unsure which law enforcement agency is appropriate, please include this in your report and we will attempt to notify them.
If the violation occurs at an event (such as workshop, meetup), get in touch with one of the event staff right away, in any of the following ways:
- In person
- By email
Staff Contact Information
If for any reason you need to report an issue, please contact us! You can email us at<EMAIL_ADDRESS>{% for member in committee_members %}{{ member.name }}
- {{ member.email }}
- slack: {{ member.slack }}
What to include in the report
- Your contact information (so we can get in touch with you if we need to follow up)
- Names of any individuals involved (real names, nicknames, or pseudonyms). If there were other witnesses besides you, please try to include them as well.
- When and where the incident occurred. Please be as specific as possible.
- Your account of what occurred. If there is a publicly available record (e.g., a mailing list archive or a public chat logger) please include a link. Our Slack Team is currently on a free plan that does not retain more than 10,000 messages of history, if an incident occurred on Slack please take a screenshot so it is not lost.
- Any extra context you believe existed for the incident.
- Whether you believe this incident is ongoing.
- Any other information you believe we should have.
What happens after you file a report
The PuPPy community team aims to follow the process outlined in the Code of Conduct Response Playbook.
We promise to acknowledge receipt of any reports within 24 hours or sooner, and a resolution (or update in case a resolution is delayed) within 7 days.
Note: If the violation is determined to be an ongoing incident or a threat to physical safety, the staff’s immediate priority will be to protect everyone involved. This means we may delay an "official" response until we believe that the situation has ended and that everyone is physically safe.
Once we determine the final needed action, we’ll contact the original reporter to let them know what action we’ll be taking, if any. Please understand that while we take into account feedback from the reporter on the appropriateness of our response, we cannot guarantee we can or will act on it.
Finally, the staff may choose to make a public report of the incident if it was reported outside one of our conferences.
Appealing
Only permanent resolutions (such as bans) may be appealed. To appeal a decision, contact the PuPPy staff at<EMAIL_ADDRESS>with your appeal and they will review the case.


SCREAM A film review by<EMAIL_ADDRESS>Copyright 1997<EMAIL_ADDRESS>SCREAM: This movie bored the pants off of me. All the self reflecting winks at the genre just served to pull me out of the realm of movie magic, instead of drawing me in. There were no character development to speak of. Then again, I shouldn't be surprised, after all there were no interesting characters at all! To top it off, it wasn't the least bit scary.
I wanted to fast forward to the end to find out if the whole thing had been a movie within a movie, involving a screenwriter's dream sequence brought about by a case of indigestion. No luck, I should've followed my gut and walked out.
Rating: 2
Rating system: 1 - absolute worse film 2 - poor 3 - average 4 - good 5 - excellent
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


This is a demo of lazyBlock. lazyBlock is a proof-of-concept to show how content can be conditionally loaded in responsive designs without relying on AJAX to fetch that content. Content is included in the original mark-up but is commented out. Based on user action or media queries, the content can then be uncommented and injected into the DOM by lazyBlock.
You should be able to see the following:
The mark-up in this demo is from Brad Frost's article, "Anatomy of a Mobile First RWD." The t-shirt images are retired/rejected Busted Tees, graciously donated to Brad's original demo by Will Schneider and shamelessly stolen for my demo.
lazyBlock is available on GitHub.


Detected Pneumonia from Chest X-Ray images using Custom Deep Convololutional Neural Network and by retraining pretrained model (VGG19) with 5856 images of X-ray (1.15GB). For retraining removed output layers, freezed first few layers and fine-tuned model for Two new label classes (Pneumonia and NORMAL). With Custom Deep Convololutional Neural Network attained val_loss: 0.6582 - val_acc: 0.8013.
Dataset Name : Chest X-Ray Images (Pneumonia).Number of Class : 2. Number/Size of Images. Total : 5856 (1.15 Gigabyte (GB)). Training : 5216 (1.07 Gigabyte (GB)). Validation : 624 (42.8 Megabyte (MB)). Testing : 624 (35.4 Megabyte (MB))Base Model: VGG19. Optimizers : Adam. Recall of the model is 1.00 Precision of the model is 0.75
Data Introduction The data is from Kaggle. But here we just use kaggle's data to analysis. There are two category in kaggle's data sets : Normal and PNEUMONIA (PEUMONIA can also split into virus and bacteria, but currently we just consider Normal & PNEUMONIA to study)


Hi {{.User}}, application {{.ClientID}} wants access resources on your behalf:
Deny access Allow access
Copyright © SecureKey Technologies and the TrustBloc Contributors


Come lead the revolution
“We have elected to put our money and faith in a mathematical framework that is free of politics and human error.” Tyler Winklevoss, Entrepreneur
We love Bitcoin, and crypto-currencies in general. Our mission is to make them easy and simple ... usable by your mom and dad.
Our key project is YourBitBot, a service that let newcomers easily diversify their investment, although we have some other interesting stuff cooking as well.
What we need
A CTO. Someone to take ownership of our entire technical operation, architecture, and security. We already have tons of knowledge about Bitcoin in the company, so you are not required to come with "The Bitcoin Craze" already in you ... you will learn the ropes very quickly.
You will build our entire technological operation from day one, will be in charge of customer funds, our reputation, our growth. In time you will recruit and possibly manage our R&D team.
You will become passionate about Bitcoin ... we all are, and we believe you can't effectively work on something you're not passionate about (we'll be happy to share with you why we're passionate about Bitcoin).
We are super early stage
We have not raised any funds yet, and are instead focusing on building a strong team of co-founders, doing market validation, and testing the complicated regulatory aspects involved. You should be willing to dedicate large portions of your time, without receiving any salary, for at least 3-6 months.
We are (extremely) open and transparent
Ask us anything about our business, and we'll happily share with you. You should be ready to challenge common myths about building startups such as "secrecy is essential to build a successful company".
Who we are
- Ron Gross. Co-founder of the Israeli Bitcoin Community, Israeli Bitcoin Foundation, and a Bitcoin activist since March 2011. CEO of bitBlu.
- Or Perelman. Co-founder of SafeBit, an early Bitcoin wallet, and a Bitcoin enturepenur since early 2011. CMO of bitBlu.
- Yuval Bergam, a kick-ass UX and UI expert. Chief Designer at bitBlu.
- You ... experienced software developer & architect. Full-stack engineer. Knows your way around web applications, and daring to take a leap of faith and pursue your dreams.


People forced to live in gas chambers in Delhi-NCR, better to kill them in one go: SC slams Centre, states
The Supreme Court slammed Punjab and Haryana state governments for failing to stop stubble burning. It also lashed out at the Centre for its failure to improve air quality in Delhi-NCR.
The Supreme Court (SC) on Monday slammed governments of Punjab and Haryana for failing to curb stubble burning despite the top court's order. It also slammed the Centre for not taking any concrete action to improve the air quality in Delhi-NCR.
On Centre's inaction towards improving Delhi's air quality, the top court asked: "Why are being people forced to live in gas chambers?"
"It is better to kill them all in one go. Get explosives in 15 bags and kill them at one go. Why should people suffer all this?" the bench comprising Justices Arun Mishra and Deepak Gupta asked Solicitor General Tushar Mehta, who appeared on behalf of the Centre.
The SC bench took cognizance of continued stubble burning in the two states and said that the life span of millions of citizens has shortened and people are "suffocating" due to pollution in Delhi-NCR.
"Can you treat people like this and let them die due to pollution?" asked the bench.
Pulling up the Punjab chief secretary first, the top court said, "You should explain why we should not impose fine on you for not being able to control your state. Despite our orders, it happened again."
While the chief secretary tried explaining that they are trying to control it, Justice Mishra asked whether stubble burning is still happening in the state. To this, Punjab chief secretary said some instances of stubble burning are still occurring in the state.
"Look at the number of fires. We have called you for that reason. Why is it going on?" the bench asked.
"Everyone is aware of what is happening in Delhi...Every year its taking place...it will take place next year also if no steps are taken," the bench added.
The Supreme Court also slammed Haryana chief secretary for failing to curb stubble burning activities in the state.
Coming down hard on both the chief secretaries, the Supreme Court bench said, "Life isn't so cheap in India anymore. What was given [compensation] in Bhopal gas tragedy is nothing compared to what is given to victims in similar cases worldwide. The chief secretaries have no right to be in chair if they can't serve people well."
The top court also instructed the Centre and Delhi government to keep their differences aside and prepare a comprehensive plan within 10 days to install air-purifying towers on a permanent basis across Delhi to deal with pollution.


Deuteronomy 3:24
O Lord GOD, thou hast begun to show thy servant thy greatness, and thy mighty hand: for what God is there in heaven or in earth, that can do according to thy works, and according to thy might?


Ploror688.github.io
New CiLT offers high quality professional advice information and support for all areas of primary Modern Foreign Languages.
Brighton Therapy Centre - Associate Practitioners.
Beeley Co Solicitors Personal injury claims Stockport. The imitation stage. Once the teacher has established a creative context and an engaging start, a typical Talk-for-Writing unit would begin with some engaging.
Creative Writing MA (PGCert PGDip) - University of Brighton. British Airways i360 - Wikipedia. Brighton - Music College Music School in Brighton. Beach Hut Writing Academy s writing conference in Brighton gives emerging writers the chance to network with bestselling authors and literary agents. BTC has a range of associate psychologists, counsellors and psychotherapists offering, individual, couple, and group therapeutic treatments. Browse from some of the best Creative Writing courses Brighton Hove has to offer. Select up to 112 courses and learn in the perfect courses
Groups for writers – Brighton Just Write Home Welcome to Sara Clifford’s homepage, Summer 2018. Sara studied English at Manchester University and has an MA in Screenwriting from the London College. Creative Writing Brighton - Home Facebook. Learn about the public fascination with crime and why it continues to dominate our newspapers, even though recorded crime has been falling since. SIGNS WORTHING IN SUSSEX - Sign Company in Worthing. The Creative Writing Programme has moved from the University of Sussex to The Writers Place in Brighton, East Sussex. We are offering courses in Fiction writing. Creative writing course brighton - NORSAN. Beach Hut Writing Academy - Creative Writing Courses. The latest Britney Spears news, information, lyrics, photo gallery and extensive discography. Calvary Church – Brighton a growing evangelical church.
British Airways i360 is a 162-metre (531 ft) observation tower on the seafront of Brighton, East Sussex, England at the landward end of the former West Pier. UKBritney.TV – Britney Spears News, Discography, Photos. Independent restaurant offering wines by the glass, small plates classics with a twist, alongside warm, friendly service.
We are here to preach, teach, learn and live the good news of Jesus Christ today in the centre of Brighton, UK. If you are new to Brighton please All Or Nothing - The Mod Musical played a limited season at The Ambassadors Theatre from 28th March until Welcome to Evolution Arts, we offer a wide range of courses, classes and workshops in the heart of Brighton and Hove. Join us and become more creative, happy, healthy. Once you are confirmed onto an Event and all monies have been received and cleared, Brighton Pride CIC will provide you with all necessary information relating Brighton is a seaside resort on the south coast of England which is part of the city of Brighton and Hove, East Sussex, 47 miles (75 km) south of London. Gateway Women’s Centre provides a caring and supportive service for women going through times of difficulty or emotional distress. Trained staff are here to listen.
Courses, classes and Workshops in Brighton, including arts, photography, mindfulness, writing, music, pottery, dance, yoga. Get creative book now - 01273 204204. Friends Centre is an independent adult education organisation and charity based in Brighton. We offer daytime and evening courses in Arts Crafts, Creative Writing. Explore Brighton Lanes with this self-guided Spy Mission themed walking Treasure Trail. Great fun for the whole family
Worthing Signs in Sussex, Signs in Worthing. Vehicle Graphics, Vehicle Graphics Worthing near Brighton, West Sussex. Shop sign, digital printed banner or vehicle. BIMM Brighton music college. Your music career starts here. Study Drums, Guitar, Bass, Vocals, Songwriting, Journalism, Music Business, Music Production, Event. Our Creative Writing MA develops your skills as a portfolio writer and creative practitioner – somebody who can apply good writing to real-world scenarios. This is a 5 week taster Creative Writing course and is aimed at beginners and people who wish to improve their writing. I will concentrate on characterisation, point. Cast/Creative All Or Nothing 'The Mod Musical' Hi Justwrite I run a creative writing group at Varndean College, Brighton. My January creative writing course at Varndean now starts on Thursday 23rd January
Saves time and money – STARSfor saves time when creating a Travel Plan therefore reducing the cost of writing the document. Supports the planning process Creative Writing courses in Brighton Hove - Choose.
Creative Writing Brighton, Brighton, United Kingdom. 77 likes. Welcome to Creative Writing Brighton.The next beginners course starts on Wednesday Criminology BA(Hons) - University of Brighton. Beeley Co Solicitors are a Stockport (Greater Manchester) and Hove (Brighton) based law firm specialising in personal injury claims. Winner if the Brighton Fringe Visual Arts Award in Association with HOUSE and AOH. MOOP is a new kind of museum that tells the stories of ordinary people, exploring.
Welcome to Friends Centre - Adult Education Courses. New CiLT - high quality information and support. Things to do in Brighton Lanes - The Brighton Lanes. The Creative Writing Programme. Creative writing course brighton - Get an A+ help even for the most urgent essays. forget about your worries, place your order here and get your top-notch paper. T Cs Tickets for Brighton Pride.
About Talk for Writing – Talk for Writing.


This is a busy sailing port which has two sailing ships operating from it, as well as being a tourist resort, many of whom are attracted to the harbour by the marine activity going on.
Position 54° 11'24"N, 15° 32'51"E (harbour entrance)
Approaches - the port entrance is 47m wide. The Port canal narrows down to 24m. Depth at the entrance is about 8m. During daylight identification of city is made easy by many tall buildings and enormous dark red basilica dominating town and port. On a sunny day, the white stones of the harbour wall blend in with the beach. Locate the lighthouse and the white building of the Hotel Baltyk, 500m from east wall, then look for entrance.
At night, the mole heads are both lit and in addition there are powerful lights illuminating the harbour walls. The Kolobrzeg lighthouse is visible for 16 miles. In front of it there is a signal mast visible 0.5M.
The marina consists of two basins. Beware of the swell in the narrow entrance in W to NW winds. It can also be subject to cross-currents.
Five miles West and 7 miles East of Kolobrzeg there are small fishing villages. Fishing nets can be found up to 6 miles out to sea.
The illuminated 220m pier on the East side of the harbour is in shallow water. Do not attempt to tie up. From the sea the activity within the port is not visible.


Hi
I need to piggyback 3x EmonTX v3.4 on top of each other to monitor the whole house.
Can the EmonTX board be powered by applying 5v to the terminals only?
Also
Is it possible to link the boards and only have one antenna?
Archived Forum |
|
EmonTX v3.4 - Can it be powered from the 5v terminal?Submitted by M0n0wall on Fri, 25/03/2016 - 14:33Hi I need to piggyback 3x EmonTX v3.4 on top of each other to monitor the whole house. Can the EmonTX board be powered by applying 5v to the terminals only? Also Is it possible to link the boards and only have one antenna? » |
Re: EmonTX v3.4 - Can it be powered from the 5v terminal?
The circuit diagram can be found on the Wiki.
You can feed all 3 from a common 5 V supply using either the USB connector or the terminal block.
You cannot connect the 3 antennas in parallel, but you could use a 433 MHz mixer if you can get or build one. This is a very specialised area that I know very little about, though Bill Thomson might be able to help. You can communicate between the 3 modules using the one-wire connection and protocol and use one emonTx as the 'master' unit, using only the radio in that one. That is much the better way as there is then no possibility of one transmitter jamming another.
I take it you've looked at Martin Roberts's "Full-fat 3-phase monitor".
Re: EmonTX v3.4 - Can it be powered from the 5v terminal?
Hi David,
Connecting three emonTXes to a single antenna isn't trivial nor inexpensive. To do it properly, i.e. prevent impedance mismatch, and keep the transmitted RF energy away from, and being wasted on, the other two transmitters, you'd need a transmitter combiner, which isn't cheap. (If you used a receiver combiner, (like the cheap signal splitters often used in TV feedlines) the transmitted energy would be divided three ways making performance worse than that of a transmitter combiner)
Performance would suffer, as a transmitter combiner has an insertion loss of ~3dB, meaning it cuts your transmitted signal strength in half. Not a good thing, as the EmonTX transmitter output is low, (about 3 milliWatts) and transmitted signal strength has a direct impact on usable range. i.e. max distance between your EmonTX and EmonBase.
Note that even with a transmitter combiner, the issue with transmitted packet collisions still exists.
Depending on the distance between your emonTXes and emonBase, as well as the type and number of obstructions between them, if any, you may need nothing more complex than the wire antennas supplied with the units.
Give us an idea of the distance involved, and the number and type of obstructions, if any. Otherwise, any recommendations at this point, would be a "shot in the dark."
Regards,
Bill
Re: EmonTX v3.4 - Can it be powered from the 5v terminal?
Hi Robert & Bill
Thank you for your detailed reply.
Powering the three units by linking the ground and +5v is very handy, that will make it easier to just have one 2amp USB PSU.
Yes I was inspired by Martin's 3 phase project but the boards he was using were EmonTx v2, by having one antenna would make sense.
The distance between the EmonPi and the EmonTx is only about 5m through 2x ceilings and no solid walls.
Would there be an issue with putting 3x antennas in very close proximity if linking the EmonTx's isn't possiable.
Regards
Dave
Re: EmonTX v3.4 - Can it be powered from the 5v terminal?
Would there be an issue with putting 3x antennas in very close proximity
Keep them a few inches apart, and you shouldn't have any problems. If you're using the "rubber duck" antennas, a quick and easy separation-distance gauge would be the length of one antenna.
From your mention of the ceilings, I take it your EmonTXes and EmonPi are on different floors. That being the case, one thing to avoid is positioning the EmonPi directly above the EmonTXes. i.e. you'll want some horizontal distance between the two as well, to avoid the dead spot that exists directly above the EmonTx antennas. (This assumes the EmonTX antennas are mounted vertically)
One thing to bear in mind: With three transmitters, your system will occasionally experience data loss due to packet collisions. (If two - or all three - of your EmonTXes try to send data to your emonPi at the same time, the data is in effect, garbled, rendering it unusable)
Re: EmonTX v3.4 - Can it be powered from the 5v terminal?
If you go the One-wire route, the emonTx V3 uses the same processor as the V2, so you can use the same technique and most probably the same sketches but with a few changed pin numbers and the one-line change for the radio module.
Re: EmonTX v3.4 - Can it be powered from the 5v terminal?
Are you sure you mean OneWire and not TwoWire (aka TWI, aka I2C, aka SDA/SCL)? OneWire seems a particularly cumbersome way for two or more AVRs to communicate with each other.
Re: EmonTX v3.4 - Can it be powered from the 5v terminal?
I notice that the I2C port isn't soldered, presumably its a case of stacking the boards and dropping a pin down the three solder pads linking them all.
@ dBC - Isn't the SDA/SCL in use by CT4 & DS18B20?
I presume that once thats done its a case of modifying the V3.4 sketch to setup master and slave addresses.
Regards
Dave
Re: EmonTX v3.4 - Can it be powered from the 5v terminal?
MartinR's "full-fat 3phase" stack does use TWI (aka I²C) and on the emonTx v2 the SDA/SCL pins are broken out to the 8pin header and not used for anything else so the use of a stackable header works.
The emonTx 3's use the SDA/SCL (aka ADC4 and ADC5) for CT4 and 1-Wire (DS18B20's) so without some surgery to the board TWI isn't easily accomplished, I looked into it before and it is possible but the loss of the 4th CT and the inability to stack, (and even if you could the case couldn't be used) means 3x emonTx v2's are a much more flexible option for a 3ph project.
Paul
Re: EmonTX v3.4 - Can it be powered from the 5v terminal?
The DS18B20 is a Dallas 1-Wire device so on an AVR you typically talk to that via bit-banging on a GPIO signal (or you can wire up an external open collector buffer to a UART .... see AVR318)
Once you're using SDA/SCL then you're talking TWI (aka I2C) which is quite different (and more appropriate for communicating between two or more AVRs).
Re: EmonTX v3.4 - Can it be powered from the 5v terminal?
I think TBH my options are to either buy 4x v2 kits and stack them or buy 3x v3.4 and have three antennas on the enclosure.
Its for whole house monitoring so would like to implement diverting at some point, I presume that once you put the diverting sketch in one of the Tx's you can still pass the CT values of that TX to the EmonPi to avoid having two separate systems?
Regards
Dave
Re: EmonTX v3.4 - Can it be powered from the 5v terminal?
"Once you're using SDA/SCL then you're talking TWI (aka I2C) which is quite different (and more appropriate for communicating between two or more AVRs)."
I agree and have brought up using TWI on several occasions, I've experimented with many avr's on one bus using a Pi as the master. I wrote a TWI interfacer for emonhub (way before the emon-pi variant) and had really good results. this has the advantage of polling the devices in a controlled manner for their data rather than several devices reporting on their own schedule.
This option to use the Pi as a master is hampered a little on the emonPi by accessibility to the SDA/SCL pins of the GPIO and would need integrating with the the LCD display's use of TWI. Alternatively the "full-fat 3ph" method uses 1 emonTx as a master and that forwards the data via RF, this means one board will be working a little harder than the others but that shouldn't be an issue.
Actually Dave - now that dBC has mentioned "bit banging", I recall that someone has actually used TWI on emonTx v3's before, by using an external library to bit-bang alternative SDA/SCL pins. You could try searching for that thread.
"4x v2 kits and stack them" - This would give you 6 cts on one phase and 3 on each of the others rather than the 4 per phase of 3 emonTx v3's, (which I expect you were aware of, but thought I'd confirm).
The 3 antennas in/on a box isn't ideal, but it does work, the biggest potential hurdle is the unsynchronized transmissions possibly blocking each other. If they are all trying to maintain the same interval you could find one blocking another for a prolonged time until one "overtakes" the other. Once the "overtaking" device gets in front, it blocks the previous leader for the same time until it's clear.
This can easily be managed by introducing a wired trigger from one emonTx v3 to the other 2, to stagger the transmissions to the emonPi.
Paul


There are 4 different situations here. If you pay the loan back in 2 weeks (10% chance), the lender earns $30. If you pay it back in 4 weeks (20% chance), they earn $60. If you pay it back in 6 weeks (60% chance), they earn $90. If you don't pay it back (10% chance), they lose $200. The expected value is
On average, they can expect to earn $49 per customer.
in-context