【问题标题】:Using JPL with SWI-Prolog on macOS在 macOS 上使用 JPL 和 SWI-Prolog
【发布时间】:2026-01-23 18:45:01
【问题描述】:

我正在尝试在 macOS High Sierra 上将 JPL 与 SWI-Prolog 一起使用,但遇到了麻烦。事实上,一开始没有找到libjpl.dylib,所以我将它的路径添加到java.library.path via

java -Djava.library.path=/Applications/SWI-Prolog.app/Contents/swipl/lib/x86_64-darwin15.6.0/

现在找到了库,但我收到另一个错误:

java.lang.UnsatisfiedLinkError: /Applications/SWI-Prolog.app/Contents/swipl/lib/x86_64-darwin15.6.0/libjpl.dylib: dlopen(/Applications/SWI-Prolog.app/Contents/swipl/lib/x86_64-darwin15.6.0/libjpl.dylib, 1): Library not loaded: @executable_path/../swipl/lib/x86_64-darwin15.6.0/libswipl.dylib
  Referenced from: /Applications/SWI-Prolog.app/Contents/swipl/lib/x86_64-darwin15.6.0/libjpl.dylib
  Reason: image not found
    at java.lang.ClassLoader$NativeLibrary.load(Native Method)
    at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1857)
    at java.lang.Runtime.loadLibrary0(Runtime.java:870)
    at java.lang.System.loadLibrary(System.java:1122)
    ...

据我了解,这是由于此版本的 SWI-Prolog 可重定位(因此具有相对于可执行文件的路径)造成的。

libjpl.dylibotool -L 的输出给我这个输出:

/Applications/SWI-Prolog.app/Contents/swipl/lib/x86_64-darwin15.6.0/libjpl.dylib:
    @rpath/libjsig.dylib (compatibility version 1.0.0, current version 1.0.0)
    @rpath/libjvm.dylib (compatibility version 1.0.0, current version 1.0.0)
    @executable_path/../swipl/lib/x86_64-darwin15.6.0/libswipl.dylib (compatibility version 0.0.0, current version 7.6.4)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)

因此修复它的一种方法是通过 macport 或 homebrew 安装不可重定位的版本。

问题是,MacPorts 和 Homebrew 版本的 SWI-Prolog 都不包含 libjpl.dylib 库:/

我在这里遗漏了什么吗?我可以做些什么来完成这项工作?

【问题讨论】:

    标签: java prolog swi-prolog dylib jpl


    【解决方案1】:

    这对可能有用的人来说,因为它不是 100% 匹配所问问题的内容,而是 100% 匹配所问问题的标题。

    使用 Homebrew 安装(至少是最新版本的)SWI-Prolog 时,尝试 use_module(library(jpl)) 将导致错误:

    ERROR: /usr/local/Cellar/swi-prolog/8.4.0/libexec/lib/swipl/library/jpl.pl:5428: Initialization goal raised exception:
    ERROR: source_sink `jar('jpl.jar')' does not exist
    ERROR: In:
    ERROR:   [48] throw(error(existence_error(source_sink,...),_109418))
    ERROR:   [44] jpl:add_jpl_to_classpath at /usr/local/Cellar/swi-prolog/8.4.0/libexec/lib/swipl/library/jpl.pl:3979
    ERROR:   [43] jpl:setup_jvm at /usr/local/Cellar/swi-prolog/8.4.0/libexec/lib/swipl/library/jpl.pl:4168
    ERROR:   [42] '$run_init_goal'(jpl:setup_jvm) at /usr/local/Cellar/swi-prolog/8.4.0/libexec/lib/swipl/boot/init.pl:796
    ERROR:   [41] catch(system:'$run_init_goal'(...),error(existence_error(source_sink,...),context(_109584,_109586)),system:'$initialization_error'(...,...,...)) at /usr/local/Cellar/swi-prolog/8.4.0/libexec/lib/swipl/boot/init.pl:546
    ERROR:   [40] catch_with_backtrace(system:'$run_init_goal'(...),error(existence_error(source_sink,...),context(_109660,_109662)),system:'$initialization_error'(...,...,...)) at /usr/local/Cellar/swi-prolog/8.4.0/libexec/lib/swipl/boot/init.pl:614
    ERROR: 
    ERROR: Note: some frames are missing due to last-call optimization.
    ERROR: Re-run your program in debug mode (:- debug.) to get more detail.
    ERROR: Exported procedure jpl:jpl_c_lib_version/1 is not defined
    true.
    

    另外,执行目标jpl_config_dylib 会导致错误:

    ?- jpl_config_dylib.
    ERROR: Unknown procedure: jpl_config_dylib/0 (DWIM could not correct goal)
    

    MacPorts 版本的 SWI-Prolog 没有这个问题。解决方法是将MacPorts版本下的相关文件复制到SWI Prolog Homebrew版本下:

    $ cp /Applications/SWI-Prolog.app/Contents/swipl/lib/jpl.jar /usr/local/Cellar/swi-prolog/8.4.0/libexec/lib/swipl/lib/
    $ cp /Applications/SWI-Prolog.app/Contents/swipl/lib/x86_64-darwin/libjpl.dylib /usr/local/Cellar/swi-prolog/8.4.0/libexec/lib/swipl/lib/x86_64-darwin/
    $ cp /Applications/SWI-Prolog.app/Contents/swipl/library/jpl.pl /usr/local/Cellar/swi-prolog/8.4.0/libexec/lib/swipl/library/
    $ cp /Applications/SWI-Prolog.app/Contents/swipl/library/jpl_config.pl /usr/local/Cellar/swi-prolog/8.4.0/libexec/lib/swipl/library/
    

    之后加载library(jpl) 就可以正常工作了:

    ?- use_module(library(jpl)).
    true.
    
    ?- jpl_new('java.lang.Object', [], JRef).
    JRef = <jref>(0x7fbefb086318).
    

    【讨论】:

      【解决方案2】:

      在 macOS 10.13.6 (High Sierra) 上,我经常使用以下方法编译 SWI-Prolog 7.x 源代码:

      $ make distclean && ./build && swipl -g "jpl_config_dylib" -t halt
      

      jpl_config_dylib/0 查找并修复 Java 路径。启动SWI-Prolog.app 应用程序后,您还应该能够从顶层调用它。

      【讨论】:

      • 知道为什么自制软件的 swipl 8.4.0 发行版完全没有 jpl 吗?
      • 没有。但我的理解是 MacPorts 替代方案不存在这个问题吗?