| ############################################################################ |
| # Copyright 2016-2017 Intel Corporation |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| ############################################################################ |
| |
| """use scons -k to invoke all builds regardless of unit test failures |
| """ |
| import string |
| import sys |
| import SCons.Script |
| import os.path |
| import subprocess |
| from subprocess import Popen, PIPE |
| from parts import * |
| import re |
| import tempfile |
| import shutil |
| from collections import OrderedDict |
| |
| def get_parts_versions(env): |
| """Get Parts related versions given SCons environment env""" |
| return OrderedDict({'python': string.split(sys.version, " ", 1)[0], |
| 'scons': str(SCons.__version__), |
| 'parts': str(PartsExtensionVersion())}) |
| |
| def get_toolchain_versions(env): |
| """Get version of compilation toolchain given SCons environment env""" |
| versions = OrderedDict() |
| if 'MSVC_VERSION' in env: |
| versions['compiler'] = 'MSVC ' + env['MSVC_VERSION'] |
| cmd = env.subst('echo int main(){return 0;} > a.cpp' |
| ' | $CXX $CCFLAGS a.cpp /link /verbose') |
| defaultlib_regexp = r'.*Searching (.*\.lib).*' |
| elif 'GCC_VERSION' in env: |
| versions['compiler'] = 'GCC ' + env['GCC_VERSION'] |
| if 'GXX_VERSION' in env: |
| versions['compiler'] += ' and GXX ' + env['GXX_VERSION'] |
| if os.name == 'nt': |
| cmd = env.subst('echo int main(){return 0;}' |
| ' | $CXX $CCFLAGS -xc++ -Wl,--verbose -') |
| else: |
| cmd = env.subst('echo "int main(){return 0;}"' |
| ' | $CXX $CCFLAGS -xc++ -Wl,--verbose -') |
| else: |
| if os.name == 'nt': |
| cmd = env.subst('echo int main(){return 0;}' |
| ' | $CXX $CCFLAGS -xc++ -Wl,--verbose -') |
| else: |
| cmd = env.subst('echo "int main(){return 0;}"' |
| ' | $CC $CCFLAGS -xc -Wl,--verbose -') |
| if os.name == 'nt': |
| defaultlib_regexp = r'\n.* open (.*) succeeded' |
| else: |
| defaultlib_regexp = r'[\n(](/.*\.so[-.\da-fA-F]*).*' |
| |
| # Intel C compiler always depends from base toolchain |
| if 'INTELC_VERSION' in env: |
| versions['compiler'] = 'INTELC {0} with {1}'.format( |
| env['INTELC_VERSION'], |
| versions['compiler']) |
| |
| env['ENV']['PATH'] = str(env['ENV']['PATH']) |
| temp_dir = tempfile.mkdtemp() |
| try: |
| proc = subprocess.Popen(cmd, |
| cwd=temp_dir, |
| env=env['ENV'], |
| shell=True, |
| stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
| stdout, _ = proc.communicate() |
| if proc.returncode != 0: |
| versions['default_libs'] = 'failure executing: "{0}"'.format(cmd) |
| else: |
| default_libs = list( |
| set(re.findall(defaultlib_regexp, stdout, re.M))) |
| if 'MSVC_VERSION' in env: |
| # for windows additionally report versions of Windows Kit used |
| runtime_version_set = set() |
| for lib_path in default_libs: |
| path_components = os.path.realpath(lib_path).split(os.sep) |
| if 'Windows Kits' in path_components: |
| i = path_components.index('Windows Kits') |
| runtime_version_set.add( |
| 'Windows Kits {0} {1}'.format(path_components[i + 1], |
| path_components[i + 3])) |
| versions['sdk_or_libc'] = '; '.join(list(runtime_version_set)) |
| else: |
| # for posix additionally report versions of libc used |
| versions['sdk_or_libc'] = os.path.split(os.path.realpath( |
| next((lib for lib in default_libs if |
| 'libc' in lib.lower() and 'libcilk' not in lib.lower()), None)))[1] |
| versions['default_libs'] = default_libs |
| finally: |
| shutil.rmtree(temp_dir) |
| |
| return versions |
| |
| |
| def log_versions(env, include_toolchain=True): |
| """Log tools and libraries versions given SCons environment env |
| |
| Args: |
| env: Scons environment. |
| include_toolchain: Log version of compilation toolchain if True. |
| """ |
| |
| versions = get_parts_versions(env) |
| if include_toolchain: |
| versions.update(get_toolchain_versions(env)) |
| |
| print "**************** VERSIONS *************" |
| long_names = { |
| 'python': 'Python Version', |
| 'scons': 'SCons Version', |
| 'parts': 'Parts Version', |
| 'compiler': 'Compiler Version', |
| 'sdk_or_libc': 'Libc/SDK', |
| 'default_libs': 'Default Libs' |
| } |
| for name, value in versions.iteritems(): |
| if not isinstance(value, list): |
| print '* {0}: {1}'.format(long_names.get(name, name), value) |
| else: |
| print '* {0}:\n* \t{1}'.format(long_names.get(name, name), |
| '\n* \t'.join(sorted(value))) |
| print "***************************************" |
| |
| |
| def include_parts(part_list, **kwargs): |
| for parts_file in part_list: |
| if os.path.isfile(DefaultEnvironment().subst(parts_file)): |
| Part(parts_file=parts_file, **kwargs) |
| |
| |
| ######## Part groups #################################################### |
| ipp_parts = ['ext/ipp/ippcp.parts'] |
| utest_parts = ['ext/gtest/gtest.parts', |
| 'epid/common-testhelper/common-testhelper.parts'] |
| common_parts = ['epid/common/common.parts'] |
| member_parts = ['epid/member/member.parts'] |
| verifier_parts = ['epid/verifier/verifier.parts'] |
| util_parts = ['example/util/util.parts'] |
| example_parts = ['ext/argtable3/argtable3.parts', |
| 'example/verifysig/verifysig.parts', |
| 'example/signmsg/signmsg.parts', |
| 'example/data/data.parts', |
| 'example/compressed_data/compressed_data.parts'] |
| sizing_parts = ['example/util/util_static.parts', |
| 'example/signmsg/signmsg_shared.parts', |
| 'example/verifysig/verifysig_shared.parts', |
| 'example/verifysig/verifysig11_shared.parts'] |
| example_static_parts = ['example/util/util_static.parts', |
| 'example/signmsg/signmsg_static.parts', |
| 'example/verifysig/verifysig_static.parts'] |
| tools_parts = ['tools/revokegrp/revokegrp.parts', |
| 'tools/revokekey/revokekey.parts', |
| 'tools/revokesig/revokesig.parts', |
| 'tools/extractkeys/extractkeys.parts', |
| 'tools/extractgrps/extractgrps.parts'] |
| testbot_test_parts = ['test/testbot/testbot.parts', |
| 'test/testbot/signmsg/signmsg_testbot.parts', |
| 'test/testbot/verifysig/verifysig_testbot.parts', |
| 'test/testbot/integration/integration_testbot.parts', |
| 'test/testbot/ssh_remote/ssh_remote_testbot.parts', |
| 'test/testbot/revokegrp/revokegrp_testbot.parts', |
| 'test/testbot/revokekey/revokekey_testbot.parts', |
| 'test/testbot/revokesig/revokesig_testbot.parts', |
| 'test/testbot/extractkeys/extractkeys_testbot.parts', |
| 'test/testbot/extractgrps/extractgrps_testbot.parts', |
| 'tools/reports/reports.parts'] |
| tss_test_parts = ['test/tss/tss.parts'] |
| package_parts = ['ext/gtest/gtest.parts', |
| 'ext/ipp/ippcp.parts', |
| 'package.parts'] |
| memory_profiler_parts = ['tools/memory_profiler/memory_profiler.parts'] |
| internal_tools_parts = ['ext/argtable3/argtable3.parts', |
| 'tools/ikgfwrapper/ikgfwrapper.parts'] |
| epid_data = ['test/epid_data/epid_data.parts'] |
| perf_benchmark_parts = ['ext/google_benchmark/google_benchmark.parts', |
| 'test/performance/performance.parts'] |
| memory_benchmark_parts = ['test/dynamic_memory/dynamic_memory.parts'] |
| ######## End Part groups ############################################### |
| ######## Commandline option setup ####################################### |
| product_variants = [ |
| 'production', |
| 'internal-test', |
| 'package-epid-sdk', |
| 'internal-tools', |
| 'benchmark', |
| 'tiny', |
| 'internal-test-tiny' |
| ] |
| |
| default_variant = 'production' |
| |
| |
| def is_production(): |
| return GetOption("product-variant") == 'production' |
| |
| |
| def is_internal_test(): |
| return GetOption("product-variant") == 'internal-test' |
| |
| |
| def is_internal_tools(): |
| return GetOption("product-variant") == 'internal-tools' |
| |
| |
| def is_package(): |
| return GetOption("product-variant") == 'package-epid-sdk' |
| |
| |
| def is_benchmark(): |
| return GetOption("product-variant") == 'benchmark' |
| |
| def is_tiny(): |
| return GetOption("product-variant") == 'tiny' |
| |
| def is_internal_test_tiny(): |
| return GetOption("product-variant") == 'internal-test-tiny' |
| |
| |
| def use_commercial_ipp(): |
| return GetOption("use-commercial-ipp") |
| |
| |
| def use_tss(): |
| return GetOption("use-tss") |
| |
| |
| def config_has_instrumentation(): |
| return any(DefaultEnvironment().isConfigBasedOn(config_name) |
| for config_name in ['instr_release']) |
| |
| |
| def variant_dirname(): |
| s = GetOption("product-variant") |
| if s == 'production': |
| return 'epid-sdk' |
| elif s == 'package-epid-sdk': |
| return 'epid-sdk' |
| elif s == 'tiny': |
| return 'epid-sdk' |
| else: |
| return s |
| |
| |
| AddOption("--product-variant", "--prod-var", nargs=1, |
| help=("Select product variant to build. Possible " |
| "options are: {0}. The default is {1} if no option " |
| "is specified").format(", ".join(product_variants), |
| default_variant), |
| action='store', dest='product-variant', type='choice', |
| choices=product_variants, default=default_variant) |
| |
| AddOption("--use-commercial-ipp", |
| help=("Link with commercial IPP. The IPPCRYPTOROOT environment " |
| "variable must be set."), |
| action='store_true', dest='use-commercial-ipp', |
| default=False) |
| |
| AddOption("--use-tss", |
| help=("Link with TPM TSS. The TSSROOT environment variable " |
| "must be set."), |
| action='store_true', dest='use-tss', |
| default=False) |
| |
| AddOption("--ipp-shared", |
| help=("Build /ext/ipp as shared library."), |
| action='store_true', dest='ipp-shared', |
| default=False) |
| |
| AddOption("--enable-sanitizers", |
| help=("Build with sanitizers (https://github.com/google/sanitizers)."), |
| action='store_true', dest='sanitizers', |
| default=False) |
| |
| AddOption("--sanitizers-recover", |
| help=("Configure sanititzers to recover and continue execution " |
| "on error found. Only applicable when sanitizers are enabled." |
| "See --enable-sanitizers option."), |
| action='store_true', dest='sanitizers-recover', |
| default=False) |
| |
| |
| SetOptionDefault("PRODUCT_VARIANT", variant_dirname()) |
| |
| ######## End Commandline option setup ################################### |
| |
| |
| # fix for parts 0.10.8 until we get better logic to extract ${CC} |
| SetOptionDefault('PARTS_USE_SHORT_TOOL_NAMES', 1) |
| |
| |
| def enable_sanitizers(recover): |
| """ |
| Configures compiler to enable sanitizers. |
| Adds sanitizer options to default scons environment such |
| that it affects all parts. |
| Args: |
| recover: Enable sanitizers recovery from errors found when True. |
| """ |
| env = DefaultEnvironment() |
| error_msg = None |
| try: |
| major = int(env.subst('$GCC_VERSION').partition('.')[0]) |
| except ValueError: |
| major = 0 |
| |
| if major >= 6 and env['TARGET_OS'] == 'posix': |
| if 'INTELC_VERSION' not in env: |
| ccflags = ['-fsanitize=address,undefined', '-fno-sanitize=alignment', |
| '-fno-sanitize=shift', '-fno-omit-frame-pointer'] |
| if recover: |
| ccflags = ccflags + ['-fsanitize-recover=all', '-fsanitize-recover=address'] |
| else: |
| ccflags = ccflags + ['-fno-sanitize-recover'] |
| # Extends default flags with sanitizer options |
| SetOptionDefault('CCFLAGS', ccflags) |
| SetOptionDefault('LIBS', ['asan', 'ubsan']) |
| else: |
| error_msg = """ |
| Build with sanitizers is not supported for Intel(R) C++ Compiler. |
| Try scons --toolchain=gcc_6 --target=posix |
| """ |
| else: |
| # User experience with sanitizers in GCC 4.8 is not great. Use at least GCC 6.x. |
| error_msg = """ |
| Build with sanitizers is only supported for GCC version greater than |
| 6.x targeting posix OS. Current GCC version is "{0}" and OS target is "{1}". |
| Try scons --toolchain=gcc_6 --target=posix |
| """.format(env.get('GCC_VERSION', 'unknown'), env.get('TARGET_OS', 'unknown')) |
| if error_msg is not None: |
| env.PrintError(error_msg) |
| |
| |
| def set_default_production_options(): |
| SetOptionDefault('CONFIG', 'release') |
| |
| SetOptionDefault('TARGET_VARIANT', '${TARGET_OS}-${TARGET_ARCH}') |
| |
| SetOptionDefault('INSTALL_ROOT', |
| '#_install/${PRODUCT_VARIANT}') |
| |
| SetOptionDefault('INSTALL_TOOLS_BIN', |
| '$INSTALL_ROOT/tools') |
| |
| SetOptionDefault('INSTALL_SAMPLE_BIN', |
| '$INSTALL_ROOT/example') |
| |
| SetOptionDefault('INSTALL_EPID_INCLUDE', |
| '$INSTALL_ROOT/include/epid') |
| |
| SetOptionDefault('INSTALL_IPP_INCLUDE', |
| '$INSTALL_ROOT/include/ext/ipp/include') |
| |
| SetOptionDefault('INSTALL_TEST_BIN', |
| '$INSTALL_ROOT/test') |
| |
| SetOptionDefault('INSTALL_LIB', |
| '$INSTALL_ROOT/lib/${TARGET_VARIANT}') |
| |
| SetOptionDefault('INSTALL_SAMPLE_DATA', |
| '$INSTALL_ROOT/example') |
| |
| SetOptionDefault('INSTALL_TOOLS_DATA', |
| '$INSTALL_ROOT/tools') |
| |
| SetOptionDefault('PACKAGE_DIR', |
| '#_package') |
| |
| SetOptionDefault('PACKAGE_ROOT', |
| '#_package/${PRODUCT_VARIANT}') |
| |
| SetOptionDefault('ROOT', |
| '#') |
| |
| SetOptionDefault('PACKAGE_NAME', |
| '{PRODUCT_VARIANT}') |
| |
| |
| if GetOption("sanitizers"): |
| enable_sanitizers(GetOption("sanitizers-recover")) |
| |
| if is_production(): |
| set_default_production_options() |
| ipp_mode = ['install_lib'] |
| if use_commercial_ipp(): |
| ipp_mode.append('use_commercial_ipp') |
| sdk_mode = ['install_lib'] |
| if use_tss(): |
| sdk_mode.append('use_tss') |
| if GetOption('ipp-shared'): |
| ipp_mode.append('build_ipp_shared') |
| include_parts(ipp_parts, mode=ipp_mode, |
| INSTALL_INCLUDE='${INSTALL_IPP_INCLUDE}') |
| include_parts(utest_parts + common_parts + |
| member_parts + verifier_parts, |
| mode=sdk_mode, |
| INSTALL_INCLUDE='${INSTALL_EPID_INCLUDE}') |
| include_parts(util_parts + example_parts, |
| INSTALL_INCLUDE='${INSTALL_EPID_INCLUDE}', |
| INSTALL_BIN='${INSTALL_SAMPLE_BIN}', |
| INSTALL_DATA='${INSTALL_SAMPLE_DATA}') |
| include_parts(tools_parts, |
| INSTALL_BIN='${INSTALL_TOOLS_BIN}', |
| INSTALL_DATA='${INSTALL_TOOLS_DATA}') |
| Default('all') |
| Default('utest::') |
| if not use_tss(): |
| Default('run_utest::') |
| |
| if is_internal_test(): |
| set_default_production_options() |
| sdk_mode = [] |
| if use_tss(): |
| sdk_mode.append('use_tss') |
| include_parts(tss_test_parts) |
| include_parts(ipp_parts) |
| include_parts(utest_parts + common_parts + |
| member_parts + verifier_parts, |
| mode=sdk_mode) |
| include_parts(util_parts + example_parts, |
| INSTALL_BIN='${INSTALL_SAMPLE_BIN}', |
| INSTALL_DATA='${INSTALL_SAMPLE_DATA}') |
| include_parts(sizing_parts, |
| INSTALL_BIN='${INSTALL_SAMPLE_BIN}') |
| include_parts(tools_parts, INSTALL_BIN='${INSTALL_TOOLS_BIN}') |
| include_parts(testbot_test_parts) |
| Default('all') |
| |
| if is_internal_tools(): |
| set_default_production_options() |
| include_parts(ipp_parts + utest_parts + common_parts + verifier_parts + member_parts + util_parts) |
| include_parts(internal_tools_parts + memory_profiler_parts, |
| INSTALL_BIN='${INSTALL_TOOLS_BIN}') |
| Default('ikgfwrapper', 'memory_profiler') |
| Default('run_utest::memory_profiler::') |
| |
| if is_benchmark(): |
| set_default_production_options() |
| MODE = [] |
| if config_has_instrumentation(): |
| MODE.append('use_memory_profiler') |
| ipp_mode = [] |
| if use_commercial_ipp(): |
| ipp_mode.append('use_commercial_ipp') |
| |
| # install ipp static and ipp shared builds into separate locations |
| if GetOption('ipp-shared'): |
| ipp_mode.append('build_ipp_shared') |
| SetOptionDefault('INSTALL_TEST_BIN', |
| '$INSTALL_ROOT/test_ipp_shared') |
| SetOptionDefault('INSTALL_LIB', |
| '$INSTALL_ROOT/lib_ipp_shared') |
| else: |
| SetOptionDefault('INSTALL_LIB', |
| '$INSTALL_ROOT/lib') |
| |
| # do not allow file links to keep previous builds intact |
| SetOptionDefault('CCOPY_LOGIC', 'copy') |
| |
| include_parts(ipp_parts, config_independent=True, mode=MODE + ipp_mode, |
| INSTALL_BIN='${INSTALL_TEST_BIN}') |
| include_parts(example_static_parts + utest_parts + perf_benchmark_parts + |
| common_parts + verifier_parts + |
| sizing_parts + epid_data, |
| config_independent=True, |
| mode=MODE, |
| INSTALL_BIN='${INSTALL_TEST_BIN}') |
| |
| member_mode = ['install_lib'] |
| member_cfg = ('embedded' if not DefaultEnvironment().isConfigBasedOn( |
| 'debug') and not config_has_instrumentation() else DefaultEnvironment().subst('$CONFIG')) |
| Part(parts_file='epid/common/tinycommon.parts', CONFIG=member_cfg) |
| Part(parts_file='epid/member/tinymember.parts', CONFIG=member_cfg, |
| config_independent=True, mode=MODE + member_mode, INSTALL_BIN='${INSTALL_TEST_BIN}') |
| |
| if config_has_instrumentation(): |
| include_parts(memory_benchmark_parts + memory_profiler_parts, |
| config_independent=True, |
| mode=MODE, |
| INSTALL_BIN='${INSTALL_TEST_BIN}') |
| |
| Default('build::') |
| |
| if is_package(): |
| set_default_production_options() |
| include_parts(package_parts, |
| mode=['install_package'], |
| INSTALL_TOP_LEVEL='${PACKAGE_ROOT}') |
| Default('package') |
| |
| if is_tiny(): |
| set_default_production_options() |
| ### Member |
| Part(parts_file='ext/gtest/gtest.parts') |
| member_mode = ['install_lib'] |
| member_cfg = ('embedded' |
| if not DefaultEnvironment().isConfigBasedOn('debug') |
| else DefaultEnvironment().subst('$CONFIG')) |
| Part(parts_file='epid/common/tinycommon.parts', CONFIG=member_cfg) |
| Part(parts_file='epid/member/tinymember.parts', CONFIG=member_cfg, |
| config_independent=True, mode=member_mode) |
| Default('member::') |
| Default('run_utest::member::') |
| ### Verifier, samples and tools |
| verifier_mode = ['install_lib'] |
| ipp_mode = ['install_lib'] |
| if use_commercial_ipp(): |
| ipp_mode.append('use_commercial_ipp') |
| if GetOption('ipp-shared'): |
| ipp_mode.append('build_ipp_shared') |
| include_parts(ipp_parts, mode=ipp_mode, |
| INSTALL_INCLUDE='${INSTALL_IPP_INCLUDE}') |
| Part(parts_file='epid/common-testhelper/common-testhelper.parts', |
| config_independent=True) |
| include_parts(common_parts + verifier_parts, |
| mode=verifier_mode, |
| INSTALL_INCLUDE='${INSTALL_EPID_INCLUDE}') |
| include_parts(util_parts + example_parts, |
| INSTALL_INCLUDE='${INSTALL_EPID_INCLUDE}', |
| INSTALL_BIN='${INSTALL_SAMPLE_BIN}', |
| INSTALL_DATA='${INSTALL_SAMPLE_DATA}') |
| include_parts(tools_parts, |
| INSTALL_BIN='${INSTALL_TOOLS_BIN}', |
| INSTALL_DATA='${INSTALL_TOOLS_DATA}') |
| Default('all') |
| Default('utest::') |
| |
| if is_internal_test_tiny(): |
| set_default_production_options() |
| sdk_mode = [] |
| ### Member |
| Part(parts_file='ext/gtest/gtest.parts') |
| member_cfg = ('embedded' |
| if not DefaultEnvironment().isConfigBasedOn('debug') |
| else DefaultEnvironment().subst('$CONFIG')) |
| Part(parts_file='epid/common/tinycommon.parts', CONFIG=member_cfg) |
| Part(parts_file='epid/member/tinymember.parts', CONFIG=member_cfg, |
| config_independent=True, mode=sdk_mode) |
| ### Verifier, samples and tools |
| include_parts(ipp_parts) |
| Part(parts_file='epid/common-testhelper/common-testhelper.parts', |
| config_independent=True) |
| include_parts(common_parts + verifier_parts, |
| mode=sdk_mode) |
| include_parts(util_parts + example_parts, |
| INSTALL_BIN='${INSTALL_SAMPLE_BIN}', |
| INSTALL_DATA='${INSTALL_SAMPLE_DATA}') |
| include_parts(tools_parts, INSTALL_BIN='${INSTALL_TOOLS_BIN}') |
| include_parts(testbot_test_parts) |
| Default('build::') |
| |
| log_versions(DefaultEnvironment(), not is_package()) |