GCC have include but not library - c

I'm writing my own kernel for fun, and in doing so I've needed to install glibc to use the standard C libraries. However, after installing the library to the desired directory, my kernel.c program includes the stdio.h header and attempts to use fopen, however I come across this error:
kernel.c:(.text+0x238): undefined reference tofopen'`
After looking around I noticed that I don't have any actual code to all of the header files, just the header files themselves. So I went and added the -L flag to GCC to add the lib folder that was created during the compilation of glibc and what I've found out is that the lib folder has nothing of what I need.
I poked around and found that the build directory I used when compiling glibc has the .o files I'm looking for (e.g it has iofopen.o for the fopen method).
So what's going on?
If needed, the commands I am using to compile my kernel are:
#!/bin/bash
nasm -felf32 boot.asm -o boot.o
/home/noah/opt/cross/bin/i686-elf-gcc -I/home/noah/Documents/NoahOS/include/ -L/home/noah/Documents/glibc/build -c *.c -std=gnu99 -ffreestanding -Wall -Wextra
/home/noah/opt/cross/bin/i686-elf-gcc -I/home/noah/Documents/NoahOS/include/ -L/home/noah/Documents/glibc/build -T linker.ld -o noahos.bin -ffreestanding -O2 -nostdlib *.o -lgcc
First line builds the boot file, which is assembly.
Second line runs gcc on all of the C language .c files and creates their object files.
Third line links all of the files together with linker.ld and outputs the final kernel to noahos.bin which is a runnable kernel using
qemu-system-i386 -kernel noahos.bin
If needed more information can be provided. Please ask.

You are correctly compiling your kernel using -nostdlib because the kernel can't use the standard library. Why not? Because it doesn't make sense: the standard library is the interface between user programs and the kernel, so that application developers don't need to know the system call specification for your kernel, all that is required is a port of the C library.
Oh, there's the answer. You need a port of the C library to use your own system calls. Starting with glibc might not be the easiest to port (it comes with the kitchen sink).

Related

Is it a compiled library portable?

I have a conceptual question about writing a library in plain c. I have some functions that I have to use in different programs in the same folder, so I was thinking about writing a library to host these functions. I have to write the whole code in a folder that will be copied to another computer (where the programs will run). If I create and compile the library in this folder, will be the user able to run the programs without rebuilding the library from source or he might have some unpredictable errors? The user will build the programs that use the library anyway, he won't build the lib itself.
Thanks
Lorenzo
In general, no, it is not portable in the sense that a compiled library can be linked on an arbitrary other system. The compiled library has to be compatible to the target architecture, the OS, the compiler system, to name some.
But you have another choice, concluded from your comment: It seems that you also provide some shell script or makefile to build the programs.
Because a library consists of "just" a set of compiled translation units before some of them get linked into the programs, you can take the set of sources of these translations unit and compile them with the sources of each program, where appropriate.
As an example, let's say you have 2 functions (each in its own source file) you use in different combinations in 3 programs. "prg1" uses func1(), "prg2" uses func2(), and "prg3" uses both.
This can be the commands to build the programs with a (static) library:
gcc -c func1.c -o func1.o
gcc -c func2.c -o func2.o
ar -r lib.a func1.o func2.o
gcc prg1.c lib.a -o prg1
gcc prg2.c lib.a -o prg2
gcc prg3.c lib.a -o prg3
Instead of the library you compile the programs' sources directly:
gcc prg1.c func1.c -o prg1
gcc prg2.c func2.c -o prg2
gcc prg3.c func1.c func2.c -o prg3
The results are the same, at least as long as you had linked statically to the library.
But even with a shared (dynamic) library the approach will be the same. Shared libraries "only" save some RAM if several programs using them are run concurrently. If only one program runs at a time, a dynamically linked program might need more RAM and loads slower.

Symbols missing from Linux static library using NetBeans

I'm working on a C static library that's eventually going to be open-source, so I'm cross-compiling on Windows and Ubuntu to backstop for any portability issues.
The problem I'm having is that the symbols from one of the object files are omitted from the Linux build. When I build the library using VS2015 on Windows, all symbols are present.
I'm mostly used to developing for Windows, so I'm pretty spoiled to using an IDE for most build scenarios. On Ubuntu, I'm using NetBeans , and I'm not sure if the problem is with my understanding of gcc or if I don't have NetBeans set up correctly.
Details
Ubuntu 16.04LTS using gcc(Ubuntu) 5.4.0
NetBeans IDE 8.1 C/C++
The library consists of 3 source files and 2 header files:
queue.c --> queue implementation
memutil.c --> memory utilities
mylib.c --> main library implementation
queue.h --> included by queue.c and mylib.c
mylib.h --> header file for the static library
The mylib.h header contains the header information for the memutil.c source file, wrapped in a conditional that depends on the MEMCHECK symbol on the command line. Likewise for the code in the memutil.c source file. The MEMCHECK symbol is defined when building the library, but when I run nm on libmylib.a after the Linux build, no symbols are listed for the memutil.o object file. When i look at the mylib.lib file on Windows, all the symbols for memutil.obj are listed.
Now, if I add a stubbed out source file that just includes the mylib.h header, all of the symbols are present in the libmylib.a library. I'm guessing there's some sort of header file interaction malfunction going on, but I don't where to look to find out what it is or how to fix it. I have Google'd the snot out of this with as many different phrasings as I can think of, but no joy.
Here's the NetBeans build output, less all of the directory noise:
gcc -c -g -Wall -DMEMCHECK -MMD -MP -MF "build/queue.o.d" -o build/queue.o queue.c
gcc -c -g -Wall -DMEMCHECK -MMD -MP -MF "build/memutil.o.d" -o build/memutil.o memutil.c
gcc -c -g -Wall -DMEMCHECK -MMD -MP -MF "build/mylib.o.d" -o build/mylib.o mylib.c
ar -rv dist/Debug/GNU-Linux/libmylib.a build/queue.o build/memutil.o build/mylib.o
ar: creating dist/Debug/GNU-Linux/libmylib.a
a - build/queue.o
a - build/memutil.o
a - build/mylib.o
ranlib dist/Debug/GNU-Linux/libmylib.a
BUILD SUCCESSFUL (total time: 3s)
Stubbing in the header file inclusion can't be the fix for this, can it? It works, but it seems awfully crude. Besides, I can't really credit that it would be necessary with gcc and not necessary with VS2015.
Well, I found the solution, but I'm not marking this as the accepted answer because I'm not sure exactly why it's the solution.
I noticed the -Mxx flags on the compiler lines:
gcc -c -g -Wall -DMEMCHECK -MMD -MP -MF "build/...
So I went back to Google and found this site: Auto-Dependency Generation, which covers having Make handle the generation and tracking of build dependencies.
Then I starting combing through every single menu item in NetBeans until I found this one:
Tools->Options->C/C++->[on/off] Enable dependency checking in generated makefiles
I cleared that switch, and all of the missing symbols appeared in the library. However, the -Mxx flags were still present on the compiler lines in the build output. Now, the makefile generation for NetBeans uses about 5 separate makefile templates and 3 or 4 different XML configuration files to generate the makefile at build time, based on build configuration and target. I couldn't figure out if the auto-dependency flags were rendered inert by flipping that switch or not.
But, if I'm reading the information on the above-mentioned website correctly, those -Mxx flags are actually used by gcc in support of Make, so I'm not sure how they would have a different interpretation based on something that NetBeans did. Although, there are a LOT of substitutions in those makefile templates, and with me not being an Autoconfig/Make wizard, I may have simply missed it.
So, apparently, since none of the source files actually included the function prototypes for the memory utilities -- because they are contained in the library header file, which none of the library source files include (it's meant for inclusion by client code) -- the NetBeans dependency checker decided that those functions weren't needed in the library.

.dylib file not loaded while loading .so files

I wanted to use INCR in redis beyond its maximum value 9,223,372,036,854,775,807. So I write a redis module C code using gmp.h. In C code I read the value in the key (the key to be incremented) and incremented by using functions in gmp.h and then written back to the same key.
I create .o files and then .so files and it works fine in my mac. When I gave the .so file to my friend, the .so file did not load and an error came for her.
Library not loaded: /usr/local/lib/libgmp.10.dylib
I guess this happend because my friend not installed gmp in her mac
But I thought it will work. Is there any way to make it work in my friend's macbook without installing the library ?
Commands used to created .o and .so files
gcc -dynamic -fno-common -std=gnu99 -c -o mycommand.o mycommand.c
ld -o mycommand.so mycommand.o -bundle -undefined dynamic_lookup -lc -lgmp

gcc and liboauth - linker can't find oauth.h

I'm trying to use liboauth with a C program, using gcc as my compiler, and no matter what I've tried I keep getting the error "ld: library not found for -loauth" and "clang: error: linker command failed with exit code 1".
I'm including the header via "#include <oauth.h>", and my most-recent call to gcc looked like this:
gcc -Wall -lcurl -loauth -I /usr/local/include -v -o api api.c
Now, oauth.h does exist in /usr/local/include, and there are a handful of liboauth files (including liboauth.a) located in /usr/local/bin, which I'm assuming were placed there when I ran the install. I will admit that I'm not very familiar with gcc and compiling non-trivial C programs, but I was able to get libcurl working on a fresh download in just a few minutes. I just can't figure out what's going on with liboauth.
Thanks in advance
If you are sure liboauth's located in /usr/local/bin use
gcc -Wall -L/usr/local/bin -I /usr/local/include -v -o api api.c -lcurl -loauth
It'd also be better to place libraries in the end of the command as there is some important stuff with them (they may depend on each other, etc).
By the way, it's pretty strange your libraries are in /usr/local/bin as libraries are almost always stored in some path like /usr/*/lib.

How to configure a non-standard linker for an autotooled build?

I wanted to configure an autotooled project to invoke a non-standard
linker (the gold linker),
using the stock autotools of Linux Mint 16/Ubuntu 13.10
I believed I would achieve this by:
libtoolize-ing the project
Running ./configure LD=/path/to/my/linker ... etc.
However this has been ineffective. libtoolize has been successful. After
a standard ./configure; make I now see that libtool is doing the
linking:
/bin/bash ./libtool --tag=CXX --mode=link g++ -g -O2 -o helloworld helloworld.o
But passing LD=/path/to/my/linker to configure makes no difference. Experimentally,
I even ran:
./configure LD=/does/not/exist
expecting to provoke an error, but I didn't. The output contains:
checking if the linker (/does/not/exist -m elf_x86_64) is GNU ld... no
checking whether the g++ linker (/does/not/exist -m elf_x86_64) supports shared libraries... yes
And thereafter a make continues to link, successfully, invoking g++ exactly as before.
What is the right way to configure a non-standard linker?
But passing LD=/path/to/my/linker to configure makes no difference
This is because LD is almost never and should almost never be used to link any user-space program. Correct links are performed by using the appropriate compiler driver (gcc, g++, etc) instead.
What is the right way to configure a non-standard linker?
If you have /some/path/ld and you want gcc to use that ld, pass -B/some/path flag to gcc.
It then follows that you likely want:
./configure CC='gcc -B/some/path' CXX='g++ -B/some/path' ...
I landed on this via a Google search, though my scenario is a bit different from yours; there was no libtool involved. An old open source program's Makefile was hard-coding ld to create an object file with a symbol from binary data.
This is what I ended up doing to work around the lack of $(LD) being recognized when passed to configure:
https://github.com/turboencabulator/tuxnes/commit/bab2747b175ee7f2fc3d9afb28d69d82db054b5e
Basically I added to configure.ac:
AC_CHECK_TOOL([LD], [ld])
Leaving this answer here for if someone else lands via a google search.

Resources