How can get g++ to use my own glibc build's headers correctly? - linux

There's a TL;DR at the end if the context is too much!
Context
I am trying to update the version of glibc a project uses to 2.23 (I know it's old, that's another issue). In order to do this, I need to swap out the libraries and use the associated interpreter.
I encountered some issues when swapping out the interpreter that looked like an ABI change, so I figured it was probably because the header files had changed somehow and started working on getting those included into the project.
At first I tried using -I to include the headers, but got an error (see below). Later I tried setting --sysroot, but this quickly felt like the wrong way of doing things since I was essentially reinventing what g++ already did with system headers. I later found another mechanism that looked more promising (see Problem section).
Could this be an XY issue? Absolutely, but either way, the problem I'm seeing seems odd to me.
Problem
I looked into whether there was a different mechanism to include headers for system libraries, such as glibc, in gcc and g++. I found the flag -isystem:
-isystem dir
Search dir for header files, after all directories specified by -I but before the standard system directories. Mark it as a system directory, so that it gets the same special treatment as is applied to the standard system directories. If dir begins with "=", then the "="
will be replaced by the sysroot prefix; see --sysroot and -isysroot.
I figured that this was probably wanted and set about intergrating this flag into the build system for the project. The resulting g++ command looks like this (simplified and broken onto multiple lines):
> /path/to/gcc-6.3.0/bin/g++
-c
-Wl,--dynamic-linker=/path/to/glibc-2.23/build/install/lib/ld-linux-x86-64.so.2
-Wl,--rpath=/path/to/glibc-2.23/build/install/lib
-isystem /path/to/glibc-2.23/build/install/include
-I.
-I/project-foo/include
-I/project-bar/include
-o example.o
example.cpp
This leads to the following error, followed by many similar ones:
In file included from /usr/include/math.h:71:0,
from /path/to/gcc-6.3.0/include/c++/6.3.0/cmath:45,
from example.cpp:42:
/path/to/glibc-2.23/build/install/include/bits/mathcalls.h:63:16: error: expected constructor, destructor, or type conversion before '(' token
__MATHCALL_VEC (cos,, (_Mdouble_ __x));
Looking into this, it appears that this particular math.h is incompatible with this version of glibc. The fact it tries to use it surprises me, because the math.h file exists in the glibc directory I specified; why didn't it use that? Here's how I verified that file exists:
> ls /path/to/glibc-2.23/build/install/include/math.h
/path/to/glibc-2.23/build/install/include/math.h
Research
I searched around on the internet for people with a similar issue and came across the following relevant things:
https://github.com/riscv/riscv-gnu-toolchain/issues/105
https://askubuntu.com/questions/806220/building-ucb-logo-6-errors-in-mathcalls-h
-isystem on a system include directory causes errors
The last of these is the most promising; it talks about why -isystem won't work here stating that the special #include_next traverses the include path in a different way. Here, the solution appears to be "don't use -isystem where you can help it", but since I've tried using -I only get get the same problem again, I'm not sure how I'd apply that here.
Original issue
When compiling with the new glibc, I get the following error (our build process ends up running some of the programs it compiles to generate further source to be compiled, hence this runtime error whilst compiling):
Inconsistency detected by ld.so: get-dynamic-info.h: 143: elf_get_dynamic_info: Assertion `info[DT_RPATH] == NULL' failed!
I found a couple of relevant things about this:
https://www.linuxquestions.org/questions/linux-software-2/how-to-get-local-gcc-to-link-with-local-glibc-404087/
https://www.linuxquestions.org/questions/programming-9/inconsistency-detected-by-ld-so-dynamic-link-h-62-elf_get_dynamic_info-assertion-621701/
The only solution I see there is completely recompiling gcc to use the new glibc. I'd like to avoid that if possible, which is what lead me down the include route.
Eliminating the complex build system
To try and eliminate the complex build system on the "real" project, I reproduced the problem using the following test.cpp file:
#include <cmath>
int main() {
}
Compiled using:
> /path/to/gcc-6.3.0/bin/g++ test.cpp -Wl,--dynamic-linker=/path/to/glibc-2.23/build/install/lib/ld-linux-x86-64.so.2 -Wl,--rpath=/path/to/glibc-2.23/build/install/lib
Running yields the same original issue:
> ./a.out
Inconsistency detected by ld.so: get-dynamic-info.h: 143: elf_get_dynamic_info: Assertion `info[DT_RPATH] == NULL' failed!
Trying to use the newer headers yields the same include issue:
> /path/to/gcc-6.3.0/bin/g++ test.cpp -Wl,--dynamic-linker=/path/to/glibc-2.23/build/install/lib/ld-linux-x86-64.so.2 -Wl,--rpath=/path/to/glibc-2.23/build/install/lib -isystem /path/to/glibc-2.23/build/install/include
In file included from /usr/include/math.h:71:0,
from /path/to/gcc-6.3.0/include/c++/6.3.0/cmath:45,
from test.cpp:1:
/path/to/glibc-2.23/build/install/include/bits/mathcalls.h:63:16: error: expected constructor, destructor, or type conversion before '(' token
__MATHCALL_VEC (cos,, (_Mdouble_ __x));
TL;DR
How can I get g++ to include the headers from my glibc build correctly, without it accidentally including incompatible files from /usr/include?

In your GCC version,<cmath> uses #include_next, which means that you need to make sure that the directory which contains the cmath file comes before (on the include search path) the directory with the proper math.h for the version of glibc you are building against.
You can use g++ -v to view the search path. In your case, it probably looks like this:
#include "..." search starts here:
#include <...> search starts here:
.
/project-foo/include
/project-bar/include
/path/to/glibc-2.23/build/install/include
/usr/include/c++/6
/usr/include/x86_64-linux-gnu/c++/6
/usr/lib/gcc/x86_64-linux-gnu/6/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/6/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include
If you configure glibc with --prefix=/usr and install it with DESTDIR=/path/to/glibc-2.23/build/install, its header files will be installed into the directory /path/to/glibc-2.23/build/install/usr/include. This means you should be able to use the -isysroot option, which rewrites the default /usr/include directory, resulting in the right ordering of the search path:
#include "..." search starts here:
#include <...> search starts here:
.
/project-foo/include
/project-bar/include
/usr/include/c++/6
/usr/include/x86_64-linux-gnu/c++/6
/usr/include/c++/6/backward
/usr/lib/gcc/x86_64-linux-gnu/6/include
/usr/lib/gcc/x86_64-linux-gnu/6/include-fixed
/path/to/glibc-2.23/build/install/usr/include

Related

Linux randomly deleted my file while compiling what do I do?

gcc -L/root/Desktop - Wall -o prog3.c -pthread -lcopy
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.0: In function '_start': (.text+0x20): undefined reference to 'main'
collect2: error: ld returned 1 exit status
This is my error code. prog3.c is nowhere to be found, what on earth happened is there any way to get my file back?? The bold is the command I ran and the rest is the resultant console output
Your problem is here: -o prog3.c. gcc’s -o option is used to tell gcc which name it should give to the executable it generates. So here, you’re basically asking your compiler to replace your prog3.c source file by an executable. Sadly your code is gone...
Little addendum of your options in such scenario:
It was Git (or any other version control) repository. In such case, you can simply bring it from previous commit
Your editor/IDE has some back-up system. Sometimes I need to bring back a file I've thought was needless. For such case, my favourite text editor should have create already back-up file in appropriate location (e.g. $XDG_DATA_HOME/vim/backup in my case).
If none of above, but you still have previously correctly compiled binary file
You can try to decompile, but this process - even if successful - isn't lossless (e.g. code is basically spaghetti).
Had you compiled with -g flag, you could possibly retrieve the code from debug info.
You can at least de-assemble to Assembly code.

Compiling FSL: 'fatal error: libxml++/libxml++.h: No such file or directory'

I understand that this has come up a lot, but I've looked through all the other answers and none of them are relevant to me.
I am trying to compile the neuroimaging software FSL from source (I have to, it's not supported on my Linux Distro). I've followed all the instructions listed here, and it's about 80% compiled. There are a few modules that have not been successful, however, and they all seem to trace back to a problem trying to compile CiftiLib-master.
Per the instructions, whenever I try to run the 'make' command, it returns:
Makefile:34: warning: overriding recipe for target 'clean'
/home/thosvarley/Desktop/fslbuild/fsl/config/common/rules.mk:32: warning: ignoring old recipe for target 'clean'
gcc -c -Wall -ansi -pedantic -Wno-long-long -m64 -g -O3 -fexpensive-optimizations -m64 -I/home/thosvarley/Desktop/fslbuild/fsl/extras/include/boost -g -DCIFTILIB_USE_XMLPP -I/home/thosvarley/Desktop/fslbuild/fsl/extras/include -I/home/thosvarley/Desktop/fslbuild/fsl/extras/include/libxml2 -I/home/thosvarley/Desktop/fslbuild/fsl/extras/include/libxml++-2.6 -I/home/thosvarley/Desktop/fslbuild/fsl/extras/lib/libxml++-2.6/include -I/home/thosvarley/Desktop/fslbuild/fsl/extras/include/boost -I./Common -I./Nifti -I./Cifti -I. -I/include -I/home/thosvarley/Desktop/fslbuild/fsl/include -o Common/XmlAdapter.o Common/XmlAdapter.cxx
In file included from Common/XmlAdapter.cxx:28:0:
Common/XmlAdapter.h:56:10: fatal error: libxml++/libxml++.h: No such file or directory
#include "libxml++/libxml++.h"
^~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make: *** [Makefile:19: Common/XmlAdapter.o] Error 1
As I am not trying to compile one foo.c file, but rather, make a program a lot of the advice I've seen doesn't seem like it would apply to me. I've already installed all of the various libxml packages that get suggested in other posts (libxml2, libxslt1, etc).
I cannot make heads or tails of the error message: I'm not familiar with compiling C programs at all (this is my first serious foray into building from source). Apologies in advance if the answer is obvious and I just don't recognize it.
I'm on Antergos Linux (Arch kernel), which I think may be where the problem is coming from as all the other people who have asked after this seem to be on Debian or Ubuntu.
I have been attempting to solve the same problem. It seems that libxml++ is bundled with FSL by default, and the bundled version fails to compile.
Solution #1: Install and use an older compiler (e.g. GCC 4.8), since the project's configurations are made to fit those old compilers
I cannot vouch for this solution, as I haven't tried it myself (because apparently, I like to make life difficult for myself), but it's probably your best bet.
Solution #2: Fix the problems manually
NOTE: This is not a comprehensive solution, but it might point you in the correct direction.
Your first problem is most likely that the compiler you're using by default uses a more recent C++ standard than the project is written to be compiled with. This causes the implicit conversion of input streams and output streams to booleans to fail. You might be able to solve it by messing around with compiler flags in the makefile configurations, but it's probably easier to just fix the problematic parts of the code. The relevant lines (FSL 5.0.11) are:
- extras/src/libxml++-2.34.0/libxml++/io/istreamparserinputbuffer.cc (line 42)
return _input;
SHOULD BE
return static_cast<bool>(_input);
- extras/src/libxml++-2.34.0/libxml++/io/ostreamoutputbuffer.cc (line 32)
return _output;
SHOULD BE
return static_cast<bool>(_output);
- extras/src/libxml++-2.34.0/libxml++/io/ostreamoutputbuffer.cc (line 39)
return _output;
SHOULD BE
return static_cast<bool>(_output);
Depending on the version you're trying to install, the actual line numbers may be different, but they're probably in the same general area.
The next problem is that the include paths are not defined for INC_XML++, INC_XML++CONF and INC_XML2 in the generic makefile configuration. This is most likely the one your system defaults to, as there are no configurations for GCC versions > 4.8. Edit the config/generic/externallibs.mk file by adding the following lines (where exactly you add it is not important):
# XML++
LIB_XML++ = ${FSLEXTLIB}
INC_XML++ = ${FSLEXTINC}/libxml++-2.6
INC_XML++CONF = ${FSLEXTLIB}/libxml++-2.6/include
INC_XML2 = ${FSLEXTINC}/libxml2
(I addeed the LIB_XML++ for good measure, because the lib path was defined by other variables in the file, but I'm not 100% sure it's necessary.)
Again, this is what fixed it on my system. Depending on the version of the source code you downloaded, it might be different for you, but at least this is a starting point.
After fixing these errors, the CiftiLib-master target should compile. HOWEVER, if your system is anything like mine, this is far from the only error in the build process. Looking at the build.log file and searching for error: should give you a pretty good idea of which projects result in which errors, and what might be needed to fix them. The problems are likely to be similar in nature to the CiftiLib ones.
Final tip: If your libgd project fails to compile, look at the error: message. It probably complains about some undeclared identifiers (IMG_FMT_I420, PLANE_Y, PLANE_U, PLANE_V). If you prefix these identifiers with VPX_, it should work. The reason this fails is because of an update to the library that removes the definitions of the deprecated identifiers, forcing users to use the newer prefixed ones.
This is as far as I've come. I'm assuming you're not still troubled with this a year later, but I'm leaving this here for posterity.

Make interprets compiler options as shell command

I'm trying to compile fbsplash under Tiny Core Linux using autotools. In the middle of compilation it crashed saying "LD: attempted static link to dynamic object /usr/local/lib/libpng16.so"
I've got rid of that, commenting out option "-all-static" in the Makefile. Now it crashes after
/bin/bash: O2: not found
/bin/bash: w: not found
/bin/bash: DTARGET_KERNEL: not found
All of these options have dashes before them. It looks like:
fbcondecor_helper_CFLAGS = -O2 -w \...
fbcondecor_helper_CPPFLAGS = $(AM_CPPFLAGS) -DTARGET_KERNEL
But somehow my shell interprets them as commands without dashes.
What's wrong?
First, you are not using the autotools. You are using a configure script that was generated using the autotools. (If indeed you are running autoconf, or autoreconf, that is a different issue and there is (much) more room for error on your part.) In either case, you should never hand edit the generated Makefile. (So short answer to "What's wrong?" is, "you edited the Makefile".) Instead, add --disable-static when you run configure.

Get rid of "gcc - /usr/bin/ld: warning lib not found"

I have the following warning during link:
/usr/bin/ld: warning: libxxx.so.6, needed by /a/b/c/libyyy.so, not found (try using -rpath or -rpath-link)
Setting environment variable LD_LIBRARY_PATH=path_to_libxxx.so.6 silence the warning (adding -Lpath_to_libxxx.so.6 doesn't help).
I have a separate compilation server, where the resulting binary is only compile.
The binary is executed on other server and there the libxxx.so.6 is seen by the binary (checked with ldd executable).
Is there're other way to get rid of the warning at compilation time (I have it several times and it's very annoying)?
You need to add the dynamic library equivalent of -L:
-Wl,-rpath-link,/path/to/lib
This will cause the linker to look for shared libraries in non-standard places, but only for the purpose of verifying the link is correct.
If you want the program to find the library at that location at run-time, then there's a similar option to do that:
-Wl,-rpath,/path/to/lib
But, if your program runs fine without this then you don't need it.
Make sure the paths to the needed libraries are known to the runtime linker. This is done by adding a file in /etc/ld.so.conf.d/ with the needed path. For example, /etc/ld.so.conf.d/foo with the following contents:
/usr/local/lib/foo/
If you have a very old Linux version, /etc/ld.so.conf.d/ might not be supported, in which case you might have to add the paths directly into the /etc/ld.so.conf file.
After you've done that, you need to update the linker's database by executing the "ldconfig" command.
I know this is old, but here's a better fix:
The root cause:
The problem actually happens when LD invoked by GCC starts resolving
library dependencies. Both GCC and LD are aware of the sysroot
containing libraries, however LD may be missing one critical
component: the /etc/ld.so.conf file. Here’s an exampleld.so.conf file
from a Raspberry PI system:
include /etc/ld.so.conf.d/*.conf
The /etc/ld.so.conf.d directory contains the following files:
00-vmcs.conf:
/opt/vc/lib
arm-linux-gnueabihf.conf:
/lib/arm-linux-gnueabihf /usr/lib/arm-linux-gnueabihf
libc.conf:
/usr/local/lib
The universal solution
 
The problem can be easily solved by copying the LD configuration files
to a location where the cross-toolchain’s LD can find them. There’s
one pitfall however: if your cross-toolchain was built with MinGW
(most are), it probably did not have access to the glob() function so
it won’t be able to parse a wildcard-enabled include statement
like *.conf. The workaround here is to just manually combine the
contents of all .conf files from /etc/ld.so.conf.d and paste them
into /etc/ld.so.conf
*/opt/vc/lib
/lib/arm-linux-gnueabihf
/usr/lib/arm-linux-gnueabihf
/usr/local/lib*
Once you create the ld.so.conf file in the correct folder, your
toolchain will be able to resolve all shared library references
automatically and you won’t see that error message again!
The only way to silence these warning using command line options would be the -L flag which curiously does not work for you (maybe you can post more details on this). Since the warning is generated by ld we could try to use -Wl,option to disable a linker warning but from the documentation of GNU ld however there is no option for (de)activating this warnings.
So this leaves us with writing a wrapper script filtering out this warning or compile a custom version of ld.

g++ default header include list

While performing a compilation with cross g++ in a Linux machine ( lubuntu 11.10 ) in verbose mode, I can see the list of the default include header directories:
#include <...> search starts here:
/opt/eldk-4.2/usr/bin/../lib/gcc/powerpc-linux/4.2.2/include
/opt/eldk-4.2/ppc_4xx/usr/include/c++/4.2.2/opt/eldk-4.2/ppc_4xx/usr/include/c++/4.2.2/powerpc-linux
/opt/eldk-4.2/ppc_4xx/usr/include/c++/4.2.2/backward
/opt/eldk-4.2/usr/../ppc_4xx/usr/include
Executing the very same g++ binary in another Linux machine (lubuntu 12.10), I get another different list, with less elements:
#include <...> search starts here:
/opt/eldk-4.2/usr/bin/../lib/gcc/powerpc-linux/4.2.2/include
and in which some of the elments seem bad constructed, like the following:
ignoring nonexistent directory "/opt/ppc_4xx/usr/lib/gcc/powerpc-linux/includ../include/c++/4.2.2"
The result is that some code compiling on the first system is not compiling on the second because some headers are not found.
Why is this happening?. Where does this list come from?. Who is responsible for constructing it?. Is it possible to easily change it?.
Any help is appreciated.
You can add directories to the default search path by setting environment variables:
C_INCLUDE_PATH (for C header files)
CPLUS_INCLUDE_PATH (for C++ header files).
Alternatively, you can create and edit specfile and place it where G++ looks for them. You can check the path with strace gcc.
Additional documentation on specfiles on GCC page.
I have the exact some problem using ELDK 4.2. This is very likely connected to something that changed in ubuntu 12.04 as I have had the compiler run fine on the same computer before the upgrade.
My problem is that is seems to have forgotten /usr
ignoring nonexistent directory "/opt/eldk-4.2/../ppc_82xx/usr/include"
It should be
/opt/eldk-4.2/usr/../ppc_82xx/usr/include
Which works perfectly on ubuntu 11.10.
I have tried both installing ELDK from the ISO and copying the installation from a working version in ubuntu 11.10

Resources