@@ -617,6 +617,15 @@ protected void launch(Builder contextBuilder) {
617617 }
618618 }
619619
620+ if (isLLVMToolchainLauncher ()) {
621+ if (!hasContextOptionSetViaCommandLine ("UseSystemToolchain" )) {
622+ contextBuilder .option ("python.UseSystemToolchain" , "false" );
623+ }
624+ if (!hasContextOptionSetViaCommandLine ("NativeModules" )) {
625+ contextBuilder .option ("python.NativeModules" , "" );
626+ }
627+ }
628+
620629 if (relaunchArgs != null ) {
621630 Iterator <String > it = origArgs .iterator ();
622631 while (it .hasNext ()) {
@@ -886,6 +895,9 @@ protected String getLanguageId() {
886895
887896 @ Override
888897 protected void printHelp (OptionCategory maxCategory ) {
898+ if (isLLVMToolchainLauncher ()) {
899+ System .out .println ("GraalPy launcher to use LLVM toolchain and Sulong execution of native extensions.\n " );
900+ }
889901 System .out .println ("usage: python [option] ... (-c cmd | file) [arg] ...\n " +
890902 "Options and arguments (and corresponding environment variables):\n " +
891903 "-B : this disables writing .py[co] files on import\n " +
@@ -958,6 +970,11 @@ protected void printHelp(OptionCategory maxCategory) {
958970 " This is required when starting subprocesses of python.\n " : "" ));
959971 }
960972
973+ private boolean isLLVMToolchainLauncher () {
974+ String exeName = getResolvedExecutableName ();
975+ return exeName != null && exeName .endsWith ("-lt" );
976+ }
977+
961978 @ Override
962979 protected String [] getDefaultLanguages () {
963980 return new String []{getLanguageId (), "llvm" , "regex" };
@@ -1186,6 +1203,39 @@ private void subExec(List<String> args, List<String> subProcessDefs) {
11861203 }
11871204 }
11881205
1206+ protected String getResolvedExecutableName () {
1207+ // Note that with thin launchers, both graalpy and graalpy-managed are actual executables
1208+ // that load and start GraalPy from a shared library
1209+ if (ImageInfo .inImageRuntimeCode ()) {
1210+ // This is the fastest, most straightforward way to get the name of the actual
1211+ // executable, i.e., with symlinks resolved all the way down to either graalpy or
1212+ // graalpy-managed.
1213+ String executableName = ProcessProperties .getExecutableName ();
1214+ if (executableName != null ) {
1215+ return executableName ;
1216+ }
1217+ }
1218+ // The program name can be a symlink, or a command resolved via $PATH
1219+ // We use getLauncherExecName, which should resolve $PATH commands for us
1220+ String launcherExecName = getLauncherExecName ();
1221+ if (launcherExecName == null ) {
1222+ return null ;
1223+ }
1224+ Path programPath = Paths .get (launcherExecName );
1225+ Path realPath ;
1226+ try {
1227+ // toRealPath resolves symlinks along the way
1228+ realPath = programPath .toRealPath ();
1229+ } catch (IOException ex ) {
1230+ throw abort (String .format ("Cannot determine the executable name from path: '%s'" , programPath ), 72 );
1231+ }
1232+ Path f = realPath .getFileName ();
1233+ if (f == null ) {
1234+ throw abort (String .format ("Cannot determine the executable name from path: '%s'" , realPath ), 73 );
1235+ }
1236+ return f .toString ();
1237+ }
1238+
11891239 private List <String > getCmdline (List <String > args , List <String > subProcessDefs ) {
11901240 List <String > cmd = new ArrayList <>();
11911241 if (isAOT ()) {
0 commit comments