mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2026-08-14 23:43:44 -04:00
Squashed 'boost/' content from commit b4feb19f2
git-subtree-dir: boost git-subtree-split: b4feb19f287ee92d87a9624b5d36b7cf46aeadeb
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,250 @@
|
||||
#!/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 sys
|
||||
|
||||
def create(t):
|
||||
t.write('''mockinfo.py''', '''
|
||||
import re
|
||||
import optparse
|
||||
import os
|
||||
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option('-o', dest="output_file")
|
||||
parser.add_option('-x', dest="language")
|
||||
parser.add_option('-c', dest="compile", action="store_true")
|
||||
parser.add_option('-I', dest="includes", action="append")
|
||||
parser.add_option('-L', dest="library_path", action="append")
|
||||
parser.add_option('--dll', dest="dll", action="store_true")
|
||||
parser.add_option('--archive', dest="archive", action="store_true")
|
||||
parser.add_option('--static-lib', dest="static_libraries", action="append")
|
||||
parser.add_option('--shared-lib', dest="shared_libraries", action="append")
|
||||
|
||||
cwd = os.environ["JAM_CWD"]
|
||||
|
||||
class MockInfo(object):
|
||||
def __init__(self, verbose=False):
|
||||
self.files = dict()
|
||||
self.commands = list()
|
||||
self.verbose = verbose
|
||||
def source_file(self, name, pattern):
|
||||
self.files[name] = pattern
|
||||
def action(self, command, status=0):
|
||||
self.commands.append((command, status))
|
||||
def check(self, command):
|
||||
print "Testing command", command
|
||||
for (raw, status) in self.commands:
|
||||
if self.matches(raw, command):
|
||||
return status
|
||||
def matches(self, raw, command):
|
||||
(expected_options, expected_args) = parser.parse_args(raw.split())
|
||||
options = command[0]
|
||||
input_files = list(command[1])
|
||||
if self.verbose:
|
||||
print " - matching against", (expected_options, expected_args)
|
||||
if len(expected_args) != len(input_files):
|
||||
if self.verbose:
|
||||
print " argument list sizes differ"
|
||||
return False
|
||||
for arg in expected_args:
|
||||
if arg.startswith('$'):
|
||||
fileid = arg[1:]
|
||||
pattern = self.files[fileid] if fileid in self.files else fileid
|
||||
matching_file = None
|
||||
for input_file in input_files:
|
||||
with open(input_file, 'r') as f:
|
||||
contents = f.read()
|
||||
if pattern == contents:
|
||||
matching_file = input_file
|
||||
break
|
||||
if matching_file is not None:
|
||||
input_files.remove(matching_file)
|
||||
else:
|
||||
if self.verbose:
|
||||
print " Failed to match input file contents: %s" % arg
|
||||
return False
|
||||
else:
|
||||
if arg in input_files:
|
||||
input_files.remove(arg)
|
||||
else:
|
||||
if self.verbose:
|
||||
print " Failed to match input file: %s" % arg
|
||||
return False
|
||||
|
||||
if options.language != expected_options.language:
|
||||
if self.verbose:
|
||||
print " Failed to match -c"
|
||||
return False
|
||||
|
||||
if options.compile != expected_options.compile:
|
||||
if self.verbose:
|
||||
print " Failed to match -x"
|
||||
return False
|
||||
|
||||
# Normalize a path for comparison purposes
|
||||
def adjust_path(p):
|
||||
return os.path.normcase(os.path.normpath(os.path.join(cwd, p)))
|
||||
|
||||
# order matters
|
||||
if options.includes is None:
|
||||
options.includes = []
|
||||
if expected_options.includes is None:
|
||||
expected_options.includes = []
|
||||
if map(adjust_path, options.includes) != \
|
||||
map(adjust_path, expected_options.includes):
|
||||
if self.verbose:
|
||||
print " Failed to match -I ", map(adjust_path, options.includes), \
|
||||
" != ", map(adjust_path, expected_options.includes)
|
||||
return False
|
||||
|
||||
if options.library_path is None:
|
||||
options.library_path = []
|
||||
if expected_options.library_path is None:
|
||||
expected_options.library_path = []
|
||||
if map(adjust_path, options.library_path) != \
|
||||
map(adjust_path, expected_options.library_path):
|
||||
if self.verbose:
|
||||
print " Failed to match -L ", map(adjust_path, options.library_path), \
|
||||
" != ", map(adjust_path, expected_options.library_path)
|
||||
return False
|
||||
|
||||
if options.static_libraries != expected_options.static_libraries:
|
||||
if self.verbose:
|
||||
print " Failed to match --static-lib"
|
||||
return False
|
||||
|
||||
if options.shared_libraries != expected_options.shared_libraries:
|
||||
if self.verbose:
|
||||
print " Failed to match --shared-lib"
|
||||
return False
|
||||
|
||||
if options.dll != expected_options.dll:
|
||||
if self.verbose:
|
||||
print " Failed to match --dll"
|
||||
return False
|
||||
|
||||
if options.archive != expected_options.archive:
|
||||
if self.verbose:
|
||||
print " Failed to match --archive"
|
||||
return False
|
||||
|
||||
# The output must be handled after everything else
|
||||
# is validated
|
||||
if expected_options.output_file is not None:
|
||||
if options.output_file is not None:
|
||||
if expected_options.output_file.startswith('$'):
|
||||
fileid = expected_options.output_file[1:]
|
||||
if fileid not in self.files:
|
||||
self.files[fileid] = fileid
|
||||
else:
|
||||
assert(self.files[fileid] == fileid)
|
||||
with open(options.output_file, 'w') as output:
|
||||
output.write(fileid)
|
||||
else:
|
||||
if self.verbose:
|
||||
print "Failed to match -o"
|
||||
return False
|
||||
elif options.output_file is not None:
|
||||
if self.verbose:
|
||||
print "Failed to match -o"
|
||||
return False
|
||||
|
||||
# if we've gotten here, then everything matched
|
||||
if self.verbose:
|
||||
print " Matched"
|
||||
return True
|
||||
''')
|
||||
|
||||
t.write('mock.py', '''
|
||||
import mockinfo
|
||||
import markup
|
||||
import sys
|
||||
|
||||
status = markup.info.check(mockinfo.parser.parse_args())
|
||||
if status is not None:
|
||||
exit(status)
|
||||
else:
|
||||
print("Unrecognized command: " + ' '.join(sys.argv))
|
||||
exit(1)
|
||||
''')
|
||||
|
||||
t.write('mock.jam', '''
|
||||
import feature ;
|
||||
import toolset ;
|
||||
import path ;
|
||||
import modules ;
|
||||
import common ;
|
||||
import type ;
|
||||
|
||||
.python-cmd = "\"%s\"" ;
|
||||
|
||||
# Behave the same as gcc on Windows, because that's what
|
||||
# the test system expects
|
||||
type.set-generated-target-prefix SHARED_LIB : <toolset>mock <target-os>windows : lib ;
|
||||
type.set-generated-target-suffix STATIC_LIB : <toolset>mock <target-os>windows : a ;
|
||||
|
||||
rule init ( )
|
||||
{
|
||||
local here = [ path.make [ modules.binding $(__name__) ] ] ;
|
||||
here = [ path.native [ path.root [ path.parent $(here) ] [ path.pwd ] ] ] ;
|
||||
.config-cmd = [ common.variable-setting-command JAM_CWD : $(here) ] $(.python-cmd) -B ;
|
||||
}
|
||||
|
||||
feature.extend toolset : mock ;
|
||||
|
||||
generators.register-c-compiler mock.compile.c++ : CPP : OBJ : <toolset>mock ;
|
||||
generators.register-c-compiler mock.compile.c : C : OBJ : <toolset>mock ;
|
||||
|
||||
generators.register-linker mock.link : LIB OBJ : EXE : <toolset>mock ;
|
||||
generators.register-linker mock.link.dll : LIB OBJ : SHARED_LIB : <toolset>mock ;
|
||||
generators.register-archiver mock.archive : OBJ : STATIC_LIB : <toolset>mock ;
|
||||
|
||||
toolset.flags mock.compile INCLUDES <include> ;
|
||||
|
||||
actions compile.c
|
||||
{
|
||||
$(.config-cmd) mock.py -c -x c -I"$(INCLUDES)" "$(>)" -o "$(<)"
|
||||
}
|
||||
|
||||
actions compile.c++
|
||||
{
|
||||
$(.config-cmd) mock.py -c -x c++ -I"$(INCLUDES)" "$(>)" -o "$(<)"
|
||||
}
|
||||
|
||||
toolset.flags mock.link USER_OPTIONS <linkflags> ;
|
||||
toolset.flags mock.link FINDLIBS-STATIC <find-static-library> ;
|
||||
toolset.flags mock.link FINDLIBS-SHARED <find-shared-library> ;
|
||||
toolset.flags mock.link LINK_PATH <library-path> ;
|
||||
toolset.flags mock.link LIBRARIES <library-file> ;
|
||||
|
||||
actions link
|
||||
{
|
||||
$(.config-cmd) mock.py "$(>)" -o "$(<)" $(USER_OPTIONS) -L"$(LINK_PATH)" --static-lib=$(FINDLIBS-STATIC) --shared-lib=$(FINDLIBS-SHARED)
|
||||
}
|
||||
|
||||
actions archive
|
||||
{
|
||||
$(.config-cmd) mock.py --archive "$(>)" -o "$(<)" $(USER_OPTIONS)
|
||||
}
|
||||
|
||||
actions link.dll
|
||||
{
|
||||
$(.config-cmd) mock.py --dll "$(>)" -o "$(<)" $(USER_OPTIONS) -L"$(LINK_PATH)" --static-lib=$(FINDLIBS-STATIC) --shared-lib=$(FINDLIBS-SHARED)
|
||||
}
|
||||
|
||||
''' % sys.executable.replace('\\', '\\\\'))
|
||||
|
||||
def set_expected(t, markup):
|
||||
verbose = "True" if t.verbose else "False"
|
||||
t.write('markup.py', '''
|
||||
import mockinfo
|
||||
info = mockinfo.MockInfo(%s)
|
||||
def source_file(name, contents):
|
||||
info.source_file(name, contents)
|
||||
def action(command, status=0):
|
||||
info.action(command, status)
|
||||
''' % verbose + markup)
|
||||
@@ -0,0 +1,589 @@
|
||||
"""
|
||||
TestCmd.py: a testing framework for commands and scripts.
|
||||
|
||||
The TestCmd module provides a framework for portable automated testing of
|
||||
executable commands and scripts (in any language, not just Python), especially
|
||||
commands and scripts that require file system interaction.
|
||||
|
||||
In addition to running tests and evaluating conditions, the TestCmd module
|
||||
manages and cleans up one or more temporary workspace directories, and provides
|
||||
methods for creating files and directories in those workspace directories from
|
||||
in-line data, here-documents), allowing tests to be completely self-contained.
|
||||
|
||||
A TestCmd environment object is created via the usual invocation:
|
||||
|
||||
test = TestCmd()
|
||||
|
||||
The TestCmd module provides pass_test(), fail_test(), and no_result() unbound
|
||||
methods that report test results for use with the Aegis change management
|
||||
system. These methods terminate the test immediately, reporting PASSED, FAILED
|
||||
or NO RESULT respectively and exiting with status 0 (success), 1 or 2
|
||||
respectively. This allows for a distinction between an actual failed test and a
|
||||
test that could not be properly evaluated because of an external condition (such
|
||||
as a full file system or incorrect permissions).
|
||||
|
||||
"""
|
||||
|
||||
# Copyright 2000 Steven Knight
|
||||
# This module is free software, and you may redistribute it and/or modify
|
||||
# it under the same terms as Python itself, so long as this copyright message
|
||||
# and disclaimer are retained in their original form.
|
||||
#
|
||||
# IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
# SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
|
||||
# THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
# DAMAGE.
|
||||
#
|
||||
# THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
# PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
|
||||
# AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
|
||||
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
# Copyright 2002-2003 Vladimir Prus.
|
||||
# Copyright 2002-2003 Dave Abrahams.
|
||||
# Copyright 2006 Rene Rivera.
|
||||
# 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)
|
||||
|
||||
|
||||
from string import join, split
|
||||
|
||||
__author__ = "Steven Knight <knight@baldmt.com>"
|
||||
__revision__ = "TestCmd.py 0.D002 2001/08/31 14:56:12 software"
|
||||
__version__ = "0.02"
|
||||
|
||||
from types import *
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import re
|
||||
import shutil
|
||||
import stat
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import traceback
|
||||
|
||||
|
||||
tempfile.template = 'testcmd.'
|
||||
|
||||
_Cleanup = []
|
||||
|
||||
def _clean():
|
||||
global _Cleanup
|
||||
list = _Cleanup[:]
|
||||
_Cleanup = []
|
||||
list.reverse()
|
||||
for test in list:
|
||||
test.cleanup()
|
||||
|
||||
sys.exitfunc = _clean
|
||||
|
||||
|
||||
def caller(tblist, skip):
|
||||
string = ""
|
||||
arr = []
|
||||
for file, line, name, text in tblist:
|
||||
if file[-10:] == "TestCmd.py":
|
||||
break
|
||||
arr = [(file, line, name, text)] + arr
|
||||
atfrom = "at"
|
||||
for file, line, name, text in arr[skip:]:
|
||||
if name == "?":
|
||||
name = ""
|
||||
else:
|
||||
name = " (" + name + ")"
|
||||
string = string + ("%s line %d of %s%s\n" % (atfrom, line, file, name))
|
||||
atfrom = "\tfrom"
|
||||
return string
|
||||
|
||||
|
||||
def fail_test(self=None, condition=True, function=None, skip=0):
|
||||
"""Cause the test to fail.
|
||||
|
||||
By default, the fail_test() method reports that the test FAILED and exits
|
||||
with a status of 1. If a condition argument is supplied, the test fails
|
||||
only if the condition is true.
|
||||
|
||||
"""
|
||||
if not condition:
|
||||
return
|
||||
if not function is None:
|
||||
function()
|
||||
of = ""
|
||||
desc = ""
|
||||
sep = " "
|
||||
if not self is None:
|
||||
if self.program:
|
||||
of = " of " + join(self.program, " ")
|
||||
sep = "\n\t"
|
||||
if self.description:
|
||||
desc = " [" + self.description + "]"
|
||||
sep = "\n\t"
|
||||
|
||||
at = caller(traceback.extract_stack(), skip)
|
||||
|
||||
sys.stderr.write("FAILED test" + of + desc + sep + at + """
|
||||
in directory: """ + os.getcwd() )
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def no_result(self=None, condition=True, function=None, skip=0):
|
||||
"""Causes a test to exit with no valid result.
|
||||
|
||||
By default, the no_result() method reports NO RESULT for the test and
|
||||
exits with a status of 2. If a condition argument is supplied, the test
|
||||
fails only if the condition is true.
|
||||
|
||||
"""
|
||||
if not condition:
|
||||
return
|
||||
if not function is None:
|
||||
function()
|
||||
of = ""
|
||||
desc = ""
|
||||
sep = " "
|
||||
if not self is None:
|
||||
if self.program:
|
||||
of = " of " + self.program
|
||||
sep = "\n\t"
|
||||
if self.description:
|
||||
desc = " [" + self.description + "]"
|
||||
sep = "\n\t"
|
||||
|
||||
at = caller(traceback.extract_stack(), skip)
|
||||
sys.stderr.write("NO RESULT for test" + of + desc + sep + at)
|
||||
sys.exit(2)
|
||||
|
||||
|
||||
def pass_test(self=None, condition=True, function=None):
|
||||
"""Causes a test to pass.
|
||||
|
||||
By default, the pass_test() method reports PASSED for the test and exits
|
||||
with a status of 0. If a condition argument is supplied, the test passes
|
||||
only if the condition is true.
|
||||
|
||||
"""
|
||||
if not condition:
|
||||
return
|
||||
if not function is None:
|
||||
function()
|
||||
sys.stderr.write("PASSED\n")
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def match_exact(lines=None, matches=None):
|
||||
"""
|
||||
Returns whether the given lists or strings containing lines separated
|
||||
using newline characters contain exactly the same data.
|
||||
|
||||
"""
|
||||
if not type(lines) is ListType:
|
||||
lines = split(lines, "\n")
|
||||
if not type(matches) is ListType:
|
||||
matches = split(matches, "\n")
|
||||
if len(lines) != len(matches):
|
||||
return
|
||||
for i in range(len(lines)):
|
||||
if lines[i] != matches[i]:
|
||||
return
|
||||
return 1
|
||||
|
||||
|
||||
def match_re(lines=None, res=None):
|
||||
"""
|
||||
Given lists or strings contain lines separated using newline characters.
|
||||
This function matches those lines one by one, interpreting the lines in the
|
||||
res parameter as regular expressions.
|
||||
|
||||
"""
|
||||
if not type(lines) is ListType:
|
||||
lines = split(lines, "\n")
|
||||
if not type(res) is ListType:
|
||||
res = split(res, "\n")
|
||||
if len(lines) != len(res):
|
||||
return
|
||||
for i in range(len(lines)):
|
||||
if not re.compile("^" + res[i] + "$").search(lines[i]):
|
||||
return
|
||||
return 1
|
||||
|
||||
|
||||
class TestCmd:
|
||||
def __init__(self, description=None, program=None, workdir=None,
|
||||
subdir=None, verbose=False, match=None, inpath=None):
|
||||
|
||||
self._cwd = os.getcwd()
|
||||
self.description_set(description)
|
||||
self.program_set(program, inpath)
|
||||
self.verbose_set(verbose)
|
||||
if match is None:
|
||||
self.match_func = match_re
|
||||
else:
|
||||
self.match_func = match
|
||||
self._dirlist = []
|
||||
self._preserve = {'pass_test': 0, 'fail_test': 0, 'no_result': 0}
|
||||
env = os.environ.get('PRESERVE')
|
||||
if env:
|
||||
self._preserve['pass_test'] = env
|
||||
self._preserve['fail_test'] = env
|
||||
self._preserve['no_result'] = env
|
||||
else:
|
||||
env = os.environ.get('PRESERVE_PASS')
|
||||
if env is not None:
|
||||
self._preserve['pass_test'] = env
|
||||
env = os.environ.get('PRESERVE_FAIL')
|
||||
if env is not None:
|
||||
self._preserve['fail_test'] = env
|
||||
env = os.environ.get('PRESERVE_PASS')
|
||||
if env is not None:
|
||||
self._preserve['PRESERVE_NO_RESULT'] = env
|
||||
self._stdout = []
|
||||
self._stderr = []
|
||||
self.status = None
|
||||
self.condition = 'no_result'
|
||||
self.workdir_set(workdir)
|
||||
self.subdir(subdir)
|
||||
|
||||
def __del__(self):
|
||||
self.cleanup()
|
||||
|
||||
def __repr__(self):
|
||||
return "%x" % id(self)
|
||||
|
||||
def cleanup(self, condition=None):
|
||||
"""
|
||||
Removes any temporary working directories for the specified TestCmd
|
||||
environment. If the environment variable PRESERVE was set when the
|
||||
TestCmd environment was created, temporary working directories are not
|
||||
removed. If any of the environment variables PRESERVE_PASS,
|
||||
PRESERVE_FAIL or PRESERVE_NO_RESULT were set when the TestCmd
|
||||
environment was created, then temporary working directories are not
|
||||
removed if the test passed, failed or had no result, respectively.
|
||||
Temporary working directories are also preserved for conditions
|
||||
specified via the preserve method.
|
||||
|
||||
Typically, this method is not called directly, but is used when the
|
||||
script exits to clean up temporary working directories as appropriate
|
||||
for the exit status.
|
||||
|
||||
"""
|
||||
if not self._dirlist:
|
||||
return
|
||||
if condition is None:
|
||||
condition = self.condition
|
||||
if self._preserve[condition]:
|
||||
for dir in self._dirlist:
|
||||
print("Preserved directory %s" % dir)
|
||||
else:
|
||||
list = self._dirlist[:]
|
||||
list.reverse()
|
||||
for dir in list:
|
||||
self.writable(dir, 1)
|
||||
shutil.rmtree(dir, ignore_errors=1)
|
||||
|
||||
self._dirlist = []
|
||||
self.workdir = None
|
||||
os.chdir(self._cwd)
|
||||
try:
|
||||
global _Cleanup
|
||||
_Cleanup.remove(self)
|
||||
except (AttributeError, ValueError):
|
||||
pass
|
||||
|
||||
def description_set(self, description):
|
||||
"""Set the description of the functionality being tested."""
|
||||
self.description = description
|
||||
|
||||
def fail_test(self, condition=True, function=None, skip=0):
|
||||
"""Cause the test to fail."""
|
||||
if not condition:
|
||||
return
|
||||
self.condition = 'fail_test'
|
||||
fail_test(self = self,
|
||||
condition = condition,
|
||||
function = function,
|
||||
skip = skip)
|
||||
|
||||
def match(self, lines, matches):
|
||||
"""Compare actual and expected file contents."""
|
||||
return self.match_func(lines, matches)
|
||||
|
||||
def match_exact(self, lines, matches):
|
||||
"""Compare actual and expected file content exactly."""
|
||||
return match_exact(lines, matches)
|
||||
|
||||
def match_re(self, lines, res):
|
||||
"""Compare file content with a regular expression."""
|
||||
return match_re(lines, res)
|
||||
|
||||
def no_result(self, condition=True, function=None, skip=0):
|
||||
"""Report that the test could not be run."""
|
||||
if not condition:
|
||||
return
|
||||
self.condition = 'no_result'
|
||||
no_result(self = self,
|
||||
condition = condition,
|
||||
function = function,
|
||||
skip = skip)
|
||||
|
||||
def pass_test(self, condition=True, function=None):
|
||||
"""Cause the test to pass."""
|
||||
if not condition:
|
||||
return
|
||||
self.condition = 'pass_test'
|
||||
pass_test(self, condition, function)
|
||||
|
||||
def preserve(self, *conditions):
|
||||
"""
|
||||
Arrange for the temporary working directories for the specified
|
||||
TestCmd environment to be preserved for one or more conditions. If no
|
||||
conditions are specified, arranges for the temporary working
|
||||
directories to be preserved for all conditions.
|
||||
|
||||
"""
|
||||
if conditions is ():
|
||||
conditions = ('pass_test', 'fail_test', 'no_result')
|
||||
for cond in conditions:
|
||||
self._preserve[cond] = 1
|
||||
|
||||
def program_set(self, program, inpath):
|
||||
"""Set the executable program or script to be tested."""
|
||||
if not inpath and program and not os.path.isabs(program[0]):
|
||||
program[0] = os.path.join(self._cwd, program[0])
|
||||
self.program = program
|
||||
|
||||
def read(self, file, mode='rb'):
|
||||
"""
|
||||
Reads and returns the contents of the specified file name. The file
|
||||
name may be a list, in which case the elements are concatenated with
|
||||
the os.path.join() method. The file is assumed to be under the
|
||||
temporary working directory unless it is an absolute path name. The I/O
|
||||
mode for the file may be specified and must begin with an 'r'. The
|
||||
default is 'rb' (binary read).
|
||||
|
||||
"""
|
||||
if type(file) is ListType:
|
||||
file = apply(os.path.join, tuple(file))
|
||||
if not os.path.isabs(file):
|
||||
file = os.path.join(self.workdir, file)
|
||||
if mode[0] != 'r':
|
||||
raise ValueError, "mode must begin with 'r'"
|
||||
return open(file, mode).read()
|
||||
|
||||
def run(self, program=None, arguments=None, chdir=None, stdin=None,
|
||||
universal_newlines=True):
|
||||
"""
|
||||
Runs a test of the program or script for the test environment.
|
||||
Standard output and error output are saved for future retrieval via the
|
||||
stdout() and stderr() methods.
|
||||
|
||||
'universal_newlines' parameter controls how the child process
|
||||
input/output streams are opened as defined for the same named Python
|
||||
subprocess.POpen constructor parameter.
|
||||
|
||||
"""
|
||||
if chdir:
|
||||
if not os.path.isabs(chdir):
|
||||
chdir = os.path.join(self.workpath(chdir))
|
||||
if self.verbose:
|
||||
sys.stderr.write("chdir(" + chdir + ")\n")
|
||||
else:
|
||||
chdir = self.workdir
|
||||
|
||||
cmd = []
|
||||
if program and program[0]:
|
||||
if program[0] != self.program[0] and not os.path.isabs(program[0]):
|
||||
program[0] = os.path.join(self._cwd, program[0])
|
||||
cmd += program
|
||||
else:
|
||||
cmd += self.program
|
||||
if arguments:
|
||||
cmd += arguments.split(" ")
|
||||
if self.verbose:
|
||||
sys.stderr.write(join(cmd, " ") + "\n")
|
||||
p = subprocess.Popen(cmd, stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=chdir,
|
||||
universal_newlines=universal_newlines)
|
||||
|
||||
if stdin:
|
||||
if type(stdin) is ListType:
|
||||
for line in stdin:
|
||||
p.tochild.write(line)
|
||||
else:
|
||||
p.tochild.write(stdin)
|
||||
out, err = p.communicate()
|
||||
self._stdout.append(out)
|
||||
self._stderr.append(err)
|
||||
self.status = p.returncode
|
||||
|
||||
if self.verbose:
|
||||
sys.stdout.write(self._stdout[-1])
|
||||
sys.stderr.write(self._stderr[-1])
|
||||
|
||||
def stderr(self, run=None):
|
||||
"""
|
||||
Returns the error output from the specified run number. If there is
|
||||
no specified run number, then returns the error output of the last run.
|
||||
If the run number is less than zero, then returns the error output from
|
||||
that many runs back from the current run.
|
||||
|
||||
"""
|
||||
if not run:
|
||||
run = len(self._stderr)
|
||||
elif run < 0:
|
||||
run = len(self._stderr) + run
|
||||
run -= 1
|
||||
if run < 0:
|
||||
return ''
|
||||
return self._stderr[run]
|
||||
|
||||
def stdout(self, run=None):
|
||||
"""
|
||||
Returns the standard output from the specified run number. If there
|
||||
is no specified run number, then returns the standard output of the
|
||||
last run. If the run number is less than zero, then returns the
|
||||
standard output from that many runs back from the current run.
|
||||
|
||||
"""
|
||||
if not run:
|
||||
run = len(self._stdout)
|
||||
elif run < 0:
|
||||
run = len(self._stdout) + run
|
||||
run -= 1
|
||||
if run < 0:
|
||||
return ''
|
||||
return self._stdout[run]
|
||||
|
||||
def subdir(self, *subdirs):
|
||||
"""
|
||||
Create new subdirectories under the temporary working directory, one
|
||||
for each argument. An argument may be a list, in which case the list
|
||||
elements are concatenated using the os.path.join() method.
|
||||
Subdirectories multiple levels deep must be created using a separate
|
||||
argument for each level:
|
||||
|
||||
test.subdir('sub', ['sub', 'dir'], ['sub', 'dir', 'ectory'])
|
||||
|
||||
Returns the number of subdirectories actually created.
|
||||
|
||||
"""
|
||||
count = 0
|
||||
for sub in subdirs:
|
||||
if sub is None:
|
||||
continue
|
||||
if type(sub) is ListType:
|
||||
sub = apply(os.path.join, tuple(sub))
|
||||
new = os.path.join(self.workdir, sub)
|
||||
try:
|
||||
os.mkdir(new)
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
count += 1
|
||||
return count
|
||||
|
||||
def unlink(self, file):
|
||||
"""
|
||||
Unlinks the specified file name. The file name may be a list, in
|
||||
which case the elements are concatenated using the os.path.join()
|
||||
method. The file is assumed to be under the temporary working directory
|
||||
unless it is an absolute path name.
|
||||
|
||||
"""
|
||||
if type(file) is ListType:
|
||||
file = apply(os.path.join, tuple(file))
|
||||
if not os.path.isabs(file):
|
||||
file = os.path.join(self.workdir, file)
|
||||
os.unlink(file)
|
||||
|
||||
def verbose_set(self, verbose):
|
||||
"""Set the verbose level."""
|
||||
self.verbose = verbose
|
||||
|
||||
def workdir_set(self, path):
|
||||
"""
|
||||
Creates a temporary working directory with the specified path name.
|
||||
If the path is a null string (''), a unique directory name is created.
|
||||
|
||||
"""
|
||||
if os.path.isabs(path):
|
||||
self.workdir = path
|
||||
else:
|
||||
if path != None:
|
||||
if path == '':
|
||||
path = tempfile.mktemp()
|
||||
if path != None:
|
||||
os.mkdir(path)
|
||||
self._dirlist.append(path)
|
||||
global _Cleanup
|
||||
try:
|
||||
_Cleanup.index(self)
|
||||
except ValueError:
|
||||
_Cleanup.append(self)
|
||||
# We would like to set self.workdir like this:
|
||||
# self.workdir = path
|
||||
# But symlinks in the path will report things differently from
|
||||
# os.getcwd(), so chdir there and back to fetch the canonical
|
||||
# path.
|
||||
cwd = os.getcwd()
|
||||
os.chdir(path)
|
||||
self.workdir = os.getcwd()
|
||||
os.chdir(cwd)
|
||||
else:
|
||||
self.workdir = None
|
||||
|
||||
def workpath(self, *args):
|
||||
"""
|
||||
Returns the absolute path name to a subdirectory or file within the
|
||||
current temporary working directory. Concatenates the temporary working
|
||||
directory name with the specified arguments using os.path.join().
|
||||
|
||||
"""
|
||||
return apply(os.path.join, (self.workdir,) + tuple(args))
|
||||
|
||||
def writable(self, top, write):
|
||||
"""
|
||||
Make the specified directory tree writable (write == 1) or not
|
||||
(write == None).
|
||||
|
||||
"""
|
||||
def _walk_chmod(arg, dirname, names):
|
||||
st = os.stat(dirname)
|
||||
os.chmod(dirname, arg(st[stat.ST_MODE]))
|
||||
for name in names:
|
||||
fullname = os.path.join(dirname, name)
|
||||
st = os.stat(fullname)
|
||||
os.chmod(fullname, arg(st[stat.ST_MODE]))
|
||||
|
||||
_mode_writable = lambda mode: stat.S_IMODE(mode|0200)
|
||||
_mode_non_writable = lambda mode: stat.S_IMODE(mode&~0200)
|
||||
|
||||
if write:
|
||||
f = _mode_writable
|
||||
else:
|
||||
f = _mode_non_writable
|
||||
try:
|
||||
os.path.walk(top, _walk_chmod, f)
|
||||
except:
|
||||
pass # Ignore any problems changing modes.
|
||||
|
||||
def write(self, file, content, mode='wb'):
|
||||
"""
|
||||
Writes the specified content text (second argument) to the specified
|
||||
file name (first argument). The file name may be a list, in which case
|
||||
the elements are concatenated using the os.path.join() method. The file
|
||||
is created under the temporary working directory. Any subdirectories in
|
||||
the path must already exist. The I/O mode for the file may be specified
|
||||
and must begin with a 'w'. The default is 'wb' (binary write).
|
||||
|
||||
"""
|
||||
if type(file) is ListType:
|
||||
file = apply(os.path.join, tuple(file))
|
||||
if not os.path.isabs(file):
|
||||
file = os.path.join(self.workdir, file)
|
||||
if mode[0] != 'w':
|
||||
raise ValueError, "mode must begin with 'w'"
|
||||
open(file, mode).write(content)
|
||||
@@ -0,0 +1,26 @@
|
||||
# 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 BoostBuild
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
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()
|
||||
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# 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)
|
||||
|
||||
# Test that sources with absolute names are handled OK.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.write("jamroot.jam", "path-constant TOP : . ;")
|
||||
t.write("jamfile.jam", """\
|
||||
local pwd = [ PWD ] ;
|
||||
ECHO $(pwd) XXXXX ;
|
||||
exe hello : $(pwd)/hello.cpp $(TOP)/empty.cpp ;
|
||||
""")
|
||||
t.write("hello.cpp", "int main() {}\n")
|
||||
t.write("empty.cpp", "\n")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition("bin/$toolset/debug/hello.exe")
|
||||
t.rm(".")
|
||||
|
||||
# Test a contrived case in which an absolute name is used in a standalone
|
||||
# project (not Jamfile). Moreover, the target with an absolute name is returned
|
||||
# via an 'alias' and used from another project.
|
||||
t.write("a.cpp", "int main() {}\n")
|
||||
t.write("jamfile.jam", "exe a : /standalone//a ;")
|
||||
t.write("jamroot.jam", "import standalone ;")
|
||||
t.write("standalone.jam", """\
|
||||
import project ;
|
||||
project.initialize $(__name__) ;
|
||||
project standalone ;
|
||||
local pwd = [ PWD ] ;
|
||||
alias a : $(pwd)/a.cpp ;
|
||||
""")
|
||||
|
||||
t.write("standalone.py", """
|
||||
from b2.manager import get_manager
|
||||
|
||||
# FIXME: this is ugly as death
|
||||
get_manager().projects().initialize(__name__)
|
||||
|
||||
import os ;
|
||||
|
||||
# This use of list as parameter is also ugly.
|
||||
project(['standalone'])
|
||||
|
||||
pwd = os.getcwd()
|
||||
alias('a', [os.path.join(pwd, 'a.cpp')])
|
||||
""")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition("bin/$toolset/debug/a.exe")
|
||||
|
||||
# Test absolute path in target ids.
|
||||
t.rm(".")
|
||||
|
||||
t.write("d1/jamroot.jam", "")
|
||||
t.write("d1/jamfile.jam", "exe a : a.cpp ;")
|
||||
t.write("d1/a.cpp", "int main() {}\n")
|
||||
t.write("d2/jamroot.jam", "")
|
||||
t.write("d2/jamfile.jam", """\
|
||||
local pwd = [ PWD ] ;
|
||||
alias x : $(pwd)/../d1//a ;
|
||||
""")
|
||||
|
||||
t.run_build_system(subdir="d2")
|
||||
t.expect_addition("d1/bin/$toolset/debug/a.exe")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,109 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2003 Dave Abrahams
|
||||
# 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
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# test_alias_rule()
|
||||
# -----------------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
def test_alias_rule(t):
|
||||
"""Basic alias rule test."""
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
exe a : a.cpp ;
|
||||
exe b : b.cpp ;
|
||||
exe c : c.cpp ;
|
||||
|
||||
alias bin1 : a ;
|
||||
alias bin2 : a b ;
|
||||
|
||||
alias src : s.cpp ;
|
||||
exe hello : hello.cpp src ;
|
||||
""")
|
||||
|
||||
t.write("a.cpp", "int main() {}\n")
|
||||
t.copy("a.cpp", "b.cpp")
|
||||
t.copy("a.cpp", "c.cpp")
|
||||
t.copy("a.cpp", "hello.cpp")
|
||||
t.write("s.cpp", "")
|
||||
|
||||
# Check that targets to which "bin1" refers are updated, and only those.
|
||||
t.run_build_system(["bin1"])
|
||||
t.expect_addition(BoostBuild.List("bin/$toolset/debug/") * "a.exe a.obj")
|
||||
t.expect_nothing_more()
|
||||
|
||||
# Try again with "bin2"
|
||||
t.run_build_system(["bin2"])
|
||||
t.expect_addition(BoostBuild.List("bin/$toolset/debug/") * "b.exe b.obj")
|
||||
t.expect_nothing_more()
|
||||
|
||||
# Try building everything, making sure 'hello' target is created.
|
||||
t.run_build_system()
|
||||
t.expect_addition(BoostBuild.List("bin/$toolset/debug/") * \
|
||||
"hello.exe hello.obj")
|
||||
t.expect_addition("bin/$toolset/debug/s.obj")
|
||||
t.expect_addition(BoostBuild.List("bin/$toolset/debug/") * "c.exe c.obj")
|
||||
t.expect_nothing_more()
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# test_alias_source_usage_requirements()
|
||||
# --------------------------------------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
def test_alias_source_usage_requirements(t):
|
||||
"""
|
||||
Check whether usage requirements are propagated via "alias". In case they
|
||||
are not, linking will fail as there will be no main() function defined
|
||||
anywhere in the source.
|
||||
|
||||
"""
|
||||
t.write("jamroot.jam", """\
|
||||
lib l : l.cpp : : : <define>WANT_MAIN ;
|
||||
alias la : l ;
|
||||
exe main : main.cpp la ;
|
||||
""")
|
||||
|
||||
t.write("l.cpp", """\
|
||||
void
|
||||
#if defined(_WIN32)
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
foo() {}
|
||||
""")
|
||||
|
||||
t.write("main.cpp", """\
|
||||
#ifdef WANT_MAIN
|
||||
int main() {}
|
||||
#endif
|
||||
""")
|
||||
|
||||
t.run_build_system()
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# main()
|
||||
# ------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
# We do not pass the '-d0' option to Boost Build here to get more detailed
|
||||
# information in case of failure.
|
||||
t = BoostBuild.Tester(pass_d0=False, use_test_config=False)
|
||||
|
||||
test_alias_rule(t)
|
||||
test_alias_source_usage_requirements(t)
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,113 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2003 Dave Abrahams
|
||||
# Copyright 2003, 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 main target alternatives.
|
||||
|
||||
import BoostBuild
|
||||
import string
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
# Test that basic alternatives selection works.
|
||||
t.write("jamroot.jam", "")
|
||||
|
||||
t.write("jamfile.jam", """
|
||||
exe a : a_empty.cpp ;
|
||||
exe a : a.cpp : <variant>release ;
|
||||
""")
|
||||
|
||||
t.write("a_empty.cpp", "")
|
||||
|
||||
t.write("a.cpp", "int main() {}\n")
|
||||
|
||||
t.run_build_system(["release"])
|
||||
|
||||
t.expect_addition("bin/$toolset/release/a.exe")
|
||||
|
||||
# Test that alternative selection works for ordinary properties, in particular
|
||||
# user-defined.
|
||||
t.write("jamroot.jam", "")
|
||||
|
||||
t.write("jamfile.jam", """
|
||||
import feature ;
|
||||
feature.feature X : off on : propagated ;
|
||||
exe a : b.cpp ;
|
||||
exe a : a.cpp : <X>on ;
|
||||
""")
|
||||
t.write("b.cpp", "int main() {}\n")
|
||||
|
||||
t.rm("bin")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition("bin/$toolset/debug/b.obj")
|
||||
|
||||
t.run_build_system(["X=on"])
|
||||
t.expect_addition("bin/$toolset/debug/X-on/a.obj")
|
||||
|
||||
t.rm("bin")
|
||||
|
||||
# Test that everything works ok even with the default build.
|
||||
t.write("jamfile.jam", """\
|
||||
exe a : a_empty.cpp : <variant>release ;
|
||||
exe a : a.cpp : <variant>debug ;
|
||||
""")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition("bin/$toolset/debug/a.exe")
|
||||
|
||||
# Test that only properties which are in the build request matter for
|
||||
# alternative selection. IOW, alternative with <variant>release is better than
|
||||
# one with <variant>debug when building the release variant.
|
||||
t.write("jamfile.jam", """\
|
||||
exe a : a_empty.cpp : <variant>debug ;
|
||||
exe a : a.cpp : <variant>release ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["release"])
|
||||
t.expect_addition("bin/$toolset/release/a.exe")
|
||||
|
||||
# Test that free properties do not matter. We really do not want <cxxflags>
|
||||
# property in build request to affect alternative selection.
|
||||
t.write("jamfile.jam", """
|
||||
exe a : a_empty.cpp : <variant>debug <define>FOO <include>BAR ;
|
||||
exe a : a.cpp : <variant>release ;
|
||||
""")
|
||||
|
||||
t.rm("bin/$toolset/release/a.exe")
|
||||
t.run_build_system(["release", "define=FOO"])
|
||||
t.expect_addition("bin/$toolset/release/a.exe")
|
||||
|
||||
# Test that ambiguity is reported correctly.
|
||||
t.write("jamfile.jam", """\
|
||||
exe a : a_empty.cpp ;
|
||||
exe a : a.cpp ;
|
||||
""")
|
||||
t.run_build_system(["--no-error-backtrace"], status=None)
|
||||
t.fail_test(string.find(t.stdout(), "No best alternative") == -1)
|
||||
|
||||
# Another ambiguity test: two matches properties in one alternative are neither
|
||||
# better nor worse than a single one in another alternative.
|
||||
t.write("jamfile.jam", """\
|
||||
exe a : a_empty.cpp : <optimization>off <profiling>off ;
|
||||
exe a : a.cpp : <debug-symbols>on ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["--no-error-backtrace"], status=None)
|
||||
t.fail_test(string.find(t.stdout(), "No best alternative") == -1)
|
||||
|
||||
# Test that we can have alternative without sources.
|
||||
t.write("jamfile.jam", """\
|
||||
alias specific-sources ;
|
||||
import feature ;
|
||||
feature.extend os : MAGIC ;
|
||||
alias specific-sources : b.cpp : <os>MAGIC ;
|
||||
exe a : a.cpp specific-sources ;
|
||||
""")
|
||||
t.rm("bin")
|
||||
t.run_build_system()
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,22 @@
|
||||
#!/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)
|
||||
|
||||
# Regression test: when directory of project root contained regex
|
||||
# metacharacters, Boost.Build failed to work. Bug reported by Michael Stevens.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester()
|
||||
|
||||
t.write("bad[abc]dirname/jamfile.jam", """
|
||||
""")
|
||||
|
||||
t.write("bad[abc]dirname/jamroot.jam", """
|
||||
""")
|
||||
|
||||
t.run_build_system(subdir="bad[abc]dirname")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,14 @@
|
||||
# Copyright 2002, 2003 Dave Abrahams
|
||||
# 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)
|
||||
|
||||
# Assume BOOST_BUILD_PATH point to the 'test' directory.
|
||||
# We need to leave 'test' there, so that 'test-config.jam'
|
||||
# can be found, but also add parent directory, to find
|
||||
# all the other modules.
|
||||
|
||||
BOOST_BUILD_PATH = $(BOOST_BUILD_PATH)/.. $(BOOST_BUILD_PATH) ;
|
||||
|
||||
# Find the boost build system in the ../kernel directory.
|
||||
boost-build ../src/kernel ;
|
||||
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2004, 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)
|
||||
|
||||
import BoostBuild
|
||||
import string
|
||||
|
||||
t = BoostBuild.Tester()
|
||||
|
||||
t.set_tree("boostbook")
|
||||
|
||||
# For some reason, the messages are sent to stderr.
|
||||
t.run_build_system()
|
||||
t.fail_test(string.find(t.stdout(), """Writing boost/A.html for refentry(boost.A)
|
||||
Writing library/reference.html for section(library.reference)
|
||||
Writing index.html for chapter(library)
|
||||
Writing docs_HTML.manifest
|
||||
""") == -1)
|
||||
t.expect_addition(["html/boost/A.html", "html/index.html"])
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,16 @@
|
||||
/* Copyright 2004, 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) */
|
||||
|
||||
|
||||
// Seems like Boostbook does like classes outside of namespaces,
|
||||
// and won't generate anything for them.
|
||||
namespace boost {
|
||||
|
||||
/// A class
|
||||
class A {
|
||||
public:
|
||||
/// A constructor
|
||||
A();
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
|
||||
|
||||
<!-- Copyright 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) -->
|
||||
|
||||
<library
|
||||
name="library"
|
||||
dirname="librarys" id="library"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<libraryinfo>
|
||||
<author>
|
||||
<firstname>Joe</firstname>
|
||||
<surname>Hacker</surname>
|
||||
</author>
|
||||
|
||||
<copyright>
|
||||
<year>7002</year>
|
||||
<holder>Joe Hacker</holder>
|
||||
</copyright>
|
||||
|
||||
</libraryinfo>
|
||||
|
||||
<title>Documentation</title>
|
||||
|
||||
<section>
|
||||
<title>Introduction</title>
|
||||
|
||||
<para>This is introduction</para>
|
||||
|
||||
</section>
|
||||
|
||||
<xi:include href="autodoc.xml"/>
|
||||
</library>
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
boostbook docs : docs.xml autodoc ;
|
||||
doxygen autodoc : [ glob *.hpp ] ;
|
||||
@@ -0,0 +1,107 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 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)
|
||||
|
||||
# Test that we can change build directory using the 'build-dir' project
|
||||
# attribute.
|
||||
|
||||
import BoostBuild
|
||||
import string
|
||||
import os
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
|
||||
# Test that top-level project can affect build dir.
|
||||
t.write("jamroot.jam", "import gcc ;")
|
||||
t.write("jamfile.jam", """\
|
||||
project : build-dir build ;
|
||||
exe a : a.cpp ;
|
||||
build-project src ;
|
||||
""")
|
||||
|
||||
t.write("a.cpp", "int main() {}\n")
|
||||
|
||||
t.write("src/jamfile.jam", "exe b : b.cpp ; ")
|
||||
|
||||
t.write("src/b.cpp", "int main() {}\n")
|
||||
|
||||
t.run_build_system()
|
||||
|
||||
t.expect_addition(["build/$toolset/debug/a.exe",
|
||||
"build/src/$toolset/debug/b.exe"])
|
||||
|
||||
# Test that building from child projects work.
|
||||
t.run_build_system(subdir='src')
|
||||
t.ignore("build/config.log")
|
||||
t.ignore("build/project-cache.jam")
|
||||
t.expect_nothing_more()
|
||||
|
||||
# Test that project can override build dir.
|
||||
t.write("jamfile.jam", """\
|
||||
exe a : a.cpp ;
|
||||
build-project src ;
|
||||
""")
|
||||
|
||||
t.write("src/jamfile.jam", """\
|
||||
project : build-dir build ;
|
||||
exe b : b.cpp ;
|
||||
""")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition(["bin/$toolset/debug/a.exe",
|
||||
"src/build/$toolset/debug/b.exe"])
|
||||
|
||||
# Now test the '--build-dir' option.
|
||||
t.rm(".")
|
||||
t.write("jamroot.jam", "")
|
||||
|
||||
# Test that we get an error when no project id is specified.
|
||||
t.run_build_system(["--build-dir=foo"])
|
||||
t.fail_test(string.find(t.stdout(),
|
||||
"warning: the --build-dir option will be ignored") == -1)
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
project foo ;
|
||||
exe a : a.cpp ;
|
||||
build-project sub ;
|
||||
""")
|
||||
t.write("a.cpp", "int main() {}\n")
|
||||
t.write("sub/jamfile.jam", "exe b : b.cpp ;\n")
|
||||
t.write("sub/b.cpp", "int main() {}\n")
|
||||
|
||||
t.run_build_system(["--build-dir=build"])
|
||||
t.expect_addition(["build/foo/$toolset/debug/a.exe",
|
||||
"build/foo/sub/$toolset/debug/b.exe"])
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
project foo : build-dir bin.v2 ;
|
||||
exe a : a.cpp ;
|
||||
build-project sub ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["--build-dir=build"])
|
||||
t.expect_addition(["build/foo/bin.v2/$toolset/debug/a.exe",
|
||||
"build/foo/bin.v2/sub/$toolset/debug/b.exe"])
|
||||
|
||||
# Try building in subdir. We expect that the entire build tree with be in
|
||||
# 'sub/build'. Today, I am not sure if this is what the user expects, but let
|
||||
# it be.
|
||||
t.rm('build')
|
||||
t.run_build_system(["--build-dir=build"], subdir="sub")
|
||||
t.expect_addition(["sub/build/foo/bin.v2/sub/$toolset/debug/b.exe"])
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
project foo : build-dir %s ;
|
||||
exe a : a.cpp ;
|
||||
build-project sub ;
|
||||
""" % string.replace(os.getcwd(), '\\', '\\\\'))
|
||||
|
||||
t.run_build_system(["--build-dir=build"], status=1)
|
||||
t.fail_test(string.find(t.stdout(),
|
||||
"Absolute directory specified via 'build-dir' project attribute") == -1)
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,170 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright (C) 2006. Vladimir Prus
|
||||
# Copyright (C) 2008. 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)
|
||||
|
||||
# Tests that we explicitly request a file (not target) to be built by
|
||||
# specifying its name on the command line.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# test_building_file_from_specific_project()
|
||||
# ------------------------------------------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
def test_building_file_from_specific_project():
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
exe hello : hello.cpp ;
|
||||
exe hello2 : hello.cpp ;
|
||||
build-project sub ;
|
||||
""")
|
||||
t.write("hello.cpp", "int main() {}\n")
|
||||
t.write("sub/jamfile.jam", """
|
||||
exe hello : hello.cpp ;
|
||||
exe hello2 : hello.cpp ;
|
||||
exe sub : hello.cpp ;
|
||||
""")
|
||||
t.write("sub/hello.cpp", "int main() {}\n")
|
||||
|
||||
t.run_build_system(["sub", t.adjust_suffix("hello.obj")])
|
||||
t.expect_output_lines("*depends on itself*", False)
|
||||
t.expect_addition("sub/bin/$toolset/debug/hello.obj")
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# test_building_file_from_specific_target()
|
||||
# -----------------------------------------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
def test_building_file_from_specific_target():
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
exe hello1 : hello1.cpp ;
|
||||
exe hello2 : hello2.cpp ;
|
||||
exe hello3 : hello3.cpp ;
|
||||
""")
|
||||
t.write("hello1.cpp", "int main() {}\n")
|
||||
t.write("hello2.cpp", "int main() {}\n")
|
||||
t.write("hello3.cpp", "int main() {}\n")
|
||||
|
||||
t.run_build_system(["hello1", t.adjust_suffix("hello1.obj")])
|
||||
t.expect_addition("bin/$toolset/debug/hello1.obj")
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# test_building_missing_file_from_specific_target()
|
||||
# -------------------------------------------------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
def test_building_missing_file_from_specific_target():
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
exe hello1 : hello1.cpp ;
|
||||
exe hello2 : hello2.cpp ;
|
||||
exe hello3 : hello3.cpp ;
|
||||
""")
|
||||
t.write("hello1.cpp", "int main() {}\n")
|
||||
t.write("hello2.cpp", "int main() {}\n")
|
||||
t.write("hello3.cpp", "int main() {}\n")
|
||||
|
||||
obj = t.adjust_suffix("hello2.obj")
|
||||
t.run_build_system(["hello1", obj], status=1)
|
||||
t.expect_output_lines("don't know how to make*" + obj)
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# test_building_multiple_files_with_different_names()
|
||||
# ---------------------------------------------------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
def test_building_multiple_files_with_different_names():
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
exe hello1 : hello1.cpp ;
|
||||
exe hello2 : hello2.cpp ;
|
||||
exe hello3 : hello3.cpp ;
|
||||
""")
|
||||
t.write("hello1.cpp", "int main() {}\n")
|
||||
t.write("hello2.cpp", "int main() {}\n")
|
||||
t.write("hello3.cpp", "int main() {}\n")
|
||||
|
||||
t.run_build_system([t.adjust_suffix("hello1.obj"), t.adjust_suffix(
|
||||
"hello2.obj")])
|
||||
t.expect_addition("bin/$toolset/debug/hello1.obj")
|
||||
t.expect_addition("bin/$toolset/debug/hello2.obj")
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# test_building_multiple_files_with_the_same_name()
|
||||
# -------------------------------------------------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
def test_building_multiple_files_with_the_same_name():
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
exe hello : hello.cpp ;
|
||||
exe hello2 : hello.cpp ;
|
||||
build-project sub ;
|
||||
""")
|
||||
t.write("hello.cpp", "int main() {}\n")
|
||||
t.write("sub/jamfile.jam", """
|
||||
exe hello : hello.cpp ;
|
||||
exe hello2 : hello.cpp ;
|
||||
exe sub : hello.cpp ;
|
||||
""")
|
||||
t.write("sub/hello.cpp", "int main() {}\n")
|
||||
|
||||
t.run_build_system([t.adjust_suffix("hello.obj")])
|
||||
t.expect_output_lines("*depends on itself*", False)
|
||||
t.expect_addition("bin/$toolset/debug/hello.obj")
|
||||
t.expect_addition("sub/bin/$toolset/debug/hello.obj")
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# main()
|
||||
# ------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
test_building_file_from_specific_project()
|
||||
test_building_file_from_specific_target()
|
||||
test_building_missing_file_from_specific_target()
|
||||
test_building_multiple_files_with_different_names()
|
||||
test_building_multiple_files_with_the_same_name()
|
||||
@@ -0,0 +1,23 @@
|
||||
#!/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)
|
||||
|
||||
# Tests that <build>no property prevents a target from being built.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.write("jamroot.jam", "exe hello : hello.cpp : <variant>debug:<build>no ;")
|
||||
t.write("hello.cpp", "int main() {}\n")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.run_build_system(["release"])
|
||||
t.expect_addition("bin/$toolset/release/hello.exe")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2012 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)
|
||||
|
||||
# This tests the ECHO rule.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
def test_echo(name):
|
||||
t = BoostBuild.Tester(["-ffile.jam"], pass_toolset=0)
|
||||
|
||||
t.write("file.jam", """\
|
||||
%s ;
|
||||
UPDATE ;
|
||||
""" % name)
|
||||
t.run_build_system(stdout="\n")
|
||||
|
||||
t.write("file.jam", """\
|
||||
%s a message ;
|
||||
UPDATE ;
|
||||
""" % name)
|
||||
t.run_build_system(stdout="a message\n")
|
||||
|
||||
t.cleanup()
|
||||
|
||||
test_echo("ECHO")
|
||||
test_echo("Echo")
|
||||
test_echo("echo")
|
||||
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2012 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)
|
||||
|
||||
# This tests the EXIT rule.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
def test_exit(name):
|
||||
t = BoostBuild.Tester(["-ffile.jam"], pass_toolset=0)
|
||||
|
||||
t.write("file.jam", "%s ;" % name)
|
||||
t.run_build_system(status=1, stdout="\n")
|
||||
t.rm(".")
|
||||
|
||||
t.write("file.jam", "%s : 0 ;" % name)
|
||||
t.run_build_system(stdout="\n")
|
||||
t.rm(".")
|
||||
|
||||
t.write("file.jam", "%s : 1 ;" % name)
|
||||
t.run_build_system(status=1, stdout="\n")
|
||||
t.rm(".")
|
||||
|
||||
t.write("file.jam", "%s : 2 ;" % name)
|
||||
t.run_build_system(status=2, stdout="\n")
|
||||
t.rm(".")
|
||||
|
||||
t.write("file.jam", "%s a message ;" % name)
|
||||
t.run_build_system(status=1, stdout="a message\n")
|
||||
t.rm(".")
|
||||
|
||||
t.write("file.jam", "%s a message : 0 ;" % name)
|
||||
t.run_build_system(stdout="a message\n")
|
||||
t.rm(".")
|
||||
|
||||
t.cleanup()
|
||||
|
||||
test_exit("EXIT")
|
||||
test_exit("Exit")
|
||||
test_exit("exit")
|
||||
@@ -0,0 +1,87 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2014 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)
|
||||
|
||||
# This tests the GLOB rule.
|
||||
|
||||
import os
|
||||
import BoostBuild
|
||||
|
||||
def test_glob(files, glob, expected, setup=""):
|
||||
t = BoostBuild.Tester(["-ffile.jam"], pass_toolset=0)
|
||||
t.write("file.jam", setup + """
|
||||
for local p in [ SORT %s ]
|
||||
{
|
||||
ECHO $(p) ;
|
||||
}
|
||||
UPDATE ;
|
||||
""" % glob)
|
||||
for f in files:
|
||||
t.write(f, "")
|
||||
# convert / into \ on windows
|
||||
expected = [os.path.join(*p.split("/")) for p in expected]
|
||||
expected.sort()
|
||||
t.run_build_system(stdout="\n".join(expected + [""]))
|
||||
t.cleanup()
|
||||
|
||||
# one or both arguments empty
|
||||
test_glob([], "[ GLOB : ]", [])
|
||||
test_glob([], "[ GLOB . : ]", [])
|
||||
test_glob([], "[ GLOB : * ]", [])
|
||||
|
||||
# a single result
|
||||
test_glob([], "[ GLOB . : * ]", ["./file.jam"])
|
||||
|
||||
# * can match any number of characters
|
||||
test_glob([], "[ GLOB . : file*.jam ]", ["./file.jam"])
|
||||
test_glob([], "[ GLOB . : f*am ]", ["./file.jam"])
|
||||
# ? should match a single character, but not more than one
|
||||
test_glob([], "[ GLOB . : fi?e.?am ]", ["./file.jam"])
|
||||
test_glob([], "[ GLOB . : fi?.jam ]", [])
|
||||
# [abc-fh-j] matches a set of characters
|
||||
test_glob([], "[ GLOB . : [f][i][l][e].jam ]", ["./file.jam"])
|
||||
test_glob([], "[ GLOB . : [fghau][^usdrwe][k-o][^f-s].jam ]", ["./file.jam"])
|
||||
# \x matches x
|
||||
test_glob([], "[ GLOB . : \\f\\i\\l\\e.jam ]", ["./file.jam"])
|
||||
|
||||
# multiple results
|
||||
test_glob(["test.txt"], "[ GLOB . : * ]", ["./file.jam", "./test.txt"])
|
||||
|
||||
# directories
|
||||
test_glob(["dir1/dir2/test.txt"], "[ GLOB dir1 : * ]", ["dir1/dir2"]);
|
||||
|
||||
# non-existent directory
|
||||
test_glob([], "[ GLOB dir1 : * ] ", [])
|
||||
|
||||
# multiple directories and patterns
|
||||
test_glob(["dir1/file1.txt", "dir2/file1.txt",
|
||||
"dir2/file2.txt"],
|
||||
"[ GLOB dir1 dir2 : file1* file2* ]",
|
||||
["dir1/file1.txt", "dir2/file1.txt",
|
||||
"dir2/file2.txt"])
|
||||
|
||||
# The directory can contain . and ..
|
||||
test_glob(["dir/test.txt"], "[ GLOB dir/. : test.txt ]", ["dir/./test.txt"])
|
||||
test_glob(["dir/test.txt"], "[ GLOB dir/.. : file.jam ]", ["dir/../file.jam"])
|
||||
|
||||
# On case insensitive filesystems, the result should
|
||||
# be normalized. It should NOT be downcased.
|
||||
test_glob(["TEST.TXT"], "[ GLOB . : TEST.TXT ]", ["./TEST.TXT"])
|
||||
|
||||
case_insensitive = (os.path.normcase("FILE") == "file")
|
||||
|
||||
if case_insensitive:
|
||||
test_glob(["TEST.TXT"], "[ GLOB . : test.txt ]", ["./TEST.TXT"])
|
||||
# This used to fail because the caching routines incorrectly
|
||||
# reported that . and .. do not exist.
|
||||
test_glob(["D1/D2/TEST.TXT"], "[ GLOB D1/./D2 : test.txt ]",
|
||||
["D1/./D2/TEST.TXT"])
|
||||
test_glob(["D1/TEST.TXT", "TEST.TXT"], "[ GLOB D1/../D1 : test.txt ]",
|
||||
["D1/../D1/TEST.TXT"])
|
||||
# This also failed because directories that were first found
|
||||
# by GLOB were recorded as non-existent.
|
||||
test_glob(["D1/D2/TEST.TXT"], "[ GLOB d1/d2 : test.txt ]",
|
||||
["D1/D2/TEST.TXT"],
|
||||
"GLOB . : * ;")
|
||||
@@ -0,0 +1,214 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2014 Steven Watanabe
|
||||
# Copyright 2015 Artur Shepilko
|
||||
# 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 GLOB_ARCHIVE rule.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import StringIO
|
||||
import BoostBuild
|
||||
|
||||
vms = ( os.name == 'posix' and sys.platform == 'OpenVMS')
|
||||
|
||||
t = BoostBuild.Tester()
|
||||
|
||||
## Setup test archive sources and symbols they contain.
|
||||
sources = {
|
||||
"a.cpp" : ["a"],
|
||||
"b.cpp" : ["b"],
|
||||
"b_match.cpp" : ["b_match"],
|
||||
"c/nopath_check.cpp" : ["nopath_check"],
|
||||
"CaseCheck.cpp" : ["CaseCheck"],
|
||||
"seq_check1.cpp" : ["seq_check1"],
|
||||
"seq_check2.cpp" : ["seq_check2"],
|
||||
"seq_check3.cpp" : ["seq_check3"],
|
||||
"symbols_check.c" : ["symbol", "symbol_match"],
|
||||
"members_and_symbols_check.c" : ["member_and_symbol_match"],
|
||||
"symbol_case_check.c" : ["SymbolCaseCheck"],
|
||||
"main_check.cpp" : ["main"]
|
||||
}
|
||||
|
||||
|
||||
def create_sources(path, sources):
|
||||
for s in sources :
|
||||
f = os.path.join(path, s)
|
||||
t.write(f, "")
|
||||
output = StringIO.StringIO()
|
||||
for sym in sources[s] :
|
||||
output.write("int %s() { return 0; }\n" % sym)
|
||||
t.write(f, output.getvalue())
|
||||
|
||||
|
||||
def setup_archive(name, sources):
|
||||
global archive
|
||||
global obj_suffix
|
||||
archive = t.adjust_names(name)[0]
|
||||
obj_suffix = t.adjust_names(".obj")[0]
|
||||
output = StringIO.StringIO()
|
||||
t.write("jamroot.jam","")
|
||||
output.write("""\
|
||||
static-lib %s :
|
||||
""" % name.split(".")[0])
|
||||
## sort the sources, so we can test order of the globbed members
|
||||
for s in sorted(sources) :
|
||||
output.write("""\
|
||||
%s
|
||||
""" % s)
|
||||
output.write("""\
|
||||
;
|
||||
""")
|
||||
t.write("lib/jamfile.jam", output.getvalue())
|
||||
create_sources("lib", sources)
|
||||
t.run_build_system(subdir="lib")
|
||||
built_archive = "lib/bin/$toolset/debug/%s" % name
|
||||
t.expect_addition(built_archive)
|
||||
t.copy(built_archive, name)
|
||||
t.rm("lib")
|
||||
|
||||
|
||||
def test_glob_archive(archives, glob, expected, sort_results = False):
|
||||
output = StringIO.StringIO()
|
||||
## replace placeholders
|
||||
glob = glob.replace("$archive1", archives[0]).replace("$obj", obj_suffix)
|
||||
expected = [ m.replace("$archive1",
|
||||
archives[0]).replace("$obj", obj_suffix) for m in expected ]
|
||||
if len(archives) > 1 :
|
||||
glob = glob.replace("$archive2", archives[1]).replace("$obj", obj_suffix)
|
||||
expected = [ m.replace("$archive2",
|
||||
archives[1]).replace("$obj", obj_suffix) for m in expected ]
|
||||
## create test jamfile
|
||||
if sort_results : glob = "[ SORT %s ]" % glob
|
||||
output.write("""\
|
||||
for local p in %s
|
||||
{
|
||||
ECHO $(p) ;
|
||||
}
|
||||
UPDATE ;
|
||||
""" % glob)
|
||||
t.write("file.jam", output.getvalue())
|
||||
## run test jamfile and match against expected results
|
||||
if sort_results : expected.sort()
|
||||
t.run_build_system(["-ffile.jam"], stdout="\n".join(expected + [""]))
|
||||
t.rm("file.jam")
|
||||
|
||||
|
||||
## RUN TESTS
|
||||
setup_archive("auxilliary1.lib", sources)
|
||||
archive1 = archive
|
||||
setup_archive("auxilliary2.lib", sources)
|
||||
archive2 = archive
|
||||
|
||||
## all arguments empty
|
||||
test_glob_archive([archive1], "[ GLOB_ARCHIVE ]", [])
|
||||
|
||||
## empty query
|
||||
test_glob_archive([archive1], "[ GLOB_ARCHIVE $archive1 : ]", [])
|
||||
|
||||
## no-match
|
||||
test_glob_archive([archive1], "[ GLOB_ARCHIVE $archive1 : a ]", [])
|
||||
|
||||
## match exact
|
||||
test_glob_archive([archive1], "[ GLOB_ARCHIVE $archive1 : a$obj ]",
|
||||
["$archive1(a$obj)"])
|
||||
|
||||
## glob wildcards:1
|
||||
test_glob_archive([archive1], "[ GLOB_ARCHIVE $archive1 : b.* ]",
|
||||
["$archive1(b$obj)"])
|
||||
|
||||
## glob wildcards:2
|
||||
test_glob_archive([archive1], "[ GLOB_ARCHIVE $archive1 : \\b?match[\.]* ]",
|
||||
["$archive1(b_match$obj)"])
|
||||
|
||||
## glob wildcards:3
|
||||
test_glob_archive([archive1], "[ GLOB_ARCHIVE $archive1 : b* ]",
|
||||
["$archive1(b$obj)", "$archive1(b_match$obj)"])
|
||||
|
||||
## glob multiple patterns with multiple results.
|
||||
test_glob_archive([archive1], "[ GLOB_ARCHIVE $archive1 : b.* b_* ]",
|
||||
["$archive1(b$obj)", "$archive1(b_match$obj)"])
|
||||
|
||||
## glob multiple archives and patterns.
|
||||
test_glob_archive([archive1, archive2],
|
||||
"[ GLOB_ARCHIVE $archive1 $archive2 : b.* b_* ]",
|
||||
["$archive1(b$obj)", "$archive1(b_match$obj)",
|
||||
"$archive2(b$obj)", "$archive2(b_match$obj)"])
|
||||
|
||||
## glob same archive multiple times.
|
||||
test_glob_archive([archive1, archive1],
|
||||
"[ GLOB_ARCHIVE $archive1 $archive2 $archive1 : b.* ]",
|
||||
["$archive1(b$obj)", "$archive2(b$obj)", "$archive1(b$obj)"])
|
||||
|
||||
## returned archive member has no path, even though its source object-file did.
|
||||
## this is rather NT-specific, where members also store their object-file's path.
|
||||
test_glob_archive([archive1], "[ GLOB_ARCHIVE $archive1 : nopath_check$obj ]",
|
||||
["$archive1(nopath_check$obj)"])
|
||||
|
||||
## case insensitive matching, when archives support case sensitive member names.
|
||||
## VMS implementation forces case-insensitive matching and downcased member names.
|
||||
|
||||
case_sensitive_members = ( not vms )
|
||||
|
||||
if case_sensitive_members:
|
||||
test_glob_archive([archive1],
|
||||
"[ GLOB_ARCHIVE $archive1 : casecheck$obj : true ]",
|
||||
["$archive1(CaseCheck$obj)"])
|
||||
elif vms:
|
||||
test_glob_archive([archive1],
|
||||
"[ GLOB_ARCHIVE $archive1 : CaseCheck$obj : false ]",
|
||||
["$archive1(casecheck$obj)"])
|
||||
|
||||
|
||||
## test the order of matched members, in general it should match the
|
||||
## insertion sequence.
|
||||
test_glob_archive([archive1], "[ GLOB_ARCHIVE $archive1 : seq_check*$obj ]",
|
||||
["$archive1(seq_check1$obj)", "$archive1(seq_check2$obj)",
|
||||
"$archive1(seq_check3$obj)"])
|
||||
|
||||
|
||||
## glob members by symbols they contain.
|
||||
## Currently supported only on VMS.
|
||||
symbol_glob_supported = ( vms )
|
||||
|
||||
if symbol_glob_supported :
|
||||
## NOTE: generated symbols are compiler-dependent and may be specifically
|
||||
## mangled (as in C++ case), so globbing by exact symbol is non-trivial.
|
||||
## However, C-generated symbols are likely to have more portable names,
|
||||
## so for the glob-by-symbol tests we glob C-generated archive members.
|
||||
|
||||
## glob members by exact symbol.
|
||||
test_glob_archive([archive1],
|
||||
"[ GLOB_ARCHIVE $archive1 : : : symbol ]",
|
||||
["$archive1(symbols_check$obj)"])
|
||||
|
||||
## glob members by symbol wildcard.
|
||||
test_glob_archive([archive1],
|
||||
"[ GLOB_ARCHIVE $archive1 : : : symbol_* ]",
|
||||
["$archive1(symbols_check$obj)"])
|
||||
|
||||
## glob members by member pattern AND symbol pattern.
|
||||
test_glob_archive([archive1],
|
||||
"[ GLOB_ARCHIVE $archive1 : *symbol* : : *member* ]",
|
||||
["$archive1(members_and_symbols_check$obj)"])
|
||||
|
||||
## case insensitive symbol glob.
|
||||
test_glob_archive([archive1],
|
||||
"[ GLOB_ARCHIVE $archive1 : : true : symbolcasecheck ]",
|
||||
["$archive1(symbol_case_check$obj)"])
|
||||
|
||||
## glob member that contains main symbol.
|
||||
test_glob_archive([archive1],
|
||||
"[ GLOB_ARCHIVE $archive1 : : : main _main ]",
|
||||
["$archive1(main_check$obj)"])
|
||||
|
||||
else:
|
||||
test_glob_archive([archive1],
|
||||
"[ GLOB_ARCHIVE $archive1 : : : symbol ]",
|
||||
[])
|
||||
|
||||
|
||||
t.cleanup()
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2012 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
|
||||
import os
|
||||
|
||||
t = BoostBuild.Tester(pass_toolset=0)
|
||||
|
||||
t.write("link-target", "")
|
||||
os.symlink("link-target", "link")
|
||||
|
||||
t.write("file.jam", """
|
||||
ECHO [ READLINK link ] ;
|
||||
EXIT [ READLINK link-target ] : 0 ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-ffile.jam"], stdout="""link-target
|
||||
|
||||
""")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,57 @@
|
||||
#!/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)
|
||||
|
||||
# This tests the SPLIT_BY_CHARACTERS rule.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
def test_invalid(params, expected_error_line):
|
||||
t = BoostBuild.Tester(pass_toolset=0)
|
||||
t.write("file.jam", "SPLIT_BY_CHARACTERS %s ;" % params)
|
||||
t.run_build_system(["-ffile.jam"], status=1)
|
||||
t.expect_output_lines("[*] %s" % expected_error_line)
|
||||
t.cleanup()
|
||||
|
||||
def test_valid():
|
||||
t = BoostBuild.Tester(pass_toolset=0)
|
||||
t.write("jamroot.jam", """\
|
||||
import assert ;
|
||||
|
||||
assert.result FooBarBaz : SPLIT_BY_CHARACTERS FooBarBaz : "" ;
|
||||
assert.result FooBarBaz : SPLIT_BY_CHARACTERS FooBarBaz : x ;
|
||||
assert.result FooBa Baz : SPLIT_BY_CHARACTERS FooBarBaz : r ;
|
||||
assert.result FooBa Baz : SPLIT_BY_CHARACTERS FooBarBaz : rr ;
|
||||
assert.result FooBa Baz : SPLIT_BY_CHARACTERS FooBarBaz : rrr ;
|
||||
assert.result FooB rB z : SPLIT_BY_CHARACTERS FooBarBaz : a ;
|
||||
assert.result FooB B z : SPLIT_BY_CHARACTERS FooBarBaz : ar ;
|
||||
assert.result ooBarBaz : SPLIT_BY_CHARACTERS FooBarBaz : F ;
|
||||
assert.result FooBarBa : SPLIT_BY_CHARACTERS FooBarBaz : z ;
|
||||
assert.result ooBarBa : SPLIT_BY_CHARACTERS FooBarBaz : Fz ;
|
||||
assert.result F B rB z : SPLIT_BY_CHARACTERS FooBarBaz : oa ;
|
||||
assert.result Alib b : SPLIT_BY_CHARACTERS Alibaba : oa ;
|
||||
assert.result libaba : SPLIT_BY_CHARACTERS Alibaba : oA ;
|
||||
assert.result : SPLIT_BY_CHARACTERS FooBarBaz : FooBarBaz ;
|
||||
assert.result : SPLIT_BY_CHARACTERS FooBarBaz : FoBarz ;
|
||||
|
||||
# Questionable results - should they return an empty string or an empty list?
|
||||
assert.result : SPLIT_BY_CHARACTERS "" : "" ;
|
||||
assert.result : SPLIT_BY_CHARACTERS "" : x ;
|
||||
assert.result : SPLIT_BY_CHARACTERS "" : r ;
|
||||
assert.result : SPLIT_BY_CHARACTERS "" : rr ;
|
||||
assert.result : SPLIT_BY_CHARACTERS "" : rrr ;
|
||||
assert.result : SPLIT_BY_CHARACTERS "" : oa ;
|
||||
""")
|
||||
t.run_build_system()
|
||||
t.cleanup()
|
||||
|
||||
test_invalid("", "missing argument string")
|
||||
test_invalid("Foo", "missing argument delimiters")
|
||||
test_invalid(": Bar", "missing argument string")
|
||||
test_invalid("a : b : c", "extra argument c")
|
||||
test_invalid("a b : c", "extra argument b")
|
||||
test_invalid("a : b c", "extra argument c")
|
||||
test_valid()
|
||||
@@ -0,0 +1,119 @@
|
||||
#!/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("bzip2/bzlib.h", 'bzip2')
|
||||
t.write("bzip2/blocksort.c", 'blocksort')
|
||||
|
||||
t.write("Jamroot.jam", """
|
||||
path-constant here : . ;
|
||||
using bzip2 : : <source>$(here)/bzip2 ;
|
||||
alias bzip2 : /bzip2//bzip2 : : <link>static <link>shared ;
|
||||
""")
|
||||
|
||||
MockToolset.set_expected(t, '''
|
||||
source_file('blocksort.c', 'blocksort')
|
||||
action('-c -x c -I./bzip2 -o $blocksort.o $blocksort.c')
|
||||
action('--dll $blocksort.o -o $bz2.so')
|
||||
action('--archive $blocksort.o -o $bz2.a')
|
||||
''')
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition('bin/standalone/bzip2/mock/debug/bz2.dll')
|
||||
t.expect_addition('bin/standalone/bzip2/mock/debug/link-static/bz2.lib')
|
||||
|
||||
t.rm('bzip2')
|
||||
|
||||
# Generic definitions that aren't configuration specific
|
||||
common_stuff = '''
|
||||
source_file('test.cpp', 'test.cpp')
|
||||
source_file('main.cpp', 'int main() {}')
|
||||
source_file('bzlib.h.cpp', '#include <bzlib.h>\\n')
|
||||
action('-c -x c++ $main.cpp -o $main.o')
|
||||
'''
|
||||
t.write('test.cpp', 'test.cpp')
|
||||
|
||||
# Default initialization - static library
|
||||
t.rm('bin')
|
||||
t.write("Jamroot.jam", """
|
||||
path-constant here : . ;
|
||||
using bzip2 ;
|
||||
exe test : test.cpp /bzip2//bzip2 : : <link>static <link>shared ;
|
||||
""")
|
||||
|
||||
MockToolset.set_expected(t, common_stuff + '''
|
||||
action('$main.o --static-lib=bz2 -o $config.exe')
|
||||
action('-c -x c++ $bzlib.h.cpp -o $bzlib.h.o')
|
||||
action('-c -x c++ $test.cpp -o $test.o')
|
||||
action('$test.o --static-lib=bz2 -o $test')
|
||||
''')
|
||||
t.run_build_system()
|
||||
t.expect_addition('bin/mock/debug/test.exe')
|
||||
t.expect_addition('bin/mock/debug/link-static/test.exe')
|
||||
|
||||
# Default initialization - shared library
|
||||
t.rm('bin')
|
||||
t.write("Jamroot.jam", """
|
||||
path-constant here : . ;
|
||||
using bzip2 ;
|
||||
exe test : test.cpp /bzip2//bzip2 : : <link>static <link>shared ;
|
||||
""")
|
||||
|
||||
MockToolset.set_expected(t, common_stuff + '''
|
||||
action('$main.o --shared-lib=bz2 -o $config.exe')
|
||||
action('-c -x c++ $bzlib.h.cpp -o $bzlib.h.o')
|
||||
action('-c -x c++ $test.cpp -o $test.o')
|
||||
action('$test.o --shared-lib=bz2 -o $test')
|
||||
''')
|
||||
t.run_build_system()
|
||||
t.expect_addition('bin/mock/debug/test.exe')
|
||||
t.expect_addition('bin/mock/debug/link-static/test.exe')
|
||||
|
||||
# Initialization in explicit location - static library
|
||||
t.rm('bin')
|
||||
t.write("Jamroot.jam", """
|
||||
path-constant here : . ;
|
||||
using bzip2 : : <name>mybzlib <include>$(here)/bzip2 <search>$(here)/bzip2 ;
|
||||
exe test : test.cpp /bzip2//bzip2 : : <link>static <link>shared ;
|
||||
""")
|
||||
|
||||
t.write('bzip2/bzlib.h', 'bzip2')
|
||||
|
||||
MockToolset.set_expected(t, common_stuff + '''
|
||||
action('$main.o -L./bzip2 --static-lib=mybzlib -o $config.exe')
|
||||
action('-c -x c++ $test.cpp -I./bzip2 -o $test.o')
|
||||
action('$test.o -L./bzip2 --static-lib=mybzlib -o $test')
|
||||
''')
|
||||
t.run_build_system()
|
||||
t.expect_addition('bin/mock/debug/test.exe')
|
||||
t.expect_addition('bin/mock/debug/link-static/test.exe')
|
||||
|
||||
# Initialization in explicit location - shared library
|
||||
t.rm('bin')
|
||||
t.write("Jamroot.jam", """
|
||||
path-constant here : . ;
|
||||
using bzip2 : : <name>mybzlib <include>$(here)/bzip2 <search>$(here)/bzip2 ;
|
||||
exe test : test.cpp /bzip2//bzip2 : : <link>static <link>shared ;
|
||||
""")
|
||||
|
||||
MockToolset.set_expected(t, common_stuff + '''
|
||||
action('$main.o -L./bzip2 --shared-lib=mybzlib -o $config.exe')
|
||||
action('-c -x c++ $test.cpp -I./bzip2 -o $test.o')
|
||||
action('$test.o -L./bzip2 --shared-lib=mybzlib -o $test')
|
||||
''')
|
||||
t.run_build_system()
|
||||
t.expect_addition('bin/mock/debug/test.exe')
|
||||
t.expect_addition('bin/mock/debug/link-static/test.exe')
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,36 @@
|
||||
#!/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)
|
||||
|
||||
# Test that C files are compiled by a C compiler.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.write("jamroot.jam", """
|
||||
project ;
|
||||
exe hello : hello.cpp a.c ;
|
||||
""")
|
||||
|
||||
t.write("hello.cpp", """
|
||||
extern "C" int foo();
|
||||
int main() { return foo(); }
|
||||
""")
|
||||
|
||||
t.write("a.c", """
|
||||
// This will not compile unless in C mode.
|
||||
int foo()
|
||||
{
|
||||
int new = 0;
|
||||
new = (new+1)*7;
|
||||
return new;
|
||||
}
|
||||
""")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition("bin/$toolset/debug/hello.exe")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,56 @@
|
||||
#!/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)
|
||||
|
||||
# This tests that :
|
||||
# 1) the 'make' correctly assigns types to produced targets
|
||||
# 2) if 'make' creates targets of type CPP, they are correctly used.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
# In order to correctly link this app, 'b.cpp', created by a 'make' rule, should
|
||||
# be compiled.
|
||||
|
||||
t.write("jamroot.jam", "import gcc ;")
|
||||
|
||||
t.write("jamfile.jam", r'''
|
||||
import os ;
|
||||
if [ os.name ] = NT
|
||||
{
|
||||
actions create
|
||||
{
|
||||
echo int main() {} > $(<)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
actions create
|
||||
{
|
||||
echo "int main() {}" > $(<)
|
||||
}
|
||||
}
|
||||
|
||||
IMPORT $(__name__) : create : : create ;
|
||||
|
||||
exe a : l dummy.cpp ;
|
||||
|
||||
# Needs to be a static lib for Windows - main() cannot appear in DLL.
|
||||
static-lib l : a.cpp b.cpp ;
|
||||
|
||||
make b.cpp : : create ;
|
||||
''')
|
||||
|
||||
t.write("a.cpp", "")
|
||||
|
||||
t.write("dummy.cpp", "// msvc needs at least one object file\n")
|
||||
|
||||
t.run_build_system()
|
||||
|
||||
t.expect_addition("bin/$toolset/debug/a.exe")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,104 @@
|
||||
#!/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)
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.write("a.cpp", "int main() {}\n")
|
||||
t.write("jamroot.jam", "exe a : a.cpp sub1//sub1 sub2//sub2 sub3//sub3 ;")
|
||||
t.write("sub1/jamfile.jam", """\
|
||||
lib sub1 : sub1.cpp sub1_2 ../sub2//sub2 ;
|
||||
lib sub1_2 : sub1_2.cpp ;
|
||||
""")
|
||||
|
||||
t.write("sub1/sub1.cpp", """\
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void sub1() {}
|
||||
""")
|
||||
|
||||
t.write("sub1/sub1_2.cpp", """\
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void sub1() {}
|
||||
""")
|
||||
|
||||
t.write("sub2/jamfile.jam", "lib sub2 : sub2.cpp ;")
|
||||
t.write("sub2/sub2.cpp", """\
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void sub2() {}
|
||||
""")
|
||||
|
||||
t.write("sub3/jamroot.jam", "lib sub3 : sub3.cpp ;")
|
||||
t.write("sub3/sub3.cpp", """\
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void sub3() {}
|
||||
""")
|
||||
|
||||
# 'clean' should not remove files under separate jamroot.jam.
|
||||
t.run_build_system()
|
||||
t.run_build_system(["--clean"])
|
||||
t.expect_removal("bin/$toolset/debug/a.obj")
|
||||
t.expect_removal("sub1/bin/$toolset/debug/sub1.obj")
|
||||
t.expect_removal("sub1/bin/$toolset/debug/sub1_2.obj")
|
||||
t.expect_removal("sub2/bin/$toolset/debug/sub2.obj")
|
||||
t.expect_nothing("sub3/bin/$toolset/debug/sub3.obj")
|
||||
|
||||
# 'clean-all' removes everything it can reach.
|
||||
t.run_build_system()
|
||||
t.run_build_system(["--clean-all"])
|
||||
t.expect_removal("bin/$toolset/debug/a.obj")
|
||||
t.expect_removal("sub1/bin/$toolset/debug/sub1.obj")
|
||||
t.expect_removal("sub1/bin/$toolset/debug/sub1_2.obj")
|
||||
t.expect_removal("sub2/bin/$toolset/debug/sub2.obj")
|
||||
t.expect_nothing("sub3/bin/$toolset/debug/sub3.obj")
|
||||
|
||||
# 'clean' together with project target removes only under that project.
|
||||
t.run_build_system()
|
||||
t.run_build_system(["sub1", "--clean"])
|
||||
t.expect_nothing("bin/$toolset/debug/a.obj")
|
||||
t.expect_removal("sub1/bin/$toolset/debug/sub1.obj")
|
||||
t.expect_removal("sub1/bin/$toolset/debug/sub1_2.obj")
|
||||
t.expect_nothing("sub2/bin/$toolset/debug/sub2.obj")
|
||||
t.expect_nothing("sub3/bin/$toolset/debug/sub3.obj")
|
||||
|
||||
# 'clean-all' removes everything.
|
||||
t.run_build_system()
|
||||
t.run_build_system(["sub1", "--clean-all"])
|
||||
t.expect_nothing("bin/$toolset/debug/a.obj")
|
||||
t.expect_removal("sub1/bin/$toolset/debug/sub1.obj")
|
||||
t.expect_removal("sub1/bin/$toolset/debug/sub1_2.obj")
|
||||
t.expect_removal("sub2/bin/$toolset/debug/sub2.obj")
|
||||
t.expect_nothing("sub3/bin/$toolset/debug/sub3.obj")
|
||||
|
||||
# If main target is explicitly named, we should not remove files from other
|
||||
# targets.
|
||||
t.run_build_system()
|
||||
t.run_build_system(["sub1//sub1", "--clean"])
|
||||
t.expect_removal("sub1/bin/$toolset/debug/sub1.obj")
|
||||
t.expect_nothing("sub1/bin/$toolset/debug/sub1_2.obj")
|
||||
t.expect_nothing("sub2/bin/$toolset/debug/sub2.obj")
|
||||
t.expect_nothing("sub3/bin/$toolset/debug/sub3.obj")
|
||||
|
||||
# Regression test: sources of the 'cast' rule were mistakenly deleted.
|
||||
t.rm(".")
|
||||
t.write("jamroot.jam", """\
|
||||
import cast ;
|
||||
cast a cpp : a.h ;
|
||||
""")
|
||||
t.write("a.h", "")
|
||||
t.run_build_system(["--clean"])
|
||||
t.expect_nothing("a.h")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2015 Aaron Boman
|
||||
# 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 free property inside.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.write("jamroot.jam", "")
|
||||
t.write(
|
||||
"subdir/build.jam",
|
||||
"""
|
||||
import feature ;
|
||||
feature.feature my-feature : : free ;
|
||||
"""
|
||||
)
|
||||
t.write(
|
||||
"subdir/subsubdir/build.jam",
|
||||
"""
|
||||
exe hello : hello.c ;
|
||||
"""
|
||||
)
|
||||
t.write(
|
||||
"subdir/subsubdir/hello.c",
|
||||
r"""
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char **argv){
|
||||
printf("%s\n", "Hello, World!");
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
# run from the root directory
|
||||
t.run_build_system(['subdir/subsubdir', 'my-feature="some value"'])
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,341 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2012 Jurko Gospodnetic
|
||||
# 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)
|
||||
|
||||
# Temporarily enabled dummy test that always fails and is used to collect
|
||||
# extra debugging information from Boost Build test runner sites.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Public interface.
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
def collectDebugInfo():
|
||||
t = _init()
|
||||
|
||||
global tag
|
||||
|
||||
tag = "Python version"
|
||||
try:
|
||||
_info(sys.version)
|
||||
except:
|
||||
_info_exc()
|
||||
|
||||
tag = "Python platform"
|
||||
try:
|
||||
_info(sys.platform)
|
||||
except:
|
||||
_info_exc()
|
||||
|
||||
tag = "Boost Jam/Build version"
|
||||
try:
|
||||
_infoX(_getJamVersionInfo(t))
|
||||
except:
|
||||
_info_exc()
|
||||
|
||||
#_collectDebugInfo_environ()
|
||||
|
||||
# Report prepared annotations.
|
||||
t.fail_test(1, dump_difference=False, dump_stdio=False, dump_stack=False)
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Private interface.
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
varSeparator = "###$^%~~~"
|
||||
|
||||
|
||||
def _collect(results, prefix, name, t):
|
||||
results.append("%s - %s - os.getenv(): %r" % (prefix, name, os.getenv(
|
||||
name)))
|
||||
results.append("%s - %s - os.environ.get(): %r" % (prefix, name,
|
||||
os.environ.get(name)))
|
||||
external_values = _getExternalValues(t, name)
|
||||
results.append("%s - %s - external: %r" % (prefix, name,
|
||||
external_values[name]))
|
||||
|
||||
|
||||
def _collectDebugInfo_environ(t):
|
||||
dummyVars = ["WOOF_WOOFIE_%d" % x for x in xrange(4)]
|
||||
global tag
|
||||
|
||||
tag = "XXX in os.environ"
|
||||
try:
|
||||
def f(name):
|
||||
return "%s: %s" % (name, name in os.environ)
|
||||
_infoX(f(x) for x in dummyVars)
|
||||
except:
|
||||
_info_exc()
|
||||
|
||||
tag = "os.environ[XXX]"
|
||||
try:
|
||||
def f(name):
|
||||
try:
|
||||
result = os.environ[name]
|
||||
except:
|
||||
result = _str_exc()
|
||||
return "%s: %r" % (name, result)
|
||||
_infoX(f(x) for x in dummyVars)
|
||||
except:
|
||||
_info_exc()
|
||||
|
||||
tag = "os.environ.get(XXX)"
|
||||
try:
|
||||
def f(name):
|
||||
return "%s: %r" % (name, os.environ.get(name))
|
||||
_infoX(f(x) for x in dummyVars)
|
||||
except:
|
||||
_info_exc()
|
||||
|
||||
tag = "os.getenv(XXX)"
|
||||
try:
|
||||
def f(name):
|
||||
return "%s: %r" % (name, os.getenv(name))
|
||||
_infoX(f(x) for x in dummyVars)
|
||||
except:
|
||||
_info_exc()
|
||||
|
||||
name = dummyVars[0]
|
||||
value = "foo"
|
||||
tag = "os.putenv(%s) to %r" % (name, value)
|
||||
try:
|
||||
results = []
|
||||
_collect(results, "before", name, t)
|
||||
os.putenv(name, value)
|
||||
_collect(results, "after", name, t)
|
||||
_infoX(results)
|
||||
except:
|
||||
_info_exc()
|
||||
|
||||
name = dummyVars[1]
|
||||
value = "bar"
|
||||
tag = "os.environ[%s] to %r" % (name, value)
|
||||
try:
|
||||
results = []
|
||||
_collect(results, "before", name, t)
|
||||
os.environ[name] = value
|
||||
_collect(results, "after", name, t)
|
||||
_infoX(results)
|
||||
except:
|
||||
_info_exc()
|
||||
|
||||
name = dummyVars[1]
|
||||
value = "baz"
|
||||
tag = "os.putenv(%s) to %r" % (name, value)
|
||||
try:
|
||||
results = []
|
||||
_collect(results, "before", name, t)
|
||||
os.putenv(name, value)
|
||||
_collect(results, "after", name, t)
|
||||
_infoX(results)
|
||||
except:
|
||||
_info_exc()
|
||||
|
||||
name = dummyVars[1]
|
||||
value = ""
|
||||
tag = "os.putenv(%s) to %r" % (name, value)
|
||||
try:
|
||||
results = []
|
||||
_collect(results, "before", name, t)
|
||||
os.putenv(name, value)
|
||||
_collect(results, "after", name, t)
|
||||
_infoX(results)
|
||||
except:
|
||||
_info_exc()
|
||||
|
||||
name = dummyVars[2]
|
||||
value = "foo"
|
||||
tag = "os.unsetenv(%s) from %r" % (name, value)
|
||||
try:
|
||||
results = []
|
||||
os.environ[name] = value
|
||||
_collect(results, "before", name, t)
|
||||
os.unsetenv(name)
|
||||
_collect(results, "after", name, t)
|
||||
_infoX(results)
|
||||
except:
|
||||
_info_exc()
|
||||
|
||||
name = dummyVars[2]
|
||||
value = "foo"
|
||||
tag = "del os.environ[%s] from %r" % (name, value)
|
||||
try:
|
||||
results = []
|
||||
os.environ[name] = value
|
||||
_collect(results, "before", name, t)
|
||||
del os.environ[name]
|
||||
_collect(results, "after", name, t)
|
||||
_infoX(results)
|
||||
except:
|
||||
_info_exc()
|
||||
|
||||
name = dummyVars[2]
|
||||
value = "foo"
|
||||
tag = "os.environ.pop(%s) from %r" % (name, value)
|
||||
try:
|
||||
results = []
|
||||
os.environ[name] = value
|
||||
_collect(results, "before", name, t)
|
||||
os.environ.pop(name)
|
||||
_collect(results, "after", name, t)
|
||||
_infoX(results)
|
||||
except:
|
||||
_info_exc()
|
||||
|
||||
name = dummyVars[2]
|
||||
value1 = "foo"
|
||||
value2 = ""
|
||||
tag = "os.environ[%s] to %r from %r" % (name, value2, value1)
|
||||
try:
|
||||
results = []
|
||||
os.environ[name] = value1
|
||||
_collect(results, "before", name, t)
|
||||
os.environ[name] = value2
|
||||
_collect(results, "after", name, t)
|
||||
_infoX(results)
|
||||
except:
|
||||
_info_exc()
|
||||
|
||||
name = dummyVars[3]
|
||||
value = '""'
|
||||
tag = "os.environ[%s] to %r" % (name, value)
|
||||
try:
|
||||
results = []
|
||||
_collect(results, "before", name, t)
|
||||
os.environ[name] = value
|
||||
_collect(results, "after", name, t)
|
||||
_infoX(results)
|
||||
except:
|
||||
_info_exc()
|
||||
|
||||
|
||||
def _getExternalValues(t, *args):
|
||||
t.run_build_system(["---var-name=%s" % x for x in args])
|
||||
result = dict()
|
||||
for x in args:
|
||||
m = re.search(r"^\*\*\*ENV\*\*\* %s: '(.*)' \*\*\*$" % x, t.stdout(),
|
||||
re.MULTILINE)
|
||||
if m:
|
||||
result[x] = m.group(1)
|
||||
else:
|
||||
result[x] = None
|
||||
return result
|
||||
|
||||
|
||||
def _getJamVersionInfo(t):
|
||||
result = []
|
||||
|
||||
# JAM version variables.
|
||||
t.run_build_system(["---version"])
|
||||
for m in re.finditer(r"^\*\*\*VAR\*\*\* ([^:]*): (.*)\*\*\*$", t.stdout(),
|
||||
re.MULTILINE):
|
||||
name = m.group(1)
|
||||
value = m.group(2)
|
||||
if not value:
|
||||
value = []
|
||||
elif value[-1] == ' ':
|
||||
value = value[:-1].split(varSeparator)
|
||||
else:
|
||||
value = "!!!INVALID!!! - '%s'" % value
|
||||
result.append("%s = %s" % (name, value))
|
||||
result.append("")
|
||||
|
||||
# bjam -v output.
|
||||
t.run_build_system(["-v"])
|
||||
result.append("--- output for 'bjam -v' ---")
|
||||
result.append(t.stdout())
|
||||
|
||||
# bjam --version output.
|
||||
t.run_build_system(["--version"], status=1)
|
||||
result.append("--- output for 'bjam --version' ---")
|
||||
result.append(t.stdout())
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def _init():
|
||||
toolsetName = "__myDummyToolset__"
|
||||
|
||||
t = BoostBuild.Tester(["toolset=%s" % toolsetName], pass_toolset=False,
|
||||
use_test_config=False)
|
||||
|
||||
# Prepare a dummy toolset so we do not get errors in case the default one
|
||||
# is not found.
|
||||
t.write(toolsetName + ".jam", """\
|
||||
import feature ;
|
||||
feature.extend toolset : %s ;
|
||||
rule init ( ) { }
|
||||
""" % toolsetName )
|
||||
|
||||
# Python version of the same dummy toolset.
|
||||
t.write(toolsetName + ".py", """\
|
||||
from b2.build import feature
|
||||
feature.extend('toolset', ['%s'])
|
||||
def init(): pass
|
||||
""" % toolsetName )
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
import os ;
|
||||
.argv = [ modules.peek : ARGV ] ;
|
||||
local names = [ MATCH ^---var-name=(.*) : $(.argv) ] ;
|
||||
for x in $(names)
|
||||
{
|
||||
value = [ os.environ $(x) ] ;
|
||||
ECHO ***ENV*** $(x): '$(value)' *** ;
|
||||
}
|
||||
if ---version in $(.argv)
|
||||
{
|
||||
for x in JAMVERSION JAM_VERSION JAMUNAME JAM_TIMESTAMP_RESOLUTION OS
|
||||
{
|
||||
v = [ modules.peek : $(x) ] ;
|
||||
ECHO ***VAR*** $(x): "$(v:J=%s)" *** ;
|
||||
}
|
||||
}
|
||||
""" % varSeparator)
|
||||
|
||||
return t
|
||||
|
||||
|
||||
def _info(*values):
|
||||
values = list(values) + [""]
|
||||
BoostBuild.annotation(tag, "\n".join(str(x) for x in values))
|
||||
|
||||
|
||||
def _infoX(values):
|
||||
_info(*values)
|
||||
|
||||
|
||||
def _info_exc():
|
||||
_info(_str_exc())
|
||||
|
||||
|
||||
def _str_exc():
|
||||
exc_type, exc_value = sys.exc_info()[0:2]
|
||||
if exc_type is None:
|
||||
exc_type_name = "None"
|
||||
else:
|
||||
exc_type_name = exc_type.__name__
|
||||
return "*** EXCEPTION *** %s - %s ***" % (exc_type_name, exc_value)
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# main()
|
||||
# ------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
collectDebugInfo()
|
||||
@@ -0,0 +1,25 @@
|
||||
#!/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)
|
||||
|
||||
# Test that composite properties are handled correctly.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.write("jamroot.jam", """
|
||||
exe hello : hello.cpp : <variant>release ;
|
||||
""")
|
||||
|
||||
t.write("hello.cpp", """
|
||||
int main() {}
|
||||
""")
|
||||
|
||||
t.run_build_system()
|
||||
|
||||
t.expect_addition("bin/$toolset/release/hello.exe")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,48 @@
|
||||
#!/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 copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
# Test conditional properties.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
# Arrange a project which will build only if 'a.cpp' is compiled with "STATIC"
|
||||
# define.
|
||||
t.write("a.cpp", """\
|
||||
#ifdef STATIC
|
||||
int main() {}
|
||||
#endif
|
||||
""")
|
||||
|
||||
# Test conditionals in target requirements.
|
||||
t.write("jamroot.jam", "exe a : a.cpp : <link>static:<define>STATIC ;")
|
||||
t.run_build_system(["link=static"])
|
||||
t.expect_addition("bin/$toolset/debug/link-static/a.exe")
|
||||
t.rm("bin")
|
||||
|
||||
# Test conditionals in project requirements.
|
||||
t.write("jamroot.jam", """
|
||||
project : requirements <link>static:<define>STATIC ;
|
||||
exe a : a.cpp ;
|
||||
""")
|
||||
t.run_build_system(["link=static"])
|
||||
t.expect_addition("bin/$toolset/debug/link-static/a.exe")
|
||||
t.rm("bin")
|
||||
|
||||
# Regression test for a bug found by Ali Azarbayejani. Conditionals inside
|
||||
# usage requirement were not being evaluated.
|
||||
t.write("jamroot.jam", """
|
||||
lib l : l.cpp : : : <link>static:<define>STATIC ;
|
||||
exe a : a.cpp l ;
|
||||
""")
|
||||
t.write("l.cpp", "int i;")
|
||||
t.run_build_system(["link=static"])
|
||||
t.expect_addition("bin/$toolset/debug/link-static/a.exe")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,43 @@
|
||||
#!/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)
|
||||
|
||||
# Regression test: it was possible that due to evaluation of conditional
|
||||
# requirements, two different values of non-free features were present in a
|
||||
# property set.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester()
|
||||
|
||||
t.write("a.cpp", "")
|
||||
|
||||
t.write("jamroot.jam", """
|
||||
import feature ;
|
||||
import common ;
|
||||
|
||||
feature.feature the_feature : false true : propagated ;
|
||||
|
||||
rule maker ( targets * : sources * : properties * )
|
||||
{
|
||||
if <the_feature>false in $(properties) &&
|
||||
<the_feature>true in $(properties)
|
||||
{
|
||||
EXIT "Oops, two different values of non-free feature" ;
|
||||
}
|
||||
CMD on $(targets) = [ common.file-creation-command ] ;
|
||||
}
|
||||
|
||||
actions maker
|
||||
{
|
||||
$(CMD) $(<) ;
|
||||
}
|
||||
|
||||
make a : a.cpp : maker : <variant>debug:<the_feature>true ;
|
||||
""")
|
||||
|
||||
t.run_build_system()
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,30 @@
|
||||
#!/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)
|
||||
|
||||
# Test that conditional properties work, even if property is free, and value
|
||||
# includes a colon.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.write("jamroot.jam", """
|
||||
exe hello : hello.cpp : <variant>debug:<define>CLASS=Foo::Bar ;
|
||||
""")
|
||||
|
||||
t.write("hello.cpp", """
|
||||
namespace Foo { class Bar { } ; }
|
||||
int main()
|
||||
{
|
||||
CLASS c;
|
||||
c; // Disables the unused variable warning.
|
||||
}
|
||||
""")
|
||||
|
||||
t.run_build_system(stdout=None, stderr=None)
|
||||
t.expect_addition("bin/$toolset/debug/hello.exe")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,312 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2008 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)
|
||||
|
||||
# Tests that properties conditioned on more than one other property work as
|
||||
# expected.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# test_multiple_conditions()
|
||||
# --------------------------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
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()
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# test_multiple_conditions_with_toolset_version()
|
||||
# -----------------------------------------------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
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()
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# main()
|
||||
# ------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
test_multiple_conditions()
|
||||
test_multiple_conditions_with_toolset_version()
|
||||
@@ -0,0 +1,328 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2008, 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 Boost Build configuration file handling.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import re
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# test_user_configuration()
|
||||
# -------------------------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
def test_user_configuration():
|
||||
"""
|
||||
Test Boost Build user configuration handling. Both relative and absolute
|
||||
path handling is tested.
|
||||
|
||||
"""
|
||||
|
||||
implicitConfigLoadMessage = \
|
||||
"notice: Loading user-config configuration file: *"
|
||||
explicitConfigLoadMessage = \
|
||||
"notice: Loading explicitly specified user configuration file:"
|
||||
disabledConfigLoadMessage = \
|
||||
"notice: User configuration file loading explicitly disabled."
|
||||
testMessage = "_!_!_!_!_!_!_!_!_ %s _!_!_!_!_!_!_!_!_"
|
||||
toolsetName = "__myDummyToolset__"
|
||||
subdirName = "ASubDirectory"
|
||||
configFileNames = ["ups_lala_1.jam", "ups_lala_2.jam",
|
||||
os.path.join(subdirName, "ups_lala_3.jam")]
|
||||
|
||||
t = BoostBuild.Tester(["toolset=%s" % toolsetName,
|
||||
"--debug-configuration"], pass_toolset=False, use_test_config=False)
|
||||
|
||||
for configFileName in configFileNames:
|
||||
message = "ECHO \"%s\" ;" % testMessage % configFileName
|
||||
# We need to double any backslashes in the message or Jam will
|
||||
# interpret them as escape characters.
|
||||
t.write(configFileName, message.replace("\\", "\\\\"))
|
||||
|
||||
# Prepare a dummy toolset so we do not get errors in case the default one
|
||||
# is not found.
|
||||
t.write(toolsetName + ".jam", """\
|
||||
import feature ;
|
||||
feature.extend toolset : %s ;
|
||||
rule init ( ) { }
|
||||
""" % toolsetName)
|
||||
|
||||
# Python version of the same dummy toolset.
|
||||
t.write(toolsetName + ".py", """\
|
||||
from b2.build import feature
|
||||
feature.extend('toolset', ['%s'])
|
||||
def init(): pass
|
||||
""" % toolsetName)
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
local test-index = [ MATCH ---test-id---=(.*) : [ modules.peek : ARGV ] ] ;
|
||||
ECHO test-index: $(test-index:E=(unknown)) ;
|
||||
""")
|
||||
|
||||
class LocalTester:
|
||||
def __init__(self, tester):
|
||||
self.__tester = tester
|
||||
self.__test_ids = []
|
||||
|
||||
def __assertionFailure(self, message):
|
||||
BoostBuild.annotation("failure", "Internal test assertion failure "
|
||||
"- %s" % message)
|
||||
self.__tester.fail_test(1)
|
||||
|
||||
def __call__(self, test_id, env, extra_args=None, *args, **kwargs):
|
||||
if env == "" and not canSetEmptyEnvironmentVariable:
|
||||
self.__assertionFailure("Can not set empty environment "
|
||||
"variables on this platform.")
|
||||
self.__registerTestId(str(test_id))
|
||||
if extra_args is None:
|
||||
extra_args = []
|
||||
extra_args.append("---test-id---=%s" % test_id)
|
||||
env_name = "BOOST_BUILD_USER_CONFIG"
|
||||
previous_env = os.environ.get(env_name)
|
||||
_env_set(env_name, env)
|
||||
try:
|
||||
self.__tester.run_build_system(extra_args, *args, **kwargs)
|
||||
finally:
|
||||
_env_set(env_name, previous_env)
|
||||
|
||||
def __registerTestId(self, test_id):
|
||||
if test_id in self.__test_ids:
|
||||
self.__assertionFailure("Multiple test cases encountered "
|
||||
"using the same test id '%s'." % test_id)
|
||||
self.__test_ids.append(test_id)
|
||||
|
||||
test = LocalTester(t)
|
||||
|
||||
test(1, None)
|
||||
t.expect_output_lines(explicitConfigLoadMessage, False)
|
||||
t.expect_output_lines(disabledConfigLoadMessage, False)
|
||||
t.expect_output_lines(testMessage % configFileNames[0], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[1], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[2], False)
|
||||
|
||||
test(2, None, ["--user-config="])
|
||||
t.expect_output_lines(implicitConfigLoadMessage, False)
|
||||
t.expect_output_lines(explicitConfigLoadMessage, False)
|
||||
t.expect_output_lines(disabledConfigLoadMessage)
|
||||
t.expect_output_lines(testMessage % configFileNames[0], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[1], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[2], False)
|
||||
|
||||
test(3, None, ['--user-config=""'])
|
||||
t.expect_output_lines(implicitConfigLoadMessage, False)
|
||||
t.expect_output_lines(explicitConfigLoadMessage, False)
|
||||
t.expect_output_lines(disabledConfigLoadMessage)
|
||||
t.expect_output_lines(testMessage % configFileNames[0], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[1], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[2], False)
|
||||
|
||||
test(4, None, ['--user-config="%s"' % configFileNames[0]])
|
||||
t.expect_output_lines(implicitConfigLoadMessage, False)
|
||||
t.expect_output_lines(explicitConfigLoadMessage)
|
||||
t.expect_output_lines(disabledConfigLoadMessage, False)
|
||||
t.expect_output_lines(testMessage % configFileNames[0])
|
||||
t.expect_output_lines(testMessage % configFileNames[1], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[2], False)
|
||||
|
||||
test(5, None, ['--user-config="%s"' % configFileNames[2]])
|
||||
t.expect_output_lines(implicitConfigLoadMessage, False)
|
||||
t.expect_output_lines(explicitConfigLoadMessage)
|
||||
t.expect_output_lines(disabledConfigLoadMessage, False)
|
||||
t.expect_output_lines(testMessage % configFileNames[0], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[1], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[2])
|
||||
|
||||
test(6, None, ['--user-config="%s"' % os.path.abspath(configFileNames[1])])
|
||||
t.expect_output_lines(implicitConfigLoadMessage, False)
|
||||
t.expect_output_lines(explicitConfigLoadMessage)
|
||||
t.expect_output_lines(disabledConfigLoadMessage, False)
|
||||
t.expect_output_lines(testMessage % configFileNames[0], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[1])
|
||||
t.expect_output_lines(testMessage % configFileNames[2], False)
|
||||
|
||||
test(7, None, ['--user-config="%s"' % os.path.abspath(configFileNames[2])])
|
||||
t.expect_output_lines(implicitConfigLoadMessage, False)
|
||||
t.expect_output_lines(explicitConfigLoadMessage)
|
||||
t.expect_output_lines(disabledConfigLoadMessage, False)
|
||||
t.expect_output_lines(testMessage % configFileNames[0], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[1], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[2])
|
||||
|
||||
if canSetEmptyEnvironmentVariable:
|
||||
test(8, "")
|
||||
t.expect_output_lines(implicitConfigLoadMessage, False)
|
||||
t.expect_output_lines(explicitConfigLoadMessage, False)
|
||||
t.expect_output_lines(disabledConfigLoadMessage, True)
|
||||
t.expect_output_lines(testMessage % configFileNames[0], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[1], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[2], False)
|
||||
|
||||
test(9, '""')
|
||||
t.expect_output_lines(implicitConfigLoadMessage, False)
|
||||
t.expect_output_lines(explicitConfigLoadMessage, False)
|
||||
t.expect_output_lines(disabledConfigLoadMessage)
|
||||
t.expect_output_lines(testMessage % configFileNames[0], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[1], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[2], False)
|
||||
|
||||
test(10, configFileNames[1])
|
||||
t.expect_output_lines(implicitConfigLoadMessage, False)
|
||||
t.expect_output_lines(explicitConfigLoadMessage)
|
||||
t.expect_output_lines(disabledConfigLoadMessage, False)
|
||||
t.expect_output_lines(testMessage % configFileNames[0], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[1])
|
||||
t.expect_output_lines(testMessage % configFileNames[2], False)
|
||||
|
||||
test(11, configFileNames[1], ['--user-config=""'])
|
||||
t.expect_output_lines(implicitConfigLoadMessage, False)
|
||||
t.expect_output_lines(explicitConfigLoadMessage, False)
|
||||
t.expect_output_lines(disabledConfigLoadMessage)
|
||||
t.expect_output_lines(testMessage % configFileNames[0], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[1], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[2], False)
|
||||
|
||||
test(12, configFileNames[1], ['--user-config="%s"' % configFileNames[0]])
|
||||
t.expect_output_lines(implicitConfigLoadMessage, False)
|
||||
t.expect_output_lines(explicitConfigLoadMessage)
|
||||
t.expect_output_lines(disabledConfigLoadMessage, False)
|
||||
t.expect_output_lines(testMessage % configFileNames[0])
|
||||
t.expect_output_lines(testMessage % configFileNames[1], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[2], False)
|
||||
|
||||
if canSetEmptyEnvironmentVariable:
|
||||
test(13, "", ['--user-config="%s"' % configFileNames[0]])
|
||||
t.expect_output_lines(implicitConfigLoadMessage, False)
|
||||
t.expect_output_lines(explicitConfigLoadMessage)
|
||||
t.expect_output_lines(disabledConfigLoadMessage, False)
|
||||
t.expect_output_lines(testMessage % configFileNames[0])
|
||||
t.expect_output_lines(testMessage % configFileNames[1], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[2], False)
|
||||
|
||||
test(14, '""', ['--user-config="%s"' % configFileNames[0]])
|
||||
t.expect_output_lines(implicitConfigLoadMessage, False)
|
||||
t.expect_output_lines(explicitConfigLoadMessage)
|
||||
t.expect_output_lines(disabledConfigLoadMessage, False)
|
||||
t.expect_output_lines(testMessage % configFileNames[0])
|
||||
t.expect_output_lines(testMessage % configFileNames[1], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[2], False)
|
||||
|
||||
test(15, "invalid", ['--user-config="%s"' % configFileNames[0]])
|
||||
t.expect_output_lines(implicitConfigLoadMessage, False)
|
||||
t.expect_output_lines(explicitConfigLoadMessage)
|
||||
t.expect_output_lines(disabledConfigLoadMessage, False)
|
||||
t.expect_output_lines(testMessage % configFileNames[0])
|
||||
t.expect_output_lines(testMessage % configFileNames[1], False)
|
||||
t.expect_output_lines(testMessage % configFileNames[2], False)
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Private interface.
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
def _canSetEmptyEnvironmentVariable():
|
||||
"""
|
||||
Unfortunately different OSs (and possibly Python implementations as well)
|
||||
have different interpretations of what it means to set an evironment
|
||||
variable to an empty string. Some (e.g. Windows) interpret it as unsetting
|
||||
the variable and some (e.g. AIX or Darwin) actually set it to an empty
|
||||
string.
|
||||
|
||||
"""
|
||||
dummyName = "UGNABUNGA_FOO_BAR_BAZ_FEE_FAE_FOU_FAM"
|
||||
original = os.environ.get(dummyName)
|
||||
_env_set(dummyName, "")
|
||||
result = _getExternalEnv(dummyName) == ""
|
||||
_env_set(dummyName, original)
|
||||
return result
|
||||
|
||||
|
||||
def _env_del(name):
|
||||
"""
|
||||
Unsets the given environment variable if it is currently set.
|
||||
|
||||
Note that we can not use os.environ.pop() or os.environ.clear() here
|
||||
since prior to Python 2.6 these functions did not remove the actual
|
||||
environment variable by calling os.unsetenv().
|
||||
|
||||
"""
|
||||
try:
|
||||
del os.environ[name]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
|
||||
def _env_set(name, value):
|
||||
"""
|
||||
Sets the given environment variable value or unsets it, if the value is
|
||||
None.
|
||||
|
||||
"""
|
||||
if value is None:
|
||||
_env_del(name)
|
||||
else:
|
||||
os.environ[name] = value
|
||||
|
||||
|
||||
def _getExternalEnv(name):
|
||||
toolsetName = "__myDummyToolset__"
|
||||
|
||||
t = BoostBuild.Tester(["toolset=%s" % toolsetName], pass_toolset=False,
|
||||
use_test_config=False)
|
||||
try:
|
||||
# Prepare a dummy toolset so we do not get errors in case the default
|
||||
# one is not found.
|
||||
t.write(toolsetName + ".jam", """\
|
||||
import feature ;
|
||||
feature.extend toolset : %s ;
|
||||
rule init ( ) { }
|
||||
""" % toolsetName)
|
||||
|
||||
# Python version of the same dummy toolset.
|
||||
t.write(toolsetName + ".py", """\
|
||||
from b2.build import feature
|
||||
feature.extend('toolset', ['%s'])
|
||||
def init(): pass
|
||||
""" % toolsetName)
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
import os ;
|
||||
local names = [ MATCH ^---var-name---=(.*) : [ modules.peek : ARGV ] ] ;
|
||||
for x in $(names)
|
||||
{
|
||||
value = [ os.environ $(x) ] ;
|
||||
ECHO "###" $(x): '$(value)' "###" ;
|
||||
}
|
||||
""")
|
||||
|
||||
t.run_build_system(["---var-name---=%s" % name])
|
||||
m = re.search("^### %s: '(.*)' ###$" % name, t.stdout(), re.MULTILINE)
|
||||
if m:
|
||||
return m.group(1)
|
||||
finally:
|
||||
t.cleanup()
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# main()
|
||||
# ------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
canSetEmptyEnvironmentVariable = _canSetEmptyEnvironmentVariable()
|
||||
|
||||
test_user_configuration()
|
||||
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Copyright (c) 2008 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)
|
||||
|
||||
# Test that the common.copy rule set the modification date of the new file to
|
||||
# the current time.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
tester = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
tester.write("test1.cpp", """\
|
||||
template<bool, int M, class Next>
|
||||
struct time_waster {
|
||||
typedef typename time_waster<true, M-1, time_waster>::type type1;
|
||||
typedef typename time_waster<false, M-1, time_waster>::type type2;
|
||||
typedef void type;
|
||||
};
|
||||
template<bool B, class Next>
|
||||
struct time_waster<B, 0, Next> {
|
||||
typedef void type;
|
||||
};
|
||||
typedef time_waster<true, 10, void>::type type;
|
||||
int f() { return 0; }
|
||||
""")
|
||||
|
||||
tester.write("test2.cpp", """\
|
||||
template<bool, int M, class Next>
|
||||
struct time_waster {
|
||||
typedef typename time_waster<true, M-1, time_waster>::type type1;
|
||||
typedef typename time_waster<false, M-1, time_waster>::type type2;
|
||||
typedef void type;
|
||||
};
|
||||
template<bool B, class Next>
|
||||
struct time_waster<B, 0, Next> {
|
||||
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()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,62 @@
|
||||
#!/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 ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-ffile.jam", "-sXXX=1"], stderr="")
|
||||
t.expect_output_lines("{{{ 1 }}}")
|
||||
t.expect_output_lines("stdout")
|
||||
t.expect_output_lines("stderr")
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.run_build_system(["-ffile.jam", "-sXXX=2", "-p0"], stderr="")
|
||||
t.expect_output_lines("{{{ 2 }}}")
|
||||
t.expect_output_lines("stdout")
|
||||
t.expect_output_lines("stderr")
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.run_build_system(["-ffile.jam", "-sXXX=3", "-p1"], stderr="")
|
||||
t.expect_output_lines("{{{ 3 }}}")
|
||||
t.expect_output_lines("stdout")
|
||||
t.expect_output_lines("stderr*", False)
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.run_build_system(["-ffile.jam", "-sXXX=4", "-p2"], stderr="stderr\n")
|
||||
t.expect_output_lines("{{{ 4 }}}")
|
||||
t.expect_output_lines("stdout*", False)
|
||||
t.expect_output_lines("stderr*", False)
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.run_build_system(["-ffile.jam", "-sXXX=5", "-p3"], stderr="stderr\n")
|
||||
t.expect_output_lines("{{{ 5 }}}")
|
||||
t.expect_output_lines("stdout")
|
||||
t.expect_output_lines("stderr*", False)
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/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)
|
||||
|
||||
t.write("file.jam", """\
|
||||
actions quietly .a. { $(ACTION) }
|
||||
|
||||
rule .a.
|
||||
{
|
||||
DEPENDS $(<) : $(>) ;
|
||||
}
|
||||
|
||||
NOTFILE subtest ;
|
||||
.a. subtest_a : subtest ;
|
||||
DEPENDS all : subtest_a ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-ffile.jam", "-sACTION=invalid"], status=1)
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,61 @@
|
||||
#!/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)
|
||||
|
||||
t.write("file.jam", """\
|
||||
actions quietly .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 ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-ffile.jam", "-d2"], stdout="""\
|
||||
...found 4 targets...
|
||||
...updating 2 targets...
|
||||
.a. subtest_a
|
||||
|
||||
echo [subtest_a] 0
|
||||
echo [subtest_a] 1
|
||||
echo [subtest_a] 2
|
||||
|
||||
[subtest_a] 0
|
||||
[subtest_a] 1
|
||||
[subtest_a] 2
|
||||
.a. subtest_b
|
||||
|
||||
echo [subtest_b] 0
|
||||
echo [subtest_b] 1
|
||||
echo [subtest_b] 2
|
||||
|
||||
[subtest_b] 0
|
||||
[subtest_b] 1
|
||||
[subtest_b] 2
|
||||
...updated 2 targets...
|
||||
""")
|
||||
|
||||
t.run_build_system(["-ffile.jam", "-d1"], stdout="""\
|
||||
...found 4 targets...
|
||||
...updating 2 targets...
|
||||
...updated 2 targets...
|
||||
""")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2001 Dave Abrahams
|
||||
# Copyright 2011 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
|
||||
|
||||
|
||||
def simple_args(start, finish):
|
||||
return " : ".join("%d" % x for x in xrange(start, finish + 1))
|
||||
|
||||
|
||||
def test(t, type, input, output, status=0):
|
||||
code = ["include echo_args.jam ; echo_%s" % type]
|
||||
if input: code.append(input)
|
||||
code.append(";")
|
||||
t.write("file.jam", " ".join(code))
|
||||
t.run_build_system(["-ffile.jam"], status=status)
|
||||
t.expect_output_lines(output);
|
||||
|
||||
|
||||
def test_args(t, *args, **kwargs):
|
||||
test(t, "args", *args, **kwargs)
|
||||
|
||||
|
||||
def test_varargs(t, *args, **kwargs):
|
||||
test(t, "varargs", *args, **kwargs)
|
||||
|
||||
|
||||
t = BoostBuild.Tester(pass_toolset=0, pass_d0=False)
|
||||
|
||||
t.write("echo_args.jam", """\
|
||||
NOCARE all ;
|
||||
|
||||
rule echo_args ( a b ? c ? : d + : e * )
|
||||
{
|
||||
ECHO a= $(a) b= $(b) c= $(c) ":" d= $(d) ":" e= $(e) ;
|
||||
}
|
||||
|
||||
rule echo_varargs ( a b ? c ? : d + : e * : * )
|
||||
{
|
||||
ECHO a= $(a) b= $(b) c= $(c) ":" d= $(d) ":" e= $(e)
|
||||
": rest= "$(4[1]) $(4[2-])
|
||||
": "$(5[1]) $(5[2-]) ": "$(6[1]) $(6[2-]) ": "$(7[1]) $(7[2-])
|
||||
": "$(8[1]) $(8[2-]) ": "$(9[1]) $(9[2-]) ": "$(10[1]) $(10[2-])
|
||||
": "$(11[1]) $(11[2-]) ": "$(12[1]) $(12[2-]) ": "$(13[1]) $(13[2-])
|
||||
": "$(14[1]) $(14[2-]) ": "$(15[1]) $(15[2-]) ": "$(16[1]) $(16[2-])
|
||||
": "$(17[1]) $(17[2-]) ": "$(18[1]) $(18[2-]) ": "$(19[1]) $(19[2-])
|
||||
": "$(20[1]) $(20[2-]) ": "$(21[1]) $(21[2-]) ": "$(22[1]) $(22[2-])
|
||||
": "$(23[1]) $(23[2-]) ": "$(24[1]) $(24[2-]) ": "$(25[1]) $(25[2-]) ;
|
||||
}
|
||||
""")
|
||||
|
||||
test_args(t, "", "* missing argument a", status=1)
|
||||
test_args(t, "1 2 : 3 : 4 : 5", "* extra argument 5", status=1)
|
||||
test_args(t, "a b c1 c2 : d", "* extra argument c2", status=1)
|
||||
|
||||
# Check modifier '?'
|
||||
test_args(t, "1 2 3 : 4", "a= 1 b= 2 c= 3 : d= 4 : e=")
|
||||
test_args(t, "1 2 : 3", "a= 1 b= 2 c= : d= 3 : e=")
|
||||
test_args(t, "1 2 : 3", "a= 1 b= 2 c= : d= 3 : e=")
|
||||
test_args(t, "1 : 2", "a= 1 b= c= : d= 2 : e=")
|
||||
|
||||
# Check modifier '+'
|
||||
test_args(t, "1", "* missing argument d", status=1)
|
||||
test_args(t, "1 : 2 3", "a= 1 b= c= : d= 2 3 : e=")
|
||||
test_args(t, "1 : 2 3 4", "a= 1 b= c= : d= 2 3 4 : e=")
|
||||
|
||||
# Check modifier '*'
|
||||
test_args(t, "1 : 2 : 3", "a= 1 b= c= : d= 2 : e= 3")
|
||||
test_args(t, "1 : 2 : 3 4", "a= 1 b= c= : d= 2 : e= 3 4")
|
||||
test_args(t, "1 : 2 : 3 4 5", "a= 1 b= c= : d= 2 : e= 3 4 5")
|
||||
|
||||
# Check varargs
|
||||
test_varargs(t, "1 : 2 : 3 4 5", "a= 1 b= c= : d= 2 : e= 3 4 5")
|
||||
test_varargs(t, "1 : 2 : 3 4 5 : 6", "a= 1 b= c= : d= 2 : e= 3 4 5 : rest= 6")
|
||||
test_varargs(t, "1 : 2 : 3 4 5 : 6 7",
|
||||
"a= 1 b= c= : d= 2 : e= 3 4 5 : rest= 6 7")
|
||||
test_varargs(t, "1 : 2 : 3 4 5 : 6 7 : 8",
|
||||
"a= 1 b= c= : d= 2 : e= 3 4 5 : rest= 6 7 : 8")
|
||||
test_varargs(t, "1 : 2 : 3 4 5 : 6 7 : 8 : 9",
|
||||
"a= 1 b= c= : d= 2 : e= 3 4 5 : rest= 6 7 : 8 : 9")
|
||||
test_varargs(t, "1 : 2 : 3 4 5 : 6 7 : 8 : 9 : 10 : 11 : 12 : 13 : 14 : 15 : "
|
||||
"16 : 17 : 18 : 19a 19b", "a= 1 b= c= : d= 2 : e= 3 4 5 : rest= 6 7 : 8 : "
|
||||
"9 : 10 : 11 : 12 : 13 : 14 : 15 : 16 : 17 : 18 : 19a 19b")
|
||||
test_varargs(t, "1 : 2 : 3 4 5 : 6 7 : 8 : 9 : 10 : 11 : 12 : 13 : 14 : 15 : "
|
||||
"16 : 17 : 18 : 19a 19b 19c : 20", "a= 1 b= c= : d= 2 : e= 3 4 5 : rest= "
|
||||
"6 7 : 8 : 9 : 10 : 11 : 12 : 13 : 14 : 15 : 16 : 17 : 18 : 19a 19b 19c : "
|
||||
"20")
|
||||
|
||||
# Check varargs upper limit
|
||||
expected = "a= 1 b= c= : d= 2 : e= 3 : rest= " + simple_args(4, 19)
|
||||
test_varargs(t, simple_args(1, 19), expected)
|
||||
test_varargs(t, simple_args(1, 19) + " 19b 19c 19d", expected + " 19b 19c 19d")
|
||||
test_varargs(t, simple_args(1, 19) + " 19b 19c 19d : 20", expected + " 19b "
|
||||
"19c 19d")
|
||||
test_varargs(t, simple_args(1, 20), expected)
|
||||
test_varargs(t, simple_args(1, 50), expected)
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2011 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
|
||||
|
||||
t = BoostBuild.Tester(["-ffile.jam"], pass_toolset=0)
|
||||
|
||||
t.write("file.jam", """\
|
||||
name = n1 n2 ;
|
||||
contents = M1 M2 ;
|
||||
EXIT file: "@(o$(name) .txt:E= test -D$(contents))" : 0 ;
|
||||
""")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_output_lines("file: on1 on2 .txt");
|
||||
t.expect_addition("on1 on2 .txt")
|
||||
t.expect_content("on1 on2 .txt", " test -DM1 -DM2", True)
|
||||
|
||||
t.rm(".")
|
||||
|
||||
t.write("file.jam", """\
|
||||
name = n1 n2 ;
|
||||
contents = M1 M2 ;
|
||||
actions run { echo file: "@(o$(name) .txt:E= test -D$(contents))" }
|
||||
run all ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-d2"])
|
||||
t.expect_output_lines(' echo file: "on1 on2 .txt" ');
|
||||
t.expect_addition("on1 on2 .txt")
|
||||
t.expect_content("on1 on2 .txt", " test -DM1 -DM2", True)
|
||||
|
||||
t.rm(".")
|
||||
|
||||
t.write("file.jam", """\
|
||||
name = n1 n2 ;
|
||||
contents = M1 M2 ;
|
||||
file = "@($(STDOUT):E= test -D$(contents)\n)" ;
|
||||
actions run { $(file) }
|
||||
run all ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-d1"])
|
||||
t.expect_output_lines(" test -DM1 -DM2")
|
||||
|
||||
t.rm(".")
|
||||
|
||||
t.write("file.jam", """\
|
||||
name = n1 n2 ;
|
||||
contents = M1 M2 ;
|
||||
actions run { @($(STDOUT):E= test -D$(contents)\n) }
|
||||
run all ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-d1"])
|
||||
t.expect_output_lines(" test -DM1 -DM2")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2001 Dave Abrahams
|
||||
# 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
|
||||
import os
|
||||
|
||||
t = BoostBuild.Tester(pass_toolset=0, pass_d0=False)
|
||||
|
||||
t.write("subdir1/file-to-bind", "# This file intentionally left blank")
|
||||
|
||||
t.write("file.jam", """\
|
||||
rule do-nothing ( target : source )
|
||||
{
|
||||
DEPENDS $(target) : $(source) ;
|
||||
}
|
||||
actions quietly do-nothing { }
|
||||
|
||||
# Make a non-file target which depends on a file that exists
|
||||
NOTFILE fake-target ;
|
||||
SEARCH on file-to-bind = subdir1 ;
|
||||
|
||||
do-nothing fake-target : file-to-bind ;
|
||||
|
||||
# Set jam up to call our bind-rule
|
||||
BINDRULE = bind-rule ;
|
||||
|
||||
rule bind-rule ( target : path )
|
||||
{
|
||||
ECHO found: $(target) at $(path) ;
|
||||
}
|
||||
|
||||
DEPENDS all : fake-target ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-ffile.jam"], stdout="""\
|
||||
found: all at all
|
||||
found: file-to-bind at subdir1%sfile-to-bind
|
||||
...found 3 targets...
|
||||
""" % os.sep)
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2002, 2003 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)
|
||||
|
||||
# This tests correct handling of "-d1" and "-d2" options.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(["-ffile.jam"], pass_d0=False, pass_toolset=0)
|
||||
|
||||
t.write("file.jam", """\
|
||||
actions a { }
|
||||
actions quietly b { }
|
||||
ALWAYS all ;
|
||||
a all ;
|
||||
b all ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-d0"], stdout="")
|
||||
|
||||
t.run_build_system(["-d1"])
|
||||
t.expect_output_lines("a all")
|
||||
t.expect_output_lines("b all", False)
|
||||
|
||||
t.run_build_system(["-d2"])
|
||||
t.expect_output_lines("a all")
|
||||
t.expect_output_lines("b all")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2003 Dave Abrahams
|
||||
# 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 facilities for deleting modules.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(pass_toolset=0)
|
||||
|
||||
t.write("file.jam", """
|
||||
module foo
|
||||
{
|
||||
rule bar { }
|
||||
var = x y ;
|
||||
}
|
||||
DELETE_MODULE foo ;
|
||||
if [ RULENAMES foo ]
|
||||
{
|
||||
EXIT DELETE_MODULE failed to kill foo's rules: [ RULENAMES foo ] ;
|
||||
}
|
||||
|
||||
module foo
|
||||
{
|
||||
if $(var)
|
||||
{
|
||||
EXIT DELETE_MODULE failed to kill foo's variables ;
|
||||
}
|
||||
|
||||
rule bar { }
|
||||
var = x y ;
|
||||
|
||||
DELETE_MODULE foo ;
|
||||
|
||||
if $(var)
|
||||
{
|
||||
EXIT internal DELETE_MODULE failed to kill foo's variables ;
|
||||
}
|
||||
if [ RULENAMES foo ]
|
||||
{
|
||||
EXIT internal DELETE_MODULE failed to kill foo's rules: [ RULENAMES foo ] ;
|
||||
}
|
||||
}
|
||||
DEPENDS all : xx ;
|
||||
NOTFILE xx ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-ffile.jam"], status=0)
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,157 @@
|
||||
#!/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 correct handling of dependencies, specifically, on generated
|
||||
# sources, and from generated sources.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
import string
|
||||
|
||||
t = BoostBuild.Tester(pass_toolset=0)
|
||||
|
||||
t.write("core-dependency-helpers", """
|
||||
rule hdrrule
|
||||
{
|
||||
INCLUDES $(1) : $(2) ;
|
||||
}
|
||||
actions copy
|
||||
{
|
||||
cp $(>) $(<)
|
||||
}
|
||||
""")
|
||||
|
||||
code = """include core-dependency-helpers ;
|
||||
DEPENDS all : a ;
|
||||
DEPENDS a : b ;
|
||||
|
||||
actions create-b
|
||||
{
|
||||
echo '#include <foo.h>' > $(<)
|
||||
}
|
||||
copy a : b ;
|
||||
create-b b ;
|
||||
HDRRULE on b foo.h bar.h = hdrrule ;
|
||||
HDRSCAN on b foo.h bar.h = \"#include <(.*)>\" ;
|
||||
"""
|
||||
|
||||
# This creates 'a' which depends on 'b', which is generated. The generated 'b'
|
||||
# contains '#include <foo.h>' and no rules for foo.h are given. The system
|
||||
# should error out on the first invocation.
|
||||
t.run_build_system("-f-", stdin=code)
|
||||
t.fail_test(string.find(t.stdout(), "...skipped a for lack of foo.h...") == -1)
|
||||
|
||||
t.rm('b')
|
||||
|
||||
# Now test that if target 'c' also depends on 'b', then it will not be built, as
|
||||
# well.
|
||||
t.run_build_system("-f-", stdin=code + " copy c : b ; DEPENDS c : b ; DEPENDS all : c ; ")
|
||||
t.fail_test(string.find(t.stdout(), "...skipped c for lack of foo.h...") == -1)
|
||||
|
||||
t.rm('b')
|
||||
|
||||
# Now add a rule for creating foo.h.
|
||||
code += """
|
||||
actions create-foo
|
||||
{
|
||||
echo // > $(<)
|
||||
}
|
||||
create-foo foo.h ;
|
||||
"""
|
||||
t.run_build_system("-f-", stdin=code)
|
||||
|
||||
# Run two times, adding explicit dependency from all to foo.h at the beginning
|
||||
# and at the end, to make sure that foo.h is generated before 'a' in all cases.
|
||||
|
||||
def mk_correct_order_func(s1, s2):
|
||||
def correct_order(s):
|
||||
n1 = string.find(s, s1)
|
||||
n2 = string.find(s, s2)
|
||||
return ( n1 != -1 ) and ( n2 != -1 ) and ( n1 < n2 )
|
||||
return correct_order
|
||||
|
||||
correct_order = mk_correct_order_func("create-foo", "copy a")
|
||||
|
||||
t.rm(["a", "b", "foo.h"])
|
||||
t.run_build_system("-d+2 -f-", stdin=code + " DEPENDS all : foo.h ;")
|
||||
t.fail_test(not correct_order(t.stdout()))
|
||||
|
||||
t.rm(["a", "b", "foo.h"])
|
||||
t.run_build_system("-d+2 -f-", stdin=" DEPENDS all : foo.h ; " + code)
|
||||
t.fail_test(not correct_order(t.stdout()))
|
||||
|
||||
# Now foo.h exists. Test include from b -> foo.h -> bar.h -> biz.h. b and foo.h
|
||||
# already have updating actions.
|
||||
t.rm(["a", "b"])
|
||||
t.write("foo.h", "#include <bar.h>")
|
||||
t.write("bar.h", "#include <biz.h>")
|
||||
t.run_build_system("-d+2 -f-", stdin=code)
|
||||
t.fail_test(string.find(t.stdout(), "...skipped a for lack of biz.h...") == -1)
|
||||
|
||||
# Add an action for biz.h.
|
||||
code += """
|
||||
actions create-biz
|
||||
{
|
||||
echo // > $(<)
|
||||
}
|
||||
create-biz biz.h ;
|
||||
"""
|
||||
|
||||
t.rm(["b"])
|
||||
correct_order = mk_correct_order_func("create-biz", "copy a")
|
||||
t.run_build_system("-d+2 -f-", stdin=code + " DEPENDS all : biz.h ;")
|
||||
t.fail_test(not correct_order(t.stdout()))
|
||||
|
||||
t.rm(["a", "biz.h"])
|
||||
t.run_build_system("-d+2 -f-", stdin=" DEPENDS all : biz.h ; " + code)
|
||||
t.fail_test(not correct_order(t.stdout()))
|
||||
|
||||
t.write("a", "")
|
||||
|
||||
code="""
|
||||
DEPENDS all : main d ;
|
||||
|
||||
actions copy
|
||||
{
|
||||
cp $(>) $(<) ;
|
||||
}
|
||||
|
||||
DEPENDS main : a ;
|
||||
copy main : a ;
|
||||
|
||||
INCLUDES a : <1>c ;
|
||||
|
||||
NOCARE <1>c ;
|
||||
SEARCH on <1>c = . ;
|
||||
|
||||
actions create-c
|
||||
{
|
||||
echo d > $(<)
|
||||
}
|
||||
|
||||
actions create-d
|
||||
{
|
||||
echo // > $(<)
|
||||
}
|
||||
|
||||
create-c <2>c ;
|
||||
LOCATE on <2>c = . ;
|
||||
create-d d ;
|
||||
|
||||
HDRSCAN on <1>c = (.*) ;
|
||||
HDRRULE on <1>c = hdrrule ;
|
||||
|
||||
rule hdrrule
|
||||
{
|
||||
INCLUDES $(1) : d ;
|
||||
}
|
||||
"""
|
||||
|
||||
correct_order = mk_correct_order_func("create-d", "copy main")
|
||||
t.run_build_system("-d2 -f-", stdin=code)
|
||||
t.fail_test(not correct_order(t.stdout()))
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2003 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
|
||||
|
||||
t = BoostBuild.Tester(pass_toolset=0)
|
||||
|
||||
t.write("code", """\
|
||||
module a
|
||||
{
|
||||
rule r1 ( )
|
||||
{
|
||||
ECHO R1 ;
|
||||
}
|
||||
|
||||
local rule l1 ( )
|
||||
{
|
||||
ECHO A.L1 ;
|
||||
}
|
||||
}
|
||||
module a2
|
||||
{
|
||||
rule r2 ( )
|
||||
{
|
||||
ECHO R2 ;
|
||||
}
|
||||
}
|
||||
IMPORT a2 : r2 : : a2.r2 ;
|
||||
|
||||
rule a.l1 ( )
|
||||
{
|
||||
ECHO L1 ;
|
||||
}
|
||||
|
||||
module b
|
||||
{
|
||||
IMPORT_MODULE a : b ;
|
||||
rule test
|
||||
{
|
||||
# Call rule visible via IMPORT_MODULE
|
||||
a.r1 ;
|
||||
# Call rule in global scope
|
||||
a2.r2 ;
|
||||
# Call rule in global scope. Doesn't find local rule
|
||||
a.l1 ;
|
||||
# Make l1 visible
|
||||
EXPORT a : l1 ;
|
||||
a.l1 ;
|
||||
}
|
||||
}
|
||||
|
||||
IMPORT b : test : : test ;
|
||||
test ;
|
||||
|
||||
module c
|
||||
{
|
||||
rule test
|
||||
{
|
||||
ECHO CTEST ;
|
||||
}
|
||||
}
|
||||
|
||||
IMPORT_MODULE c : ;
|
||||
c.test ;
|
||||
|
||||
actions do-nothing { }
|
||||
do-nothing all ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-fcode"], stdout="""\
|
||||
R1
|
||||
R2
|
||||
L1
|
||||
A.L1
|
||||
CTEST
|
||||
""")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2014 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
|
||||
import sys
|
||||
|
||||
t = BoostBuild.Tester(pass_toolset=False, pass_d0=False)
|
||||
|
||||
t.write("file.jam", """
|
||||
actions run {
|
||||
$(ACTION)
|
||||
}
|
||||
|
||||
# Raw commands only work on Windows
|
||||
if $(OS) = NT
|
||||
{
|
||||
JAMSHELL on test-raw = % ;
|
||||
JAMSHELL on test-raw-fail = % ;
|
||||
}
|
||||
ACTION on test-raw = "\"$(PYTHON)\" -V" ;
|
||||
run test-raw ;
|
||||
|
||||
ACTION on test-raw-fail = missing-executable ;
|
||||
run test-raw-fail ;
|
||||
|
||||
# On Windows, the command is stored in a temporary
|
||||
# file. On other systems it is passed directly.
|
||||
if $(OS) = NT
|
||||
{
|
||||
JAMSHELL on test-py = $(PYTHON) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
JAMSHELL on test-py = $(PYTHON) -c ;
|
||||
}
|
||||
ACTION on test-py = "
|
||||
print \\\",\\\".join([str(x) for x in range(3)])
|
||||
" ;
|
||||
run test-py ;
|
||||
|
||||
DEPENDS all : test-raw test-raw-fail test-py ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-ffile.jam", "-d1", "-sPYTHON=" + sys.executable], status=1)
|
||||
t.expect_output_lines([
|
||||
"...failed run test-raw-fail...",
|
||||
"0,1,2",
|
||||
"...failed updating 1 target...",
|
||||
"...updated 2 targets..."])
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# 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)
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(pass_toolset=0)
|
||||
t.set_tree("core-language")
|
||||
t.run_build_system(["-ftest.jam"])
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,51 @@
|
||||
#!/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 "existing" and "updated" modifiers on actions.
|
||||
|
||||
import BoostBuild
|
||||
import string
|
||||
|
||||
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 ;
|
||||
"""
|
||||
|
||||
t.write("file.jam", code)
|
||||
t.write("a-1", "")
|
||||
|
||||
t.run_build_system("-ffile.jam")
|
||||
t.fail_test(string.strip(t.read("list")) != "a-1")
|
||||
t.rm(["a-3", "list"])
|
||||
|
||||
code = string.replace(code, "existing", "updated")
|
||||
t.write("file.jam", code)
|
||||
t.run_build_system("-ffile.jam")
|
||||
t.fail_test(string.strip(t.read("list")) != "a-3")
|
||||
|
||||
code = string.replace(code, "updated", "existing updated")
|
||||
t.write("file.jam", code)
|
||||
t.run_build_system("-ffile.jam")
|
||||
t.fail_test(string.strip(t.read("list")) != "a-1 a-3")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,202 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2013 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)
|
||||
|
||||
# Tests that actions that produce multiple targets are handled
|
||||
# correctly. The rules are as follows:
|
||||
#
|
||||
# - If any action that updates a target is run, then the target
|
||||
# is considered to be out-of-date and all of its updating actions
|
||||
# are run in order.
|
||||
# - A target is considered updated when all of its updating actions
|
||||
# have completed successfully.
|
||||
# - If any updating action for a target fails, then the remaining
|
||||
# actions are skipped and the target is marked as failed.
|
||||
#
|
||||
# Note that this is a more thorough test case for the same
|
||||
# problem that core_parallel_multifile_actions_N.py checks for.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(pass_toolset=0, pass_d0=False)
|
||||
|
||||
t.write("file.jam", """
|
||||
actions update
|
||||
{
|
||||
echo updating $(<)
|
||||
}
|
||||
|
||||
update x1 x2 ;
|
||||
update x2 x3 ;
|
||||
""")
|
||||
|
||||
# Updating x1 should force x2 to update as well.
|
||||
t.run_build_system(["-ffile.jam", "x1"], stdout="""\
|
||||
...found 3 targets...
|
||||
...updating 3 targets...
|
||||
update x1
|
||||
updating x1 x2
|
||||
update x2
|
||||
updating x2 x3
|
||||
...updated 3 targets...
|
||||
""")
|
||||
|
||||
# If x1 is up-to-date, we don't need to update x2,
|
||||
# even though x2 is missing.
|
||||
t.write("x1", "")
|
||||
t.run_build_system(["-ffile.jam", "x1"], stdout="""\
|
||||
...found 1 target...
|
||||
""")
|
||||
|
||||
# Building x3 should update x1 and x2, even though
|
||||
# x1 would be considered up-to-date, taken alone.
|
||||
t.run_build_system(["-ffile.jam", "x3"], stdout="""\
|
||||
...found 3 targets...
|
||||
...updating 2 targets...
|
||||
update x1
|
||||
updating x1 x2
|
||||
update x2
|
||||
updating x2 x3
|
||||
...updated 3 targets...
|
||||
""")
|
||||
|
||||
# Updating x2 should succeed, but x3 should be skipped
|
||||
t.rm("x1")
|
||||
t.write("file.jam", """\
|
||||
actions update
|
||||
{
|
||||
echo updating $(<)
|
||||
}
|
||||
actions fail
|
||||
{
|
||||
echo failed $(<)
|
||||
exit 1
|
||||
}
|
||||
|
||||
update x1 x2 ;
|
||||
fail x1 ;
|
||||
update x1 x3 ;
|
||||
update x2 ;
|
||||
update x3 ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-ffile.jam", "x3"], status=1, stdout="""\
|
||||
...found 3 targets...
|
||||
...updating 3 targets...
|
||||
update x1
|
||||
updating x1 x2
|
||||
fail x1
|
||||
failed x1
|
||||
|
||||
echo failed x1
|
||||
exit 1
|
||||
|
||||
...failed fail x1...
|
||||
update x2
|
||||
updating x2
|
||||
...failed updating 2 targets...
|
||||
...updated 1 target...
|
||||
""")
|
||||
|
||||
# Make sure that dependencies of targets that are
|
||||
# updated as a result of a multifile action are
|
||||
# processed correctly.
|
||||
t.rm("x1")
|
||||
t.write("file.jam", """\
|
||||
actions update
|
||||
{
|
||||
echo updating $(<)
|
||||
}
|
||||
|
||||
update x1 ;
|
||||
update x2 ;
|
||||
DEPENDS x2 : x1 ;
|
||||
update x2 x3 ;
|
||||
""")
|
||||
t.run_build_system(["-ffile.jam", "x3"], stdout="""\
|
||||
...found 3 targets...
|
||||
...updating 3 targets...
|
||||
update x1
|
||||
updating x1
|
||||
update x2
|
||||
updating x2
|
||||
update x2
|
||||
updating x2 x3
|
||||
...updated 3 targets...
|
||||
""")
|
||||
|
||||
# JAM_SEMAPHORE rules:
|
||||
#
|
||||
# - if two updating actions have targets that share a semaphore,
|
||||
# these actions cannot be run in parallel.
|
||||
#
|
||||
t.write("file.jam", """\
|
||||
actions update
|
||||
{
|
||||
echo updating $(<)
|
||||
}
|
||||
|
||||
targets = x1 x2 ;
|
||||
JAM_SEMAPHORE on $(targets) = <s>update_sem ;
|
||||
update x1 x2 ;
|
||||
""")
|
||||
t.run_build_system(["-ffile.jam", "x1"], stdout="""\
|
||||
...found 2 targets...
|
||||
...updating 2 targets...
|
||||
update x1
|
||||
updating x1 x2
|
||||
...updated 2 targets...
|
||||
""")
|
||||
|
||||
# A target can appear multiple times in an action
|
||||
t.write("file.jam", """\
|
||||
actions update
|
||||
{
|
||||
echo updating $(<)
|
||||
}
|
||||
|
||||
update x1 x1 ;
|
||||
""")
|
||||
t.run_build_system(["-ffile.jam", "x1"], stdout="""\
|
||||
...found 1 target...
|
||||
...updating 1 target...
|
||||
update x1
|
||||
updating x1 x1
|
||||
...updated 1 target...
|
||||
""")
|
||||
|
||||
# Together actions should check that all the targets are the same
|
||||
# before combining.
|
||||
t.write("file.jam", """\
|
||||
actions together update
|
||||
{
|
||||
echo updating $(<) : $(>)
|
||||
}
|
||||
|
||||
update x1 x2 : s1 ;
|
||||
update x1 x2 : s2 ;
|
||||
|
||||
update x3 : s3 ;
|
||||
update x3 x4 : s4 ;
|
||||
update x4 x3 : s5 ;
|
||||
DEPENDS all : x1 x2 x3 x4 ;
|
||||
""")
|
||||
t.run_build_system(["-ffile.jam"], stdout="""\
|
||||
...found 5 targets...
|
||||
...updating 4 targets...
|
||||
update x1
|
||||
updating x1 x2 : s1 s2
|
||||
update x3
|
||||
updating x3 : s3
|
||||
update x3
|
||||
updating x3 x4 : s4
|
||||
update x4
|
||||
updating x4 x3 : s5
|
||||
...updated 4 targets...
|
||||
""")
|
||||
|
||||
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,266 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2001 Dave Abrahams
|
||||
# Copyright 2011 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)
|
||||
|
||||
# Tests Windows command line construction.
|
||||
#
|
||||
# Note that the regular 'echo' is an internal shell command on Windows and
|
||||
# therefore can not be called directly as a standalone Windows process.
|
||||
|
||||
import BoostBuild
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
executable = sys.executable.replace("\\", "/")
|
||||
if " " in executable:
|
||||
executable = '"%s"' % executable
|
||||
|
||||
|
||||
def string_of_length(n):
|
||||
if n <= 0:
|
||||
return ""
|
||||
n -= 1
|
||||
y = ['', '$(1x10-1)', '$(10x10-1)', '$(100x10-1)', '$(1000x10-1)']
|
||||
result = []
|
||||
for i in reversed(xrange(5)):
|
||||
x, n = divmod(n, 10 ** i)
|
||||
result += [y[i]] * x
|
||||
result.append('x')
|
||||
return " ".join(result)
|
||||
|
||||
|
||||
# Boost Jam currently does not allow preparing actions with completely empty
|
||||
# content and always requires at least a single whitespace after the opening
|
||||
# brace in order to satisfy its Boost Jam language grammar rules.
|
||||
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 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()
|
||||
|
||||
|
||||
def test_raw_to_shell_fallback_nt():
|
||||
t = BoostBuild.Tester(["-d1", "-d+4"], pass_d0=False, pass_toolset=0,
|
||||
use_test_config=False)
|
||||
|
||||
cmd_prefix = '%s -c print(' % executable
|
||||
cmd_suffix = ')'
|
||||
|
||||
t.write("file_multiline.jam", """\
|
||||
actions do_multiline
|
||||
{
|
||||
echo one
|
||||
|
||||
|
||||
echo two
|
||||
}
|
||||
JAMSHELL = % ;
|
||||
do_multiline all ;
|
||||
""")
|
||||
t.run_build_system(["-ffile_multiline.jam"])
|
||||
t.expect_output_lines("do_multiline all")
|
||||
t.expect_output_lines("one")
|
||||
t.expect_output_lines("two")
|
||||
t.expect_output_lines("Executing raw command directly", False)
|
||||
t.expect_output_lines("Executing using a command file and the shell: "
|
||||
"cmd.exe /Q/C")
|
||||
|
||||
t.write("file_redirect.jam", """\
|
||||
actions do_redirect { echo one > two.txt }
|
||||
JAMSHELL = % ;
|
||||
do_redirect all ;
|
||||
""")
|
||||
t.run_build_system(["-ffile_redirect.jam"])
|
||||
t.expect_output_lines("do_redirect all")
|
||||
t.expect_output_lines("one", False)
|
||||
t.expect_output_lines("Executing raw command directly", False)
|
||||
t.expect_output_lines("Executing using a command file and the shell: "
|
||||
"cmd.exe /Q/C")
|
||||
t.expect_addition("two.txt")
|
||||
|
||||
t.write("file_pipe.jam", """\
|
||||
actions do_pipe
|
||||
{
|
||||
echo one | echo two
|
||||
}
|
||||
JAMSHELL = % ;
|
||||
do_pipe all ;
|
||||
""")
|
||||
t.run_build_system(["-ffile_pipe.jam"])
|
||||
t.expect_output_lines("do_pipe all")
|
||||
t.expect_output_lines("one*", False)
|
||||
t.expect_output_lines("two")
|
||||
t.expect_output_lines("Executing raw command directly", False)
|
||||
t.expect_output_lines("Executing using a command file and the shell: "
|
||||
"cmd.exe /Q/C")
|
||||
|
||||
t.write("file_single_quoted.jam", """\
|
||||
actions do_single_quoted { %s'5>10'%s }
|
||||
JAMSHELL = %% ;
|
||||
do_single_quoted all ;
|
||||
""" % (cmd_prefix, cmd_suffix))
|
||||
t.run_build_system(["-ffile_single_quoted.jam"])
|
||||
t.expect_output_lines("do_single_quoted all")
|
||||
t.expect_output_lines("5>10")
|
||||
t.expect_output_lines("Executing raw command directly")
|
||||
t.expect_output_lines("Executing using a command file and the shell: "
|
||||
"cmd.exe /Q/C", False)
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.write("file_double_quoted.jam", """\
|
||||
actions do_double_quoted { %s"5>10"%s }
|
||||
JAMSHELL = %% ;
|
||||
do_double_quoted all ;
|
||||
""" % (cmd_prefix, cmd_suffix))
|
||||
t.run_build_system(["-ffile_double_quoted.jam"])
|
||||
t.expect_output_lines("do_double_quoted all")
|
||||
# The difference between this example and the similar previous one using
|
||||
# single instead of double quotes stems from how the used Python executable
|
||||
# parses the command-line string received from Windows.
|
||||
t.expect_output_lines("False")
|
||||
t.expect_output_lines("Executing raw command directly")
|
||||
t.expect_output_lines("Executing using a command file and the shell: "
|
||||
"cmd.exe /Q/C", False)
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.write("file_escaped_quote.jam", """\
|
||||
actions do_escaped_quote { %s\\"5>10\\"%s }
|
||||
JAMSHELL = %% ;
|
||||
do_escaped_quote all ;
|
||||
""" % (cmd_prefix, cmd_suffix))
|
||||
t.run_build_system(["-ffile_escaped_quote.jam"])
|
||||
t.expect_output_lines("do_escaped_quote all")
|
||||
t.expect_output_lines("5>10")
|
||||
t.expect_output_lines("Executing raw command directly", False)
|
||||
t.expect_output_lines("Executing using a command file and the shell: "
|
||||
"cmd.exe /Q/C")
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# main()
|
||||
# ------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
if os.name == 'nt':
|
||||
test_raw_empty()
|
||||
|
||||
# Can not test much shorter lengths as the shortest possible command line
|
||||
# line length constructed in this depends on the runtime environment, e.g.
|
||||
# path to the Panther executable running this test.
|
||||
test_raw_nt()
|
||||
test_raw_nt(255)
|
||||
test_raw_nt(1000)
|
||||
test_raw_nt(8000)
|
||||
test_raw_nt(8191)
|
||||
test_raw_nt(8192)
|
||||
test_raw_nt(10000)
|
||||
test_raw_nt(30000)
|
||||
test_raw_nt(32766)
|
||||
# CreateProcessA() Windows API places a limit of 32768 on the allowed
|
||||
# command-line length, including a trailing Unicode (2-byte) nul-terminator
|
||||
# character.
|
||||
test_raw_nt(32767, error=True)
|
||||
test_raw_nt(40000, error=True)
|
||||
test_raw_nt(100001, error=True)
|
||||
|
||||
test_raw_to_shell_fallback_nt()
|
||||
@@ -0,0 +1,55 @@
|
||||
#!/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 ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-ffile.jam", "-d2"], stdout="""\
|
||||
...found 4 targets...
|
||||
...updating 2 targets...
|
||||
.a. subtest_a
|
||||
|
||||
echo [subtest_a] 0
|
||||
echo [subtest_a] 1
|
||||
echo [subtest_a] 2
|
||||
|
||||
[subtest_a] 0
|
||||
[subtest_a] 1
|
||||
[subtest_a] 2
|
||||
.a. subtest_b
|
||||
|
||||
echo [subtest_b] 0
|
||||
echo [subtest_b] 1
|
||||
echo [subtest_b] 2
|
||||
|
||||
[subtest_b] 0
|
||||
[subtest_b] 1
|
||||
[subtest_b] 2
|
||||
...updated 2 targets...
|
||||
""")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/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 copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(pass_toolset=0)
|
||||
|
||||
t.write("sleep.bat", """\
|
||||
::@timeout /T %1 /NOBREAK >nul
|
||||
@ping 127.0.0.1 -n 2 -w 1000 >nul
|
||||
@ping 127.0.0.1 -n %1 -w 1000 >nul
|
||||
@exit /B 0
|
||||
""")
|
||||
|
||||
t.write("file.jam", """\
|
||||
if $(NT)
|
||||
{
|
||||
SLEEP = @call sleep.bat ;
|
||||
}
|
||||
else
|
||||
{
|
||||
SLEEP = sleep ;
|
||||
}
|
||||
|
||||
actions .a. {
|
||||
echo 001
|
||||
$(SLEEP) 4
|
||||
echo 002
|
||||
}
|
||||
|
||||
.a. sleeper ;
|
||||
|
||||
DEPENDS all : sleeper ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-ffile.jam", "-d1", "-l2"], status=1)
|
||||
t.expect_output_lines("2 second time limit exceeded")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,51 @@
|
||||
#!/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 ;
|
||||
FAIL_EXPECTED subtest_b ;
|
||||
DEPENDS all : subtest_a subtest_b ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-ffile.jam", "-n"], stdout="""\
|
||||
...found 4 targets...
|
||||
...updating 2 targets...
|
||||
.a. subtest_a
|
||||
|
||||
echo [subtest_a] 0
|
||||
echo [subtest_a] 1
|
||||
echo [subtest_a] 2
|
||||
|
||||
.a. subtest_b
|
||||
|
||||
echo [subtest_b] 0
|
||||
echo [subtest_b] 1
|
||||
echo [subtest_b] 2
|
||||
|
||||
...updated 2 targets...
|
||||
""")
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2006 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("sleep.bat", """\
|
||||
::@timeout /T %1 /NOBREAK >nul
|
||||
@ping 127.0.0.1 -n 2 -w 1000 >nul
|
||||
@ping 127.0.0.1 -n %1 -w 1000 >nul
|
||||
@exit /B 0
|
||||
""")
|
||||
|
||||
t.write("file.jam", """\
|
||||
if $(NT)
|
||||
{
|
||||
actions sleeper
|
||||
{
|
||||
echo [$(<:S)] 0
|
||||
call sleep.bat 1
|
||||
echo [$(<:S)] 1
|
||||
call sleep.bat 1
|
||||
echo [$(<:S)] 2
|
||||
call sleep.bat $(<:B)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
actions sleeper
|
||||
{
|
||||
echo "[$(<:S)] 0"
|
||||
sleep 1
|
||||
echo "[$(<:S)] 1"
|
||||
sleep 1
|
||||
echo "[$(<:S)] 2"
|
||||
sleep $(<:B)
|
||||
}
|
||||
}
|
||||
|
||||
rule sleeper
|
||||
{
|
||||
DEPENDS $(<) : $(>) ;
|
||||
}
|
||||
|
||||
NOTFILE front ;
|
||||
sleeper 1.a : front ;
|
||||
sleeper 2.a : front ;
|
||||
sleeper 3.a : front ;
|
||||
sleeper 4.a : front ;
|
||||
NOTFILE choke ;
|
||||
DEPENDS choke : 1.a 2.a 3.a 4.a ;
|
||||
sleeper 1.b : choke ;
|
||||
sleeper 2.b : choke ;
|
||||
sleeper 3.b : choke ;
|
||||
sleeper 4.b : choke ;
|
||||
DEPENDS bottom : 1.b 2.b 3.b 4.b ;
|
||||
DEPENDS all : bottom ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-ffile.jam", "-j4"], stdout="""\
|
||||
...found 12 targets...
|
||||
...updating 8 targets...
|
||||
sleeper 1.a
|
||||
[.a] 0
|
||||
[.a] 1
|
||||
[.a] 2
|
||||
sleeper 2.a
|
||||
[.a] 0
|
||||
[.a] 1
|
||||
[.a] 2
|
||||
sleeper 3.a
|
||||
[.a] 0
|
||||
[.a] 1
|
||||
[.a] 2
|
||||
sleeper 4.a
|
||||
[.a] 0
|
||||
[.a] 1
|
||||
[.a] 2
|
||||
sleeper 1.b
|
||||
[.b] 0
|
||||
[.b] 1
|
||||
[.b] 2
|
||||
sleeper 2.b
|
||||
[.b] 0
|
||||
[.b] 1
|
||||
[.b] 2
|
||||
sleeper 3.b
|
||||
[.b] 0
|
||||
[.b] 1
|
||||
[.b] 2
|
||||
sleeper 4.b
|
||||
[.b] 0
|
||||
[.b] 1
|
||||
[.b] 2
|
||||
...updated 8 targets...
|
||||
""")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,78 @@
|
||||
#!/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)
|
||||
|
||||
# Added to guard against a bug causing targets to be used before they
|
||||
# themselves have finished building. This used to happen for targets built by a
|
||||
# multi-file action that got triggered by another target.
|
||||
#
|
||||
# Example:
|
||||
# When target A and target B were declared as created by a single action and
|
||||
# target A triggered running that action then, while the action was still
|
||||
# running, target B was already reporting as being built causing other targets
|
||||
# depending on target A to be built prematurely.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(pass_toolset=0, pass_d0=False)
|
||||
|
||||
t.write("sleep.bat", """\
|
||||
::@timeout /T %1 /NOBREAK >nul
|
||||
@ping 127.0.0.1 -n 2 -w 1000 >nul
|
||||
@ping 127.0.0.1 -n %1 -w 1000 >nul
|
||||
@exit /B 0
|
||||
""")
|
||||
|
||||
t.write("file.jam", """\
|
||||
if $(NT)
|
||||
{
|
||||
SLEEP = @call sleep.bat ;
|
||||
}
|
||||
else
|
||||
{
|
||||
SLEEP = sleep ;
|
||||
}
|
||||
|
||||
actions .gen.
|
||||
{
|
||||
echo 001
|
||||
$(SLEEP) 4
|
||||
echo 002
|
||||
}
|
||||
rule .use.1 { DEPENDS $(<) : $(>) ; }
|
||||
actions .use.1
|
||||
{
|
||||
echo 003
|
||||
}
|
||||
|
||||
rule .use.2 { DEPENDS $(<) : $(>) ; }
|
||||
actions .use.2
|
||||
{
|
||||
$(SLEEP) 1
|
||||
echo 004
|
||||
}
|
||||
|
||||
.gen. g1.generated g2.generated ;
|
||||
.use.1 u1.user : g1.generated ;
|
||||
.use.2 u2.user : g2.generated ;
|
||||
|
||||
DEPENDS all : u1.user u2.user ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-ffile.jam", "-j2"], stdout="""\
|
||||
...found 5 targets...
|
||||
...updating 4 targets...
|
||||
.gen. g1.generated
|
||||
001
|
||||
002
|
||||
.use.1 u1.user
|
||||
003
|
||||
.use.2 u2.user
|
||||
004
|
||||
...updated 4 targets...
|
||||
""")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2008 Jurko Gospodnetic, Vladimir Prus
|
||||
# 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)
|
||||
|
||||
# Added to guard against a bug causing targets to be used before they
|
||||
# themselves have finished building. This used to happen for targets built by a
|
||||
# multi-file action that got triggered by another target, except when the
|
||||
# target triggering the action was the first one in the list of targets
|
||||
# produced by that action.
|
||||
#
|
||||
# Example:
|
||||
# When target A and target B were declared as created by a single action with
|
||||
# A being the first one listed, and target B triggered running that action
|
||||
# then, while the action was still running, target A was already reporting as
|
||||
# being built causing other targets depending on target A to be built
|
||||
# prematurely.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(pass_toolset=0, pass_d0=False)
|
||||
|
||||
t.write("sleep.bat", """\
|
||||
::@timeout /T %1 /NOBREAK >nul
|
||||
@ping 127.0.0.1 -n 2 -w 1000 >nul
|
||||
@ping 127.0.0.1 -n %1 -w 1000 >nul
|
||||
@exit /B 0
|
||||
""")
|
||||
|
||||
t.write("file.jam", """\
|
||||
if $(NT)
|
||||
{
|
||||
SLEEP = @call sleep.bat ;
|
||||
}
|
||||
else
|
||||
{
|
||||
SLEEP = sleep ;
|
||||
}
|
||||
|
||||
actions link
|
||||
{
|
||||
$(SLEEP) 1
|
||||
echo 001 - linked
|
||||
}
|
||||
|
||||
link dll lib ;
|
||||
|
||||
actions install
|
||||
{
|
||||
echo 002 - installed
|
||||
}
|
||||
|
||||
install installed_dll : dll ;
|
||||
DEPENDS installed_dll : dll ;
|
||||
|
||||
DEPENDS all : lib installed_dll ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-ffile.jam", "-j2"], stdout="""\
|
||||
...found 4 targets...
|
||||
...updating 3 targets...
|
||||
link dll
|
||||
001 - linked
|
||||
install installed_dll
|
||||
002 - installed
|
||||
...updated 3 targets...
|
||||
""")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,74 @@
|
||||
#!/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 Boost Jam parser's source line tracking & reporting.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
|
||||
def test_eof_in_string():
|
||||
t = BoostBuild.Tester(pass_toolset=False)
|
||||
t.write("file.jam", '\n\n\naaa = "\n\n\n\n\n\n')
|
||||
t.run_build_system(["-ffile.jam"], status=1)
|
||||
t.expect_output_lines('file.jam:4: unmatched " in string at keyword =')
|
||||
t.expect_output_lines("file.jam:4: syntax error at EOF")
|
||||
t.cleanup()
|
||||
|
||||
|
||||
def test_error_missing_argument(eof):
|
||||
"""
|
||||
This use case used to cause a missing argument error to be reported in
|
||||
module '(builtin)' in line -1 when the input file did not contain a
|
||||
trailing newline.
|
||||
|
||||
"""
|
||||
t = BoostBuild.Tester(pass_toolset=False)
|
||||
t.write("file.jam", """\
|
||||
rule f ( param ) { }
|
||||
f ;%s""" % __trailing_newline(eof))
|
||||
t.run_build_system(["-ffile.jam"], status=1)
|
||||
t.expect_output_lines("file.jam:2: in module scope")
|
||||
t.expect_output_lines("file.jam:1:see definition of rule 'f' being called")
|
||||
t.cleanup()
|
||||
|
||||
|
||||
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()
|
||||
|
||||
|
||||
def test_traceback():
|
||||
t = BoostBuild.Tester(pass_toolset=False)
|
||||
t.write("file.jam", """\
|
||||
NOTFILE all ;
|
||||
ECHO [ BACKTRACE ] ;""")
|
||||
t.run_build_system(["-ffile.jam"])
|
||||
t.expect_output_lines("file.jam 2 module scope")
|
||||
t.cleanup()
|
||||
|
||||
|
||||
def __trailing_newline(eof):
|
||||
"""
|
||||
Helper function returning an empty string or a newling character to
|
||||
append to the current output line depending on whether we want that line to
|
||||
be the last line in the file (eof == True) or not (eof == False).
|
||||
|
||||
"""
|
||||
if eof:
|
||||
return ""
|
||||
return "\n"
|
||||
|
||||
|
||||
test_error_missing_argument(eof=False)
|
||||
test_error_missing_argument(eof=True)
|
||||
test_error_syntax(eof=False)
|
||||
test_error_syntax(eof=True)
|
||||
test_traceback()
|
||||
test_eof_in_string()
|
||||
@@ -0,0 +1,47 @@
|
||||
#!/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) ;
|
||||
|
||||
actions dummy { }
|
||||
dummy all ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-sARGUMENT=::a/b/c"])
|
||||
t.run_build_system(["-sARGUMENT=a/b/c"], status=1, stdout="""\
|
||||
Error: a/b/c is not a path
|
||||
file.jam:18: in module scope
|
||||
*** argument error
|
||||
* rule do ( [path] a )
|
||||
* called with: ( a/b/c )
|
||||
* true a
|
||||
file.jam:16:see definition of rule 'do' being called
|
||||
""")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,377 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# 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
|
||||
import os
|
||||
|
||||
|
||||
def basic():
|
||||
t = BoostBuild.Tester(pass_toolset=0, pass_d0=False)
|
||||
|
||||
t.write("file.jam", """\
|
||||
actions do-print
|
||||
{
|
||||
echo updating $(<)
|
||||
}
|
||||
|
||||
NOTFILE target1 ;
|
||||
ALWAYS target1 ;
|
||||
do-print target1 ;
|
||||
|
||||
UPDATE_NOW target1 ;
|
||||
|
||||
DEPENDS all : target1 ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-ffile.jam"], stdout="""\
|
||||
...found 1 target...
|
||||
...updating 1 target...
|
||||
do-print target1
|
||||
updating target1
|
||||
...updated 1 target...
|
||||
...found 1 target...
|
||||
""")
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
def ignore_minus_n():
|
||||
t = BoostBuild.Tester(pass_toolset=0, pass_d0=False)
|
||||
|
||||
t.write("file.jam", """\
|
||||
actions do-print
|
||||
{
|
||||
echo updating $(<)
|
||||
}
|
||||
|
||||
NOTFILE target1 ;
|
||||
ALWAYS target1 ;
|
||||
do-print target1 ;
|
||||
|
||||
UPDATE_NOW target1 : : ignore-minus-n ;
|
||||
|
||||
DEPENDS all : target1 ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-ffile.jam", "-n"], stdout="""\
|
||||
...found 1 target...
|
||||
...updating 1 target...
|
||||
do-print target1
|
||||
|
||||
echo updating target1
|
||||
|
||||
updating target1
|
||||
...updated 1 target...
|
||||
...found 1 target...
|
||||
""")
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
def failed_target():
|
||||
t = BoostBuild.Tester(pass_toolset=0, pass_d0=False)
|
||||
|
||||
t.write("file.jam", """\
|
||||
actions fail
|
||||
{
|
||||
exit 1
|
||||
}
|
||||
|
||||
NOTFILE target1 ;
|
||||
ALWAYS target1 ;
|
||||
fail target1 ;
|
||||
|
||||
actions do-print
|
||||
{
|
||||
echo updating $(<)
|
||||
}
|
||||
|
||||
NOTFILE target2 ;
|
||||
do-print target2 ;
|
||||
DEPENDS target2 : target1 ;
|
||||
|
||||
UPDATE_NOW target1 : : ignore-minus-n ;
|
||||
|
||||
DEPENDS all : target1 target2 ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-ffile.jam", "-n"], stdout="""\
|
||||
...found 1 target...
|
||||
...updating 1 target...
|
||||
fail target1
|
||||
|
||||
exit 1
|
||||
|
||||
...failed fail target1...
|
||||
...failed updating 1 target...
|
||||
...found 2 targets...
|
||||
...updating 1 target...
|
||||
do-print target2
|
||||
|
||||
echo updating target2
|
||||
|
||||
...updated 1 target...
|
||||
""")
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
def missing_target():
|
||||
t = BoostBuild.Tester(pass_toolset=0, pass_d0=False)
|
||||
|
||||
t.write("file.jam", """\
|
||||
actions do-print
|
||||
{
|
||||
echo updating $(<)
|
||||
}
|
||||
|
||||
NOTFILE target2 ;
|
||||
do-print target2 ;
|
||||
DEPENDS target2 : target1 ;
|
||||
|
||||
UPDATE_NOW target1 : : ignore-minus-n ;
|
||||
|
||||
DEPENDS all : target1 target2 ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-ffile.jam", "-n"], status=1, stdout="""\
|
||||
don't know how to make target1
|
||||
...found 1 target...
|
||||
...can't find 1 target...
|
||||
...found 2 targets...
|
||||
...can't make 1 target...
|
||||
""")
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
def build_once():
|
||||
"""
|
||||
Make sure that if we call UPDATE_NOW with ignore-minus-n, the target gets
|
||||
updated exactly once regardless of previous calls to UPDATE_NOW with -n in
|
||||
effect.
|
||||
|
||||
"""
|
||||
t = BoostBuild.Tester(pass_toolset=0, pass_d0=False)
|
||||
|
||||
t.write("file.jam", """\
|
||||
actions do-print
|
||||
{
|
||||
echo updating $(<)
|
||||
}
|
||||
|
||||
NOTFILE target1 ;
|
||||
ALWAYS target1 ;
|
||||
do-print target1 ;
|
||||
|
||||
UPDATE_NOW target1 ;
|
||||
UPDATE_NOW target1 : : ignore-minus-n ;
|
||||
UPDATE_NOW target1 : : ignore-minus-n ;
|
||||
|
||||
DEPENDS all : target1 ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-ffile.jam", "-n"], stdout="""\
|
||||
...found 1 target...
|
||||
...updating 1 target...
|
||||
do-print target1
|
||||
|
||||
echo updating target1
|
||||
|
||||
...updated 1 target...
|
||||
do-print target1
|
||||
|
||||
echo updating target1
|
||||
|
||||
updating target1
|
||||
...updated 1 target...
|
||||
...found 1 target...
|
||||
""")
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
def return_status():
|
||||
"""
|
||||
Make sure that UPDATE_NOW returns a failure status if
|
||||
the target failed in a previous call to UPDATE_NOW
|
||||
"""
|
||||
t = BoostBuild.Tester(pass_toolset=0, pass_d0=False)
|
||||
|
||||
t.write("file.jam", """\
|
||||
actions fail
|
||||
{
|
||||
exit 1
|
||||
}
|
||||
|
||||
NOTFILE target1 ;
|
||||
ALWAYS target1 ;
|
||||
fail target1 ;
|
||||
|
||||
ECHO update1: [ UPDATE_NOW target1 ] ;
|
||||
ECHO update2: [ UPDATE_NOW target1 ] ;
|
||||
|
||||
DEPENDS all : target1 ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-ffile.jam"], status=1, stdout="""\
|
||||
...found 1 target...
|
||||
...updating 1 target...
|
||||
fail target1
|
||||
|
||||
exit 1
|
||||
|
||||
...failed fail target1...
|
||||
...failed updating 1 target...
|
||||
update1:
|
||||
update2:
|
||||
...found 1 target...
|
||||
""")
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
def save_restore():
|
||||
"""Tests that ignore-minus-n and ignore-minus-q are
|
||||
local to the call to UPDATE_NOW"""
|
||||
t = BoostBuild.Tester(pass_toolset=0, pass_d0=False)
|
||||
|
||||
t.write("actions.jam", """\
|
||||
rule fail
|
||||
{
|
||||
NOTFILE $(<) ;
|
||||
ALWAYS $(<) ;
|
||||
}
|
||||
actions fail
|
||||
{
|
||||
exit 1
|
||||
}
|
||||
|
||||
rule pass
|
||||
{
|
||||
NOTFILE $(<) ;
|
||||
ALWAYS $(<) ;
|
||||
}
|
||||
actions pass
|
||||
{
|
||||
echo updating $(<)
|
||||
}
|
||||
""")
|
||||
t.write("file.jam", """
|
||||
include actions.jam ;
|
||||
fail target1 ;
|
||||
fail target2 ;
|
||||
UPDATE_NOW target1 target2 : : $(IGNORE_MINUS_N) : $(IGNORE_MINUS_Q) ;
|
||||
fail target3 ;
|
||||
fail target4 ;
|
||||
UPDATE_NOW target3 target4 ;
|
||||
UPDATE ;
|
||||
""")
|
||||
t.run_build_system(['-n', '-sIGNORE_MINUS_N=1', '-ffile.jam'],
|
||||
stdout='''...found 2 targets...
|
||||
...updating 2 targets...
|
||||
fail target1
|
||||
|
||||
exit 1
|
||||
|
||||
...failed fail target1...
|
||||
fail target2
|
||||
|
||||
exit 1
|
||||
|
||||
...failed fail target2...
|
||||
...failed updating 2 targets...
|
||||
...found 2 targets...
|
||||
...updating 2 targets...
|
||||
fail target3
|
||||
|
||||
exit 1
|
||||
|
||||
fail target4
|
||||
|
||||
exit 1
|
||||
|
||||
...updated 2 targets...
|
||||
''')
|
||||
|
||||
t.run_build_system(['-q', '-sIGNORE_MINUS_N=1', '-ffile.jam'],
|
||||
status=1, stdout='''...found 2 targets...
|
||||
...updating 2 targets...
|
||||
fail target1
|
||||
|
||||
exit 1
|
||||
|
||||
...failed fail target1...
|
||||
...failed updating 1 target...
|
||||
...found 2 targets...
|
||||
...updating 2 targets...
|
||||
fail target3
|
||||
|
||||
exit 1
|
||||
|
||||
...failed fail target3...
|
||||
...failed updating 1 target...
|
||||
''')
|
||||
|
||||
t.run_build_system(['-n', '-sIGNORE_MINUS_Q=1', '-ffile.jam'],
|
||||
stdout='''...found 2 targets...
|
||||
...updating 2 targets...
|
||||
fail target1
|
||||
|
||||
exit 1
|
||||
|
||||
fail target2
|
||||
|
||||
exit 1
|
||||
|
||||
...updated 2 targets...
|
||||
...found 2 targets...
|
||||
...updating 2 targets...
|
||||
fail target3
|
||||
|
||||
exit 1
|
||||
|
||||
fail target4
|
||||
|
||||
exit 1
|
||||
|
||||
...updated 2 targets...
|
||||
''')
|
||||
|
||||
t.run_build_system(['-q', '-sIGNORE_MINUS_Q=1', '-ffile.jam'],
|
||||
status=1, stdout='''...found 2 targets...
|
||||
...updating 2 targets...
|
||||
fail target1
|
||||
|
||||
exit 1
|
||||
|
||||
...failed fail target1...
|
||||
fail target2
|
||||
|
||||
exit 1
|
||||
|
||||
...failed fail target2...
|
||||
...failed updating 2 targets...
|
||||
...found 2 targets...
|
||||
...updating 2 targets...
|
||||
fail target3
|
||||
|
||||
exit 1
|
||||
|
||||
...failed fail target3...
|
||||
...failed updating 1 target...
|
||||
''')
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
basic()
|
||||
ignore_minus_n()
|
||||
failed_target()
|
||||
missing_target()
|
||||
build_once()
|
||||
return_status()
|
||||
save_restore()
|
||||
@@ -0,0 +1,39 @@
|
||||
#!/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)
|
||||
|
||||
# Tests that variables in actions get expanded but double quote characters
|
||||
# get treated as regular characters and not string literal delimiters when
|
||||
# determining string tokens concatenated to the variable being expanded.
|
||||
#
|
||||
# We also take care to make this test work correctly when run using both
|
||||
# Windows and Unix echo command variant. That is why we add the extra single
|
||||
# quotes around the text being echoed - they will make the double quotes be
|
||||
# displayed as regular characters in both cases but will be displayed
|
||||
# themselves only when using the Windows cmd shell's echo command.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(pass_toolset=0)
|
||||
t.write("file.jam", """\
|
||||
rule dummy ( i )
|
||||
{
|
||||
local a = 1 2 3 ;
|
||||
ECHO From rule: $(a)" seconds" ;
|
||||
a on $(i) = $(a) ;
|
||||
}
|
||||
|
||||
actions dummy
|
||||
{
|
||||
echo 'From action: $(a)" seconds"'
|
||||
}
|
||||
|
||||
dummy all ;
|
||||
""")
|
||||
t.run_build_system(["-ffile.jam", "-d1"])
|
||||
t.expect_output_lines("From rule: 1 seconds 2 seconds 3 seconds")
|
||||
t.expect_output_lines('*From action: 1" 2" 3" seconds"*')
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2003 Dave Abrahams
|
||||
# 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 core rule for enumerating the variable names in a module.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(pass_toolset=0)
|
||||
|
||||
t.write("file.jam", """\
|
||||
module foo
|
||||
{
|
||||
rule bar { }
|
||||
var1 = x y ;
|
||||
var2 = fubar ;
|
||||
}
|
||||
|
||||
expected = var1 var2 ;
|
||||
names = [ VARNAMES foo ] ;
|
||||
if $(names) in $(expected) && $(expected) in $(names)
|
||||
{
|
||||
# everything OK
|
||||
}
|
||||
else
|
||||
{
|
||||
EXIT expected to find variables $(expected:J=", ") in module foo,
|
||||
but found $(names:J=", ") instead. ;
|
||||
}
|
||||
DEPENDS all : xx ;
|
||||
NOTFILE xx ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-ffile.jam"], status=0)
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2003, 2004, 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)
|
||||
|
||||
# Attempt to declare a generator for creating OBJ from RC files. That generator
|
||||
# should be considered together with standard CPP->OBJ generators and
|
||||
# successfully create the target. Since we do not have a RC compiler everywhere,
|
||||
# we fake the action. The resulting OBJ will be unusable, but it must be
|
||||
# created.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester()
|
||||
|
||||
t.write("jamroot.jam", """
|
||||
import rcc ;
|
||||
""")
|
||||
|
||||
t.write("rcc.jam", """
|
||||
import type ;
|
||||
import generators ;
|
||||
import print ;
|
||||
|
||||
# Use 'RCC' to avoid conflicts with definitions in the standard rc.jam and
|
||||
# msvc.jam
|
||||
type.register RCC : rcc ;
|
||||
|
||||
rule resource-compile ( targets * : sources * : properties * )
|
||||
{
|
||||
print.output $(targets[1]) ;
|
||||
print.text "rc-object" ;
|
||||
}
|
||||
|
||||
generators.register-standard rcc.resource-compile : RCC : OBJ ;
|
||||
""")
|
||||
|
||||
t.write("rcc.py", """
|
||||
import b2.build.type as type
|
||||
import b2.build.generators as generators
|
||||
|
||||
from b2.manager import get_manager
|
||||
|
||||
# Use 'RCC' to avoid conflicts with definitions in the standard rc.jam and
|
||||
# msvc.jam
|
||||
type.register('RCC', ['rcc'])
|
||||
|
||||
generators.register_standard("rcc.resource-compile", ["RCC"], ["OBJ"])
|
||||
|
||||
get_manager().engine().register_action(
|
||||
"rcc.resource-compile",
|
||||
'@($(STDOUT):E=rc-object) > "$(<)"')
|
||||
""")
|
||||
|
||||
t.write("jamfile.jam", """
|
||||
obj r : r.rcc ;
|
||||
""")
|
||||
|
||||
t.write("r.rcc", """
|
||||
""")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_content("bin/$toolset/debug/r.obj", "rc-object")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,80 @@
|
||||
#!/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.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"])
|
||||
t.expect_addition("bin/$toolset/debug/optimization-space/a.exe")
|
||||
t.expect_addition("bin/$toolset/release/optimization-space/a.exe")
|
||||
|
||||
# Test that default-build must be identical in all alternatives. Error case.
|
||||
t.write("jamfile.jam", """\
|
||||
exe a : a.cpp : : debug ;
|
||||
exe a : b.cpp : : ;
|
||||
""")
|
||||
t.run_build_system(["-n", "--no-error-backtrace"], status=1)
|
||||
t.fail_test(t.stdout().find("default build must be identical in all alternatives") == -1)
|
||||
|
||||
# Test that default-build must be identical in all alternatives. No Error case,
|
||||
# empty default build.
|
||||
t.write("jamfile.jam", """\
|
||||
exe a : a.cpp : <variant>debug ;
|
||||
exe a : b.cpp : <variant>release ;
|
||||
""")
|
||||
t.run_build_system(["-n", "--no-error-backtrace"], status=0)
|
||||
|
||||
# Now try a harder example: default build which contains <define> should cause
|
||||
# <define> to be present when "b" is compiled. This happens only if
|
||||
# "build-project b" is placed first.
|
||||
t.write("jamfile.jam", """\
|
||||
project : default-build <define>FOO ;
|
||||
build-project a ;
|
||||
build-project b ;
|
||||
""")
|
||||
|
||||
t.write("a/jamfile.jam", "exe a : a.cpp ../b//b ;")
|
||||
t.write("a/a.cpp", """\
|
||||
#ifdef _WIN32
|
||||
__declspec(dllimport)
|
||||
#endif
|
||||
void foo();
|
||||
int main() { foo(); }
|
||||
""")
|
||||
|
||||
t.write("b/jamfile.jam", "lib b : b.cpp ;")
|
||||
t.write("b/b.cpp", """\
|
||||
#ifdef FOO
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void foo() {}
|
||||
#endif
|
||||
""")
|
||||
|
||||
t.run_build_system()
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,50 @@
|
||||
#!/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)
|
||||
|
||||
# Test that features with default values are always present in build properties
|
||||
# of any target.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
# Declare *non-propagated* feature foo.
|
||||
t.write("jamroot.jam", """
|
||||
import feature : feature ;
|
||||
feature foo : on off ;
|
||||
""")
|
||||
|
||||
# Note that '<foo>on' will not be propagated to 'd/l'.
|
||||
t.write("jamfile.jam", """
|
||||
exe hello : hello.cpp d//l ;
|
||||
""")
|
||||
|
||||
t.write("hello.cpp", """
|
||||
#ifdef _WIN32
|
||||
__declspec(dllimport)
|
||||
#endif
|
||||
void foo();
|
||||
int main() { foo(); }
|
||||
""")
|
||||
|
||||
t.write("d/jamfile.jam", """
|
||||
lib l : l.cpp : <foo>on:<define>FOO ;
|
||||
""")
|
||||
|
||||
t.write("d/l.cpp", """
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
#ifdef FOO
|
||||
void foo() {}
|
||||
#endif
|
||||
""")
|
||||
|
||||
t.run_build_system()
|
||||
|
||||
t.expect_addition("bin/$toolset/debug/hello.exe")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,215 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2008 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 that the expected default toolset is used when no toolset is explicitly
|
||||
# specified on the command line or used from code via the using rule. Test that
|
||||
# the default toolset is correctly used just like any other explicitly used
|
||||
# toolset (e.g. toolset prerequisites, properties conditioned on toolset
|
||||
# related features, etc.).
|
||||
#
|
||||
# Note that we need to ignore regular site/user/test configuration files to
|
||||
# avoid them marking any toolsets not under our control as used.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
|
||||
# Line displayed by Boost Build when using the default toolset.
|
||||
configuring_default_toolset_message = \
|
||||
'warning: Configuring default toolset "%s".'
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# test_conditions_on_default_toolset()
|
||||
# ------------------------------------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
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_lines(configuring_default_toolset_message % toolset_name)
|
||||
t.expect_output_lines(message_loaded)
|
||||
t.expect_output_lines(message_initialized)
|
||||
t.expect_output_lines("descriptions: /stand-alone/ /toolset/ "
|
||||
"/toolset-version/")
|
||||
t.expect_output_lines("toolset: /%s/" % toolset_name)
|
||||
t.expect_output_lines("toolset-version: /%s/" % toolset_version)
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# test_default_toolset_on_os()
|
||||
# ----------------------------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
def test_default_toolset_on_os( os, expected_toolset ):
|
||||
"""Test that the given toolset is used as the default toolset on the given
|
||||
os. Uses hardcoded knowledge of how Boost Build decides on which host OS it
|
||||
is currently running. Note that we must not do much after tricking Boost
|
||||
Build into believing it has a specific host OS as this might mess up other
|
||||
important internal Boost Build state.
|
||||
"""
|
||||
|
||||
t = BoostBuild.Tester("--user-config= --ignore-site-config",
|
||||
pass_toolset=False, use_test_config=False)
|
||||
|
||||
t.write("jamroot.jam", "modules.poke os : .name : %s ;" % os)
|
||||
|
||||
# We need to tell the test system to ignore stderr output as attempting to
|
||||
# load missing toolsets might cause random failures with which we are not
|
||||
# concerned in this test.
|
||||
t.run_build_system(stderr=None)
|
||||
t.expect_output_lines(configuring_default_toolset_message %
|
||||
expected_toolset)
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# test_default_toolset_requirements()
|
||||
# -----------------------------------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
def test_default_toolset_requirements():
|
||||
"""Test that default toolset's requirements get applied correctly.
|
||||
"""
|
||||
|
||||
t = BoostBuild.Tester("--user-config= --ignore-site-config",
|
||||
pass_toolset=False, use_test_config=False,
|
||||
ignore_toolset_requirements=False)
|
||||
|
||||
toolset_name = "customTestToolsetWithRequirements"
|
||||
|
||||
# Custom toolset.
|
||||
t.write(toolset_name + ".jam", """
|
||||
import feature ;
|
||||
import toolset ;
|
||||
feature.extend toolset : %(toolset_name)s ;
|
||||
toolset.add-requirements <description>toolset-requirement ;
|
||||
rule init ( ) { }
|
||||
""" % {'toolset_name': toolset_name})
|
||||
|
||||
# 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 ;
|
||||
|
||||
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)/ ;
|
||||
}
|
||||
|
||||
notfile testTarget
|
||||
: @buildRule
|
||||
:
|
||||
:
|
||||
<description>target-requirement
|
||||
<description>toolset-requirement:<description>conditioned-requirement
|
||||
<description>unrelated-condition:<description>unrelated-description ;
|
||||
""" % {'toolset_name': toolset_name})
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_output_lines(configuring_default_toolset_message % toolset_name)
|
||||
t.expect_output_lines("descriptions: /conditioned-requirement/ "
|
||||
"/target-requirement/ /toolset-requirement/")
|
||||
t.expect_output_lines("toolset: /%s/" % toolset_name)
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# main()
|
||||
# ------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
test_default_toolset_on_os("NT" , "msvc")
|
||||
test_default_toolset_on_os("LINUX" , "gcc" )
|
||||
test_default_toolset_on_os("CYGWIN" , "gcc" )
|
||||
test_default_toolset_on_os("SomeOtherOS", "gcc" )
|
||||
test_default_toolset_requirements()
|
||||
test_conditions_on_default_toolset()
|
||||
@@ -0,0 +1,39 @@
|
||||
#!/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)
|
||||
|
||||
# Regression test: virtual targets with different dependency properties were
|
||||
# considered different by 'virtual-target.register', but the code which
|
||||
# determined the actual target paths ignored dependency properties so both
|
||||
# targets ended up being in the same location.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
|
||||
t = BoostBuild.Tester()
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
lib foo : foo.cpp ;
|
||||
exe hello : hello.cpp ;
|
||||
exe hello2 : hello.cpp : <library>foo ;
|
||||
""")
|
||||
|
||||
t.write("hello.cpp", "int main() {}\n")
|
||||
|
||||
t.write("foo.cpp", """\
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void foo() {}
|
||||
""")
|
||||
|
||||
t.run_build_system(["--no-error-backtrace"], status=1)
|
||||
output = t.stdout()
|
||||
t.fail_test(
|
||||
"Tried to build the target twice" not in output and
|
||||
"Duplicate name of actual target" not in output
|
||||
)
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,239 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2003 Dave Abrahams
|
||||
# Copyright 2002, 2003, 2005, 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
|
||||
|
||||
|
||||
def test_basic():
|
||||
t = BoostBuild.Tester(["-d3", "-d+12"], pass_d0=False, 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.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.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.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()
|
||||
|
||||
|
||||
def test_scanned_includes_with_absolute_paths():
|
||||
"""
|
||||
Regression test: on Windows, <includes> with absolute paths were not
|
||||
considered when scanning dependencies.
|
||||
|
||||
"""
|
||||
t = BoostBuild.Tester(["-d3", "-d+12"], pass_d0=False)
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
path-constant TOP : . ;
|
||||
exe app : main.cpp : <include>$(TOP)/include ;
|
||||
""");
|
||||
|
||||
t.write("main.cpp", """\
|
||||
#include <dir/header.h>
|
||||
int main() {}
|
||||
""")
|
||||
|
||||
t.write("include/dir/header.h", "\n")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition("bin/$toolset/debug/main.obj")
|
||||
|
||||
t.touch("include/dir/header.h")
|
||||
t.run_build_system()
|
||||
t.expect_touch("bin/$toolset/debug/main.obj")
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
test_basic()
|
||||
test_scanned_includes_with_absolute_paths()
|
||||
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
# First check some startup.
|
||||
|
||||
t.write("jamroot.jam", "")
|
||||
t.write("jamfile.jam", """\
|
||||
exe a : a.cpp b ;
|
||||
lib b : b.cpp ;
|
||||
""")
|
||||
|
||||
t.write("a.cpp", """\
|
||||
void
|
||||
# ifdef _WIN32
|
||||
__declspec(dllimport)
|
||||
# endif
|
||||
foo();
|
||||
int main() { foo(); }
|
||||
""")
|
||||
|
||||
t.write("b.cpp", """\
|
||||
#ifdef MACROS
|
||||
void
|
||||
# ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
# endif
|
||||
foo() {}
|
||||
#endif
|
||||
|
||||
# ifdef _WIN32
|
||||
int __declspec(dllexport) force_implib_creation;
|
||||
# endif
|
||||
""")
|
||||
|
||||
t.run_build_system(["define=MACROS"])
|
||||
t.expect_addition("bin/$toolset/debug/"
|
||||
* (BoostBuild.List("a.obj b.obj b.dll a.exe")))
|
||||
|
||||
|
||||
# When building a debug version, the 'define' still applies.
|
||||
t.rm("bin")
|
||||
t.run_build_system(["debug", "define=MACROS"])
|
||||
t.expect_addition("bin/$toolset/debug/"
|
||||
* (BoostBuild.List("a.obj b.obj b.dll a.exe")))
|
||||
|
||||
|
||||
# When building a release version, the 'define' still applies.
|
||||
t.write("jamfile.jam", """\
|
||||
exe a : a.cpp b : <variant>debug ;
|
||||
lib b : b.cpp ;
|
||||
""")
|
||||
t.rm("bin")
|
||||
t.run_build_system(["release", "define=MACROS"])
|
||||
|
||||
|
||||
# Regression test: direct build request was not working when there was more
|
||||
# than one level of 'build-project'.
|
||||
t.rm(".")
|
||||
t.write("jamroot.jam", "")
|
||||
t.write("jamfile.jam", "build-project a ;")
|
||||
t.write("a/jamfile.jam", "build-project b ;")
|
||||
t.write("a/b/jamfile.jam", "")
|
||||
t.run_build_system(["release"])
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,32 @@
|
||||
#!/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 that it is possible to add a suffix to a main target name to disambiguate
|
||||
# that main target from another, and that this does not affect the names of the
|
||||
# generated targets.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.write("jamroot.jam", """
|
||||
exe hello.exe : hello.obj ;
|
||||
obj hello.obj : hello.cpp : <variant>debug ;
|
||||
obj hello.obj2 : hello.cpp : <variant>release ;
|
||||
""")
|
||||
|
||||
t.write("hello.cpp", """
|
||||
int main() {}
|
||||
""")
|
||||
|
||||
t.run_build_system()
|
||||
|
||||
t.expect_addition("bin/$toolset/debug/hello.exe")
|
||||
t.expect_addition("bin/$toolset/debug/hello.obj")
|
||||
t.expect_addition("bin/$toolset/release/hello.obj")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,146 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright (C) 2003. 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)
|
||||
|
||||
# Test that the <dll-path> property is correctly set when using
|
||||
# <hardcode-dll-paths>true.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
# The point of this test is to have exe "main" which uses library "b", which
|
||||
# uses library "a". When "main" is built with <hardcode-dll-paths>true, paths
|
||||
# to both libraries should be present as values of <dll-path> feature. We
|
||||
# create a special target type which reports <dll-path> values on its sources
|
||||
# and compare the list of found values with out expectations.
|
||||
|
||||
t.write("jamroot.jam", "using dll_paths ;")
|
||||
t.write("jamfile.jam", """\
|
||||
exe main : main.cpp b//b ;
|
||||
explicit main ;
|
||||
path-list mp : main ;
|
||||
""")
|
||||
|
||||
t.write("main.cpp", "int main() {}\n")
|
||||
t.write("dll_paths.jam", """\
|
||||
import "class" : new ;
|
||||
import feature ;
|
||||
import generators ;
|
||||
import print ;
|
||||
import sequence ;
|
||||
import type ;
|
||||
|
||||
rule init ( )
|
||||
{
|
||||
type.register PATH_LIST : pathlist ;
|
||||
|
||||
class dll-paths-list-generator : generator
|
||||
{
|
||||
rule __init__ ( )
|
||||
{
|
||||
generator.__init__ dll_paths.list : EXE : PATH_LIST ;
|
||||
}
|
||||
|
||||
rule generated-targets ( sources + : property-set : project name ? )
|
||||
{
|
||||
local dll-paths ;
|
||||
for local s in $(sources)
|
||||
{
|
||||
local a = [ $(s).action ] ;
|
||||
if $(a)
|
||||
{
|
||||
local p = [ $(a).properties ] ;
|
||||
dll-paths += [ $(p).get <dll-path> ] ;
|
||||
}
|
||||
}
|
||||
return [ generator.generated-targets $(sources) :
|
||||
[ $(property-set).add-raw $(dll-paths:G=<dll-path>) ] :
|
||||
$(project) $(name) ] ;
|
||||
}
|
||||
}
|
||||
generators.register [ new dll-paths-list-generator ] ;
|
||||
}
|
||||
|
||||
rule list ( target : sources * : properties * )
|
||||
{
|
||||
local paths = [ feature.get-values <dll-path> : $(properties) ] ;
|
||||
paths = [ sequence.insertion-sort $(paths) ] ;
|
||||
print.output $(target) ;
|
||||
print.text $(paths) ;
|
||||
}
|
||||
""")
|
||||
|
||||
t.write("dll_paths.py", """\
|
||||
import bjam
|
||||
|
||||
import b2.build.type as type
|
||||
import b2.build.generators as generators
|
||||
|
||||
from b2.manager import get_manager
|
||||
|
||||
def init():
|
||||
type.register("PATH_LIST", ["pathlist"])
|
||||
|
||||
class DllPathsListGenerator(generators.Generator):
|
||||
|
||||
def __init__(self):
|
||||
generators.Generator.__init__(self, "dll_paths.list", False,
|
||||
["EXE"], ["PATH_LIST"])
|
||||
|
||||
def generated_targets(self, sources, ps, project, name):
|
||||
dll_paths = []
|
||||
for s in sources:
|
||||
a = s.action()
|
||||
if a:
|
||||
p = a.properties()
|
||||
dll_paths += p.get('dll-path')
|
||||
dll_paths.sort()
|
||||
return generators.Generator.generated_targets(self, sources,
|
||||
ps.add_raw(["<dll-path>" + p for p in dll_paths]), project,
|
||||
name)
|
||||
|
||||
generators.register(DllPathsListGenerator())
|
||||
|
||||
command = \"\"\"
|
||||
echo $(PATHS) > $(<[1])
|
||||
\"\"\"
|
||||
def function(target, sources, ps):
|
||||
bjam.call('set-target-variable', target, "PATHS", ps.get('dll-path'))
|
||||
|
||||
get_manager().engine().register_action("dll_paths.list", command,
|
||||
function=function)
|
||||
""")
|
||||
|
||||
t.write("a/jamfile.jam", "lib a : a.cpp ;")
|
||||
t.write("a/a.cpp", """\
|
||||
void
|
||||
#if defined(_WIN32)
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
foo() {}
|
||||
""")
|
||||
|
||||
t.write("b/jamfile.jam", "lib b : b.cpp ../a//a ;")
|
||||
t.write("b/b.cpp", """\
|
||||
void
|
||||
#if defined(_WIN32)
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
bar() {}
|
||||
""")
|
||||
|
||||
t.run_build_system(["hardcode-dll-paths=true"])
|
||||
|
||||
t.expect_addition("bin/$toolset/debug/mp.pathlist")
|
||||
|
||||
es1 = t.adjust_names("a/bin/$toolset/debug")[0]
|
||||
es2 = t.adjust_names("b/bin/$toolset/debug")[0]
|
||||
|
||||
t.expect_content_lines("bin/$toolset/debug/mp.pathlist", "*" + es1);
|
||||
t.expect_content_lines("bin/$toolset/debug/mp.pathlist", "*" + es2);
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2003 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
|
||||
|
||||
t = BoostBuild.Tester()
|
||||
|
||||
# Regression test for double loading of the same Jamfile.
|
||||
t.write("jamroot.jam", "")
|
||||
t.write("jamfile.jam", "build-project subdir ;")
|
||||
t.write("subdir/jamfile.jam", 'ECHO "Loaded subdir" ;')
|
||||
|
||||
t.run_build_system(subdir="subdir")
|
||||
t.expect_output_lines("Loaded subdir")
|
||||
|
||||
|
||||
# Regression test for a more contrived case. The top-level Jamfile refers to
|
||||
# subdir via use-project, while subdir's Jamfile is being loaded. The
|
||||
# motivation why use-project referring to subprojects is useful can be found
|
||||
# at: http://article.gmane.org/gmane.comp.lib.boost.build/3906
|
||||
t.write("jamroot.jam", "")
|
||||
t.write("jamfile.jam", "use-project /subdir : subdir ;")
|
||||
t.write("subdir/jamfile.jam", "project subdir ;")
|
||||
|
||||
t.run_build_system(subdir="subdir");
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 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)
|
||||
|
||||
# This test tries to stage the same file to the same location by *two* different
|
||||
# stage rules, in two different projects. This is not exactly good thing to do,
|
||||
# but still, V2 should handle this. We had two bugs:
|
||||
# - since the file is referred from two projects, we created to different
|
||||
# virtual targets
|
||||
# - we also failed to figure out that the two target corresponding to the copied
|
||||
# files (created in two projects) are actually equivalent.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester()
|
||||
|
||||
t.write("a.cpp", """
|
||||
""")
|
||||
|
||||
t.write("jamroot.jam", """
|
||||
build-project a ;
|
||||
build-project b ;
|
||||
""")
|
||||
|
||||
t.write("a/jamfile.jam", """
|
||||
stage bin : ../a.cpp : <location>../dist ;
|
||||
""")
|
||||
|
||||
t.write("b/jamfile.jam", """
|
||||
stage bin : ../a.cpp : <location>../dist ;
|
||||
""")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition("dist/a.cpp")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/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 'customization' example.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester()
|
||||
|
||||
t.set_tree("../example/customization")
|
||||
|
||||
t.run_build_system()
|
||||
|
||||
t.expect_addition(["bin/$toolset/debug/codegen.exe",
|
||||
"bin/$toolset/debug/usage.cpp"])
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,30 @@
|
||||
#!/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 'gettext' example.
|
||||
|
||||
import BoostBuild
|
||||
import os
|
||||
import string
|
||||
|
||||
t = BoostBuild.Tester()
|
||||
|
||||
t.set_tree("../example/gettext")
|
||||
|
||||
t.run_build_system(stderr=None)
|
||||
|
||||
t.expect_addition(["bin/$toolset/debug/main.exe",
|
||||
"bin/$toolset/debug/russian.mo"])
|
||||
|
||||
file = t.adjust_names(["bin/$toolset/debug/main.exe"])[0]
|
||||
|
||||
input_fd = os.popen(file)
|
||||
input = input_fd.read();
|
||||
|
||||
t.fail_test(string.find(input, "international hello") != 0)
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/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 'libraries' example.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.set_tree("../example/libraries")
|
||||
|
||||
t.run_build_system()
|
||||
|
||||
t.expect_addition(["app/bin/$toolset/debug/app.exe",
|
||||
"util/foo/bin/$toolset/debug/bar.dll"])
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,17 @@
|
||||
#!/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
|
||||
import sys
|
||||
|
||||
t = BoostBuild.Tester(['example.python.interpreter=%s' % sys.executable])
|
||||
t.set_tree("../example/make")
|
||||
t.run_build_system()
|
||||
t.expect_addition(["bin/$toolset/debug/main.cpp"])
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,26 @@
|
||||
#!/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 'qt4' examples.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester()
|
||||
|
||||
t.set_tree("../example/qt/qt4/hello")
|
||||
t.run_build_system()
|
||||
t.expect_addition(["bin/$toolset/debug/threading-multi/arrow"])
|
||||
|
||||
t.set_tree("../example/qt/qt4/moccable-cpp")
|
||||
t.run_build_system()
|
||||
t.expect_addition(["bin/$toolset/debug/threading-multi/main"])
|
||||
|
||||
t.set_tree("../example/qt/qt4/uic")
|
||||
t.run_build_system()
|
||||
t.expect_addition(["bin/$toolset/debug/threading-multi/hello"])
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright (C) Vladimir Prus 2010.
|
||||
# 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 that build failure results in non-zero exit status
|
||||
|
||||
import BoostBuild
|
||||
|
||||
# Create a temporary working directory.
|
||||
t = BoostBuild.Tester()
|
||||
|
||||
# Create the needed files.
|
||||
t.write("jamroot.jam", """
|
||||
exe hello : hello.cpp ;
|
||||
""")
|
||||
|
||||
t.write("hello.cpp", """
|
||||
int main() {
|
||||
""")
|
||||
|
||||
t.run_build_system(status=1)
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,80 @@
|
||||
#!/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("a.cpp", """
|
||||
#ifdef CF_IS_OFF
|
||||
int main() {}
|
||||
#endif
|
||||
""")
|
||||
|
||||
t.write("b.cpp", """
|
||||
#ifdef CF_1
|
||||
int main() {}
|
||||
#endif
|
||||
""")
|
||||
|
||||
t.write("c.cpp", """
|
||||
#ifdef FOO
|
||||
int main() {}
|
||||
#endif
|
||||
""")
|
||||
|
||||
t.write("jamfile.jam", """
|
||||
# See if default value of composite feature 'cf' will be expanded to
|
||||
# <define>CF_IS_OFF.
|
||||
exe a : a.cpp ;
|
||||
|
||||
# See if subfeature in requirements in expanded.
|
||||
exe b : b.cpp : <cf>on-1 ;
|
||||
|
||||
# See if conditional requirements are recursively expanded.
|
||||
exe c : c.cpp : <toolset>$toolset:<variant>release <variant>release:<define>FOO
|
||||
;
|
||||
""")
|
||||
|
||||
t.write("jamroot.jam", """
|
||||
import feature ;
|
||||
feature.feature cf : off on : composite incidental ;
|
||||
feature.compose <cf>off : <define>CF_IS_OFF ;
|
||||
feature.subfeature cf on : version : 1 2 : composite optional incidental ;
|
||||
feature.compose <cf-on:version>1 : <define>CF_1 ;
|
||||
""")
|
||||
|
||||
t.expand_toolset("jamfile.jam")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition(["bin/$toolset/debug/a.exe",
|
||||
"bin/$toolset/debug/b.exe",
|
||||
"bin/$toolset/release/c.exe"])
|
||||
|
||||
t.rm("bin")
|
||||
|
||||
|
||||
# Test for issue BB60.
|
||||
|
||||
t.write("test.cpp", """
|
||||
#include "header.h"
|
||||
int main() {}
|
||||
""")
|
||||
|
||||
t.write("jamfile.jam", """
|
||||
project : requirements <toolset>$toolset:<include>foo ;
|
||||
exe test : test.cpp : <toolset>$toolset ;
|
||||
""")
|
||||
|
||||
t.expand_toolset("jamfile.jam")
|
||||
t.write("foo/header.h", "\n")
|
||||
t.write("jamroot.jam", "")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition("bin/$toolset/debug/test.exe")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,58 @@
|
||||
#!/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
|
||||
# not to the Jamfile where the helper rule is defined.
|
||||
t.write("jamroot.jam", """\
|
||||
rule myinstall ( name : target )
|
||||
{
|
||||
install $(name)-bin : $(target) ;
|
||||
explicit $(name)-bin ;
|
||||
alias $(name) : $(name)-bin ;
|
||||
}
|
||||
""")
|
||||
|
||||
t.write("sub/a.cpp", "\n")
|
||||
t.write("sub/jamfile.jam", "myinstall dist : a.cpp ;")
|
||||
|
||||
t.run_build_system(subdir="sub")
|
||||
t.expect_addition("sub/dist-bin/a.cpp")
|
||||
|
||||
t.rm("sub/dist-bin")
|
||||
|
||||
t.write("sub/jamfile.jam", """\
|
||||
myinstall dist : a.cpp ;
|
||||
explicit dist ;
|
||||
""")
|
||||
|
||||
t.run_build_system(subdir="sub")
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2014 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)
|
||||
|
||||
# Tests the cxxflags feature
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
# cxxflags should be applied to C++ compilation,
|
||||
# but not to C.
|
||||
t.write("Jamroot.jam", """
|
||||
obj test-cpp : test.cpp : <cxxflags>-DOKAY ;
|
||||
obj test-c : test.c : <cxxflags>-DBAD ;
|
||||
""")
|
||||
|
||||
t.write("test.cpp", """
|
||||
#ifndef OKAY
|
||||
#error Cannot compile without OKAY
|
||||
#endif
|
||||
""")
|
||||
|
||||
t.write("test.c", """
|
||||
#ifdef BAD
|
||||
#error Cannot compile with BAD
|
||||
#endif
|
||||
""")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition("bin/$toolset/debug/test-cpp.obj")
|
||||
t.expect_addition("bin/$toolset/debug/test-c.obj")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright (C) Vladimir Prus 2007.
|
||||
# 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)
|
||||
|
||||
# Tests that a free feature specified on the command line applies to all
|
||||
# targets ever built.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
exe hello : hello.cpp foo ;
|
||||
lib foo : foo.cpp ;
|
||||
""")
|
||||
|
||||
t.write("hello.cpp", """\
|
||||
extern void foo();
|
||||
#ifdef FOO
|
||||
int main() { foo(); }
|
||||
#endif
|
||||
""")
|
||||
|
||||
t.write("foo.cpp", """\
|
||||
#ifdef FOO
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void foo() {}
|
||||
#endif
|
||||
""")
|
||||
|
||||
# If FOO is not defined when compiling the 'foo' target, we will get a link
|
||||
# error at this point.
|
||||
t.run_build_system(["hello", "define=FOO"])
|
||||
|
||||
t.expect_addition("bin/$toolset/debug/hello.exe")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2004 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)
|
||||
|
||||
# Tests that on gcc, we correctly report a problem when static runtime is
|
||||
# requested for building a shared library.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester()
|
||||
t.write("jamroot.jam", "lib hello : hello.cpp ;")
|
||||
t.write("hello.cpp", "int main() {}\n")
|
||||
|
||||
t.run_build_system(["runtime-link=static"])
|
||||
t.expect_output_lines("warning: On gcc, DLLs can not be built with "
|
||||
"'<runtime-link>static'.")
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.run_build_system(["link=static", "runtime-link=static"])
|
||||
binFolder = "bin/$toolset/debug/link-static/runtime-link-static"
|
||||
t.expect_addition("%s/hello.obj" % binFolder)
|
||||
t.expect_addition("%s/hello.lib" % binFolder)
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,157 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2008, 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)
|
||||
|
||||
# Tests that generators get selected correctly.
|
||||
#
|
||||
# We do not use the internal C++-compiler CPP --> OBJ generator to avoid
|
||||
# problems with specific compilers or their configurations, e.g. IBM's AIX test
|
||||
# runner 'AIX Version 5.3 TL7 SP5 (5300-07-05-0831)' using the 'IBM XL C/C++
|
||||
# for AIX, V12.1 (Version: 12.01.0000.0000)' reporting errors when run with a
|
||||
# source file whose suffix is not '.cpp'.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# test_generator_added_after_already_building_a_target_of_its_target_type()
|
||||
# -------------------------------------------------------------------------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
def test_generator_added_after_already_building_a_target_of_its_target_type():
|
||||
"""
|
||||
Regression test for a Boost Build bug causing it to not use a generator
|
||||
if it got added after already building a target of its target type.
|
||||
|
||||
"""
|
||||
t = BoostBuild.Tester()
|
||||
|
||||
t.write("dummy.cpp", "void f() {}\n")
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
import common ;
|
||||
import generators ;
|
||||
import type ;
|
||||
type.register MY_OBJ : my_obj ;
|
||||
generators.register-standard common.copy : CPP : MY_OBJ ;
|
||||
|
||||
# Building this dummy target must not cause a later defined CPP target type
|
||||
# generator not to be recognized as viable.
|
||||
my-obj dummy : dummy.cpp ;
|
||||
alias the-other-obj : Other//other-obj ;
|
||||
""")
|
||||
|
||||
t.write("Other/source.extension", "A dummy source file.")
|
||||
|
||||
t.write("Other/mygen.jam", """\
|
||||
import common ;
|
||||
import generators ;
|
||||
import type ;
|
||||
type.register MY_TYPE : extension ;
|
||||
generators.register-standard $(__name__).generate-a-cpp-file : MY_TYPE : CPP ;
|
||||
rule generate-a-cpp-file { ECHO Generating a CPP file... ; }
|
||||
CREATE-FILE = [ common.file-creation-command ] ;
|
||||
actions generate-a-cpp-file { $(CREATE-FILE) "$(<)" }
|
||||
""")
|
||||
|
||||
t.write("Other/mygen.py", """\
|
||||
import b2.build.generators as generators
|
||||
import b2.build.type as type
|
||||
|
||||
from b2.manager import get_manager
|
||||
|
||||
import os
|
||||
|
||||
type.register('MY_TYPE', ['extension'])
|
||||
generators.register_standard('mygen.generate-a-cpp-file', ['MY_TYPE'], ['CPP'])
|
||||
if os.name == 'nt':
|
||||
action = 'echo void g() {} > "$(<)"'
|
||||
else:
|
||||
action = 'echo "void g() {}" > "$(<)"'
|
||||
def f(*args):
|
||||
print "Generating a CPP file..."
|
||||
|
||||
get_manager().engine().register_action("mygen.generate-a-cpp-file", action,
|
||||
function=f)
|
||||
""")
|
||||
|
||||
t.write("Other/jamfile.jam", """\
|
||||
import mygen ;
|
||||
my-obj other-obj : source.extension ;
|
||||
""")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_output_lines("Generating a CPP file...")
|
||||
t.expect_addition("bin/$toolset/debug/dummy.my_obj")
|
||||
t.expect_addition("Other/bin/$toolset/debug/other-obj.cpp")
|
||||
t.expect_addition("Other/bin/$toolset/debug/other-obj.my_obj")
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# test_using_a_derived_source_type_created_after_generator_already_used()
|
||||
# -----------------------------------------------------------------------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
def test_using_a_derived_source_type_created_after_generator_already_used():
|
||||
"""
|
||||
Regression test for a Boost Build bug causing it to not use a generator
|
||||
with a source type derived from one of the generator's sources but created
|
||||
only after already using the generateor.
|
||||
|
||||
"""
|
||||
t = BoostBuild.Tester()
|
||||
|
||||
t.write("dummy.xxx", "Hello. My name is Peter Pan.\n")
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
import common ;
|
||||
import generators ;
|
||||
import type ;
|
||||
type.register XXX : xxx ;
|
||||
type.register YYY : yyy ;
|
||||
generators.register-standard common.copy : XXX : YYY ;
|
||||
|
||||
# Building this dummy target must not cause a later defined XXX2 target type not
|
||||
# to be recognized as a viable source type for building YYY targets.
|
||||
yyy dummy : dummy.xxx ;
|
||||
alias the-test-output : Other//other ;
|
||||
""")
|
||||
|
||||
t.write("Other/source.xxx2", "Hello. My name is Tinkerbell.\n")
|
||||
|
||||
t.write("Other/jamfile.jam", """\
|
||||
import type ;
|
||||
type.register XXX2 : xxx2 : XXX ;
|
||||
# We are careful not to do anything between defining our new XXX2 target type
|
||||
# and using the XXX --> YYY generator that could potentially cover the Boost
|
||||
# Build bug by clearing its internal viable source target type state.
|
||||
yyy other : source.xxx2 ;
|
||||
""")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition("bin/$toolset/debug/dummy.yyy")
|
||||
t.expect_addition("Other/bin/$toolset/debug/other.yyy")
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# main()
|
||||
# ------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
test_generator_added_after_already_building_a_target_of_its_target_type()
|
||||
test_using_a_derived_source_type_created_after_generator_already_used()
|
||||
@@ -0,0 +1,433 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2002, 2003 Dave Abrahams
|
||||
# Copyright 2002, 2003, 2004, 2005 Vladimir Prus
|
||||
# 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)
|
||||
|
||||
import BoostBuild
|
||||
import re
|
||||
|
||||
|
||||
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()
|
||||
|
||||
|
||||
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(pass_d0=False)
|
||||
__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/$toolset/debug/_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()
|
||||
|
||||
|
||||
def __match_count_is(lines, pattern, expected):
|
||||
count = 0
|
||||
for x in lines:
|
||||
if re.search(pattern, x):
|
||||
count += 1
|
||||
if count > expected:
|
||||
return False
|
||||
return count == expected
|
||||
|
||||
|
||||
def __write_appender(t, name):
|
||||
t.write(name,
|
||||
r"""# 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)
|
||||
|
||||
# Support for registering test generators that construct their targets by
|
||||
# simply appending their given input data, e.g. list of sources & targets.
|
||||
|
||||
import "class" : new ;
|
||||
import generators ;
|
||||
import modules ;
|
||||
import sequence ;
|
||||
|
||||
rule register ( id composing ? : source-types + : target-types + )
|
||||
{
|
||||
local caller-module = [ CALLER_MODULE ] ;
|
||||
id = $(caller-module).$(id) ;
|
||||
local g = [ new generator $(id) $(composing) : $(source-types) :
|
||||
$(target-types) ] ;
|
||||
$(g).set-rule-name $(__name__).appender ;
|
||||
generators.register $(g) ;
|
||||
return $(id) ;
|
||||
}
|
||||
|
||||
if [ modules.peek : NT ]
|
||||
{
|
||||
X = ")" ;
|
||||
ECHO_CMD = (echo. ;
|
||||
}
|
||||
else
|
||||
{
|
||||
X = \" ;
|
||||
ECHO_CMD = "echo $(X)" ;
|
||||
}
|
||||
|
||||
local appender-runs ;
|
||||
|
||||
# We set up separate actions for building each target in order to avoid having
|
||||
# to iterate over them in action (i.e. shell) code. We have to be extra careful
|
||||
# though to achieve the exact same effect as if doing all the work in just one
|
||||
# action. Otherwise Boost Jam might, under some circumstances, run only some of
|
||||
# our actions. To achieve this we register a series of actions for all the
|
||||
# targets (since they all have the same target list - either all or none of them
|
||||
# get run independent of which target actually needs to get built), each
|
||||
# building only a single target. Since all our actions use the same targets, we
|
||||
# can not use 'on-target' parameters to pass data to a specific action so we
|
||||
# pass them using the second 'sources' parameter which our actions then know how
|
||||
# to interpret correctly. This works well since Boost Jam does not automatically
|
||||
# add dependency relations between specified action targets & sources and so the
|
||||
# second argument, even though most often used to pass in a list of sources, can
|
||||
# actually be used for passing in any type of information.
|
||||
rule appender ( targets + : sources + : properties * )
|
||||
{
|
||||
appender-runs = [ CALC $(appender-runs:E=0) + 1 ] ;
|
||||
local target-index = 0 ;
|
||||
local target-count = [ sequence.length $(targets) ] ;
|
||||
local original-targets ;
|
||||
for t in $(targets)
|
||||
{
|
||||
target-index = [ CALC $(target-index) + 1 ] ;
|
||||
local appender-run = $(appender-runs) ;
|
||||
if $(targets[2])-defined
|
||||
{
|
||||
appender-run += [$(target-index)/$(target-count)] ;
|
||||
}
|
||||
append $(targets) : $(appender-run:J=" ") $(t) $(sources) ;
|
||||
}
|
||||
}
|
||||
|
||||
actions append
|
||||
{
|
||||
$(ECHO_CMD)-------------------------------------------------$(X)
|
||||
$(ECHO_CMD)Appender run: $(>[1])$(X)
|
||||
$(ECHO_CMD)Appender run: $(>[1])$(X)>> "$(>[2])"
|
||||
$(ECHO_CMD)Target group: $(<:J=' ')$(X)
|
||||
$(ECHO_CMD)Target group: $(<:J=' ')$(X)>> "$(>[2])"
|
||||
$(ECHO_CMD) Target: '$(>[2])'$(X)
|
||||
$(ECHO_CMD) Target: '$(>[2])'$(X)>> "$(>[2])"
|
||||
$(ECHO_CMD) Sources: '$(>[3-]:J=' ')'$(X)
|
||||
$(ECHO_CMD) Sources: '$(>[3-]:J=' ')'$(X)>> "$(>[2])"
|
||||
$(ECHO_CMD)=================================================$(X)
|
||||
$(ECHO_CMD)-------------------------------------------------$(X)>> "$(>[2])"
|
||||
}
|
||||
""")
|
||||
|
||||
|
||||
test_basic()
|
||||
test_generated_target_names()
|
||||
@@ -0,0 +1,81 @@
|
||||
#!/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 <implicit-dependency> is respected even if the target referred to is
|
||||
# not built itself, but only referred to by <implicit-dependency>.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.write("jamroot.jam", """
|
||||
make a.h : : gen-header ;
|
||||
explicit a.h ;
|
||||
|
||||
exe hello : hello.cpp : <implicit-dependency>a.h ;
|
||||
|
||||
import os ;
|
||||
if [ os.name ] = NT
|
||||
{
|
||||
actions gen-header
|
||||
{
|
||||
echo int i; > $(<)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
actions gen-header
|
||||
{
|
||||
echo "int i;" > $(<)
|
||||
}
|
||||
}
|
||||
""")
|
||||
|
||||
t.write("hello.cpp", """
|
||||
#include "a.h"
|
||||
int main() { return i; }
|
||||
""")
|
||||
|
||||
|
||||
t.run_build_system()
|
||||
|
||||
t.expect_addition("bin/$toolset/debug/hello.exe")
|
||||
|
||||
t.rm("bin")
|
||||
|
||||
t.write("jamroot.jam", """
|
||||
make dir/a.h : : gen-header ;
|
||||
explicit dir/a.h ;
|
||||
|
||||
exe hello : hello.cpp : <implicit-dependency>dir/a.h ;
|
||||
|
||||
import os ;
|
||||
if [ os.name ] = NT
|
||||
{
|
||||
actions gen-header
|
||||
{
|
||||
echo int i; > $(<)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
actions gen-header
|
||||
{
|
||||
echo "int i;" > $(<)
|
||||
}
|
||||
}
|
||||
""")
|
||||
|
||||
t.write("hello.cpp", """
|
||||
#include "dir/a.h"
|
||||
int main() { return i; }
|
||||
""")
|
||||
t.run_build_system()
|
||||
|
||||
t.expect_addition("bin/$toolset/debug/hello.exe")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,105 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright (C) 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
|
||||
|
||||
def test_basic():
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
exe a1 : a1.cpp : <conditional>@a1-rule ;
|
||||
rule a1-rule ( properties * )
|
||||
{
|
||||
if <variant>debug in $(properties)
|
||||
{
|
||||
return <define>OK ;
|
||||
}
|
||||
}
|
||||
|
||||
exe a2 : a2.cpp : <conditional>@$(__name__).a2-rule
|
||||
<variant>debug:<optimization>speed ;
|
||||
rule a2-rule ( properties * )
|
||||
{
|
||||
if <optimization>speed in $(properties)
|
||||
{
|
||||
return <define>OK ;
|
||||
}
|
||||
}
|
||||
|
||||
exe a3 : a3.cpp :
|
||||
<conditional>@$(__name__).a3-rule-1
|
||||
<conditional>@$(__name__).a3-rule-2 ;
|
||||
rule a3-rule-1 ( properties * )
|
||||
{
|
||||
if <optimization>speed in $(properties)
|
||||
{
|
||||
return <define>OK ;
|
||||
}
|
||||
}
|
||||
rule a3-rule-2 ( properties * )
|
||||
{
|
||||
if <variant>debug in $(properties)
|
||||
{
|
||||
return <optimization>speed ;
|
||||
}
|
||||
}
|
||||
""")
|
||||
|
||||
t.write("a1.cpp", "#ifdef OK\nint main() {}\n#endif\n")
|
||||
t.write("a2.cpp", "#ifdef OK\nint main() {}\n#endif\n")
|
||||
t.write("a3.cpp", "#ifdef OK\nint main() {}\n#endif\n")
|
||||
|
||||
t.run_build_system()
|
||||
|
||||
t.expect_addition("bin/$toolset/debug/a1.exe")
|
||||
t.expect_addition("bin/$toolset/debug/optimization-speed/a2.exe")
|
||||
t.expect_addition("bin/$toolset/debug/optimization-speed/a3.exe")
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
def test_glob_in_indirect_conditional():
|
||||
"""
|
||||
Regression test: project-rules.glob rule run from inside an indirect
|
||||
conditional should report an error as it depends on the 'currently loaded
|
||||
project' concept and indirect conditional rules get called only after all
|
||||
the project modules have already finished loading.
|
||||
|
||||
"""
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
use-project /library-example/foo : util/foo ;
|
||||
build-project app ;
|
||||
""")
|
||||
t.write("app/app.cpp", "int main() {}\n");
|
||||
t.write("app/jamfile.jam", "exe app : app.cpp /library-example/foo//bar ;")
|
||||
t.write("util/foo/bar.cpp", """\
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void foo() {}
|
||||
""")
|
||||
t.write("util/foo/jamfile.jam", """\
|
||||
rule print-my-sources ( properties * )
|
||||
{
|
||||
ECHO My sources: ;
|
||||
ECHO [ glob *.cpp ] ;
|
||||
}
|
||||
lib bar : bar.cpp : <conditional>@print-my-sources ;
|
||||
""")
|
||||
|
||||
t.run_build_system(status=1)
|
||||
t.expect_output_lines(["My sources:", "bar.cpp"], False)
|
||||
t.expect_output_lines("error: Reference to the project currently being "
|
||||
"loaded requested when there was no project module being loaded.")
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
test_basic()
|
||||
test_glob_in_indirect_conditional()
|
||||
@@ -0,0 +1,100 @@
|
||||
#!/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
|
||||
import string
|
||||
|
||||
t = BoostBuild.Tester(pass_toolset=0)
|
||||
|
||||
t.write("a.cpp", "\n")
|
||||
|
||||
t.write("yfc1.jam", """\
|
||||
import feature ;
|
||||
import generators ;
|
||||
|
||||
feature.extend toolset : yfc1 ;
|
||||
rule init ( ) { }
|
||||
|
||||
generators.register-standard yfc1.compile : CPP : OBJ : <toolset>yfc1 ;
|
||||
generators.register-standard yfc1.link : OBJ : EXE : <toolset>yfc1 ;
|
||||
|
||||
actions compile { yfc1-compile }
|
||||
actions link { yfc1-link }
|
||||
""")
|
||||
|
||||
t.write(
|
||||
'yfc1.py',
|
||||
"""
|
||||
from b2.build import feature, generators
|
||||
from b2.manager import get_manager
|
||||
|
||||
MANAGER = get_manager()
|
||||
ENGINE = MANAGER.engine()
|
||||
|
||||
feature.extend('toolset', ['yfc1'])
|
||||
|
||||
generators.register_standard('yfc1.compile', ['CPP'], ['OBJ'], ['<toolset>yfc1'])
|
||||
generators.register_standard('yfc1.link', ['OBJ'], ['EXE'], ['<toolset>yfc1'])
|
||||
|
||||
ENGINE.register_action(
|
||||
'yfc1.compile',
|
||||
'yfc1-compile'
|
||||
)
|
||||
|
||||
ENGINE.register_action(
|
||||
'yfc1.link',
|
||||
'yfc1-link'
|
||||
)
|
||||
|
||||
def init(*args):
|
||||
pass
|
||||
|
||||
"""
|
||||
)
|
||||
|
||||
t.write("yfc2.jam", """\
|
||||
import feature ;
|
||||
import toolset ;
|
||||
|
||||
feature.extend toolset : yfc2 ;
|
||||
toolset.inherit yfc2 : yfc1 ;
|
||||
rule init ( ) { }
|
||||
|
||||
actions link { yfc2-link }
|
||||
""")
|
||||
|
||||
t.write(
|
||||
'yfc2.py',
|
||||
"""
|
||||
from b2.build import feature, toolset
|
||||
from b2.manager import get_manager
|
||||
|
||||
MANAGER = get_manager()
|
||||
ENGINE = MANAGER.engine()
|
||||
|
||||
feature.extend('toolset', ['yfc2'])
|
||||
toolset.inherit('yfc2', 'yfc1')
|
||||
|
||||
ENGINE.register_action('yfc2.link', 'yfc2-link')
|
||||
|
||||
def init(*args):
|
||||
pass
|
||||
"""
|
||||
)
|
||||
|
||||
t.write("jamfile.jam", "exe a : a.cpp ;")
|
||||
t.write("jamroot.jam", "using yfc1 ;")
|
||||
|
||||
t.run_build_system(["-n", "-d2", "yfc1"])
|
||||
t.fail_test(string.find(t.stdout(), "yfc1-link") == -1)
|
||||
|
||||
# Make sure we do not have to explicitly 'use' yfc1.
|
||||
t.write("jamroot.jam", "using yfc2 ;")
|
||||
|
||||
t.run_build_system(["-n", "-d2", "yfc2"])
|
||||
t.fail_test(string.find(t.stdout(), "yfc2-link") == -1)
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,237 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Copyright (c) 2008 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
|
||||
|
||||
tester = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Test without giving the project an explicit id.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
tester.write("jamroot.jam", """
|
||||
lib test : test.cpp ;
|
||||
project : requirements <library>test ;
|
||||
build-project a ;
|
||||
""")
|
||||
|
||||
tester.write("test.cpp", """
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void foo() {}
|
||||
""")
|
||||
|
||||
tester.write("a/test1.cpp", """
|
||||
int main() {}
|
||||
""")
|
||||
|
||||
tester.write("a/jamfile.jam", """
|
||||
exe test1 : test1.cpp ;
|
||||
""")
|
||||
|
||||
tester.run_build_system()
|
||||
|
||||
tester.expect_addition("bin/$toolset/debug/test.obj")
|
||||
tester.expect_addition("a/bin/$toolset/debug/test1.exe")
|
||||
|
||||
tester.rm("bin")
|
||||
tester.rm("a/bin")
|
||||
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Run the same test from the "a" directory.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
tester.run_build_system(subdir="a")
|
||||
|
||||
tester.expect_addition("bin/$toolset/debug/test.obj")
|
||||
tester.expect_addition("a/bin/$toolset/debug/test1.exe")
|
||||
|
||||
tester.rm("bin")
|
||||
tester.rm("a/bin")
|
||||
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# This time, do give the project an id.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
tester.write("jamroot.jam", """
|
||||
lib test : test.cpp ;
|
||||
project test_project : requirements <library>test ;
|
||||
build-project a ;
|
||||
""")
|
||||
|
||||
tester.run_build_system()
|
||||
|
||||
tester.expect_addition("bin/$toolset/debug/test.obj")
|
||||
tester.expect_addition("a/bin/$toolset/debug/test1.exe")
|
||||
|
||||
tester.rm("bin")
|
||||
tester.rm("a/bin")
|
||||
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Now, give the project an id in its attributes.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
tester.write("jamroot.jam", """
|
||||
lib test : test.cpp ;
|
||||
project : id test_project : requirements <library>test ;
|
||||
build-project a ;
|
||||
""")
|
||||
|
||||
tester.run_build_system()
|
||||
|
||||
tester.expect_addition("bin/$toolset/debug/test.obj")
|
||||
tester.expect_addition("a/bin/$toolset/debug/test1.exe")
|
||||
|
||||
tester.rm("bin")
|
||||
tester.rm("a/bin")
|
||||
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Give the project an id in both ways at once.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
tester.write("jamroot.jam", """
|
||||
lib test : test.cpp ;
|
||||
project test_project1 : id test_project : requirements <library>test ;
|
||||
build-project a ;
|
||||
""")
|
||||
|
||||
tester.run_build_system()
|
||||
|
||||
tester.expect_addition("bin/$toolset/debug/test.obj")
|
||||
tester.expect_addition("a/bin/$toolset/debug/test1.exe")
|
||||
|
||||
tester.rm("bin")
|
||||
tester.rm("a/bin")
|
||||
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Test an absolute path in native format.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
tester.write("jamroot.jam", """
|
||||
import path ;
|
||||
path-constant here : . ;
|
||||
current-location = [ path.native [ path.root [ path.make $(here) ] [ path.pwd ]
|
||||
] ] ;
|
||||
project test : requirements <source>$(current-location)/a/test1.cpp ;
|
||||
exe test : test.cpp ;
|
||||
""")
|
||||
|
||||
tester.run_build_system()
|
||||
tester.expect_addition("bin/$toolset/debug/test.exe")
|
||||
|
||||
tester.rm("bin")
|
||||
tester.rm("a/bin")
|
||||
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Test an absolute path in canonical format.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
tester.write("jamroot.jam", """
|
||||
import path ;
|
||||
path-constant here : . ;
|
||||
current-location = [ path.root [ path.make $(here) ] [ path.pwd ] ] ;
|
||||
project test : requirements <source>$(current-location)/a/test1.cpp ;
|
||||
exe test : test.cpp ;
|
||||
""")
|
||||
|
||||
tester.run_build_system()
|
||||
tester.expect_addition("bin/$toolset/debug/test.exe")
|
||||
|
||||
tester.rm("bin")
|
||||
tester.rm("a/bin")
|
||||
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Test dependency properties (e.g. <source>) whose targets are specified using a
|
||||
# relative path.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
# Use jamroot.jam rather than jamfile.jam to avoid inheriting the <source> from
|
||||
# the parent as that would would make test3 a source of itself.
|
||||
tester.write("b/jamroot.jam", """
|
||||
obj test3 : test3.cpp ;
|
||||
""")
|
||||
|
||||
tester.write("b/test3.cpp", """
|
||||
void bar() {}
|
||||
""")
|
||||
|
||||
tester.write("jamroot.jam", """
|
||||
project test : requirements <source>b//test3 ;
|
||||
build-project a ;
|
||||
""")
|
||||
|
||||
tester.write("a/jamfile.jam", """
|
||||
exe test : test1.cpp ;
|
||||
""")
|
||||
|
||||
tester.write("a/test1.cpp", """
|
||||
void bar();
|
||||
int main() { bar(); }
|
||||
""")
|
||||
|
||||
tester.run_build_system()
|
||||
tester.expect_addition("b/bin/$toolset/debug/test3.obj")
|
||||
tester.expect_addition("a/bin/$toolset/debug/test.exe")
|
||||
|
||||
tester.rm("bin")
|
||||
tester.rm("a")
|
||||
tester.rm("jamroot.jam")
|
||||
tester.rm("test.cpp")
|
||||
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Test that source-location is respected.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
tester.write("build/jamroot.jam", """
|
||||
project : requirements <source>test.cpp : source-location ../src ;
|
||||
""")
|
||||
|
||||
tester.write("src/test.cpp", """
|
||||
int main() {}
|
||||
""")
|
||||
|
||||
tester.write("build/a/jamfile.jam", """
|
||||
project : source-location ../../a_src ;
|
||||
exe test : test1.cpp ;
|
||||
""")
|
||||
|
||||
tester.write("a_src/test1.cpp", """
|
||||
""")
|
||||
|
||||
tester.run_build_system(subdir="build/a")
|
||||
tester.expect_addition("build/a/bin/$toolset/debug/test.exe")
|
||||
|
||||
tester.cleanup()
|
||||
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2003, 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)
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
project : requirements <link>static ;
|
||||
exe a : a.cpp [ lib helper : helper.cpp ] ;
|
||||
""")
|
||||
|
||||
t.write("a.cpp", """\
|
||||
extern void helper();
|
||||
int main() {}
|
||||
""")
|
||||
|
||||
t.write("helper.cpp", "void helper() {}\n")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition("bin/$toolset/debug/link-static/a__helper.lib")
|
||||
t.rm("bin/$toolset/debug/link-static/a__helper.lib")
|
||||
|
||||
t.run_build_system(["a__helper"])
|
||||
t.expect_addition("bin/$toolset/debug/link-static/a__helper.lib")
|
||||
|
||||
t.rm("bin")
|
||||
|
||||
|
||||
# Now check that inline targets with the same name but present in different
|
||||
# places are not confused between each other, and with top-level targets.
|
||||
t.write("jamroot.jam", """\
|
||||
project : requirements <link>static ;
|
||||
exe a : a.cpp [ lib helper : helper.cpp ] ;
|
||||
exe a2 : a.cpp [ lib helper : helper.cpp ] ;
|
||||
""")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition("bin/$toolset/debug/link-static/a.exe")
|
||||
t.expect_addition("bin/$toolset/debug/link-static/a__helper.lib")
|
||||
t.expect_addition("bin/$toolset/debug/link-static/a2__helper.lib")
|
||||
|
||||
|
||||
# Check that the 'alias' target does not change the name of inline targets, and
|
||||
# that inline targets are explicit.
|
||||
t.write("jamroot.jam", """\
|
||||
project : requirements <link>static ;
|
||||
alias a : [ lib helper : helper.cpp ] ;
|
||||
explicit a ;
|
||||
""")
|
||||
t.rm("bin")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.run_build_system(["a"])
|
||||
t.expect_addition("bin/$toolset/debug/link-static/helper.lib")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/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)
|
||||
|
||||
# Regression test: if a library had no explicit sources, but only <source>
|
||||
# properties, it was built as if it were a searched library, and the specified
|
||||
# sources were not compiled.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.write("jamroot.jam", """
|
||||
lib a : : <source>a.cpp ;
|
||||
""")
|
||||
|
||||
t.write("a.cpp", """
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void foo() {}
|
||||
""")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition("bin/$toolset/debug/a.obj")
|
||||
|
||||
t.rm("bin")
|
||||
|
||||
|
||||
# Now try with <conditional>.
|
||||
t.write("jamroot.jam", """
|
||||
rule test ( properties * )
|
||||
{
|
||||
return <source>a.cpp ;
|
||||
}
|
||||
lib a : : <conditional>@test ;
|
||||
""")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition("bin/$toolset/debug/a.obj")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,119 @@
|
||||
#!/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("libjpeg/jpeg.h", 'libjpeg')
|
||||
t.write("libjpeg/jpeg.c", 'jpeg')
|
||||
|
||||
t.write("Jamroot.jam", """
|
||||
path-constant here : . ;
|
||||
using libjpeg : : <source>$(here)/libjpeg ;
|
||||
alias libjpeg : /libjpeg//libjpeg : : <link>static <link>shared ;
|
||||
""")
|
||||
|
||||
MockToolset.set_expected(t, '''
|
||||
source_file('jpeg.c', 'jpeg')
|
||||
action('-c -x c -I./libjpeg -o $jpeg.o $jpeg.c')
|
||||
action('--dll $jpeg.o -o $jpeg.so')
|
||||
action('--archive $jpeg.o -o $jpeg.a')
|
||||
''')
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition('bin/standalone/libjpeg/mock/debug/jpeg.dll')
|
||||
t.expect_addition('bin/standalone/libjpeg/mock/debug/link-static/jpeg.lib')
|
||||
|
||||
t.rm('libjpeg')
|
||||
|
||||
# Generic definitions that aren't configuration specific
|
||||
common_stuff = '''
|
||||
source_file('test.cpp', 'test.cpp')
|
||||
source_file('main.cpp', 'int main() {}')
|
||||
source_file('jpeg.h.cpp', '#include <jpeg.h>')
|
||||
action('-c -x c++ $main.cpp -o $main.o')
|
||||
'''
|
||||
t.write('test.cpp', 'test.cpp')
|
||||
|
||||
# Default initialization - static library
|
||||
t.rm('bin')
|
||||
t.write("Jamroot.jam", """
|
||||
path-constant here : . ;
|
||||
using libjpeg ;
|
||||
exe test : test.cpp /libjpeg//libjpeg : : <link>static <link>shared ;
|
||||
""")
|
||||
|
||||
MockToolset.set_expected(t, common_stuff + '''
|
||||
action('$main.o --static-lib=jpeg -o $config.exe')
|
||||
action('-c -x c++ $jpeg.h.cpp -o $jpeg.h.o')
|
||||
action('-c -x c++ $test.cpp -o $test.o')
|
||||
action('$test.o --static-lib=jpeg -o $test')
|
||||
''')
|
||||
t.run_build_system()
|
||||
t.expect_addition('bin/mock/debug/test.exe')
|
||||
t.expect_addition('bin/mock/debug/link-static/test.exe')
|
||||
|
||||
# Default initialization - shared library
|
||||
t.rm('bin')
|
||||
t.write("Jamroot.jam", """
|
||||
path-constant here : . ;
|
||||
using libjpeg ;
|
||||
exe test : test.cpp /libjpeg//libjpeg : : <link>static <link>shared ;
|
||||
""")
|
||||
|
||||
MockToolset.set_expected(t, common_stuff + '''
|
||||
action('$main.o --shared-lib=jpeg -o $config.exe')
|
||||
action('-c -x c++ $jpeg.h.cpp -o $jpeg.h.o')
|
||||
action('-c -x c++ $test.cpp -o $test.o')
|
||||
action('$test.o --shared-lib=jpeg -o $test')
|
||||
''')
|
||||
t.run_build_system()
|
||||
t.expect_addition('bin/mock/debug/test.exe')
|
||||
t.expect_addition('bin/mock/debug/link-static/test.exe')
|
||||
|
||||
# Initialization in explicit location - static library
|
||||
t.rm('bin')
|
||||
t.write("Jamroot.jam", """
|
||||
path-constant here : . ;
|
||||
using libjpeg : : <name>mylibjpeg <include>$(here)/libjpeg <search>$(here)/libjpeg ;
|
||||
exe test : test.cpp /libjpeg//libjpeg : : <link>static <link>shared ;
|
||||
""")
|
||||
|
||||
t.write('libjpeg/jpeg.h', 'libjpeg')
|
||||
|
||||
MockToolset.set_expected(t, common_stuff + '''
|
||||
action('$main.o -L./libjpeg --static-lib=mylibjpeg -o $config.exe')
|
||||
action('-c -x c++ $test.cpp -I./libjpeg -o $test.o')
|
||||
action('$test.o -L./libjpeg --static-lib=mylibjpeg -o $test')
|
||||
''')
|
||||
t.run_build_system()
|
||||
t.expect_addition('bin/mock/debug/test.exe')
|
||||
t.expect_addition('bin/mock/debug/link-static/test.exe')
|
||||
|
||||
# Initialization in explicit location - shared library
|
||||
t.rm('bin')
|
||||
t.write("Jamroot.jam", """
|
||||
path-constant here : . ;
|
||||
using libjpeg : : <name>mylibjpeg <include>$(here)/libjpeg <search>$(here)/libjpeg ;
|
||||
exe test : test.cpp /libjpeg//libjpeg : : <link>static <link>shared ;
|
||||
""")
|
||||
|
||||
MockToolset.set_expected(t, common_stuff + '''
|
||||
action('$main.o -L./libjpeg --shared-lib=mylibjpeg -o $config.exe')
|
||||
action('-c -x c++ $test.cpp -I./libjpeg -o $test.o')
|
||||
action('$test.o -L./libjpeg --shared-lib=mylibjpeg -o $test')
|
||||
''')
|
||||
t.run_build_system()
|
||||
t.expect_addition('bin/mock/debug/test.exe')
|
||||
t.expect_addition('bin/mock/debug/link-static/test.exe')
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,119 @@
|
||||
#!/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("libpng/png.h", 'libpng')
|
||||
t.write("libpng/png.c", 'png')
|
||||
|
||||
t.write("Jamroot.jam", """
|
||||
path-constant here : . ;
|
||||
using libpng : : <source>$(here)/libpng ;
|
||||
alias libpng : /libpng//libpng : : <link>static <link>shared ;
|
||||
""")
|
||||
|
||||
MockToolset.set_expected(t, '''
|
||||
source_file('png.c', 'png')
|
||||
action('-c -x c -I./libpng -o $png.o $png.c')
|
||||
action('--dll $png.o -o $png.so')
|
||||
action('--archive $png.o -o $png.a')
|
||||
''')
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition('bin/standalone/libpng/mock/debug/png.dll')
|
||||
t.expect_addition('bin/standalone/libpng/mock/debug/link-static/png.lib')
|
||||
|
||||
t.rm('libpng')
|
||||
|
||||
# Generic definitions that aren't configuration specific
|
||||
common_stuff = '''
|
||||
source_file('test.cpp', 'test.cpp')
|
||||
source_file('main.cpp', 'int main() {}')
|
||||
source_file('png.h.cpp', '#include <png.h>')
|
||||
action('-c -x c++ $main.cpp -o $main.o')
|
||||
'''
|
||||
t.write('test.cpp', 'test.cpp')
|
||||
|
||||
# Default initialization - static library
|
||||
t.rm('bin')
|
||||
t.write("Jamroot.jam", """
|
||||
path-constant here : . ;
|
||||
using libpng ;
|
||||
exe test : test.cpp /libpng//libpng : : <link>static <link>shared ;
|
||||
""")
|
||||
|
||||
MockToolset.set_expected(t, common_stuff + '''
|
||||
action('$main.o --static-lib=png -o $config.exe')
|
||||
action('-c -x c++ $png.h.cpp -o $png.h.o')
|
||||
action('-c -x c++ $test.cpp -o $test.o')
|
||||
action('$test.o --static-lib=png -o $test')
|
||||
''')
|
||||
t.run_build_system()
|
||||
t.expect_addition('bin/mock/debug/test.exe')
|
||||
t.expect_addition('bin/mock/debug/link-static/test.exe')
|
||||
|
||||
# Default initialization - shared library
|
||||
t.rm('bin')
|
||||
t.write("Jamroot.jam", """
|
||||
path-constant here : . ;
|
||||
using libpng ;
|
||||
exe test : test.cpp /libpng//libpng : : <link>static <link>shared ;
|
||||
""")
|
||||
|
||||
MockToolset.set_expected(t, common_stuff + '''
|
||||
action('$main.o --shared-lib=png -o $config.exe')
|
||||
action('-c -x c++ $png.h.cpp -o $png.h.o')
|
||||
action('-c -x c++ $test.cpp -o $test.o')
|
||||
action('$test.o --shared-lib=png -o $test')
|
||||
''')
|
||||
t.run_build_system()
|
||||
t.expect_addition('bin/mock/debug/test.exe')
|
||||
t.expect_addition('bin/mock/debug/link-static/test.exe')
|
||||
|
||||
# Initialization in explicit location - static library
|
||||
t.rm('bin')
|
||||
t.write("Jamroot.jam", """
|
||||
path-constant here : . ;
|
||||
using libpng : : <name>mylibpng <include>$(here)/libpng <search>$(here)/libpng ;
|
||||
exe test : test.cpp /libpng//libpng : : <link>static <link>shared ;
|
||||
""")
|
||||
|
||||
t.write('libpng/png.h', 'libpng')
|
||||
|
||||
MockToolset.set_expected(t, common_stuff + '''
|
||||
action('$main.o -L./libpng --static-lib=mylibpng -o $config.exe')
|
||||
action('-c -x c++ $test.cpp -I./libpng -o $test.o')
|
||||
action('$test.o -L./libpng --static-lib=mylibpng -o $test')
|
||||
''')
|
||||
t.run_build_system()
|
||||
t.expect_addition('bin/mock/debug/test.exe')
|
||||
t.expect_addition('bin/mock/debug/link-static/test.exe')
|
||||
|
||||
# Initialization in explicit location - shared library
|
||||
t.rm('bin')
|
||||
t.write("Jamroot.jam", """
|
||||
path-constant here : . ;
|
||||
using libpng : : <name>mylibpng <include>$(here)/libpng <search>$(here)/libpng ;
|
||||
exe test : test.cpp /libpng//libpng : : <link>static <link>shared ;
|
||||
""")
|
||||
|
||||
MockToolset.set_expected(t, common_stuff + '''
|
||||
action('$main.o -L./libpng --shared-lib=mylibpng -o $config.exe')
|
||||
action('-c -x c++ $test.cpp -I./libpng -o $test.o')
|
||||
action('$test.o -L./libpng --shared-lib=mylibpng -o $test')
|
||||
''')
|
||||
t.run_build_system()
|
||||
t.expect_addition('bin/mock/debug/test.exe')
|
||||
t.expect_addition('bin/mock/debug/link-static/test.exe')
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,152 @@
|
||||
#!/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 os
|
||||
import string
|
||||
|
||||
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", """\
|
||||
void
|
||||
#if defined(_WIN32)
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
gee() {}
|
||||
void
|
||||
#if defined(_WIN32)
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
geek() {}
|
||||
""")
|
||||
|
||||
t.write("a/jamfile.jam", "lib a : a.cpp ;")
|
||||
|
||||
t.write("b/b.cpp", """\
|
||||
void geek();
|
||||
void
|
||||
#if defined(_WIN32)
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
foo() { geek(); }
|
||||
""")
|
||||
|
||||
t.write("b/jamfile.jam", "lib b : b.cpp ../a//a ;")
|
||||
|
||||
t.run_build_system(["-d2"], stderr=None)
|
||||
t.expect_addition("bin/$toolset/debug/main.exe")
|
||||
t.rm(["bin", "a/bin", "b/bin"])
|
||||
|
||||
t.run_build_system(["link=static"])
|
||||
t.expect_addition("bin/$toolset/debug/link-static/main.exe")
|
||||
t.rm(["bin", "a/bin", "b/bin"])
|
||||
|
||||
|
||||
# Check that <library> works for static linking.
|
||||
t.write("b/jamfile.jam", "lib b : b.cpp : <library>../a//a ;")
|
||||
|
||||
t.run_build_system(["link=static"])
|
||||
t.expect_addition("bin/$toolset/debug/link-static/main.exe")
|
||||
|
||||
t.rm(["bin", "a/bin", "b/bin"])
|
||||
|
||||
t.write("b/jamfile.jam", "lib b : b.cpp ../a//a/<link>shared : <link>static ;")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition("bin/$toolset/debug/main.exe")
|
||||
|
||||
t.rm(["bin", "a/bin", "b/bin"])
|
||||
|
||||
|
||||
# Test that putting a library in sources of a searched library works.
|
||||
t.write("jamfile.jam", """\
|
||||
exe main : main.cpp png ;
|
||||
lib png : z : <name>png ;
|
||||
lib z : : <name>zzz ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-a", "-d+2"], status=None, stderr=None)
|
||||
# Try to find the "zzz" string either in response file (for Windows compilers),
|
||||
# or in the standard output.
|
||||
rsp = t.adjust_names("bin/$toolset/debug/main.exe.rsp")[0]
|
||||
if os.path.exists(rsp) and ( string.find(open(rsp).read(), "zzz") != -1 ):
|
||||
pass
|
||||
elif string.find(t.stdout(), "zzz") != -1:
|
||||
pass
|
||||
else:
|
||||
t.fail_test(1)
|
||||
|
||||
# Test main -> libb -> liba chain in the case where liba is a file and not a
|
||||
# Boost.Build target.
|
||||
t.rm(".")
|
||||
|
||||
t.write("jamroot.jam", "")
|
||||
t.write("a/jamfile.jam", """\
|
||||
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 a 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)
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void b() { a(); }
|
||||
""")
|
||||
|
||||
t.write("jamroot.jam", "exe main : main.cpp b//b ;")
|
||||
|
||||
t.write("main.cpp", """\
|
||||
#if defined(_WIN32)
|
||||
__declspec(dllimport)
|
||||
#endif
|
||||
void b();
|
||||
int main() { b(); }
|
||||
""")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition("bin/$toolset/debug/main.exe")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 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)
|
||||
|
||||
# Test that on compilers sensitive to library order on linker's command line,
|
||||
# we generate the correct order.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.write("main.cpp", """\
|
||||
void a();
|
||||
int main() { a(); }
|
||||
""")
|
||||
|
||||
t.write("a.cpp", """\
|
||||
void b();
|
||||
void a() { b(); }
|
||||
""")
|
||||
|
||||
t.write("b.cpp", """\
|
||||
void c();
|
||||
void b() { c(); }
|
||||
""")
|
||||
|
||||
t.write("c.cpp", """\
|
||||
void d();
|
||||
void c() { d(); }
|
||||
""")
|
||||
|
||||
t.write("d.cpp", """\
|
||||
void d() {}
|
||||
""")
|
||||
|
||||
# The order of libraries in 'main' is crafted so that we get an error unless we
|
||||
# do something about the order ourselves.
|
||||
t.write("jamroot.jam", """\
|
||||
exe main : main.cpp libd libc libb liba ;
|
||||
lib libd : d.cpp ;
|
||||
lib libc : c.cpp : <link>static <use>libd ;
|
||||
lib libb : b.cpp : <use>libc ;
|
||||
lib liba : a.cpp : <use>libb ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-d2"])
|
||||
t.expect_addition("bin/$toolset/debug/main.exe")
|
||||
|
||||
|
||||
# Test the order between searched libraries.
|
||||
t.write("jamroot.jam", """\
|
||||
exe main : main.cpp png z ;
|
||||
lib png : z : <name>png ;
|
||||
lib z : : <name>zzz ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-a", "-n", "-d+2"])
|
||||
t.fail_test(t.stdout().find("png") > t.stdout().find("zzz"))
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
exe main : main.cpp png z ;
|
||||
lib png : : <name>png ;
|
||||
lib z : png : <name>zzz ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-a", "-n", "-d+2"])
|
||||
t.fail_test(t.stdout().find("png") < t.stdout().find("zzz"))
|
||||
|
||||
|
||||
# Test the order between prebuilt libraries.
|
||||
t.write("first.a", "")
|
||||
t.write("second.a", "")
|
||||
t.write("jamroot.jam", """\
|
||||
exe main : main.cpp first second ;
|
||||
lib first : second : <file>first.a ;
|
||||
lib second : : <file>second.a ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-a", "-n", "-d+2"])
|
||||
t.fail_test(t.stdout().find("first") > t.stdout().find("second"))
|
||||
|
||||
t.write("jamroot.jam", """
|
||||
exe main : main.cpp first second ;
|
||||
lib first : : <file>first.a ;
|
||||
lib second : first : <file>second.a ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["-a", "-n", "-d+2"])
|
||||
t.fail_test(t.stdout().find("first") < t.stdout().find("second"))
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 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)
|
||||
|
||||
# Test that the <library> property has no effect on "obj" targets. Previously,
|
||||
# it affected all targets, so
|
||||
#
|
||||
# project : requirements <library>foo ;
|
||||
# exe a : a.cpp helper ;
|
||||
# obj helper : helper.cpp : <optimization>off ;
|
||||
#
|
||||
# caused 'foo' to be built with and without optimization.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.write("jamroot.jam", """
|
||||
project : requirements <library>lib//x ;
|
||||
exe a : a.cpp foo ;
|
||||
obj foo : foo.cpp : <variant>release ;
|
||||
""")
|
||||
|
||||
t.write("a.cpp", """
|
||||
void aux();
|
||||
int main() { aux(); }
|
||||
""")
|
||||
|
||||
t.write("foo.cpp", """
|
||||
void gee();
|
||||
void aux() { gee(); }
|
||||
""")
|
||||
|
||||
t.write("lib/x.cpp", """
|
||||
void
|
||||
#if defined(_WIN32)
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
gee() {}
|
||||
""")
|
||||
|
||||
t.write("lib/jamfile.jam", """
|
||||
lib x : x.cpp ;
|
||||
""")
|
||||
|
||||
t.write("lib/jamroot.jam", """
|
||||
""")
|
||||
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition("bin/$toolset/debug/a.exe")
|
||||
t.expect_nothing("lib/bin/$toolset/release/x.obj")
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,119 @@
|
||||
#!/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')
|
||||
''')
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition('bin/standalone/libtiff/mock/debug/tiff.dll')
|
||||
t.expect_addition('bin/standalone/libtiff/mock/debug/link-static/tiff.lib')
|
||||
|
||||
t.rm('libtiff')
|
||||
|
||||
# Generic definitions that aren't configuration specific
|
||||
common_stuff = '''
|
||||
source_file('test.cpp', 'test.cpp')
|
||||
source_file('main.cpp', 'int main() {}')
|
||||
source_file('tiff.h.cpp', '#include <tiff.h>')
|
||||
action('-c -x c++ $main.cpp -o $main.o')
|
||||
'''
|
||||
t.write('test.cpp', 'test.cpp')
|
||||
|
||||
# Default initialization - static library
|
||||
t.rm('bin')
|
||||
t.write("Jamroot.jam", """
|
||||
path-constant here : . ;
|
||||
using libtiff ;
|
||||
exe test : test.cpp /libtiff//libtiff : : <link>static <link>shared ;
|
||||
""")
|
||||
|
||||
MockToolset.set_expected(t, common_stuff + '''
|
||||
action('$main.o --static-lib=tiff -o $config.exe')
|
||||
action('-c -x c++ $tiff.h.cpp -o $tiff.h.o')
|
||||
action('-c -x c++ $test.cpp -o $test.o')
|
||||
action('$test.o --static-lib=tiff -o $test')
|
||||
''')
|
||||
t.run_build_system()
|
||||
t.expect_addition('bin/mock/debug/test.exe')
|
||||
t.expect_addition('bin/mock/debug/link-static/test.exe')
|
||||
|
||||
# Default initialization - shared library
|
||||
t.rm('bin')
|
||||
t.write("Jamroot.jam", """
|
||||
path-constant here : . ;
|
||||
using libtiff ;
|
||||
exe test : test.cpp /libtiff//libtiff : : <link>static <link>shared ;
|
||||
""")
|
||||
|
||||
MockToolset.set_expected(t, common_stuff + '''
|
||||
action('$main.o --shared-lib=tiff -o $config.exe')
|
||||
action('-c -x c++ $tiff.h.cpp -o $tiff.h.o')
|
||||
action('-c -x c++ $test.cpp -o $test.o')
|
||||
action('$test.o --shared-lib=tiff -o $test')
|
||||
''')
|
||||
t.run_build_system()
|
||||
t.expect_addition('bin/mock/debug/test.exe')
|
||||
t.expect_addition('bin/mock/debug/link-static/test.exe')
|
||||
|
||||
# Initialization in explicit location - static library
|
||||
t.rm('bin')
|
||||
t.write("Jamroot.jam", """
|
||||
path-constant here : . ;
|
||||
using libtiff : : <name>mylibtiff <include>$(here)/libtiff <search>$(here)/libtiff ;
|
||||
exe test : test.cpp /libtiff//libtiff : : <link>static <link>shared ;
|
||||
""")
|
||||
|
||||
t.write('libtiff/tiff.h', 'libtiff')
|
||||
|
||||
MockToolset.set_expected(t, common_stuff + '''
|
||||
action('$main.o -L./libtiff --static-lib=mylibtiff -o $config.exe')
|
||||
action('-c -x c++ $test.cpp -I./libtiff -o $test.o')
|
||||
action('$test.o -L./libtiff --static-lib=mylibtiff -o $test')
|
||||
''')
|
||||
t.run_build_system()
|
||||
t.expect_addition('bin/mock/debug/test.exe')
|
||||
t.expect_addition('bin/mock/debug/link-static/test.exe')
|
||||
|
||||
# Initialization in explicit location - shared library
|
||||
t.rm('bin')
|
||||
t.write("Jamroot.jam", """
|
||||
path-constant here : . ;
|
||||
using libtiff : : <name>mylibtiff <include>$(here)/libtiff <search>$(here)/libtiff ;
|
||||
exe test : test.cpp /libtiff//libtiff : : <link>static <link>shared ;
|
||||
""")
|
||||
|
||||
MockToolset.set_expected(t, common_stuff + '''
|
||||
action('$main.o -L./libtiff --shared-lib=mylibtiff -o $config.exe')
|
||||
action('-c -x c++ $test.cpp -I./libtiff -o $test.o')
|
||||
action('$test.o -L./libtiff --shared-lib=mylibtiff -o $test')
|
||||
''')
|
||||
t.run_build_system()
|
||||
t.expect_addition('bin/mock/debug/test.exe')
|
||||
t.expect_addition('bin/mock/debug/link-static/test.exe')
|
||||
|
||||
t.cleanup()
|
||||
@@ -0,0 +1,334 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2014-2015 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)
|
||||
|
||||
# Tests the link-directory rule used to create the
|
||||
# common boost/ directory in the new git layout.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
def ignore_config(t):
|
||||
"""These files are created by the configuration logic in link.jam
|
||||
They may or may not exist, depending on the system."""
|
||||
t.ignore("bin/symlink/test-hardlink")
|
||||
t.ignore("bin/test-hardlink-source")
|
||||
t.ignore("bin/test-symlink")
|
||||
t.ignore("bin/test-symlink-source")
|
||||
|
||||
def test_basic():
|
||||
"""Test creation of a single link"""
|
||||
t = BoostBuild.Tester()
|
||||
t.write("jamroot.jam", """\
|
||||
import link ;
|
||||
link-directory dir1-link : src/dir1/include : <location>. ;
|
||||
""")
|
||||
|
||||
t.write("src/dir1/include/file1.h", "file1")
|
||||
|
||||
t.run_build_system()
|
||||
|
||||
t.expect_addition("include/file1.h")
|
||||
t.expect_content("include/file1.h", "file1")
|
||||
ignore_config(t)
|
||||
t.expect_nothing_more()
|
||||
t.cleanup()
|
||||
|
||||
def test_merge_two():
|
||||
"""Test merging two directories"""
|
||||
t = BoostBuild.Tester()
|
||||
t.write("jamroot.jam", """\
|
||||
import link ;
|
||||
link-directory dir1-link : src/dir1/include : <location>. ;
|
||||
link-directory dir2-link : src/dir2/include : <location>. ;
|
||||
""")
|
||||
|
||||
t.write("src/dir1/include/file1.h", "file1")
|
||||
t.write("src/dir2/include/file2.h", "file2")
|
||||
|
||||
t.run_build_system()
|
||||
|
||||
t.expect_addition("include/file1.h")
|
||||
t.expect_content("include/file1.h", "file1")
|
||||
t.expect_addition("include/file2.h")
|
||||
t.expect_content("include/file2.h", "file2")
|
||||
ignore_config(t)
|
||||
t.expect_nothing_more()
|
||||
t.cleanup()
|
||||
|
||||
def test_merge_existing(group1, group2):
|
||||
"""Test adding a link when a different symlink already exists"""
|
||||
t = BoostBuild.Tester()
|
||||
t.write("jamroot.jam", """\
|
||||
import link ;
|
||||
link-directory dir1-link : src/dir1/include : <location>. ;
|
||||
link-directory dir2-link : src/dir2/include : <location>. ;
|
||||
""")
|
||||
|
||||
t.write("src/dir1/include/file1.h", "file1")
|
||||
t.write("src/dir2/include/file2.h", "file2")
|
||||
|
||||
t.run_build_system(group1)
|
||||
|
||||
if "dir1-link" in group1:
|
||||
t.expect_addition("include/file1.h")
|
||||
t.expect_content("include/file1.h", "file1")
|
||||
if "dir2-link" in group1:
|
||||
t.expect_addition("include/file2.h")
|
||||
t.expect_content("include/file2.h", "file2")
|
||||
ignore_config(t)
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.run_build_system(group2)
|
||||
|
||||
if "dir1-link" in group2:
|
||||
if "dir1-link" not in group1:
|
||||
t.expect_addition("include/file1.h")
|
||||
t.expect_content("include/file1.h", "file1")
|
||||
else:
|
||||
t.ignore_removal("include/file1.h")
|
||||
|
||||
if "dir2-link" in group2:
|
||||
if "dir2-link" not in group1:
|
||||
t.expect_addition("include/file2.h")
|
||||
t.expect_content("include/file2.h", "file2")
|
||||
else:
|
||||
t.ignore_removal("include/file2.h")
|
||||
ignore_config(t)
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.cleanup()
|
||||
|
||||
def test_merge_existing_all():
|
||||
test_merge_existing(["dir1-link"], ["dir2-link"])
|
||||
test_merge_existing(["dir2-link"], ["dir1-link"])
|
||||
test_merge_existing(["dir1-link"], ["dir1-link", "dir2-link"])
|
||||
test_merge_existing(["dir2-link"], ["dir1-link", "dir2-link"])
|
||||
|
||||
def test_merge_recursive():
|
||||
"Test merging several directories including common prefixes"
|
||||
t = BoostBuild.Tester()
|
||||
t.write("jamroot.jam", """\
|
||||
import link ;
|
||||
link-directory dir1-link : src/dir1/include : <location>. ;
|
||||
link-directory dir2-link : src/dir2/include : <location>. ;
|
||||
link-directory dir3-link : src/dir3/include : <location>. ;
|
||||
""")
|
||||
|
||||
t.write("src/dir1/include/file1.h", "file1")
|
||||
t.write("src/dir2/include/file2.h", "file2")
|
||||
t.write("src/dir2/include/nested/file3.h", "file3")
|
||||
t.write("src/dir3/include/nested/file4.h", "file4")
|
||||
|
||||
t.run_build_system()
|
||||
|
||||
t.expect_addition("include/file1.h")
|
||||
t.expect_content("include/file1.h", "file1")
|
||||
t.expect_addition("include/file2.h")
|
||||
t.expect_content("include/file2.h", "file2")
|
||||
t.expect_addition("include/nested/file3.h")
|
||||
t.expect_content("include/nested/file3.h", "file3")
|
||||
t.expect_addition("include/nested/file4.h")
|
||||
t.expect_content("include/nested/file4.h", "file4")
|
||||
ignore_config(t)
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.cleanup()
|
||||
|
||||
def test_merge_recursive_existing(group1, group2):
|
||||
"Test merging several directories including common prefixes."
|
||||
t = BoostBuild.Tester()
|
||||
t.write("jamroot.jam", """\
|
||||
import link ;
|
||||
link-directory dir1-link : src/dir1/include : <location>. ;
|
||||
link-directory dir2-link : src/dir2/include : <location>. ;
|
||||
link-directory dir3-link : src/dir3/include : <location>. ;
|
||||
link-directory dir4-link : src/dir4/include : <location>. ;
|
||||
link-directory dir5-link : src/dir5/include : <location>. ;
|
||||
""")
|
||||
|
||||
t.write("src/dir1/include/file1.h", "file1")
|
||||
t.write("src/dir2/include/nested/file2.h", "file2")
|
||||
t.write("src/dir3/include/nested/file3.h", "file3")
|
||||
t.write("src/dir4/include/nested/xxx/yyy/file4.h", "file4")
|
||||
t.write("src/dir5/include/nested/xxx/yyy/file5.h", "file5")
|
||||
|
||||
t.run_build_system(group1)
|
||||
t.run_build_system(group2 + ["-d+12"])
|
||||
|
||||
t.ignore_addition("include/file1.h")
|
||||
t.ignore_addition("include/nested/file2.h")
|
||||
t.ignore_addition("include/nested/file3.h")
|
||||
t.ignore_addition("include/nested/xxx/yyy/file4.h")
|
||||
t.ignore_addition("include/nested/xxx/yyy/file5.h")
|
||||
ignore_config(t)
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.cleanup()
|
||||
|
||||
def test_merge_recursive_existing_all():
|
||||
# These should create a link
|
||||
test_merge_recursive_existing(["dir2-link"], ["dir2-link", "dir1-link"])
|
||||
test_merge_recursive_existing(["dir2-link"], ["dir1-link", "dir2-link"])
|
||||
# These should create a directory
|
||||
test_merge_recursive_existing(["dir2-link"], ["dir2-link", "dir3-link"])
|
||||
test_merge_recursive_existing(["dir2-link"], ["dir3-link", "dir2-link"])
|
||||
# It should work even if we have to create many intermediate subdirectories
|
||||
test_merge_recursive_existing(["dir4-link"], ["dir4-link", "dir5-link"])
|
||||
test_merge_recursive_existing(["dir4-link"], ["dir5-link", "dir4-link"])
|
||||
|
||||
def test_include_scan():
|
||||
"""Make sure that the #include scanner finds the headers"""
|
||||
t = BoostBuild.Tester()
|
||||
t.write("jamroot.jam", """\
|
||||
import link ;
|
||||
link-directory dir1-link : src/dir1/include : <location>. ;
|
||||
link-directory dir2-link : src/dir2/include : <location>. ;
|
||||
obj test : test.cpp :
|
||||
<include>include
|
||||
<implicit-dependency>dir1-link
|
||||
<implicit-dependency>dir2-link ;
|
||||
""")
|
||||
|
||||
t.write("src/dir1/include/file1.h", "#include <file2.h>\n")
|
||||
t.write("src/dir2/include/file2.h", "int f();\n")
|
||||
t.write("test.cpp", """\
|
||||
#include <file1.h>
|
||||
int main() { f(); }
|
||||
""");
|
||||
|
||||
t.run_build_system(["test"])
|
||||
|
||||
t.expect_addition("bin/$toolset/debug/test.obj")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.cleanup()
|
||||
|
||||
def test_include_scan_merge_existing():
|
||||
"""Make sure that files are replaced if needed when merging in
|
||||
a new directory"""
|
||||
t = BoostBuild.Tester()
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
import link ;
|
||||
link-directory dir1-link : src/dir1/include : <location>. ;
|
||||
link-directory dir2-link : src/dir2/include : <location>. ;
|
||||
obj test : test.cpp :
|
||||
<include>include
|
||||
<implicit-dependency>dir1-link
|
||||
<implicit-dependency>dir2-link ;
|
||||
""")
|
||||
|
||||
t.write("src/dir1/include/file1.h", "int f();")
|
||||
t.write("src/dir2/include/file2.h", "#include <file1.h>")
|
||||
t.write("test.cpp", """\
|
||||
#include <file2.h>
|
||||
int main() { f(); }
|
||||
""")
|
||||
|
||||
t.run_build_system(["dir2-link"])
|
||||
|
||||
t.run_build_system(["test"])
|
||||
t.expect_addition("include/file1.h")
|
||||
t.expect_addition("bin/$toolset/debug/test.obj")
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.cleanup()
|
||||
|
||||
def test_update_file_link(params1, params2):
|
||||
"""Tests the behavior of updates when changing the link mode.
|
||||
The link needs to be updated iff the original was a copy."""
|
||||
t = BoostBuild.Tester()
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
import link ;
|
||||
import project ;
|
||||
import property-set ;
|
||||
import modules ;
|
||||
|
||||
if --no-symlinks in [ modules.peek : ARGV ]
|
||||
{
|
||||
modules.poke link : .can-symlink : false ;
|
||||
}
|
||||
|
||||
if --no-hardlinks in [ modules.peek : ARGV ]
|
||||
{
|
||||
modules.poke link : .can-hardlink : false ;
|
||||
}
|
||||
|
||||
.project = [ project.current ] ;
|
||||
.has-files = [ glob include/file1.h ] ;
|
||||
|
||||
rule can-link ( properties * ) {
|
||||
if ( ! [ link.can-symlink $(.project) : [ property-set.empty ] ] ) &&
|
||||
( ! [ link.can-hardlink $(.project) : [ property-set.empty ] ] )
|
||||
{
|
||||
ECHO links unsupported ;
|
||||
}
|
||||
}
|
||||
|
||||
# Use two directories so that we link to individual files.
|
||||
link-directory dir1-link : src/dir1/include : <location>. ;
|
||||
link-directory dir2-link : src/dir2/include : <location>. ;
|
||||
alias check-linking : : <conditional>@can-link ;
|
||||
""")
|
||||
t.write("src/dir1/include/file1.h", "file1")
|
||||
t.write("src/dir2/include/file2.h", "file2")
|
||||
|
||||
t.run_build_system(params1)
|
||||
ignore_config(t)
|
||||
t.expect_addition("include/file1.h")
|
||||
t.expect_addition("include/file2.h")
|
||||
t.expect_nothing_more()
|
||||
|
||||
using_links = "links unsupported" not in t.stdout()
|
||||
|
||||
t.touch("src/dir1/include/file1.h")
|
||||
|
||||
t.run_build_system(params2)
|
||||
if not using_links: t.expect_touch("include/file1.h")
|
||||
ignore_config(t)
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.cleanup()
|
||||
|
||||
def test_update_file_link_all():
|
||||
"""Test all nine possible combinations of two runs."""
|
||||
possible_args = [[], ["--no-symlinks"], ["--no-symlinks", "--no-hardlinks"]]
|
||||
for arg1 in possible_args:
|
||||
for arg2 in possible_args:
|
||||
test_update_file_link(arg1, arg2)
|
||||
|
||||
def test_error_duplicate():
|
||||
"""Test that linking a single file from
|
||||
multiple sources causes a hard error."""
|
||||
t = BoostBuild.Tester()
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
import link ;
|
||||
link-directory dir1-link : src/dir1/include : <location>. ;
|
||||
link-directory dir2-link : src/dir2/include : <location>. ;
|
||||
""")
|
||||
|
||||
t.write("src/dir1/include/file1.h", "file1")
|
||||
t.write("src/dir2/include/file1.h", "file2")
|
||||
|
||||
t.run_build_system(status=1)
|
||||
t.expect_output_lines(
|
||||
["error: Cannot create link include/file1.h to src/dir2/include/file1.h.",
|
||||
"error: Link previously defined to another file, src/dir1/include/file1.h."])
|
||||
|
||||
t.cleanup()
|
||||
|
||||
test_basic()
|
||||
test_merge_two()
|
||||
test_merge_existing_all()
|
||||
test_merge_recursive()
|
||||
test_merge_recursive_existing_all()
|
||||
test_include_scan()
|
||||
test_include_scan_merge_existing()
|
||||
test_update_file_link_all()
|
||||
test_error_duplicate()
|
||||
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
"""
|
||||
Traverses a directory and output the code that would create the same directory
|
||||
structure during testing. Assumes that the instance of Tester is called 't'.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import stat
|
||||
import string
|
||||
|
||||
def usage():
|
||||
print "usage: load_dir.py directory"
|
||||
|
||||
|
||||
def remove_first_component(path):
|
||||
result = [path]
|
||||
while 1:
|
||||
s = os.path.split(result[0])
|
||||
if not s[0]:
|
||||
break
|
||||
result[:1] = list(s)
|
||||
return apply(os.path.join, result[1:])
|
||||
|
||||
|
||||
def create_file(arg, dirname, fnames):
|
||||
for n in fnames:
|
||||
path = os.path.join(dirname, n)
|
||||
if not os.path.isdir(path):
|
||||
print "t.write(\"%s\", \"\"\"" % (remove_first_component(path),),
|
||||
f = open(path, "r")
|
||||
for l in f:
|
||||
print l,
|
||||
print '\n""")\n'
|
||||
|
||||
|
||||
header = """#!/usr/bin/python
|
||||
|
||||
# Copyright (C) FILL SOMETHING HERE 2005.
|
||||
# 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
|
||||
|
||||
t = BoostBuild.Tester()
|
||||
"""
|
||||
|
||||
footer = """
|
||||
|
||||
t.run_build_system()
|
||||
|
||||
t.expect_addition("bin/$toolset/debug/FILL_SOME_HERE.exe")
|
||||
|
||||
t.cleanup()
|
||||
"""
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 2:
|
||||
usage()
|
||||
else:
|
||||
path = sys.argv[1]
|
||||
|
||||
if not os.access(path, os.F_OK):
|
||||
print "Path '%s' does not exist" % (path,)
|
||||
sys.exit(1)
|
||||
|
||||
if not os.path.isdir(path):
|
||||
print "Path '%s' is not a directory" % (path,)
|
||||
|
||||
print header
|
||||
|
||||
os.path.walk(path, create_file, None)
|
||||
|
||||
print footer
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user