2

I have just started learning about makefile files. I created a program that consists of two functions and wanted to use a makefile to put it all together. This is my file:

#Makefile

all: main

main: main.o find_root.o
    clang -o main main.o find_root.o

main.o: main.c
    clang -c -Wall --pedantic -std=c11 main.c -lm

find_root.o: find_root.c
    clang -c -Wall --pedantic -std=c11 find_root.c -lm

clean: rm -f main *.o*

However, when I run this, I get an error - "undefined reference to cos". I am using the cosine functions in my program, but I have already linked the library to the compilation of those two files. I thought about adding "-lm" to the first clang option as well. This led to no errors, but it made a warning instead - saying that "-lm linker is unused". What should I change in my file?

Aemilius
  • 556
  • 1
  • 6
  • 13
  • 2
    You don't link with libraries when creating the object files, but when you create (and *link*) the executable. – Some programmer dude Dec 12 '17 at 09:41
  • Possible duplicate of [What is an undefined reference/unresolved external symbol error and how do I fix it?](https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – underscore_d Dec 12 '17 at 09:51
  • Remove all `-lm`s and then change `clang -o main main.o find_root.o` to `clang -lm -o main main.o find_root.o`. – Jabberwocky Dec 12 '17 at 10:08
  • @MichaelWalz I'm not sure about clang, but for some linker front-ends you would need to put the `-lm` option after the `.o` files like this: `clang -o main main.o find_root.o -lm`. – Ian Abbott Dec 12 '17 at 10:17
  • 1
    There is a mistake in the `clean:` rule in the Makefile. It currently has the command part of the rule where the target dependencies should go. Move the `rm` command onto the next line, indented, to fix it. – Ian Abbott Dec 12 '17 at 10:23

2 Answers2

4

The "-lm" is a linker option but you have only included it in your compilation rule (main.o: main.c). You need to include it in your linker rule (main: main.o find_root.o).

As it stand the -lm option is ignored during compilation and missing during linking.

doron
  • 27,972
  • 12
  • 65
  • 103
1

The linker flags aren't used when compiling, but when linking, so the command for the main rule should have -lm, rather than the command for the *.o files.

Better would be just to set the appropriate variables, and let Make use its built-in rules:

#Makefile

LDLIBS += -lm
CFLAGS += -Wall --pedantic -std=c11
C = clang

all: main

main: main.o find_root.o
    $(LINK.c) $^ $(LDLIBS) -o $@

clean:
    $(RM) main *.o *~
Toby Speight
  • 27,591
  • 48
  • 66
  • 103