Linking 2 object files in c to create an executable - c

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.

Related

Problem compiling C progtam from command line gcc with math.h

I am new to the command line and I am trying to run a C program containing the function log10.
If I give
gcc -o -lm randomVamp random\ vampire.c
I get the error
gcc: error: randomVamp: No such file or directory
but randomVamp is the name I wanted to give to the executable, of course it doesn't exist yet.
If I prompt just
gcc -o -lm random\ vampire.c
then I get the error
/usr/bin/ld: /tmp/ccbWivPU.o: in function `main':
random vampire.c:(.text+0x312): undefined reference to `log10'
collect2: error: ld returned 1 exit status
Anyone knows what's going on?
I don't know if it's relevant, but the program also includes stdlib.h and time.h should I use some flag or link them in some way?
-o means that the next argument is the output file name. Replace -o -lm randomVamp with something like -o randomVamp -lm.
Also, note that -l... have no effect if specified before the .c/.cpp/.o/... files. So, the command could look like this:
gcc -o randomVamp random\ vampire.c -lm

Including directories with gcc is not linking correctly

So I have a subdirectory with several files and need to link with it. Inside the .c files I have an include that looks somewhat like:
#include "subdirectory/header.h"
This header file includes functions such as lex() that I am using and my output on compiling is:
cc -IlexicalAnalyzer -Wall -c -o parser.o parser.c
cc -IlexicalAnalyzer -Wall -c -o recognizer.o recognizer.c
g++ -IlexicalAnalyzer -Wall parser.o recognizer.o -o recognizer
parser.o: In function `advance':
parser.c:(.text+0x36): undefined reference to `lex'
recognizer.o: In function `recognizer':
recognizer.c:(.text+0xd): undefined reference to `newLexer'
collect2: error: ld returned 1 exit status
make: *** [recognizer] Error 1
What am I doing wrong?
You have included the header files from the subdirectory, that's good because that declares them for the compiler, but there should also be some source files there that you need to compile and then link. Those source files should define the lex and newLexer functions that are referred to by the header files.

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.

'ld' cannot link symbols, although they are in library

I have a problem while trying to compile and link my program with "dmalloc".
bin
+--dmalloc
include
+--dmalloc.h
lib
+--libdmalloc.a
+--libdmallocth.a
main.c
I have the following directory structure
Now I try to compile my program with the following command:
gcc -Iinclude -Llib -ldmalloc -DDMALLOC main.c
/tmp/ccSDFmWj.o: In function `main':
main.c:(.text+0x29): undefined reference to `dmalloc_malloc'
collect2: ld returned 1 exit status
Okay, I get that there's a problem with linking the symbols, ld simply cannot find reference to dmalloc_malloc. However...
nm lib/libdmalloc.a | grep dmalloc_malloc
0000000000001170 T dmalloc_malloc
0000000000000fe0 t dmalloc_malloc.part.6
I am puzzled... The symbol is there in that library. Why does 'ld' has problem with it?
List the libraries last:
gcc -Iinclude -Llib -DDMALLOC main.c -ldmalloc

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