Исходники из подкаталогов в Makefile - PullRequest
47 голосов
/ 27 октября 2010

У меня есть библиотека C ++, созданная с использованием Makefile.До недавнего времени все исходники были в одном каталоге, и Makefile делал что-то вроде этого

SOURCES = $(wildcard *.cpp)

, которое работало нормально.

Теперь я добавилисточники, которые находятся в подкаталоге, скажем subdir.Я знаю, что могу сделать это

SOURCES = $(wildcard *.cpp) $(wildcard subdir/*.cpp)

, но я ищу способ избежать указания subdir вручную, то есть заставить wildcard просматривать подкаталоги или генерироватьсписок подкаталогов каким-либо образом и расширение его несколькими wildcard функциями.На этом этапе было бы неплохо иметь нерекурсивное решение (то есть расширять только первый уровень).

Я ничего не нашел - мое лучшее предположение - использовать find -type d для вывода списка подкаталогов,но это похоже на взлом.Есть ли какой-нибудь встроенный способ сделать это?

Ответы [ 7 ]

70 голосов
/ 28 октября 2010

Это должно сделать это:

SOURCES = $(wildcard *.cpp) $(wildcard */*.cpp)

Если вы передумали и хотите рекурсивное решение (т.е. на любую глубину), это можно сделать, но оно включает в себя некоторые из более мощных функций Make. Вы знаете, те, которые позволяют вам делать то, что вы действительно не должны.

EDIT:
Джек Келли отмечает, что $(wildcard **/*.cpp) работает на любой глубине, по крайней мере, на некоторых платформах, используя GNUMake 3.81. (Как он это понял, я понятия не имею.)

19 голосов
/ 18 октября 2012

Рекурсивные подстановочные знаки могут быть сделаны исключительно в Make без вызова shell или команды find.Выполнение поиска с использованием только Make означает, что это решение работает и в Windows, а не только * nix.

# Make does not offer a recursive wildcard function, so here's one:
rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))

# How to recursively find all files with the same name in a given folder
ALL_INDEX_HTMLS := $(call rwildcard,foo/,index.html)

# How to recursively find all files that match a pattern
ALL_HTMLS := $(call rwildcard,foo/,*.html)

Требуется завершающий слеш в имени папки.Эта функция rwildcard не поддерживает множественные символы подстановки, как это делает встроенная функция подстановки Make, но добавление этой поддержки было бы простым, если использовать foreach еще парой.

15 голосов
/ 27 октября 2010

Если вы не хотите использовать рекурсивные make-файлы, это может дать вам несколько идей:

subdirs := $(wildcard */)
sources := $(wildcard $(addsuffix *.cpp,$(subdirs)))
objects := $(patsubst %.cpp,%.o,$(sources))

$(objects) : %.o : %.cpp
9 голосов
/ 27 октября 2010

Обычная практика - поместить Makefile в каждый подкаталог с источниками, затем

all: recursive
    $(MAKE) -C componentX
    # stuff for current dir

или

all: recursive
    cd componentX && $(MAKE)
    # stuff for current dir

recursive: true

Может быть целесообразно поместить настройки для каждого Makefile в Makefile.inc в корневом каталоге исходного кода. Цель recursive заставляет make перейти в подкаталоги. Убедитесь, что он не перекомпилирует что-либо в цели, требующей recursive.

8 голосов
/ 27 октября 2010

Это дополнительная заметка, которая не отвечает на ваш вопрос, но есть статья "Рекурсивная работа считается вредной".Стоит прочесть.

Вот ссылка.http://aegis.sourceforge.net/auug97.pdf

2 голосов
/ 27 сентября 2018

Вы можете использовать несколько правил в wildcard:

SOURCES := $(wildcard *.cpp */*.cpp)

если вам нужно больше глубины:

SOURCES := $(wildcard *.cpp */*.cpp */*/*.cpp */*/*/*.cpp)

к сожалению, и вопреки тому, что мы иногда читаем, glob (**) не поддерживается make-файлом и будет интерпретироваться как обычный подстановочный знак (**/*.cpp match */*.cpp, но не */*/*.cpp).

если вам нужна бесконечная глубина, используйте shell

SOURCES := $(shell find . -name "*.cpp")
2 голосов
/ 10 февраля 2011

Если вы можете использовать find команду оболочки, вы можете определить функцию для ее использования.

recurfind = $(shell find $(1) -name '$(2)')
SRCS := $(call recurfind,subdir1,*.c) $(call recurfind,subdir2,*.cc) $(call recurfind,subdir2,*.cu) \
        ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...