@@ -1014,24 +1014,50 @@ def graalvm_vm_arg(java_arg):
10141014 agent_args = ' ' .join (graalvm_vm_arg (arg ) for arg in mx_gate .get_jacoco_agent_args () or [])
10151015
10161016 # We need to make sure the arguments get passed to subprocesses, so we create a temporary launcher
1017- # with the arguments. We also disable compilation, it hardly helps for this use case
1017+ # with the arguments.
10181018 original_launcher = os .path .abspath (os .path .realpath (launcher ))
10191019 if sys .platform != 'win32' :
1020- coverage_launcher = original_launcher + '.sh'
1021- preamble = '#!/bin/sh'
1022- pass_args = '"$@"'
1020+ coverage_launcher = original_launcher + "_cov"
1021+ c_launcher_source = coverage_launcher + ".c"
1022+ exe_arg = f"--python.Executable={ coverage_launcher } "
1023+ agent_args_list = shlex .split (agent_args )
1024+ extra_args_c = []
1025+ for i , arg in enumerate (agent_args_list ):
1026+ extra_args_c .append (f'new_args[{ i + 3 } ] = "' + arg .replace ("\" " , r"\"" ) + '";' )
1027+ extra_args_c = ' ' .join (extra_args_c )
1028+ c_code = dedent (f"""\
1029+ #include <stdio.h>
1030+ #include <stdlib.h>
1031+ #include <unistd.h>
1032+
1033+ int main(int argc, char **argv) {{
1034+ char *new_args[argc + 3 + { len (agent_args_list )} ];
1035+ new_args[0] = "{ original_launcher } ";
1036+ new_args[1] = "--jvm";
1037+ new_args[2] = "{ exe_arg } ";
1038+ { extra_args_c }
1039+ for (int i = 1; i < argc; i++) {{
1040+ new_args[i + 3 + { len (agent_args_list )} ] = argv[i];
1041+ }}
1042+ new_args[argc + 3 + { len (agent_args_list )} ] = NULL;
1043+ execvp("{ original_launcher } ", new_args);
1044+ perror("execvp failed");
1045+ return 1;
1046+ }}
1047+ """ )
1048+ with open (c_launcher_source , "w" ) as f :
1049+ f .write (c_code )
1050+ compile_cmd = ["cc" , c_launcher_source , "-o" , coverage_launcher ]
1051+ subprocess .check_call (compile_cmd )
1052+ os .chmod (coverage_launcher , 0o775 )
10231053 else :
10241054 coverage_launcher = original_launcher .replace ('.exe' , '.cmd' )
10251055 # Windows looks for libraries on PATH, we need to add the jvm bin dir there or it won't find the instrumentation dlls
10261056 jvm_bindir = os .path .join (os .path .dirname (os .path .dirname (original_launcher )), 'jvm' , 'bin' )
1027- preamble = f'@echo off\n set PATH=%PATH%;{ jvm_bindir } '
1028- pass_args = '%*'
1029- with open (coverage_launcher , "w" ) as f :
1030- f .write (f'{ preamble } \n ' )
1031- exe_arg = quote (f"--python.Executable={ coverage_launcher } " )
1032- f .write (f'{ original_launcher } --jvm { exe_arg } { agent_args } { pass_args } \n ' )
1033- if sys .platform != 'win32' :
1034- os .chmod (coverage_launcher , 0o775 )
1057+ with open (coverage_launcher , "w" ) as f :
1058+ f .write (f'@echo off\n set PATH=%PATH%;{ jvm_bindir } \n ' )
1059+ exe_arg = quote (f"--python.Executable={ coverage_launcher } " )
1060+ f .write (f'{ original_launcher } --jvm { exe_arg } { agent_args } %*\n ' )
10351061 mx .log (f"Replaced { launcher } with { coverage_launcher } to collect coverage" )
10361062 launcher = coverage_launcher
10371063 return launcher
0 commit comments