simple Makefile for c program - c

I have this (working) Makefile for single-file C-Application.
all: simpleua
simpleua: simpleua.c
$(CC) -o $# $< `pkg-config --cflags --libs libpjproject`
now I want to extend this Makefile for a multiple-file C-Application.
The files are main.c simpleua.c simpleua.h
I have found some samples on the Internet but nothing simple and working with pkg-config
Thanks alot
florian

This is simple example Makefile for you
CC = gcc
XX = g++
CFLAGS = -g
INC := -I test.h
$(LIBS)
TGT = ./sample
OUTPUT = ../output/
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
SOURCES = $(wildcard *.c *.cpp)
OBJS = $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCES)))
$(TGT) : $(OBJS)
$(CC) $(OBJS) -o $(TGT)
chmod 777 $(TGT)
cp $(TGT) $(OUTPUT)
clean:
rm -rf *.o *~ $(OUTPUT)/*
It works for both C and C++ for this you just need change from CC to XX.
For example purpose i have two directory as in Makefile
1)sample
2)output
In sample directory all my source resides and in output folder my final binary copied (you can give any name to directory as you want but make sure you also give same name in Makefile ).so you can put as many source file in sample directory and able to compile it.

This may take a few iterations (and you've left out a lot of details). Try this:
all: simpleua
simpleua: simpleua.o main.o
$(CC) -o $# $^ `pkg-config --cflags --libs libpjproject`
simpleua.o main.o: %.o: %.c simpleua.h
$(CC) -c -o $# $< `pkg-config --cflags --libs libproject`
EDIT: second try (with thanks to Jonathan Leffler). The use of --libs in the pattern rule may be unnecessary, but try it and see.

Related

How do I write a "selective" Makefile?

noob question here.
I have a directory with a lot of .c files, they're basicely libc functions that I code myself as an exercice.
I write a little main() in these files to test the functions, and I want to write a Makefile that allow me to compile only the file I want to test, for exemple:
make memset.c
And get only the executable of the code wrote in memset.c.
I tried to do something like this:
CC = gcc
CFLAGS = -Wall -Wextra -pedantic
all : %.o
$(CC) $(CFLAGS) $<
%.o : %.c
$(CC) $(CFLAGS) $< -c -o $#
But obviously it doens't work. I don't what to put in place of the "all".
I know it's very basic, but I didn't manage to do it, and I did research but didn't find an answer to this specific question.
Thanks in advance for your help.
If you do make -n -p you get a dump of all of the built-in rules in make. In GNU Make 4.1, this includes:
%: %.o
# recipe to execute (built-in):
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $#
So you might just needs a % in your makefile where you currently have all.
You also might find that you don't need those rules which are already built in. Suppose you have three C files, each with a main() as you specify: abs.c, div.c and fmax.c. Your Makefile needs to be no more than two lines:
CFLAGS = -Wall -Wextra -pedantic
all: abs div fmax
which would then allow you to do make abs to make the abs executable, and make all to make them all.
You can define static pattern rules to build the object files and the executables and then invoke make with the name of the executable you want as the goal:
CC = gcc
CFLAGS = -Wall -Wextra -pedantic
SRC := $(wildcard *.c)
OBJ := $(patsubst %.c,%.o,$(SRC))
EXE := $(patsubst %.c,%,$(SRC))
.PHONY: all obj
all: $(EXE)
obj: $(OBJ)
$(EXE): %: %.o
$(CC) $(LDFLAGS) $< -o $#
$(OBJ): %.o: %.c
$(CC) $(CFLAGS) $< -c -o $#
.PHONY: clean
clean:
rm -f $(OBJ) $(EXE)
Then:
$ make memset.o
builds only memset.o,
$ make memset
builds only memset (and memset.o if needed),
$ make obj
builds all object files,
$ make # or make all
builds all executables (and object files if needed), and
$ make clean
deletes all executables and object files.
With wildcard, you can achieve what you want.
Note that if each program depends on only one .c file, you don't need %.o rules:
CC = gcc
CFLAGS = -Wall -Wextra -pedantic
SRC := $(wildcard *.c)
EXEC = $(SRC:%.c=%)
all: $(EXEC)
%: %.c
$(CC) $(CFLAGS) $< -o $# $(LDFLAGS)
And just invoke this way for instance:
make memset
You already have most you to compile the executable selectively:
CC = gcc
CFLAGS = -Wall -Wextra -pedantic
%.o : %.c
$(CC) $(CFLAGS) $< -c -o $#
% : %.o
$(CC) $(LDLAGS) $< -o $#
Then you just need to call make with the target you want, the executable:
make select
If you have several sets of executable with different flags, you can use:
EX0 = drink clean
${EXE0}: % : %.o
$(CC) $(LDLAGS) -lwater $< -o $#
EX1 = burn melt
{EX1}: % : %.o
$(CC) $(LDLAGS) -lfire $< -o $#

makefile not updating .o file with respectively with .h file

I have following make file :-
VER = Debug
CC = gcc
objectfiles = Getstr.o ui.o ustreqsol.o main.o
pkg = `pkg-config --cflags --libs gtk+-3.0`
obj = $(addprefix objs/,$(objectfiles))
../$(VER)/Calculator: $(obj)
$(CC) -o $# $(obj) $(pkg)
./objs/ui.o:ui.c
$(CC) -c -o $# $< $(pkg)
./objs/main.o:main.c
$(CC) -c -o $# $< $(pkg)
./objs/%.o: %.c %.h
$(CC) -c -o $# $<
clean:
-rm ../$(VER)/Calculator
-rm /objs/*
and follwing files in my src dir:-
$ ls
Getstr.c main.c Makefile objs ui.c ui.h ustreqsol.c ustreqsol.h
objs is directory. Whenver I change ustreqsol.h file it compiles ustreqsol.c file but not in case for ui.h file
$ touch ustreqsol.h
$ make
gcc -c -o objs/ustreqsol.o ustreqsol.c
gcc -o ../Debug/Calculator objs/Getstr.o objs/ui.o objs/ustreqsol.o objs/main.o `pkg-config --cflags --libs gtk+-3.0`
$ make
make: '../Debug/Calculator' is up to date.
$ touch ui.h
$ make
make: '../Debug/Calculator' is up to date.
As a noob in makefiles i have no idea why is this happening
The reason ui.c is not being rebuilt is because you explictly said ui.h is not a dependency:
./objs/ui.o:ui.c
$(CC) -c -o $# $< $(pkg)
For the general dependency you have set up:
./objs/%.o: %.c %.h
$(CC) -c -o $# $<
The dependency list only takes effect for files that you didn't explicitly set them for, such as ustreqsol.c.
You need to add targets for each object file specifying the dependencies for each one. The targets can be blank, as the %.o target will fill in what to do.
For example:
./objs/ustreqsol.o: ustreqsol.c ustreqsol.h ui.h
./objs/ui.o: ui.c ui.h
./objs/main.o: main.c ui.h ustreqsol.h
./objs/Getstr.o: Getstr.c
./objs/%.o: %.c %.h
$(CC) -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

Adapt Makefile for cross-compilation

I have a makefile that works fine when I compile using /usr/bin/gcc to compile it. However I'm trying to compile it using a crosstool-ng compiler. I've changed CC to the cross-compilers location, and added a prefix to the directory that holds the compiler, but I get an error compiling.
The Makefile is here (sorry, it's long):
CFLAGS ?= -Wall -O0 -ggdb3
PREFIX = /home/me/crosstool-ng-1.18.0/x-tools/i586-system-linux-gnu/
CC = /home/me/crosstool-ng-1.18.0/x-tools/i586-system-linux-gnu/bin/i586-system-linux-gnu-gcc
ALL_CFLAGS = $(CFLAGS) -D_GNU_SOURCE
.phony: all
all: food libfood.so.1.0.0 foo_query
.phony: tools
tool tools: libfood_print foo_print
.phony: install
install: libfood.so.1.0.0
cp libfood.so.1.0.0 $(PREFIX)/lib
cd $(PREFIX)/lib ; \
ln -sf libfood.so.1.0.0 libfood.so.1 ; \
ln -sf libfood.so.1 libfood.so
cp libfood.h $(PREFIX)/include
cp foo_data.h $(PREFIX)/include
cp food $(PREFIX)/bin
cp foo_query $(PREFIX)/bin
%.o: %.c
$(CC) $(ALL_CFLAGS) -c $<
food: food.o foo.o
$(CC) $(ALL_CFLAGS) -o $# $^ -lm -lpthread
libfood.so.1.0.0: libfood.o
$(CC) -shared -Wl,-soname,libfood.so.1 -o libfood.so.1.0.0 libfood.o
libfood_print: libfood_print.o
$(CC) $(ALL_CFLAGS) -o $# $^ -lfood
foo_print: foo_print.o foo.o
$(CC) $(ALL_CFLAGS) -o $# $^ -lm -lpthread
foo_query: foo_query.o
$(CC) $(ALL_CFLAGS) -o $# $^ -lfood
food.o: food.c foo.h foo_data.h
foo.o: foo.c foo.h foo_data.h
foo_print.o: foo_print.c foo_data.h
foo_query.o: foo_query.c foo_data.h
libfood.o: libfood.c libfood.h
$(CC) $(ALL_CFLAGS) -fPIC -c $<
foo_print.o: foo_print.c foo.h
.phony:clean
clean:
rm -rf *.o *~ food libfood.so.1.0.0 foo_print libfood_print foo_query
The error message I'm getting says cannot find -lfood
collect2: ld returned 1 exit status
If anyone could suggest a fix for this I'd be very grateful.
EDIT: My Solution:
I should probably have been clearer but this Makefile was being used to build a package that was included in buildroot. I tried the suggestion by Jonatan, but unfortunately I still got the same error. My workaround was to run buildroot using make -k, and then build again using make.
An easy way to solve this would be:
ALL_CFLAGS += -L$(PREFIX)/lib
If you really want to install your lib in the toolchain, you should look for the usr/lib directory, usually the path is TOOLCHAIN_DIR/TOOLCHAIN_PREFIX/sysroot/usr/lib
Check other binaries in the $(PREFIX)/lib directory, you will notice that they were compile to run in you host, and not in your target.
The files the compiler need to check dependencies, link, and execute in your target, are installed in the sysroot directory.

How to use makefile to compile all sources (some only to object files)?

I'm getting an "undefined reference to main" error on one of my files when trying to compile. I know this is because this file doesn't have a main method. This is just an implementation file for some helper methods, so I only want it compiled to an object file not an executable. I know how to do this if I explicitly tell the makefile what to do for each file, but I'm trying to write a makefile that will compile all of my sources at once. I tried using the -c flag, but then it compiled all of my files to only object files rather than executables. How in the world do I do this?
Here it is:
CC = gcc
CFLAGS = -g -Wall
SRCS = ./src/server.c ./src/client_slave.c ./src/sockaddrAL.c
EXECS = ./bin/server ./bin/client_slave
OBJS = $(SRCS:.c=.o)
all: clean $(SRCS) server client
server: $(OBJS)
$(CC) $(CFLAGS) ./src/server.o -o ./bin/server
client: $(OBJS)
$(CC) $(CFLAGS) ./src/client_slave.o -o ./bin/client_slave
.c.o:
$(CC) $(CFLAGS) -c $< -o $#
clean:
#rm -f $(EXECS) $(OBJS)
You should add the -c flag to the rule that builds .o files (your .c.o suffix rule) and not add it to the rule that builds the executables (the $(EXECS) rule).
CC = gcc
CFLAGS = -g -Wall
EXECS = ./bin/server ./bin/client_slave
all: $(EXECS)
./bin/%: ./src/%.o ./src/sockaddrAL.o
$(CC) $(CFLAGS) -o $# $^
.c.o:
$(CC) $(CFLAGS) -c $< -o $#
clean:
#rm -f $(EXECS) $(OBJS)
You didn't show sockAddrAL at all in your question so I assumed it belonged in both executables. Also note that the above syntax assumes GNU make. If you want to use only features available in POSIX standard make you pretty much have to write it all out.
Let implicit rules be your friend. Your entire Makfefile should just be:
CC = clang
CFLAGS = -O0 -g -Wall
SRCS = server.c client_slave.c sockaddrAL.c
OBJS = $(SRCS:.c=.o)
EXECS = server
server: $(OBJS)
clean:
#rm -f $(EXECS) $(OBJS)
Invoke it from the src directory.

Resources