Update copyright. Remove unused CI code. Upate AZP config.

(merge from hash-predef)
This commit is contained in:
Rene Rivera
2020-03-24 10:25:28 -05:00
parent f6979bd4a7
commit 9c46a94ae5
6 changed files with 311 additions and 1777 deletions

View File

@ -2,7 +2,7 @@
# subject to the Boost Software License, Version 1.0. (See accompanying # subject to 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) # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
# #
# Copyright Rene Rivera 2019. # Copyright Rene Rivera 2019-2020.
trigger: trigger:
branches: branches:
@ -19,185 +19,315 @@ variables:
AZP: 1 AZP: 1
AZP_REPO_DIR: $(Build.Repository.LocalPath) AZP_REPO_DIR: $(Build.Repository.LocalPath)
AZP_BRANCH: $(Build.SourceBranch) AZP_BRANCH: $(Build.SourceBranch)
AZP_BRANCH_NAME: $(Build.SourceBranchName)
AZP_COMMIT: $(Build.SourceVersion) AZP_COMMIT: $(Build.SourceVersion)
AZP_REPO: $(Build.Repository.Name) AZP_REPO: $(Build.Repository.Name)
AZP_PULL_REQUEST: $(System.PullRequest.PullRequestNumber) AZP_PULL_REQUEST: $(System.PullRequest.PullRequestNumber)
jobs: stages:
- job: 'Linux' - stage: Test
pool: jobs:
vmImage: 'ubuntu-16.04'
strategy:
matrix:
GCC 8 (GNU):
TOOLSET: gcc-8
CXXSTD: 03,11,14,17,2a
CXXDIALECT: gnu
GCC 8 (ISO):
TOOLSET: gcc-8
CXXSTD: 03,11,14,17,2a
GCC 7:
TOOLSET: gcc-7
GCC 6:
TOOLSET: gcc-6
GCC 5:
TOOLSET: gcc-5
GCC 4.9:
TOOLSET: gcc-4.9
GCC 4.8:
TOOLSET: gcc-4.8
GCC 4.7:
TOOLSET: gcc-4.7
Clang 8:
TOOLSET: clang-8
Clang 7:
TOOLSET: clang-7
Clang 6:
TOOLSET: clang-6.0
Clang 5:
TOOLSET: clang-5.0
Clang 4:
TOOLSET: clang-4.0
Clang 3.9:
TOOLSET: clang-3.9
Clang 3.8:
TOOLSET: clang-3.8
Clang 3.7:
TOOLSET: clang-3.7
Clang 3.6:
TOOLSET: clang-3.6
Clang 3.5:
TOOLSET: clang-3.5
steps:
- task: UsePythonVersion@0
- script: python tools/ci/library_test.py install
failOnStderr: false
displayName: Install
- script: python tools/ci/library_test.py script
failOnStderr: false
displayName: Test
- job: 'macOS' - job: 'Linux'
strategy: strategy:
matrix: matrix:
Xcode 10.1: GCC 9 (GNU):
TOOLSET: xcode-10.1 TOOLSET: gcc
XCODE_APP: /Applications/Xcode_10.1.app CXX: g++-9
VM_IMAGE: 'macOS-10.14' PACKAGES: g++-9
Xcode 10.0: B2_ARGS: 'cxxstd=03,11,14,17,2a cxxstd-dialect=gnu'
TOOLSET: xcode-10.0 VM_IMAGE: 'ubuntu-18.04'
XCODE_APP: /Applications/Xcode_10.app GCC 9 (ISO):
VM_IMAGE: 'macOS-10.14' TOOLSET: gcc
Xcode 9.4.1: CXX: g++-9
TOOLSET: xcode-9.4.1 PACKAGES: g++-9
XCODE_APP: /Applications/Xcode_9.4.1.app B2_ARGS: 'cxxstd=03,11,14,17,2a cxxstd-dialect=iso'
VM_IMAGE: 'macOS-10.13' VM_IMAGE: 'ubuntu-18.04'
Xcode 9.4: GCC 9:
TOOLSET: xcode-9.4 TOOLSET: gcc
XCODE_APP: /Applications/Xcode_9.4.app CXX: g++-9
VM_IMAGE: 'macOS-10.13' PACKAGES: g++-9
Xcode 9.3.1: VM_IMAGE: 'ubuntu-18.04'
TOOLSET: xcode-9.3.1 GCC 8:
XCODE_APP: /Applications/Xcode_9.3.1.app TOOLSET: gcc
VM_IMAGE: 'macOS-10.13' CXX: g++-8
Xcode 9.3: PACKAGES: g++-8
TOOLSET: xcode-9.3 VM_IMAGE: 'ubuntu-18.04'
XCODE_APP: /Applications/Xcode_9.3.app GCC 7:
VM_IMAGE: 'macOS-10.13' TOOLSET: gcc
Xcode 9.2: CXX: g++-7
TOOLSET: xcode-9.2 PACKAGES: g++-7
XCODE_APP: /Applications/Xcode_9.2.app VM_IMAGE: 'ubuntu-18.04'
VM_IMAGE: 'macOS-10.13' GCC 6:
Xcode 9.1: TOOLSET: gcc
TOOLSET: xcode-9.1 CXX: g++-6
XCODE_APP: /Applications/Xcode_9.1.app PACKAGES: g++-6
VM_IMAGE: 'macOS-10.13' VM_IMAGE: 'ubuntu-18.04'
Xcode 9.0.1: GCC 5:
TOOLSET: xcode-9.0.1 TOOLSET: gcc
XCODE_APP: /Applications/Xcode_9.0.1.app CXX: g++-5
VM_IMAGE: 'macOS-10.13' PACKAGES: g++-5
Xcode 9.0: VM_IMAGE: 'ubuntu-18.04'
TOOLSET: xcode-9.0 GCC 4.9:
XCODE_APP: /Applications/Xcode_9.app TOOLSET: gcc
VM_IMAGE: 'macOS-10.13' CXX: g++-4.9
Xcode 8.3.3: PACKAGES: g++-4.9
TOOLSET: xcode-8.3 VM_IMAGE: 'ubuntu-16.04'
XCODE_APP: /Applications/Xcode_8.3.3.app GCC 4.8:
VM_IMAGE: 'macOS-10.13' TOOLSET: gcc
pool: CXX: g++-4.8
vmImage: $(VM_IMAGE) PACKAGES: g++-4.8
steps: VM_IMAGE: 'ubuntu-16.04'
- task: UsePythonVersion@0 GCC 4.7:
- script: sudo xcode-select -switch ${XCODE_APP} TOOLSET: gcc
failOnStderr: false CXX: g++-4.7
displayName: Xcode Select PACKAGES: g++-4.7
- script: python tools/ci/library_test.py install VM_IMAGE: 'ubuntu-16.04'
failOnStderr: false Clang 9:
displayName: Install TOOLSET: clang
- script: python tools/ci/library_test.py script CXX: clang++-9
failOnStderr: false PACKAGES: clang-9
displayName: Test LLVM_REPO: llvm-toolchain-xenial-9
VM_IMAGE: 'ubuntu-18.04'
Clang 8:
TOOLSET: clang
CXX: clang++-8
PACKAGES: clang-8
LLVM_REPO: llvm-toolchain-xenial-8
VM_IMAGE: 'ubuntu-18.04'
Clang 7:
TOOLSET: clang
CXX: clang++-7
PACKAGES: clang-7
LLVM_REPO: llvm-toolchain-xenial-7
VM_IMAGE: 'ubuntu-18.04'
Clang 6:
TOOLSET: clang
CXX: clang++-6.0
PACKAGES: clang-6.0
LLVM_REPO: llvm-toolchain-xenial-6.0
VM_IMAGE: 'ubuntu-18.04'
Clang 5:
TOOLSET: clang
CXX: clang++-5.0
PACKAGES: clang-5.0
LLVM_REPO: llvm-toolchain-xenial-5.0
VM_IMAGE: 'ubuntu-18.04'
Clang 4:
TOOLSET: clang
CXX: clang++-4.0
PACKAGES: clang-4.0
LLVM_REPO: llvm-toolchain-xenial-4.0
VM_IMAGE: 'ubuntu-18.04'
Clang 3.9:
TOOLSET: clang
CXX: clang++-3.9
PACKAGES: clang-3.9
VM_IMAGE: 'ubuntu-18.04'
Clang 3.8:
TOOLSET: clang
CXX: clang++-3.8
PACKAGES: clang-3.8
VM_IMAGE: 'ubuntu-16.04'
Clang 3.7:
TOOLSET: clang
CXX: clang++-3.7
PACKAGES: clang-3.7
VM_IMAGE: 'ubuntu-16.04'
Clang 3.6:
TOOLSET: clang
CXX: clang++-3.6
PACKAGES: clang-3.6
VM_IMAGE: 'ubuntu-16.04'
Clang 3.5:
TOOLSET: clang
CXX: clang++-3.5
PACKAGES: clang-3.5
VM_IMAGE: 'ubuntu-16.04'
pool:
vmImage: $(VM_IMAGE)
steps:
- bash: |
set -e
uname -a
sudo -E apt-add-repository -y "ppa:ubuntu-toolchain-r/test"
if test -n "${LLVM_REPO}" ; then
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo -E apt-add-repository "deb http://apt.llvm.org/xenial/ ${LLVM_REPO} main"
fi
sudo -E apt-get update
sudo -E apt-get -yq --no-install-suggests --no-install-recommends install ${PACKAGES}
displayName: 'Install CXX'
- bash: |
set -e
pushd ${HOME}
wget -nv https://github.com/boostorg/build/archive/master.tar.gz
tar -zxf master.tar.gz
cd build-master
CXX= ./bootstrap.sh
sudo ./b2 install
popd
displayName: 'Install B2'
- bash: |
set -e
CXX_PATH=`which ${CXX}`
echo "using ${TOOLSET} : : ${CXX_PATH} ;" > ${HOME}/user-config.jam
pushd test
b2 --debug-configuration -a toolset=${TOOLSET} ${B2_ARGS}
popd
displayName: Test
- job: 'Windows' - job: 'macOS'
strategy: strategy:
matrix: matrix:
VS 2019: Xcode 11.4:
TOOLSET: vs-2019 TOOLSET: clang
ADDRESS_MODEL: 32,64 CXX: clang++
CXXSTD: 14,latest XCODE_APP: /Applications/Xcode_11.4_beta.app
VM_IMAGE: 'windows-2019' VM_IMAGE: 'macOS-10.15'
VS 2019 (UWP DESKTOP): Xcode 11.3.1:
TOOLSET: vs-2019 TOOLSET: clang
ADDRESS_MODEL: 64 CXX: clang++
CXXDEFS: _WIN32_WINNT=0x0A00,WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP XCODE_APP: /Applications/Xcode_11.3.1.app
VM_IMAGE: 'windows-2019' VM_IMAGE: 'macOS-10.15'
VS 2019 (UWP PHONE): Xcode 11.3:
TOOLSET: vs-2019 TOOLSET: clang
ADDRESS_MODEL: 64 CXX: clang++
CXXDEFS: _WIN32_WINNT=0x0A00,WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP XCODE_APP: /Applications/Xcode_11.3.app
VM_IMAGE: 'windows-2019' VM_IMAGE: 'macOS-10.15'
VS 2019 (UWP STORE): Xcode 11.2:
TOOLSET: vs-2019 TOOLSET: clang
ADDRESS_MODEL: 64 CXX: clang++
CXXDEFS: _WIN32_WINNT=0x0A00,WINAPI_FAMILY=WINAPI_FAMILY_PC_APP XCODE_APP: /Applications/Xcode_11.2.app
VM_IMAGE: 'windows-2019' VM_IMAGE: 'macOS-10.15'
VS 2019 (UWP SERVER): Xcode 11.1:
TOOLSET: vs-2019 TOOLSET: clang
ADDRESS_MODEL: 64 CXX: clang++
CXXDEFS: _WIN32_WINNT=0x0A00,WINAPI_FAMILY=WINAPI_FAMILY_SERVER XCODE_APP: /Applications/Xcode_11.1.app
VM_IMAGE: 'windows-2019' VM_IMAGE: 'macOS-10.15'
VS 2019 (UWP SYSTEM): Xcode 11.0:
TOOLSET: vs-2019 TOOLSET: clang
ADDRESS_MODEL: 64 CXX: clang++
CXXDEFS: _WIN32_WINNT=0x0A00,WINAPI_FAMILY=WINAPI_FAMILY_SYSTEM XCODE_APP: /Applications/Xcode_11.app
VM_IMAGE: 'windows-2019' VM_IMAGE: 'macOS-10.15'
VS 2017: Xcode 10.2.1:
TOOLSET: vs-2017 TOOLSET: clang
VM_IMAGE: 'vs2017-win2016' CXX: clang++
VS 2015: XCODE_APP: /Applications/Xcode_10.2.1.app
TOOLSET: vs-2015 VM_IMAGE: 'macOS-10.14'
VM_IMAGE: 'vs2015-win2012r2' Xcode 10.2:
VS 2013: TOOLSET: clang
TOOLSET: vs-2013 CXX: clang++
VM_IMAGE: 'vs2015-win2012r2' XCODE_APP: /Applications/Xcode_10.2.app
MinGW 8.1.0: VM_IMAGE: 'macOS-10.14'
TOOLSET: mingw-8 Xcode 10.1:
VM_IMAGE: 'vs2017-win2016' TOOLSET: clang
MinGW 8.1.0 (UWP DESKTOP): CXX: clang++
TOOLSET: mingw-8 XCODE_APP: /Applications/Xcode_10.1.app
CXXDEFS: _WIN32_WINNT=0x0A00,WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP VM_IMAGE: 'macOS-10.14'
VM_IMAGE: 'vs2017-win2016' Xcode 10.0:
MinGW 8.1.0 (UWP STORE): TOOLSET: clang
TOOLSET: mingw-8 CXX: clang++
CXXDEFS: _WIN32_WINNT=0x0A00,WINAPI_FAMILY=WINAPI_FAMILY_PC_APP XCODE_APP: /Applications/Xcode_10.app
VM_IMAGE: 'vs2017-win2016' VM_IMAGE: 'macOS-10.14'
pool: pool:
vmImage: $(VM_IMAGE) vmImage: $(VM_IMAGE)
steps: steps:
- script: python tools/ci/library_test.py install - bash: |
failOnStderr: false set -e
displayName: Install uname -a
- script: python tools/ci/library_test.py script sudo xcode-select -switch ${XCODE_APP}
failOnStderr: false which clang++
displayName: Test clang++ --version
displayName: 'Install CXX'
- bash: |
set -e
pushd ${HOME}
wget -nv https://github.com/boostorg/build/archive/master.tar.gz
tar -zxf master.tar.gz
cd build-master
CXX= ./bootstrap.sh
sudo ./b2 install
popd
displayName: 'Install B2'
- bash: |
set -e
CXX_PATH=`which ${CXX}`
echo "using ${TOOLSET} : : ${CXX_PATH} ;" > ${HOME}/user-config.jam
pushd test
b2 --debug-configuration -a toolset=${TOOLSET} ${B2_ARGS}
popd
displayName: Test
- job: 'Windows'
strategy:
matrix:
VS 2019:
TOOLSET: msvc
TOOLSET_VERSION: 14.2
B2_ARGS: address-model=32,64 cxxstd=14,latest
VM_IMAGE: 'windows-2019'
VS 2019 (UWP DESKTOP):
TOOLSET: msvc
TOOLSET_VERSION: 14.2
B2_ARGS: address-model=64 define=_WIN32_WINNT=0x0A00 define=WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP
VM_IMAGE: 'windows-2019'
VS 2019 (UWP PHONE):
TOOLSET: msvc
TOOLSET_VERSION: 14.2
B2_ARGS: address-model=64 define=_WIN32_WINNT=0x0A00 define=WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP
VM_IMAGE: 'windows-2019'
VS 2019 (UWP STORE):
TOOLSET: msvc
TOOLSET_VERSION: 14.2
B2_ARGS: address-model=64 define=_WIN32_WINNT=0x0A00 define=WINAPI_FAMILY=WINAPI_FAMILY_PC_APP
VM_IMAGE: 'windows-2019'
VS 2019 (UWP SERVER):
TOOLSET: msvc
TOOLSET_VERSION: 14.2
B2_ARGS: address-model=64 define=_WIN32_WINNT=0x0A00 define=WINAPI_FAMILY=WINAPI_FAMILY_SERVER
VM_IMAGE: 'windows-2019'
VS 2019 (UWP SYSTEM):
TOOLSET: msvc
TOOLSET_VERSION: 14.2
B2_ARGS: address-model=64 define=_WIN32_WINNT=0x0A00 define=WINAPI_FAMILY=WINAPI_FAMILY_SYSTEM
VM_IMAGE: 'windows-2019'
VS 2017:
TOOLSET: msvc
TOOLSET_VERSION: 14.1
VM_IMAGE: 'vs2017-win2016'
MinGW 8.1.0:
TOOLSET: gcc
VM_IMAGE: 'windows-2019'
MinGW 8.1.0 (UWP DESKTOP):
TOOLSET: gcc
B2_ARGS: define=_WIN32_WINNT=0x0A00 define=WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP
VM_IMAGE: 'windows-2019'
MinGW 8.1.0 (UWP STORE):
TOOLSET: gcc
B2_ARGS: define=_WIN32_WINNT=0x0A00 define=WINAPI_FAMILY=WINAPI_FAMILY_PC_APP
VM_IMAGE: 'windows-2019'
pool:
vmImage: $(VM_IMAGE)
steps:
- script: |
cd %BUILD_SOURCESDIRECTORY%/..
curl "https://github.com/boostorg/build/archive/master.zip" -L -o b2.zip
displayName: Download B2
- task: ExtractFiles@1
inputs:
archiveFilePatterns: $(Build.SourcesDirectory)/../b2.zip
destinationFolder: $(Build.SourcesDirectory)/..
cleanDestinationFolder: false
displayName: Extract B2
- script: |
echo using %TOOLSET% ^: %TOOLSET_VERSION% ^; > %HOMEDRIVE%%HOMEPATH%/user-config.jam
cd %BUILD_SOURCESDIRECTORY%/../build-master
cmd.exe /c bootstrap.bat
displayName: Install B2
- script: |
set BOOST_BUILD_PATH=%BUILD_SOURCESDIRECTORY%/../build-master
cd %BUILD_SOURCESDIRECTORY%/test
%BUILD_SOURCESDIRECTORY%/../build-master/b2.exe --debug-configuration -a toolset=%TOOLSET% %B2_ARGS%
displayName: Test

View File

@ -6746,6 +6746,9 @@ expressions. It defaults to "c++", but can be any of: "c", "cpp",
<li> <li>
<p>Remove deprecated <code>BOOST_OS_ANDROID</code>.</p> <p>Remove deprecated <code>BOOST_OS_ANDROID</code>.</p>
</li> </li>
<li>
<p>Fix compile for Wine. (Kevin Puetz)</p>
</li>
</ul> </ul>
</div> </div>
</div> </div>
@ -7043,7 +7046,7 @@ Joel Falcou for managing the review of this library.</p>
<a href="https://www.boost.org/LICENSE_1_0.txt" class="bare">https://www.boost.org/LICENSE_1_0.txt</a>)</p> <a href="https://www.boost.org/LICENSE_1_0.txt" class="bare">https://www.boost.org/LICENSE_1_0.txt</a>)</p>
</div> </div>
<div class="paragraph"> <div class="paragraph">
<p>Copyright 2005-2019 Rene Rivera; Copyright 2015 Charly Chevalier; Copyright 2015 Joel Falcou</p> <p>Copyright 2005-2020 Rene Rivera; Copyright 2015 Charly Chevalier; Copyright 2015 Joel Falcou</p>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1011,4 +1011,4 @@ Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at (See accompanying file LICENSE_1_0.txt or copy at
https://www.boost.org/LICENSE_1_0.txt) https://www.boost.org/LICENSE_1_0.txt)
Copyright 2005-2019 Rene Rivera; Copyright 2015 Charly Chevalier; Copyright 2015 Joel Falcou Copyright 2005-2020 Rene Rivera; Copyright 2015 Charly Chevalier; Copyright 2015 Joel Falcou

View File

@ -1,446 +0,0 @@
# Copyright 2008-2019 Rene Rivera
# 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)
from __future__ import print_function
import re
import optparse
import time
import xml.dom.minidom
import xml.dom.pulldom
from xml.sax.saxutils import unescape, escape
import os.path
from pprint import pprint
from sys import exit
class BuildOutputXMLParsing(object):
'''
XML parsing utilities for dealing with the Boost Build output
XML format.
'''
def get_child_data(self, root, tag=None, id=None, name=None, strip=False, default=None):
return self.get_data(self.get_child(root, tag=tag, id=id, name=name), strip=strip, default=default)
def get_data(self, node, strip=False, default=None):
data = None
if node:
data_node = None
if not data_node:
data_node = self.get_child(node, tag='#text')
if not data_node:
data_node = self.get_child(node, tag='#cdata-section')
data = ""
while data_node:
data += data_node.data
data_node = data_node.nextSibling
if data_node:
if data_node.nodeName != '#text' \
and data_node.nodeName != '#cdata-section':
data_node = None
if not data:
data = default
else:
if strip:
data = data.strip()
return data
def get_child(self, root, tag=None, id=None, name=None, type=None):
return self.get_sibling(root.firstChild, tag=tag, id=id, name=name, type=type)
def get_sibling(self, sibling, tag=None, id=None, name=None, type=None):
n = sibling
while n:
found = True
if type and found:
found = found and type == n.nodeType
if tag and found:
found = found and tag == n.nodeName
if (id or name) and found:
found = found and n.nodeType == xml.dom.Node.ELEMENT_NODE
if id and found:
if n.hasAttribute('id'):
found = found and n.getAttribute('id') == id
else:
found = found and n.hasAttribute(
'id') and n.getAttribute('id') == id
if name and found:
found = found and n.hasAttribute(
'name') and n.getAttribute('name') == name
if found:
return n
n = n.nextSibling
return None
class BuildOutputProcessor(BuildOutputXMLParsing):
def __init__(self, inputs):
self.test = {}
self.target_to_test = {}
self.target = {}
self.parent = {}
self.timestamps = []
for input in inputs:
self.add_input(input)
def add_input(self, input):
'''
Add a single build XML output file to our data.
'''
events = xml.dom.pulldom.parse(input)
context = []
for (event, node) in events:
if event == xml.dom.pulldom.START_ELEMENT:
context.append(node)
if node.nodeType == xml.dom.Node.ELEMENT_NODE:
x_f = self.x_name_(*context)
if x_f:
events.expandNode(node)
# expanding eats the end element, hence walking us out one level
context.pop()
# call handler
(x_f[1])(node)
elif event == xml.dom.pulldom.END_ELEMENT:
context.pop()
def x_name_(self, *context, **kwargs):
node = None
names = []
for c in context:
if c:
if not isinstance(c, xml.dom.Node):
suffix = '_'+c.replace('-', '_').replace('#', '_')
else:
suffix = '_'+c.nodeName.replace('-', '_').replace('#', '_')
node = c
names.append('x')
names = [x+suffix for x in names]
if node:
for name in names:
if hasattr(self, name):
return (name, getattr(self, name))
return None
def x_build_test(self, node):
'''
Records the initial test information that will eventually
get expanded as we process the rest of the results.
'''
test_node = node
test_name = test_node.getAttribute('name')
test_target = self.get_child_data(test_node, tag='target', strip=True)
# print ">>> %s %s" %(test_name,test_target)
self.test[test_name] = {
'library': "/".join(test_name.split('/')[0:-1]),
'test-name': test_name.split('/')[-1],
'test-type': test_node.getAttribute('type').lower(),
'test-program': self.get_child_data(test_node, tag='source', strip=True),
'target': test_target,
'info': self.get_child_data(test_node, tag='info', strip=True),
'dependencies': [],
'actions': [],
}
# Add a lookup for the test given the test target.
self.target_to_test[self.test[test_name]['target']] = test_name
return None
def x_build_targets_target(self, node):
'''
Process the target dependency DAG into an ancestry tree so we can look up
which top-level library and test targets specific build actions correspond to.
'''
target_node = node
name = self.get_child_data(target_node, tag='name', strip=True)
path = self.get_child_data(target_node, tag='path', strip=True)
jam_target = self.get_child_data(
target_node, tag='jam-target', strip=True)
# ~ Map for jam targets to virtual targets.
self.target[jam_target] = {
'name': name,
'path': path
}
# ~ Create the ancestry.
dep_node = self.get_child(self.get_child(
target_node, tag='dependencies'), tag='dependency')
while dep_node:
child = self.get_data(dep_node, strip=True)
child_jam_target = '<p%s>%s' % (path, child.split('//', 1)[1])
self.parent[child_jam_target] = jam_target
dep_node = self.get_sibling(dep_node.nextSibling, tag='dependency')
return None
def x_build_action(self, node):
'''
Given a build action log, process into the corresponding test log and
specific test log sub-part.
'''
action_node = node
name = self.get_child(action_node, tag='name')
if name:
name = self.get_data(name)
# ~ Based on the action, we decide what sub-section the log
# ~ should go into.
action_type = None
if re.match('[^%]+%[^.]+[.](compile)', name):
action_type = 'compile'
elif re.match('[^%]+%[^.]+[.](link|archive)', name):
action_type = 'link'
elif re.match('[^%]+%testing[.](capture-output)', name):
action_type = 'run'
elif re.match('[^%]+%testing[.](expect-failure|expect-success)', name):
action_type = 'result'
else:
# TODO: Enable to see what other actions can be included in the test results.
# action_type = None
action_type = 'other'
# ~ print "+ [%s] %s %s :: %s" %(action_type,name,'','')
if action_type:
# ~ Get the corresponding test.
(target, test) = self.get_test(action_node, type=action_type)
# ~ Skip action that have no corresponding test as they are
# ~ regular build actions and don't need to show up in the
# ~ regression results.
if not test:
# print "??? [%s] %s %s :: %s" %(action_type,name,target,test)
return None
# print "+++ [%s] %s %s :: %s" %(action_type,name,target,test)
# ~ Collect some basic info about the action.
action = {
'command': self.get_action_command(action_node, action_type),
'output': self.get_action_output(action_node, action_type),
'info': self.get_action_info(action_node, action_type)
}
# ~ For the test result status we find the appropriate node
# ~ based on the type of test. Then adjust the result status
# ~ accordingly. This makes the result status reflect the
# ~ expectation as the result pages post processing does not
# ~ account for this inversion.
action['type'] = action_type
if action_type == 'result':
if re.match(r'^compile', test['test-type']):
action['type'] = 'compile'
elif re.match(r'^link', test['test-type']):
action['type'] = 'link'
elif re.match(r'^run', test['test-type']):
action['type'] = 'run'
# ~ The result sub-part we will add this result to.
if action_node.getAttribute('status') == '0':
action['result'] = 'succeed'
else:
action['result'] = 'fail'
# Add the action to the test.
test['actions'].append(action)
# Set the test result if this is the result action for the test.
if action_type == 'result':
test['result'] = action['result']
return None
def x_build_timestamp(self, node):
'''
The time-stamp goes to the corresponding attribute in the result.
'''
self.timestamps.append(self.get_data(node).strip())
return None
def get_test(self, node, type=None):
'''
Find the test corresponding to an action. For testing targets these
are the ones pre-declared in the --dump-test option. For libraries
we create a dummy test as needed.
'''
jam_target = self.get_child_data(node, tag='jam-target')
base = self.target[jam_target]['name']
target = jam_target
while target in self.parent:
target = self.parent[target]
# ~ print "--- TEST: %s ==> %s" %(jam_target,target)
# ~ main-target-type is a precise indicator of what the build target is
# ~ originally meant to be.
# main_type = self.get_child_data(self.get_child(node,tag='properties'),
# name='main-target-type',strip=True)
main_type = None
if main_type == 'LIB' and type:
lib = self.target[target]['name']
if not lib in self.test:
self.test[lib] = {
'library': re.search(r'libs/([^/]+)', lib).group(1),
'test-name': os.path.basename(lib),
'test-type': 'lib',
'test-program': os.path.basename(lib),
'target': lib
}
test = self.test[lib]
else:
target_name_ = self.target[target]['name']
if target_name_ in self.target_to_test:
test = self.test[self.target_to_test[target_name_]]
else:
test = None
return (base, test)
# ~ The command executed for the action. For run actions we omit the command
# ~ as it's just noise.
def get_action_command(self, action_node, action_type):
if action_type != 'run':
return self.get_child_data(action_node, tag='command')
else:
return ''
# ~ The command output.
def get_action_output(self, action_node, action_type):
return self.get_child_data(action_node, tag='output', default='')
# ~ Some basic info about the action.
def get_action_info(self, action_node, action_type):
info = {}
# ~ The jam action and target.
info['name'] = self.get_child_data(action_node, tag='name')
info['path'] = self.get_child_data(action_node, tag='path')
# ~ The timing of the action.
info['time-start'] = action_node.getAttribute('start')
info['time-end'] = action_node.getAttribute('end')
info['time-user'] = action_node.getAttribute('user')
info['time-system'] = action_node.getAttribute('system')
# ~ Testing properties.
test_info_prop = self.get_child_data(self.get_child(
action_node, tag='properties'), name='test-info')
info['always_show_run_output'] = test_info_prop == 'always_show_run_output'
# ~ And for compiles some context that may be hidden if using response files.
if action_type == 'compile':
info['define'] = []
define = self.get_child(self.get_child(
action_node, tag='properties'), name='define')
while define:
info['define'].append(self.get_data(define, strip=True))
define = self.get_sibling(define.nextSibling, name='define')
return info
class BuildConsoleSummaryReport(object):
HEADER = '\033[35m\033[1m'
INFO = '\033[34m'
OK = '\033[32m'
WARNING = '\033[33m'
FAIL = '\033[31m'
ENDC = '\033[0m'
def __init__(self, bop, opt):
self.bop = bop
def generate(self):
self.summary_info = {
'total': 0,
'success': 0,
'failed': [],
}
self.header_print(
"======================================================================")
self.print_test_log()
self.print_summary()
self.header_print(
"======================================================================")
@property
def failed(self):
return len(self.summary_info['failed']) > 0
def print_test_log(self):
self.header_print("Tests run..")
self.header_print(
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
for k in sorted(self.bop.test.keys()):
test = self.bop.test[k]
if len(test['actions']) > 0:
self.summary_info['total'] += 1
# print ">>>> {0}".format(test['test-name'])
if 'result' in test:
succeed = test['result'] == 'succeed'
else:
succeed = test['actions'][-1]['result'] == 'succeed'
if succeed:
self.summary_info['success'] += 1
else:
self.summary_info['failed'].append(test)
if succeed:
self.ok_print("[PASS] {0}", k)
else:
self.fail_print("[FAIL] {0}", k)
for action in test['actions']:
self.print_action(succeed, action)
def print_action(self, test_succeed, action):
'''
Print the detailed info of failed or always print tests.
'''
#self.info_print(">>> {0}",action.keys())
if not test_succeed or action['info']['always_show_run_output']:
output = action['output'].strip()
if output != "":
p = self.fail_print if action['result'] == 'fail' else self.p_print
self.info_print("")
self.info_print(
"({0}) {1}", action['info']['name'], action['info']['path'])
p("")
p("{0}", action['command'].strip())
p("")
for line in output.splitlines():
p("{0}", line.encode('utf-8'))
def print_summary(self):
self.header_print("")
self.header_print("Testing summary..")
self.header_print(
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
self.p_print("Total: {0}", self.summary_info['total'])
self.p_print("Success: {0}", self.summary_info['success'])
if self.failed:
self.fail_print("Failed: {0}", len(self.summary_info['failed']))
for test in self.summary_info['failed']:
self.fail_print(
" {0}/{1}", test['library'], test['test-name'])
def p_print(self, format, *args, **kargs):
print(format.format(*args, **kargs))
def info_print(self, format, *args, **kargs):
print(self.INFO+format.format(*args, **kargs)+self.ENDC)
def header_print(self, format, *args, **kargs):
print(self.HEADER+format.format(*args, **kargs)+self.ENDC)
def ok_print(self, format, *args, **kargs):
print(self.OK+format.format(*args, **kargs)+self.ENDC)
def warn_print(self, format, *args, **kargs):
print(self.WARNING+format.format(*args, **kargs)+self.ENDC)
def fail_print(self, format, *args, **kargs):
print(self.FAIL+format.format(*args, **kargs)+self.ENDC)
class Main(object):
def __init__(self, args=None):
op = optparse.OptionParser(
usage="%prog [options] input+")
op.add_option('--output',
help="type of output to generate")
(opt, inputs) = op.parse_args(args)
bop = BuildOutputProcessor(inputs)
output = None
if opt.output == 'console':
output = BuildConsoleSummaryReport(bop, opt)
if output:
output.generate()
self.failed = output.failed
if __name__ == '__main__':
m = Main()
if m.failed:
exit(-1)

File diff suppressed because it is too large Load Diff

View File

@ -1,152 +0,0 @@
# Copyright Rene Rivera 2016-2019
#
# 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 __future__ import print_function
import os.path
import shutil
import sys
from common import toolset_info, main, utils, script_common, ci_cli, set_arg
__dirname__ = os.path.dirname(os.path.realpath(__file__))
class script(script_common):
'''
Main script to test a Boost C++ Library.
'''
def __init__(self, ci_klass, **kargs):
script_common.__init__(self, ci_klass, **kargs)
def init(self, opt, kargs):
opt.add_option(
'--toolset',
help="single toolset to test with")
opt.add_option(
'--target',
help="test target to build for testing, defaults to TARGET or 'minimal'")
opt.add_option(
'--address-model',
help="address model to test, ie 64 or 32")
opt.add_option(
'--variant',
help="variant to test, ie debug, release")
set_arg(kargs, 'toolset', os.getenv("TOOLSET"))
set_arg(kargs, 'target', os.getenv('TARGET', 'minimal'))
set_arg(kargs, 'address_model', os.getenv("ADDRESS_MODEL", None))
set_arg(kargs, 'variant', os.getenv("VARIANT", "debug"))
set_arg(kargs, 'cxxstd', os.getenv("CXXSTD", None))
set_arg(kargs, 'cxxdialect', os.getenv("CXXDIALECT", None))
set_arg(kargs, 'cxxdefs', os.getenv("CXXDEFS", None))
return kargs
def start(self):
script_common.start(self)
# Some setup we need to redo for each invocation.
self.b2_dir = os.path.join(self.build_dir, 'b2')
def command_install(self):
script_common.command_install(self)
# Fetch & install toolset..
utils.log("Install toolset: %s" % (self.toolset))
if self.toolset:
self.command_install_toolset(self.toolset)
def command_before_build(self):
script_common.command_before_build(self)
# Fetch dependencies.
utils.git_clone('boostorg', 'build', 'develop', repo_dir=self.b2_dir)
# Create config file for b2 toolset.
if not isinstance(self.ci, ci_cli):
utils.make_file(os.path.join(self.repo_dir, 'project-config.jam'),
"""
using %(toolset)s : %(version)s : %(command)s ;
""" % {
'toolset': toolset_info[self.toolset]['toolset'],
'version': toolset_info[self.toolset]['version'],
'command': toolset_info[self.toolset]['command'],
})
# # "Convert" boostorg-predef into standalone b2 project.
# if os.path.exists(os.path.join(self.repo_dir, 'build.jam')) and not os.path.exists(os.path.join(self.repo_dir, 'project-root.jam')):
# os.rename(os.path.join(self.repo_dir, 'build.jam'),
# os.path.join(self.repo_dir, 'project-root.jam'))
def command_build(self):
script_common.command_build(self)
# Set up tools.
if not isinstance(self.ci, ci_cli) and toolset_info[self.toolset]['command']:
os.environ['PATH'] = os.pathsep.join([
os.path.dirname(toolset_info[self.toolset]['command']),
os.environ['PATH']])
# Bootstrap Boost Build engine.
os.chdir(self.b2_dir)
if sys.platform == 'win32':
utils.check_call(".\\bootstrap.bat")
else:
utils.check_call("./bootstrap.sh")
os.environ['PATH'] = os.pathsep.join([self.b2_dir, os.environ['PATH']])
os.environ['BOOST_BUILD_PATH'] = self.b2_dir
# Run the limited tests.
print("--- Testing %s ---" % (self.repo_dir))
os.chdir(os.path.join(self.repo_dir, 'test'))
toolset_to_test = ""
if self.toolset:
if not isinstance(self.ci, ci_cli):
toolset_to_test = toolset_info[self.toolset]['toolset']
else:
toolset_to_test = self.toolset
cxxdefs = []
if self.cxxdefs:
cxxdefs = ['define=%s' % (d) for d in self.cxxdefs.split(',')]
self.b2(
'-d1',
'-p0',
'preserve-test-targets=off',
'--dump-tests',
'--verbose-test',
'--build-dir=%s' % (self.build_dir),
'--out-xml=%s' % (os.path.join(self.build_dir, 'regression.xml')),
'' if not toolset_to_test else 'toolset=%s' % (toolset_to_test),
'' if not self.address_model else 'address-model=%s' % (
self.address_model),
'variant=%s' % (self.variant),
'' if not self.cxxstd else 'cxxstd=%s' % (
self.cxxstd),
'' if not self.cxxdialect else 'cxxstd-dialect=%s' % (
self.cxxdialect),
self.target,
*cxxdefs
)
# Generate a readable test report.
import build_log
log_main = build_log.Main([
'--output=console',
os.path.join(self.build_dir, 'regression.xml')])
# And exit with an error if the report contains failures.
# This lets the CI notice the error and report a failed build.
# And hence trigger the failure machinery, like sending emails.
if log_main.failed:
self.ci.finish(-1)
def command_before_cache(self):
script_common.command_before_cache(self)
os.chdir(self.b2_dir)
utils.check_call("git", "clean", "-dfqx")
utils.check_call("git", "status", "-bs")
# utils.check_call("git","submodule","--quiet","foreach","git","clean","-dfqx")
# utils.check_call("git","submodule","foreach","git","status","-bs")
main(script)