gcc compiles ELF file with wrong search list - c

After compiling gcc and using it to compile a simple c program:
echo 'int main(){}' > dummy.c
cc dummy.c -v -Wl,--verbose &> dummy.log
grep -B4 '^ /usr/include' dummy.log
the result is:
ignoring nonexistent directory "/tools/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../x86_64-pc-linux-gnu/include"
ignoring duplicate directory "/tools/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/include
but according to Linux From Scratch guide 9.1 in section 6.25 "Verify that the compiler is searching for the correct header files:" the following is expected (ignoring the *linux-gnu paths...):
#include <...> search starts here:
/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/include
/usr/local/include
/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/include-fixed
/usr/include
What's even worse is that
grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
is:
SEARCH_DIR("/usr/lib");
but should be:
SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib64")
SEARCH_DIR("/usr/local/lib64")
SEARCH_DIR("/lib64")
SEARCH_DIR("/usr/lib64")
SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib")
SEARCH_DIR("/usr/local/lib")
SEARCH_DIR("/lib")
SEARCH_DIR("/usr/lib");
I've tried to add all paths to /etc/ld.so.conf and recompiled gcc pass 2, but nothing changed.
So what exactly determines the SEARCH_DIR entries in an ELF file?
EDIT1: I backtracked and found out that the previous step make -k clean did not finish because it's missing autogen, which is not covered at all in the LFS guide 9.1 it seems.

I restarted LFS 9.1 and followed the instruction with more care, now the output is as expected!
There are two things I did differently:
In my first attempt I ignored the advice on chapter 5 to remove extracted tarballs after each section:
For each package:
Using the tar program, extract the package to be built. In Chapter 5, ensure you are the lfs user when extracting the package.
Change to the directory created when the package was extracted.
Follow the book's instructions for building the package.
Change back to the sources directory.
Delete the extracted source directory unless instructed otherwise.
When I reinstalled the host OS I didn't create it with lfs as first user. Instead I created it with lfshost user and created the user lfs as described in section 4.3

Related

Windres not compiling .rc file no matter what I do

So I am making a desktop application using C and the Win32 API. I am also using CMake/Make in conjunction with MinGW. Everything went smoothly until I wanted to add an .rc file to the executable. From my understanding you write an .rc file which is then compiled to a .res file, then presumably you are supposed to embed it in the executable. Here's the problem however, when I attempt to compile the .rc file with the GNU utility windres it fails to compile. I always get the following error messages:
C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin\windres.exe: can't open file `page:': Invalid argument
C:\Code\C\test\resources.rc:4: fatal error: when writing output to : No such file or directory
4 | IDI_TEST_ICON ICON "test.ico"
|
compilation terminated.
C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin\windres.exe: preprocessing failed.
This occurs with every .rc file I've tried, for completeness however, here is the current test file I am trying to compile:
#include <windows.h>
#include "resource.h"
IDI_TEST_ICON ICON "test.ico"
And the resource.h file:
#define IDI_TEST_ICON 101
So the final question is the following: Why doesn't windres compile the .rc file successfully? And what can I do about in the context of using MinGW?
Edit 1:
Worth noting is that I also converted the .rc file to ANSI format since windres is notorious for yielding peculiar errors when formatted in UTF-8. Yet, the same errors occur.
windres actually generates an object file (in COFF format)
So you should run the command like this:
windres resource.rc -o resource.o
When I check the format of the generated file like this:
file resource.o
I get the following result:
resource.o: Intel amd64 COFF object file, no line number info, not stripped, 1 section, symbol offset=0x3c4c, 1 symbols
So you just need to include the generated .o file in the link step to include the resource.
For example when you run the following command you will get an .exe that won't run, but it will show the icon in Explorer:
gcc -shared -o resource.exe resource.o
After a lot of digging in old forum threads I managed to find a "solution" that works. However I still find it peculiar that this solves the problem. I followed Brecht Sanders advise and downloaded a standalone build from winlibs.com. Even this didn't solve the problem which led me to investigate possible RC_COMPILER_FLAGS which ultimately led me to the --use-temp-file flag.
This flag acts as an alternate approach to compile .rc files since it excludes the use of popen (or the equivalent of it in Windows). According to the documentation this flag should be used if the implemenation of popen is buggy on the host. What is interesting here is that the documentation states that this is known to happen on certain non-english versions of Windows. In my case I am using the Swedish language version of Windows which might explain why this is occuring.
Thus the final solution turns out to be:
windres -i resource.rc -o resource.o --use-temp-file
Which ultimately yields an object file which can then be included in the add_executable call in CMake.

Running a 32-bit C code on a 64-bit system with Windows and a C compiler

I am trying to run a c code on my Windows laptop using the 64-bit MinGW compiler. There are a few lines in the beginning of the code that direct to other files such as:
#include <openssl/e_os2.h>
When compiling the code the following error shows up:
C:\MinGW\bin\openssl\apps>gcc s_server.c
s_server.c:21:27: fatal error: openssl/e_os2.h: No such file or directory
#include <openssl/e_os2.h>
^
compilation terminated.
I made sure the files were in the correct locations, however the error still occurs. I am thinking the error occurs because I am running a 32-bit binary on a 64-bit system. Are there any ways to work around this issue given that I don't have a Linux system?
C:\MinGW\bin\openssl\apps>gcc s_server.c
s_server.c:21:27: fatal error: openssl/e_os2.h: No such file or directory
#include <openssl/e_os2.h>
^
compilation terminated.
I believe you need a -I argument during compile. The headers are not located in the apps/ directory. Instead, they are located at ../include/ (relative to apps/).
So maybe a compile command like:
# from apps/ directory
gcc -I ../include/ s_server.c
You will probably have additional problems because you need to link against libssl and libcrypto. Be aware you will still have work to do.
Here is what it looks like on Linux:
openssl$ find . -name e_os2.h
./include/openssl/e_os2.h
openssl$ cd apps
apps$ ls ../include/openssl/e_os2.h
../include/openssl/e_os2.h
Since the relative path is ../include/openssl/e_os2.h and the source file #include "openssl/e_os2.h", you only need to include ../include using -I.
I am running a 32-bit binary on a 64-bit system...
You need to build OpenSSL as 32-bit. Run ./Configure LIST to get a list of MinGW targets. Then, configure with the appropriate triplet.
You may need to add -m32 to the command line for your program.

What is the difference between /usr/include/linux and /usr/include/x86_64-linux-gnu/

I'm very new to native C programming and now I'm trying to configure my IDE to set up include paths correctly. Since I would like to navigate by sys/xxx.h files I added
/usr/include/x86_64-linux-gnu/
to my include path. But there is also /usr/include/linux which seems contains the same headers also. So what is the difference between them? And which one should I use actually?
I can tell you immediately that the directories /usr/include/linux and /usr/include/asm should never be included in a list of system header directories. The headers in those directories are meant to be used as #include <linux/whatever.h> or #include <asm/whatever.h>, not as #include <whatever.h>.
The rest of the answer to this question depends on exactly which "distribution" of Linux you are using, so I can't just say it. Fortunately, there is a way to get the compiler to tell you. Run this command (exactly as shown) in a terminal window:
LC_ALL=C gcc -v -xc -E /dev/null 2>&1 |
sed -ne '/search starts here/,/End of search list/p'
You will get output that looks something like this, but the details may be slightly different:
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/x86_64-linux-gnu/8/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/8/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
The directories listed are the directories you should configure your IDE to look for system headers in, for purpose of looking up declarations and whatnot. However, you should not configure your IDE to pass any of these directories to the compiler as -I directories. It already knows to use them, it doesn't need to be told again, and telling it again can mess things up (for instance, the order of the above directories matters).
As an application programmer you don't need to worry about which headers "belong" in which directories. That's entirely the compiler and C library developers and Linux distribution maintainers' task.

Compiling C code with external library references

I am on RHEL 6.0 and got hold of the source code for join command(hopefully from the right source!!). I rarely work on a C code and hence finding this difficult. I am trying to compile and run the C code for join, but running into compile time errors.
g++ join.c
join.c:19:20: error: config.h: No such file or directory
join.c:25:20: error: system.h: No such file or directory
join.c:27:25: error: hard-locale.h: No such file or directory
join.c:28:24: error: linebuffer.h: No such file or directory
join.c:29:24: error: memcasecmp.h: No such file or directory
join.c:30:19: error: quote.h: No such file or directory
join.c:31:21: error: stdio--.h: No such file or directory
join.c:32:22: error: xmemcoll.h: No such file or directory
join.c:33:21: error: xstrtol.h: No such file or directory
join.c:34:22: error: argmatch.h: No such file or directory
Since I am not aware of where to find these libraries(I did google for each one and they are spread all over different websites), can anyone please guide me as to how I can link these libraries together and compile the source code of join command?
This is not a linking problem as you suggest. Instead, you get these errors because g++ can't find these files: config.h, system.h, ..., that are #included (indirectly) by join.c.
What you could do is find these files on your system, and then add as many -I<directory> options behind the g++ as there were directories you found these files in. Do man g++ for more info.
You'll also need to find the where the libraries are you need to link against. So you'll need to specify more than -I's.
On the other hand, aren't there 'configure' or other package files? Normally you don't have to specify compiler flags (like this -I) by hand. Instead, it's common that for example Makefile's are generated from such a configuration file, after which you just have to type make.
I advise you to get someone that has done this before, because you don't seem to understand the basics of C program compilation. This can cost you a lot of your precious time without results. But good luck anyway!
Perhaps you don't have everything in place to compile your code. Try installing the build-essential package.
sudo yum install build-essential
On a relevant note, I'm not aware of the script join.c but if you are looking for a way to concatenate a bunch of files together, you can do cat FILE1 FILE2 FILE3 > BIG_FILE where FILE1 FILE2 FILE3 are the files you want to join them. Under RHEL 6.0, you can use asterisks too, if there is a pattern. For example, cat FILE.00* > BIG_FILE

Trouble building gcc-4.3.4 in a non-standard location

I need to build gcc-4.3.4 in a non-standard location (NFS mounted). I configured:
../gcc-4.3.4/configure --prefix={install dir} --with-gmp={install dir} --with-mpfr={install dir} --with-local-prefix={install dir} --disable-shared
I ran make -j1. But I keep getting:
checking for suffix of object files... configure: error: cannot compute suffix of object files: cannot compile
In x86_64-unknown-linux-gnu/libgcc/config.log, I can see:
/home/panthdev/apps/gcc-4.3.4-compliant/compiler/objdir/./gcc/cc1: error while loading shared libraries: libmpfr.so.1: cannot open shared object file: No such file or directory
libmpfr.so.1 is there in {install dir}/lib. Also if I set LD_LIBRARY_PATH to {install dir}/lib, then it finds the libmpfr.so.1 but config.log starts complaining:
/tmp/cce9YhFK.s: Assembler messages:
/tmp/cce9YhFK.s:16: Error: bad register name `%rbp'
/tmp/cce9YhFK.s:18: Error: bad register name `%rsp'
As I read here you have 32bit binutils where as gcc is trying to do a 64bit build. Make sure your binutils & gcc has the same configuration.
You should maybe try using --with-sysroot instead of --prefix.
In the GCC 4.5.2 configure script (I have that available, but not 4.3.4), at around line 4500 (of 15.5K lines), there is the stanza:
rm -f conftest.$ac_ext
EXEEXT=$ac_cv_exeext
ac_exeext=$EXEEXT
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
$as_echo_n "checking for suffix of object files... " >&6; }
if test "${ac_cv_objext+set}" = set; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
rm -f conftest.o conftest.obj
if { { ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then :
for ac_file in conftest.o conftest.obj conftest.*; do
test -f "$ac_file" || continue;
case $ac_file in
*.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
*) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
break;;
esac
done
else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error "cannot compute suffix of object files: cannot compile
See \`config.log' for more details." "$LINENO" 5; }
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
Basically, the script is trying to compile 'conftest.c' and trying to find the extension of the object file created - and, for some reason, your compiler is not creating a conftest.o.
This isn't the first test it does on the compiler, so there seems to be something rather odd going on in your environment.
I've built GCC numerous times over the years - on Solaris and MacOS X - and I've always used the --prefix option. That is not the problem. The GMP, MPFR, MPC directories are necessary; the only option you've used that I'm not familiar with is the --with-local-prefix.
Are you specifying the bootstrap compiler somehow? Consider trying your current configure line with the addition of CC=/usr/bin/gcc or something similar, identifying a fully working compiler on your machine. I'm not convinced that'll solve the problem, but there is something funny about the way the compiler is behaving, or about the object file extensions that it produces. I assume you have several GB of spare space on the disk system? You'll need that.
Poking around the 'Installing GCC: Configuration' page, I find:
--with-local-prefix=dirname
Specify the installation directory for local include files. The default is /usr/local. Specify this option if you want the compiler to search directory dirname/include for locally installed header files instead of /usr/local/include.
You should specify --with-local-prefix only if your site has a different convention (not /usr/local) for where to put site-specific files.
The default value for --with-local-prefix is /usr/local regardless of the value of --prefix. Specifying --prefix has no effect on which directory GCC searches for local header files. This may seem counterintuitive, but actually it is logical.
The purpose of --prefix is to specify where to install GCC. The local header files in /usr/local/include—if you put any in that directory—are not part of GCC. They are part of other programs—perhaps many others. (GCC installs its own header files in another directory which is based on the --prefix value.)
Both the local-prefix include directory and the GCC-prefix include directory are part of GCC's “system include” directories. Although these two directories are not fixed, they need to be searched in the proper order for the correct processing of the include_next directive. The local-prefix include directory is searched before the GCC-prefix include directory. Another characteristic of system include directories is that pedantic warnings are turned off for headers in these directories.
Some autoconf macros add -I directory options to the compiler command line, to ensure that directories containing installed packages' headers are searched. When directory is one of GCC's system include directories, GCC will ignore the option so that system directories continue to be processed in the correct order. This may result in a search order different from what was specified but the directory will still be searched.
GCC automatically searches for ordinary libraries using GCC_EXEC_PREFIX. Thus, when the same installation prefix is used for both GCC and packages, GCC will automatically search for both headers and libraries. This provides a configuration that is easy to use. GCC behaves in a manner similar to that when it is installed as a system compiler in /usr.
Sites that need to install multiple versions of GCC may not want to use the above simple configuration. It is possible to use the --program-prefix, --program-suffix and --program-transform-name options to install multiple versions into a single directory, but it may be simpler to use different prefixes and the --with-local-prefix option to specify the location of the site-specific files for each version. It will then be necessary for users to specify explicitly the location of local site libraries (e.g., with LIBRARY_PATH).
The same value can be used for both --with-local-prefix and --prefix provided it is not /usr. This can be used to avoid the default search of /usr/local/include.
Do not specify /usr as the --with-local-prefix! The directory you use for --with-local-prefix must not contain any of the system's standard header files. If it did contain them, certain programs would be miscompiled (including GNU Emacs, on certain targets), because this would override and nullify the header file corrections made by the fixincludes script.
Indications are that people who use this option use it based on mistaken ideas of what it is for. People use it as if it specified where to install part of GCC. Perhaps they make this assumption because installing GCC creates the directory.
Are you sure you're using that correctly? You probably are since you have to search to find the option -- ../gcc-4.x.y/configure --help does not mention the option.

Resources