2015-07-07 3 views
1

Мне было интересно, какие существуют разные подходы к использованию Make в проекте с подкаталогами, и каковы их преимущества/недостатки, но он никогда не сможет увидеть хорошее резюме или кулинарию.Использование GNU Make с подкаталогами

В моих исследованиях я видел в основном подходы «рекурсивный» и «единственный макияж», но есть ли другие?

Я также предполагаю, что существует не только один «рекурсивный» или «единственный макет», но и несколько, так может кто-нибудь его подвести?

Для моего конкретного случая, я хотел бы архитектуру каталогов, глядя, как это:

. 
├── build 
│   ├── *.d 
│   ├── *.o 
| ├── subdir1 
| │ ├── *.d 
| │ └── *.o 
| └── subdir2 
|  ├── *.d 
|  ├── *.o 
|  └── subdir3 
|   ├── *.d 
|   └── *.o 
├── include 
│   ├── *.h 
│   └── *.h 
├── Makefile 
└── src 
    ├── *.c 
    ├── *.h 
    ├── subdir1 
    │   ├── *.c 
    │   └── *.h 
    └── subdir2 
     ├── *.c 
     ├── *.h 
     └── subdir3 
      ├── *.c 
      └── *.h 

Какое решение я должен выбрать? Возможно, тот, который разрешил бы исходные файлы с тем же именем?

+0

Основные аргументы против рекурсивного дела изложены в документе [Рекурсивный взгляд на вредные последствия] (http://aegis.sourceforge.net/auug97.pdf) (pdf). [Эта страница] (http://evbergen.home.xs4all.nl/nonrecursive-make.html) говорит о внедрении нерекурсивной системы make, как это делает [Безболезненный нерекурсивный Make] (http: //www.cmcrossroads .com/article/безболезненный-нерекурсивный-make). [Multi-Architecture Builds] (http: //make.mad-scientist.net/papers/multi-architecture-builds /) В статье также есть некоторые интересные вещи, которые можно сказать по этой теме. –

+0

Рекурсивный и одномастный файл почти полностью покрывает его, но, конечно, вы можете их смешивать - есть мастер makefile, вызывающий 'src/Makefile', который затем обрабатывает все дерево' src/'самостоятельно. – Beta

+0

Есть аргументы в обоих направлениях. Время запуска с нерекурсивным make может быть дорогостоящим (когда я впервые построил glibc, потребовалось почти час, чтобы начать). Документы, пропагандирующие нерекурсивный характер, отвергают этот вопрос или полностью забывают упомянуть об этом. Учитывая это, вопрос не соответствует теме. –

ответ

1

После прочтения Recursive Make Considered Harmful, я понял, довольно простой и модульный способ для достижения этой цели, по имеющие файлы во всех подкаталогах, которые включают в себя друг друга и быть включены в основной Makefile:

CXX   := gcc 

SRCDIR   := src 
OBJDIR   := build 

# These lines are needed to set immediate evaluation for 
# these variables, instead of deferred evaluation which is unsuitable. 
SRCS   := 
SUBDIRS   := 
CFLAGS   := 
LDFLAGS   := 

include $(SRCDIR)/module.mk 

OBJS   := $(addprefix $(OBJDIR)/, $(SRCS:.c=.o)) 

SRCS   := $(addprefix $(SRCDIR)/, $(SRCS)) 

DEPS   := $(OBJS:.o=.d) 

TMPS   := $(OBJS) $(OBJS:.o=.d) 

CFLAGS   += -MD 
debug: CFLAGS += -g -g3 -ggdb 
CFLAGS   += $(addprefix -I./$(SRCDIR)/, $(SUBDIRS)) 

LDFLAGS   += -lsomelib 
debug: LDFLAGS  += -g -g3 -ggdb 

NAME   := yolo 

all: $(NAME) 

debug: re 

-include $(DEPS) 

$(OBJDIR)/%.o: $(SRCDIR)/%.c 
    $(COMPILE.c) $(OUTPUT_OPTION) $< 

$(NAME): $(OBJS) 
    @$(CXX) $(OBJS) -o $(NAME) $(LDFLAGS) 

$(OBJS): | $(OBJDIR) 

$(OBJDIR): 
    @mkdir -p $(OBJDIR) 
    @for dir in $(SUBDIRS);   \ 
    do     \ 
     mkdir -p $(OBJDIR)/$$dir; \ 
    done 

clean: 
    rm -rf $(TMPS) 

fclean: clean 
    rm -rf $(NAME) 
    rm -rf $(OBJDIR) 

re: fclean all 

.PHONY: all clean fclean re 

и в каждом подкаталоге, файл module.mk (Я мог бы назвать это чем угодно, но это выглядело круто).

Для ЦСИ:

SRCS  := main.c file1.c file2.c 

SUBDIRS  += subdir1 subdir2 

include $(SRCDIR)/subdir1/module.mk 
include $(SRCDIR)/subdir2/module.mk 

Для подкаталог уровня 1:

THIS_DIR_L0 := subdir1 

MOD_SRC  := file3.c file4.c 

SRCS  += $(addprefix $(THIS_DIR_L0)/, $(MOD_SRC)) 

SUBDIRS  += $(THIS_DIR_L0)/subdir3 

include $(SRCDIR)/$(THIS_DIR_L0)/subdir3/module.mk 

А для 2-го уровня подкаталог (один глубже):

THIS_DIR_L1 := subdir3 

MOD_SRC  := file5.c file6.c 

SRCS  += $(addprefix $(THIS_DIR_L0)/$(THIS_DIR_L1)/, $(MOD_SRC)) 

И так далее .. .

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

Любой, кто имеет лучшую идею, скажите, пожалуйста.

1

Вашего проект установка очень проста, так что должна быть ваш Makefile:

SRC_DIR := src 
BLD_DIR := build 

SRC := $(shell find $(SRC_DIR) -name "*.c") 
OBJ := $(SRC:$(SRC_DIR)/%.c=$(BLD_DIR)/%.o) 
DEP := $(OBJ:.o=.d) 

CPPFLAGS := -MMD -MP # enable auto-dependency generation 
CFLAGS := -Wall -W -pedantic 

.PHONY: all clean 

all: $(OBJ) 

clean: 
    $(RM) -r $(BLD_DIR) 

.SECONDEXPANSION: 
$(BLD_DIR)/%.o: $(SRC_DIR)/%.c | $$(@D)/ # First check that the destination directory exists 
    $(CC) $(CPPFLAGS) $(CFLAGS) -o [email protected] -c $< 

%/: 
    mkdir -p $* # -p flag necessary for recursive directory creation 

ifeq "$(MAKECMDGOALS)" "" 
-include $(DEP) 
endif 

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


Испытано с GNU Make 4.1 под ОС Windows 8.1 с GIT Bash оболочки и следующую структуру каталогов:

. 
├── Makefile 
└── src 
    ├── test.c 
    ├── test1.c 
    └── subdir1 
     └── test.c 
+0

Большое спасибо за ваш ответ, так как это сработает для моей проблемы. Мое единственное беспокойство в этом методе заключается в том, что я не определяю свои исходные файлы в некоторых конкретных местах, но вместо этого просто беру все, что там нечетко. Иногда это нежелательно. – deb0ch

+0

То, как вы перечисляете исходные файлы, в конечном итоге зависит от вас, вы можете сделать это вручную, но даже если вам нужно только перечислить только определенные файлы, моя техника позволяет вам написать один небольшой файл Makefile и все, что вам нужно обновить, 'SRC', поскольку все изменения структуры проекта уже покрыты, тогда как для вашего решения требуется файл для каждого каталога, а изменения в ваших разных вариантах включают всюду по файловой системе. Для меня мой Makefile более модульный и даже меньше, чем все, что ваш ответ способствует. – Chnossos

Смежные вопросы