src/Pure/System/executable.scala
author wenzelm
Thu, 10 Apr 2025 20:39:06 +0200
changeset 82480 489f4a79d215
parent 80224 db92e0b6a11a
child 82497 b7554954d697
permissions -rw-r--r--
more robust access to GMP library that is provided here;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
72448
faad63aca1e7 support for platform-specific executables;
wenzelm
parents:
diff changeset
     1
/*  Title:      Pure/System/executable.scala
faad63aca1e7 support for platform-specific executables;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
faad63aca1e7 support for platform-specific executables;
wenzelm
parents:
diff changeset
     3
faad63aca1e7 support for platform-specific executables;
wenzelm
parents:
diff changeset
     4
Support for platform-specific executables.
faad63aca1e7 support for platform-specific executables;
wenzelm
parents:
diff changeset
     5
*/
faad63aca1e7 support for platform-specific executables;
wenzelm
parents:
diff changeset
     6
faad63aca1e7 support for platform-specific executables;
wenzelm
parents:
diff changeset
     7
package isabelle
faad63aca1e7 support for platform-specific executables;
wenzelm
parents:
diff changeset
     8
faad63aca1e7 support for platform-specific executables;
wenzelm
parents:
diff changeset
     9
75393
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 73317
diff changeset
    10
object Executable {
82480
489f4a79d215 more robust access to GMP library that is provided here;
wenzelm
parents: 80224
diff changeset
    11
  def library_path_variable(platform: Isabelle_Platform): String =
489f4a79d215 more robust access to GMP library that is provided here;
wenzelm
parents: 80224
diff changeset
    12
    if (platform.is_linux) "LD_LIBRARY_PATH"
489f4a79d215 more robust access to GMP library that is provided here;
wenzelm
parents: 80224
diff changeset
    13
    else if (platform.is_macos) "DYLD_LIBRARY_PATH"
489f4a79d215 more robust access to GMP library that is provided here;
wenzelm
parents: 80224
diff changeset
    14
    else if (platform.is_windows) "PATH"
489f4a79d215 more robust access to GMP library that is provided here;
wenzelm
parents: 80224
diff changeset
    15
    else error("Bad platform " + platform)
489f4a79d215 more robust access to GMP library that is provided here;
wenzelm
parents: 80224
diff changeset
    16
72460
e79294c4230c more portable;
wenzelm
parents: 72454
diff changeset
    17
  def libraries_closure(path: Path,
82480
489f4a79d215 more robust access to GMP library that is provided here;
wenzelm
parents: 80224
diff changeset
    18
    env_prefix: String = "",
72454
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    19
    mingw: MinGW = MinGW.none,
79499
d117821a5e82 always use patchelf on Linux: base-line is Ubuntu 18.04 where that works properly (see also e79294c4230c);
wenzelm
parents: 78773
diff changeset
    20
    filter: String => Boolean = _ => true
75393
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 73317
diff changeset
    21
  ): List[String] = {
72460
e79294c4230c more portable;
wenzelm
parents: 72454
diff changeset
    22
    val exe_path = path.expand
72454
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    23
    val exe_dir = exe_path.dir
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    24
    val exe = exe_path.base
72448
faad63aca1e7 support for platform-specific executables;
wenzelm
parents:
diff changeset
    25
75393
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 73317
diff changeset
    26
    val ldd_lines = {
72454
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    27
      val ldd = if (Platform.is_macos) "otool -L" else "ldd"
82480
489f4a79d215 more robust access to GMP library that is provided here;
wenzelm
parents: 80224
diff changeset
    28
      val script = mingw.bash_script(env_prefix + ldd + " " + File.bash_path(exe))
80224
db92e0b6a11a clarified signature: prefer symbolic isabelle.Path over physical java.io.File;
wenzelm
parents: 79499
diff changeset
    29
      split_lines(Isabelle_System.bash(script, cwd = exe_dir).check.out)
72448
faad63aca1e7 support for platform-specific executables;
wenzelm
parents:
diff changeset
    30
    }
faad63aca1e7 support for platform-specific executables;
wenzelm
parents:
diff changeset
    31
72454
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    32
    def lib_name(lib: String): String =
72468
60471f4bafd2 proper library names on Windows;
wenzelm
parents: 72460
diff changeset
    33
      Library.take_prefix[Char](c => c != '.' && c != '-',
72454
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    34
        Library.take_suffix[Char](_ != '/', lib.toList)._2)._1.mkString
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    35
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    36
    val libs =
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    37
      if (Platform.is_macos) {
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    38
        val Pattern = """^\s*(/.+)\s+\(.*\)$""".r
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    39
        for {
78592
fdfe9b91d96e misc tuning: support "scalac -source 3.3";
wenzelm
parents: 77217
diff changeset
    40
          case Pattern(lib) <- ldd_lines
72454
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    41
          if !lib.startsWith("@executable_path/") && filter(lib_name(lib))
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    42
        } yield lib
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    43
      }
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    44
      else {
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    45
        val Pattern = """^.*=>\s*(/.+)\s+\(.*\)$""".r
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    46
        val prefix =
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    47
          mingw.root match {
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    48
            case None => ""
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    49
            case Some(path) => path.absolute.implode
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    50
          }
78592
fdfe9b91d96e misc tuning: support "scalac -source 3.3";
wenzelm
parents: 77217
diff changeset
    51
        for { case Pattern(lib) <- ldd_lines if filter(lib_name(lib)) }
72454
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    52
          yield prefix + lib
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    53
      }
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    54
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    55
    if (libs.nonEmpty) {
73317
df49ca5da9d0 clarified modules: more like ML;
wenzelm
parents: 72468
diff changeset
    56
      libs.foreach(lib => Isabelle_System.copy_file(Path.explode(lib), exe_dir))
72454
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    57
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    58
      if (Platform.is_linux) {
79499
d117821a5e82 always use patchelf on Linux: base-line is Ubuntu 18.04 where that works properly (see also e79294c4230c);
wenzelm
parents: 78773
diff changeset
    59
        Isabelle_System.require_command("patchelf")
d117821a5e82 always use patchelf on Linux: base-line is Ubuntu 18.04 where that works properly (see also e79294c4230c);
wenzelm
parents: 78773
diff changeset
    60
        Isabelle_System.bash("patchelf --force-rpath --set-rpath '$ORIGIN' " + File.bash_path(exe_path)).check
72454
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    61
      }
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    62
      else if (Platform.is_macos) {
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    63
        val script =
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    64
          ("install_name_tool" ::
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    65
            libs.map(file => "-change " + Bash.string(file) + " " +
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    66
              Bash.string("@executable_path/" + Path.explode(file).file_name) + " " +
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    67
              File.bash_path(exe))).mkString(" ")
80224
db92e0b6a11a clarified signature: prefer symbolic isabelle.Path over physical java.io.File;
wenzelm
parents: 79499
diff changeset
    68
        Isabelle_System.bash(script, cwd = exe_dir).check
72448
faad63aca1e7 support for platform-specific executables;
wenzelm
parents:
diff changeset
    69
      }
faad63aca1e7 support for platform-specific executables;
wenzelm
parents:
diff changeset
    70
    }
72454
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    71
549391271e74 clarified Executable.libraries_closure;
wenzelm
parents: 72448
diff changeset
    72
    libs
72448
faad63aca1e7 support for platform-specific executables;
wenzelm
parents:
diff changeset
    73
  }
faad63aca1e7 support for platform-specific executables;
wenzelm
parents:
diff changeset
    74
}