MrSquaare
MrSquaare

Reputation: 63

Makefile: Separated sources and objects

I've been trying for some time to separate the source files of my project from the generated object files.

Indeed, I would like my project to be structured this way:

obj/
    main.o
    src1.o
    [...]
src/
    main.c
    src1.c
    [...]
Makefile

The Makefile I currently have is as follows:

NAME                =       a.out

OBJ_DIR             =       "obj"
SRC_DIR             =       "src"

MAIN_SRC            =       main.c

PROJ_SRC            =       src1.c      \
                            src2.c      \
                            src3.c

MAIN_OBJ            =       $(MAIN_SRC:%.c=%.o)

PROJ_OBJ            =       $(PROJ_SRC:%.c=%.o)

CC                  =       gcc
RM                  =       rm -rf

$(NAME):            $(MAIN_OBJ) $(PROJ_OBJ)
                    $(CC) $(MAIN_OBJ) $(PROJ_OBJ) -o $(NAME)

all:                $(NAME)

clean:
                    $(RM) $(MAIN_OBJ) $(PROJ_OBJ)

fclean:             clean
                    $(RM) $(NAME)

I tried to use pattern rules, without success.

MAIN_OBJ            =       $(MAIN_SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)

PROJ_OBJ            =       $(PROJ_SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)

[...]

$(OBJ_DIR)/%.o:     $(SRC_DIR)/%.c
                    $(CC) $(CFLAGS) -c $< -o $@

Does anyone have a solution to my problem?

Upvotes: 1

Views: 322

Answers (2)

Vittore Marcas
Vittore Marcas

Reputation: 1215

bro!

If your project "main" 's architecture is just liking this:

main

|

|__Makefile

|__obj

|__src

     |__main.c
 
     |__src1.c

     |__src2.c

     [...]

Just add this to your "Makefile" to store your object out of source files directory:

# Object files
# String substituion for every C/C++ file
# e.g: ./src/src1.cpp turns into ./obj/src1.o
OBJS := $(patsubst %.c, ${OBJ_DIR}/%.o, $(notdir $(SRC_DIR)))

And just add this to your "Makefile" to compile:

# Compile: Generate object files from source files
# $@ := {NAME}
# $< := THE first file
# $^ all the dependency
# C Sources
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
    $(CC) $(C_FLAGS) -c $< -o $@

END!

Upvotes: 0

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136247

MAIN_SRC and PROJ_OBJ do not have directory prefix, so that expressions

$(MAIN_SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
$(PROJ_SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)

do not replace anything.

Fix:

MAIN_OBJ := $(MAIN_SRC:%.c=$(OBJ_DIR)/%.o)
PROJ_OBJ := $(PROJ_SRC:%.c=$(OBJ_DIR)/%.o)

And then your pattern rule should work.

You may like to have make create that $(OBJ_DIR) for you:

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
    $(CC) $(CFLAGS) -c -o $@ $<

$(OBJ_DIR) :
    mkdir -p $@

A more advanced example for you with automatic header dependency generation.

Upvotes: 1

Related Questions