How to link math.h library in a makefile? - c

i need to compile 3 files- part1.c, part2.c, and part3.c in a makefile.
only part3.c needs to use the <math.h> library.
Before a makefile, this is what the gcc commands will look like:
gcc -g -o part1 part1.c
gcc -g -o part2 part2.c
gcc -g -o part3 part3.c -lm
When i try to use a makefile to run the "make" command, i keep getting errors and it does not recognize any of the math functions from the math.h library.
This is what i have in my makefile so far that is not working:
CC = gcc
CFLAGS = -Wall -g
all: driver1
clean:
rm -f *.o driver1
part1.o: part1.c
$(CC) $(CFLAGS) -c part1.c
part2.o: part2.c
$(CC) $(CFLAGS) -c part2.c
part3.o: part3.c
$(CC) $(CFLAGS) -c part3.c -lm
driver1: part1.o part2.o part3.o
$(CC) $(CFLAGS) -o driver1 part1.o part2.o part3.o
i had tried to run the makefile i provided, but it was giving me errors. any help will be appreciated

part3.o does not need to link with the library although it uses its header file. You need the library when linking everything into driver1:
# ...
part3.o: part3.c
$(CC) $(CFLAGS) -c part3.c
driver1: part1.o part2.o part3.o
$(CC) $(CFLAGS) -o driver1 part1.o part2.o part3.o -lm

Related

Makefile does not make all targets

I am trying to have the compiled obj files in two different folder
dobjects: where the objects have the debug symbol (gcc with -g option)
sobjects: where the objects are compiled without the debug symbols.
Source files are the same,
I have the following makefile.
CC = gcc
CFLAGS = -Wall
OBJS = a.o b.o
SRCS = a.c b.c
SOBJS_DIR = sobjects
DOBJS_DIR = dobjects
SOBJS = $(addprefix $(SOBJS_DIR)/, $(OBJS))
DOBJS = $(addprefix $(DOBJS_DIR)/, $(OBJS))
all: release debug
release: $(SOBJS)
debug: $(DOBJS)
$(DOBJS_DIR)/%.o: CFLAGS += -g
$(DOBJS_DIR)/%.o $(SOBJS_DIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
clean:
rm dobjects/*
rm sobjects/*
But every time I try "make" only one target is made.
$ make
gcc -Wall -c a.c -o sobjects/a.o
gcc -Wall -c b.c -o sobjects/b.o
$ make
gcc -Wall -g -c a.c -o dobjects/a.o
gcc -Wall -g -c b.c -o dobjects/b.o
any help would be greatly appreciated
This rule does not do what you think it does:
$(DOBJS_DIR)/%.o $(SOBJS_DIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
Pattern rules with multiple targets tell make that one single invocation of the recipe will build BOTH targets. So when make runs that rule to build $(DOBJS_DIR)/a.o, make believes that $(SOBJS_DIR)/a.o was also built, so it doesn't try to run the rule to build it. But your rule doesn't actually build it, so when you run make a second time it sees that object file is missing and runs the above rule again, to build the missing one.
You have to write this as two different rules:
$(DOBJS_DIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
$(SOBJS_DIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#

"make clean" causes "make all" failure

When I execute this Makefile without clean, it functions OK and both the shared library and the main executable are created correctly. However, when I add the clean target, the "make all" fails. What could be the reason?
CC = gcc
CFLAGS = -fPIC -Wall -Werror
LDFLAGS = -shared
TARGET_LIB= libnsd.so
lib: nsd.o nd.o
$(CC) $(LDFLAGS) -o ${TARGET_LIB} nsd.o nd.o -lm
nd.o : nd.c nd.h
$(CC) -c $(CFLAGS) nd.c
nsd.o : nsd.c nsd.h
$(CC) -c $(CFLAGS) nsd.c
all: main.c
$(CC) -o -I. -L. main.c -lnsd
clean:
rm -f libnsd.so nd.o nsd.o
Your all: target needs to depend on the lib target, so the library is built first.
The -o argument to the compiler also needs a name for executable it should create.
all: lib main.c
$(CC) -o main -I. -L. main.c -lnsd
Normally you want the target name to be the file that you create, otherwise things get rebuilt when it's not needed. (the lib: target has the same issue) but as an exampe for the executable:
.PHONY: all
all: lib main
main: lib main.c
$(CC) -o main -I. -L. main.c -lnsd
nos's answer is on the right track.
It only appeared to work before, because you happened to run make in the right order. It won't work after a clean operation because, as nos points out, you have not declared all of your prerequisites. The rule that links main.o must depend on the shared library target, so make knows the right order to build things.
Also, you REALLY want your targets to be the actual file you're building. If they're something else, then make will always think they're out of date even if you haven't changed anything, and always rebuild them.
Something like this will be better:
CC = gcc
CFLAGS = -fPIC -Wall -Werror
CPPFLAGS = -I.
LDFLAGS = -shared
PROGRAM = main
TARGET_LIB= libnsd.so
all: $(PROGRAM)
$(PROGRAM): main.o $(TARGET_LIB)
$(CC) -o $# -L. main.o -lnsd
$(TARGET_LIB): nsd.o nd.o
$(CC) $(LDFLAGS) -o $# nsd.o nd.o -lm
nd.o : nd.c nd.h
nsd.o : nsd.c nsd.h
clean:
rm -f libnsd.so *.o

Make: Totally ignoring a rule

I am trying to compile my project after adding a new source(processHandling.c) and I am getting this as a result when I 'make'
gcc -gstabs -W -Wall -std=gnu99 -c main.c
gcc -gstabs -W -Wall -std=gnu99 -c inputHandling.c
gcc -gstabs -W -Wall -std=gnu99 -c syscallsWrapper.c
gcc -gstabs -W -Wall -std=gnu99 -o myShell main.o inputHandling.o processHandling.o syscallsWrapper.o
gcc: error: processHandling.o: No such file or directory
make: *** [myShell] Error 1
This is the makefile
CC = gcc
CFLAGS = -gstabs -W -Wall -std=gnu99
myShell: main.o inputHandling.o syscallsWrapper.o
$(CC) $(CFLAGS) -o myShell main.o inputHandling.o processHandling.o syscallsWrapper.o
main.o: main.c
$(CC) $(CFLAGS) -c main.c
inputHandling.o: inputHandling.c
$(CC) $(CFLAGS) -c inputHandling.c
processHandling.o: processHandling.c
$(CC) $(CFLAGS) -c processHandling.c
syscallsWrapper.o: syscallsWrapper.c
$(CC) $(CFLAGS) -c syscallsWrapper.c
clean:
-rm myShell *.o
I tried running make with the -d flag and it seems make for some reason is totally ignoring the rule to compile processHandling.o; what could the problem be?
Also note that if I compile processHandling manually using gcc -c everything works fine.
Add processHandling.o to the dependency list for the myShell target:
myShell: main.o inputHandling.o processHandling.o syscallsWrapper.o
$(CC) $(CFLAGS) -o myShell main.o inputHandling.o processHandling.o syscallsWrapper.o
By the way, using automatic variables can help reduce the repeated file names. For example:
myShell: main.o inputHandling.o processHandling.o syscallsWrapper.o
$(CC) $(CFLAGS) -o $# $^
You need to add "processHandling.o" as a prerequisit of myShell. Otherwise when making myShell, the rule for processHandling.o will not be applied because the makefile thinks that that processHandling.o is not needed for myShell. You can simply add it like this
myShell: main.o inputHandling.o syscallsWrapper.o processHandling.o
$(CC) $(CFLAGS) -o myShell main.o inputHandling.o processHandling.o syscallsWrapper.o
Check if you really have the file processHandling.c. This error implies that the source file has not been found.

math.h linkage with file

I have a small problem, and I have tried everything to test this function, could you please help me? I need to write a C file that is called "mutual_info.c", and it needs a mathematical function. I have included the library and linked it in the makefile, but it still gives me "undefined reference to log"... my includes look like this: (I'm using Eclipse on Ubuntu)
#include <stdio.h>
#include <stdlib.h>
#include "sample.h"
#include "graph_or.h"
#include <math.h>
and my makefile looks like this:
all:
gcc -g amostra.c sample.h -o amostra.o
gcc -g graph_or.c graph_or.h -o graph_or.o
gcc -g graph_w.c graph_W.h -o graph_W.o
gcc -g mutual_info.c -o mutual_info.o -lm
clean:
rm *.o
I have absolutely no idea what is going on, I have even tried to define the LDFLAGS before the command "all" and putting it like this:
LDFLAGS= -lm
all:
gcc -g amostra.c sample.h -o amostra.o
gcc -g graph_or.c graph_or.h -o graph_or.o
gcc -g graph_w.c graph_W.h -o graph_W.o
gcc -g mutual_info.c -o mutual_info.o -lm
clean:
rm *.o
But it still won't work!! Please anyone, I need help with this! Thanks!
Let's take this in steps.
The usual way to write a makefile is to have a rule for each target, and to use prerequisites:
thing: amostra.o graph_or.o graph_w.o mutual_info.o
gcc -g amostra.o graph_or.o graph_w.o mutual_info.o -o thing -lm
mutual_info.o: mutual_info.c
gcc -g -c mutual_info.c -o mutual_info.o -lm
amostra.o: amostra.c sample.h
gcc -g -c amostra.c -o amostra.o
graph_or.o: graph_or.c graph_or.h
gcc -g -c graph_or.c -o graph_or.o
graph_w.o: graph_w.c graph_w.h
gcc -g -c graph_w.c -o graph_w.o
mutual_info.o: mutual_info.c
gcc -g -c mutual_info.c -o mutual_info.o -lm
(I have guessed that you want the executable to be called thing, and that you meant graph_w, not graph_W.)
That should work, but we can make it tidier. First we introduce automatic variables:
thing: amostra.o graph_or.o graph_w.o mutual_info.o
gcc -g $^ -o $# -lm
mutual_info.o: mutual_info.c
gcc -g -c $< -o $#
amostra.o: amostra.c sample.h
gcc -g -c $< -o $#
graph_or.o: graph_or.c graph_or.h
gcc -g -c $< -o $#
graph_w.o: graph_w.c graph_w.h
gcc -g -c $< -o $#
mutual_info.o: mutual_info.c
gcc -g -c $< -o $#
Then we see that these recipes use the same command, so we create a pattern rule:
thing: amostra.o graph_or.o graph_w.o mutual_info.o
gcc -g $^ -o $# -lm
amostra.o: sample.h
graph_or.o: graph_or.h
graph_w.o: graph_w.h
%.o: %.c
gcc -g -c $< -o $#
Give this a try and tell us if it works.
Is that a snippet from your Makefile? Hav you tried exporting LDFLAGs? I have seen this error before, but it was always fixed with the -lm flag.
gcc -lm -o blah blah.c
you need to:
gcc -c -o amostra.o amostra.c
gcc -c -o graph_or.o graph_or.c
gcc -c -o graph_w.o graph_w.c
gcc -c -o mutual_info.o mutual_info.c
gcc -o YourExecutableName amostra.o graph_or.o graph_w.o mutual_info.o -lm
Here's a generic makefile using my best guess of what you want to achieve: It compiles all *.c files in the current directory and creates a binary mutual_info.
RM := rm -f
CC := gcc
CFLAGS := -g
LDLIBS := -lm
SOURCES := $(wildcard *.c)
OBJECTS := $(SOURCES:%.c=%.o)
DEPS := $(SOURCES:%.c=%.d)
BINARY := mutual_info
FILES_TO_CLEAN := $(OBJECTS) $(DEPS)
.PHONY : all clean realclean
all : $(BINARY)
clean :
$(RM) $(FILES_TO_CLEAN)
realclean : FILES_TO_CLEAN += $(BINARY)
realclean : clean
-include $(DEPS)
$(OBJECTS) : %.o : %.c
$(CC) $(CFLAGS) -c -MMD -o $# $<
$(BINARY) : $(OBJECTS)
$(CC) -o $# $^ $(LDLIBS)
Please clarify if that's not what you want.

how to write a simple makefile for c

I need to write a simple make file for my.c, and so after
make
then my program can be run by
./my
my.c can be compiled by this:
gcc cJ/cJ.c my.c -lcrypto -o my -lm
Thanks
I put this in my makefile
all:my
my: cJ.o my.o
gcc cJ.o -lcrypt my.o -o my
cJ.o: cJ/cJ.c
gcc -c cJ/cJ.c
my.o: my.c
gcc -c my.c -lm
help please
Well, makefiles are just kind of special scripts. Every is unique, for such simple task this would be sufficient:
Makefile:
CC=gcc
CFLAGS=-lm -lcrypto
SOURCES=my.c cJ/cJ.c
all: my
my: $(SOURCES)
$(CC) -o my $(SOURCES) $(CFLAGS)
Later you may want to use some other options such as wildcards %.c to compile in multiple files without having to write them in.
Alternatively:
CC=gcc
CFLAGS=-lm -lcrypto
MY_SOURCES = my.c cJ/cJ.c
MY_OBJS = $(patsubst %.c,%.o, $(MY_SOURCES))
all: my
%o: %.c
$(CC) $(CFLAGS) -c $<
my: $(MY_OBJS)
$(CC) $(CFLAGS) $^ -o $#
Note that lines following each target ("my:", ...) must start with tab (\t), not spaces.
Just a minor correction: put the -lm to the linking step, and there after all object files.
all: my
my: cJ.o my.o
gcc cJ.o my.o -o my -lcrypt -lm
cJ.o: cJ/cJ.c
gcc -c cJ/cJ.c
my.o: my.c
gcc -c my.c
And then, you could work more with automatic variables:
all: my
my: cJ.o my.o
gcc $^ -o $# -lcrypt -lm
cJ.o: cJ/cJ.c
gcc -c $^
my.o: my.c
gcc -c $^
where $# is the target of the current rule and $^ are the prerequisites.
See also http://www.gnu.org/software/make/manual/make.html.
simple make file for your program is
build :
gcc /your_full_path_to_c_file/cJ.c my.c -lcrypto -o my -lm
just copy this in one file keep name of that file as makefile
then run as make build

Resources