Robb1
Robb1

Reputation: 5025

How to write a single Makefile for a project with several folders?

I have the following project structure (I got this simply running $ tree src):

src
├── client
│   ├── client.c
│   ├── client_functions.c
│   ├── client_functions.h
├── common
│   ├── conf.c
│   ├── conf.h
│   ├── file_list.c
│   └── file_list.h
├── Makefile
└── server
    ├── server.c
    ├── server_functions.c
    └── server_functions.h

I want to have a single Makefile in the root src folder (therefore running a single $ make command for the whole project).

Here are dependencies (note that each *.c depends on the relative *.h):

I'm trying to write a Makefile but I keep getting errors. I never created one for such a complex project structure (usally everything was in a single folder). Here's the first part of the Makefile:

CC := /usr/bin/gcc
RM := /usr/bin/rm -f
CFLAGS := -Wall -Wextra -Wpedantic -O3

How should I write the rest of the Makefile?

Note that I want only 2 executables: client inside the client folder and server inside the server folder.

EDIT: taking in consideration @melpomene answer, I wrote the following Makefile

CC := gcc
CFLAGS := -Wall -Wextra -Wpedantic -O3
SRC := client/client.c client/client_functions.c client/client_functions.h server/server.c server/server_functions.c server/server_functions.h common/conf.c common/conf.h common/file_list.c common/file_list.h
OBJ := $(SRC:.c=.o)

.PHONY: all

all: client/client server/server

client/client: client/client.o client/client_functions.o common/conf.o

client/client.o: client/client.c client/client_functions.h
client/client_functions.o: client/client_functions.c client/client_functions.h common/conf.h

server/server: server/server.o server/server_functions.o common/conf.o common/file_list.o

server/server.o: server/server.c server/server_functions.h
server/server_functions.o: server/server_functions.c server/server_functions.h common/conf.h common/file_list.h

common/conf.o: common/conf.c common/conf.h
common/file_list.o: common/file_list.c common/file_list.h

clean:
        rm -f client/*.o server/*.o common/*.o core

cleanall:
        rm -f client/*.o server/*.o common/*.o core client/client server/server

That now results in the following output:

gcc -Wall -Wextra -Wpedantic -O3   -c -o client/client.o client/client.c
gcc -Wall -Wextra -Wpedantic -O3   -c -o client/client_functions.o client/client_functions.c
gcc -Wall -Wextra -Wpedantic -O3   -c -o common/conf.o common/conf.c
gcc   client/client.o client/client_functions.o common/conf.o   -o client/client
common/conf.o:(.rodata+0x0): multiple definition of `at'
client/client_functions.o:(.rodata+0x0): first defined here
common/conf.o:(.rodata+0x4): multiple definition of `T'
client/client_functions.o:(.rodata+0x4): first defined here
common/conf.o:(.rodata+0x8): multiple definition of `N'
client/client_functions.o:(.rodata+0x8): first defined here
common/conf.o:(.rodata+0x10): multiple definition of `p'
client/client_functions.o:(.rodata+0x10): first defined here
collect2: error: ld returned 1 exit status
<builtin>: recipe for target 'client/client' failed
make: *** [client/client] Error 1

at, T, N and p are all variables defined in conf.h

Upvotes: 0

Views: 103

Answers (1)

melpomene
melpomene

Reputation: 85757

Sounds like this is all you need:

.PHONY: all

all: client/client server/server

client/client: client/client.o client/client_functions.o common/conf.o

client/client.o: client/client.c client/client_functions.h
client/client_functions.o: client/client_functions.c client/client_functions.h common/conf.h

server/server: server/server.o server/server_functions.o common/conf.o common/file_list.o

server/server.o: server/server.c server/server_functions.h
server/server_functions.o: server/server_functions.c server/server_functions.h common/conf.h common/file_list.h

common/conf.o: common/conf.c common/conf.h
common/file_list.o: common/file_list.c common/file_list.h

I've listed all the dependencies you've described (modified by some educated guessing). The built-in implicit rules should do the rest.

Upvotes: 1

Related Questions