Я новичок в make-файлах и хочу создавать каталоги с помощью make-файлов. Мой каталог проекта выглядит так
+--Project
+--output
+--source
+Testfile.cpp
+Makefile
Я хочу поместить все объекты и вывод в соответствующую папку вывода. Я хочу создать структуру папок, которая была бы такой после компиляции.
+--Project
+--output
+--debug (or release)
+--objs
+Testfile.o
+Testfile (my executable file)
+--source
+Testfile.cpp
+Makefile
Я пробовал с несколькими вариантами, но безуспешно. Пожалуйста, помогите мне создать каталоги с помощью make file. Я отправляю на ваше рассмотрение свой Makefile.
#---------------------------------------------------------------------
# Input dirs, names, files
#---------------------------------------------------------------------
OUTPUT_ROOT := output/
TITLE_NAME := TestProj
ifdef DEBUG
TITLE_NAME += _DEBUG
else
ifdef RELEASE
TITLE_NAME += _RELEASE
endif
endif
# Include all the source files here with the directory tree
SOURCES := \
source/TestFile.cpp \
#---------------------------------------------------------------------
# configs
#---------------------------------------------------------------------
ifdef DEBUG
OUT_DIR := $(OUTPUT_ROOT)debug
CC_FLAGS := -c -Wall
else
ifdef RELEASE
OUT_DIR := $(OUTPUT_ROOT)release
CC_FLAGS := -c -Wall
else
$(error no build type defined)
endif
endif
# Put objects in the output directory.
OUT_O_DIR := $(OUT_DIR)/objs
#---------------------------------------------------------------------
# settings
#---------------------------------------------------------------------
OBJS = $(SOURCES:.cpp=.o)
DIRS = $(subst /,/,$(sort $(dir $(OBJS))))
DIR_TARGET = $(OUT_DIR)
OUTPUT_TARGET = $(OUT_DIR)/$(TITLE_NAME)
CC_FLAGS +=
LCF_FLAGS :=
LD_FLAGS :=
#---------------------------------------------------------------------
# executables
#---------------------------------------------------------------------
MD := mkdir
RM := rm
CC := g++
#---------------------------------------------------------------------
# rules
#---------------------------------------------------------------------
.PHONY: all clean title
all: title
clean:
$(RM) -rf $(OUT_DIR)
$(DIR_TARGET):
$(MD) -p $(DIRS)
.cpp.o:
@$(CC) -c $< -o $@
$(OBJS): $(OUT_O_DIR)/%.o: %.cpp
@$(CC) -c $< -o $@
title: $(DIR_TARGET) $(OBJS)
Заранее спасибо. Пожалуйста, помогите мне, если я тоже допустил ошибки.
output/debug', needed by
каталогов. Остановить». Но сейчас я не буду об этом беспокоиться. буду придерживаться основных правил. :). Спасибо за руководство. И я запускаю "make" только из каталога верхнего уровня.directories
не заставляя их всегда перестраивать ..На мой взгляд, каталоги не должны рассматриваться как цели вашего make-файла ни в техническом, ни в дизайнерском смысле. Вы должны создавать файлы, и если для создания файла требуется новый каталог, незаметно создайте каталог в правиле для соответствующего файла.
Если вы нацеливаетесь на обычный или «шаблонный» файл, просто используйте
make
внутреннюю переменную$(@D)
, которая означает «каталог, в котором находится текущая цель» (cmp. With$@
для цели). Например,Затем вы фактически делаете то же самое: создаете каталоги для всех
$(OBJS)
, но вы будете делать это менее сложным способом.Одна и та же политика (файлы - цели, каталоги - никогда) используется в различных приложениях. Например,
git
система контроля версий не хранит каталоги.Примечание. Если вы собираетесь его использовать, может быть полезно ввести вспомогательную переменную и использовать
make
правила расширения.источник
Или ПОЦЕЛУЙ.
Это создаст все каталоги после анализа Makefile.
источник
$(info $(shell mkdir -p $(DIRS)))
без символа$(info ...)
выводmkdir
команды будет вставлен в Makefile , что в лучшем случае приведет к синтаксическим ошибкам. В$(info ...)
гарантирует вызов , что а) ошибки (если таковые имеются) видны пользователю, и б) , что расширяется вызова функции ни к чему.make
in и off себя обрабатывает целевые объекты каталогов точно так же, как целевые файлы. Итак, легко написать такие правила:Единственная проблема в том, что временная метка каталогов зависит от того, что делается с файлами внутри. Для приведенных выше правил это приводит к следующему результату:
Это определенно не то, что вам нужно. Всякий раз, когда вы касаетесь файла, вы также касаетесь каталога. И поскольку файл зависит от каталога, он, следовательно, кажется устаревшим, что вынуждает его перестроить.
Однако вы можете легко разорвать этот цикл, указав программе make игнорировать временную метку каталога . Это делается путем объявления каталога как предварительного сайта только для заказа:
Это правильно дает:
TL; DR:
Напишите правило для создания каталога:
И цели для содержимого внутри зависят только от порядка каталогов:
источник
touch
изменение каких-либо статистических данных в родительском каталоге? Для меня это не имеет смысла. Время mtime каталога зависит только от содержащихся в нем имен файлов. Я не смог воспроизвести вашу проблему.Все решения, включая принятое, имеют некоторые проблемы, указанные в соответствующих комментариях. Общепринятый ответ на @ Джонатан Леффлера уже довольно хорошо , но не принимает в том , что предпосылки не обязательно должны быть построены в порядке ( в течение
make -j
, например). Однако простое перемещениеdirectories
предпосылки сall
наprogram
вызывает перестройку AFAICT при каждом запуске. Следующее решение не имеет этой проблемы, и AFAICS работает по назначению.источник
Я только что придумал довольно разумное решение, которое позволяет вам определять файлы для сборки и автоматически создавать каталоги. Во-первых, определите переменную,
ALL_TARGET_FILES
которая содержит имя каждого файла, который будет создан вашим make-файлом. Затем используйте следующий код:Вот как это работает. Я определяю функцию,
depend_on_dir
которая принимает имя файла и генерирует правило, которое заставляет файл зависеть от каталога, в котором он находится, а затем определяет правило для создания этого каталога при необходимости. Затем я используюforeach
дляcall
этой функции на каждом имени файла иeval
результата.Обратите внимание, что вам понадобится поддерживающая версия GNU make
eval
, я думаю, это версии 3.81 и выше.источник
учитывая, что вы новичок, я бы посоветовал пока не пытаться это сделать. это определенно возможно, но без нужды усложнит ваш Makefile. придерживайтесь простых способов, пока не освоитесь с make.
Тем не менее, один из способов создания каталога, отличного от исходного каталога, - VPATH ; я предпочитаю шаблонные правила
источник
Независимость от ОС для меня критична, поэтому
mkdir -p
это не вариант. Я создал эту серию функций, которые используютсяeval
для создания целевых каталогов с предварительным условием для родительского каталога. Это имеет то преимущество, чтоmake -j 2
будет работать без проблем, поскольку зависимости определены правильно.Например, выполнение вышеуказанного приведет к созданию:
источник
См. Https://www.oreilly.com/library/view/managing-projects-with/0596006101/ch12.html.
Поскольку я использую Ubuntu, мне также нужно было добавить это вверху моего Makefile:
источник