Am I writing this makefile correctly? - c

I am learning how to write C code in Linux and I am learning makefiles at a very beginner level.
I am having problems when making shared libraries.
The exercise is to make a simple function calculator C program with files:
main.c
add.c
subt.c
mult.c
div.c
The names of the files define the function they do.
The function in the file subt.c is in the static library:
libsubstatic.a
The function in the file mult.c is in the shared library:
libmultshared.so
For this program, I write the following makefile:
calc.exe: main.o add.o div.o libsubstatic.a libmultshared.so
gcc -o calc.exe main.o add.o div.o libsubstatic.a -Wl,-rpath,/home/ahmed/Desktop/labTask3 -lmultshared.so
main.o: main.c header.h
gcc -c main.c
add.o: add.c header.h
gcc -c add.c
libsubstatic.a: subt.o
ar cr libsubstatic.a subt.o
subt.o: subt.c header.h
gcc -c subt.c
libmultshared.so: mult.o
gcc -shared -fPIC -o libmultshared.so mult.o
mult.o: mult.c header.h
gcc -c -fPIC mult.c
div.o: div.c header.h
gcc -c div.c
The path where the code and makefile is placed:
/home/ahmed/Desktop/labTask3
I get the following message after I type "make" in the terminal:
gcc -o calc.exe main.o add.o div.o libsubstatic.a -Wl, -rpath, /home/ahmed/Desktop/labTask3 -lmultshared.so
gcc: error: unrecognized command line option ‘-rpath,’
make: *** [calc.exe] Error 1
What am I missing? Did I write this makefile correctly?
Please explain shared libraries, my concept might be faulty.
Please help.
Note that, I'm new to linux and I don't have much experience in makefiles.
EDIT: I removed the spaces as directed in the first answer. Now the terminal says:
gcc -o calc.exe main.o add.o div.o libsubstatic.a -Wl,-rpath,/home/ahmed/Desktop/labTask3 -lmultshared.so
/usr/bin/ld: cannot find -lmultshared.so
collect2: error: ld returned 1 exit status
make: *** [calc.exe] Error 1
Should I do something with the "-lmultshared.so"? What should I do?

-Wl, -rpath, /home/ahmed/Desktop/labTask3
Get rid of the spaces. This should all be one long argument.
-Wl,-rpath,/home/ahmed/Desktop/labTask3
See this excellent answer by #KerrekSB for a detailed explanation about passing arguments to the linker with -Wl.

Related

How to link a simple program in Windows with Mingw GCC

I have a simple "Hello World!" c program, named hello.c on my desktop:
#include <stdio.h>
int main() {
printf("Hello world!\n");
return 0;
}
I run the following commands.
I pre-process it with : cpp hello.c > hello.i
I compile it with : gcc -S hello.i
I assemble it with : as -o hello.o hello.s
All good so far. But, i'm unable to link it. I've tried, among other commands, these:
ld -o hello.exe hello.o
ld -o hello.exe hello.o -lgcc
ld -o hello.exe hello.o -nostdlib -lgcc
Nothing works. The link errors i get in every single case are :
hello.o:hello.c:(.text+0x9): undefined reference to `__main'
hello.o:hello.c:(.text+0x15): undefined reference to `puts'
How can i link this assembled program hello.o in order to finally produce the executable program hello.exe? What am i missing? [Using Windows 8.1, Mingw version 0.6.2.] Thanks in advance.
Even if your answers to clarification questions are not particularly useful:
Try something like
ld hello.o -lmsvcrt -entry=_main -subsystem=console -o hello.exe
If you want to see the linker command line the standard gcc uses, invoke gcc like so:
gcc test.c -o test -Wl,-v
The last lines output is what you should be using...
If you want to compile something rather than experimenting with tools, don't link it using the linker directly. Use gcc, which will call the linker for you with the right options:
Compile step:
gcc -c hello.c
Link step:
gcc -o hello.exe hello.o
Or all in one:
gcc -o hello.exe hello.c
You can also use a simple Makefile, then run make:
all: hello.exe

How to compile this lib for usage?

I'm new to C programming, and I'm trying to compile this Simple training example with GCC on Ubuntu 12.10.
Looks like fann.h should not be included (as stated on the file itself), so I included fixedfann.h instead.
First attempt (without include, just to see what the compiler will ask for):
$ gcc main.c -o output
/tmp/cckKyM92.o: In function `main':
main.c:(.text+0x62): undefined reference to `fann_create_standard'
main.c:(.text+0x7a): undefined reference to `fann_set_activation_function_hidden'
main.c:(.text+0x8e): undefined reference to `fann_set_activation_function_output'
main.c:(.text+0xba): undefined reference to `fann_train_on_file'
main.c:(.text+0xce): undefined reference to `fann_save'
main.c:(.text+0xda): undefined reference to `fann_destroy'
collect2: ld returned 1 exit status
fann_create_standard is on fann.h and fann.c. As fann.h is included by fixedfann.h, and fann.h should not be included directly, I believe I have to compile fann.c and fixedfann.c, and link then (tell me if I'm doing any mistake, I'm still not familiar with this "linking" stuff).
So I did:
$ gcc fann/fixedfann.c -o fann/fixedfann.o
fann/fixedfann.c:22:20: fatal error: config.h: No such file or directory
compilation terminated.
and then I did:
$ gcc fann/fixedfann.c -o fann/fixedfann.o -include fann/include/config.h
fann/fixedfann.c:22:20: fatal error: config.h: No such file or directory
compilation terminated.
Now, why it's not finding the config.h file here?
--update
Thanks #JonathanLeffler, I could make some steps here. But now I'm stuck at:
$ gcc fann/fixedfann.c -o fann/fixedfann.o -I./fann/include/ -lm
/usr/lib/gcc/i686-linux-gnu/4.6/../../../i386-linux-gnu/crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
collect2: ld returned 1 exit status
and, with grep, I could not find any reference to main on the fann folder... Also no function _start, and I don't know who is linking this crt1.o... Any idea what's wrong here?
--update2
Ok, I got the .o files using Harmeet's Makefile, now I'm trying to link everything.
I created the main.o with gcc -c main.c, and I tried:
gcc -o output main.o fann/fixedfann.o -lm
(-lm for the libmath, that is needed) and I got:
main.c:(.text+0xba): undefined reference to `fann_train_on_file'
This fann_train_on_file is on fann_train_data.c, so I tried:
gcc -o output main.o fann/fixedfann.o fann/fann_train_data.o -lm
but I got lots of multiple definition of... errors... :/
Looks like fann_train_data.o is already included/linked, but if so, why it's not finding fann_train_on_file?
--update3
I'm still really stuck here... Any idea of which (if any) of this two lines should work?:
gcc -o output main.o hello.o fann/fixedfann.o fann/fann_train_data.o -lm
or
gcc -o output main.o hello.o fann/fixedfann.o -lm
--update for Harmeet
The output was:
$ make
gcc -L./fann -lfann main.o -o main
main.o: In function `main':
main.c:(.text+0x62): undefined reference to `fann_create_standard'
main.c:(.text+0x7a): undefined reference to `fann_set_activation_function_hidden'
main.c:(.text+0x8e): undefined reference to `fann_set_activation_function_output'
main.c:(.text+0xba): undefined reference to `fann_train_on_file'
main.c:(.text+0xce): undefined reference to `fann_save'
main.c:(.text+0xda): undefined reference to `fann_destroy'
collect2: ld returned 1 exit status
make: *** [main] Error 1
You can use ar to make a static library and work with that.
Create a Makefile under your hello-fann-3/fann/ folder with the following contents -
SOURCES = $(wildcard *.c)
OBJECTS = $(SOURCES:.c=.o)
CFLAGS = -c -Iinclude
all: libfann.a
libfann.a: $(OBJECTS)
ar rcs $# $^
%.o: %.c
gcc $(CFLAGS) $^
Then use the make command in hello-fann-3/fann/ to build the static library. The above Makefile will generate libfann.a that you can link to your program.
Create a Makefile under your hello-fann-3/ folder with the following contents -
SOURCES = $(wildcard *.c)
OBJECTS = $(SOURCES:.c=.o)
CFLAGS = -c -I./fann/include
LFLAGS = -L./fann -lfann
main: $(OBJECTS)
gcc $(LFLAGS) $^ -o $#
%.o: %.c
gcc $(CFLAGS) $^
Then use the make command in hello-fann-3/ to build the main program.
In your main.c, you must include fan.h like -
#include "fann.h"
If you do not understand the Makefile, you can read about it here -
http://www.gnu.org/software/make/manual/html_node/index.html
You just need to link the fann library.
If you compile manually do this
gcc main.c -lfann -lm -o main
then simply run it like
./main
If you are on Ubuntu and you faced the following error
./main: error while loading shared libraries: libfann.so.2: cannot open shared object file: No such file or directory
Then run
sudo ldconfig
If you are using NetBeans, then simply Right click on your project -> Properties -> Build -> Linker,
then in the Libraries section click on the browse button [...] then in the new window click on Add Library...
Then add fann library (for example my fann library path is: /usr/local/lib/libfann.a) and click Ok
A fellow helped me, and we came to this line that compiled everything, and make the executable:
$ gcc fann/fann.c fann/fann_io.c fann/fann_train.c fann/fann_train_data.c fann/fann_error.c fann/fann_cascade.c main.c -Ifann/include -lm
And this is the answer.
That said, this is exactly what fixedfann.c is doing (include all this .c files). But if I try:
$ gcc fann/fixedfann.c main.c -Ifann/include -lm
..I get:
undefined reference to `fann_train_on_file'
This fann_train_on_file is on fann_train_data.c, which is included by fixedfann.c, so why it is undefined? I don't know... :/
--update
I realized that:
$ gcc fann/fixedfann.c main.c -Ifann/include -lm
will work if I comment the headers on fixedfann.c:
//#include "config.h"
//#include "fixedfann.h"
#include "fann.c"
#include "fann_io.c"
#include "fann_train.c"
#include "fann_train_data.c"
#include "fann_error.c"
#include "fann_cascade.c"

Trouble with implementing a basic Makefile in c

Okay so I need to make a basic Makefile for a program I wrote. Here are the files:
list.c
hash.c
order_book.c
libdefault_hash.a //provided already so I do not need to create.
I need to create libraries for list.c and hash.c so that orderbook can use them when it compiles. So this is what I currently have in Makefile:
all: orderbook
orderbook: orderbook.c liblist.a libhash.a
gcc -std=c99 -o orderbook order_book.c list.c -L. -llist -lhash -libdefault_hash
liblist.a: list.c
gcc -std=c99 -c list.c
ar rcu liblist.a list.o
libhash.a: hash.c
gcc -std=c99 -c hash.c
ar rcu libhash.a hash.o
My understanding of how makefiles work is very small but here is my thought process,
all: orderbook will mean that orderbook: will run.
orderbook.c will then compile, then the code will compile the libraries.
Once the libraries are compiled it will run:
gcc -std=c99 -o orderbook order_book.c list.c -L. -llist -lhash -libdefault_hash
And the result should be a simple program file named orderbook, but the terminal prints out:
$ make
gcc -std=c99 -o orderbook order_book.c list.c hash.c -L. -llist -lhash -libdefault_hash
/usr/lib/gcc/x86_64-pc-linux-gnu/4.6.3/../../../../x86_64-pc-linux-gnu/bin/ld: skipping incompatible ./liblist.a when searching for -llist
/usr/lib/gcc/x86_64-pc-linux-gnu/4.6.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -llist
/usr/lib/gcc/x86_64-pc-linux-gnu/4.6.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -libdefault_hash
collect2: ld returned 1 exit status
make: *** [orderbook] Error 1
$
Any help/guidance is much appreciated.
Let's take this in small steps. First, here's a sequence of commands that looks like what you have in mind:
gcc -std=c99 -c list.c -o list.o
ar rcu liblist.a list.o
gcc -std=c99 -c hash.c -o hash.o
ar rcu libhash.a hash.o
gcc -std=c99 -o orderbook order_book.c -L. -llist -lhash -libdefault_hash
Try these commands without Make, and see which ones work (are you sure "rcu" shouldn't be "-rcu"?). Tell us the results either by commenting on this answer or editing your question. Once any of these commands works, we can start writing the makefile.

Compiling to 32-bit using make

I am trying to compile a very simple program using the -m32 flag.
If I try to do this using gcc -m32 it works just fine(I have the needed libs)
Yet, when I add this flag to my flags in a makefile, I get a weird error
This is the makefile that I have
CC=gcc
CFLAGS=-m32 -O1 -W -Wall -pedantic -std=c99
all: main.o
$(CC) -o main main.o
rm main.o
clean:
rm main
The error that I receive is the following
gcc -o main main.o
/usr/bin/ld: i386 architecture of input file `main.o' is incompatible with i386:x86-64 output
collect2: ld returned 1 exit status
make: *** [all] Error 1
Can someone please tell me what does this mean? and how can I fix it?
As for the code, the code does NOTHING except printing 'hello world'
I am using GCC 4.4.3 under Linux 2.6.35 64-bits
Your mistake is that you don't pass -m32 to the linker.
You actually need to change your Makefile to look like this:
CC=gcc
CFLAGS=-m32 -O1 -W -Wall -pedantic -std=c99
LDFLAGS = -m32
all: main.o
$(CC) $(LDFLAGS) -o main main.o
rm main.o
clean:
rm main
An even better approach would be the following Makefile:
CC=gcc
CFLAGS=-m32 -O1 -W -Wall -pedantic -std=c99
LDFLAGS=-m32
.INTERMEDIATE: main.o
all: main
main: main.o
clean:
-rm main
In the later you just say that main depends on main.o and GNU Make will invoke the linker with the LDFLAGS as arguments for you as it invokes the compiler with the CFLAGS as arguments for the main.o
"The targets which .INTERMEDIATE depends on are treated as intermediate files. See section Chains of Implicit Rules. .INTERMEDIATE with no dependencies marks all file targets mentioned in the makefile as intermediate." Special Built-in Target Names
You should inform the linker as well about the architecture being 32-bit. Try adding
LD = $(CC)
LDFLAGS = -m32
to your Makefile and change
$(CC) -o main main.o
to
$(LD) $(LDFLAGS) -o main $^
and it shoud work.
(Why it worked? If you use GCC to compile and link your code in one step, all the relevant flags and options will be passed down not only to the compiler but to the linker as well.)

More GCC link time issues: undefined reference to main

I'm writing software for a Cortex-A8 processor and I have to write some ARM assembly code to access specific registers. I'm making use of the GNU compilers and related toolchains; these tools are installed on the processor board (Freescale i.MX515) with Ubuntu. I make a connection to it from my host PC (Windows) using WinSCP and the PuTTY terminal.
As usual I started with a simple C project having main.c and functions.s. I compile the main.c using GCC, assemble the functions.s using as and link the generated object files using once again GCC, but I get strange errors during this process.
An important finding -
Meanwhile, I found out that my assembly code may have some issues because when I individually assemble it using the command as -o functions.o functions.s and try running the generated functions.o using ./functions.o command, the Bash shell is failing to recognize this file as an executable (on pressing tab functions.o is not getting selected/PuTTY is not highlighting the file).
Can anyone suggest what's happening here? Are there any specific options I have to send, to GCC during the linking process? The errors I see are strange and beyond my understanding, I don't understand to what the GCC is referring.
I'm pasting here the contents of main.c, functions.s, the Makefile and the list of errors.
Help, please!!!
**Latest errors included after the makefile was edited as suggested here **
ubuntu#ubuntu-desktop:~/Documents/Project/Others/helloworld$ make
gcc -c -mcpu=cortex-a8 main.c
as -mcpu=cortex-a8 -o functions.o functions.s
gcc -o hello main.o functions.o
functions.o: In function `_start':
(.text+0x0): multiple definition of `_start'
/usr/lib/gcc/arm-linux-gnueabi/4.3.3/../../../crt1.o:init.c:(.text+0x0): first defined here
collect2: ld returned 1 exit status
make: *** [hello] Error 1
main.c
#include <stdio.h>
#include <stdlib.h>
int main(void) {
puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */
return EXIT_SUCCESS;
}
functions.s
* Main program */
.equ STACK_TOP, 0x20000800
.text
.global _start
.syntax unified
_start:
.word STACK_TOP, start
.type start, function
start:
movs r0, #10
movs r1, #0
.end
Makefile
all: hello
hello: main.o functions.o
gcc hello -o main.o functions.o
-- hello was included here after suggested here by guys at Stack Overflow, but the problem still persists; I still get the same errors.
main.o: main.c
gcc -c -mcpu=cortex-a8 main.c
functions.o: functions.s
as -mcpu=cortex-a8 -o functions.o functions.s
Errors
ubuntu#ubuntu-desktop:~/Documents/Project/Others/helloworld$ make
gcc -c -mcpu=cortex-a8 main.c
as -mcpu=cortex-a8 -o functions.o functions.s
gcc -o main.o functions.o
functions.o: In function `_start':
(.text+0x0): multiple definition of `_start'
/usr/lib/gcc/arm-linux-gnueabi/4.3.3/../../../crt1.o:init.c:(.text+0x0): first defined here
/usr/lib/gcc/arm-linux-gnueabi/4.3.3/../../../crt1.o: In function `_start':
init.c:(.text+0x30): undefined reference to `main'
collect2: ld returned 1 exit status
make: *** [hello] Error 1
In the makefile:
hello: main.o functions.o
gcc -o main.o functions.o
should be:
hello: main.o functions.o
gcc -o hello main.o functions.o
As it stands, you are linking functions.o, but not main.o, and producing an output executable called main.o, which is overwriting your existing main.o.
Shouldn't
hello: main.o functions.o
gcc -o main.o functions.o
be
hello: main.o functions.o
gcc -o hello main.o functions.o
As Bigbohne suggests, gcc is trying to link in the standard runtime library. Try adding the -nostdlib option to your gcc call:
gcc -nostdlib -o hello main.o functions.o
I think that has something to do with the Runtime library the gcc is linking at the end.
And in this library there already is a "_start".
I think you have to compile without "std library". but than you wont have printf,getchar and all the other useful stuff.
Normally execution of a program compiled with gcc starts in the function called _start (in a startup file provided by gcc), which calls main.
If you are supplying your own _start, you should pass -nostdlib to gcc when linking. This disables all default startup files and all default libraries. You should therefore also explicitly provide any libraries you need such as libc and libgcc.
Your _start however does not call main, so it is unclear why you bother to provide main and the .c file at all.
gcc -o main.o functions.o is a mistake, it should be gcc -o main main.o functions.o, but this will not fix the problem described above.

Resources