# Compiling with Rtools40, UCRT

**URL:** <https://swi-prolog.discourse.group/t/compiling-with-rtools40-ucrt/4363>\
**Category:** General\
**Created:** [September 1, 2021, 8:22am UTC](https://swi-prolog.discourse.group/t/compiling-with-rtools40-ucrt/4363 "2021-09-01T08:22:21Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![mgondan1](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/mgondan1/32/803_2.png) [@mgondan1](https://swi-prolog.discourse.group/u/mgondan1)\
**Post date:** [September 1, 2021, 8:22am UTC](https://swi-prolog.discourse.group/t/compiling-with-rtools40-ucrt/4363/1 "2021-09-01T08:22:22Z")

</div>

RTools40 is a minimalistic gcc compiler suite for building R and R packages under Windows. I tried to compile current swipl with the “UCRT” flavor of Rtools, whatever it is, but in contrast to “mingw32” and “mingw64”, it has a package libarchive.

One of the complications is that the libraries bundled with Rtools are all static, no dlls. That’s an R thing. R packages are themselves dlls under windows, but these libraries should preferably link to static dependencies. There is probably a reason for this.

- Download and install Rtools, see here [RTools: Toolchains for building R and R packages from source on Windows](https://cran.r-project.org/bin/windows/Rtools/)
- The pacman repository of Rtools does not include git, so I installed git for Windows ([Git - Downloading Package](https://git-scm.com/download/win)) and made it accessible to the path.
- in Rtools (UCRT): `pacman -Syu`
- maybe do it twice: `pacman -Syu`
- `pacman -S mingw-w64-ucrt-x86_64-cmake mingw-w64-ucrt-x86_64-libjpeg mingw-w64-ucrt-x86_64-libyaml mingw-w64-ucrt-x86_64-pcre mingw-w64-ucrt-x86_64-libarchive`
- `git clone https://github.com/SWI-Prolog/swipl-devel`
- `cd swipl-devel`
- `git submodule update --init`
- `mkdir build`
- `cd build`

```prolog
cmake -DMINGW_ROOT=/ucrt64 -DINSTALL_DOCUMENTATION=OFF \
    -DSWIPL_PACKAGES_X=OFF -DWIN32_DLLS="" \
    -DLibArchive_INCLUDE_DIRS="`pkg-config --cflags-only-I libarchive`" \
    -DLibArchive_LIBRARIES="`pkg-config --libs --static libarchive`" \
    -DCMAKE_C_FLAGS=-DPCRE_STATIC \
    -DCMAKE_INSTALL_PREFIX:PATH=/usr/local -G "MSYS Makefiles" ..

```

- Now wait 10 min 🙂
- If you run the command a second time, it returns within a few instances, and you can inspect the missing dependencies: libtcmalloc, libuuid, Berkeley DB, JNI, Java, qt5widgets. libuuid can, in principle, be fixed, but let’s move on.
- `make`

_(Removed the parts that have been fixed, see conversation below)._

Last problem (we’re still at 98%), in crypto4pl.c:

```prolog
C:/Users/matth/swipl-devel/packages/ssl/cryptolib.c:53:1: error: static declaration of 'EVP_MD_CTX_free' follows non-static declaration
   53 | EVP_MD_CTX_free(EVP_MD_CTX *ctx)

```

I am unsure if this is due to clutter on my hard disk (see the recent topic), but I fixed it like this:

- (still in swipl-devel/build): `cd packages/ssl`
- `notepad config.h` and add the following 3 lines in the beginning:

```prolog
#define HAVE_EVP_MD_CTX_FREE 1
#define HAVE_X509_DIGEST 1
#define HAVE_X509_CRL_DIGEST 1

```

- (back in swipl-devel/build): `make`
- `make install`
- Now, fasten your seatbelts.
- `start swipl` (it works without “start”, as well, but you won’t have color)

```prolog
Welcome to SWI-Prolog etc.

```

- ?- `member(X, [1, 2, 3]).`

```prolog
X = 1 ;
X = 2 ;
X = 3.

```

- ?- `check_installation.`

```prolog
% Checking your SWI-Prolog kit for common issues ...
%
% Version: ............. 8.3.28-42-gcfeb5156d-DIRTY
% Address bits: ........ 64
% Architecture: ........ x64-win64
% Installed at: ........ c:/rtools40/usr/local
% Cores: ............... 4
%
% Checking tcmalloc ............................ not present
Warning: See http://www.swi-prolog.org/build/issues/tcmalloc.html
% Checking gmp ................................. ok
% Loading library(archive) ..................... ok
% Supported filters:
% Supported formats: 7zip, ar, cab, cpio, empty, gnutar, iso9660, lha, mtree, rar, raw, tar, xar, zip
% Loading library(cgi) ......................... ok
% Loading library(crypt) ....................... ok
Warning: library(bdb) .......................... NOT FOUND
Warning: See http://www.swi-prolog.org/build/issues/bdb.html
% 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 c:/rtools40/usr/local/library/http/web/js/jquery-1.11.3.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
Warning: library(pce) .......................... NOT FOUND
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(readutil) .................... 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(table) ....................... ok
% Loading library(time) ........................ ok
% Loading library(unicode) ..................... ok
% Loading library(uri) ......................... ok
% Loading library(uuid) ........................ ok
% Loading library(zlib) ........................ ok
% Loading library(yaml) ........................ ok
Warning: Found 4 issues.
true.

```

Nothing unexpected. Except that libarchive claims to support RAW and MTREE, which it doesn’t, so my pull request for packages/archive4pl.c may be wrong or not sufficient.

- Let’s see if we can compile things: ?- `pack_install(environ).`

```prolog
% Contacting server at https://www.swi-prolog.org/pack/query ... ok
Install environ@1.0 from http://www.swi-prolog.org/download/pack/environ-1.0.tgz Y/n?
% Contacting server at https://www.swi-prolog.org/pack/query ... ok
% "environ-1.0.tgz" was downloaded 52 times
Package: environ
Title: Demo package with C code, fetching the program environment
Installed version: 1.0
Author: Jan Wielemaker <jan@swi-prolog.org>
Home page: http://www.swi-prolog.org/howto/ForeignPack.html
Download URL: http://www.swi-prolog.org/download/pack/environ-*.tgz
Install "environ-1.0.tgz" (1,084 bytes) Y/n?
Warning: In file included from c:/rtools40/usr/local/include/SWI-Prolog.h:50,
Warning: from c/environ.c:1:
Warning: c/environ.c: In function 'pl_environ':
Warning: c/environ.c:9:17: warning: ' __p__ environ' redeclared without dllimport attribute: previous dllimport ignored [-Wattributes]
Warning: 9 | { extern char **environ;
Warning: | ^ ~~~~~~
% gcc -I"c:/rtools40/usr/local/include" -c -o c/environ.o c/environ.c
% mkdir -p lib/x64-win64
% gcc -shared -L"c:/rtools40/usr/local/bin" -o lib/x64-win64/environ.dll c/environ.o -lswipl
% make: Nothing to be done for 'check'.
% make: Nothing to be done for 'install'.
true.

```

Good enough for now.

- ?- `use_module(library(environ)).`
- ?- `environ(X).`

(some stuff is shown)

Very nice.

---

<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:** [September 1, 2021, 11:23am UTC](https://swi-prolog.discourse.group/t/compiling-with-rtools40-ucrt/4363/2 "2021-09-01T11:23:49Z")

</div>

> [@mgondan1](#):
>
> `#define FORMAT_ALL (FORMAT_MASK&~(0x04000000|0x01000000))`

Thanks. Added a fix for that.

> [@mgondan1](#):
>
> Then go to line 100, column 440 and append: `-lz -lbz2 -llz4 -lbcrypt -lnettle -liconv -llzma -lexpat`

It probably works by setting `LibArchive_LIBRARIES`. This is the disadvantage of not using DLLs: you need to know the dependencies of the library you link to. Normally CMake’s `find_package(LibArchive)` should deal with that. There are many ways to make this fail though, notably on Windows ☹ . libarchive has a lot of dependencies and the dependencies depend 🙂 on how the library was configured and built ☹

> [@mgondan1](#):
>
> `notepad flags.make` and append -DPCRE\_STATIC to the CFLAGS (last line)

I guess we could check `PCRE_LIBRARIES` to see whether the library is static or dynamic (that is in the end heuristic as there is no platform standard for library filename extensions) and if static add this to the target CFLAGS. This is a bit CMake hacking. I don’t have a good platform to test. Happy to merge a patch 🙂

---

<div class="post-metadata">

**Author:** ![mgondan1](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/mgondan1/32/803_2.png) [@mgondan1](https://swi-prolog.discourse.group/u/mgondan1)\
**Post date:** [September 1, 2021, 4:56pm UTC](https://swi-prolog.discourse.group/t/compiling-with-rtools40-ucrt/4363/3 "2021-09-01T16:56:00Z")

</div>

Regarding the second point: You wrote below that it probably works by setting `LibArchive_LIBRARIES`. Unfortunately, it is overwritten by find\_package(LibArchive), I checked it with message("${LibArchive\_LIBRARIES}") before and after find\_package in swipl-devel/packages/archive/CMakeLists.txt. Would you accept something like this?

Old:

find\_package(LibArchive)

New:

if(DEFINED LibArchive\_INCLUDE\_DIRS OR DEFINED LibArchive\_LIBRARIES)

set(LibArchive\_FOUND:BOOL=ON)

else()

find\_package(LibArchive)

endif()

The LibArchive\_FOUND is used in the later course.

Citing O‘Keefe: This is dirty, but not too dirty.

---

<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:** [September 2, 2021, 7:13am UTC](https://swi-prolog.discourse.group/t/compiling-with-rtools40-ucrt/4363/4 "2021-09-02T07:13:30Z")

</div>

Pushed something along these ways, well, like below. I think be specified and as non-empty strings.

```prolog
if(LibArchive_LIBRARIES AND LibArchive_INCLUDE_DIRS)
  set(LibArchive_FOUND ON)
else()
  find_package(LibArchive)
endif()

```

This is to overcome that the CMake FindLibArchive.cmake is rather simple. It should use `pkg-config` to figure out the library dependencies (and `pkg-config` should be installed properly for libarchive).

---

<div class="post-metadata">

**Author:** ![mgondan1](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/mgondan1/32/803_2.png) [@mgondan1](https://swi-prolog.discourse.group/u/mgondan1)\
**Post date:** [September 2, 2021, 12:37pm UTC](https://swi-prolog.discourse.group/t/compiling-with-rtools40-ucrt/4363/5 "2021-09-02T12:37:07Z")

</div>

Cool, thanks. Works. I will update the description above to specify both LibArchive\_LIBRARIES and LibArchive\_INCLUDE\_DIRS.

For what it’s worth, pkg-config works fine:

$ pkg-config --libs --static libarchive  
-LC:/rtools40/ucrt64/lib -larchive -lnettle -lexpat -llzma -llz4 -lbz2 -lz -lregex -ltre -pipe -lintl /ucrt64/lib/libiconv.a -lbcrypt

---

<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:** [September 2, 2021, 1:08pm UTC](https://swi-prolog.discourse.group/t/compiling-with-rtools40-ucrt/4363/6 "2021-09-02T13:08:02Z")

</div>

> [@mgondan1](#):
>
> For what it’s worth, pkg-config works fine:

Great. Unfortunately FindLibArchive.cmake, which is part of the CMake package doesn’t use `pkg-config` ☹ I had a brief look to first use pkg-config in our CMakeLists.txt. It surely can be done, but it is not that easy ☹

---

<div class="post-metadata">

**Author:** ![mgondan1](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/mgondan1/32/803_2.png) [@mgondan1](https://swi-prolog.discourse.group/u/mgondan1)\
**Post date:** [September 2, 2021, 1:33pm UTC](https://swi-prolog.discourse.group/t/compiling-with-rtools40-ucrt/4363/7 "2021-09-02T13:33:57Z")

</div>

The plural is correct, or isn’t it? LibArchive\_INCLUDE\_DIRS (my guess would have been LibArchive\_INCLUDE\_DIR). It’s working fine, I am just asking (and please disregard my question if you’re busy).

---

<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:** [September 2, 2021, 2:02pm UTC](https://swi-prolog.discourse.group/t/compiling-with-rtools40-ucrt/4363/8 "2021-09-02T14:02:39Z")

</div>

The plural is correct. There may be multiple libraries in multiple directories involved.

---

<div class="post-metadata">

**Author:** ![mgondan1](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/mgondan1/32/803_2.png) [@mgondan1](https://swi-prolog.discourse.group/u/mgondan1)\
**Post date:** [September 2, 2021, 3:26pm UTC](https://swi-prolog.discourse.group/t/compiling-with-rtools40-ucrt/4363/9 "2021-09-02T15:26:55Z")

</div>

I tried to apply a similar patch to libPCRE, but without any success. I don’t know what I am doing wrong. I tried PCRE\_INCLUDE\_DIRS, PCRE\_C\_FLAGS, any combination.

I gave up and just added -DCMAKE\_C\_FLAGS=-DPCRE\_STATIC to the cmake command. This is obviously a hack; on the other hand, this particular global flag does not hurt anything else in the SWIPL tree, so for now, I am fine.

Edit: Ok, now I found a FindPCRE.cmake which does not exist for libArchive, so the workaround for libArchive cannot be generalized that easily.
