# Static executable (-DSTATIC\_EXTENSIONS)

**URL:** https://swi-prolog.discourse.group/t/static-executable-dstatic-extensions/5710
**Category:** General
**Created:** [August 23, 2022, 3:24am UTC](https://swi-prolog.discourse.group/t/static-executable-dstatic-extensions/5710 "2022-08-23T03:24:17Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)
#### Post date: [August 23, 2022, 3:24am UTC](https://swi-prolog.discourse.group/t/static-executable-dstatic-extensions/5710/1 "2022-08-23T03:24:17Z")

</div>

> [@Wiki Discussion: SWI-Prolog in the browser using WASM](https://swi-prolog.discourse.group/t/wiki-discussion-swi-prolog-in-the-browser-using-wasm/5651/91):
>
> This is now a new option `-DSTATIC_EXTENSIONS` to `cmake` which is enabled by default for Emscripten. This allows building fully static [SWI-Prolog](https://www.swi-prolog.org/pldoc/doc_for?object=manual) executables with extensions, which surely has value on its own

Tried to build a static executable (x86\_64) with -DSTATIC\_EXTENSIONS (and a static libswipl.a) but got the following error:

```prolog
[...]
/usr/sbin/ld: src/libswipl.a(pl-load.c.o):(.data+0x1a8): undefined reference to `install_tex'
/usr/sbin/ld: src/libswipl.a(pl-load.c.o):(.data+0x2b8): undefined reference to `install_bdb4pl'
collect2: error: ld returned 1 exit status
[5/280] Building CXX object packages/swipl-win/CMakeFiles/swipl-win.dir/Completion.cpp.o
ninja: build stopped: subcommand failed.

```

---

<div class="post-metadata">

### Author: ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)
#### Post date: [August 23, 2022, 9:33am UTC](https://swi-prolog.discourse.group/t/static-executable-dstatic-extensions/5710/2 "2022-08-23T09:33:46Z")

</div>

Some packages are not yet ready for this. There are two demands: the install function of a library **must** be called `install_<libname>` and the Prolog side **must** use use\_foreign\_library/1 as

```
:- use_foreign_library(foreign(libname)).

```

Some packages (still) name the install function simply `install()`, but this obviously cannot work as you get a name conflict.

There may be other problems ☹ Only working on the Emscripten version with this option. PRs welcome 🙂

---

<div class="post-metadata">

### Author: ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)
#### Post date: [August 23, 2022, 4:17pm UTC](https://swi-prolog.discourse.group/t/static-executable-dstatic-extensions/5710/3 "2022-08-23T16:17:28Z")

</div>

After fixing some `install_<name>` naming problems and replacing 'autoload(…)`with`use\_foreign\_library(foreign(libname))` I am getting some errors:

```prolog
[..]
ERROR: /home/u/tmp/swipl-devel/build.static/home/xpce/prolog/boot/pce_principal.pl:71:
ERROR: '$activate_static_extension'/1: foreign_extension `shlib' does not exist

```

any idea where to look? thanks!

---

<div class="post-metadata">

### Author: ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)
#### Post date: [August 23, 2022, 5:03pm UTC](https://swi-prolog.discourse.group/t/static-executable-dstatic-extensions/5710/4 "2022-08-23T17:03:15Z")

</div>

After commenting out `autoload(library(shlib),[load_foreign_library/1])` I am left with these errors:

```prolog
5/167] Generating lib/shlib.tex
FAILED: man/lib/shlib.tex man/lib/summaries.d/shlib.tex /tmp/swipl-devel/build.static/man/lib/shlib.tex /tmp/swipl-devel/build.static/man/lib/summaries.d/shlib.tex 
cd /tmp/swipl-devel/build.static/man && /tmp/swipl-devel/build.static/src/swipl -f none --no-packs -x /tmp/swipl-devel/build.static/man/pldoc2tex -- --source=/tmp/swipl-devel/man --out=lib/shlib.tex --subsection --summaries "library(shlib)"
ERROR: /tmp/swipl-devel/man/pldoc2tex.pl:48: pltotex:main source_sink `library(shlib)' does not exist
[14/167] Generating lib/readutil.tex
FAILED: man/lib/readutil.tex man/lib/summaries.d/readutil.tex /tmp/swipl-devel/build.static/man/lib/readutil.tex /tmp/swipl-devel/build.static/man/lib/summaries.d/readutil.tex 
cd /tmp/swipl-devel/build.static/man && /tmp/swipl-devel/build.static/src/swipl -f none --no-packs -x /tmp/swipl-devel/build.static/man/pldoc2tex -- --source=/tmp/swipl-devel/man --out=lib/readutil.tex --summaries "library(readutil)"
Warning: /tmp/swipl-devel/build.static/home/library/readutil.pl:89:
Warning: /tmp/swipl-devel/build.static/home/library/prolog_xref.pl:86: 
Warning: library(shlib): No such file
ERROR: /tmp/swipl-devel/build.static/home/library/readutil.pl:89:
ERROR: prolog_xref:process_foreign/2: Unknown procedure: prolog_xref:current_foreign_library/2
Warning: Halting with status 1 due to 1 errors and 1 warnings
ninja: build stopped: subcommand failed.

```

obviously `library(shlib)` won’t be used for static binary, so we need some kind of conditional compile time flag that we can use like this:

```nohighlight
:- if (...dynamic_binary...).
:- use_foreign_library(foreign(shlib)).
:- endif

```

we can use this flag for `prolog_xref` when it calls `current\_foreign\_library/2? or better, current\_foreign\_library/2 should work with static extensions linked in the executable?

---

<div class="post-metadata">

### Author: ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)
#### Post date: [August 23, 2022, 5:20pm UTC](https://swi-prolog.discourse.group/t/static-executable-dstatic-extensions/5710/5 "2022-08-23T17:20:53Z")

</div>

Good question. Some of this can probably be resolved by avoiding the use of old stuff from library(shlib). I’m also in doubt whether using this should imply complete static linking on all platforms ort it should still allow for dynamic linking and only statically link the _extensions_? That would give two flags, one to decide whether or not to include the extensions statically and one to decide whether or not to support dynamic linking (if the platform allows for it).

I’ll push a few commits to ltx2htm and bdb packages to fix some of this.

---

<div class="post-metadata">

### Author: ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)
#### Post date: [August 23, 2022, 5:29pm UTC](https://swi-prolog.discourse.group/t/static-executable-dstatic-extensions/5710/6 "2022-08-23T17:29:46Z")

</div>

> [@jan](#):
>
> I’m also in doubt whether using this should imply complete static linking on all platforms ort it should still allow for dynamic linking and only statically link the _extensions_?

I think the most useful use case is complete static linking (even allowing the user to statically link in some packs that use foreign modules) **for unix like systems**. This, by the way, may make it easier to embed a static swi-prolog in an android apk, making it much more easy to move forward with android apps.

Windows has no need of static linking since it is very good at binary compatibility already, so no need for static linking on windows.

---

<div class="post-metadata">

### Author: ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)
#### Post date: [August 23, 2022, 6:25pm UTC](https://swi-prolog.discourse.group/t/static-executable-dstatic-extensions/5710/7 "2022-08-23T18:25:59Z")

</div>

Good points. For now I’ve pushed some changes that make the system compile out of the box on MacOS (I’m traveling) using -DSTATIC\_EXTENSIONS. JPL is disabled (needs dynamic linkng). All tests pass and fthe result is a single executable that only depends on the system shared libs 🙂

---

<div class="post-metadata">

### Author: ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)
#### Post date: [August 23, 2022, 6:58pm UTC](https://swi-prolog.discourse.group/t/static-executable-dstatic-extensions/5710/8 "2022-08-23T18:58:01Z")

</div>

> [@jan](#):
>
> For now I’ve pushed some changes that make the system compile out of the box on MacOS (I’m traveling) using -DSTATIC\_EXTENSIONS.

Thanks! It compiles on X86 too, xpce is not working, but the rest seems ok.

Of course, It is not a statically linked binary yet, but great progress. Here is what I get:

```prolog
$ ldd src/swipl
	linux-vdso.so.1 => linux-vdso.so.1 (0x00007f9eeef63000)
	libtcmalloc_minimal.so.4 => /usr/lib/libtcmalloc_minimal.so.4 (0x00007f9eee626000)
	libncursesw.so.6 => /usr/lib/libncursesw.so.6 (0x00007f9eeee9f000)
	libformw.so.6 => /usr/lib/libformw.so.6 (0x00007f9eeee8b000)
	libgmp.so.10 => /usr/lib/libgmp.so.10 (0x00007f9eee583000)
	libz.so.1 => /usr/lib/libz.so.1 (0x00007f9eeee71000)
	libm.so.6 => /usr/lib/libm.so.6 (0x00007f9eee49b000)
	libcrypt.so.2 => /usr/lib/libcrypt.so.2 (0x00007f9eeee3d000)
	libossp-uuid.so.16 => /usr/lib/libossp-uuid.so.16 (0x00007f9eeee2c000)
	libnsl.so.3 => /usr/lib/libnsl.so.3 (0x00007f9eeee23000)
	libarchive.so.13 => /usr/lib/libarchive.so.13 (0x00007f9eee3d4000)
	libodbc.so.2 => /usr/lib/libodbc.so.2 (0x00007f9eee362000)
	libdb-5.3.so => /usr/lib/libdb-5.3.so (0x00007f9eee1a3000)
	libpcre2-8.so.0 => /usr/lib/libpcre2-8.so.0 (0x00007f9eee106000)
	libyaml-0.so.2 => /usr/lib/libyaml-0.so.2 (0x00007f9eee0e4000)
	libssl.so.1.1 => /usr/lib/libssl.so.1.1 (0x00007f9eee04f000)
	libcrypto.so.1.1 => /usr/lib/libcrypto.so.1.1 (0x00007f9eedc00000)
	libXinerama.so.1 => /usr/lib/libXinerama.so.1 (0x00007f9eeee1c000)
	libXpm.so.4 => /usr/lib/libXpm.so.4 (0x00007f9eeee06000)
	libXext.so.6 => /usr/lib/libXext.so.6 (0x00007f9eee03a000)
	libXt.so.6 => /usr/lib/libXt.so.6 (0x00007f9eedfcf000)
	libX11.so.6 => /usr/lib/libX11.so.6 (0x00007f9eedabd000)
	libSM.so.6 => /usr/lib/libSM.so.6 (0x00007f9eedfc4000)
	libICE.so.6 => /usr/lib/libICE.so.6 (0x00007f9eedfa7000)
	libXft.so.2 => /usr/lib/libXft.so.2 (0x00007f9eedf8f000)
	libfreetype.so.6 => /usr/lib/libfreetype.so.6 (0x00007f9eed9ee000)
	libfontconfig.so.1 => /usr/lib/libfontconfig.so.1 (0x00007f9eedf3f000)
	libjpeg.so.8 => /usr/lib/libjpeg.so.8 (0x00007f9eed96b000)
	libedit.so.0 => /usr/lib/libedit.so.0 (0x00007f9eedf04000)
	libreadline.so.8 => /usr/lib/libreadline.so.8 (0x00007f9eed915000)
	libc.so.6 => /usr/lib/libc.so.6 (0x00007f9eed72e000)
	libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f9eed400000)
	libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f9eedee2000)
	/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f9eeef65000)
	libtirpc.so.3 => /usr/lib/libtirpc.so.3 (0x00007f9eed701000)
	libacl.so.1 => /usr/lib/libacl.so.1 (0x00007f9eed6f7000)
	libexpat.so.1 => /usr/lib/libexpat.so.1 (0x00007f9eed6c6000)
	liblzma.so.5 => /usr/lib/liblzma.so.5 (0x00007f9eed69c000)
	libzstd.so.1 => /usr/lib/libzstd.so.1 (0x00007f9eed357000)
	liblz4.so.1 => /usr/lib/liblz4.so.1 (0x00007f9eed679000)
	libbz2.so.1.0 => /usr/lib/libbz2.so.1.0 (0x00007f9eed666000)
	libltdl.so.7 => /usr/lib/libltdl.so.7 (0x00007f9eed65b000)
	libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007f9eed654000)
	libxcb.so.1 => /usr/lib/libxcb.so.1 (0x00007f9eed32c000)
	libuuid.so.1 => /usr/lib/libuuid.so.1 (0x00007f9eed64b000)
	libXrender.so.1 => /usr/lib/libXrender.so.1 (0x00007f9eed63e000)
	libpng16.so.16 => /usr/lib/libpng16.so.16 (0x00007f9eed2f5000)
	libharfbuzz.so.0 => /usr/lib/libharfbuzz.so.0 (0x00007f9eed1f9000)
	libbrotlidec.so.1 => /usr/lib/libbrotlidec.so.1 (0x00007f9eed1eb000)
	libgssapi_krb5.so.2 => /usr/lib/libgssapi_krb5.so.2 (0x00007f9eed196000)
	libXau.so.6 => /usr/lib/libXau.so.6 (0x00007f9eed637000)
	libXdmcp.so.6 => /usr/lib/libXdmcp.so.6 (0x00007f9eed18e000)
	libgraphite2.so.3 => /usr/lib/libgraphite2.so.3 (0x00007f9eed16a000)
	libglib-2.0.so.0 => /usr/lib/libglib-2.0.so.0 (0x00007f9eed02d000)
	libbrotlicommon.so.1 => /usr/lib/libbrotlicommon.so.1 (0x00007f9eed00a000)
	libkrb5.so.3 => /usr/lib/libkrb5.so.3 (0x00007f9eecf31000)
	libk5crypto.so.3 => /usr/lib/libk5crypto.so.3 (0x00007f9eecf01000)
	libcom_err.so.2 => /usr/lib/libcom_err.so.2 (0x00007f9eecefb000)
	libkrb5support.so.0 => /usr/lib/libkrb5support.so.0 (0x00007f9eeceea000)
	libkeyutils.so.1 => /usr/lib/libkeyutils.so.1 (0x00007f9eecee3000)
	libresolv.so.2 => /usr/lib/libresolv.so.2 (0x00007f9eeced1000)
	libpcre.so.1 => /usr/lib/libpcre.so.1 (0x00007f9eece5a000)

```

and here is the output of check\_installation:

```prolog

1 ?- check_installation 
| .
% Checking your SWI-Prolog kit for common issues ...
% 
% Version: ............. 8.5.15-96-gc5e130043-DIRTY
% Address bits: ........ 64
% Architecture: ........ x86_64-linux
% Installed at: ........ /tmp/swipl-devel/build.static/home
% Cores: ............... 16
% 
% Checking tcmalloc ............................ ok
% Checking gmp ................................. ok
% Loading library(archive) ..................... ok
% Supported filters: bzip2, compress, gzip, grzip, lrzip, lzip, lzma, lzop, none, rpm, uu, xz
% Supported formats: 7zip, ar, cab, cpio, empty, gnutar, iso9660, lha, mtree, rar, raw, tar, xar, zip
% Loading library(cgi) ......................... ok
% Loading library(crypt) ....................... ok
% Loading library(bdb) ......................... ok
% Loading library(double_metaphone) ............ ok
% Loading library(filesex) ..................... ok
% Loading library(http/http_stream) ............ ok
% Loading library(http/json) ................... ok
% Loading library(http/jquery) ................. ok
% jQuery from /tmp/swipl-devel/build.static/home/library/http/web/js/jquery-3.6.0.min.js
% Loading library(isub) ........................ ok
Warning: library(jpl) .......................... NOT FOUND
Warning: See http://www.swi-prolog.org/build/issues/jpl.html
% Loading library(memfile) ..................... ok
% Loading library(odbc) ........................ ok
% Loading library(pce) ......................... FAILEDUnknown procedure: send/2
Warning: Unknown procedure: get/3
Warning: However, there are definitions for:
Warning: det/1
Warning: get/1
Warning: get0/1
Warning: get/2
Warning: get0/2
Warning: 
Warning: Unknown procedure: pce_error/1
Warning: Unknown procedure: pce_info/1
Warning: Unknown procedure: pce_warn/1
Warning: Unknown procedure: pce_error/1
Warning: Unknown procedure: pce_error/1
Warning: Unknown procedure: get/3
Warning: However, there are definitions for:
Warning: det/1
Warning: get/1
Warning: get0/1
Warning: get/2
Warning: get0/2
Warning: 
Warning: 
Warning: See http://www.swi-prolog.org/build/issues/xpce.html
% Loading library(pcre) ........................ ok
% Loading library(pdt_console) ................. ok
% Loading library(porter_stem) ................. ok
% Loading library(process) ..................... ok
% Loading library(protobufs) ................... ok
% Loading library(editline) .................... ok
% Loading library(readline) .................... ok
% Loading library(readutil) .................... ok
% Loading library(rlimit) ...................... ok
% Loading library(semweb/rdf_db) ............... ok
% Loading library(semweb/rdf_ntriples) ......... ok
% Loading library(semweb/turtle) ............... ok
% Loading library(sgml) ........................ ok
% Loading library(sha) ......................... ok
% Loading library(snowball) .................... ok
% Loading library(socket) ...................... ok
% Loading library(ssl) ......................... ok
% Loading library(crypto) ...................... ok
% Loading library(syslog) ...................... ok
% Loading library(table) ....................... ok
% Loading library(time) ........................ ok
Warning: library(tipc/tipc) .................... NOT FOUND
Warning: See http://www.swi-prolog.org/build/issues/tipc/tipc.html
% Loading library(unicode) ..................... ok
% Loading library(uri) ......................... ok
% Loading library(uuid) ........................ ok
% Loading library(zlib) ........................ ok
% Loading library(yaml) ........................ ok

[...]

```

---

<div class="post-metadata">

### Author: ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)
#### Post date: [August 24, 2022, 5:23am UTC](https://swi-prolog.discourse.group/t/static-executable-dstatic-extensions/5710/9 "2022-08-24T05:23:35Z")

</div>

> [@swi](#):
>
> Thanks! It compiles on X86 too, xpce is not working, but the rest seems ok.
> 
> Of course, It is not a statically linked binary yet, but great progress. Here is what I get:

xpce works for me. Whether or not to link the executable dynamically or statically against the system libraries is another decision. Fully static linking should not be hard. Not sure how useful this is, but it is good to know that dynamic linking is no longer really needed and for WASM this seems the preferred route.

Attaching user packs is another matter. For the whole thing to work the extension needs to use the cmake infrastructure that is used for the bundled extensions. That requires following much more strict conventions.

---

<div class="post-metadata">

### Author: ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)
#### Post date: [August 24, 2022, 10:35am UTC](https://swi-prolog.discourse.group/t/static-executable-dstatic-extensions/5710/10 "2022-08-24T10:35:48Z")

</div>

> [@jan](#):
>
> xpce works for me.

I did a `ninja clean && ninja`, now xpce works fine.  
The only strange thing I noticed is that libpcre is linked twice, both the new libpcre2 and the old libpcre are linked. Wonder why?

```prolog
$ ldd src/swipl | grep pcre
	libpcre2-8.so.0 => /usr/lib/libpcre2-8.so.0 (0x00007f4d4c89c000)
	libpcre.so.1 => /usr/lib/libpcre.so.1 (0x00007f4d4b5d3000)

```

> [@jan](#):
>
> Fully static linking should not be hard. Not sure how useful this is, but it is good to know that dynamic linking is no longer really needed and for WASM this seems the preferred route.

There are two use cases where I see static linking as useful:

1. **Android**. Full static linking would be specially useful to run swi-prolog in Android. You could compile swi-prolog in some ARM compatible board and then include the static binary in your java Android app to run it on a phone. They could communicate via sockets, with the Java android app providing the gui (maybe just a webview and swiprolog acting as a web server) and the prolog code doing all the rest.   
  
The static linking would shield swi-prolog from most of the non-standard changes they have made in Android, because the binary would be simply making direct system calls to the linux kernel without dependency on anything else. As long as they have not blocked/changed kernel system calls the binary should work. I have done this with a statically linked Ada executable and it works well.

2. **Stable deployment of prolog executables**. A fully statically linked binary would be very useful for deploying single binary prolog applications, without worrying about breaking things because we installed a new version of SWI prolog. I have single file prolog saved states that I run and some times I have to recompile them because of a WAM/VM change in libswipl.so or some such change. This would not be needed at all if I just used the static binary, and I could install the cutting-edge version of SWI-Prolog while all my saved states and prolog applications would continue to work without trouble.

> [@jan](#):
>
> Attaching user packs is another matter. For the whole thing to work the extension needs to use the cmake infrastructure that is used for the bundled extensions. That requires following much more strict conventions.

What is needed to convert a user made pack into an extension? Probably use cmake, but what else would be needed?

---

<div class="post-metadata">

### Author: ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)
#### Post date: [August 24, 2022, 12:58pm UTC](https://swi-prolog.discourse.group/t/static-executable-dstatic-extensions/5710/12 "2022-08-24T12:58:12Z")

</div>

> [@swi](#):
>
> `libpcre.so.1`

No clue. Not on my Mac … Also the CMakeCache.txt only shows 2-8,

> [@swi](#):
>
> What is needed to convert a user made pack into an extension? Probably use cmake, but what else would be needed?

Not much. The dependencies and api to the Prolog system are the same. If you dump the Prolog and C/C++ files in a subdir of packages and add a cmake config it should work. Actually, you could simply maintain the layout of the pack and add a CMakeLists.txt at the top. The only issue is that pack\_install/1 also triggers on a cmake config, but in a quite different way. That could be changed using some naming convention, I guess.

---

<div class="post-metadata">

### Author: ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)
#### Post date: [August 24, 2022, 4:43pm UTC](https://swi-prolog.discourse.group/t/static-executable-dstatic-extensions/5710/14 "2022-08-24T16:43:39Z")

</div>

> [@jan](#):
>
> > [@swi](#):
> >
> > `libpcre.so.1`
> 
> No clue. Not on my Mac … Also the CMakeCache.txt only shows 2-8,

think I found out where it comes from, I have this in CMakeCache.txt:

```prolog
PKG_FONTCONFIG_STATIC_LIBRARIES:INTERNAL=fontconfig;freetype;bz2;z;png16;m;m;z;harfbuzz;m;graphite2;glib-2.0;m;pcre;sysprof-capture-4;brotlidec;brotlicommon;expat;m

```

So it must come from fontconfig.

> [@jan](#):
>
> Not much. The dependencies and api to the Prolog system are the same. If you dump the Prolog and C/C++ files in a subdir of packages and add a cmake config it should work.

good to know, thanks.
