[12] | 1 | # (C) Copyright David Abrahams 2002. |
---|
| 2 | # Distributed under the Boost Software License, Version 1.0. |
---|
| 3 | # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) |
---|
| 4 | |
---|
| 5 | if ! $(.testing.jam-included) |
---|
| 6 | { |
---|
| 7 | .testing.jam-included = "}" ; # The brace makes emacs indentation happy |
---|
| 8 | |
---|
| 9 | # Decide which toolsets should be treated like an ordinary (unix) GCC installation |
---|
| 10 | gcc-compilers = [ MATCH ^(gcc.*)$ : $(TOOLS) ] ; |
---|
| 11 | mingw-compilers = [ MATCH ^(mingw.*)$ ^(gcc-nocygwin.*) : $(TOOLS) ] ; |
---|
| 12 | gcc-compilers = [ difference $(gcc-compilers) : $(mingw-compilers) ] ; |
---|
| 13 | |
---|
| 14 | local rule get-var-value ( name + ) |
---|
| 15 | { |
---|
| 16 | return $($(name)) ; |
---|
| 17 | } |
---|
| 18 | |
---|
| 19 | local rule get-library-name ( path_or_tokens + ) |
---|
| 20 | { |
---|
| 21 | local path = $(path_or_tokens) ; |
---|
| 22 | if ! $(path[1]) { path = [ split-path $(path) ] ; } |
---|
| 23 | path = /$(path:J=/) ; |
---|
| 24 | |
---|
| 25 | local match1 = [ MATCH /libs/(.*)/(test|example) : $(path) ] ; |
---|
| 26 | local match2 = [ MATCH /libs/(.*)$ : $(path) ] ; |
---|
| 27 | local match3 = [ MATCH (/status$) : $(path) ] ; |
---|
| 28 | |
---|
| 29 | if $(match1) { return $(match1[0]) ; } |
---|
| 30 | else if $(match2) { return $(match2[0]) ; } |
---|
| 31 | else if $(match3) { return "" ; } |
---|
| 32 | else if --dump-tests in $(ARGV) |
---|
| 33 | { |
---|
| 34 | EXIT Cannot extract library name from path $(path) ; |
---|
| 35 | } |
---|
| 36 | } |
---|
| 37 | |
---|
| 38 | # Declares a test target. If name is not supplied, it is taken from the name of |
---|
| 39 | # the first source file, sans extension and directory path. |
---|
| 40 | # |
---|
| 41 | # type should be a target type (e.g. OBJ, DLL, LIB, EXE) |
---|
| 42 | # |
---|
| 43 | # RETURNS the name(s) of the generated test target(s). |
---|
| 44 | rule boost-test ( sources + : target-type : requirements * : test-name ? : default-build * ) |
---|
| 45 | { |
---|
| 46 | if ! $(gIN_LIB_INCLUDE) # No need to execute this code twice |
---|
| 47 | { |
---|
| 48 | local result ; |
---|
| 49 | { |
---|
| 50 | # manufacture a test name if none supplied explicitly |
---|
| 51 | test-name ?= $(sources[1]:D=:S=) ; |
---|
| 52 | |
---|
| 53 | local library = "" ; |
---|
| 54 | if $(SUBDIR_TOKENS) { library = [ get-library-name $(SUBDIR_TOKENS) ] ; } |
---|
| 55 | |
---|
| 56 | # Make sure that targets don't become part of "all" |
---|
| 57 | local gSUPPRESS_FAKE_TARGETS = true ; |
---|
| 58 | |
---|
| 59 | result = [ |
---|
| 60 | declare-local-target $(test-name) |
---|
| 61 | : $(sources) |
---|
| 62 | : $(requirements) <sysinclude>$(BOOST_ROOT) |
---|
| 63 | : $(default-build) |
---|
| 64 | : $(target-type) |
---|
| 65 | ] ; |
---|
| 66 | |
---|
| 67 | if $(result) && $(result) in $(.all-boost-tests) |
---|
| 68 | { |
---|
| 69 | EXIT boost-test \"$(result)\" declared twice ; |
---|
| 70 | .all-boost-tests += $(result) ; |
---|
| 71 | } |
---|
| 72 | |
---|
| 73 | if --dump-tests in $(ARGV) && $(result) |
---|
| 74 | { |
---|
| 75 | dump-test $(library) : $(result) : $(requirements) ; |
---|
| 76 | } |
---|
| 77 | } |
---|
| 78 | |
---|
| 79 | Clean clean : $(result) ; |
---|
| 80 | |
---|
| 81 | # make NOTFILE targets of the same base name as the sources which can |
---|
| 82 | # be used to build a single test. |
---|
| 83 | type-DEPENDS $(sources:B:S=) : $(result) ; |
---|
| 84 | |
---|
| 85 | # The NOTFILE target called "test" builds all tests |
---|
| 86 | type-DEPENDS test : $(result) ; |
---|
| 87 | |
---|
| 88 | # Make sure the test result doesn't hang around if the test fails |
---|
| 89 | RMOLD $(result) ; |
---|
| 90 | |
---|
| 91 | return $(result) ; |
---|
| 92 | } |
---|
| 93 | } |
---|
| 94 | |
---|
| 95 | |
---|
| 96 | |
---|
| 97 | |
---|
| 98 | # Helper for boost-test above. Uses dynamic scoping to access |
---|
| 99 | # boost-test's locals. |
---|
| 100 | local rule dump-test ( library ? : targets + : requirements * ) |
---|
| 101 | { |
---|
| 102 | local srcs = [ on $(targets) get-var-value source-files ] ; |
---|
| 103 | |
---|
| 104 | # Pick any source file names off the associated main target as well. |
---|
| 105 | srcs += [ unique [ on $(gTARGET_SUBVARIANT($(targets))) get-var-value source-files ] ] ; |
---|
| 106 | |
---|
| 107 | local pwd = [ PWD ] ; |
---|
| 108 | |
---|
| 109 | # locate each source file |
---|
| 110 | local source-files ; |
---|
| 111 | for local s in $(srcs) |
---|
| 112 | { |
---|
| 113 | # find out where to look for the file |
---|
| 114 | local paths = [ on $(s) get-var-value LOCATE SEARCH ] ; |
---|
| 115 | |
---|
| 116 | s = $(s:G=) ; # strip grist |
---|
| 117 | |
---|
| 118 | # build all the potential full paths of the file |
---|
| 119 | local full-paths = $(s:R=$(paths)) ; |
---|
| 120 | |
---|
| 121 | # look there |
---|
| 122 | local files = [ GLOB $(full-paths:D) : $(s:D=) ] ; |
---|
| 123 | |
---|
| 124 | if $(files) |
---|
| 125 | { |
---|
| 126 | # make relative to the project root instead of "." |
---|
| 127 | local file = $(files[1]:R=$(pwd)) ; |
---|
| 128 | |
---|
| 129 | # try to undo absolute paths |
---|
| 130 | source-files += [ relative-path $(file) ] ; |
---|
| 131 | } |
---|
| 132 | } |
---|
| 133 | |
---|
| 134 | # Extract values of the <test-info> feature |
---|
| 135 | local dump-test-info = [ get-values <test-info> : $(requirements) ] ; |
---|
| 136 | |
---|
| 137 | # Format them into a single string of quoted strings |
---|
| 138 | dump-test-info = \"$(dump-test-info:J=\"\ \")\" ; |
---|
| 139 | |
---|
| 140 | local test-id ; # unique among all tests |
---|
| 141 | |
---|
| 142 | if $(library) |
---|
| 143 | { |
---|
| 144 | test-id = $(library)/$(test-name) ; |
---|
| 145 | } |
---|
| 146 | else |
---|
| 147 | { |
---|
| 148 | test-id = $(test-name) ; |
---|
| 149 | } |
---|
| 150 | |
---|
| 151 | ECHO boost-test($(target-type)) \"$(test-id)\" |
---|
| 152 | [$(dump-test-info)] |
---|
| 153 | ":" \"$(source-files)\" |
---|
| 154 | ; |
---|
| 155 | |
---|
| 156 | if --dump-test-targets in $(ARGV) |
---|
| 157 | { |
---|
| 158 | ECHO boost-test(TARGET) |
---|
| 159 | \"$(test-id)\" [$(dump-test-info)] ":" |
---|
| 160 | \"$(targets)\" |
---|
| 161 | ; |
---|
| 162 | } |
---|
| 163 | } |
---|
| 164 | |
---|
| 165 | |
---|
| 166 | ####### |
---|
| 167 | |
---|
| 168 | BOOST_TEST_SUFFIX ?= .test ; |
---|
| 169 | |
---|
| 170 | # Set a variable which says how to dump a file to stdout |
---|
| 171 | if $(NT) |
---|
| 172 | { |
---|
| 173 | CATENATE = type ; |
---|
| 174 | } |
---|
| 175 | else |
---|
| 176 | { |
---|
| 177 | CATENATE = cat ; |
---|
| 178 | } |
---|
| 179 | |
---|
| 180 | actions **passed** bind source-files |
---|
| 181 | { |
---|
| 182 | echo $(source-files) > $(<) |
---|
| 183 | } |
---|
| 184 | |
---|
| 185 | actions (failed-as-expected) |
---|
| 186 | { |
---|
| 187 | echo failed as expected > $(<) |
---|
| 188 | } |
---|
| 189 | |
---|
| 190 | # a utility rule which causes test-file to be built successfully only if |
---|
| 191 | # dependency fails to build. Used for expected-failure tests. |
---|
| 192 | rule failed-test-file ( test-file : dependency + ) |
---|
| 193 | { |
---|
| 194 | local grist = [ MATCH ^<(.*)> : $(dependency:G) ] ; |
---|
| 195 | local marker = $(dependency:G=$(grist)*fail) ; |
---|
| 196 | (failed-as-expected) $(marker) ; |
---|
| 197 | FAIL_EXPECTED $(dependency) ; |
---|
| 198 | MakeLocate $(marker) : $(LOCATE_TARGET) ; |
---|
| 199 | RMOLD $(marker) ; |
---|
| 200 | DEPENDS $(marker) : $(dependency) ; |
---|
| 201 | |
---|
| 202 | succeeded-test-file $(test-file) : $(marker) ; |
---|
| 203 | } |
---|
| 204 | |
---|
| 205 | # a utility rule which causes test-file to be built successfully only if |
---|
| 206 | # dependency builds. Used for expected-success tests. |
---|
| 207 | rule succeeded-test-file ( test-file : dependency + ) |
---|
| 208 | { |
---|
| 209 | **passed** $(test-file) ; |
---|
| 210 | DEPENDS $(test-file) : $(dependency) ; |
---|
| 211 | } |
---|
| 212 | |
---|
| 213 | rule declare-build-succeed-test ( test-type : dependency-type ) |
---|
| 214 | { |
---|
| 215 | gGENERATOR_FUNCTION($(test-type)) = build-test succeeded-test-file ; |
---|
| 216 | gDEPENDENCY_TYPE($(test-type)) = $(dependency-type) ; |
---|
| 217 | SUF$(test-type) = $(BOOST_TEST_SUFFIX) ; |
---|
| 218 | } |
---|
| 219 | |
---|
| 220 | # A utility rule which declares test-type to be a target type which |
---|
| 221 | # depends on the /failed/ construction of a target of type |
---|
| 222 | # dependency-type. |
---|
| 223 | rule declare-build-fail-test ( test-type : dependency-type ) |
---|
| 224 | { |
---|
| 225 | gGENERATOR_FUNCTION($(test-type)) = build-test failed-test-file ; |
---|
| 226 | gDEPENDENCY_TYPE($(test-type)) = $(dependency-type) ; |
---|
| 227 | SUF$(test-type) = $(BOOST_TEST_SUFFIX) ; |
---|
| 228 | } |
---|
| 229 | |
---|
| 230 | # When the appropriate generator function is bound to the |
---|
| 231 | # test-file-generator argument, this is a target generator function |
---|
| 232 | # for target types declared with declare-build-succeed-test and |
---|
| 233 | # declare-build-fail-test, above. |
---|
| 234 | rule build-test ( test-file-generator test-file + : sources * : requirements * ) |
---|
| 235 | { |
---|
| 236 | # Get the target type of the current target out of the build properties |
---|
| 237 | local target-type = [ get-values <target-type> : $(gBUILD_PROPERTIES) ] ; |
---|
| 238 | |
---|
| 239 | # Get the type of target to attempt to build; the outcome of this |
---|
| 240 | # attempt determines the result of the test. |
---|
| 241 | local dependency-type = $(gDEPENDENCY_TYPE($(target-type))) ; |
---|
| 242 | |
---|
| 243 | # Get the actual name of the target to attempt to build |
---|
| 244 | local dependency = $(test-file[1]:S=$(SUF$(dependency-type))) ; |
---|
| 245 | |
---|
| 246 | # record the source file names so we can put them in the .test |
---|
| 247 | # file. |
---|
| 248 | source-files on $(test-file) = $(sources) ; |
---|
| 249 | |
---|
| 250 | # Make sure that the test-file is erased upon failure, so as not |
---|
| 251 | # to give a false indication of success. |
---|
| 252 | RMOLD $(test-file) ; |
---|
| 253 | |
---|
| 254 | # Call dependency-type's generator function to attempt the build |
---|
| 255 | $(gGENERATOR_FUNCTION($(dependency-type))) $(dependency) : $(sources) : $(requirements) ; |
---|
| 256 | |
---|
| 257 | # Generator functions don't handle this job for us; perhaps they should. |
---|
| 258 | set-target-variables $(dependency) ; |
---|
| 259 | |
---|
| 260 | if $(test-file:S) != $(BOOST_TEST_SUFFIX) |
---|
| 261 | { |
---|
| 262 | EXIT unexpected test file suffix. Filename: $(test-file) ; |
---|
| 263 | } |
---|
| 264 | |
---|
| 265 | # The test files go with the other subvariant targets |
---|
| 266 | MakeLocate $(test-file) : $(LOCATE_TARGET) ; |
---|
| 267 | Clean clean : $(test-file) ; |
---|
| 268 | |
---|
| 269 | # Generate the test file |
---|
| 270 | $(test-file-generator) $(test-file) : $(dependency) ; |
---|
| 271 | } |
---|
| 272 | |
---|
| 273 | ### Rules for testing whether a file compiles ### |
---|
| 274 | |
---|
| 275 | # Establish the rule which generates targets of type "OBJ". Should really go |
---|
| 276 | # into basic build system, but wasn't needed 'till now. |
---|
| 277 | gGENERATOR_FUNCTION(OBJ) = Object ; |
---|
| 278 | declare-build-fail-test COMPILE_FAIL : OBJ ; |
---|
| 279 | declare-build-succeed-test COMPILE : OBJ ; |
---|
| 280 | |
---|
| 281 | # Test that the given source-file(s) compile |
---|
| 282 | rule compile ( sources + : requirements * : test-name ? ) |
---|
| 283 | { |
---|
| 284 | return [ boost-test $(sources) : COMPILE : $(requirements) : $(test-name) ] ; |
---|
| 285 | } |
---|
| 286 | |
---|
| 287 | # Test that the given source-file(s) fail to compile |
---|
| 288 | rule compile-fail ( sources + : requirements * : test-name ? ) |
---|
| 289 | { |
---|
| 290 | return [ boost-test $(sources) : COMPILE_FAIL : $(requirements) : $(test-name) ] ; |
---|
| 291 | } |
---|
| 292 | |
---|
| 293 | |
---|
| 294 | ### Rules for testing whether a program runs ### |
---|
| 295 | |
---|
| 296 | gGENERATOR_FUNCTION(TEST_EXE) = run-test EXE ; |
---|
| 297 | SUFTEST_EXE = .run ; |
---|
| 298 | |
---|
| 299 | rule test-executable(EXE) ( target-to-test ) |
---|
| 300 | { |
---|
| 301 | return $(target-to-test) ; |
---|
| 302 | } |
---|
| 303 | |
---|
| 304 | rule nt-paths-to-cygwin ( paths * ) |
---|
| 305 | { |
---|
| 306 | local result ; |
---|
| 307 | for local p in $(paths) |
---|
| 308 | { |
---|
| 309 | # if already rooted... |
---|
| 310 | if [ MATCH ^([A-Za-z]:[/\\]) : $(p) ] |
---|
| 311 | { |
---|
| 312 | p = [ split-path $(p) ] ; |
---|
| 313 | p = [ join-path /cygdrive [ MATCH ^(.).* : $(p[1]) ] $(p[2-]) ] ; |
---|
| 314 | } |
---|
| 315 | result += $(p:T) ; |
---|
| 316 | } |
---|
| 317 | return $(result) ; |
---|
| 318 | } |
---|
| 319 | |
---|
| 320 | rule run-test ( type-to-test run-target : sources * ) |
---|
| 321 | { |
---|
| 322 | local parent = $(run-target:S=.test) ; |
---|
| 323 | local targets-to-test ; |
---|
| 324 | local main-target = $(gTARGET_SUBVARIANT($(parent))) ; |
---|
| 325 | |
---|
| 326 | # If no sources, assume someone else already built the targets, |
---|
| 327 | # and they are the library dependencies of the test target that |
---|
| 328 | # match the type-to-test. This should perhaps be _all_ |
---|
| 329 | # dependencies, but hopefully we'll throw this code out soon! |
---|
| 330 | if ! $(sources) |
---|
| 331 | { |
---|
| 332 | for local t in [ on $(parent) return $(library-dependencies) ] |
---|
| 333 | { |
---|
| 334 | if $(gTARGET_TYPE($(t))) = $(type-to-test) |
---|
| 335 | { |
---|
| 336 | targets-to-test += $(t) ; |
---|
| 337 | } |
---|
| 338 | } |
---|
| 339 | } |
---|
| 340 | else |
---|
| 341 | { |
---|
| 342 | targets-to-test = $(run-target:S=$(SUF$(type-to-test))) ; |
---|
| 343 | |
---|
| 344 | set-target-variables $(targets-to-test) ; |
---|
| 345 | |
---|
| 346 | generate-dependencies $(main-target) : $(targets-to-test) ; |
---|
| 347 | |
---|
| 348 | declare-basic-target $(targets-to-test) : $(sources) : : : $(type-to-test) ; |
---|
| 349 | $(gGENERATOR_FUNCTION($(type-to-test))) $(targets-to-test) : $(sources) ; |
---|
| 350 | } |
---|
| 351 | |
---|
| 352 | # The .test file goes with the other subvariant targets |
---|
| 353 | # normalization is a hack to get the slashes going the right way on Windoze |
---|
| 354 | local LOCATE_TARGET = [ FDirName [ split-path $(LOCATE_TARGET) ] ] ; |
---|
| 355 | MakeLocate $(run-target) : $(LOCATE_TARGET) ; |
---|
| 356 | |
---|
| 357 | local executable = [ test-executable($(type-to-test)) $(targets-to-test) ] ; |
---|
| 358 | local x-input-files = [ expand-source-names $(gRUN_TEST_INPUT_FILES) ] ; |
---|
| 359 | local x-input-deps = ; |
---|
| 360 | for local x-input-file in $(x-input-files) |
---|
| 361 | { |
---|
| 362 | local input-file-type = [ ungrist $(x-input-file:G:L) ] ; |
---|
| 363 | local input-file-type-id = $(gTARGET_TYPE_ID($(input-file-type))) ; |
---|
| 364 | local input-file-typed = $(x-input-file:G=$(input-file-type-id)) ; |
---|
| 365 | |
---|
| 366 | if $(input-file-typed) |
---|
| 367 | { |
---|
| 368 | dependent-include $(input-file-typed) ; |
---|
| 369 | |
---|
| 370 | local input-file-path = [ target-path-of $(input-file-typed) ] ; |
---|
| 371 | local input-file-target = [ target-id-of $(input-file-path) ] ; |
---|
| 372 | |
---|
| 373 | local [ protect-subproject ] ; |
---|
| 374 | enter-subproject [ directory-of $(input-file-path) ] ; |
---|
| 375 | |
---|
| 376 | local p = $(gBUILD_PROPERTIES) ; |
---|
| 377 | segregate-free-properties p ; |
---|
| 378 | local input-file-subvariant = [ |
---|
| 379 | find-compatible-subvariant $(input-file-target) |
---|
| 380 | : $(gCURRENT_TOOLSET) $(variant) |
---|
| 381 | : $(p) ] ; |
---|
| 382 | local input-file-dep = [ |
---|
| 383 | subvariant-target $(input-file-target) |
---|
| 384 | : $(input-file-subvariant) |
---|
| 385 | : $(gCURRENT_TOOLSET) $(variant) ] ; |
---|
| 386 | x-input-deps += $(input-file-dep) ; |
---|
| 387 | } |
---|
| 388 | else |
---|
| 389 | { |
---|
| 390 | x-input-deps += $(x-input-file) ; |
---|
| 391 | } |
---|
| 392 | } |
---|
| 393 | DEPENDS $(run-target) : $(executable) $(targets-to-test) $(x-input-deps) ; |
---|
| 394 | INPUT_FILES on $(run-target) = $(x-input-deps) ; |
---|
| 395 | ARGS on $(run-target) = $(gRUN_TEST_ARGS) ; |
---|
| 396 | ARGS2 on $(run-target) = $(gRUN_TEST_ARGS2) ; |
---|
| 397 | |
---|
| 398 | # |
---|
| 399 | # Prepare path setup |
---|
| 400 | # |
---|
| 401 | local path-sources = $(parent) $(executable) ; # where do we get paths from? |
---|
| 402 | local $(.run-path-shell-vars) ; # declare local path variables |
---|
| 403 | |
---|
| 404 | # initialize path variables from the path-sources |
---|
| 405 | for local v in $(.run-path-vars) |
---|
| 406 | { |
---|
| 407 | local shell-var = $(.shell-var($(v))) ; |
---|
| 408 | $(shell-var) = [ unique $($(shell-var)) $(gRUN_$(v)($(path-sources))) ] ; |
---|
| 409 | } |
---|
| 410 | |
---|
| 411 | local nt-cygwin ; |
---|
| 412 | if $(NT) && $(gCURRENT_TOOLSET) in $(gcc-compilers) |
---|
| 413 | { |
---|
| 414 | nt-cygwin = true ; |
---|
| 415 | } |
---|
| 416 | |
---|
| 417 | # build up a fragment of shell command |
---|
| 418 | local path-setup ; |
---|
| 419 | for local shell-var in $(.run-path-shell-vars) |
---|
| 420 | { |
---|
| 421 | if $($(shell-var)) |
---|
| 422 | { |
---|
| 423 | local dirs = $($(shell-var)) ; |
---|
| 424 | local splitpath = $(SPLITPATH) ; |
---|
| 425 | |
---|
| 426 | # PATH gets translated automatically; the rest must be |
---|
| 427 | # cygwin-native when running with Cygwin GCC under NT |
---|
| 428 | if $(nt-cygwin) && $(shell-var) != PATH |
---|
| 429 | { |
---|
| 430 | dirs = [ nt-paths-to-cygwin $(dirs) ] ; |
---|
| 431 | splitpath = ":" ; |
---|
| 432 | } |
---|
| 433 | |
---|
| 434 | if $(.run-path-shell-var-value($(shell-var))) |
---|
| 435 | { |
---|
| 436 | dirs += $(.env-prefix)$(shell-var)$(.env-suffix) ; |
---|
| 437 | } |
---|
| 438 | |
---|
| 439 | path-setup += $(SHELL_SET)$(shell-var)=$(dirs:J=$(splitpath)) ; |
---|
| 440 | path-setup += $(SHELL_EXPORT)$(shell-var) ; |
---|
| 441 | } |
---|
| 442 | } |
---|
| 443 | |
---|
| 444 | local debugger = [ MATCH ^--debugger=(.*) : $(ARGV) ] ; |
---|
| 445 | debugger = $(debugger)" " ; |
---|
| 446 | local newline = " |
---|
| 447 | " ; |
---|
| 448 | PATH_SETUP on $(run-target) = $(path-setup:J=$(newline):E=)$(newline)$(debugger:E=) ; |
---|
| 449 | local verbose-test = 1 ; |
---|
| 450 | if --verbose-test in $(ARGV) |
---|
| 451 | { |
---|
| 452 | verbose-test = 0 ; |
---|
| 453 | } |
---|
| 454 | |
---|
| 455 | VERBOSE_TEST on $(run-target) = $(verbose-test) ; |
---|
| 456 | if $(NT) |
---|
| 457 | { |
---|
| 458 | STATUS on $(run-target) = %status% ; |
---|
| 459 | SET_STATUS on $(run-target) = "set status=%ERRORLEVEL%" ; |
---|
| 460 | RUN_OUTPUT_NL on $(run-target) = "echo." ; |
---|
| 461 | STATUS_0 on $(run-target) = "%status% EQU 0 (" ; |
---|
| 462 | STATUS_NOT_0 on $(run-target) = "%status% NEQ 0 (" ; |
---|
| 463 | VERBOSE on $(run-target) = "%verbose% EQU 0 (" ; |
---|
| 464 | ENDIF on $(run-target) = ")" ; |
---|
| 465 | } |
---|
| 466 | else |
---|
| 467 | { |
---|
| 468 | STATUS on $(run-target) = "$status" ; |
---|
| 469 | SET_STATUS on $(run-target) = "status=$?" ; |
---|
| 470 | RUN_OUTPUT_NL on $(run-target) = "echo" ; |
---|
| 471 | STATUS_0 on $(run-target) = "test $status -eq 0 ; then" ; |
---|
| 472 | STATUS_NOT_0 on $(run-target) = "test $status -ne 0 ; then" ; |
---|
| 473 | VERBOSE on $(run-target) = "test $verbose -eq 0 ; then" ; |
---|
| 474 | ENDIF on $(run-target) = "fi" ; |
---|
| 475 | } |
---|
| 476 | |
---|
| 477 | capture-run-output $(run-target) : $(executable) : $(debugger) ; |
---|
| 478 | |
---|
| 479 | if ! ( --preserve-test-targets in $(ARGV) ) && ! [ MATCH ^--debugger=(.*) : $(ARGV) ] |
---|
| 480 | { |
---|
| 481 | RmTemps $(run-target) : $(targets-to-test) ; |
---|
| 482 | } |
---|
| 483 | } |
---|
| 484 | |
---|
| 485 | # The rule is just used for argument checking |
---|
| 486 | rule capture-run-output ( target : executable + : debugger ? ) |
---|
| 487 | { |
---|
| 488 | gTEST_OUTPUT_FILE($(target)) = $(target:S=.output) ; |
---|
| 489 | INCLUDES $(target) : $(target:S=.output) ; |
---|
| 490 | MakeLocate $(test-file:S=.output) : $(LOCATE_TARGET) ; |
---|
| 491 | Clean clean : $(test-file:S=.output) ; |
---|
| 492 | output-file on $(target) = $(target:S=.output) ; |
---|
| 493 | if $(debugger) |
---|
| 494 | { |
---|
| 495 | debug-test $(target) : $(executable) ; |
---|
| 496 | } |
---|
| 497 | else |
---|
| 498 | { |
---|
| 499 | execute-test $(target) : $(executable) ; |
---|
| 500 | } |
---|
| 501 | |
---|
| 502 | if --run-all-tests in $(ARGV) |
---|
| 503 | { |
---|
| 504 | ALWAYS $(target) ; |
---|
| 505 | } |
---|
| 506 | } |
---|
| 507 | |
---|
| 508 | if $(NT) |
---|
| 509 | { |
---|
| 510 | CATENATE = type ; |
---|
| 511 | } |
---|
| 512 | else |
---|
| 513 | { |
---|
| 514 | CATENATE = cat ; |
---|
| 515 | } |
---|
| 516 | |
---|
| 517 | actions debug-test bind INPUT_FILES |
---|
| 518 | { |
---|
| 519 | $(PATH_SETUP)$(>) $(ARGS) "$(INPUT_FILES)" $(ARGS2) |
---|
| 520 | } |
---|
| 521 | |
---|
| 522 | actions execute-test bind INPUT_FILES output-file |
---|
| 523 | { |
---|
| 524 | $(PATH_SETUP)$(>) $(ARGS) "$(INPUT_FILES)" $(ARGS2) > $(output-file) 2>&1 |
---|
| 525 | $(SET_STATUS) |
---|
| 526 | $(RUN_OUTPUT_NL) >> $(output-file) |
---|
| 527 | echo EXIT STATUS: $(STATUS) >> $(output-file) |
---|
| 528 | if $(STATUS_0) |
---|
| 529 | $(CP) $(output-file) $(<) |
---|
| 530 | $(ENDIF) |
---|
| 531 | $(SHELL_SET)verbose=$(VERBOSE_TEST) |
---|
| 532 | if $(STATUS_NOT_0) |
---|
| 533 | $(SHELL_SET)verbose=0 |
---|
| 534 | $(ENDIF) |
---|
| 535 | if $(VERBOSE) |
---|
| 536 | echo ====== BEGIN OUTPUT ====== |
---|
| 537 | $(CATENATE) $(output-file) |
---|
| 538 | echo ====== END OUTPUT ====== |
---|
| 539 | $(ENDIF) |
---|
| 540 | exit $(STATUS) |
---|
| 541 | } |
---|
| 542 | |
---|
| 543 | |
---|
| 544 | declare-build-fail-test RUN_FAIL : TEST_EXE ; |
---|
| 545 | declare-build-succeed-test RUN : TEST_EXE ; |
---|
| 546 | rule run ( sources + : args * : input-files * : requirements * : name ? : default-build * : args2 * ) |
---|
| 547 | { |
---|
| 548 | local gRUN_TEST_ARGS = $(args) ; |
---|
| 549 | local gRUN_TEST_ARGS2 = $(args2) ; |
---|
| 550 | local gRUN_TEST_INPUT_FILES = $(input-files) ; |
---|
| 551 | SEARCH on $(input-files) = $(SEARCH_SOURCE) ; |
---|
| 552 | return [ boost-test $(sources) : RUN : $(requirements) : $(name) : $(default-build) ] ; |
---|
| 553 | } |
---|
| 554 | |
---|
| 555 | rule run-fail ( sources + : args * : input-files * : requirements * : name ? ) |
---|
| 556 | { |
---|
| 557 | local gRUN_TEST_ARGS = $(2) ; |
---|
| 558 | local gRUN_TEST_INPUT_FILES = $(3) ; |
---|
| 559 | SEARCH on $(3) = $(SEARCH_SOURCE) ; |
---|
| 560 | return [ boost-test $(<) : RUN_FAIL : $(4) : $(name) ] ; |
---|
| 561 | } |
---|
| 562 | |
---|
| 563 | ### Rules for testing whether a program links |
---|
| 564 | |
---|
| 565 | declare-build-fail-test LINK_FAIL : EXE ; |
---|
| 566 | rule link-fail ( sources + : requirements * : name ? ) |
---|
| 567 | { |
---|
| 568 | return [ boost-test $(<) : LINK_FAIL : $(2) : $(name) ] ; |
---|
| 569 | } |
---|
| 570 | |
---|
| 571 | declare-build-succeed-test LINK : EXE ; |
---|
| 572 | rule link ( sources + : requirements * : name ? ) |
---|
| 573 | { |
---|
| 574 | return [ boost-test $(<) : LINK : $(2) : $(name) ] ; |
---|
| 575 | } |
---|
| 576 | |
---|
| 577 | ### Rules for grouping tests into suites: |
---|
| 578 | |
---|
| 579 | rule test-suite # pseudotarget-name : test-targets... |
---|
| 580 | { |
---|
| 581 | NOTFILE $(<) ; |
---|
| 582 | type-DEPENDS $(<) : $(>) ; |
---|
| 583 | } |
---|
| 584 | |
---|
| 585 | } # include guard |
---|
| 586 | |
---|