Index: libcxx/test/libcxx/strings/basic.string/PR42676.sh.cpp =================================================================== --- libcxx/test/libcxx/strings/basic.string/PR42676.sh.cpp +++ libcxx/test/libcxx/strings/basic.string/PR42676.sh.cpp @@ -9,7 +9,7 @@ // Regression test for PR42676. // RUN: %cxx %flags %s -o %t.exe %compile_flags %link_flags -D_LIBCPP_HIDE_FROM_ABI_PER_TU -// RUN: %t.exe +// RUN: %run #include #include Index: libcxx/test/lit.site.cfg.in =================================================================== --- libcxx/test/lit.site.cfg.in +++ libcxx/test/lit.site.cfg.in @@ -36,6 +36,9 @@ config.pstl_src_root = "@ParallelSTL_SOURCE_DIR@" if @LIBCXX_ENABLE_PARALLEL_ALGORITHMS@ else None config.pstl_obj_root = "@ParallelSTL_BINARY_DIR@" if @LIBCXX_ENABLE_PARALLEL_ALGORITHMS@ else None +# Code signing +config.llvm_codesign_identity = "@LLVM_CODESIGNING_IDENTITY@" + # Let the main config do the real work. config.loaded_site_config = True lit_config.load_config(config, "@LIBCXX_SOURCE_DIR@/test/lit.cfg") Index: libcxx/utils/libcxx/compiler.py =================================================================== --- libcxx/utils/libcxx/compiler.py +++ libcxx/utils/libcxx/compiler.py @@ -17,12 +17,13 @@ CM_Compile = 2 CM_Link = 3 - def __init__(self, path, flags=None, compile_flags=None, link_flags=None, + def __init__(self, config, path, flags=None, compile_flags=None, link_flags=None, warning_flags=None, verify_supported=None, verify_flags=None, use_verify=False, modules_flags=None, use_modules=False, use_ccache=False, use_warnings=False, compile_env=None, cxx_type=None, cxx_version=None): + self.libcxx_config = config self.source_lang = 'c++' self.path = path self.flags = list(flags or []) @@ -163,17 +164,34 @@ cwd=cwd) return cmd, out, err, rc - def link(self, source_files, out=None, flags=[], cwd=None): - cmd = self.linkCmd(source_files, out, flags) + def link(self, source_files, exec_path=None, flags=[], cwd=None): + cmd = self.linkCmd(source_files, exec_path, flags) out, err, rc = libcxx.util.executeCommand(cmd, env=self.compile_env, cwd=cwd) + cs_cmd, cs_out, cs_err, cs_rc = self.codesign(exec_path, cwd) + if cs_rc != 0: + return cs_cmd, cs_out, cs_err, cs_rc return cmd, out, err, rc - def compileLink(self, source_files, out=None, flags=[], + def compileLink(self, source_files, exec_path=None, flags=[], cwd=None): - cmd = self.compileLinkCmd(source_files, out, flags) + cmd = self.compileLinkCmd(source_files, exec_path, flags) out, err, rc = libcxx.util.executeCommand(cmd, env=self.compile_env, cwd=cwd) + cs_cmd, cs_out, cs_err, cs_rc = self.codesign(exec_path, cwd) + if cs_rc != 0: + return cs_cmd, cs_out, cs_err, cs_rc + return cmd, out, err, rc + + def codesign(self, exec_path, cwd=None): + null_op = [], '', '', 0 + if not exec_path: + return null_op + codesign_ident = self.libcxx_config.get_lit_conf('llvm_codesign_identity', '') + if not codesign_ident: + return null_op + cmd = ['xcrun', 'codesign', '-s', codesign_ident, exec_path] + out, err, rc = libcxx.util.executeCommand(cmd, cwd=cwd) return cmd, out, err, rc def compileLinkTwoSteps(self, source_file, out=None, object_file=None, @@ -193,7 +211,7 @@ return cc_cmd, cc_stdout, cc_stderr, rc link_cmd, link_stdout, link_stderr, rc = self.link( - object_file, out=out, flags=flags, cwd=cwd) + object_file, exec_path=out, flags=flags, cwd=cwd) return (cc_cmd + ['&&'] + link_cmd, cc_stdout + link_stdout, cc_stderr + link_stderr, rc) Index: libcxx/utils/libcxx/test/config.py =================================================================== --- libcxx/utils/libcxx/test/config.py +++ libcxx/utils/libcxx/test/config.py @@ -228,7 +228,7 @@ if not cxx: self.lit_config.fatal('must specify user parameter cxx_under_test ' '(e.g., --param=cxx_under_test=clang++)') - self.cxx = CXXCompiler(cxx) if not self.cxx_is_clang_cl else \ + self.cxx = CXXCompiler(self, cxx) if not self.cxx_is_clang_cl else \ self._configure_clang_cl(cxx) cxx_type = self.cxx.type if cxx_type is not None: @@ -258,7 +258,7 @@ link_flags = _prefixed_env_list('LIB', '-L') for path in _split_env_var('LIB'): self.add_path(self.exec_env, path) - return CXXCompiler(clang_path, flags=flags, + return CXXCompiler(self, clang_path, flags=flags, compile_flags=compile_flags, link_flags=link_flags) @@ -1029,8 +1029,14 @@ self.cxx.useModules() def configure_substitutions(self): + tool_env = '' + if platform.system() == 'Darwin': + # Do not pass DYLD_LIBRARY_PATH to the compiler, linker, etc. as + # these tools are not meant to exercise the just-built libraries. + tool_env += 'DYLD_LIBRARY_PATH="" ' + sub = self.config.substitutions - cxx_path = pipes.quote(self.cxx.path) + cxx_path = tool_env + pipes.quote(self.cxx.path) # Configure compiler substitutions sub.append(('%cxx', cxx_path)) sub.append(('%libcxx_src_root', self.libcxx_src_root)) @@ -1065,7 +1071,11 @@ sub.append(('%build', build_str)) # Configure exec prefix substitutions. # Configure run env substitution. - sub.append(('%run', '%t.exe')) + codesign_ident = self.get_lit_conf('llvm_codesign_identity', '') + run_py = os.path.join(self.libcxx_src_root, 'utils', 'run.py') + run_str = '%s %s "%s" %%t.exe' % (pipes.quote(sys.executable), \ + pipes.quote(run_py), codesign_ident) + sub.append(('%run', run_str)) # Configure not program substitutions not_py = os.path.join(self.libcxx_src_root, 'utils', 'not.py') not_str = '%s %s ' % (pipes.quote(sys.executable), pipes.quote(not_py)) Index: libcxx/utils/run.py =================================================================== --- /dev/null +++ libcxx/utils/run.py @@ -0,0 +1,43 @@ +#===----------------------------------------------------------------------===## +# +# 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 +# +#===----------------------------------------------------------------------===## + +"""run.py is a utility for running a program. + +It can perform code signing, forward arguments to the program, and return the +program's error code. +""" + +import subprocess +import sys + + +def main(): + argv = list(sys.argv) + + codesign_ident = argv[1] + + # Delete 'run.py'. + del argv[0] + + # Delete the codesigning identity. + del argv[0] + + exec_path = argv[0] + + # Do any necessary codesigning. + if codesign_ident: + sign_cmd = ['xcrun', 'codesign', '-f', '-s', codesign_ident, exec_path] + cs_rc = subprocess.call(sign_cmd, env={}) + if cs_rc != 0: + sys.stderr.write('Failed to codesign: ' + exec_path) + return cs_rc + + return subprocess.call(argv) + +if __name__ == '__main__': + exit(main())