2
\$\begingroup\$

I'm working on a project that will have both a server and a client, using Boost's ASIO library for networking. I'm not really comfortable working with Makefiles, but, with some help from Chase Lambert's https://makefiletutorial.com/#makefile-cookbook and other things I found online I got the following Makefile:

BUILD_DIR := ./build
INC_DIRS := ./include
SRC_DIRS := ./src
SERVER_TARGET_EXEC := server
CLIENT_TARGET_EXEC := client
TARGETS := $(BUILD_DIR)/$(SERVER_TARGET_EXEC) $(BUILD_DIR)/$(CLIENT_TARGET_EXEC)
# Find all the C and C++ files we want to compile
# For SRCS we exclude files inside the src/server and src/client directories
SRCS := $(shell find $(SRC_DIRS) \( -name "*.cpp" -or -name "*.c" \) ! \( -path '*/server/*' -or -path '*/client/*' \))
SERVER_SRCS := $(shell find $(SRC_DIRS)/server -name *.cpp -or -name *.c)
CLIENT_SRCS := $(shell find $(SRC_DIRS)/client -name *.cpp -or -name *.c)
# String substitution for every C/C++ file.
# As an example, hello.cpp turns into ./build/hello.cpp.o
OBJS := $(SRCS:%=$(BUILD_DIR)/%.o)
SERVER_OBJS := $(SERVER_SRCS:%=$(BUILD_DIR)/%.o)
CLIENT_OBJS := $(CLIENT_SRCS:%=$(BUILD_DIR)/%.o)
ALL_OBJS := $(SUDOKU_OBJS) $(SERVER_OBJS) $(CLIENT_OBJS)
# String substitution (suffix version without %).
# As an example, ./build/hello.cpp.o turns into ./build/hello.cpp.d
DEPS := $(ALL_OBJS:.o=.d)
# Every folder in ./src will need to be passed to GCC so that it can find header files
INC_DIRS += $(shell find $(SRC_DIRS) -type d ! \( -path '*/server' -or -path '*/client' \))
# Add a prefix to INC_DIRS. So moduleA would become -ImoduleA. GCC understands this -I flag
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
# The -MMD and -MP flags together generate Makefiles for us!
# These files will have .d instead of .o as the ouput
CPPFLAGS := $(INC_FLAGS) -MMD -MP -g
CPPFLAGS += -g
CPPFLAGS += -Wall -Wextra
CPPFLAGS += -Wpedantic -Warray-bounds -Weffc++
CPPFLAGS += -Werror
# For Boost ASIO we need to link against Boost Thread and Boost System
LDFLAGS := -pthread
LDFLAGS += -lboost_thread -lboost_system
all: $(TARGETS)
$(BUILD_DIR)/$(SERVER_TARGET_EXEC): $(OBJS) $(SERVER_OBJS)
$(BUILD_DIR)/$(CLIENT_TARGET_EXEC): $(OBJS) $(CLIENT_OBJS)
# The final build step
$(TARGETS):
 $(CXX) $^ -o $@ $(LDFLAGS)
# Build step for C source
$(BUILD_DIR)/%.c.o: %.c
 mkdir -p $(dir $@)
 $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
# Build step for C++ source
$(BUILD_DIR)/%.cpp.o: %.cpp
 mkdir -p $(dir $@)
 $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
.PHONY: clean
clean:
 rm -r $(BUILD_DIR)
# Include the .d makefiles. The - at the front suppresses the errors of missing
# Makefiles. Initially, all the .d files will be missing, and we don't want those
# errors to show up
-include $(DEPS)

Any suggestions on what could be improved?

asked Aug 10, 2021 at 14:24
\$\endgroup\$
1
  • \$\begingroup\$ Is SUDOKU_OBJS a copy paste error? \$\endgroup\$ Commented Aug 11, 2021 at 3:01

1 Answer 1

1
\$\begingroup\$

Why are INC_DIRS and SRC_DIRS pluralized if they only contain one value each, and are treated that way throughout the rest of the makefile? These should be singular.

It looks like $(OBJS) is common to both executables, and is re-linked in each case. It would be (in most cases) better to represent this as a separate, dedicated link step that produces a .so shared object rather than static linking. This shared object file would be shipped beside both the server and client, and the size of the server and client binaries would be reduced.

Your

 mkdir -p $(dir $@)
 $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

would ideally be split up into two different make targets - one to make the directory, and the second depending on the directory and compiling the object.

SUDOKU_OBJS seems a likely error.

answered Aug 11, 2021 at 3:35
\$\endgroup\$
1
  • \$\begingroup\$ Thank you for your suggestions, I like the idea of compiling $(OBJS) as a shared object :) And yes, SUDOKU_OBJS was indeed a copy paste error, I forgot to change its name when modifying the code for my question :/ \$\endgroup\$ Commented Aug 11, 2021 at 13:59

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.