How do I split the source file path when writing a compilation rule in a makefile?

In short: I want to compile sources from different directories and put the object files in the current directory.

For example, I have files:

test.c
../../lib1/boot.c
../../lib2/startup.c
../common/utils.c

(there are also few .s (assembly) and .cpp files, but I hope this is not important).

All their object files I want to be in the current directory:

test.o
boot.o
startup.o
utils.o

And I can’t understand how to write such a rule in my makefile.

For instance,

%o.: %.c

now it doesn’t work, because it makecannot find a rule for building boot.ofrom ../../lib1/boot.c, it can only find a rule for building ../../lib1/boot.ofrom ../../lib1/boot.c.

I tried using this:

%o.: %.c
 (my compilation line, for example "gcc -c $^ -o $@")
%o.: ../../lib1/%.c
 (my compilation line)
%o.: ../../lib2/%.c
 (my compilation line)
%o.: ../common/%.c
 (my compilation line)

. , , , , , , ../../some_other_lib/common_things.c, makefile . . . .

, : - , ( ) , ?

.

+5
3

, , , , ( , ):

# Defining compilation rules in a way that object files will be produced in current directory, and not in the directory of source files:
all: <List of my targets>

define my_c_rule
$(subst .c,.o,$(notdir $(1))): $(1)
    $(CC) $(CFLAGS) $(CDEFINES) $$^ -o $$@
endef
$(foreach f, $(CSRC), $(eval $(call my_c_rule, $(f))))

$(CSRC) .

, - :

.c.o:
    $(CC) $(CFLAGS) $(CDEFINES) $^ -o $@

all: <List of my targets>

... all , my_c_rule. , make . , " ", .c.o %.o: %.c, all ( ), , boot.o: ../../lib1/boot.c ( ) , .

+1

CSRC $(dir ...), vpath.

vpath %.c $(sort $(dir $(CSRC)))
vpath %.s $(sort $(dir $(SSRC)))
vpath %.cpp $(sort $(dir $(CPPSRC)))

( sort , .)

make .

$(COBJ) := $(notdir $(CSRC))
$(SOBJ) := $(notdir $(SSRC))
$(CPPOBJ) := $(notdir $(CPPSRC))

.PHONY: all
all: $(EXECUTABLE)

$(EXECUTABLE): $(COBJ) $(SOBJ) $(CPPOBJ)
    ....

$(COBJ): %.o: %.c
    ...

$(SOBJ): %.o: %.s
    ...

$(CPPOBJ): %.o: %.cpp
    ...
+3

Try using the makefile function notdirlike this:

%.o:    %.c
    gcc -c $< -o $(notdir $@)

$@should be equal to the full path ex: ../../lib2/startup.oad notdirconnect it with: startup.o.

With this rule, you can compile all the source code in the current directory.

Actually, your example is this:

.
└── common
    β”œβ”€β”€ lib1
    β”‚   └── boot.c
    β”œβ”€β”€ lib2
    β”‚   └── startup.c
    β”œβ”€β”€ test
    β”‚   β”œβ”€β”€ Makefile
    β”‚   └── test.c
    └── utils.c

I think I will be better:

.
β”œβ”€β”€ common
β”‚   β”œβ”€β”€ lib1
β”‚   β”‚   β”œβ”€β”€ Makefile
β”‚   β”‚   β”œβ”€β”€ obj
β”‚   β”‚   └── src
β”‚   β”‚       └── boot.c
β”‚   β”œβ”€β”€ lib2
β”‚   β”‚   β”œβ”€β”€ Makefile
β”‚   β”‚   β”œβ”€β”€ obj
β”‚   β”‚   └── src
β”‚   β”‚       └── startup.c
β”‚   β”œβ”€β”€ Makefile
β”‚   β”œβ”€β”€ obj
β”‚   β”œβ”€β”€ src
β”‚   β”‚   └── utils.c
β”‚   └── test
β”‚       β”œβ”€β”€ Makefile
β”‚       β”œβ”€β”€ obj
β”‚       └── src
β”‚           └── test.c
└── Makefile

To do this, you need all your Makefiles to call the Makefiles subdirectories. and src/ objdirs is the separation between your source and objects.

SRC := utils.c

OBJ := $(SRC:%.c=%.o)

NAME := project

SRC_D := src
OBJ_D := obj

SUBDIRS := lib1/ \
           lib2/ \
           test/

all: $(NAME) $(SUBDIRS)
    @for dir in $(SUBDIRS); \
    do \
    $(MAKE) -C $$dir; \
    done

$(NAME):    $(OBJ:%.o=$(OBJ_D)/%.o)

$(OBJ_D)/%.o :  $(SRC_D)/%.c
    gcc -c $< -o $@
+1
source

All Articles