You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
120 lines
4.2 KiB
120 lines
4.2 KiB
4 months ago
|
# DExTer : Debugging Experience Tester
|
||
|
# ~~~~~~ ~ ~~ ~ ~~
|
||
|
#
|
||
|
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||
|
# See https://llvm.org/LICENSE.txt for license information.
|
||
|
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||
|
"""Deals with the processing execution of shell or batch build scripts."""
|
||
|
|
||
|
import os
|
||
|
import subprocess
|
||
|
import unittest
|
||
|
|
||
|
from dex.dextIR import BuilderIR
|
||
|
from dex.utils import Timer
|
||
|
from dex.utils.Exceptions import BuildScriptException
|
||
|
|
||
|
|
||
|
def _quotify(text):
|
||
|
if '"' in text or ' ' not in text:
|
||
|
return text
|
||
|
return '"{}"'.format(text)
|
||
|
|
||
|
|
||
|
def _get_script_environment(source_files, compiler_options,
|
||
|
linker_options, executable_file):
|
||
|
|
||
|
source_files = [_quotify(f) for f in source_files]
|
||
|
object_files = [
|
||
|
_quotify('{}.o'.format(os.path.basename(f))) for f in source_files
|
||
|
]
|
||
|
source_indexes = ['{:02d}'.format(i + 1) for i in range(len(source_files))]
|
||
|
|
||
|
env_variables = {}
|
||
|
env_variables['SOURCE_INDEXES'] = ' '.join(source_indexes)
|
||
|
env_variables['SOURCE_FILES'] = ' '.join(source_files)
|
||
|
env_variables['OBJECT_FILES'] = ' '.join(object_files)
|
||
|
env_variables['LINKER_OPTIONS'] = linker_options
|
||
|
|
||
|
for i, _ in enumerate(source_files):
|
||
|
index = source_indexes[i]
|
||
|
env_variables['SOURCE_FILE_{}'.format(index)] = source_files[i]
|
||
|
env_variables['OBJECT_FILE_{}'.format(index)] = object_files[i]
|
||
|
env_variables['COMPILER_OPTIONS_{}'.format(index)] = compiler_options[i]
|
||
|
|
||
|
env_variables['EXECUTABLE_FILE'] = executable_file
|
||
|
|
||
|
return env_variables
|
||
|
|
||
|
|
||
|
def run_external_build_script(context, script_path, source_files,
|
||
|
compiler_options, linker_options,
|
||
|
executable_file):
|
||
|
"""Build an executable using a builder script.
|
||
|
|
||
|
The executable is saved to `context.working_directory.path`.
|
||
|
|
||
|
Returns:
|
||
|
( stdout (str), stderr (str), builder (BuilderIR) )
|
||
|
"""
|
||
|
|
||
|
builderIR = BuilderIR(
|
||
|
name=context.options.builder,
|
||
|
cflags=compiler_options,
|
||
|
ldflags=linker_options,
|
||
|
)
|
||
|
assert len(source_files) == len(compiler_options), (source_files,
|
||
|
compiler_options)
|
||
|
|
||
|
script_environ = _get_script_environment(source_files, compiler_options,
|
||
|
linker_options, executable_file)
|
||
|
env = dict(os.environ)
|
||
|
env.update(script_environ)
|
||
|
try:
|
||
|
with Timer('running build script'):
|
||
|
process = subprocess.Popen(
|
||
|
[script_path],
|
||
|
cwd=context.working_directory.path,
|
||
|
env=env,
|
||
|
stdout=subprocess.PIPE,
|
||
|
stderr=subprocess.PIPE)
|
||
|
out, err = process.communicate()
|
||
|
returncode = process.returncode
|
||
|
out = out.decode('utf-8')
|
||
|
err = err.decode('utf-8')
|
||
|
if returncode != 0:
|
||
|
raise BuildScriptException(
|
||
|
'{}: failed with returncode {}.\nstdout:\n{}\n\nstderr:\n{}\n'.
|
||
|
format(script_path, returncode, out, err),
|
||
|
script_error=err)
|
||
|
return out, err, builderIR
|
||
|
except OSError as e:
|
||
|
raise BuildScriptException('{}: {}'.format(e.strerror, script_path))
|
||
|
|
||
|
|
||
|
class TestBuilder(unittest.TestCase):
|
||
|
def test_get_script_environment(self):
|
||
|
source_files = ['a.a', 'b.b']
|
||
|
compiler_options = ['-option1 value1', '-option2 value2']
|
||
|
linker_options = '-optionX valueX'
|
||
|
executable_file = 'exe.exe'
|
||
|
env = _get_script_environment(source_files, compiler_options,
|
||
|
linker_options, executable_file)
|
||
|
|
||
|
assert env['SOURCE_FILES'] == 'a.a b.b'
|
||
|
assert env['OBJECT_FILES'] == 'a.a.o b.b.o'
|
||
|
|
||
|
assert env['SOURCE_INDEXES'] == '01 02'
|
||
|
assert env['LINKER_OPTIONS'] == '-optionX valueX'
|
||
|
|
||
|
assert env['SOURCE_FILE_01'] == 'a.a'
|
||
|
assert env['SOURCE_FILE_02'] == 'b.b'
|
||
|
|
||
|
assert env['OBJECT_FILE_01'] == 'a.a.o'
|
||
|
assert env['OBJECT_FILE_02'] == 'b.b.o'
|
||
|
|
||
|
assert env['EXECUTABLE_FILE'] == 'exe.exe'
|
||
|
|
||
|
assert env['COMPILER_OPTIONS_01'] == '-option1 value1'
|
||
|
assert env['COMPILER_OPTIONS_02'] == '-option2 value2'
|