Generate gcc dependencies with full path

I have a simple project that looks something like this:

.
├── build
│   ├── file1.o
│   └── one
│       ├── file1.o
│       └── file2.o
├── .depend
├── Makefile
└── src
    ├── file1.cpp
    └── one
        ├── file1.cpp
        └── file2.cpp

The Makefile looks something like this:

# Get all of the source files
SRC = $(shell find src/ -name "*.cpp")
# Get all of the object files
OBJ = $(subst src,build,$(SRC:.cpp=.o))

$(OBJ):
    @mkdir -p $(shell dirname $@)
    g++ -g -c $(subst build,src,$(subst .o,.cpp,$@)) -o $@

all: depend build

build: $(OBJ)
    gcc -o project $^

depend:
    g++ -MM $(SRC) > .depend
    sed -i 's/.\/src/.\/build\//g' .depend

sinclude .depend

I am trying to create makefile dependencies by running g++ -MM src/file1.cpp src/one/file1.cpp src/one/file2.cpp > .dependand it generates the following directives:

file1.o: src/file1.cpp <other headers>
file1.o: src/one/file1.cpp <other headers>
file2.o: src/one/file2.cpp <other headers>

The problem with this is that it build/file1.odoes not match file1.o, and as a result, changing src/file1.cppeither of any of the headers on which it depends does not cause a rebuild of the object file. At first I thought it might be a problem when it sinclude .dependwas run before the .depend file was created, but the problem persists even if I run it make depend, and then make build. Of all that I read, there are no arguments or parameters g++that will preserve the name path.

, ?

, , , , make , Makefile, gcc -MM. .

+4
3

:

# Get all of the source files
SRC = $(shell find src/ -name "*.cpp")
# Get all of the object files
OBJ = $(patsubst src/%.cpp,build/%.o,$(SRC))

.PHONY: all

all: project

project: $(OBJ)
    gcc -o $@ $^

$(OBJ): build/%.o: src/%.cpp
    @mkdir -p $(dir $@)
    g++ -g -c $< -o $@

.depend: $(SRC)
    g++ -MM $^ > $@ && \
    sed -Ei 's#^(.*\.o: *)src/(.*/)?(.*\.cpp)#build/\2\1src/\2\3#' $@

include .depend

sed :

file.o: src/file.cpp ...

:

build/file.o: src/file.cpp ...

:

file.o: src/X/Y/Z/file.cpp ...

:

build/X/Y/Z/file.o: src/X/Y/Z/file.cpp ...

.depend , , . depend all ( , include).

GNU make (patsubst, , ...) , make.

+2

.

, sed ( ):

depend:
    g++ -MM $(SRC) | sed 's/.*: src\([^ ]*\)cpp/build\1o: src\1cpp/' > .depend                  

, :

STEMS := file1 one/file1 one/file2
depend:
    rm -f .depend
    for x in $(STEMS); do g++ -MM -MT build/$$x.o src/$$x.cpp >> .depend; done

, Make:

DEPENDENCIES := $(addsuffix -depend,$(STEMS))

clear-depend:
    rm -f .depend

depend: $(DEPENDENCIES)

%-depend: clear-depend
    g++ -MM -MT build/$*.o src/$*.cpp >> .depend

( , , .depend. , , , , file1.cpp file1.cpp.)

+1

:

define req
$(subst ..,__,$(dir build-$(TARGET)$(build_dir_ext)/$(1)))%.o: $(dir $1)%.cpp
    mkdir -p $$(dir $$(subst ..,__,$$@))
    $$(CXX) -MM $$(CXXFLAGS) $$< -MT   $$(subst ..,__,$$@) > $$(patsubst %.o,%.d,$$(subst ..,__,$$@))
    $$(CXX)     $$(CXXFLAGS) $$< -c -o $$(subst ..,__,$$@)
endef

$(eval $(foreach x,$(OBJ),$(call req,$(x))))

make , "" , "__" ".." , , src build. "" , .

, ...

EDIT 1: Why replace ".."

Think of the following source tree:

./sourcepool/lib1/src/one.cpp
./sourcepool/project/build

If your Makefile is on the go. / sourcepool / project, and one of the OBJs is "../lib1/src/one.o", the Makefile should create an equivalent path in the assembly directory. That is, if ".." is used, it is impossible, because then the path is no longer built, but one depth is higher. If you replace .. with __, the result is as follows:

./sourcepool/project/build/__/lib1/src/one.o

This allows you to not copy or associate all used dirs with the local project and build a file tree.

0
source

Source: https://habr.com/ru/post/1690649/


All Articles