undefined reference to `le16toh' error in Makefile - c

I'm trying to compile a C program with the following Makefile:
msh: libFAT32.so
gcc -Wall -fPIC -I. -o msh newTest.c -L. -lFAT32
libFAT32.so:
gcc -std=c99 -shared -o libFAT32.so -fPIC fat32.c
clean:
rm *.so msh
However, every time I try to compile the program with make I get the following error:
user#user-VirtualBox:~/fat1$ make
gcc -Wall -fPIC -I. -o msh newTest.c -L. -lFAT32
./libFAT32.so: undefined reference to `le32toh'
./libFAT32.so: undefined reference to `le16toh'
collect2: error: ld returned 1 exit status
Makefile:19: recipe for target 'msh' failed
make: *** [msh] Error 1
Can some one tell how to fix this?

So, here's what's going on (making the safe assumption that you're using a linux distribution in your VM).
With this test program:
#include <stdio.h>
#include <endian.h>
int main(void) {
printf("%d\n", le32toh(1234));
return 0;
}
compiling and running it works:
$ gcc -Wall -Wextra test.c
$ ./a.out
1234
However, you're compiling using -std=c99. So let's try that:
$ gcc -std=c99 -Wall -Wextra test.c
test.c: In function ‘main’:
test.c:5:18: warning: implicit declaration of function ‘le32toh’ [-Wimplicit-function-declaration]
printf("%d\n", le32toh(1234));
^~~~~~~
/tmp/cc7p3cO8.o: In function `main':
test.c:(.text+0xf): undefined reference to `le32toh'
collect2: error: ld returned 1 exit status
Compiling in c99 mode disables a bunch of functions and macros and such that aren't in the 1999 version of the C standard unless they're explicitly requested, hence the implicit declaration warning. le32toh() is a macro, not a function with a symbol in libc, hence the linker error.
If you read the man page for le32toh(), you'll see that it needs the _DEFAULT_SOURCE feature test macro, which must be defined before any headers are included.
So, your options are:
Compile in gnu99 mode instead, since that automatically defines a bunch of the feature test macros.
Continue to use c99 mode and add a #define _DEFAULT_SOURCE at the very start of your fat32.c source file.
Continue to use c99 mode and add -D_DEFAULT_SOURCE to your compiler arguments.

Related

Linking 2 object files in c to create an executable

I am having an issue with a makefile for something I am making. My makefile looks like this
bag: main.o bow.o
gcc bow.o main.o -o bag
main.o: main.c bow.h
gcc -Wall -ansi -pedantic main.c -o main.o
bow.o: bow.c bow.h
gcc -Wall -ansi -pedantic -c bow.c -o -bow.o
I also have a header file called "bow.h" that is used in both bow.o and main.o. bow.h consists of 8 function definitions and 2 structs, bow.c contains the 8 functions and NO MAIN file. main.c is suppose to be a minimal main file so it only consists of
#include "bow.h"
When I run my makefile in the Terminal with
make
I get this message
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
makefile:2: recipe for target 'bag' failed
make: *** [bag] Error 1
What exactly does this mean, how is it caused and how can I fix it?
Even a minimal program (executable) needs a point to start. For a C program, this is the main() function. Thus, the linker seeks for that function (more precisely, it links the start-up object where main is an unresolved symbol), does not find it, and issues an error.
Thus, you have to provide a main(). Alternatively, you may not generate an executable but a library.

Undefined reference error but symbol existing in the library

I get an undefined reference error for the example below. I have seen lots of questions that relate to this issue but believe I gave a stripped, reproducible, conceptual example as opposed specific issues in other questions,
dynlib.h:
void printMe_dyn();
dynlib.c:
#include <stdio.h>
#include "dynlib.h"
void printMe_dyn() {
printf("I am execuded from a dynamic lib");
}
myapp.c:
#include <stdio.h>
#include "dynlib.h"
int main()
{
printMe_dyn();
return 0;
}
Build steps:
gcc -Wall -fpic -c dynlib.c
gcc -shared -o libdynlib.so dynlib.o
gcc -Wall -L. -ldynlib myapp.c -o myapp
Error:
/tmp/ccwb6Fnv.o: In function `main':
myapp.c:(.text+0xa): undefined reference to `printMe_dyn'
collect2: error: ld returned 1 exit status
Proof that the symbol is in the library:
nm libdynlib.so | grep printMe_dyn
00000000000006e0 T printMe_dyn
Am I using the correct compiler flags for building the dynamic
library?
Is the proof I've presented really an unambiguous proof?
What other approach could be taken to diagnose the issue?
The order of appearance of libraries matter.
To quote the online gcc manual
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not be loaded.
You should be changing your compilation statement to
gcc -o myapp -Wall -L. myapp.c -ldynlib
to tell gcc to search for the symbols used in (compiled) myapp.c to be present in dynlib.
Just as additional notice. The same behavior one may obtain when the library has been built by gcc and linked to the c++ project. Like follows:
gcc -Wall -fpic -c dynlib.c
gcc -shared -o libdynlib.so dynlib.o
g++ -o myapp -Wall -L. myapp.cpp -ldynlib
In such case the reason is name-mangling used by g++. To have it turned off one must wrap C-function prototypes by extern "C" within C-library. For example like follows:
dynlib.h:
#ifdef __cplusplus
extern "C"{
#endif
void printMe_dyn();
#ifdef __cplusplus
}
#endif
The order of libraries in linker command line matters. Fix:
gcc -o myapp -Wall -L. myapp.c -ldynlib

GCC Compiler Refuses To See Main Method (C Programming)

I recently downloaded the AGIL adventure game interpreter from: http://www.agidev.com/dl_files/agil-0.1.5.tar.gz
It is a C program which runs old Sierra adventure games like King's Quest.
I have being trying to compile the source code so that I can debug it and learn how it works.
However despite my best efforts the GCC compiler never sees the main method, despite its existence.
Here is the compiler output:
make linsdl all
make -fMakefile.sdl
make[1]: Entering directory `/home/alay/Downloads/AGIL/agil'
gcc -O -Wall -Isrc/include -I/usr/local/include -DTARGET_SDL -fstrength-reduce -fomit-frame-pointer -pedantic -I/usr/local/include/SDL -Dmain=SDL_main -c src/main.c -o bin/main.o
gcc -O -Wall -Isrc/include -I/usr/local/include -DTARGET_SDL -fstrength-reduce -fomit-frame-pointer -pedantic -I/usr/local/include/SDL -Dmain=SDL_main -c src/drivers/sdl.c -o bin/driver.o
gcc -L/usr/local/lib bin/main.o bin/general.o bin/event.o bin/graphics.o bin/menu.o bin/text.o bin/resource.o bin/gameid.o bin/pic_op.o bin/picture.o bin/lzw.o bin/vm.o bin/actionop.o bin/testop.o bin/status.o bin/object.o bin/view.o bin/check.o bin/save.o bin/message.o bin/sound.o bin/decomp.o bin/driver.o \
-o bin/agil -lm -lSDLmain -lSDL -lpthread
/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crt1.o: In function `_start':
make[1]: Leaving directory `/home/alay/Downloads/AGIL/agil'
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status
make[1]: *** [all] Error 1
make: *** [linsdl] Error 2
The only changes I made were to change include statements so that the compiler could find the SDL library. For example I changed: #include "SDL.h" to #include "SDL/SDL.h".
My goal is to understand the C code so that I can build something similar on another platform.
The -Dmain=SDL_main is equivalent to having a #define main SDL_main in your code. The preprocessor will replace the main with SDL_main, and the linker won't find it ( because it itn't there).
Run gcc -E ... and see how the code looks after the preprocessor ran, but before it goes to the compiler.
LE: True. But I wouldn't pass it as argument to gcc ( and changing the header files ). But it as a define after the includes.
Also run a locate libsdl and check you pass the path correctly to the linker.

CS107 Assignment file couldn't compile, missing expat.h and thread_107.h files

I was auditing cs107 at stanford online
The problem I ran into is with assignment 6, when I type "make" in terminal, the error message pops up. Basically, I miss two header files, which I guess can be got from the pre-compiled .lib file. But somehow it just doesn't work.
Here's part of the original make file:
CFLAGS = -D_REENTRANT -g -Wall -D__ostype_is_$(OSTYPE)__ -std=gnu99 -I/usr/class/cs107/include/ -Wno-unused-function $(DFLAG)
LDFLAGS = -L/usr/class/cs107/assignments/assn-6-rss-news-search-lib/$(OSTYPE) -L/usr/class/cs107/lib -lexpat -lrssnews $(PLATFORM_LIBS) $(THREAD_LIBS)
PFLAGS= -linker=/usr/pubsw/bin/ld -best-effort -threads=yes -max-threads=1000
Edit:
When I said "This is supposed to compile even without threading implementation", I meant that it should compile without FURTHER threading implementation by students.
So here's the error message with thread:
gcc -D_REENTRANT -g -Wall -D__ostype_is_linux__ -std=gnu99 -I/usr/class/cs107/include/ -Wno-unused-function -c -o rss-news-search.o rss-news-search.c
rss-news-search.c: In function ‘main’:
rss-news-search.c:109:3: warning: implicit declaration of function ‘InitThreadPackage’ [-Wimplicit-function-declaration]
gcc rss-news-search.o -D_REENTRANT -g -Wall -D__ostype_is_linux__ -std=gnu99 -I/usr/class/cs107/include/ -Wno-unused-function -L/home/h/cs107/assn-6-rss-news-search-lib/linux -L/usr/class/cs107/lib -L. -lexpat -lrssnews -lnsl -lpthread -lthread_107_linux -o rss-news-search
/usr/bin/ld: cannot find -lthread_107_linux
collect2: ld returned 1 exit status
make: *** [rss-news-search] Error 1
here's the error message without $(THREAD_LIBS):
gcc -D_REENTRANT -g -Wall -D__ostype_is_linux__ -std=gnu99 -I/usr/class/cs107/include/ -Wno-unused-function -c -o rss-news-search.o rss-news-search.c
rss-news-search.c: In function ‘main’:
rss-news-search.c:109:3: warning: implicit declaration of function ‘InitThreadPackage’ [-Wimplicit-function-declaration]
gcc rss-news-search.o -D_REENTRANT -g -Wall -D__ostype_is_linux__ -std=gnu99 -I/usr/class/cs107/include/ -Wno-unused-function -L/home/h/cs107/assn-6-rss-news-search-lib/linux -L/usr/class/cs107/lib -L. -lexpat -lrssnews -lnsl -lpthread -o rss-news-search
rss-news-search.o: In function `main':
/home/h/cs107/assn-6-rss-news-search/rss-news-search.c:109: undefined reference to `InitThreadPackage'
collect2: ld returned 1 exit status
make: *** [rss-news-search] Error 1
In the later case, if I comment out "InitThreadPackage", it compiles just fine.
This is the procedure to compile your project:
Create a file assn-6-rss-news-search/thread_107.h, and put this inside:
/* Empty header file */
Copy the library librssnews.a from assn-6-rss-news-search-lib/linux/ to assn-6-rss-news-search/
Modify the file rss-news-search.c by commenting the call to the function : InitThreadPackage on line 109:
//InitThreadPackage(false);
Modify the Makefile to include the path to the current directory (to be able to link to the library you've copied earlier librssnews.a):
The line 27 should look like this:
LDFLAGS = -L/usr/class/cs107/assignments/assn-6-rss-news-search-lib/$(OSTYPE) -L/usr/class/cs107/lib -L. -lexpat -lrssnews $(PLATFORM_LIBS) $(THREAD_LIBS)
Then:
make clean
make
EDIT :
When you got this error cannot find lthread_107_linux, Edit your Makefile to remove this $(THREAD_LIBS) on line 27:
LDFLAGS = -L/usr/class/cs107/assignments/assn-6-rss-news-search-lib/$(OSTYPE) -L/usr/class/cs107/lib -L. -lexpat -lrssnews $(PLATFORM_LIBS)
The class-specific header files, like thread_107.h are found in /usr/class/cs107/include/ on whatever machine the instructor is expecting the students to use. If you're not using that machine, you'll have to copy those include files or make your own.
The expat.h file is from an open source library. You'll need to install the appropriate package on the system you're compiling on. On Ubuntu, that's sudo apt-get install libexpat1-dev, but the package name should be similar on other distributions.

Why am I getting a gcc "undefined reference" error trying to create shared objects?

Why am I getting an "undefined reference" error using gcc?
I am trying to create a shared object (.so) that exports one function, "external()". I then try to link against the .so but get "undefined reference 'external'". What am I doing wrong here?
File: external.c
int external() {
return 5;
}
File: program.c
int external();
int main(char** argv, int* argc) {
return external();
}
Commands:
$ gcc -fPIC -c external.c
$ gcc -shared -o libexternal.so external.o
$ gcc -L. -lexternal -o program program.c
/tmp/cc3MmhAE.o: In function `main':
program.c:(.text+0x7): undefined reference to `external'
collect2: ld returned 1 exit status
I can even run nm and see that the .so is defining 'external':
Command:
$ nm libexternal.so | grep external
0000040c T external
What am I missing here?
Recent versions of gcc/ld default to linking with --as-needed.
This means if you write -lexternal before the C file the library will automatically get excluded (the order matters when testing if things are "needed" like this)
You can fix this with either of:
gcc -L. -o program program.c -lexternal
gcc -L. -Wl,--no-as-needed -lexternal -o program program.c
The latter of which passes --no-as-needed to the linker, which would cause the library to still be linked, even if you didn't call external() from it.
Note: -Wl,--no-as-needed isn't applied globally to everything that's linked, it's only applied to things that follow it in the command line order. So -lexternal -Wl,--no-as-needed also wouldn't work. This does mean that you can mix and match behaviours though, for example gcc -L. -Wl,--no-as-needed -lexternal -Wl,--as-needed -o program program.c -lmightneed would always link against external, but only link against mightneed if one or both of program.c/libexternal.so caused it to be needed.

Resources