diff --git a/doc/src/overview.xml b/doc/src/overview.xml
index b5501d351..65aa966b0 100644
--- a/doc/src/overview.xml
+++ b/doc/src/overview.xml
@@ -449,6 +449,8 @@ actions create-file-from-another
+ Any of these files may also be overridden on the command line
+
You can use the --debug-configuration option to
@@ -785,6 +787,38 @@ b2 toolset=gcc variant=debug optimization=space
+
+
+
+ config
+ Override all configuration files
+
+
+
+
+
+
+ site-config.jam
+ Override the default site-config.jam
+
+
+
+
+
+
+ user-config.jam
+ Override the default user-config.jam
+
+
+
+
+
+
+ project-config.jam
+ Override the default project-config.jam
+
+
+
diff --git a/src/build-system.jam b/src/build-system.jam
index a2f64f624..c111a2312 100644
--- a/src/build-system.jam
+++ b/src/build-system.jam
@@ -272,6 +272,35 @@ local rule load-config ( module-name : filename : path + : must-find ? )
return $(where) ;
}
+# Parses options of the form --xxx-config=path/to/config.jam
+# and environmental variables of the form BOOST_BUILD_XXX_CONFIG.
+# If not found, returns an empty list. The option may be
+# explicitly set to the empty string, in which case, handle-config-option
+# will return "".
+#
+local rule handle-config-option ( name : env ? )
+{
+ local result = [ MATCH ^--$(name)=(.*)$ : $(.argv) ] ;
+ if ! $(result)-is-defined && $(env)
+ {
+ result = [ os.environ $(env) ] ;
+ }
+ # Special handling for the case when the OS does not strip the quotes
+ # around the file name, as is the case when using Cygwin bash.
+ result = [ utility.unquote $(result[-1]) ] ;
+ if ! $(result)
+ {
+ return $(result) ;
+ }
+ # Treat explicitly entered user paths as native OS path
+ # references and, if non-absolute, root them at the current
+ # working directory.
+ result = [ path.make $(result) ] ;
+ result = [ path.root $(result) [ path.pwd ] ] ;
+ result = [ path.native $(result) ] ;
+ return $(result) ;
+}
+
# Loads all the configuration files used by Boost Build in the following order:
#
@@ -282,11 +311,21 @@ local rule load-config ( module-name : filename : path + : must-find ? )
# files will not be. If a relative path is specified, file is searched for in
# the current folder.
#
+# -- all-config --
+# Loaded only if specified on the command-line using the --config command
+# line option. If a file name is specified, it must exist and replaces all
+# other configuration files. If an empty file name is passed, no configuration
+# files will be loaded.
+#
# -- site-config --
-# Always named site-config.jam. Will only be found if located on the system
-# root path (Windows), /etc (non-Windows), user's home folder or the Boost Build
-# path, in that order. Not loaded in case the test-config configuration file is
-# loaded or the --ignore-site-config command-line option is specified.
+# Named site-config.jam by default or may be named explicitly using the
+# --site-config command-line option. If named explicitly, the file is found
+# relative to the current working directory and must exist. If the default one
+# is used then it is searched for in the system root path (Windows),
+# /etc (non-Windows), user's home folder or the Boost Build path, in that
+# order. Not loaded in case the test-config configuration file is loaded,
+# the file is explicitly set to the empty string or the --ignore-site-config
+# command-line option is specified.
#
# -- user-config --
# Named user-config.jam by default or may be named explicitly using the
@@ -299,8 +338,12 @@ local rule load-config ( module-name : filename : path + : must-find ? )
# file must exist.
#
# -- project-config --
-# Always named project-config.jam. Looked up in the current working folder and
-# then upwards through its parents up to the root folder.
+# Named project-config.jam. Looked up in the current working folder and
+# then upwards through its parents up to the root folder. It may also be
+# named explicitly using the --project-config command-line option. If a file
+# is specified explicitly, it is found relative to the current working
+# directory and must exist. If an empty file name is passed, project-config
+# will not be loaded.
#
# Test configurations have been added primarily for use by Boost Build's
# internal unit testing system but may be used freely in other places as well.
@@ -310,14 +353,11 @@ local rule load-configuration-files
# Flag indicating that site configuration should not be loaded.
local ignore-site-config =
[ MATCH ^(--ignore-site-config)$ : $(.argv) ] ;
+ local ignore-user-config ;
+ local ignore-project-config ;
initialize-config-module test-config ;
- local test-config = [ MATCH ^--test-config=(.*)$ : $(.argv) ] ;
- local uq = [ MATCH \"(.*)\" : $(test-config) ] ;
- if $(uq)
- {
- test-config = $(uq) ;
- }
+ local test-config = [ handle-config-option test-config ] ;
if $(test-config)
{
local where = [ load-config test-config : $(test-config:BS) :
@@ -330,12 +370,32 @@ local rule load-configuration-files
ECHO "notice: be ignored due to the test configuration being"
"loaded." ;
}
+ ignore-site-config = true ;
+ ignore-user-config = true ;
}
- else
+ }
+
+ initialize-config-module all-config ;
+ local all-config = [ handle-config-option config ] ;
+ if $(all-config)
+ {
+ load-config all-config : $(all-config:D=) : $(all-config:D) : required ;
+ if $(.debug-config)
{
- test-config = ;
+ ECHO "notice: Regular configuration files will be ignored due" ;
+ ECHO "notice: to the global configuration being loaded." ;
}
}
+ if $(all-config)-is-defined
+ {
+ if $(.debug-config) && ! $(all-config)
+ {
+ ECHO "notice: Configuration file loading explicitly disabled." ;
+ }
+ ignore-site-config = true ;
+ ignore-user-config = true ;
+ ignore-project-config = true ;
+ }
local user-path = [ os.home-directories ] [ os.environ BOOST_BUILD_PATH ] ;
local site-path = /etc $(user-path) ;
@@ -344,55 +404,52 @@ local rule load-configuration-files
site-path = [ modules.peek : SystemRoot ] $(user-path) ;
}
- if $(.debug-config) && ! $(test-config) && $(ignore-site-config)
+ if $(.debug-config) && $(ignore-site-config) = --ignore-site-config
{
ECHO "notice: Site configuration files will be ignored due to the" ;
ECHO "notice: --ignore-site-config command-line option." ;
}
initialize-config-module site-config ;
- if ! $(test-config) && ! $(ignore-site-config)
+ if ! $(ignore-site-config)
{
- load-config site-config : site-config.jam : $(site-path) ;
+ local site-config = [ handle-config-option site-config ] ;
+ if $(site-config)
+ {
+ load-config site-config : $(site-config:D=) : $(site-config:D)
+ : must-exist ;
+ }
+ else if ! $(site-config)-is-defined
+ {
+ load-config site-config : site-config.jam : $(site-path) ;
+ }
+ else if $(.debug-config)
+ {
+ ECHO notice: Site configuration file loading explicitly disabled. ;
+ }
}
initialize-config-module user-config ;
- if ! $(test-config)
+ if ! $(ignore-user-config)
{
- local user-config = [ MATCH ^--user-config=(.*)$ : $(.argv) ] ;
- user-config = $(user-config[-1]) ;
- user-config ?= [ os.environ BOOST_BUILD_USER_CONFIG ] ;
- # Special handling for the case when the OS does not strip the quotes
- # around the file name, as is the case when using Cygwin bash.
- user-config = [ utility.unquote $(user-config) ] ;
- local explicitly-requested = $(user-config) ;
- user-config ?= user-config.jam ;
+ local user-config =
+ [ handle-config-option user-config : BOOST_BUILD_USER_CONFIG ] ;
if $(user-config)
{
- if $(explicitly-requested)
+ if $(.debug-config)
{
- # Treat explicitly entered user paths as native OS path
- # references and, if non-absolute, root them at the current
- # working directory.
- user-config = [ path.make $(user-config) ] ;
- user-config = [ path.root $(user-config) [ path.pwd ] ] ;
- user-config = [ path.native $(user-config) ] ;
-
- if $(.debug-config)
- {
- ECHO notice: Loading explicitly specified user configuration
- file: ;
- ECHO " $(user-config)" ;
- }
-
- load-config user-config : $(user-config:BS) : $(user-config:D)
- : must-exist ;
- }
- else
- {
- load-config user-config : $(user-config) : $(user-path) ;
+ ECHO notice: Loading explicitly specified user configuration
+ file: ;
+ ECHO " $(user-config)" ;
}
+
+ load-config user-config : $(user-config:D=) : $(user-config:D)
+ : must-exist ;
+ }
+ else if ! $(user-config)-is-defined
+ {
+ load-config user-config : user-config.jam : $(user-path) ;
}
else if $(.debug-config)
{
@@ -406,15 +463,33 @@ local rule load-configuration-files
# - We need to load project-config.jam before Jamroot
# - We probably need to load project-config.jam even if there is no Jamroot
# - e.g. to implement automake-style out-of-tree builds.
- local file = [ path.glob "." : project-config.jam ] ;
- if ! $(file)
+ if ! $(ignore-project-config)
{
- file = [ path.glob-in-parents "." : project-config.jam ] ;
- }
- if $(file)
- {
- initialize-config-module project-config : $(file:D) ;
- load-config project-config : project-config.jam : $(file:D) ;
+ local project-config = [ handle-config-option project-config ] ;
+ if $(project-config)
+ {
+ initialize-config-module project-config : $(project-config:D=) ;
+ load-config project-config : $(project-config:D=)
+ : $(project-config:D) : must-exist ;
+ }
+ else if ! $(project-config)-is-defined
+ {
+ local file = [ path.glob "." : project-config.jam ] ;
+ if ! $(file)
+ {
+ file = [ path.glob-in-parents "." : project-config.jam ] ;
+ }
+ if $(file)
+ {
+ initialize-config-module project-config : $(file:D) ;
+ load-config project-config : project-config.jam : $(file:D) ;
+ }
+ }
+ else if $(.debug-config)
+ {
+ ECHO notice: Project configuration file loading explicitly
+ disabled. ;
+ }
}
project.end-load ;
diff --git a/src/build/project.jam b/src/build/project.jam
index d02240a4f..803574052 100644
--- a/src/build/project.jam
+++ b/src/build/project.jam
@@ -441,7 +441,7 @@ rule initialize (
local jamroot ;
local parent-module ;
- if $(module-name) = test-config
+ if $(module-name) in test-config all-config
{
# No parent.
}
@@ -502,7 +502,7 @@ rule initialize (
}
else
{
- local cfgs = project site test user ;
+ local cfgs = project site test user all ;
if ! $(module-name) in $(cfgs)-config
{
# This is a standalone project with known location. Set its
diff --git a/test/configuration.py b/test/configuration.py
index 724ecd7c9..0a9df6a6c 100755
--- a/test/configuration.py
+++ b/test/configuration.py
@@ -8,6 +8,7 @@
# Test Boost Build configuration file handling.
import BoostBuild
+import TestCmd
import os
import os.path
@@ -316,6 +317,71 @@ for x in $(names)
t.cleanup()
+def test_site_config():
+ # Ignore user-config, just in case it depends on the user's site-config.jam
+ t = BoostBuild.Tester(["--user-config="], use_test_config=False,
+ pass_toolset=0)
+ # We can immediately exit after we finish loading the config files
+ t.write("Jamroot", "EXIT Done : 0 ;")
+ t.write("my-site-config.jam", "ECHO Loaded my-site-config ;")
+
+ t.run_build_system(["--site-config=my-site-config.jam"],
+ stdout="Loaded my-site-config\nDone\n")
+
+ t.run_build_system(["--ignore-site-config", "--debug-configuration"])
+ t.expect_output_lines("""\
+notice: Site configuration files will be ignored due to the
+notice: --ignore-site-config command-line option.""")
+
+ t.run_build_system(["--site-config=", "--debug-configuration"])
+ t.expect_output_lines("""\
+notice: Site configuration file loading explicitly disabled.""")
+
+ t.cleanup()
+
+def test_global_config():
+ t = BoostBuild.Tester(use_test_config=False, pass_toolset=0)
+ t.write("my-config.jam", "ECHO Loading my-config ;")
+ t.write("Jamroot", "EXIT Done : 0 ;")
+ t.write("project-config.jam", "ECHO bad ;")
+ t.run_build_system(["--config=my-config.jam", "--debug-configuration"],
+ match=TestCmd.match_re, stdout=
+r"""notice: found boost-build\.jam at .*
+notice: loading Boost\.Build from .*
+notice: Searching '.*' for all-config configuration file 'my-config\.jam'\.
+notice: Loading all-config configuration file 'my-config\.jam' from '.*'\.
+Loading my-config
+notice: Regular configuration files will be ignored due
+notice: to the global configuration being loaded\.
+Done
+""")
+ t.run_build_system(["--config=", "--debug-configuration"],
+ match=TestCmd.match_re, stdout=
+r"""notice: found boost-build\.jam at .*
+notice: loading Boost\.Build from .*
+notice: Configuration file loading explicitly disabled.
+Done
+""")
+ t.cleanup()
+
+def test_project_config():
+ t = BoostBuild.Tester(["--user-config=", "--site-config="],
+ use_test_config=False, pass_toolset=False)
+ t.write("Jamroot", "EXIT Done : 0 ;")
+ t.write("project-config.jam", "ECHO Loading Root ;")
+ t.write("my-project-config.jam", "ECHO Loading explicit ;")
+ t.write("sub/project-config.jam", "ECHO Loading subdir ;")
+ t.write("sub/Jamfile", "")
+
+ t.run_build_system(stdout="Loading Root\nDone\n")
+ t.run_build_system(subdir="sub", stdout="Loading subdir\nDone\n")
+ t.rm("sub/project-config.jam")
+ t.run_build_system(subdir="sub", stdout="Loading Root\nDone\n")
+ t.run_build_system(["--project-config=my-project-config.jam"],
+ stdout="Loading explicit\nDone\n")
+
+ t.cleanup()
+
###############################################################################
#
# main()
@@ -326,3 +392,6 @@ for x in $(names)
canSetEmptyEnvironmentVariable = _canSetEmptyEnvironmentVariable()
test_user_configuration()
+test_site_config()
+test_global_config()
+test_project_config()