Exemple #1
0
def test_raw_empty():
    whitespace_in = "  \n\n\r\r\v\v\t\t   \t   \r\r   \n\n"

    #   We tell the testing system to read its child process output as raw
    # binary data but the bjam process we run will read its input file and
    # write out its output as text, i.e. convert all of our "\r\n" sequences to
    # "\n" on input and all of its "\n" characters back to "\r\n" on output.
    # This means that any lone "\n" input characters not preceded by "\r" will
    # get an extra "\r" added in front of it on output.
    whitespace_out = whitespace_in.replace("\r\n", "\n").replace("\n", "\r\n")

    t = BoostBuild.Tester(["-d2", "-d+4"], pass_d0=False, pass_toolset=0,
        use_test_config=False)
    t.write("file.jam", """\
actions do_empty {%s}
JAMSHELL = %% ;
do_empty all ;
""" % (whitespace_in))
    t.run_build_system(["-ffile.jam"], universal_newlines=False)
    t.expect_output_lines("do_empty all")
    t.expect_output_lines("Executing raw command directly", False)
    if "\r\n%s\r\n" % whitespace_out not in t.stdout():
        BoostBuild.annotation("failure", "Whitespace action content not found "
            "on stdout.")
        t.fail_test(1, dump_difference=False)
    t.cleanup()
def run_tests(critical_tests, other_tests):
    """Runs first critical tests and then other_tests.

       Stops on first error, and write the name of failed test to
       test_results.txt. Critical tests are run in the specified order,
       other tests are run starting with the one that failed the last time.
    """
    last_failed = last_failed_test()
    other_tests = reorder_tests(other_tests, last_failed)
    all_tests = critical_tests + other_tests

    invocation_dir = os.getcwd()

    pass_count = 0
    failures_count = 0
    for i in all_tests:
        print ("%-25s : " %(i)),
        try:
            __import__(i)
        except SystemExit:
            print "FAILED"
            if failures_count == 0:
                f = open(os.path.join(invocation_dir, 'test_results.txt'), 'w')
                f.write(i)
                f.close()
            failures_count = failures_count + 1
            # Restore the current directory, which might be changed by the
            # test
            os.chdir(invocation_dir)
            BoostBuild.flush_annotations();
            continue
        print "PASSED"
        BoostBuild.flush_annotations();
        pass_count = pass_count + 1
        sys.stdout.flush()  # makes testing under emacs more entertaining.
        
    # Erase the file on success
    if failures_count == 0:
        open('test_results.txt', 'w')

    print """
    === Test summary ===
    PASS: %d
    FAIL: %d
    """ % (pass_count, failures_count)
Exemple #3
0
def check_for_existing_boost_build_jam(t):
    """
      This test depends on no boost-build.jam file existing in any of the
    folders along the current folder's path. If it does exist, not only would
    this test fail but it could point to a completely wrong Boost Build
    installation, thus causing headaches when attempting to diagnose the
    problem. That is why we explicitly check for this scenario.

    """
    problem = find_up_to_root(t.workdir, "boost-build.jam")
    if problem:
        BoostBuild.annotation("misconfiguration", """\
This test expects to be run from a folder with no 'boost-build.jam' file in any
of the folders along its path.

Working folder:
  '%s'

Problematic boost-build.jam found at:
  '%s'

Please remove this file or change the test's working folder and rerun the test.
""" % (t.workdir, problem))
        t.fail_test(1, dump_stdio=False, dump_stack=False)
Exemple #4
0
#!/usr/bin/python

# Copyright 2003 Vladimir Prus
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE.txt or https://www.bfgroup.xyz/b2/LICENSE.txt)

# Test that building with optimization brings NDEBUG define, and, more
# importantly, that dependency targets are built with NDEBUG as well, even if
# they are not directly requested.

import BoostBuild

t = BoostBuild.Tester(use_test_config=False)

t.write("jamroot.jam", "exe hello : hello.cpp lib//lib1 ;")
t.write("hello.cpp", """\
#ifdef NDEBUG
void foo();
int main() { foo(); }
#endif
""")
t.write("lib/jamfile.jam", "lib lib1 : lib1.cpp ;")
t.write("lib/lib1.cpp", """\
#ifdef NDEBUG
void foo() {}
#endif
""")

# 'release' builds should get the NDEBUG define. We use static linking to avoid
# messing with imports/exports on Windows.
t.run_build_system(["link=static", "release"])
Exemple #5
0
def test_generated_target_names():
    """
      Test generator generated target names. Unless given explicitly, target
    names should be determined based on their specified source names. All
    sources for generating a target need to have matching names in order for
    Boost Build to be able to implicitly determine the target's name.

      We use the following target generation structure with differently named
    BBX targets:
                       /---> BB1 ---\
                AAA --<----> BB2 ---->--> CCC --(composing)--> DDD
                       \---> BB3 ---/

      The extra generator at the end is needed because generating a top-level
    CCC target directly would requires us to explicitly specify a name for it.
    The extra generator needs to be composing in order not to explicitly
    request a specific name for its CCC source target based on its own target
    name.

      We also check for a regression where only the first two sources were
    checked to see if their names match. Note that we need to try out all file
    renaming combinations as we do not know what ordering Boost Build is going
    to use when passing in those files as generator sources.

    """
    jamfile_template = """\
import type ;
type.register AAA : _a ;
type.register BB1 : _b1 ;
type.register BB2 : _b2 ;
type.register BB3 : _b3 ;
type.register CCC : _c ;
type.register DDD : _d ;

import appender ;
appender.register aaa-to-bbX           : AAA         : BB1%s BB2%s BB3%s ;
appender.register bbX-to-ccc           : BB1 BB2 BB3 : CCC ;
appender.register ccc-to-ddd composing : CCC         : DDD ;

ddd _xxx : _xxx._a ;
"""

    t = BoostBuild.Tester()
    __write_appender(t, "appender.jam")
    t.write("_xxx._a", "")

    def test_one(t, rename1, rename2, rename3, status):
        def f(rename):
            if rename: return "(%_x)"
            return ""

        jamfile = jamfile_template % (f(rename1), f(rename2), f(rename3))
        t.write("jamroot.jam", jamfile, wait=False)

        #   Remove any preexisting targets left over from a previous test run
        # so we do not have to be careful about tracking which files have been
        # newly added and which preexisting ones have only been modified.
        t.rm("bin")

        t.run_build_system(status=status)

        if status:
            t.expect_output_lines(
                "*.bbX-to-ccc: source targets have "
                "different names: cannot determine target name")
        else:

            def suffix(rename):
                if rename: return "_x"
                return ""

            name = "bin/_xxx"
            e = t.expect_addition
            e("%s%s._b1" % (name, suffix(rename1)))
            e("%s%s._b2" % (name, suffix(rename2)))
            e("%s%s._b3" % (name, suffix(rename3)))
            e("%s%s._c" % (name, suffix(rename1 and rename2 and rename3)))
            e("%s._d" % name)
        t.expect_nothing_more()

    test_one(t, False, False, False, status=0)
    test_one(t, True, False, False, status=1)
    test_one(t, False, True, False, status=1)
    test_one(t, False, False, True, status=1)
    test_one(t, True, True, False, status=1)
    test_one(t, True, False, True, status=1)
    test_one(t, False, True, True, status=1)
    test_one(t, True, True, True, status=0)
    t.cleanup()
Exemple #6
0
#!/usr/bin/python

# Copyright 2003 Dave Abrahams
# Copyright 2002, 2003, 2004 Vladimir Prus
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)

import BoostBuild

t = BoostBuild.Tester(translate_suffixes=0)

t.set_tree("project-test4")

t.run_build_system()

t.expect_addition("bin/$toolset/debug*/a.obj")
t.expect_content("bin/$toolset/debug*/a.obj",
                 """$toolset/debug*/include-everything*
a.cpp
""")

t.expect_addition("bin/$toolset/debug*/a.exe")
t.expect_content(
    "bin/$toolset/debug*/a.exe", "$toolset/debug*/include-everything*\n" +
    "bin/$toolset/debug*/a.obj lib/bin/$toolset/debug/optimization-speed*/b.obj\n"
)

t.expect_addition("lib/bin/$toolset/debug/optimization-speed*/b.obj")
t.expect_content(
    "lib/bin/$toolset/debug/optimization-speed*/b.obj",
    """$toolset/debug/include-everything/optimization-speed*
Exemple #7
0
#!/usr/bin/python

# Copyright (C) Vladimir Prus 2006.
# Distributed under the Boost Software License, Version 1.0. (See
# accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)

# Test the 'make' example.

import BoostBuild

t = BoostBuild.Tester()

t.set_tree("../example/make")

t.run_build_system()

t.expect_addition(["bin/$toolset/debug/main.cpp"])

t.cleanup()
Exemple #8
0
#!/usr/bin/python

# Copyright 2002-2005 Dave Abrahams.
# Copyright 2002-2006 Vladimir Prus.
# Distributed under the Boost Software License, Version 1.0.
#    (See accompanying file LICENSE_1_0.txt or copy at
#         http://www.boost.org/LICENSE_1_0.txt)

import os
import sys
import string
import BoostBuild

xml = "--xml" in sys.argv
toolset = BoostBuild.get_toolset()


# Clear environment for testing.
#
for s in ("BOOST_ROOT", "BOOST_BUILD_PATH", "JAM_TOOLSET", "BCCROOT", "MSVCDir", "MSVC", "MSVCNT", "MINGW", "watcom"):
    try:
        del os.environ[s]
    except:
        pass

BoostBuild.set_defer_annotations(1)


def run_tests(critical_tests, other_tests):
    """Runs first critical tests and then other_tests.
Exemple #9
0
def run_tests(critical_tests, other_tests):
    """Runs first critical tests and then other_tests.

       Stops on first error, and write the name of failed test to
       test_results.txt. Critical tests are run in the specified order, other
       tests are run starting with the one that failed the last time.
    """
    last_failed = last_failed_test()
    other_tests = reorder_tests(other_tests, last_failed)
    all_tests = critical_tests + other_tests

    invocation_dir = os.getcwd()

    pass_count = 0
    failures_count = 0

    for i in all_tests:
        passed = 1
        if not xml:
            print ("%-25s : " %(i)),
        try:
            __import__(i)
        except SystemExit:
            passed = 0;
            if failures_count == 0:
                f = open(os.path.join(invocation_dir, 'test_results.txt'), 'w')
                f.write(i)
                f.close()
            failures_count = failures_count + 1
            # Restore the current directory, which might be changed by the test.
            os.chdir(invocation_dir)

        if not xml:
            if passed:
                print "PASSED"
            else:
                print "FAILED"

            if i == "regression":
                BoostBuild.flush_annotations()
            BoostBuild.clear_annotations()
        else:
            rs = "succeed"
            if not passed:
                rs = "fail"
            print """
<test-log library="build" test-name="%s" test-type="run" toolset="%s" test-program="%s" target-directory="%s">
<run result="%s">""" % (i, toolset, "tools/build/v2/test/" + i + ".py",
                        "boost/bin.v2/boost.build.tests/" + toolset + "/" + i, rs)

            if not passed:
                BoostBuild.flush_annotations(1)

            print """
</run>
</test-log>
"""
        if passed:
            pass_count = pass_count + 1
        sys.stdout.flush()  # Makes testing under emacs more entertaining.

    # Erase the file on success.
    if failures_count == 0:
        open('test_results.txt', 'w')

    if not xml:
        print """
        === Test summary ===
        PASS: %d
        FAIL: %d
        """ % (pass_count, failures_count)
Exemple #10
0
def test_check_target_builds():
    t = BoostBuild.Tester(use_test_config=0)
    t.write(
        "Jamroot", """
import configure ;
obj pass : pass.cpp ;
obj fail : fail.cpp ;
explicit pass fail ;
obj foo : foo.cpp :
  [ configure.check-target-builds pass : <define>PASS : <define>FAIL ] ;
obj bar : foo.cpp :
  [ configure.check-target-builds fail : <define>FAIL : <define>PASS ] ;
""")
    t.write("pass.cpp", "void f() {}\n")
    t.write("fail.cpp", "#error fail.cpp\n")
    t.write(
        "foo.cpp", """
#ifndef PASS
#error PASS not defined
#endif
#ifdef FAIL
#error FAIL is defined
#endif
""")
    t.run_build_system()
    t.expect_output_lines([
        "    - pass builds              : yes*",
        "    - fail builds              : no*"
    ])
    t.expect_addition("bin/$toolset/debug*/pass.obj")
    t.expect_addition("bin/$toolset/debug*/foo.obj")
    t.expect_addition("bin/$toolset/debug*/bar.obj")
    t.expect_nothing_more()

    # An up-to-date build should use the cache
    t.run_build_system()
    t.expect_output_lines([
        "    - pass builds              : yes (cached)*",
        "    - fail builds              : no  (cached)*"
    ])
    t.expect_nothing_more()

    # -a should re-run everything, including configuration checks
    t.run_build_system(["-a"])
    t.expect_output_lines([
        "    - pass builds              : yes*",
        "    - fail builds              : no*"
    ])
    t.expect_touch("bin/$toolset/debug*/pass.obj")
    t.expect_touch("bin/$toolset/debug*/foo.obj")
    t.expect_touch("bin/$toolset/debug*/bar.obj")
    t.expect_nothing_more()

    # --reconfigure should re-run configuration checks only
    t.run_build_system(["--reconfigure"])
    t.expect_output_lines([
        "    - pass builds              : yes*",
        "    - fail builds              : no*"
    ])
    t.expect_touch("bin/$toolset/debug*/pass.obj")
    t.expect_nothing_more()

    # -a -n should not rebuild configuration checks
    t.run_build_system(["-a", "-n"])
    t.expect_output_lines([
        "    - pass builds              : yes (cached)*",
        "    - fail builds              : no  (cached)*"
    ])
    t.expect_nothing_more()

    # --clean-all should clear all configuration checks
    t.run_build_system(["--clean-all"])
    t.expect_output_lines([
        "    - pass builds              : yes (cached)*",
        "    - fail builds              : no  (cached)*"
    ])
    t.expect_removal("bin/$toolset/debug*/pass.obj")
    t.expect_removal("bin/$toolset/debug*/foo.obj")
    t.expect_removal("bin/$toolset/debug*/bar.obj")
    t.expect_nothing_more()

    # If configuration checks are absent, then --clean-all
    # should create them and then delete them again.  This
    # currently fails because clean cannot remove targets
    # that were created in the same build.
    #t.run_build_system(["--clean-all"])
    #t.expect_output_lines([
    #    "    - pass builds              : yes",
    #    "    - fail builds              : no"])
    #t.expect_nothing_more()

    # Just verify that we're actually in the initial
    # state here.
    t.run_build_system()
    t.expect_output_lines([
        "    - pass builds              : yes*",
        "    - fail builds              : no*"
    ])
    t.expect_addition("bin/$toolset/debug*/pass.obj")
    t.expect_addition("bin/$toolset/debug*/foo.obj")
    t.expect_addition("bin/$toolset/debug*/bar.obj")
    t.expect_nothing_more()

    t.cleanup()
Exemple #11
0
def test_order_graph():
    t = BoostBuild.Tester(use_test_config=False)
    t.write("jamroot.jam", """
    obj test : test.cpp :
        <include>b&&a
        <include>c&&b
        <include>a
        <include>c
        <include>b
        <include>e&&b&&d
      ;
    """)
    t.write("test.cpp", """
    #include <test1.h>
    #include <test2.h>
    #include <test3.h>
    #include <test4.h>
    int main() {}
    """)
    t.write("b/test1.h", "")
    t.write("a/test1.h", "#error should find b/test1.h\n")

    t.write("c/test2.h", "")
    t.write("b/test2.h", "#error should find c/test2.h\n")

    t.write("e/test3.h", "")
    t.write("b/test3.h", "#error should find e/test3.h\n")

    t.write("b/test4.h", "")
    t.write("d/test4.h", "#error should find b/test4.h\n")

    t.run_build_system()
    t.expect_addition("bin/$toolset/debug/test.obj")

    t.touch("b/test1.h")
    t.run_build_system()
    t.expect_touch("bin/$toolset/debug/test.obj")
    t.expect_nothing_more()

    t.touch("a/test1.h")
    t.run_build_system()
    t.expect_nothing_more()

    t.touch("c/test2.h")
    t.run_build_system()
    t.expect_touch("bin/$toolset/debug/test.obj")
    t.expect_nothing_more()

    t.touch("b/test2.h")
    t.run_build_system()
    t.expect_nothing_more()

    t.touch("e/test3.h")
    t.run_build_system()
    t.expect_touch("bin/$toolset/debug/test.obj")
    t.expect_nothing_more()

    t.touch("b/test3.h")
    t.run_build_system()
    t.expect_nothing_more()

    t.touch("b/test4.h")
    t.run_build_system()
    t.expect_touch("bin/$toolset/debug/test.obj")
    t.expect_nothing_more()

    t.touch("d/test4.h")
    t.run_build_system()
    t.expect_nothing_more()

    t.cleanup()
Exemple #12
0
def test_unresolved_project_references():
    t = BoostBuild.Tester()

    __write_appender(t, "appender.jam")
    t.write("a/source._a", "")
    t.write("a/jamfile.jam", "import alias ; alias target : source._a ;")
    t.write("jamroot.jam", """\
import type ;
type.register AAA : _a ;
type.register BBB : _b ;

import appender ;
appender.register aaa-to-bbb : AAA : BBB ;

use-project foo : a ;

bbb b1 : a//target ;
bbb b2 : /foo//target ;
bbb b-invalid : invalid//target ;
bbb b-root-invalid : /invalid//target ;
bbb b-missing-root : foo//target ;
bbb b-invalid-target : /foo//invalid ;
""")

    t.run_build_system(["b1", "b2"])
    t.expect_addition("bin/$toolset/debug/b%d._b" % x for x in range(1, 3))
    t.expect_nothing_more()

    t.run_build_system(["b-invalid"], status=1)
    t.expect_output_lines("""\
error: Unable to find file or target named
error:     'invalid//target'
error: referred to from project at
error:     '.'
error: could not resolve project reference 'invalid'""")

    t.run_build_system(["b-root-invalid"], status=1)
    t.expect_output_lines("""\
error: Unable to find file or target named
error:     '/invalid//target'
error: referred to from project at
error:     '.'
error: could not resolve project reference '/invalid'""")

    t.run_build_system(["b-missing-root"], status=1)
    t.expect_output_lines("""\
error: Unable to find file or target named
error:     'foo//target'
error: referred to from project at
error:     '.'
error: could not resolve project reference 'foo' - possibly missing a """
    "leading slash ('/') character.")

    t.run_build_system(["b-invalid-target"], status=1)
    t.expect_output_lines("""\
error: Unable to find file or target named
error:     '/foo//invalid'
error: referred to from project at
error:     '.'""")
    t.expect_output_lines("*could not resolve project reference*", False)

    t.cleanup()
Exemple #13
0
# Copyright 2002 Dave Abrahams
# Copyright 2003, 2004 Vladimir Prus
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)

import BoostBuild
import os
import re


def match_re(actual, expected):
    return re.match(expected, actual, re.DOTALL) != None


# Test the v1 startup behavior.
t = BoostBuild.Tester(match=match_re, boost_build_path='', pass_toolset=0)

t.set_tree('startup')

t.run_build_system(
    status=1,
    stdout=r'''Unable to load Boost\.Build: could not find "boost-build.jam"
.*Attempted search from .* up to the root''',
    match=match_re)

os.chdir('no-bootstrap1')

t.run_build_system(
    status=1,
    stdout=r'''Unable to load Boost\.Build: could not find build system\.''' +
    r'''.*attempted to load the build system by invoking''' +
Exemple #14
0
def test_repeated_ids_for_same_project():
    t = BoostBuild.Tester()

    t.write("jamroot.jam", "project foo ; project foo ;")
    t.run_build_system()

    t.write("jamroot.jam", "project foo ; use-project foo : . ;")
    t.run_build_system()

    t.write("jamroot.jam", "project foo ; use-project foo : ./. ;")
    t.run_build_system()

    t.write("jamroot.jam", """\
project foo ;
use-project foo : . ;
use-project foo : ./aaa/.. ;
use-project foo : ./. ;
""")
    t.run_build_system()

    # On Windows we have a case-insensitive file system and we can use
    # backslashes as path separators.
    # FIXME: Make a similar test pass on Cygwin.
    if sys.platform in ['win32']:
        t.write("a/fOo bAr/b/jamfile.jam", "")
        t.write("jamroot.jam", r"""
use-project bar : "a/foo bar/b" ;
use-project bar : "a/foO Bar/b" ;
use-project bar : "a/foo BAR/b/" ;
use-project bar : "a\\.\\FOO bar\\b\\" ;
""")
        t.run_build_system()
        t.rm("a")

    t.write("bar/jamfile.jam", "")
    t.write("jamroot.jam", """\
use-project bar : bar ;
use-project bar : bar/ ;
use-project bar : bar// ;
use-project bar : bar/// ;
use-project bar : bar//// ;
use-project bar : bar/. ;
use-project bar : bar/./ ;
use-project bar : bar/////./ ;
use-project bar : bar/../bar/xxx/.. ;
use-project bar : bar/..///bar/xxx///////.. ;
use-project bar : bar/./../bar/xxx/.. ;
use-project bar : bar/.////../bar/xxx/.. ;
use-project bar : bar/././../bar/xxx/.. ;
use-project bar : bar/././//////////../bar/xxx/.. ;
use-project bar : bar/.///.////../bar/xxx/.. ;
use-project bar : bar/./././xxx/.. ;
use-project bar : bar/xxx////.. ;
use-project bar : bar/xxx/.. ;
use-project bar : bar///////xxx/.. ;
""")
    t.run_build_system()
    t.rm("bar")

    # On Windows we have a case-insensitive file system and we can use
    # backslashes as path separators.
    # FIXME: Make a similar test pass on Cygwin.
    if sys.platform in ['win32']:
        t.write("baR/jamfile.jam", "")
        t.write("jamroot.jam", r"""
use-project bar : bar ;
use-project bar : BAR ;
use-project bar : bAr ;
use-project bar : bAr/ ;
use-project bar : bAr\\ ;
use-project bar : bAr\\\\ ;
use-project bar : bAr\\\\///// ;
use-project bar : bAr/. ;
use-project bar : bAr/./././ ;
use-project bar : bAr\\.\\.\\.\\ ;
use-project bar : bAr\\./\\/.\\.\\ ;
use-project bar : bAr/.\\././ ;
use-project bar : Bar ;
use-project bar : BaR ;
use-project bar : BaR/./../bAr/xxx/.. ;
use-project bar : BaR/./..\\bAr\\xxx/.. ;
use-project bar : BaR/xxx/.. ;
use-project bar : BaR///\\\\\\//xxx/.. ;
use-project bar : Bar\\xxx/.. ;
use-project bar : BAR/xXx/.. ;
use-project bar : BAR/xXx\\\\/\\/\\//\\.. ;
""")
        t.run_build_system()
        t.rm("baR")

    t.cleanup()
Exemple #15
0
def test_multiple_conditions():
    """Basic tests for properties conditioned on multiple other properties."""

    t = BoostBuild.Tester(["--user-config=", "--ignore-site-config",
        "toolset=testToolset"], pass_toolset=False, use_test_config=False)

    t.write("testToolset.jam", """\
import feature ;
feature.extend toolset : testToolset ;
rule init ( ) { }
""")

    t.write("testToolset.py", """\
from b2.build import feature
feature.extend('toolset', ["testToolset"])
def init ( ): pass
""")

    t.write("jamroot.jam", """\
import feature ;
import notfile ;
import toolset ;

feature.feature description : : free incidental ;
feature.feature aaa : 1 0 : incidental ;
feature.feature bbb : 1 0 : incidental ;
feature.feature ccc : 1 0 : incidental ;

rule buildRule ( name : targets ? : properties * )
{
    for local description in [ feature.get-values description : $(properties) ]
    {
        ECHO "description:" /$(description)/ ;
    }
}

notfile testTarget1 : @buildRule : :
    <description>d
    <aaa>0:<description>a0
    <aaa>1:<description>a1
    <aaa>0,<bbb>0:<description>a0-b0
    <aaa>0,<bbb>1:<description>a0-b1
    <aaa>1,<bbb>0:<description>a1-b0
    <aaa>1,<bbb>1:<description>a1-b1
    <aaa>0,<bbb>0,<ccc>0:<description>a0-b0-c0
    <aaa>0,<bbb>0,<ccc>1:<description>a0-b0-c1
    <aaa>0,<bbb>1,<ccc>1:<description>a0-b1-c1
    <aaa>1,<bbb>0,<ccc>1:<description>a1-b0-c1
    <aaa>1,<bbb>1,<ccc>0:<description>a1-b1-c0
    <aaa>1,<bbb>1,<ccc>1:<description>a1-b1-c1 ;
""")

    t.run_build_system(["aaa=1", "bbb=1", "ccc=1"])
    t.expect_output_lines("description: /d/"              )
    t.expect_output_lines("description: /a0/"      , False)
    t.expect_output_lines("description: /a1/"             )
    t.expect_output_lines("description: /a0-b0/"   , False)
    t.expect_output_lines("description: /a0-b1/"   , False)
    t.expect_output_lines("description: /a1-b0/"   , False)
    t.expect_output_lines("description: /a1-b1/"          )
    t.expect_output_lines("description: /a0-b0-c0/", False)
    t.expect_output_lines("description: /a0-b0-c1/", False)
    t.expect_output_lines("description: /a0-b1-c1/", False)
    t.expect_output_lines("description: /a1-b0-c1/", False)
    t.expect_output_lines("description: /a1-b1-c0/", False)
    t.expect_output_lines("description: /a1-b1-c1/"       )

    t.run_build_system(["aaa=0", "bbb=0", "ccc=1"])
    t.expect_output_lines("description: /d/"              )
    t.expect_output_lines("description: /a0/"             )
    t.expect_output_lines("description: /a1/"      , False)
    t.expect_output_lines("description: /a0-b0/"          )
    t.expect_output_lines("description: /a0-b1/"   , False)
    t.expect_output_lines("description: /a1-b0/"   , False)
    t.expect_output_lines("description: /a1-b1/"   , False)
    t.expect_output_lines("description: /a0-b0-c0/", False)
    t.expect_output_lines("description: /a0-b0-c1/"       )
    t.expect_output_lines("description: /a0-b1-c1/", False)
    t.expect_output_lines("description: /a1-b0-c1/", False)
    t.expect_output_lines("description: /a1-b1-c0/", False)
    t.expect_output_lines("description: /a1-b1-c1/", False)

    t.run_build_system(["aaa=0", "bbb=0", "ccc=0"])
    t.expect_output_lines("description: /d/"              )
    t.expect_output_lines("description: /a0/"             )
    t.expect_output_lines("description: /a1/"      , False)
    t.expect_output_lines("description: /a0-b0/"          )
    t.expect_output_lines("description: /a0-b1/"   , False)
    t.expect_output_lines("description: /a1-b0/"   , False)
    t.expect_output_lines("description: /a1-b1/"   , False)
    t.expect_output_lines("description: /a0-b0-c0/"       )
    t.expect_output_lines("description: /a0-b0-c1/", False)
    t.expect_output_lines("description: /a0-b1-c1/", False)
    t.expect_output_lines("description: /a1-b0-c1/", False)
    t.expect_output_lines("description: /a1-b1-c0/", False)
    t.expect_output_lines("description: /a1-b1-c1/", False)

    t.cleanup()
Exemple #16
0
def test_multiple_conditions_with_toolset_version():
    """
      Regression tests for properties conditioned on the toolset version
    subfeature and some additional properties.

    """
    toolset = "testToolset" ;

    t = BoostBuild.Tester(["--user-config=", "--ignore-site-config"],
        pass_toolset=False, use_test_config=False)

    t.write(toolset + ".jam", """\
import feature ;
feature.extend toolset : %(toolset)s ;
feature.subfeature toolset %(toolset)s : version : 0 1 ;
rule init ( version ? ) { }
""" % {"toolset": toolset})

    t.write("testToolset.py", """\
from b2.build import feature
feature.extend('toolset', ["%(toolset)s"])
feature.subfeature('toolset', "%(toolset)s", "version", ['0','1'])
def init ( version ): pass
""" % {"toolset": toolset})

    t.write("jamroot.jam", """\
import feature ;
import notfile ;
import toolset ;

toolset.using testToolset ;

feature.feature description : : free incidental ;
feature.feature aaa : 0 1 : incidental ;
feature.feature bbb : 0 1 : incidental ;
feature.feature ccc : 0 1 : incidental ;

rule buildRule ( name : targets ? : properties * )
{
    local ttt = [ feature.get-values toolset                     : $(properties) ] ;
    local vvv = [ feature.get-values toolset-testToolset:version : $(properties) ] ;
    local aaa = [ feature.get-values aaa                         : $(properties) ] ;
    local bbb = [ feature.get-values bbb                         : $(properties) ] ;
    local ccc = [ feature.get-values ccc                         : $(properties) ] ;
    ECHO "toolset:" /$(ttt)/ "version:" /$(vvv)/ "aaa/bbb/ccc:" /$(aaa)/$(bbb)/$(ccc)/ ;
    for local description in [ feature.get-values description : $(properties) ]
    {
        ECHO "description:" /$(description)/ ;
    }
}

notfile testTarget1 : @buildRule : :
    <toolset>testToolset,<aaa>0:<description>t-a0
    <toolset>testToolset,<aaa>1:<description>t-a1

    <toolset>testToolset-0,<aaa>0:<description>t0-a0
    <toolset>testToolset-0,<aaa>1:<description>t0-a1
    <toolset>testToolset-1,<aaa>0:<description>t1-a0
    <toolset>testToolset-1,<aaa>1:<description>t1-a1

    <toolset>testToolset,<aaa>0,<bbb>0:<description>t-a0-b0
    <toolset>testToolset,<aaa>0,<bbb>1:<description>t-a0-b1
    <toolset>testToolset,<aaa>1,<bbb>0:<description>t-a1-b0
    <toolset>testToolset,<aaa>1,<bbb>1:<description>t-a1-b1

    <aaa>0,<toolset>testToolset,<bbb>0:<description>a0-t-b0
    <aaa>0,<toolset>testToolset,<bbb>1:<description>a0-t-b1
    <aaa>1,<toolset>testToolset,<bbb>0:<description>a1-t-b0
    <aaa>1,<toolset>testToolset,<bbb>1:<description>a1-t-b1

    <aaa>0,<bbb>0,<toolset>testToolset:<description>a0-b0-t
    <aaa>0,<bbb>1,<toolset>testToolset:<description>a0-b1-t
    <aaa>1,<bbb>0,<toolset>testToolset:<description>a1-b0-t
    <aaa>1,<bbb>1,<toolset>testToolset:<description>a1-b1-t

    <toolset>testToolset-0,<aaa>0,<bbb>0:<description>t0-a0-b0
    <toolset>testToolset-0,<aaa>0,<bbb>1:<description>t0-a0-b1
    <toolset>testToolset-0,<aaa>1,<bbb>0:<description>t0-a1-b0
    <toolset>testToolset-0,<aaa>1,<bbb>1:<description>t0-a1-b1
    <toolset>testToolset-1,<aaa>0,<bbb>0:<description>t1-a0-b0
    <toolset>testToolset-1,<aaa>0,<bbb>1:<description>t1-a0-b1
    <toolset>testToolset-1,<aaa>1,<bbb>0:<description>t1-a1-b0
    <toolset>testToolset-1,<aaa>1,<bbb>1:<description>t1-a1-b1

    <aaa>0,<toolset>testToolset-1,<bbb>0:<description>a0-t1-b0
    <aaa>0,<toolset>testToolset-1,<bbb>1:<description>a0-t1-b1
    <aaa>1,<toolset>testToolset-0,<bbb>0:<description>a1-t0-b0
    <aaa>1,<toolset>testToolset-0,<bbb>1:<description>a1-t0-b1

    <bbb>0,<aaa>1,<toolset>testToolset-0:<description>b0-a1-t0
    <bbb>0,<aaa>0,<toolset>testToolset-1:<description>b0-a0-t1
    <bbb>0,<aaa>1,<toolset>testToolset-1:<description>b0-a1-t1
    <bbb>1,<aaa>0,<toolset>testToolset-1:<description>b1-a0-t1
    <bbb>1,<aaa>1,<toolset>testToolset-0:<description>b1-a1-t0
    <bbb>1,<aaa>1,<toolset>testToolset-1:<description>b1-a1-t1 ;
""")

    t.run_build_system(["aaa=1", "bbb=1", "ccc=1", "toolset=%s-0" % toolset])
    t.expect_output_lines("description: /t-a0/"    , False)
    t.expect_output_lines("description: /t-a1/"           )
    t.expect_output_lines("description: /t0-a0/"   , False)
    t.expect_output_lines("description: /t0-a1/"          )
    t.expect_output_lines("description: /t1-a0/"   , False)
    t.expect_output_lines("description: /t1-a1/"   , False)
    t.expect_output_lines("description: /t-a0-b0/" , False)
    t.expect_output_lines("description: /t-a0-b1/" , False)
    t.expect_output_lines("description: /t-a1-b0/" , False)
    t.expect_output_lines("description: /t-a1-b1/"        )
    t.expect_output_lines("description: /a0-t-b0/" , False)
    t.expect_output_lines("description: /a0-t-b1/" , False)
    t.expect_output_lines("description: /a1-t-b0/" , False)
    t.expect_output_lines("description: /a1-t-b1/"        )
    t.expect_output_lines("description: /a0-b0-t/" , False)
    t.expect_output_lines("description: /a0-b1-t/" , False)
    t.expect_output_lines("description: /a1-b0-t/" , False)
    t.expect_output_lines("description: /a1-b1-t/"        )
    t.expect_output_lines("description: /t0-a0-b0/", False)
    t.expect_output_lines("description: /t0-a0-b1/", False)
    t.expect_output_lines("description: /t0-a1-b0/", False)
    t.expect_output_lines("description: /t0-a1-b1/"       )
    t.expect_output_lines("description: /t1-a0-b0/", False)
    t.expect_output_lines("description: /t1-a0-b1/", False)
    t.expect_output_lines("description: /t1-a1-b0/", False)
    t.expect_output_lines("description: /t1-a1-b1/", False)
    t.expect_output_lines("description: /a0-t1-b0/", False)
    t.expect_output_lines("description: /a0-t1-b1/", False)
    t.expect_output_lines("description: /a1-t0-b0/", False)
    t.expect_output_lines("description: /a1-t0-b1/"       )
    t.expect_output_lines("description: /b0-a1-t0/", False)
    t.expect_output_lines("description: /b0-a0-t1/", False)
    t.expect_output_lines("description: /b0-a1-t1/", False)
    t.expect_output_lines("description: /b1-a0-t1/", False)
    t.expect_output_lines("description: /b1-a1-t0/"       )
    t.expect_output_lines("description: /b1-a1-t1/", False)

    t.run_build_system(["aaa=1", "bbb=1", "ccc=1", "toolset=%s-1" % toolset])
    t.expect_output_lines("description: /t-a0/"    , False)
    t.expect_output_lines("description: /t-a1/"           )
    t.expect_output_lines("description: /t0-a0/"   , False)
    t.expect_output_lines("description: /t0-a1/"   , False)
    t.expect_output_lines("description: /t1-a0/"   , False)
    t.expect_output_lines("description: /t1-a1/"          )
    t.expect_output_lines("description: /t-a0-b0/" , False)
    t.expect_output_lines("description: /t-a0-b1/" , False)
    t.expect_output_lines("description: /t-a1-b0/" , False)
    t.expect_output_lines("description: /t-a1-b1/"        )
    t.expect_output_lines("description: /a0-t-b0/" , False)
    t.expect_output_lines("description: /a0-t-b1/" , False)
    t.expect_output_lines("description: /a1-t-b0/" , False)
    t.expect_output_lines("description: /a1-t-b1/"        )
    t.expect_output_lines("description: /a0-b0-t/" , False)
    t.expect_output_lines("description: /a0-b1-t/" , False)
    t.expect_output_lines("description: /a1-b0-t/" , False)
    t.expect_output_lines("description: /a1-b1-t/"        )
    t.expect_output_lines("description: /t0-a0-b0/", False)
    t.expect_output_lines("description: /t0-a0-b1/", False)
    t.expect_output_lines("description: /t0-a1-b0/", False)
    t.expect_output_lines("description: /t0-a1-b1/", False)
    t.expect_output_lines("description: /t1-a0-b0/", False)
    t.expect_output_lines("description: /t1-a0-b1/", False)
    t.expect_output_lines("description: /t1-a1-b0/", False)
    t.expect_output_lines("description: /t1-a1-b1/"       )
    t.expect_output_lines("description: /a0-t1-b0/", False)
    t.expect_output_lines("description: /a0-t1-b1/", False)
    t.expect_output_lines("description: /a1-t0-b0/", False)
    t.expect_output_lines("description: /a1-t0-b1/", False)
    t.expect_output_lines("description: /b0-a1-t0/", False)
    t.expect_output_lines("description: /b0-a0-t1/", False)
    t.expect_output_lines("description: /b0-a1-t1/", False)
    t.expect_output_lines("description: /b1-a0-t1/", False)
    t.expect_output_lines("description: /b1-a1-t0/", False)
    t.expect_output_lines("description: /b1-a1-t1/"       )

    t.cleanup()
    "lib/test_lib.cpp",
    """
#ifdef _WIN32
__declspec(dllexport)
#endif
void foo() {}
""",
)

t.run_build_system(subdir="lib")
t.expect_addition("lib/bin/$toolset/debug/test_lib.dll")


# Auto adjusting of suffixes does not work, since we need to
# change dll to lib.
if ((os.name == "nt") or os.uname()[0].lower().startswith("cygwin")) and (BoostBuild.get_toolset() != "gcc"):
    t.copy("lib/bin/$toolset/debug/test_lib.implib", "lib/test_lib.implib")
    t.copy("lib/bin/$toolset/debug/test_lib.dll", "lib/test_lib.dll")
else:
    t.copy("lib/bin/$toolset/debug/test_lib.dll", "lib/test_lib.dll")


# Test that the simplest usage of searched library works.
t.write("jamroot.jam", "")

t.write(
    "jamfile.jam",
    """
import path ;
import project ;
def test_error_syntax(eof):
    t = BoostBuild.Tester(pass_toolset=False)
    t.write("file.jam", "ECHO%s" % __trailing_newline(eof))
    t.run_build_system(["-ffile.jam"], status=1)
    t.expect_output_lines("file.jam:1: syntax error at EOF")
    t.cleanup()
Exemple #19
0
def run_tests(critical_tests, other_tests):
    """
      Runs first the critical_tests and then the other_tests.

      Writes the name of the first failed test to test_results.txt. Critical
    tests are run in the specified order, other tests are run starting with the
    one that failed first on the last test run.

    """
    last_failed = last_failed_test()
    other_tests = reorder_tests(other_tests, last_failed)
    all_tests = critical_tests + other_tests

    invocation_dir = os.getcwd()
    max_test_name_len = 10
    for x in all_tests:
        if len(x) > max_test_name_len:
            max_test_name_len = len(x)

    pass_count = 0
    failures_count = 0

    for test in all_tests:
        if not xml:
            print ("%%-%ds :" % max_test_name_len % test),

        passed = 0
        try:
            __import__(test)
            passed = 1
        except KeyboardInterrupt:
            """This allows us to abort the testing manually using Ctrl-C."""
            raise
        except SystemExit:
            """This is the regular way our test scripts are supposed to report
            test failures."""
        except:
            exc_type, exc_value, exc_tb = sys.exc_info()
            try:
                BoostBuild.annotation("failure - unhandled exception", "%s - " "%s" % (exc_type.__name__, exc_value))
                BoostBuild.annotate_stack_trace(exc_tb)
            finally:
                #   Explicitly clear a hard-to-garbage-collect traceback
                # related reference cycle as per documented sys.exc_info()
                # usage suggestion.
                del exc_tb

        if passed:
            pass_count += 1
        else:
            failures_count += 1
            if failures_count == 1:
                f = open(os.path.join(invocation_dir, "test_results.txt"), "w")
                try:
                    f.write(test)
                finally:
                    f.close()

        #   Restore the current directory, which might have been changed by the
        # test.
        os.chdir(invocation_dir)

        if not xml:
            if passed:
                print ("PASSED")
            else:
                print ("FAILED")
        else:
            rs = "succeed"
            if not passed:
                rs = "fail"
            print """
<test-log library="build" test-name="%s" test-type="run" toolset="%s" test-program="%s" target-directory="%s">
<run result="%s">""" % (
                test,
                toolset,
                "tools/build/v2/test/" + test + ".py",
                "boost/bin.v2/boost.build.tests/" + toolset + "/" + test,
                rs,
            )
            if not passed:
                BoostBuild.flush_annotations(1)
            print """
</run>
</test-log>
"""
        sys.stdout.flush()  # Makes testing under emacs more entertaining.
        BoostBuild.clear_annotations()

    # Erase the file on success.
    if failures_count == 0:
        open("test_results.txt", "w").close()

    if not xml:
        print """
        === Test summary ===
        PASS: %d
        FAIL: %d
        """ % (
            pass_count,
            failures_count,
        )
Exemple #20
0
#!/usr/bin/python

# Copyright 2003 Dave Abrahams
# Copyright 2002, 2003 Vladimir Prus
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)

# Test that default build clause actually has any effect.

import BoostBuild

t = BoostBuild.Tester(use_test_config=False)

t.write("jamroot.jam", "")
t.write("jamfile.jam", "exe a : a.cpp : : debug release ;")
t.write("a.cpp", "int main() {}\n")

t.run_build_system()
t.expect_addition("bin/$toolset/debug*/a.exe")
t.expect_addition("bin/$toolset/release*/a.exe")

# Check that explictly-specified build variant suppresses default-build.
t.rm("bin")
t.run_build_system(["release"])
t.expect_addition(BoostBuild.List("bin/$toolset/release*/") * "a.exe a.obj")
t.ignore_addition('bin/*/a.rsp')
t.expect_nothing_more()

# Now check that we can specify explicit build request and default-build will be
# combined with it.
t.run_build_system(["optimization=space"])
Exemple #21
0
    typedef void type;
};
typedef time_waster<true, 10, void>::type type;
int g() { return 0; }
""")

tester.write("jamroot.jam", """\
obj test2 : test2.cpp ;
obj test1 : test1.cpp : <dependency>test2 ;
install test2i : test2 : <dependency>test1 ;
""")

tester.run_build_system()
tester.expect_addition("bin/$toolset/debug*/test2.obj")
tester.expect_addition("bin/$toolset/debug*/test1.obj")
tester.expect_addition("test2i/test2.obj")
tester.expect_nothing_more()

test2src = tester.read("test2i/test2.obj")
test2dest = tester.read("bin/$toolset/debug*/test2.obj")
if test2src != test2dest:
    BoostBuild.annotation("failure", "The object file was not copied "
        "correctly")
    tester.fail_test(1)

tester.run_build_system(["-d1"])
tester.expect_output_lines("common.copy*", False)
tester.expect_nothing_more()

tester.cleanup()
Exemple #22
0
#!/usr/bin/python

# Copyright 2018 Steven Watanabe
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)

# Test the handling of toolset.add-defaults

import BoostBuild

t = BoostBuild.Tester(pass_toolset=0, ignore_toolset_requirements=False)

t.write(
    'jamroot.jam', '''
import toolset ;
import errors ;
import feature : feature ;
import set ;

feature f1 : a b ;
feature f2 : c d ;
feature f3 : e f ;
feature f4 : g h ;
feature f5 : i j ;
feature f6 : k l m ;

rule test-rule ( properties * )
{
  if <f1>a in $(properties)
  {
    return <f2>d ;
def _info(*values):
    values = list(values) + [""]
    BoostBuild.annotation(tag, "\n".join(str(x) for x in values))
#!/usr/bin/python

# Copyright 2003, 2004, 2005, 2006 Vladimir Prus
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)

# Test that a chain of libraries works ok, no matter if we use static or shared
# linking.

import os
import string

import BoostBuild

t = BoostBuild.Tester(use_test_config=False)

# Stage the binary, so that it will be relinked without hardcode-dll-paths.
# That will check that we pass correct -rpath-link, even if not passing -rpath.
t.write("jamfile.jam", """\
stage dist : main ;
exe main : main.cpp b ;
""")

t.write("main.cpp", """\
void foo();
int main() { foo(); }
""")

t.write("jamroot.jam", "")

t.write("a/a.cpp", """\
#!/usr/bin/python

# Copyright 2007 Rene Rivera.
# Copyright 2011 Steven Watanabe
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)

import BoostBuild

t = BoostBuild.Tester(pass_toolset=0, pass_d0=False)

t.write(
    "file.jam", """\
actions .a.
{
echo [$(<:B)] 0
echo [$(<:B)] 1
echo [$(<:B)] 2
}

rule .a.
{
    DEPENDS $(<) : $(>) ;
}

NOTFILE subtest ;
.a. subtest_a : subtest ;
.a. subtest_b : subtest ;
DEPENDS all : subtest_a subtest_b ;
""")
Exemple #26
0
#!/usr/bin/python

# Copyright 2003 Vladimir Prus
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)

import BoostBuild

t = BoostBuild.Tester(use_test_config=False)

t.write("jamroot.jam", """\
exe hello : hello.cpp ;
exe hello2 : hello.cpp ;
explicit hello2 ;
""")

t.write("hello.cpp", "int main() {}\n")

t.run_build_system()
t.ignore("*.tds")
t.expect_addition(BoostBuild.List("bin/$toolset/debug*/hello") * \
    [".exe", ".obj"])
t.expect_nothing_more()

t.run_build_system(["hello2"])
t.expect_addition("bin/$toolset/debug*/hello2.exe")

t.rm(".")


# Test that 'explicit' used in a helper rule applies to the current project, and
#!/usr/bin/python

# Copyright 2012. Jurko Gospodnetic
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)

# Test correct "-p" option handling.

import BoostBuild

t = BoostBuild.Tester(["-d1"], pass_d0=False, pass_toolset=False)

t.write(
    "file.jam", """\
prefix = "echo \\"" ;
suffix = "\\"" ;
if $(NT)
{
    prefix = "(echo " ;
    suffix = ")" ;
}
actions go
{
    $(prefix)stdout$(suffix)
    $(prefix)stderr$(suffix) 1>&2
}
ECHO {{{ $(XXX) }}} ;
ALWAYS all ;
go all ;
""")
import BoostBuild
from BoostBuild import get_toolset

# clear environment for testing
#
for s in (
    'BOOST_ROOT','BOOST_BUILD_PATH','JAM_TOOLSET','BCCROOT',
    'MSVCDir','MSVC','MSVCNT','MINGW','watcom'
    ):
    
    try:
        del os.environ[s]
    except:
        pass

BoostBuild.set_defer_annotations(1)    

def run_tests(critical_tests, other_tests):
    """Runs first critical tests and then other_tests.

       Stops on first error, and write the name of failed test to
       test_results.txt. Critical tests are run in the specified order,
       other tests are run starting with the one that failed the last time.
    """
    last_failed = last_failed_test()
    other_tests = reorder_tests(other_tests, last_failed)
    all_tests = critical_tests + other_tests

    invocation_dir = os.getcwd()

    pass_count = 0
#!/usr/bin/python

# Copyright 2002, 2003 Dave Abrahams
# Copyright 2002, 2003, 2005 Vladimir Prus
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)

import BoostBuild

t = BoostBuild.Tester(use_test_config=False)
t.write("jamroot.jam", "")
t.write("lib/c.cpp", "int bar() { return 0; }\n")
t.write("lib/jamfile.jam", """\
static-lib auxilliary1 : c.cpp ;
lib auxilliary2 : c.cpp ;
""")

def reset():
    t.rm("lib/bin")

t.run_build_system(subdir='lib')
t.expect_addition("lib/bin/$toolset/debug/" * BoostBuild.List("c.obj "
    "auxilliary1.lib auxilliary2.dll"))
t.expect_nothing_more()

reset()
t.run_build_system(["link=shared"], subdir="lib")
t.expect_addition("lib/bin/$toolset/debug/" * BoostBuild.List("c.obj "
    "auxilliary1.lib auxilliary2.dll"))
t.expect_nothing_more()
t.write("lib/jamfile.jam", "lib test_lib : test_lib.cpp ;")
t.write("lib/test_lib.cpp", """
#ifdef _WIN32
__declspec(dllexport)
#endif
void foo() {}
""");

t.run_build_system(subdir="lib")
t.expect_addition("lib/bin/$toolset/debug/test_lib.dll")


# Auto adjusting of suffixes does not work, since we need to
# change dll to lib.
if ( ( os.name == "nt" ) or os.uname()[0].lower().startswith("cygwin") ) and \
    ( BoostBuild.get_toolset() != "gcc" ):
    t.copy("lib/bin/$toolset/debug/test_lib.implib", "lib/test_lib.implib")
    t.copy("lib/bin/$toolset/debug/test_lib.dll", "lib/test_lib.dll")
else:
    t.copy("lib/bin/$toolset/debug/test_lib.dll", "lib/test_lib.dll")


# Test that the simplest usage of searched library works.
t.write("jamroot.jam", "")

t.write("jamfile.jam", """
import path ;
import project ;

local here = [ project.attribute $(__name__) location ] ;
here = [ path.root $(here) [ path.pwd ] ] ;
Exemple #31
0
#!/usr/bin/python

# Copyright (C) 2013 Steven Watanabe
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)

import BoostBuild
import MockToolset

t = BoostBuild.Tester(arguments=['toolset=mock', '--ignore-site-config', '--user-config='], pass_toolset=0)

MockToolset.create(t)

# Build from source
t.write("libtiff/tiff.h", 'libtiff')
t.write("libtiff/tiff.c", 'tiff')

t.write("Jamroot.jam", """
path-constant here : . ;
using libtiff : : <source>$(here)/libtiff ;
alias libtiff : /libtiff//libtiff : : <link>static <link>shared ;
""")

MockToolset.set_expected(t, '''
source_file('tiff.c', 'tiff')
action('-c -x c -I./libtiff -o $tiff.o $tiff.c')
action('--dll $tiff.o -o $tiff.so')
action('--archive $tiff.o -o $tiff.a')
''')
Exemple #32
0
def test_basic():
    t = BoostBuild.Tester()
    __write_appender(t, "appender.jam")
    t.write("a.cpp", "")
    t.write("b.cxx", "")
    t.write("c.tui", "")
    t.write("d.wd", "")
    t.write("e.cpp", "")
    t.write("x.l", "")
    t.write("y.x_pro", "")
    t.write("z.cpp", "")
    t.write("lib/c.cpp", "int bar() { return 0; }\n")
    t.write("lib/jamfile.jam", "my-lib auxilliary : c.cpp ;")
    t.write(
        "jamroot.jam", r"""import appender ;

import "class" : new ;
import generators ;
import type ;


################################################################################
#
#   We use our own custom EXE, LIB & OBJ target generators as using the regular
# ones would force us to have to deal with different compiler/linker specific
# 'features' that really have nothing to do with this test. For example, IBM XL
# C/C++ for AIX, V12.1 (Version: 12.01.0000.0000) compiler exits with a non-zero
# exit code and thus fails our build when run with a source file using an
# unknown suffix like '.marked_cpp'.
#
################################################################################

type.register MY_EXE : my_exe ;
type.register MY_LIB : my_lib ;
type.register MY_OBJ : my_obj ;

appender.register compile-c : C : MY_OBJ ;
appender.register compile-cpp : CPP : MY_OBJ ;
appender.register link-lib composing : MY_OBJ : MY_LIB ;
appender.register link-exe composing : MY_OBJ MY_LIB : MY_EXE ;


################################################################################
#
# LEX --> C
#
################################################################################

type.register LEX : l ;

appender.register lex-to-c : LEX : C ;


################################################################################
#
#        /--> tUI_H --\
# tUI --<              >--> CPP
#        \------------/
#
################################################################################

type.register tUI : tui ;
type.register tUI_H : tui_h ;

appender.register ui-to-cpp : tUI tUI_H : CPP ;
appender.register ui-to-h : tUI : tUI_H ;


################################################################################
#
#          /--> X1 --\
# X_PRO --<           >--> CPP
#          \--> X2 --/
#
################################################################################

type.register X1 : x1 ;
type.register X2 : x2 ;
type.register X_PRO : x_pro ;

appender.register x1-x2-to-cpp : X1 X2 : CPP ;
appender.register x-pro-to-x1-x2 : X_PRO : X1 X2 ;


################################################################################
#
#   When the main target type is NM_EXE, build OBJ from CPP-MARKED and not from
# anything else, e.g. directly from CPP.
#
################################################################################

type.register CPP_MARKED : marked_cpp : CPP ;
type.register POSITIONS : positions ;
type.register NM.TARGET.CPP : target_cpp : CPP ;
type.register NM_EXE : : MY_EXE ;

appender.register marked-to-target-cpp : CPP_MARKED : NM.TARGET.CPP ;
appender.register cpp-to-marked-positions : CPP : CPP_MARKED POSITIONS ;

class "nm::target::cpp-obj-generator" : generator
{
    rule __init__ ( id )
    {
        generator.__init__ $(id) : NM.TARGET.CPP : MY_OBJ ;
        generator.set-rule-name appender.appender ;
    }

    rule requirements ( )
    {
        return <main-target-type>NM_EXE ;
    }

    rule run ( project name ? : properties * : source : multiple ? )
    {
        if [ $(source).type ] = CPP
        {
            local converted = [ generators.construct $(project) : NM.TARGET.CPP
                : $(properties) : $(source) ] ;
            if $(converted)
            {
                return [ generators.construct $(project) : MY_OBJ :
                    $(properties) : $(converted[2]) ] ;
            }
        }
    }
}
generators.register [ new "nm::target::cpp-obj-generator" target-obj ] ;
generators.override target-obj : all ;


################################################################################
#
# A more complex test case scenario with the following generators:
#  1. WHL --> CPP, WHL_LR0, H, H(%_symbols)
#  2. DLP --> CPP
#  3. WD --> WHL(%_parser) DLP(%_lexer)
#  4. A custom generator of higher priority than generators 1. & 2. that helps
#     disambiguate between them when generating CPP files from WHL and DLP
#     sources.
#
################################################################################

type.register WHL : whl ;
type.register DLP : dlp ;
type.register WHL_LR0 : lr0 ;
type.register WD : wd ;

local whale-generator-id = [ appender.register whale : WHL : CPP WHL_LR0 H
    H(%_symbols) ] ;
local dolphin-generator-id = [ appender.register dolphin : DLP : CPP ] ;
appender.register wd : WD : WHL(%_parser) DLP(%_lexer) ;

class wd-to-cpp : generator
{
    rule __init__ ( id : sources * : targets * )
    {
        generator.__init__ $(id) : $(sources) : $(targets) ;
    }

    rule run ( project name ? : property-set : source )
    {
        local new-sources = $(source) ;
        if ! [ $(source).type ] in WHL DLP
        {
            local r1 = [ generators.construct $(project) $(name) : WHL :
                $(property-set) : $(source) ] ;
            local r2 = [ generators.construct $(project) $(name) : DLP :
                $(property-set) : $(source) ] ;
            new-sources = [ sequence.unique $(r1[2-]) $(r2[2-]) ] ;
        }

        local result ;
        for local i in $(new-sources)
        {
            local t = [ generators.construct $(project) $(name) : CPP :
                $(property-set) : $(i) ] ;
            result += $(t[2-]) ;
        }
        return $(result) ;
    }
}
generators.override $(__name__).wd-to-cpp : $(whale-generator-id) ;
generators.override $(__name__).wd-to-cpp : $(dolphin-generator-id) ;
generators.register [ new wd-to-cpp $(__name__).wd-to-cpp : : CPP ] ;


################################################################################
#
# Declare build targets.
#
################################################################################

# This should not cause two CPP --> MY_OBJ constructions for a.cpp or b.cpp.
my-exe a : a.cpp b.cxx obj_1 obj_2 c.tui d.wd x.l y.x_pro lib//auxilliary ;
my-exe f : a.cpp b.cxx obj_1 obj_2 lib//auxilliary ;

# This should cause two CPP --> MY_OBJ constructions for z.cpp.
my-obj obj_1 : z.cpp ;
my-obj obj_2 : z.cpp ;

nm-exe e : e.cpp ;
""")

    t.run_build_system()
    t.expect_addition("bin/" * BoostBuild.List(
        "a.my_exe "
        "a.my_obj b.my_obj c.tui_h c.cpp c.my_obj d_parser.whl d_lexer.dlp "
        "d_parser.cpp d_lexer.cpp d_lexer.my_obj d_parser.lr0 d_parser.h "
        "d_parser.my_obj d_parser_symbols.h x.c x.my_obj y.x1 y.x2 y.cpp "
        "y.my_obj e.marked_cpp e.positions e.target_cpp e.my_obj e.my_exe "
        "f.my_exe obj_1.my_obj obj_2.my_obj"))
    t.expect_addition("lib/bin/" * BoostBuild.List("c.my_obj "
                                                   "auxilliary.my_lib"))
    t.expect_nothing_more()

    folder = "bin"
    t.expect_content_lines("%s/obj_1.my_obj" % folder, "     Sources: 'z.cpp'")
    t.expect_content_lines("%s/obj_2.my_obj" % folder, "     Sources: 'z.cpp'")
    t.expect_content_lines("%s/a.my_obj" % folder, "     Sources: 'a.cpp'")

    lines = t.stdout().splitlines()
    source_lines = [x for x in lines if re.match("^     Sources: '", x)]
    if not __match_count_is(source_lines, "'z.cpp'", 2):
        BoostBuild.annotation("failure", "z.cpp must be compiled exactly "
                              "twice.")
        t.fail_test(1)
    if not __match_count_is(source_lines, "'a.cpp'", 1):
        BoostBuild.annotation("failure", "a.cpp must be compiled exactly "
                              "once.")
        t.fail_test(1)
    t.cleanup()
Exemple #33
0
#!/usr/bin/python

# Copyright 2003 Vladimir Prus
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)

# This tests the typechecking facilities.

import BoostBuild

t = BoostBuild.Tester(["-ffile.jam"], pass_toolset=0)

t.write(
    "file.jam", """
module .typecheck
{
    rule "[path]" ( x )
    {
        if ! [ MATCH "^(::)" : $(x) ]
        {
            ECHO "Error: $(x) is not a path" ;
            return true ;
        }
    }
}

rule do ( [path] a )
{
}

do $(ARGUMENT) ;
def test_basic():
    t = BoostBuild.Tester(["-d3", "-d+12"], use_test_config=False)

    t.write(
        "a.cpp", """
#include <a.h>
# include "a.h"
#include <x.h>
int main() {}
""")
    t.write("a.h", "\n")
    t.write("a_c.c", """\
#include <a.h>
# include "a.h"
#include <x.h>
""")
    t.write("b.cpp", """\
#include "a.h"
int main() {}
""")
    t.write("b.h", "\n")
    t.write("c.cpp", """\
#include "x.h"
int main() {}
""")
    t.write("e.cpp", """\
#include "x.h"
int main() {}
""")
    t.write("x.foo", "")
    t.write("y.foo", "")

    t.write("src1/a.h", '#include "b.h"\n')
    t.write("src1/b.h", '#include "c.h"\n')
    t.write("src1/c.h", "\n")
    t.write(
        "src1/z.h", """\
extern int dummy_variable_suppressing_empty_file_warning_on_hp_cxx_compiler;
""")

    t.write("src2/b.h", "\n")

    t.write(
        "jamroot.jam", """\
import foo ;
import types/cpp ;
import types/exe ;

project test : requirements <include>src1 ;

exe a : x.foo a.cpp a_c.c ;
exe b : b.cpp ;

# Because of <define>FOO, c.cpp will be compiled to a different directory than
# everything for main target "a". Therefore, without <implicit-dependency>, C
# preprocessor processing that module will not find "x.h", which is part of
# "a"'s dependency graph.
#
# --------------------------
# More detailed explanation:
# --------------------------
#   c.cpp includes x.h which does not exist on the current include path so Boost
# Jam will try to match it to existing Jam targets to cover cases as this one
# where the file is generated by the same build.
#
#   However, as x.h is not part of "c" metatarget's dependency graph, Boost
# Build will not actualize its target by default, i.e. create its Jam target.
#
#   To get the Jam target created in time, we use the <implicit-dependency>
# feature. This tells Boost Build that it needs to actualize the dependency
# graph for metatarget "a", even though that metatarget has not been directly
# mentioned and is not a dependency for any of the metatargets mentioned in the
# current build request.
#
#   Note that Boost Build does not automatically add a dependency between the
# Jam targets in question so, if Boost Jam does not add a dependency on a target
# from that other dependency graph (x.h in our case), i.e. if c.cpp does not
# actually include x.h, us actualizing it will have no effect in the end as
# Boost Jam will not have a reason to actually build those targets in spite of
# knowing about them.
exe c : c.cpp : <define>FOO <implicit-dependency>a ;
""")

    t.write(
        "foo.jam", """\
import generators ;
import modules ;
import os ;
import print ;
import type ;
import types/cpp ;

type.register FOO : foo ;

generators.register-standard foo.foo : FOO : CPP H ;

nl = "
" ;

rule foo ( targets * : sources * : properties * )
{
    # On NT, you need an exported symbol in order to have an import library
    # generated. We will not really use the symbol defined here, just force the
    # import library creation.
    if ( [ os.name ] = NT || [ modules.peek : OS ] in CYGWIN ) &&
        <main-target-type>LIB in $(properties)
    {
        .decl = "void __declspec(dllexport) foo() {}" ;
    }
    print.output $(<[1]) ;
    print.text $(.decl:E="//")$(nl) ;
    print.output $(<[2]) ;
    print.text "#include <z.h>"$(nl) ;
}
""")

    t.write(
        "foo.py", r"""import bjam
import b2.build.type as type
import b2.build.generators as generators

from b2.manager import get_manager

type.register("FOO", ["foo"])
generators.register_standard("foo.foo", ["FOO"], ["CPP", "H"])

def prepare_foo(targets, sources, properties):
    if properties.get('os') in ['windows', 'cygwin']:
        bjam.call('set-target-variable', targets, "DECL",
            "void __declspec(dllexport) foo() {}")

get_manager().engine().register_action("foo.foo",
    "echo -e $(DECL:E=//)\\n > $(<[1])\n"
    "echo -e "#include <z.h>\\n" > $(<[2])\n", function=prepare_foo)
""")

    # Check that main target 'c' was able to find 'x.h' from 'a's dependency
    # graph.
    t.run_build_system()
    t.expect_addition("bin/$toolset/debug*/c.exe")

    # Check handling of first level includes.

    # Both 'a' and 'b' include "a.h" and should be updated.
    t.touch("a.h")
    t.run_build_system()

    t.expect_touch("bin/$toolset/debug*/a.exe")
    t.expect_touch("bin/$toolset/debug*/a.obj")
    t.expect_touch("bin/$toolset/debug*/a_c.obj")
    t.expect_touch("bin/$toolset/debug*/b.exe")
    t.expect_touch("bin/$toolset/debug*/b.obj")
    t.ignore_touch("bin/*/a.rsp")
    t.ignore_touch("bin/*/b.rsp")
    t.expect_nothing_more()

    # Only source files using include <a.h> should be compiled.
    t.touch("src1/a.h")
    t.run_build_system()

    t.expect_touch("bin/$toolset/debug*/a.exe")
    t.expect_touch("bin/$toolset/debug*/a.obj")
    t.expect_touch("bin/$toolset/debug*/a_c.obj")
    t.ignore_touch("bin/*/a.rsp")
    t.expect_nothing_more()

    # "src/a.h" includes "b.h" (in the same dir).
    t.touch("src1/b.h")
    t.run_build_system()
    t.expect_touch("bin/$toolset/debug*/a.exe")
    t.expect_touch("bin/$toolset/debug*/a.obj")
    t.expect_touch("bin/$toolset/debug*/a_c.obj")
    t.ignore_touch("bin/*/a.rsp")
    t.expect_nothing_more()

    # Included by "src/b.h". We had a bug: file included using double quotes
    # (e.g. "b.h") was not scanned at all in this case.
    t.touch("src1/c.h")
    t.run_build_system()
    t.expect_touch("bin/$toolset/debug*/a.exe")

    t.touch("b.h")
    t.run_build_system()
    t.expect_nothing_more()

    # Test dependency on a generated header.
    #
    # TODO: we have also to check that generated header is found correctly if
    # it is different for different subvariants. Lacking any toolset support,
    # this check will be implemented later.
    t.touch("x.foo")
    t.run_build_system()
    t.expect_touch("bin/$toolset/debug*/a.obj")
    t.expect_touch("bin/$toolset/debug*/a_c.obj")

    # Check that generated headers are scanned for dependencies as well.
    t.touch("src1/z.h")
    t.run_build_system()
    t.expect_touch("bin/$toolset/debug*/a.obj")
    t.expect_touch("bin/$toolset/debug*/a_c.obj")

    t.cleanup()
Exemple #35
0
def test_basic():
    t = BoostBuild.Tester(pass_d0=False)
    __write_appender(t, "appender.jam")
    t.write("a.cpp", "")
    t.write("b.cxx", "")
    t.write("c.tui", "")
    t.write("d.wd", "")
    t.write("e.cpp", "")
    t.write("x.l", "")
    t.write("y.x_pro", "")
    t.write("z.cpp", "")
    t.write("lib/c.cpp", "int bar() { return 0; }\n")
    t.write("lib/jamfile.jam", "my-lib auxilliary : c.cpp ;")
    t.write("jamroot.jam",
r"""import appender ;

import "class" : new ;
import generators ;
import type ;


################################################################################
#
#   We use our own custom EXE, LIB & OBJ target generators as using the regular
# ones would force us to have to deal with different compiler/linker specific
# 'features' that really have nothing to do with this test. For example, IBM XL
# C/C++ for AIX, V12.1 (Version: 12.01.0000.0000) compiler exits with a non-zero
# exit code and thus fails our build when run with a source file using an
# unknown suffix like '.marked_cpp'.
#
################################################################################

type.register MY_EXE : my_exe ;
type.register MY_LIB : my_lib ;
type.register MY_OBJ : my_obj ;

appender.register compile-c : C : MY_OBJ ;
appender.register compile-cpp : CPP : MY_OBJ ;
appender.register link-lib composing : MY_OBJ : MY_LIB ;
appender.register link-exe composing : MY_OBJ MY_LIB : MY_EXE ;


################################################################################
#
# LEX --> C
#
################################################################################

type.register LEX : l ;

appender.register lex-to-c : LEX : C ;


################################################################################
#
#        /--> tUI_H --\
# tUI --<              >--> CPP
#        \------------/
#
################################################################################

type.register tUI : tui ;
type.register tUI_H : tui_h ;

appender.register ui-to-cpp : tUI tUI_H : CPP ;
appender.register ui-to-h : tUI : tUI_H ;


################################################################################
#
#          /--> X1 --\
# X_PRO --<           >--> CPP
#          \--> X2 --/
#
################################################################################

type.register X1 : x1 ;
type.register X2 : x2 ;
type.register X_PRO : x_pro ;

appender.register x1-x2-to-cpp : X1 X2 : CPP ;
appender.register x-pro-to-x1-x2 : X_PRO : X1 X2 ;


################################################################################
#
#   When the main target type is NM_EXE, build OBJ from CPP-MARKED and not from
# anything else, e.g. directly from CPP.
#
################################################################################

type.register CPP_MARKED : marked_cpp : CPP ;
type.register POSITIONS : positions ;
type.register NM.TARGET.CPP : target_cpp : CPP ;
type.register NM_EXE : : MY_EXE ;

appender.register marked-to-target-cpp : CPP_MARKED : NM.TARGET.CPP ;
appender.register cpp-to-marked-positions : CPP : CPP_MARKED POSITIONS ;

class nm::target::cpp-obj-generator : generator
{
    rule __init__ ( id )
    {
        generator.__init__ $(id) : NM.TARGET.CPP : MY_OBJ ;
        generator.set-rule-name appender.appender ;
    }

    rule requirements ( )
    {
        return <main-target-type>NM_EXE ;
    }

    rule run ( project name ? : properties * : source : multiple ? )
    {
        if [ $(source).type ] = CPP
        {
            local converted = [ generators.construct $(project) : NM.TARGET.CPP
                : $(properties) : $(source) ] ;
            if $(converted)
            {
                return [ generators.construct $(project) : MY_OBJ :
                    $(properties) : $(converted[2]) ] ;
            }
        }
    }
}
generators.register [ new nm::target::cpp-obj-generator target-obj ] ;
generators.override target-obj : all ;


################################################################################
#
# A more complex test case scenario with the following generators:
#  1. WHL --> CPP, WHL_LR0, H, H(%_symbols)
#  2. DLP --> CPP
#  3. WD --> WHL(%_parser) DLP(%_lexer)
#  4. A custom generator of higher priority than generators 1. & 2. that helps
#     disambiguate between them when generating CPP files from WHL and DLP
#     sources.
#
################################################################################

type.register WHL : whl ;
type.register DLP : dlp ;
type.register WHL_LR0 : lr0 ;
type.register WD : wd ;

local whale-generator-id = [ appender.register whale : WHL : CPP WHL_LR0 H
    H(%_symbols) ] ;
local dolphin-generator-id = [ appender.register dolphin : DLP : CPP ] ;
appender.register wd : WD : WHL(%_parser) DLP(%_lexer) ;

class wd-to-cpp : generator
{
    rule __init__ ( id : sources * : targets * )
    {
        generator.__init__ $(id) : $(sources) : $(targets) ;
    }

    rule run ( project name ? : property-set : source )
    {
        local new-sources = $(source) ;
        if ! [ $(source).type ] in WHL DLP
        {
            local r1 = [ generators.construct $(project) $(name) : WHL :
                $(property-set) : $(source) ] ;
            local r2 = [ generators.construct $(project) $(name) : DLP :
                $(property-set) : $(source) ] ;
            new-sources = [ sequence.unique $(r1[2-]) $(r2[2-]) ] ;
        }

        local result ;
        for local i in $(new-sources)
        {
            local t = [ generators.construct $(project) $(name) : CPP :
                $(property-set) : $(i) ] ;
            result += $(t[2-]) ;
        }
        return $(result) ;
    }
}
generators.override $(__name__).wd-to-cpp : $(whale-generator-id) ;
generators.override $(__name__).wd-to-cpp : $(dolphin-generator-id) ;
generators.register [ new wd-to-cpp $(__name__).wd-to-cpp : : CPP ] ;


################################################################################
#
# Declare build targets.
#
################################################################################

# This should not cause two CPP --> MY_OBJ constructions for a.cpp or b.cpp.
my-exe a : a.cpp b.cxx obj_1 obj_2 c.tui d.wd x.l y.x_pro lib//auxilliary ;
my-exe f : a.cpp b.cxx obj_1 obj_2 lib//auxilliary ;

# This should cause two CPP --> MY_OBJ constructions for z.cpp.
my-obj obj_1 : z.cpp ;
my-obj obj_2 : z.cpp ;

nm-exe e : e.cpp ;
""")

    t.run_build_system()
    t.expect_addition("bin/$toolset/debug/" * BoostBuild.List("a.my_exe "
        "a.my_obj b.my_obj c.tui_h c.cpp c.my_obj d_parser.whl d_lexer.dlp "
        "d_parser.cpp d_lexer.cpp d_lexer.my_obj d_parser.lr0 d_parser.h "
        "d_parser.my_obj d_parser_symbols.h x.c x.my_obj y.x1 y.x2 y.cpp "
        "y.my_obj e.marked_cpp e.positions e.target_cpp e.my_obj e.my_exe "
        "f.my_exe obj_1.my_obj obj_2.my_obj"))
    t.expect_addition("lib/bin/$toolset/debug/" * BoostBuild.List("c.my_obj "
        "auxilliary.my_lib"))
    t.expect_nothing_more()

    folder = "bin/$toolset/debug"
    t.expect_content_lines("%s/obj_1.my_obj" % folder, "     Sources: 'z.cpp'")
    t.expect_content_lines("%s/obj_2.my_obj" % folder, "     Sources: 'z.cpp'")
    t.expect_content_lines("%s/a.my_obj" % folder, "     Sources: 'a.cpp'")

    lines = t.stdout().splitlines()
    source_lines = [x for x in lines if re.match("^     Sources: '", x)]
    if not __match_count_is(source_lines, "'z.cpp'", 2):
        BoostBuild.annotation("failure", "z.cpp must be compiled exactly "
            "twice.")
        t.fail_test(1)
    if not __match_count_is(source_lines, "'a.cpp'", 1):
        BoostBuild.annotation("failure", "a.cpp must be compiled exactly "
            "once.")
        t.fail_test(1)
    t.cleanup()
Exemple #36
0
def test_conditions_on_default_toolset():
    """Test that toolset and toolset subfeature conditioned properties get
    applied correctly when the toolset is selected by default. Implicitly tests
    that we can use the set-default-toolset rule to set the default toolset to
    be used by Boost Build.
    """

    t = BoostBuild.Tester("--user-config= --ignore-site-config",
        pass_toolset=False, use_test_config=False)

    toolset_name           = "myCustomTestToolset"
    toolset_version        = "v"
    toolset_version_unused = "v_unused"
    message_loaded         = "Toolset '%s' loaded." % toolset_name
    message_initialized    = "Toolset '%s' initialized." % toolset_name ;

    # Custom toolset.
    t.write(toolset_name + ".jam", """
import feature ;
ECHO "%(message_loaded)s" ;
feature.extend toolset : %(toolset_name)s ;
feature.subfeature toolset %(toolset_name)s : version : %(toolset_version)s %(toolset_version_unused)s ;
rule init ( version ) { ECHO "%(message_initialized)s" ; }
""" % {'message_loaded'     : message_loaded     ,
    'message_initialized'   : message_initialized,
    'toolset_name'          : toolset_name       ,
    'toolset_version'       : toolset_version    ,
    'toolset_version_unused': toolset_version_unused})

    # Main Boost Build project script.
    t.write("Jamroot.jam", """
import build-system ;
import errors ;
import feature ;
import notfile ;

build-system.set-default-toolset %(toolset_name)s : %(toolset_version)s ;

feature.feature description : : free incidental ;

# We use a rule instead of an action to avoid problems with action output not
# getting piped to stdout by the testing system.
rule buildRule ( names : targets ? : properties * )
{
    local descriptions = [ feature.get-values description : $(properties) ] ;
    ECHO "descriptions:" /$(descriptions)/ ;
    local toolset = [ feature.get-values toolset : $(properties) ] ;
    ECHO "toolset:" /$(toolset)/ ;
    local toolset-version = [ feature.get-values "toolset-$(toolset):version" : $(properties) ] ;
    ECHO "toolset-version:" /$(toolset-version)/ ;
}

notfile testTarget
    : @buildRule
    :
    :
    <description>stand-alone
    <toolset>%(toolset_name)s:<description>toolset
    <toolset>%(toolset_name)s-%(toolset_version)s:<description>toolset-version
    <toolset>%(toolset_name)s-%(toolset_version_unused)s:<description>toolset-version-unused ;
""" % {'toolset_name'       : toolset_name   ,
    'toolset_version'       : toolset_version,
    'toolset_version_unused': toolset_version_unused})

    t.run_build_system()
    t.expect_output_line(configuring_default_toolset_message % toolset_name)
    t.expect_output_line(message_loaded)
    t.expect_output_line(message_initialized)
    t.expect_output_line("descriptions: /stand-alone/ /toolset/ /toolset-version/")
    t.expect_output_line("toolset: /%s/" % toolset_name)
    t.expect_output_line("toolset-version: /%s/" % toolset_version)

    t.cleanup()
Exemple #37
0
#!/usr/bin/python

# Copyright 2002-2005 Dave Abrahams.
# Copyright 2002-2006 Vladimir Prus.
# Distributed under the Boost Software License, Version 1.0.
#    (See accompanying file LICENSE_1_0.txt or copy at
#         http://www.boost.org/LICENSE_1_0.txt)

import BoostBuild

import os
import os.path
import sys

xml = "--xml" in sys.argv
toolset = BoostBuild.get_toolset()


# Clear environment for testing.
#
for s in ("BOOST_ROOT", "BOOST_BUILD_PATH", "JAM_TOOLSET", "BCCROOT", "MSVCDir", "MSVC", "MSVCNT", "MINGW", "watcom"):
    try:
        del os.environ[s]
    except:
        pass

BoostBuild.set_defer_annotations(1)


def run_tests(critical_tests, other_tests):
    """
Exemple #38
0
#!/usr/bin/python

# Copyright 2003 Vladimir Prus
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE.txt or https://www.bfgroup.xyz/b2/LICENSE.txt)

# This tests the "existing" and "updated" modifiers on actions.

import BoostBuild

t = BoostBuild.Tester(pass_toolset=0)

code = """
DEPENDS all : a ;
ALWAYS a ;
NOTFILE a ;

actions existing make-a
{
    echo $(>) > list
}
make-a a : a-1 a-2 a-3 ;
DEPENDS a : a-1 a-2 a-3 ;
NOCARE a-1 a-2 ;

actions make-a3
{
   echo foo > $(<)
}
make-a3 a-3 ;
"""
Exemple #39
0
#!/usr/bin/python

# Copyright 2002-2005 Dave Abrahams.
# Copyright 2002-2006 Vladimir Prus.
# Distributed under the Boost Software License, Version 1.0.
#    (See accompanying file LICENSE_1_0.txt or copy at
#         http://www.boost.org/LICENSE_1_0.txt)

import os
import sys
import string
import BoostBuild

xml = "--xml" in sys.argv
toolset = BoostBuild.get_toolset()


# Clear environment for testing.
#
for s in ('BOOST_ROOT', 'BOOST_BUILD_PATH', 'JAM_TOOLSET', 'BCCROOT', 'MSVCDir',
    'MSVC', 'MSVCNT', 'MINGW', 'watcom' ):
    try:
        del os.environ[s]
    except:
        pass

BoostBuild.set_defer_annotations(1)


def run_tests(critical_tests, other_tests):
    """Runs first critical tests and then other_tests.
# Niklaus Giger, 2005-03-15
# Testing whether we may run a test in absolute directories. There are no tests
# for temporary directories as this is implictly tested in a lot of other cases.

# TODO: Move to a separate testing-system test group.
# TODO: Make the test not display any output on success.
# TODO: Make sure implemented path handling is correct under Windows, Cygwin &
#       Unix/Linux.

import os
import tempfile

import BoostBuild

t = BoostBuild.Tester(["-ffile.jam"],
                      workdir=os.getcwd(),
                      pass_d0=False,
                      pass_toolset=False)

t.write("file.jam", "EXIT [ PWD ] : 0 ;")

t.run_build_system()
t.expect_output_lines("*%s*" % tempfile.gettempdir(), False)
t.expect_output_lines("*build/v2/test*")

t.run_build_system(status=1,
                   subdir="/must/fail/with/absolute/path",
                   stderr=None)

t.cleanup()
Exemple #41
0
def test_raw_nt(n=None, error=False):
    t = BoostBuild.Tester(["-d1", "-d+4"], pass_d0=False, pass_toolset=0,
        use_test_config=False)

    cmd_prefix = "%s -c \"print('XXX: " % executable
    cmd_suffix = "')\""
    cmd_extra_length = len(cmd_prefix) + len(cmd_suffix)

    if n == None:
        n = cmd_extra_length

    data_length = n - cmd_extra_length
    if data_length < 0:
        BoostBuild.annotation("failure", """\
Can not construct Windows command of desired length. Requested command length
too short for the current test configuration.
    Requested command length: %d
    Minimal supported command length: %d
""" % (n, cmd_extra_length))
        t.fail_test(1, dump_difference=False)

    #   Each $(Xx10-1) variable contains X words of 9 characters each, which,
    # including spaces between words, brings the total number of characters in
    # its string representation to X * 10 - 1 (X * 9 characters + (X - 1)
    # spaces).
    t.write("file.jam", """\
ten = 0 1 2 3 4 5 6 7 8 9 ;

1x10-1 = 123456789 ;
10x10-1 = $(ten)12345678 ;
100x10-1 = $(ten)$(ten)1234567 ;
1000x10-1 = $(ten)$(ten)$(ten)123456 ;

actions do_echo
{
    %s%s%s
}
JAMSHELL = %% ;
do_echo all ;
""" % (cmd_prefix, string_of_length(data_length), cmd_suffix))
    if error:
        expected_status = 1
    else:
        expected_status = 0
    t.run_build_system(["-ffile.jam"], status=expected_status)
    if error:
        t.expect_output_lines("Executing raw command directly", False)
        t.expect_output_lines("do_echo action is too long (%d, max 32766):" % n
            )
        t.expect_output_lines("XXX: *", False)
    else:
        t.expect_output_lines("Executing raw command directly")
        t.expect_output_lines("do_echo action is too long*", False)

        m = re.search("^XXX: (.*)$", t.stdout(), re.MULTILINE)
        if not m:
            BoostBuild.annotation("failure", "Expected output line starting "
                "with 'XXX: ' not found.")
            t.fail_test(1, dump_difference=False)
        if len(m.group(1)) != data_length:
            BoostBuild.annotation("failure", """Unexpected output data length.
    Expected: %d
    Received: %d""" % (n, len(m.group(1))))
            t.fail_test(1, dump_difference=False)

    t.cleanup()
#!/usr/bin/python

# Copyright 2003, 2004, 2005, 2006 Vladimir Prus
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)

# Test that a chain of libraries works ok, no matter if we use static or shared
# linking.

import BoostBuild
import string
import os

t = BoostBuild.Tester()

t.write(
    "jamfile.jam", """
# Stage the binary, so that it will be relinked without hardcode-dll-paths. That
# will chech that we pass correct -rpath-link, even if not passing -rpath.
stage dist : main ;
exe main : main.cpp b ;
""")

t.write("main.cpp", """
void foo();
int main() { foo(); }
""")

t.write("jamroot.jam", """
""")
Exemple #43
0
lib a : a.cpp ;
install dist : a ;
""")

t.write("a/a.cpp", """
#if defined(_WIN32)
__declspec(dllexport)
#endif
void a() {}
""")

t.run_build_system(subdir="a")
t.expect_addition("a/dist/a.dll")

if ( ( os.name == 'nt' ) or os.uname()[0].lower().startswith('cygwin') ) and \
    ( BoostBuild.get_toolset() != 'gcc' ):
    # This is windows import library -- we know the exact name.
    file = "a/dist/a.lib"
else:
    file = t.adjust_names(["a/dist/a.dll"])[0]

t.write("b/jamfile.jam", """
lib b : b.cpp ../%s ;
""" % file)

t.write("b/b.cpp", """
#if defined(_WIN32)
__declspec(dllimport)
#endif
void a();
#if defined(_WIN32)
Exemple #44
0
# Copyright 2002-2005 Dave Abrahams.
# Copyright 2002-2006 Vladimir Prus.
# Distributed under the Boost Software License, Version 1.0.
#    (See accompanying file LICENSE.txt or copy at
#         https://www.bfgroup.xyz/b2/LICENSE.txt)

from __future__ import print_function

import BoostBuild

import os
import os.path
import sys

xml = "--xml" in sys.argv
toolset = BoostBuild.get_toolset()

# Clear environment for testing.
#
for s in ("BOOST_ROOT", "BOOST_BUILD_PATH", "JAM_TOOLSET", "BCCROOT",
          "MSVCDir", "MSVC", "MSVCNT", "MINGW", "watcom"):
    try:
        del os.environ[s]
    except:
        pass

BoostBuild.set_defer_annotations(1)


def run_tests(critical_tests, other_tests):
    """
Exemple #45
0
def run_tests(critical_tests, other_tests):
    """Runs first critical tests and then other_tests.

       Stops on first error, and write the name of failed test to
       test_results.txt. Critical tests are run in the specified order, other
       tests are run starting with the one that failed the last time.
    """
    last_failed = last_failed_test()
    other_tests = reorder_tests(other_tests, last_failed)
    all_tests = critical_tests + other_tests

    invocation_dir = os.getcwd()

    pass_count = 0
    failures_count = 0

    for i in all_tests:
        passed = 1
        if not xml:
            print ("%-25s : " % (i)),
        try:
            __import__(i)
        except SystemExit:
            passed = 0
            if failures_count == 0:
                f = open(os.path.join(invocation_dir, "test_results.txt"), "w")
                f.write(i)
                f.close()
            failures_count = failures_count + 1
            # Restore the current directory, which might be changed by the test.
            os.chdir(invocation_dir)

        if not xml:
            if passed:
                print "PASSED"
            else:
                print "FAILED"

            if i == "regression":
                BoostBuild.flush_annotations()
            BoostBuild.clear_annotations()
        else:
            rs = "succeed"
            if not passed:
                rs = "fail"
            print """
<test-log library="build" test-name="%s" test-type="run" toolset="%s" test-program="%s" target-directory="%s">
<run result="%s">""" % (
                i,
                toolset,
                "tools/build/v2/test/" + i + ".py",
                "boost/bin.v2/boost.build.tests/" + toolset + "/" + i,
                rs,
            )

            if not passed:
                BoostBuild.flush_annotations(1)

            print """
</run>
</test-log>
"""
        if passed:
            pass_count = pass_count + 1
        sys.stdout.flush()  # Makes testing under emacs more entertaining.

    # Erase the file on success.
    if failures_count == 0:
        open("test_results.txt", "w")

    if not xml:
        print """
        === Test summary ===
        PASS: %d
        FAIL: %d
        """ % (
            pass_count,
            failures_count,
        )
Exemple #46
0
def run_tests(critical_tests, other_tests):
    """
      Runs first the critical_tests and then the other_tests.

      Writes the name of the first failed test to test_results.txt. Critical
    tests are run in the specified order, other tests are run starting with the
    one that failed first on the last test run.

    """
    last_failed = last_failed_test()
    other_tests = reorder_tests(other_tests, last_failed)
    all_tests = critical_tests + other_tests

    invocation_dir = os.getcwd()
    max_test_name_len = 10
    for x in all_tests:
        if len(x) > max_test_name_len:
            max_test_name_len = len(x)

    pass_count = 0
    failures_count = 0

    for test in all_tests:
        if not xml:
            s = "%%-%ds :" % max_test_name_len % test
            print(s, end='')

        passed = 0
        try:
            __import__(test)
            passed = 1
        except KeyboardInterrupt:
            """This allows us to abort the testing manually using Ctrl-C."""
            raise
        except SystemExit as e:
            """This is the regular way our test scripts are supposed to report
            test failures."""
            if e.code is None or e.code == 0:
                passed = 1
        except:
            exc_type, exc_value, exc_tb = sys.exc_info()
            try:
                BoostBuild.annotation(
                    "failure - unhandled exception", "%s - "
                    "%s" % (exc_type.__name__, exc_value))
                BoostBuild.annotate_stack_trace(exc_tb)
            finally:
                #   Explicitly clear a hard-to-garbage-collect traceback
                # related reference cycle as per documented sys.exc_info()
                # usage suggestion.
                del exc_tb

        if passed:
            pass_count += 1
        else:
            failures_count += 1
            if failures_count == 1:
                f = open(os.path.join(invocation_dir, "test_results.txt"), "w")
                try:
                    f.write(test)
                finally:
                    f.close()

        #   Restore the current directory, which might have been changed by the
        # test.
        os.chdir(invocation_dir)

        if not xml:
            if passed:
                print("PASSED")
            else:
                print("FAILED")
                BoostBuild.flush_annotations()
        else:
            rs = "succeed"
            if not passed:
                rs = "fail"
            print(
                '''
<test-log library="build" test-name="%s" test-type="run" toolset="%s" test-program="%s" target-directory="%s">
<run result="%s">''' %
                (test, toolset, "tools/build/v2/test/" + test + ".py",
                 "boost/bin.v2/boost.build.tests/" + toolset + "/" + test, rs))
            if not passed:
                BoostBuild.flush_annotations(1)
            print('''
</run>
</test-log>
''')
        sys.stdout.flush()  # Makes testing under emacs more entertaining.
        BoostBuild.clear_annotations()

    # Erase the file on success.
    if failures_count == 0:
        open("test_results.txt", "w").close()

    if not xml:
        print('''
        === Test summary ===
        PASS: %d
        FAIL: %d
        ''' % (pass_count, failures_count))

    # exit with failure with failures
    if failures_count > 0:
        sys.exit(1)
Exemple #47
0
 def __assertionFailure(self, message):
     BoostBuild.annotation("failure", "Internal test assertion failure "
         "- %s" % message)
     self.__tester.fail_test(1)
Exemple #48
0
#ifdef ERROR
#error ERROR defined
#endif
#ifndef OK
#error ERROR not defined
#endif
''')

# Don't check the status immediately, so that we have a chance
# to print config.log.  Also, we need a minimum of d2 to make
# sure that we always see the commands and output.
t.run_build_system(['-sOBJECT_FILE=' + linker_input, '-d2'], status=None)

if t.status != 0:
    log_file = t.read('bin/config.log')
    BoostBuild.annotation("config.log", log_file)
    t.fail_test(True)

t.expect_output_lines(['    - has --illegal-flag-cpp   : no',
                       '    - has -DMACRO_CPP          : yes',
                       '    - has --illegal-flag-c     : no',
                       '    - has -DMACRO_C            : yes',
                       '    - has --illegal-flag-link  : no',
                       '    - has *bin*/input.* : yes'])
t.expect_addition('bin/$toolset/debug*/fail_cpp.obj')
t.expect_addition('bin/$toolset/debug*/pass_cpp.obj')
t.expect_addition('bin/$toolset/debug*/fail_c.obj')
t.expect_addition('bin/$toolset/debug*/pass_c.obj')
t.expect_addition('bin/$toolset/debug*/fail_link.obj')
t.expect_addition('bin/$toolset/debug*/pass_link.obj')