1#!/usr/bin/env python3 2# Copyright 2016 Google Inc. All Rights Reserved. 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS-IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16import yaml 17 18# "smoke tests" are run before other build matrix rows. 19build_matrix_smoke_test_rows = [] 20build_matrix_rows = [] 21 22 23def determine_compiler_kind(compiler): 24 if compiler.startswith('gcc'): 25 return 'gcc' 26 elif compiler.startswith('clang'): 27 return 'clang' 28 else: 29 raise Exception('Unexpected compiler: %s' % compiler) 30 31 32def determine_tests(asan, ubsan, clang_tidy, smoke_tests, use_precompiled_headers_in_tests, exclude_tests, 33 include_only_tests): 34 tests = [] 35 has_debug_build = False 36 tests += ['ReleasePlain'] 37 if asan: 38 has_debug_build = True 39 if ubsan: 40 tests += ['DebugAsanUbsan'] 41 else: 42 tests += ['DebugAsan'] 43 if ubsan and not asan: 44 raise Exception('Enabling UBSan but not ASan is not currently supported.') 45 if not has_debug_build: 46 tests += ['DebugPlain'] 47 for smoke_test in smoke_tests: 48 if smoke_test not in tests: 49 tests += [smoke_test] 50 excessive_excluded_tests = set(exclude_tests) - set(tests) 51 if excessive_excluded_tests: 52 raise Exception( 53 'Some tests were excluded but were not going to run anyway: %s. ' 54 'Tests to run (ignoring the possible NoPch/NoClangTidy prefixes): %s' 55 % (excessive_excluded_tests, tests)) 56 if include_only_tests is not None: 57 if exclude_tests != []: 58 raise Exception('Using exclude_tests and include_only_tests together is not supported.') 59 tests = include_only_tests 60 else: 61 tests = [test for test in tests if test not in exclude_tests] 62 if not use_precompiled_headers_in_tests: 63 tests = [test + 'NoPch' for test in tests] 64 if not clang_tidy: 65 tests = [test + 'NoClangTidy' for test in tests] 66 return tests 67 68 69def generate_export_statements_for_env(env): 70 return ' '.join(['export %s=\'%s\';' % (var_name, value) for (var_name, value) in sorted(env.items())]) 71 72 73def generate_env_string_for_env(env): 74 return ' '.join(['%s=%s' % (var_name, value) for (var_name, value) in sorted(env.items())]) 75 76 77def add_ubuntu_tests(ubuntu_version, compiler, os='linux', stl=None, asan=True, ubsan=True, clang_tidy=True, 78 use_precompiled_headers_in_tests=True, smoke_tests=[], exclude_tests=[], include_only_tests=None): 79 env = { 80 'UBUNTU': ubuntu_version, 81 'COMPILER': compiler 82 } 83 if stl is not None: 84 env['STL'] = stl 85 compiler_kind = determine_compiler_kind(compiler) 86 export_statements = 'export OS=' + os + '; ' + generate_export_statements_for_env(env=env) 87 test_environment_template = {'os': 'linux', 'compiler': compiler_kind, 88 'install': '%s extras/scripts/travis_ci_install_linux.sh' % export_statements} 89 tests = determine_tests(asan, ubsan, clang_tidy, smoke_tests, 90 use_precompiled_headers_in_tests=use_precompiled_headers_in_tests, 91 exclude_tests=exclude_tests, 92 include_only_tests=include_only_tests) 93 for test in tests: 94 test_environment = test_environment_template.copy() 95 test_environment['script'] = '%s extras/scripts/postsubmit.sh %s' % (export_statements, test) 96 # The TEST variable has no effect on the test run, but allows to see the test name in the Travis CI dashboard. 97 test_environment['env'] = generate_env_string_for_env(env) + " TEST=%s" % test 98 if test in smoke_tests: 99 build_matrix_smoke_test_rows.append(test_environment) 100 else: 101 build_matrix_rows.append(test_environment) 102 103 104def add_osx_tests(compiler, xcode_version=None, stl=None, asan=True, ubsan=True, clang_tidy=True, 105 use_precompiled_headers_in_tests=True, smoke_tests=[], exclude_tests=[], include_only_tests=None): 106 env = {'COMPILER': compiler} 107 if stl is not None: 108 env['STL'] = stl 109 compiler_kind = determine_compiler_kind(compiler) 110 export_statements = 'export OS=osx; ' + generate_export_statements_for_env(env=env) 111 test_environment_template = {'os': 'osx', 'compiler': compiler_kind, 112 'install': '%s travis_wait extras/scripts/travis_ci_install_osx.sh' % export_statements} 113 if xcode_version is not None: 114 test_environment_template['osx_image'] = 'xcode%s' % xcode_version 115 116 tests = determine_tests(asan, ubsan, clang_tidy, smoke_tests, 117 use_precompiled_headers_in_tests=use_precompiled_headers_in_tests, 118 exclude_tests=exclude_tests, include_only_tests=include_only_tests) 119 for test in tests: 120 test_environment = test_environment_template.copy() 121 test_environment['script'] = '%s extras/scripts/postsubmit.sh %s' % (export_statements, test) 122 # The TEST variable has no effect on the test run, but allows to see the test name in the Travis CI dashboard. 123 test_environment['env'] = generate_env_string_for_env(env) + " TEST=%s" % test 124 if test in smoke_tests: 125 build_matrix_smoke_test_rows.append(test_environment) 126 else: 127 build_matrix_rows.append(test_environment) 128 129 130def add_bazel_tests(ubuntu_version, smoke_tests=[]): 131 env = { 132 'UBUNTU': ubuntu_version, 133 'COMPILER': 'bazel', 134 } 135 test = 'DebugPlain' 136 export_statements = 'export OS=linux; ' + generate_export_statements_for_env(env=env) 137 test_environment = {'os': 'linux', 138 'compiler': 'gcc', 139 'env': generate_env_string_for_env(env), 140 'install': '%s extras/scripts/travis_ci_install_linux.sh' % export_statements, 141 'script': '%s extras/scripts/postsubmit.sh %s' % (export_statements, test)} 142 if test in smoke_tests: 143 build_matrix_smoke_test_rows.append(test_environment) 144 else: 145 build_matrix_rows.append(test_environment) 146 147add_ubuntu_tests(ubuntu_version='20.10', compiler='gcc-7') 148add_ubuntu_tests(ubuntu_version='20.10', compiler='gcc-10', 149 smoke_tests=['DebugPlain', 'ReleasePlain']) 150add_ubuntu_tests(ubuntu_version='20.10', compiler='clang-8.0', stl='libstdc++', 151 smoke_tests=['DebugPlain', 'DebugAsanUbsan', 'ReleasePlain']) 152add_ubuntu_tests(ubuntu_version='20.10', compiler='clang-11.0', stl='libstdc++') 153add_ubuntu_tests(ubuntu_version='20.10', compiler='clang-11.0', stl='libc++') 154 155add_ubuntu_tests(ubuntu_version='20.04', compiler='gcc-7') 156add_ubuntu_tests(ubuntu_version='20.04', compiler='clang-6.0', stl='libstdc++', 157 smoke_tests=['DebugPlain', 'DebugAsanUbsan', 'ReleasePlain']) 158 159add_ubuntu_tests(ubuntu_version='18.04', compiler='gcc-5', asan=False, ubsan=False) 160add_ubuntu_tests(ubuntu_version='18.04', compiler='gcc-8', asan=False, ubsan=False) 161add_ubuntu_tests(ubuntu_version='18.04', compiler='clang-3.9', stl='libstdc++') 162add_ubuntu_tests(ubuntu_version='18.04', compiler='clang-7.0', stl='libstdc++', 163 # Disabled due to https://bugs.llvm.org/show_bug.cgi?id=41625. 164 use_precompiled_headers_in_tests=False) 165 166add_bazel_tests(ubuntu_version='18.04', smoke_tests=['DebugPlain']) 167 168# ASan/UBSan are disabled for all these, the analysis on later versions is better anyway. 169# Also, in some combinations they wouldn't work. 170add_ubuntu_tests(ubuntu_version='16.04', compiler='gcc-5', asan=False, ubsan=False) 171add_ubuntu_tests(ubuntu_version='16.04', compiler='clang-3.5', stl='libstdc++', asan=False, ubsan=False) 172add_ubuntu_tests(ubuntu_version='16.04', compiler='clang-3.9', stl='libstdc++', asan=False, ubsan=False) 173 174# Asan/Ubsan are disabled because it generates lots of warnings like: 175# warning: direct access in [...] to global weak symbol guard variable for [...] means the weak symbol cannot be 176# overridden at runtime. This was likely caused by different translation units being compiled with different 177# visibility settings. 178# and the build eventually fails or times out. 179add_osx_tests(compiler='gcc-6', xcode_version='11.4', asan=False, ubsan=False, clang_tidy=False) 180add_osx_tests(compiler='gcc-9', xcode_version='11.4', asan=False, ubsan=False, clang_tidy=False, smoke_tests=['DebugPlain'], 181 # Using PCHs fails with this error: 182 # error: /Users/travis/build/google/fruit/build/tests/test_common-precompiled.h.gch: had text segment 183 # at different address 184 use_precompiled_headers_in_tests=False) 185add_osx_tests(compiler='clang-6.0', xcode_version='11.4', stl='libc++', clang_tidy=False) 186add_osx_tests(compiler='clang-8.0', xcode_version='11.4', stl='libc++', smoke_tests=['DebugPlain'], 187 clang_tidy=False, 188 # Disabled due to https://bugs.llvm.org/show_bug.cgi?id=41625. 189 use_precompiled_headers_in_tests=False) 190 191add_osx_tests(compiler='clang-default', xcode_version='9.4', stl='libc++', clang_tidy=False) 192add_osx_tests(compiler='clang-default', xcode_version='11.3', stl='libc++', clang_tidy=False, 193 # Disabled due to https://bugs.llvm.org/show_bug.cgi?id=41625. 194 use_precompiled_headers_in_tests=False, 195 smoke_tests=['DebugPlain']) 196 197# ** Disabled combinations ** 198# 199# These fail with "'type_traits' file not found" (the <type_traits> header is missing). 200# 201# add_osx_tests('gcc-default', stl='libstdc++') 202# add_osx_tests('clang-default', stl='libstdc++') 203# add_osx_tests('clang-3.5', stl='libstdc++') 204# add_osx_tests('clang-3.6', stl='libstdc++') 205# 206# 207# The compiler complains that the 2-argument constructor of std::pair is ambiguous, even after 208# adding explicit casts to the exact types of the expected overload. 209# 210# add_osx_tests('clang-default', stl='libc++') 211# 212# 213# This triggers an assert error in the compiler, with the message: 214# "expected to get called on an inlined function!" [...] function isMSExternInline, file Decl.cpp, line 2647. 215# 216# add_osx_tests('clang-3.5', stl='libc++', asan=False, ubsan=False) 217# 218# 219# This fails with this error: 220# /usr/include/c++/v1/string:1938:44: error: 'basic_string<_CharT, _Traits, _Allocator>' is missing 221# exception specification 'noexcept(is_nothrow_copy_constructible<allocator_type>::value)' 222# TODO: Try again every once in a while (to re-enable these once the bug in libc++ is fixed). 223# 224# add_ubuntu_tests(ubuntu_version='16.04', compiler='clang-3.8', stl='libc++', asan=False, ubsan=False) 225# 226 227 228yaml_file = { 229 'sudo': 'required', 230 'dist': 'xenial', 231 'services': ['docker'], 232 'language': 'cpp', 233 'branches': { 234 'only': ['master'], 235 }, 236 'matrix': { 237 'fast_finish': True, 238 'include': build_matrix_smoke_test_rows + build_matrix_rows, 239 }, 240} 241 242 243class CustomDumper(yaml.SafeDumper): 244 def ignore_aliases(self, _data): 245 return True 246 247 248print('#') 249print('# This file was auto-generated from extras/scripts/travis_yml_generator.py, DO NOT EDIT') 250print('#') 251print(yaml.dump(yaml_file, default_flow_style=False, Dumper=CustomDumper)) 252