Почему make не повторяется в моих исходных файлах? - PullRequest
0 голосов
/ 09 июня 2019

Я сделал make-файл для моего проекта, но make не выполняет итерации по моим исходным файлам. Я не могу понять, что я мог сделать, чтобы решить эту проблему.

У меня есть 2 исходных файла в моей директории atm

Makefile:

LIBNAME=hazelicious
FLIBNAME=lib$(LIBNAME).so
VERSION=
CC=g++
CXXFLAGS=-W -Wall -O2 -std=c++17 -fPIC -I./vendor/spdlog/include/
LDFLAGS=-shared -Wl,-soname,$(FLIBNAME)
DSRC=src/
DTGT=
DOBJ=$(DTGT)obj/
DOUT=$(DTGT)bin/
EXEC=$(DOUT)$(APPNAME)
SRC= $(wildcard $(DSRC)**/*.cpp)
OBJ= $(subst $(DSRC), $(DOBJ), $(patsubst %.cpp, %.o, $(SRC)))

all: $(FLIBNAME)

install: 
    @sudo cp $(DOUT)$(FLIBNAME) /usr/local/lib/
    @sudo cp $(DSRC)Hazelicious.h /usr/local/include/
    @echo "Library and header files copied!"

$(FLIBNAME): $(OBJ)
    @mkdir -p $(DOUT)
    @$(CC) -o $(DOUT)$@ $^ $(LDFLAGS)

$(OBJ): $(SRC)
    mkdir -p $(DOBJ)
    mkdir -p $(@D)
    $(CC) -o $@ -c $< $(CXXFLAGS)

checkvar:
    @echo $(SRC)
    @echo $(OBJ)

clean:
    @rm -rf $(DOBJ)
    @rm -rf $(EXEC)

run:
    @./$(EXEC)

Выход:

g++ -o obj/Hazelicious/Log.o -c src/Hazelicious/Log.cpp -W -Wall -O2 -std=c++17 -fPIC -I./vendor/spdlog/include/
g++ -o obj/Hazelicious/Application.o -c src/Hazelicious/Log.cpp -W -Wall -O2 -std=c++17 -fPIC -I./vendor/spdlog/include/

Как видите, вторая строка занимает тот же Log.cpp файл

Структура моих каталогов:

/src
  /Hazelicious
    Application.cpp
    Log.cpp
    ...
/obj
  /Hazelicicous
/bin

1 Ответ

0 голосов
/ 10 июня 2019

Если вы ожидаете этого:

SRC= $(wildcard $(DSRC)**/*.cpp)

, чтобы найти все .cpp файлы во всех подкаталогах $(DSRC), вы будете разочарованы.Специальная последовательность глобализации ** является нестандартной и поддерживается только некоторыми оболочками (например, zsh или bash, если вы включили специальную опцию).Он не входит в стандартную глобализацию POSIX и не поддерживается функцией GNU make wildcard.Вам нужно будет использовать стандартную реализацию, такую ​​как:

SRC := $(shell find $(DSRC) -name \*.cpp)

(здесь используется простое присвоение переменной (:=), а не рекурсивное присвоение переменной (=) для значительного повышения эффективности).

Также это:

OBJ= $(subst $(DSRC), $(DOBJ), $(patsubst %.cpp, %.o, $(SRC)))

может привести к неприятностям, потому что subst заменяет все экземпляров, даже в середине слов, даже если их несколькоэкземпляр одним словом.Гораздо лучше (и проще) это просто:

OBJ := $(patsubst $(DSRC)/%.cpp,$(DOBJ)/%.o,$(SRC))

Причина, по которой вы видите тот же исходный файл, заключается в том, что ваш рецепт неверен:

$(OBJ): $(SRC)
        mkdir -p $(DOBJ)
        mkdir -p $(@D)
        $(CC) -o $@ -c $< $(CXXFLAGS)

Предположим, SRC разрешается в src/foo.cpp src/bar.cpp src/biz.cpp.Затем OBJ разрешается до obj/foo.o obj/bar.o obj/biz.o.Таким образом, после расширения цели и предварительных условий вышеуказанного правила, make получит следующее:

obj/foo.o obj/bar.o obj/biz.o : src/foo.cpp src/bar.cpp src/biz.cpp
        mkdir -p $(DOBJ)
        mkdir -p $(@D)
        $(CC) -o $@ -c $< $(CXXFLAGS)

Когда make видит несколько целей в явном правиле, он обрабатывает это как несколько явных правил, по одному для каждой цели,например:

obj/foo.o : src/foo.cpp src/bar.cpp src/biz.cpp
        mkdir -p $(DOBJ)
        mkdir -p $(@D)
        $(CC) -o $@ -c $< $(CXXFLAGS)
obj/bar.o : src/foo.cpp src/bar.cpp src/biz.cpp
        mkdir -p $(DOBJ)
        mkdir -p $(@D)
        $(CC) -o $@ -c $< $(CXXFLAGS)
obj/biz.o : src/foo.cpp src/bar.cpp src/biz.cpp
        mkdir -p $(DOBJ)
        mkdir -p $(@D)
        $(CC) -o $@ -c $< $(CXXFLAGS)

Вы можете видеть, что во всех ваших правилах первым предварительным условием (к которому относится $<) будет src/foo.cpp, и именно это поведение вы наблюдаете.

Make не каким-то волшебным образом перебирает все цели и предпосылки и сопоставляет их для вас.

В make вы всегда пишете правило, которое строит одну цель из списка предпосылок этой цели.,В вашем случае вы, вероятно, захотите написать шаблонное правило , например:

$(DOBJ)/%.o : $(DSRC)/%.cpp
        mkdir -p $(@D)
        $(CC) -o $@ -c $< $(CXXFLAGS)

вместо явного правила, приведенного выше.Это обеспечивает make шаблоном, который он может использовать для создания любой цели, которая ему соответствует, и перечисляет предварительное условие связанного файла .cpp.

...