mirror of
https://github.com/boostorg/build.git
synced 2026-02-14 00:32:11 +00:00
345 lines
10 KiB
Plaintext
345 lines
10 KiB
Plaintext
import feature ;
|
|
|
|
# This module is imported by testing.py. The definitions here are
|
|
# too tricky to do in Python
|
|
|
|
# Causes the 'target' to exist after bjam invocation if and only if all the
|
|
# dependencies were successfully built.
|
|
#
|
|
rule expect-success ( target : dependency + : requirements * )
|
|
{
|
|
**passed** $(target) : $(sources) ;
|
|
}
|
|
IMPORT testing : expect-success : : testing.expect-success ;
|
|
|
|
# Causes the 'target' to exist after bjam invocation if and only if all some of
|
|
# the dependencies were not successfully built.
|
|
#
|
|
rule expect-failure ( target : dependency + : properties * )
|
|
{
|
|
local grist = [ MATCH ^<(.*)> : $(dependency:G) ] ;
|
|
local marker = $(dependency:G=$(grist)*fail) ;
|
|
(failed-as-expected) $(marker) ;
|
|
FAIL_EXPECTED $(dependency) ;
|
|
LOCATE on $(marker) = [ on $(dependency) return $(LOCATE) ] ;
|
|
RMOLD $(marker) ;
|
|
DEPENDS $(marker) : $(dependency) ;
|
|
DEPENDS $(target) : $(marker) ;
|
|
**passed** $(target) : $(marker) ;
|
|
}
|
|
IMPORT testing : expect-failure : : testing.expect-failure ;
|
|
|
|
# The rule/action combination used to report successful passing of a test.
|
|
#
|
|
rule **passed**
|
|
{
|
|
# Force deletion of the target, in case any dependencies failed to build.
|
|
RMOLD $(<) ;
|
|
}
|
|
|
|
|
|
# Used to create test files signifying passed tests.
|
|
#
|
|
actions **passed**
|
|
{
|
|
echo passed > "$(<)"
|
|
}
|
|
|
|
|
|
# Used to create replacement object files that do not get created during tests
|
|
# that are expected to fail.
|
|
#
|
|
actions (failed-as-expected)
|
|
{
|
|
echo failed as expected > "$(<)"
|
|
}
|
|
|
|
|
|
if [ os.name ] = VMS
|
|
{
|
|
actions **passed**
|
|
{
|
|
PIPE WRITE SYS$OUTPUT "passed" > $(<:W)
|
|
}
|
|
|
|
actions (failed-as-expected)
|
|
{
|
|
PIPE WRITE SYS$OUTPUT "failed as expected" > $(<:W)
|
|
}
|
|
}
|
|
|
|
|
|
# Runs executable 'sources' and stores stdout in file 'target'. Unless
|
|
# --preserve-test-targets command line option has been specified, removes the
|
|
# executable. The 'target-to-remove' parameter controls what should be removed:
|
|
# - if 'none', does not remove anything, ever
|
|
# - if empty, removes 'source'
|
|
# - if non-empty and not 'none', contains a list of sources to remove.
|
|
#
|
|
rule capture-output ( target : source : properties * : targets-to-remove * )
|
|
{
|
|
output-file on $(target) = $(target:S=.output) ;
|
|
LOCATE on $(target:S=.output) = [ on $(target) return $(LOCATE) ] ;
|
|
|
|
# The INCLUDES kill a warning about independent target...
|
|
INCLUDES $(target) : $(target:S=.output) ;
|
|
# but it also puts .output into dependency graph, so we must tell jam it is
|
|
# OK if it cannot find the target or updating rule.
|
|
NOCARE $(target:S=.output) ;
|
|
|
|
# This has two-fold effect. First it adds input files to the dependency
|
|
# graph, preventing a warning. Second, it causes input files to be bound
|
|
# before target is created. Therefore, they are bound using SEARCH setting
|
|
# on them and not LOCATE setting of $(target), as in other case (due to jam
|
|
# bug).
|
|
DEPENDS $(target) : [ on $(target) return $(INPUT_FILES) ] ;
|
|
|
|
if $(targets-to-remove) = none
|
|
{
|
|
targets-to-remove = ;
|
|
}
|
|
else if ! $(targets-to-remove)
|
|
{
|
|
targets-to-remove = $(source) ;
|
|
}
|
|
|
|
if [ on $(target) return $(REMOVE_TEST_TARGETS) ]
|
|
{
|
|
TEMPORARY $(targets-to-remove) ;
|
|
# Set a second action on target that will be executed after capture
|
|
# output action. The 'RmTemps' rule has the 'ignore' modifier so it is
|
|
# always considered succeeded. This is needed for 'run-fail' test. For
|
|
# that test the target will be marked with FAIL_EXPECTED, and without
|
|
# 'ignore' successful execution will be negated and be reported as
|
|
# failure. With 'ignore' we do not detect a case where removing files
|
|
# fails, but it is not likely to happen.
|
|
RmTemps $(target) : $(targets-to-remove) ;
|
|
}
|
|
|
|
if ! [ feature.get-values testing.launcher : $(properties) ]
|
|
{
|
|
## On VMS set default launcher to MCR
|
|
if [ os.name ] = VMS { LAUNCHER on $(target) = MCR ; }
|
|
}
|
|
}
|
|
|
|
|
|
if [ os.name ] = NT
|
|
{
|
|
.STATUS = %status% ;
|
|
.SET_STATUS = "set status=%ERRORLEVEL%" ;
|
|
.RUN_OUTPUT_NL = "echo." ;
|
|
.THEN = "(" ;
|
|
.EXIT_SUCCESS = "0" ;
|
|
.STATUS_0 = "%status% EQU 0 $(.THEN)" ;
|
|
.STATUS_NOT_0 = "%status% NEQ 0 $(.THEN)" ;
|
|
.VERBOSE = "%verbose% EQU 1 $(.THEN)" ;
|
|
.ENDIF = ")" ;
|
|
.SHELL_SET = "set " ;
|
|
.CATENATE = type ;
|
|
.CP = copy ;
|
|
.NULLIN = ;
|
|
}
|
|
else if [ os.name ] = VMS
|
|
{
|
|
local nl = "
|
|
" ;
|
|
|
|
.STATUS = "''status'" ;
|
|
.SET_STATUS = "status=$STATUS" ;
|
|
.SAY = "pipe write sys$output" ; ## not really echo
|
|
.RUN_OUTPUT_NL = "$(.SAY) \"\"" ;
|
|
.THEN = "$(nl)then" ;
|
|
.EXIT_SUCCESS = "1" ;
|
|
.SUCCESS = "status .eq. $(.EXIT_SUCCESS) $(.THEN)" ;
|
|
.STATUS_0 = "status .eq. 0 $(.THEN)" ;
|
|
.STATUS_NOT_0 = "status .ne. 0 $(.THEN)" ;
|
|
.VERBOSE = "verbose .eq. 1 $(.THEN)" ;
|
|
.ENDIF = "endif" ;
|
|
.SHELL_SET = "" ;
|
|
.CATENATE = type ;
|
|
.CP = copy ;
|
|
.NULLIN = ;
|
|
}
|
|
else
|
|
{
|
|
.STATUS = "$status" ;
|
|
.SET_STATUS = "status=$?" ;
|
|
.RUN_OUTPUT_NL = "echo" ;
|
|
.THEN = "; then" ;
|
|
.EXIT_SUCCESS = "0" ;
|
|
.STATUS_0 = "test $status -eq 0 $(.THEN)" ;
|
|
.STATUS_NOT_0 = "test $status -ne 0 $(.THEN)" ;
|
|
.VERBOSE = "test $verbose -eq 1 $(.THEN)" ;
|
|
.ENDIF = "fi" ;
|
|
.SHELL_SET = "" ;
|
|
.CATENATE = cat ;
|
|
.CP = cp ;
|
|
.NULLIN = "<" "/dev/null" ;
|
|
}
|
|
|
|
|
|
.VERBOSE_TEST = 0 ;
|
|
if --verbose-test in [ modules.peek : ARGV ]
|
|
{
|
|
.VERBOSE_TEST = 1 ;
|
|
}
|
|
|
|
|
|
.RM = [ common.rm-command ] ;
|
|
|
|
|
|
actions capture-output bind INPUT_FILES output-file
|
|
{
|
|
$(PATH_SETUP)
|
|
$(LAUNCHER) "$(>)" $(ARGS) "$(INPUT_FILES)" > "$(output-file)" 2>&1
|
|
$(.SET_STATUS)
|
|
$(.RUN_OUTPUT_NL) >> "$(output-file)"
|
|
echo EXIT STATUS: $(.STATUS) >> "$(output-file)"
|
|
if $(.STATUS_0)
|
|
$(.CP) "$(output-file)" "$(<)"
|
|
$(.ENDIF)
|
|
$(.SHELL_SET)verbose=$(.VERBOSE_TEST)
|
|
if $(.STATUS_NOT_0)
|
|
$(.SHELL_SET)verbose=1
|
|
$(.ENDIF)
|
|
if $(.VERBOSE)
|
|
echo ====== BEGIN OUTPUT ======
|
|
$(.CATENATE) "$(output-file)"
|
|
echo ====== END OUTPUT ======
|
|
$(.ENDIF)
|
|
exit $(.STATUS)
|
|
}
|
|
|
|
IMPORT testing : capture-output : : testing.capture-output ;
|
|
|
|
|
|
actions quietly updated ignore piecemeal together RmTemps
|
|
{
|
|
$(.RM) "$(>)"
|
|
}
|
|
|
|
|
|
if [ os.name ] = VMS
|
|
{
|
|
actions capture-output bind INPUT_FILES output-file
|
|
{
|
|
$(PATH_SETUP)
|
|
!! Execute twice - first for status, second for output
|
|
set noon
|
|
pipe $(LAUNCHER) $(>:W) $(ARGS) $(INPUT_FILES:W) 2>NL: >NL:
|
|
$(.SET_STATUS)
|
|
pipe $(LAUNCHER) $(>:W) $(ARGS) $(INPUT_FILES:W) | type sys$input /out=$(output-file:W)
|
|
set on
|
|
!! Harmonize VMS success status with POSIX
|
|
if $(.SUCCESS)
|
|
$(.SHELL_SET)status="0"
|
|
$(.ENDIF)
|
|
$(.RUN_OUTPUT_NL) | append /new sys$input $(output-file:W)
|
|
$(.SAY) "EXIT STATUS: $(.STATUS)" | append /new sys$input $(output-file:W)
|
|
if $(.STATUS_0)
|
|
$(.CP) $(output-file:W) $(<:W)
|
|
$(.ENDIF)
|
|
$(.SHELL_SET)verbose=$(.VERBOSE_TEST)
|
|
if $(.STATUS_NOT_0)
|
|
$(.SHELL_SET)verbose=1
|
|
$(.ENDIF)
|
|
if $(.VERBOSE)
|
|
$(.SAY) "====== BEGIN OUTPUT ======"
|
|
$(.CATENATE) $(output-file:W)
|
|
$(.SAY) "====== END OUTPUT ======"
|
|
$(.ENDIF)
|
|
!! Harmonize VMS success status with POSIX on exit
|
|
if $(.STATUS_0)
|
|
$(.SHELL_SET)status="$(.EXIT_SUCCESS)"
|
|
$(.ENDIF)
|
|
exit "$(.STATUS)"
|
|
}
|
|
|
|
actions quietly updated ignore piecemeal together RmTemps
|
|
{
|
|
$(.RM) $(>:WJ=;*,);*
|
|
}
|
|
}
|
|
|
|
|
|
.MAKE_FILE = [ common.file-creation-command ] ;
|
|
|
|
|
|
rule unit-test ( target : source : properties * )
|
|
{
|
|
if ! [ feature.get-values testing.launcher : $(properties) ]
|
|
{
|
|
## On VMS set default launcher to MCR
|
|
if [ os.name ] = VMS { LAUNCHER on $(target) = MCR ; }
|
|
}
|
|
}
|
|
|
|
actions unit-test
|
|
{
|
|
$(PATH_SETUP)
|
|
$(LAUNCHER) "$(>)" $(ARGS) && $(.MAKE_FILE) "$(<)"
|
|
}
|
|
|
|
if [ os.name ] = VMS
|
|
{
|
|
actions unit-test
|
|
{
|
|
$(PATH_SETUP)
|
|
pipe $(LAUNCHER) $(>:W) $(ARGS) && $(.MAKE_FILE) $(<:W)
|
|
}
|
|
}
|
|
|
|
# Note that this rule may be called multiple times for a single target in case
|
|
# there are multiple actions operating on the same target in sequence. One such
|
|
# example are msvc exe targets first created by a linker action and then updated
|
|
# with an embedded manifest file by a separate action.
|
|
rule record-time ( target : source : start end user system )
|
|
{
|
|
local src-string = [$(source:G=:J=",")"] " ;
|
|
USER_TIME on $(target) += $(src-string)$(user) ;
|
|
SYSTEM_TIME on $(target) += $(src-string)$(system) ;
|
|
|
|
# We need the following variables because attempting to perform such
|
|
# variable expansion in actions would not work due to quotes getting treated
|
|
# as regular characters.
|
|
USER_TIME_SECONDS on $(target) += $(src-string)$(user)" seconds" ;
|
|
SYSTEM_TIME_SECONDS on $(target) += $(src-string)$(system)" seconds" ;
|
|
}
|
|
|
|
# Calling this rule requests that Boost Build time how long it takes to build
|
|
# the 'source' target and display the results both on the standard output and in
|
|
# the 'target' file.
|
|
#
|
|
rule time ( target : sources + : properties * )
|
|
{
|
|
# Set up rule for recording timing information.
|
|
__TIMING_RULE__ on $(sources) = testing.record-time $(target) ;
|
|
|
|
# Make sure the sources get rebuilt any time we need to retrieve that
|
|
# information.
|
|
REBUILDS $(target) : $(sources) ;
|
|
}
|
|
|
|
|
|
actions time
|
|
{
|
|
echo user: $(USER_TIME)
|
|
echo system: $(SYSTEM_TIME)
|
|
|
|
echo user: $(USER_TIME_SECONDS) > "$(<)"
|
|
echo system: $(SYSTEM_TIME_SECONDS) >> "$(<)"
|
|
}
|
|
|
|
if [ os.name ] = VMS
|
|
{
|
|
actions time
|
|
{
|
|
WRITE SYS$OUTPUT "user: ", "$(USER_TIME)"
|
|
WRITE SYS$OUTPUT "system: ", "(SYSTEM_TIME)"
|
|
|
|
PIPE WRITE SYS$OUTPUT "user: ", "$(USER_TIME_SECONDS)" | TYPE SYS$INPUT /OUT=$(<:W)
|
|
PIPE WRITE SYS$OUTPUT "system: ", "$(SYSTEM_TIME_SECONDS)" | APPEND /NEW SYS$INPUT $(<:W)
|
|
}
|
|
}
|