2
0
mirror of https://github.com/boostorg/build.git synced 2026-02-15 13:02:11 +00:00
Files
build/testing.jam
Dave Abrahams c2eaee4aaf Allow multiple elements in RUN_PATH
[SVN r14460]
2002-07-14 21:58:14 +00:00

390 lines
13 KiB
Plaintext
Executable File

# (C) Copyright David Abrahams 2002. Permission to copy, use, modify, sell and
# distribute this software is granted provided this copyright notice appears in
# all copies. This software is provided "as is" without express or implied
# warranty, and with no claim as to its suitability for any purpose.
if ! $(.testing.jam-included)
{
.testing.jam-included = "}" ; # The brace makes emacs indentation happy
#######################################################################################
# Tests generate a number of files reflecting their status in the subvariant-directory
#
# <test-name>.test - a marker so that Jam knows when it needs to be
# rebuilt. It will contain the paths from this
# directory to the source files used for the test
#
# <test-name>.success - present only if the test last succeeded.
# Contains the string "succeeded"
#
# <test-name>.failure - present only if the test last failed. Contains the string
# "failed".
#
# <test-name>.output - contains the output of the test if it was a run test.
#######################################################################################
# Declares a test target. If name is not supplied, it is taken from the name of
# the first source file, sans extension and directory path.
#
# type should be a target type (e.g. OBJ, DLL, LIB, EXE)
#
# RETURNS the name(s) of the generated test target(s).
rule boost-test ( sources + : target-type : requirements * : test-name ? )
{
local result ;
{
# manufacture a test name if none supplied explicitly
test-name ?= $(sources[1]:D=:S=) ;
# Make sure that targets don't become part of "all"
local gSUPPRESS_FAKE_TARGETS = true ;
local dependencies = [ select-gristed $(sources) ] ;
local source-files = [ select-ungristed $(sources) ] ;
result = [
declare-local-target $(test-name)
: $(source-files) $(dependencies) # sources
: $(requirements) <sysinclude>$(BOOST_ROOT) # requirements
: # default build
: $(target-type)
] ;
}
Clean clean : $(result) ;
# make NOTFILE targets of the same base name as the sources which can
# be used to build a single test.
type-DEPENDS $(sources:B:S=) : $(result) ;
# The NOTFILE target called "test" builds all tests
type-DEPENDS test : $(result) ;
return $(result) ;
}
#######
BOOST_TEST_SUFFIX ?= .test ;
# a utility rule which causes test-file to be built successfully only if
# dependency fails to build. Used for expected-failure tests.
rule failed-test-file ( test-file : dependency + )
{
catenate-output-on-failure $(test-file) : $(dependency[1]) ;
DEPENDS $(test-file) : $(dependency) ;
NOCARE $(dependency) ;
TEMPORARY $(dependency) ;
FAIL_EXPECTED $(dependency) ;
}
# a utility rule which causes test-file to be built successfully only if
# dependency builds. Used for expected-success tests.
rule succeeded-test-file ( test-file : dependency + )
{
catenate-output-on-failure $(test-file) : $(dependency[1]) ;
DEPENDS $(test-file) : $(dependency) ;
NOCARE $(dependency) ;
TEMPORARY $(dependency) ;
}
rule catenate-output-on-failure ( test-file : dependency )
{
if $(gTEST_OUTPUT_FILE($(dependency)))
{
output-file on $(test-file) = $(gTEST_OUTPUT_FILE($(dependency))) ;
}
}
if $(NT)
{
CATENATE1 = "if exist \"" ;
CATENATE2 = "\" ( ECHO *** output file follows ***
type \"" ;
CATENATE3 = "\"
ECHO *** end of output file *** )" ;
actions failed-test-file bind output-file source-files
{
echo "$(source-files)" > $(<:S=.test)
if EXIST "$(>)". (
if EXIST "$(<:S=.success)". del /f/q "$(<:S=.success)".
echo "failed" > "$(<:S=.failure)"
$(CATENATE1)$(output-file)$(CATENATE2)$(output-file)$(CATENATE3)
echo *
echo ***************** failed above test: $(<:B:S=) ********************
echo *
) ELSE (
if EXIST "$(<:S=.failure)". del /f/q "$(<:S=.failure)".
echo succeeded > "$(<:S=.success)"
)
}
actions succeeded-test-file bind output-file source-files
{
echo "$(source-files)" > $(<:S=.test)
if EXIST "$(>)". (
if EXIST "$(<:S=.failure)". del /f/q "$(<:S=.failure)".
echo succeeded > "$(<:S=.success)"
) ELSE (
if EXIST "$(<:S=.success)". del /f/q "$(<:S=.success)".
echo failed > "$(<:S=.failure)"
$(CATENATE1)$(output-file)$(CATENATE2)$(output-file)$(CATENATE3)
echo *
echo ***************** failed above test: $(<:B:S=) ********************
echo *
)
}
}
else
{
CATENATE = "cat " ;
CATENATE1 = "if [ -f \"" ;
CATENATE2 = "\" ] ; then
echo *** output file follows ***
cat \"" ;
CATENATE3 = "\" ; echo *** end of output file ***
fi" ;
actions failed-test-file bind output-file source-files
{
echo "$(source-files)" > $(<:S=.test)
if [ -f "$(>)" ] ; then
if [ -f "$(<:S=.success)" ] ; then
$(RM) "$(<:S=.success)"
fi
echo "failed" > $(<:S=.failure)
$(CATENATE1)$(output-file)$(CATENATE2)$(output-file)$(CATENATE3)
echo "*"
echo "***************** failed above test: $(<:B:S=) ********************"
echo "*"
else
if [ -f "$(<:S=.failure)" ] ; then
$(RM) "$(<:S=.failure)"
fi
echo "succeeded" > "$(<:S=.success)"
fi
}
actions succeeded-test-file bind output-file source-files
{
echo "$(source-files)" > "$(<:S=.test)"
if [ -f "$(>)" ] ; then
if [ -f "$(<:S=.failure)" ] ; then
$(RM) "$(<:S=.failure)"
fi
echo "succeeded" > "$(<:S=.success)"
else
if [ -f "$(<:S=.success)" ] ; then
$(RM) "$(<:S=.success)"
fi
echo "failed" > "$(<:S=.failure)"
$(CATENATE1)$(output-file)$(CATENATE2)$(output-file)$(CATENATE3)
echo "*"
echo "***************** failed above test: $(<:B:S=) ********************"
echo "*"
fi
}
}
rule declare-build-succeed-test ( test-type : dependency-type )
{
gGENERATOR_FUNCTION($(test-type)) = build-test succeeded-test-file ;
gDEPENDENCY_TYPE($(test-type)) = $(dependency-type) ;
SUF$(test-type) = $(BOOST_TEST_SUFFIX) ;
}
# A utility rule which declares test-type to be a target type which
# depends on the /failed/ construction of a target of type
# dependency-type.
rule declare-build-fail-test ( test-type : dependency-type )
{
gGENERATOR_FUNCTION($(test-type)) = build-test failed-test-file ;
gDEPENDENCY_TYPE($(test-type)) = $(dependency-type) ;
SUF$(test-type) = $(BOOST_TEST_SUFFIX) ;
}
# A temporary measure in case people don't rebuild their Jam
# executables. Define the builtin RMOLD if it's missing.
if ! ( RMOLD in [ RULENAMES ] )
{
rule RMOLD { }
}
# When the appropriate generator function is bound to the
# test-file-generator argument, this is a target generator function
# for target types declared with declare-build-succeed-test and
# declare-build-fail-test, above.
rule build-test ( test-file-generator test-file + : sources + : requirements * )
{
# Get the target type of the current target out of the build properties
local target-type = [ get-values <target-type> : $(gBUILD_PROPERTIES) ] ;
# Get the type of target to attempt to build; the outcome of this
# attempt determines the result of the test.
local dependency-type = $(gDEPENDENCY_TYPE($(target-type))) ;
# Get the actual name of the target to attempt to build
local dependency = $(test-file[1]:S=$(SUF$(dependency-type))) ;
# record the source file names so we can put them in the .test
# file.
source-files on $(test-file) = $(sources) ;
# Make sure that the dependency is erased, so as not to give a
# false indication of success.
RMOLD $(dependency) ;
# Call dependency-type's generator function to attempt the build
local ignored = [
$(gGENERATOR_FUNCTION($(dependency-type))) $(dependency) : $(sources) : $(requirements) ] ;
# Generator functions don't handle this job for us; perhaps they should.
set-target-variables $(dependency) ;
# The .test file goes with the other subvariant targets
MakeLocate $(test-file:S=.test) : $(LOCATE_TARGET) ;
MakeLocate $(test-file:S=.success) : $(LOCATE_TARGET) ;
MakeLocate $(test-file:S=.failure) : $(LOCATE_TARGET) ;
# Generate the test file
$(test-file-generator) $(test-file) : $(dependency) ;
if $(RUN_ALL_TESTS)
{
ALWAYS $(test-file) ;
}
}
### Rules for testing whether a file compiles ###
# Establish the rule which generates targets of type "OBJ". Should really go
# into basic build system, but wasn't needed 'till now.
gGENERATOR_FUNCTION(OBJ) = Object ;
declare-build-fail-test COMPILE_FAIL : OBJ ;
declare-build-succeed-test COMPILE : OBJ ;
# Test that the given source-file(s) compile
rule compile ( sources + : requirements * : test-name ? )
{
return [ boost-test $(sources) : COMPILE : $(requirements) : $(test-name) ] ;
}
# Test that the given source-file(s) fail to compile
rule compile-fail ( sources + : requirements * : test-name ? )
{
return [ boost-test $(sources) : COMPILE_FAIL : $(requirements) : $(test-name) ] ;
}
### Rules for testing whether a program runs ###
gGENERATOR_FUNCTION(RUN_TEST) = run-test ;
SUFRUN_TEST = .run ;
rule run-test ( target : sources + : requirements * )
{
local executable = $(target:S=$(SUFEXE)) ;
local parent = $(target:S=.test) ;
# Move important data from the test target to the executable
gRUN_LD_LIBRARY_PATH($(executable)) = $(gRUN_LD_LIBRARY_PATH($(parent))) ;
gRUN_PATH($(executable)) = $(gRUN_PATH($(parent))) ;
executable-file $(executable) : $(sources) : $(requirements) ;
set-target-variables $(executable) ;
# The .test file goes with the other subvariant targets
# normalization is a hack to get the slashes going the right way on Windoze
local LOCATE_TARGET = [ FDirName [ split-path $(LOCATE_TARGET) ] ] ;
MakeLocate $(target) : $(LOCATE_TARGET) ;
DEPENDS $(target) : $(executable) $(gRUN_TEST_INPUT_FILES) ;
INPUT_FILES on $(target) = $(gRUN_TEST_INPUT_FILES) ;
ARGS on $(target) = $(gRUN_TEST_ARGS) ;
capture-run-output $(target) : $(executable) ;
}
# The rule is just used for argument checking
rule capture-run-output ( target : executable + )
{
gTEST_OUTPUT_FILE($(target)) = $(target:S=.output) ;
INCLUDES $(target) : $(target:S=.output) ;
MakeLocate $(test-file:S=.failure) : $(LOCATE_TARGET) ;
MakeLocate $(test-file:S=.output) : $(LOCATE_TARGET) ;
capture-run-output1 $(target) : $(executable) ;
}
rule capture-run-output1 ( target : executable )
{
output-file on $(target) = $(target:S=.output) ;
local targets = $(target) $(target:S=.output) ;
RUN_PATH on $(targets) = [ join $(gRUN_PATH($(executable))) : $(SPLITPATH) ] ;
if $(UNIX)
{
RUN_LD_LIBRARY_PATH on $(targets) = [ join $(gRUN_LD_LIBRARY_PATH($(executable))) : $(SPLITPATH) ] ;
}
}
if $(UNIX)
{
actions capture-run-output1 bind INPUT_FILES output-file
{
$(SHELL_SET)PATH=$(RUN_PATH:J=:):$PATH
$(SHELL_EXPORT)PATH
$(SHELL_SET)LD_LIBRARY_PATH=$(RUN_LD_LIBRARY_PATH):$LD_LIBRARY_PATH
$(SHELL_EXPORT)LD_LIBRARY_PATH
$(>) $(ARGS) $(INPUT_FILES) > $(output-file) 2>&1 && $(CP) $(output-file) $(<[1])
}
}
else
{
actions capture-run-output1 bind INPUT_FILES output-file
{
$(SHELL_SET)PATH=$(RUN_PATH:J=;);%PATH%
$(SHELL_EXPORT)PATH
$(>) $(ARGS) $(INPUT_FILES) > $(output-file) 2>&1 && $(CP) $(output-file) $(<[1])
}
}
declare-build-fail-test RUN_FAIL : RUN_TEST ;
declare-build-succeed-test RUN : RUN_TEST ;
rule run ( sources + : args * : input-files * : requirements * : name ? )
{
local gRUN_TEST_ARGS = $(args) ;
local gRUN_TEST_INPUT_FILES = $(input-files) ;
SEARCH on $(input-files) = $(LOCATE_SOURCE) ;
return [ boost-test $(sources) : RUN : $(requirements) : $(name) ] ;
}
rule run-fail ( sources + : args * : input-files * : requirements * : name ? )
{
local gRUN_TEST_ARGS = $(2) ;
local gRUN_TEST_INPUT_FILES = $(3) ;
SEARCH on $(3) = $(LOCATE_SOURCE) ;
return [ boost-test $(<) : RUN_FAIL : $(4) : $(name) ] ;
}
### Rules for testing whether a program links
declare-build-fail-test LINK_FAIL : EXE ;
rule link-fail ( sources + : requirements * : name ? )
{
return [ boost-test $(<) : LINK_FAIL : $(2) : $(name) ] ;
}
### Rules for grouping tests into suites:
rule test-suite # pseudotarget-name : test-targets...
{
NOTFILE $(<) ;
type-DEPENDS $(<) : $(>) ;
}
} # include guard