1 # DExTer : Debugging Experience Tester
4 # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 # See https://llvm.org/LICENSE.txt for license information.
6 # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 """Deals with the processing execution of shell or batch build scripts."""
13 from dex
.dextIR
import BuilderIR
14 from dex
.utils
import Timer
15 from dex
.utils
.Exceptions
import BuildScriptException
19 if '"' in text
or " " not in text
:
21 return '"{}"'.format(text
)
24 def _get_script_environment(
25 source_files
, compiler_options
, linker_options
, executable_file
28 source_files
= [_quotify(f
) for f
in source_files
]
29 object_files
= [_quotify("{}.o".format(os
.path
.basename(f
))) for f
in source_files
]
30 source_indexes
= ["{:02d}".format(i
+ 1) for i
in range(len(source_files
))]
33 env_variables
["SOURCE_INDEXES"] = " ".join(source_indexes
)
34 env_variables
["SOURCE_FILES"] = " ".join(source_files
)
35 env_variables
["OBJECT_FILES"] = " ".join(object_files
)
36 env_variables
["LINKER_OPTIONS"] = linker_options
38 for i
, _
in enumerate(source_files
):
39 index
= source_indexes
[i
]
40 env_variables
["SOURCE_FILE_{}".format(index
)] = source_files
[i
]
41 env_variables
["OBJECT_FILE_{}".format(index
)] = object_files
[i
]
42 env_variables
["COMPILER_OPTIONS_{}".format(index
)] = compiler_options
[i
]
44 env_variables
["EXECUTABLE_FILE"] = executable_file
49 def run_external_build_script(
57 """Build an executable using a builder script.
59 The executable is saved to `context.working_directory.path`.
62 ( stdout (str), stderr (str), builder (BuilderIR) )
65 builderIR
= BuilderIR(
66 name
=context
.options
.builder
,
67 cflags
=compiler_options
,
68 ldflags
=linker_options
,
70 assert len(source_files
) == len(compiler_options
), (source_files
, compiler_options
)
72 script_environ
= _get_script_environment(
73 source_files
, compiler_options
, linker_options
, executable_file
75 env
= dict(os
.environ
)
76 env
.update(script_environ
)
78 with
Timer("running build script"):
79 process
= subprocess
.Popen(
81 cwd
=context
.working_directory
.path
,
83 stdout
=subprocess
.PIPE
,
84 stderr
=subprocess
.PIPE
,
86 out
, err
= process
.communicate()
87 returncode
= process
.returncode
88 out
= out
.decode("utf-8")
89 err
= err
.decode("utf-8")
91 raise BuildScriptException(
92 "{}: failed with returncode {}.\nstdout:\n{}\n\nstderr:\n{}\n".format(
93 script_path
, returncode
, out
, err
97 return out
, err
, builderIR
99 raise BuildScriptException("{}: {}".format(e
.strerror
, script_path
))
102 class TestBuilder(unittest
.TestCase
):
103 def test_get_script_environment(self
):
104 source_files
= ["a.a", "b.b"]
105 compiler_options
= ["-option1 value1", "-option2 value2"]
106 linker_options
= "-optionX valueX"
107 executable_file
= "exe.exe"
108 env
= _get_script_environment(
109 source_files
, compiler_options
, linker_options
, executable_file
112 assert env
["SOURCE_FILES"] == "a.a b.b"
113 assert env
["OBJECT_FILES"] == "a.a.o b.b.o"
115 assert env
["SOURCE_INDEXES"] == "01 02"
116 assert env
["LINKER_OPTIONS"] == "-optionX valueX"
118 assert env
["SOURCE_FILE_01"] == "a.a"
119 assert env
["SOURCE_FILE_02"] == "b.b"
121 assert env
["OBJECT_FILE_01"] == "a.a.o"
122 assert env
["OBJECT_FILE_02"] == "b.b.o"
124 assert env
["EXECUTABLE_FILE"] == "exe.exe"
126 assert env
["COMPILER_OPTIONS_01"] == "-option1 value1"
127 assert env
["COMPILER_OPTIONS_02"] == "-option2 value2"