Closed bodkan closed 1 year ago
Upon reading a bit more into the topic, I discovered this. It's probably obvious to experts in C++ standards (or, as in this case, their implementations), but I'm reproducing it here full for posterity in case someone else runs into this or similar C++ compilation issues:
It is not specified in the C++ standards how exactly you must invoke your compiler. I guess this is up to implementations to decide, so there might still be a need for -lstdc++fs.
Note that C++17 is not yet officially a standard, and implementations may or may not yet have implemented it. Even when C++17 finally becomes a standard, this won't magically change the implementation. It doesn't even define what linker flags an implementation should or should not require. It is completely unrelated.
How you can include the officially accepted version after C++17 becomes a standard and your implementation begins to support it, is completely implementation-specific. We'll probably just have to wait and see how that works out.
On a similar note, it does seem like starting with GCC version 9.1, the std::filesystem library became a part of the standard library and is included by default, so the -lstdc++fs flag should not be necessary for 9.1 and later versions.
Thank you very much for your report and thorough analysis. This problem was introduced to CRAN yesterday; and I expect that others will also run into it.
I have changed the configure script so that the -lstdc++fs
flag is used. I now also use <experimental/filesystem>
instead of <filesystem>
if I can detect that the latter is not available or when the gcc version is < 8 (I tested with 7.5.0 on Ubuntu 18.04). Further tweaks may be necessary for other compilers (CLANG on OSX). This is not an issue on windows.
The "~/.R/Makevars" file with
PKG_LIBS += -lstdc++fs
is an elegant workaround for installing the CRAN version with compilers that have the <filesystem>
library.
I have an issue with compiling the latest version of terra from CRAN on my Red Hat Linux system while installing it as a dependency of other R packages (in this case rnaturalearth). Although I haven't used terra directly before, I think I must have managed to install it successfully at some point in the past as a dependency via other R packages -- unfortunately, I don't know at which point has the compilation issue described below started and if this is or isn't a regression of some kind.
I think I have a potential fix for this which I attempt to describe below (I don't really write C or C++ code so excuse some weird terminology or naivety in my approach).
Problem description
When I run
install.packages("terra")
, I get the following (I'm cutting the log output to what I think is the most useful information -- the error itself is at the end):System information
Compiler version:
OS version:
R version:
Hypothesis
After a bit of googling based on this error from the
install.packages
call:I wondered if the issue is with
std::filesystem
not being properly discovered or linked -- and it does indeed seem to be the case.Minimal (approximate) example
Consider this minimal C++ program source code
test.cpp
:If I compile it with this (using the
-std=c++17
flag as shown in theinstall.packages("terra")
log above):I get
However, if I compile it with this (note the last flag!)
it compiles without error and I can run the produced
./test
binary.Fix?
Based on this simple compilation test, I created a
~/.R/Makevars
file with the following contents:After this, running
install.packages("terra")
ran without any issues, and the R package was installed successfully (as do the R packages which previously failed to install due to the terra itself failing to compile).Conclusion
It seem that although std::filesystem is part of the C++17 standard, which GCC v8.5.0 distributed by my RHEL version supports, specifying
-std=c++17
is not sufficient. It needs to be linked explicitly via-lstdc++fs
.Is this something that can be added to the build instructions (or however is configuration of these things called with R packages using C/C++ code) of terra itself so that this is done automatically? I have been using R for a long time, and had my share of issues with compilation, but I have never had to use
~/.R/Makevars
in the past. In my experience, 99.9% of compilation issues are solved by installing a missing header library. I don't have any experience with C/C++ compilation in R packages, but I would hope that adding-lstdc++fs
would be -- in the worst case -- redundant while fixing compilation using compiler toolchains which do not link to std::filesystem automatically (despite supporting C++17).(Unfortunately, I work on shared machines in a university setting which maintains corporate-level RHEL installations, so I have no way to influence which versions of GCC or other compiler toolchains are installed on our systems.)
Thanks for your help!