#!/usr/bin/env python # -*- python -*- # BEGIN_LEGAL # # Copyright (c) 2021 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. # # END_LEGAL import sys import os import re import shutil import copy import time import types import optparse # sys.path is set up by calling script (mfile.py ususally) import mbuild import xed_build_common as xbc def ex_compile_and_link(env, dag, src, objs): """Return the exe name - used for the examples""" basename = os.path.basename(src) exe = env.build_dir_join(env.resuffix(basename, env['EXEEXT'])) all_obj = [] # first_example_lib and last_example_lib are for supporting # compilations using custom C runtimes. if 'first_example_lib' in env: all_obj.append(env['first_example_lib']) all_obj.extend(env.compile(dag, [src])) all_obj.extend(objs) if 'last_example_lib' in env: all_obj.append(env['last_example_lib']) lc = env.link(all_obj, exe) cmd = dag.add(env,lc) return cmd.targets[0] ########################################################################### def mkenv(): """External entry point: create the environment""" if sys.version_info[0] == 3 and sys.version_info[1] < 4: _fatal("Need python version 3.4 or later.") elif sys.version_info[0] == 2 and sys.version_info[1] < 7: _fatal("Need python version 2.7 or later.") # create an environment, parse args env = mbuild.env_t() standard_defaults = dict( doxygen_install='', doxygen='', clean=False, die_on_errors=True, xed_messages=False, xed_asserts=False, pedantic=True, clr=False, use_werror=True, dbghelp=False, install_dir='', kit_kind='base', win=False, dev=False, legal_header=None, encoder=True, enc2=True, decoder=True, ld_library_path=[], ld_library_path_for_tests=[], use_elf_dwarf=False, use_elf_dwarf_precompiled=False, strip='strip', verbose = 1, example_linkflags='', example_flags='', example_rpaths=[], android=False, xed_inc_dir=[], xed_lib_dir='', xed_enc2_libs=[], xed_dir='', build_cpp_examples=False, set_copyright=False, pin_crt='') env['xed_defaults'] = standard_defaults env.set_defaults(env['xed_defaults']) return env def xed_args(env): """For command line invocation: parse the arguments""" env.parser.add_option("--no-encoder", dest="encoder", action="store_false", help="No encoder") env.parser.add_option("--no-enc2", dest="enc2", action="store_false", help="No enc2 encoder") env.parser.add_option("--no-decoder", dest="decoder", action="store_false", help="No decoder") env.parser.add_option("--android", dest="android", action="store_true", help="Android build (avoid rpath for examples)") env.parser.add_option("--example-linkflags", dest="example_linkflags", action="store", help="Extra link flags for the examples") env.parser.add_option("--example-flags", dest="example_flags", action="store", help="Extra compilation flags for the examples") env.parser.add_option("--example-rpath", dest="example_rpaths", action="append", help="Extra rpath dirs for examples") env.parser.add_option("-c","--clean", dest="clean", action="store_true", help="Clean targets") env.parser.add_option("--keep-going", '-k', action="store_false", dest="die_on_errors", help="Keep going after errors occur when building") env.parser.add_option("--messages", action="store_true", dest="xed_messages", help="Enable use xed's debug messages") env.parser.add_option("--no-pedantic", action="store_false", dest="pedantic", help="Disable -pedantic (gnu/clang compilers).") env.parser.add_option("--asserts", action="store_true", dest="xed_asserts", help="Enable use xed's asserts") env.parser.add_option("--clr", action="store_true", dest="clr", help="Compile for Microsoft CLR") env.parser.add_option("--no-werror", action="store_false", dest="use_werror", help="Disable use of -Werror on GNU compiles") env.parser.add_option("--dbghelp", action="store_true", dest="dbghelp", help="Use dbghelp.dll on windows.") env.parser.add_option("--install-dir", dest="install_dir", action="store", help="XED Install directory. " + "Default: kits/xed-install-date-os-cpu") env.parser.add_option("--kit-kind", dest="kit_kind", action="store", help="Kit version string. " + "The default is 'base'") env.parser.add_option("--win", action="store_true", dest="win", help="Add -mno-cygwin to GCC-on-windows compilation") env.parser.add_option("--ld-library-path", action="append", dest="ld_library_path", help="Specify additions to LD_LIBRARY_PATH " + "for use when running ldd and making kits") env.parser.add_option("--ld-library-path-for-tests", action="append", dest="ld_library_path_for_tests", help="Specify additions to LD_LIBRARY_PATH " + "for use when running the tests") # elf.h is different than libelf.h. env.parser.add_option("--elf-dwarf", "--dwarf", action="store_true", dest="use_elf_dwarf", help="Use libelf/libdwarf. (Linux only)") env.parser.add_option("--elf-dwarf-precompiled", action="store_true", dest="use_elf_dwarf_precompiled", help="Use precompiled libelf/libdwarf from " + " the XED source distribution." + " This is the currently required" + " if you are installing a kit." + " Implies the --elf-dwarf knob." " (Linux only)") env.parser.add_option("--strip", action="store", dest="strip", help="Path to strip binary. (Linux only)") env.parser.add_option("--pin-crt", action="store", dest="pin_crt", help="Compile for the Pin C-runtime. Specify" + " path to pin kit") env.parser.add_option("--lib-dir", action='store', dest="xed_lib_dir", help="directory where libxed* is located.") env.parser.add_option("--enc2-lib", action='append', dest="xed_enc2_libs", help="Filenames (with paths) of the XED enc2 libraries.") env.parser.add_option("--inc-dir", action="append", dest="xed_inc_dir", help="directory where xed generated headers are located.") env.parser.add_option("--xed-dir", action="store", dest="xed_dir", help="directory where xed sources are located.") env.parser.add_option("--build-cpp-examples", action="store_true", dest="build_cpp_examples", help="Build the C++ examples default: False.") env.parser.add_option("--set-copyright", action="store_true", dest="set_copyright", help="Set the Intel copyright on Windows XED executable") env.parse_args(env['xed_defaults']) def nchk(env,s): #null string check or not set check if s not in env or len(env[s]) == 0: return True return False def init(env): xbc.init(env) if nchk(env,'xed_lib_dir'): env['xed_lib_dir'] = '../lib' if nchk(env,'xed_enc2_libs'): env['xed_enc2_libs'] = ( mbuild.glob(env['xed_lib_dir'],'*xed-chk-enc2-*') + mbuild.glob(env['xed_lib_dir'],'*xed-enc2-*') ) if nchk(env,'xed_enc2_libs'): # do not build enc2 examples if libraries are missing env['enc2'] = False if nchk(env,'xed_inc_dir'): env['xed_inc_dir'] = ['../include'] if nchk(env,'xed_dir'): env['xed_dir'] = '..' env.add_include_dir( env['src_dir'] ) # examples dir for inc in env['xed_inc_dir']: env.add_include_dir( inc ) def _wk_show_errors_only(): #True means show errors only when building. if mbuild.verbose(2): return False # show output return True # show errors only. def _add_libxed_rpath(env): """Make example tools refer to the libxed.so from the lib directory""" if env['shared'] and env.on_linux() and not env['android']: env['LINKFLAGS'] += " -Wl,-rpath,'$ORIGIN/../lib'" def build_asmparse(env, dag, otherobj): srcs = env.src_dir_join(['xed-asmparse.c']) objs = env.compile(dag, srcs) exe = ex_compile_and_link(env, dag, env.src_dir_join('xed-asmparse-main.c'), objs + otherobj + [env['link_libxed']]) return exe def build_examples(env, work_queue): """Build the examples""" example_exes = [] env['example_exes'] = [] # used by install examples_dag = mbuild.dag_t('xedexamples', env=env) if not env.on_windows(): for d in env['example_rpaths']: env.add_to_var('example_linkflags', '-Wl,-rpath,{}'.format(d)) env.add_to_var('LINKFLAGS', env['example_linkflags']) env.add_to_var('CCFLAGS', env['example_flags']) env.add_to_var('CXXFLAGS', env['example_flags']) mbuild.cmkdir(env['build_dir']) link_libxed = env['link_libxed'] if env['shared']: _add_libxed_rpath(env) # C vs C++: env is for C++ and env_c is for C programs. if env['compiler'] in ['gnu','clang', 'icc']: env['LINK'] = env['CXX'] env_c = copy.deepcopy(env) if env_c['compiler'] in ['gnu','clang']: env_c['LINK'] = '%(CC)s' if env['pin_crt']: xbc.compile_with_pin_crt_lin_mac_common_cplusplus(env) # shared files cc_shared_files = env.src_dir_join([ 'xed-examples-util.c']) if env['decoder']: cc_shared_files.extend(env.src_dir_join([ 'xed-dot.c', 'xed-dot-prep.c'])) if env['encoder']: cc_shared_files += env.src_dir_join([ 'xed-enc-lang.c']) cc_shared_objs = env.compile( examples_dag, cc_shared_files) # the XED command line tool xed_cmdline_files = [ 'xed-disas-raw.c', 'avltree.c', 'xed-disas-hex.c', 'xed-symbol-table.c'] if env.on_windows() and env['set_copyright']: # AUTOMATICALLY UPDATE YEAR IN THE RC FILE year = time.strftime("%Y") lines = open(env.src_dir_join('xed-rc-template.txt')).readlines() lines = [ re.sub('%%YEAR%%',year,x) for x in lines ] xbc.write_file(env.src_dir_join('xed.rc'), lines) xed_cmdline_files.append("xed.rc") extra_libs = [] if env['decoder']: if env.on_linux() or env.on_freebsd() or env.on_netbsd(): xed_cmdline_files.append('xed-disas-filter.c') xed_cmdline_files.append('xed-nm-symtab.c') elif env.on_mac(): xed_cmdline_files.append('xed-disas-macho.c') elif env.on_windows(): xed_cmdline_files.append('xed-disas-pecoff.cpp') if ( env['dbghelp'] and env['msvs_version'] not in ['6','7'] ): env.add_define("XED_DBGHELP") xed_cmdline_files.append('udhelp.cpp') extra_libs = ['dbghelp.lib', 'version.lib' ] xed_cmdline_files = env.src_dir_join(xed_cmdline_files) xed_cmdline_obj = copy.deepcopy(cc_shared_objs) # Env for cmdline tool (with libelf/dwarf on linux.) if env.on_windows(): # still C++ cenv = copy.deepcopy(env) else: # lin/mac are C code only. cenv = copy.deepcopy(env_c) if env.on_linux(): xbc.cond_add_elf_dwarf(cenv) if env.on_linux() or env.on_freebsd() or env.on_netbsd(): src_elf = env.src_dir_join('xed-disas-elf.c') if env['use_elf_dwarf_precompiled']: cenv2 = copy.deepcopy(cenv) # need to remove -pedantic because of redundant typedef Elf in dwarf header file cenv2.remove_from_var('CCFLAGS','-pedantic') xed_cmdline_obj += cenv2.compile(examples_dag, [src_elf]) else: xed_cmdline_files.append(src_elf) xed_cmdline_obj += cenv.compile(examples_dag, xed_cmdline_files) xed_cmdline = ex_compile_and_link(cenv, examples_dag, env.src_dir_join('xed.c'), xed_cmdline_obj + [link_libxed] + extra_libs) mbuild.msgb("CMDLINE", xed_cmdline) example_exes.append(xed_cmdline) if env['encoder']: exe = build_asmparse(cenv, examples_dag, cc_shared_objs) example_exes.append(exe) ild_examples = [] other_c_examples = [] enc2_examples = [] small_examples = ['xed-size.c'] if env['enc2']: enc2_examples += [ 'xed-enc2-1.c', 'xed-enc2-2.c', 'xed-enc2-3.c' ] if env['encoder']: small_examples += ['xed-ex5-enc.c'] other_c_examples += ['xed-ex3.c'] if env['decoder'] and env['encoder']: other_c_examples += ['xed-ex6.c', 'xed-ex9-patch.c' ] if env['decoder']: ild_examples += [ 'xed-ex-ild.c' ] other_c_examples += ['xed-ex1.c', 'xed-ex-ild2.c', 'xed-min.c', 'xed-reps.c', 'xed-ex4.c', 'xed-tester.c', 'xed-dec-print.c', 'xed-ex-agen.c', 'xed-ex7.c', 'xed-ex8.c', 'xed-ex-cpuid.c', 'xed-tables.c', 'xed-find-special.c', 'xed-dll-discovery.c'] # compile & link other_c_examples for example in env.src_dir_join(other_c_examples): example_exes.append(ex_compile_and_link(env_c, examples_dag, example, cc_shared_objs + [ link_libxed ])) # compile & link ild_examples if os.path.exists(env['link_libild']): for example in env.src_dir_join(ild_examples): example_exes.append(ex_compile_and_link(env_c, examples_dag, example, [ env['link_libild'] ])) # compile & link small_examples for example in env.src_dir_join(small_examples): example_exes.append(ex_compile_and_link(env_c, examples_dag, example, [ link_libxed ])) for example in env.src_dir_join(enc2_examples): example_exes.append(ex_compile_and_link( env_c, examples_dag, example, env['xed_enc2_libs'] + [link_libxed] )) mbuild.vmsgb(4, "ALL EXAMPLES", "\n\t".join(example_exes)) examples_to_build = example_exes env['example_exes'] = example_exes mbuild.msgb("BUILDING EXAMPLES") okay = work_queue.build(examples_dag, targets=examples_to_build, die_on_errors=env['die_on_errors'], show_progress=True, show_output=True, show_errors_only=_wk_show_errors_only()) if not okay: xbc.cdie( "XED EXAMPLES build failed") mbuild.vmsgb(3, "XED EXAMPLES", "build succeeded") return 0 def verify_args(env): if env['use_elf_dwarf_precompiled']: env['use_elf_dwarf'] = True def examples_work(env): """External entry point for non-command line invocations. Initialize the environment, build libxed, the examples, the kit and run the tests""" xbc.prep(env) verify_args(env) start_time=mbuild.get_time() xbc.init_once(env) init(env) if 'clean' in env['targets'] or env['clean']: xbc.xed_remove_files_glob(env) if len(env['targets'])<=1: xbc.cexit(0) mbuild.cmkdir(env['build_dir']) work_queue = mbuild.work_queue_t(env['jobs']) xbc.get_libxed_names(env) retval = build_examples(env, work_queue) end_time=mbuild.get_time() mbuild.msgb("EXAMPLES BUILD ELAPSED TIME", mbuild.get_elapsed_time(start_time, end_time)) return retval def execute(): """Main external entry point for command line invocations""" import mbuild env = mkenv() # xed_args() is skip-able for remote (import) invocation. The env # from mkenv can be updated programmatically. One must call # xbc.set_xed_defaults(env) if not calling xed_args(env) xed_args(env) # parse command line knobs retval = examples_work(env) return retval