• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1############################################################################
2# Copyright 2016-2017 Intel Corporation
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############################################################################
16
17"""use scons -k to invoke all builds regardless of unit test failures
18"""
19import string
20import sys
21import SCons.Script
22import os.path
23import subprocess
24from subprocess import Popen, PIPE
25from parts import *
26import re
27import tempfile
28import shutil
29from collections import OrderedDict
30
31def get_parts_versions(env):
32    """Get Parts related versions given SCons environment env"""
33    return OrderedDict({'python': string.split(sys.version, " ", 1)[0],
34                        'scons': str(SCons.__version__),
35                        'parts': str(PartsExtensionVersion())})
36
37def get_toolchain_versions(env):
38    """Get version of compilation toolchain given SCons environment env"""
39    versions = OrderedDict()
40    if 'MSVC_VERSION' in env:
41        versions['compiler'] = 'MSVC ' + env['MSVC_VERSION']
42        cmd = env.subst('echo int main(){return 0;} > a.cpp'
43                        ' | $CXX $CCFLAGS a.cpp /link /verbose')
44        defaultlib_regexp = r'.*Searching (.*\.lib).*'
45    elif 'GCC_VERSION' in env:
46        versions['compiler'] = 'GCC ' + env['GCC_VERSION']
47        if 'GXX_VERSION' in env:
48            versions['compiler'] += ' and GXX ' + env['GXX_VERSION']
49            if os.name == 'nt':
50                cmd = env.subst('echo int main(){return 0;}'
51                                ' | $CXX $CCFLAGS -xc++ -Wl,--verbose -')
52            else:
53                cmd = env.subst('echo "int main(){return 0;}"'
54                                ' | $CXX $CCFLAGS -xc++ -Wl,--verbose -')
55        else:
56            if os.name == 'nt':
57                cmd = env.subst('echo int main(){return 0;}'
58                                ' | $CXX $CCFLAGS -xc++ -Wl,--verbose -')
59            else:
60                cmd = env.subst('echo "int main(){return 0;}"'
61                                ' | $CC  $CCFLAGS -xc   -Wl,--verbose -')
62        if os.name == 'nt':
63            defaultlib_regexp = r'\n.* open (.*) succeeded'
64        else:
65            defaultlib_regexp = r'[\n(](/.*\.so[-.\da-fA-F]*).*'
66
67    # Intel C compiler always depends from base toolchain
68    if 'INTELC_VERSION' in env:
69        versions['compiler'] = 'INTELC {0} with {1}'.format(
70            env['INTELC_VERSION'],
71            versions['compiler'])
72
73    env['ENV']['PATH'] = str(env['ENV']['PATH'])
74    temp_dir = tempfile.mkdtemp()
75    try:
76        proc = subprocess.Popen(cmd,
77                                cwd=temp_dir,
78                                env=env['ENV'],
79                                shell=True,
80                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
81        stdout, _ = proc.communicate()
82        if proc.returncode != 0:
83            versions['default_libs'] = 'failure executing: "{0}"'.format(cmd)
84        else:
85            default_libs = list(
86                set(re.findall(defaultlib_regexp, stdout, re.M)))
87            if 'MSVC_VERSION' in env:
88                # for windows additionally report versions of Windows Kit used
89                runtime_version_set = set()
90                for lib_path in default_libs:
91                    path_components = os.path.realpath(lib_path).split(os.sep)
92                    if 'Windows Kits' in path_components:
93                        i = path_components.index('Windows Kits')
94                        runtime_version_set.add(
95                            'Windows Kits {0} {1}'.format(path_components[i + 1],
96                                                          path_components[i + 3]))
97                versions['sdk_or_libc'] = '; '.join(list(runtime_version_set))
98            else:
99                # for posix additionally report versions of libc used
100                versions['sdk_or_libc'] = os.path.split(os.path.realpath(
101                    next((lib for lib in default_libs if
102                          'libc' in lib.lower() and 'libcilk' not in lib.lower()), None)))[1]
103            versions['default_libs'] = default_libs
104    finally:
105        shutil.rmtree(temp_dir)
106
107    return versions
108
109
110def log_versions(env, include_toolchain=True):
111    """Log tools and libraries versions given SCons environment env
112
113    Args:
114        env: Scons environment.
115        include_toolchain: Log version of compilation toolchain if True.
116    """
117
118    versions = get_parts_versions(env)
119    if include_toolchain:
120        versions.update(get_toolchain_versions(env))
121
122    print "**************** VERSIONS *************"
123    long_names = {
124        'python': 'Python Version',
125        'scons': 'SCons  Version',
126        'parts': 'Parts  Version',
127        'compiler': 'Compiler Version',
128        'sdk_or_libc': 'Libc/SDK',
129        'default_libs': 'Default Libs'
130    }
131    for name, value in versions.iteritems():
132        if not isinstance(value, list):
133            print '* {0}: {1}'.format(long_names.get(name, name), value)
134        else:
135            print '* {0}:\n* \t{1}'.format(long_names.get(name, name),
136                                           '\n* \t'.join(sorted(value)))
137    print "***************************************"
138
139
140def include_parts(part_list, **kwargs):
141    for parts_file in part_list:
142        if os.path.isfile(DefaultEnvironment().subst(parts_file)):
143            Part(parts_file=parts_file, **kwargs)
144
145
146######## Part groups ####################################################
147ipp_parts = ['ext/ipp/ippcp.parts']
148utest_parts = ['ext/gtest/gtest.parts',
149               'epid/common-testhelper/common-testhelper.parts']
150common_parts = ['epid/common/common.parts']
151member_parts = ['epid/member/member.parts']
152verifier_parts = ['epid/verifier/verifier.parts']
153util_parts = ['example/util/util.parts']
154example_parts = ['ext/argtable3/argtable3.parts',
155                 'example/verifysig/verifysig.parts',
156                 'example/signmsg/signmsg.parts',
157                 'example/data/data.parts',
158                 'example/compressed_data/compressed_data.parts']
159sizing_parts = ['example/util/util_static.parts',
160                'example/signmsg/signmsg_shared.parts',
161                'example/verifysig/verifysig_shared.parts',
162                'example/verifysig/verifysig11_shared.parts']
163example_static_parts = ['example/util/util_static.parts',
164                        'example/signmsg/signmsg_static.parts',
165                        'example/verifysig/verifysig_static.parts']
166tools_parts = ['tools/revokegrp/revokegrp.parts',
167               'tools/revokekey/revokekey.parts',
168               'tools/revokesig/revokesig.parts',
169               'tools/extractkeys/extractkeys.parts',
170               'tools/extractgrps/extractgrps.parts']
171testbot_test_parts = ['test/testbot/testbot.parts',
172                      'test/testbot/signmsg/signmsg_testbot.parts',
173                      'test/testbot/verifysig/verifysig_testbot.parts',
174                      'test/testbot/integration/integration_testbot.parts',
175                      'test/testbot/ssh_remote/ssh_remote_testbot.parts',
176                      'test/testbot/revokegrp/revokegrp_testbot.parts',
177                      'test/testbot/revokekey/revokekey_testbot.parts',
178                      'test/testbot/revokesig/revokesig_testbot.parts',
179                      'test/testbot/extractkeys/extractkeys_testbot.parts',
180                      'test/testbot/extractgrps/extractgrps_testbot.parts',
181                      'tools/reports/reports.parts']
182tss_test_parts = ['test/tss/tss.parts']
183package_parts = ['ext/gtest/gtest.parts',
184                 'ext/ipp/ippcp.parts',
185                 'package.parts']
186memory_profiler_parts = ['tools/memory_profiler/memory_profiler.parts']
187internal_tools_parts = ['ext/argtable3/argtable3.parts',
188                        'tools/ikgfwrapper/ikgfwrapper.parts']
189epid_data = ['test/epid_data/epid_data.parts']
190perf_benchmark_parts = ['ext/google_benchmark/google_benchmark.parts',
191                        'test/performance/performance.parts']
192memory_benchmark_parts = ['test/dynamic_memory/dynamic_memory.parts']
193######## End Part groups ###############################################
194######## Commandline option setup #######################################
195product_variants = [
196    'production',
197    'internal-test',
198    'package-epid-sdk',
199    'internal-tools',
200    'benchmark',
201    'tiny',
202    'internal-test-tiny'
203]
204
205default_variant = 'production'
206
207
208def is_production():
209    return GetOption("product-variant") == 'production'
210
211
212def is_internal_test():
213    return GetOption("product-variant") == 'internal-test'
214
215
216def is_internal_tools():
217    return GetOption("product-variant") == 'internal-tools'
218
219
220def is_package():
221    return GetOption("product-variant") == 'package-epid-sdk'
222
223
224def is_benchmark():
225    return GetOption("product-variant") == 'benchmark'
226
227def is_tiny():
228    return GetOption("product-variant") == 'tiny'
229
230def is_internal_test_tiny():
231    return GetOption("product-variant") == 'internal-test-tiny'
232
233
234def use_commercial_ipp():
235    return GetOption("use-commercial-ipp")
236
237
238def use_tss():
239    return GetOption("use-tss")
240
241
242def config_has_instrumentation():
243    return any(DefaultEnvironment().isConfigBasedOn(config_name)
244               for config_name in ['instr_release'])
245
246
247def variant_dirname():
248    s = GetOption("product-variant")
249    if s == 'production':
250        return 'epid-sdk'
251    elif s == 'package-epid-sdk':
252        return 'epid-sdk'
253    elif s == 'tiny':
254        return 'epid-sdk'
255    else:
256        return s
257
258
259AddOption("--product-variant", "--prod-var", nargs=1,
260          help=("Select product variant to build. Possible "
261                "options are: {0}. The default is {1} if no option "
262                "is specified").format(", ".join(product_variants),
263                                       default_variant),
264          action='store', dest='product-variant', type='choice',
265          choices=product_variants, default=default_variant)
266
267AddOption("--use-commercial-ipp",
268          help=("Link with commercial IPP. The IPPCRYPTOROOT environment "
269                "variable must be set."),
270          action='store_true', dest='use-commercial-ipp',
271          default=False)
272
273AddOption("--use-tss",
274          help=("Link with TPM TSS. The TSSROOT environment variable "
275                "must be set."),
276          action='store_true', dest='use-tss',
277          default=False)
278
279AddOption("--ipp-shared",
280          help=("Build /ext/ipp as shared library."),
281          action='store_true', dest='ipp-shared',
282          default=False)
283
284AddOption("--enable-sanitizers",
285          help=("Build with sanitizers (https://github.com/google/sanitizers)."),
286          action='store_true', dest='sanitizers',
287          default=False)
288
289AddOption("--sanitizers-recover",
290          help=("Configure sanititzers to recover and continue execution "
291                "on error found. Only applicable when sanitizers are enabled."
292                "See --enable-sanitizers option."),
293          action='store_true', dest='sanitizers-recover',
294          default=False)
295
296
297SetOptionDefault("PRODUCT_VARIANT", variant_dirname())
298
299######## End Commandline option setup ###################################
300
301
302# fix for parts 0.10.8 until we get better logic to extract ${CC}
303SetOptionDefault('PARTS_USE_SHORT_TOOL_NAMES', 1)
304
305
306def enable_sanitizers(recover):
307    """
308        Configures compiler to enable sanitizers.
309        Adds sanitizer options to default scons environment such
310        that it affects all parts.
311    Args:
312        recover: Enable sanitizers recovery from errors found when True.
313    """
314    env = DefaultEnvironment()
315    error_msg = None
316    try:
317       major = int(env.subst('$GCC_VERSION').partition('.')[0])
318    except ValueError:
319       major = 0
320
321    if major >= 6 and env['TARGET_OS'] == 'posix':
322        if 'INTELC_VERSION' not in env:
323            ccflags = ['-fsanitize=address,undefined', '-fno-sanitize=alignment',
324                       '-fno-sanitize=shift', '-fno-omit-frame-pointer']
325            if recover:
326                ccflags = ccflags + ['-fsanitize-recover=all', '-fsanitize-recover=address']
327            else:
328                ccflags = ccflags + ['-fno-sanitize-recover']
329            # Extends default flags with sanitizer options
330            SetOptionDefault('CCFLAGS', ccflags)
331            SetOptionDefault('LIBS', ['asan', 'ubsan'])
332        else:
333            error_msg = """
334                Build with sanitizers is not supported for Intel(R) C++ Compiler.
335                Try scons --toolchain=gcc_6 --target=posix
336                """
337    else:
338        # User experience with sanitizers in GCC 4.8 is not great. Use at least GCC 6.x.
339        error_msg = """
340            Build with sanitizers is only supported for GCC version greater than
341            6.x targeting posix OS. Current GCC version is "{0}" and OS target is "{1}".
342            Try scons --toolchain=gcc_6 --target=posix
343            """.format(env.get('GCC_VERSION', 'unknown'), env.get('TARGET_OS', 'unknown'))
344    if error_msg is not None:
345        env.PrintError(error_msg)
346
347
348def set_default_production_options():
349    SetOptionDefault('CONFIG', 'release')
350
351    SetOptionDefault('TARGET_VARIANT', '${TARGET_OS}-${TARGET_ARCH}')
352
353    SetOptionDefault('INSTALL_ROOT',
354                     '#_install/${PRODUCT_VARIANT}')
355
356    SetOptionDefault('INSTALL_TOOLS_BIN',
357                     '$INSTALL_ROOT/tools')
358
359    SetOptionDefault('INSTALL_SAMPLE_BIN',
360                     '$INSTALL_ROOT/example')
361
362    SetOptionDefault('INSTALL_EPID_INCLUDE',
363                     '$INSTALL_ROOT/include/epid')
364
365    SetOptionDefault('INSTALL_IPP_INCLUDE',
366                     '$INSTALL_ROOT/include/ext/ipp/include')
367
368    SetOptionDefault('INSTALL_TEST_BIN',
369                     '$INSTALL_ROOT/test')
370
371    SetOptionDefault('INSTALL_LIB',
372                     '$INSTALL_ROOT/lib/${TARGET_VARIANT}')
373
374    SetOptionDefault('INSTALL_SAMPLE_DATA',
375                     '$INSTALL_ROOT/example')
376
377    SetOptionDefault('INSTALL_TOOLS_DATA',
378                     '$INSTALL_ROOT/tools')
379
380    SetOptionDefault('PACKAGE_DIR',
381                     '#_package')
382
383    SetOptionDefault('PACKAGE_ROOT',
384                     '#_package/${PRODUCT_VARIANT}')
385
386    SetOptionDefault('ROOT',
387                     '#')
388
389    SetOptionDefault('PACKAGE_NAME',
390                     '{PRODUCT_VARIANT}')
391
392
393if GetOption("sanitizers"):
394    enable_sanitizers(GetOption("sanitizers-recover"))
395
396if is_production():
397    set_default_production_options()
398    ipp_mode = ['install_lib']
399    if use_commercial_ipp():
400        ipp_mode.append('use_commercial_ipp')
401    sdk_mode = ['install_lib']
402    if use_tss():
403        sdk_mode.append('use_tss')
404    if GetOption('ipp-shared'):
405        ipp_mode.append('build_ipp_shared')
406    include_parts(ipp_parts, mode=ipp_mode,
407                  INSTALL_INCLUDE='${INSTALL_IPP_INCLUDE}')
408    include_parts(utest_parts + common_parts +
409                  member_parts + verifier_parts,
410                  mode=sdk_mode,
411                  INSTALL_INCLUDE='${INSTALL_EPID_INCLUDE}')
412    include_parts(util_parts + example_parts,
413                  INSTALL_INCLUDE='${INSTALL_EPID_INCLUDE}',
414                  INSTALL_BIN='${INSTALL_SAMPLE_BIN}',
415                  INSTALL_DATA='${INSTALL_SAMPLE_DATA}')
416    include_parts(tools_parts,
417                  INSTALL_BIN='${INSTALL_TOOLS_BIN}',
418                  INSTALL_DATA='${INSTALL_TOOLS_DATA}')
419    Default('all')
420    Default('utest::')
421    if not use_tss():
422        Default('run_utest::')
423
424if is_internal_test():
425    set_default_production_options()
426    sdk_mode = []
427    if use_tss():
428        sdk_mode.append('use_tss')
429        include_parts(tss_test_parts)
430    include_parts(ipp_parts)
431    include_parts(utest_parts + common_parts +
432                  member_parts + verifier_parts,
433                  mode=sdk_mode)
434    include_parts(util_parts + example_parts,
435                  INSTALL_BIN='${INSTALL_SAMPLE_BIN}',
436                  INSTALL_DATA='${INSTALL_SAMPLE_DATA}')
437    include_parts(sizing_parts,
438                  INSTALL_BIN='${INSTALL_SAMPLE_BIN}')
439    include_parts(tools_parts, INSTALL_BIN='${INSTALL_TOOLS_BIN}')
440    include_parts(testbot_test_parts)
441    Default('all')
442
443if is_internal_tools():
444    set_default_production_options()
445    include_parts(ipp_parts + utest_parts + common_parts + verifier_parts + member_parts + util_parts)
446    include_parts(internal_tools_parts + memory_profiler_parts,
447                  INSTALL_BIN='${INSTALL_TOOLS_BIN}')
448    Default('ikgfwrapper', 'memory_profiler')
449    Default('run_utest::memory_profiler::')
450
451if is_benchmark():
452    set_default_production_options()
453    MODE = []
454    if config_has_instrumentation():
455        MODE.append('use_memory_profiler')
456    ipp_mode = []
457    if use_commercial_ipp():
458        ipp_mode.append('use_commercial_ipp')
459
460    # install ipp static and ipp shared builds into separate locations
461    if GetOption('ipp-shared'):
462        ipp_mode.append('build_ipp_shared')
463        SetOptionDefault('INSTALL_TEST_BIN',
464                         '$INSTALL_ROOT/test_ipp_shared')
465        SetOptionDefault('INSTALL_LIB',
466                         '$INSTALL_ROOT/lib_ipp_shared')
467    else:
468        SetOptionDefault('INSTALL_LIB',
469                         '$INSTALL_ROOT/lib')
470
471    # do not allow file links to keep previous builds intact
472    SetOptionDefault('CCOPY_LOGIC', 'copy')
473
474    include_parts(ipp_parts, config_independent=True, mode=MODE + ipp_mode,
475                  INSTALL_BIN='${INSTALL_TEST_BIN}')
476    include_parts(example_static_parts + utest_parts + perf_benchmark_parts +
477                  common_parts + verifier_parts +
478                  sizing_parts + epid_data,
479                  config_independent=True,
480                  mode=MODE,
481                  INSTALL_BIN='${INSTALL_TEST_BIN}')
482
483    member_mode = ['install_lib']
484    member_cfg = ('embedded' if not DefaultEnvironment().isConfigBasedOn(
485        'debug') and not config_has_instrumentation() else DefaultEnvironment().subst('$CONFIG'))
486    Part(parts_file='epid/common/tinycommon.parts', CONFIG=member_cfg)
487    Part(parts_file='epid/member/tinymember.parts', CONFIG=member_cfg,
488         config_independent=True, mode=MODE + member_mode, INSTALL_BIN='${INSTALL_TEST_BIN}')
489
490    if config_has_instrumentation():
491        include_parts(memory_benchmark_parts + memory_profiler_parts,
492                      config_independent=True,
493                      mode=MODE,
494                      INSTALL_BIN='${INSTALL_TEST_BIN}')
495
496    Default('build::')
497
498if is_package():
499    set_default_production_options()
500    include_parts(package_parts,
501                  mode=['install_package'],
502                  INSTALL_TOP_LEVEL='${PACKAGE_ROOT}')
503    Default('package')
504
505if is_tiny():
506    set_default_production_options()
507    ### Member
508    Part(parts_file='ext/gtest/gtest.parts')
509    member_mode = ['install_lib']
510    member_cfg = ('embedded'
511                  if not DefaultEnvironment().isConfigBasedOn('debug')
512                  else DefaultEnvironment().subst('$CONFIG'))
513    Part(parts_file='epid/common/tinycommon.parts', CONFIG=member_cfg)
514    Part(parts_file='epid/member/tinymember.parts', CONFIG=member_cfg,
515         config_independent=True, mode=member_mode)
516    Default('member::')
517    Default('run_utest::member::')
518    ### Verifier, samples and tools
519    verifier_mode = ['install_lib']
520    ipp_mode = ['install_lib']
521    if use_commercial_ipp():
522        ipp_mode.append('use_commercial_ipp')
523    if GetOption('ipp-shared'):
524        ipp_mode.append('build_ipp_shared')
525    include_parts(ipp_parts, mode=ipp_mode,
526                  INSTALL_INCLUDE='${INSTALL_IPP_INCLUDE}')
527    Part(parts_file='epid/common-testhelper/common-testhelper.parts',
528         config_independent=True)
529    include_parts(common_parts + verifier_parts,
530                  mode=verifier_mode,
531                  INSTALL_INCLUDE='${INSTALL_EPID_INCLUDE}')
532    include_parts(util_parts + example_parts,
533                  INSTALL_INCLUDE='${INSTALL_EPID_INCLUDE}',
534                  INSTALL_BIN='${INSTALL_SAMPLE_BIN}',
535                  INSTALL_DATA='${INSTALL_SAMPLE_DATA}')
536    include_parts(tools_parts,
537                  INSTALL_BIN='${INSTALL_TOOLS_BIN}',
538                  INSTALL_DATA='${INSTALL_TOOLS_DATA}')
539    Default('all')
540    Default('utest::')
541
542if is_internal_test_tiny():
543    set_default_production_options()
544    sdk_mode = []
545    ### Member
546    Part(parts_file='ext/gtest/gtest.parts')
547    member_cfg = ('embedded'
548                  if not DefaultEnvironment().isConfigBasedOn('debug')
549                  else DefaultEnvironment().subst('$CONFIG'))
550    Part(parts_file='epid/common/tinycommon.parts', CONFIG=member_cfg)
551    Part(parts_file='epid/member/tinymember.parts', CONFIG=member_cfg,
552         config_independent=True, mode=sdk_mode)
553    ### Verifier, samples and tools
554    include_parts(ipp_parts)
555    Part(parts_file='epid/common-testhelper/common-testhelper.parts',
556         config_independent=True)
557    include_parts(common_parts + verifier_parts,
558                  mode=sdk_mode)
559    include_parts(util_parts + example_parts,
560                  INSTALL_BIN='${INSTALL_SAMPLE_BIN}',
561                  INSTALL_DATA='${INSTALL_SAMPLE_DATA}')
562    include_parts(tools_parts, INSTALL_BIN='${INSTALL_TOOLS_BIN}')
563    include_parts(testbot_test_parts)
564    Default('build::')
565
566log_versions(DefaultEnvironment(), not is_package())
567