[РЕШЕНО] Почему make не сразу находит объектные файлы? (И как это исправить?)

Модератор: Модераторы разделов

Ответить
DetL0k
Сообщения: 11

[РЕШЕНО] Почему make не сразу находит объектные файлы?

Сообщение DetL0k »

Есть проект. Только-только начал. К коду притензий нет, а вот сборка глючит.
Структура классическая:
  • папка src для исходников
  • папка include для заголовочных файлов
  • папка build для сборки
  • Makefile

Сборку выполняю через Makefile:

Код: Выделить всё

CC                  = cc
OPATH               = build
VPATH               = src:$(OPATH)
CFLAGS              = -Wall -Iinclude -g -o $(OPATH)/$@

.PHONY              : all clean
.SILENT             : clean

all                 : jd
jd                  : core.o jd_opts.o
    $(CC) $(CFLAGS) $^
core.o              : core.c
    $(CC) $(CFLAGS) -c $^
jd_opts.o           : jd_opts.c
    $(CC) $(CFLAGS) -c $^
clean               :
    rm -f $(OPATH)/*

При первой сборке получаю такой вывод:

Код: Выделить всё

cc -Wall -Iinclude -g -o build/core.o -c src/core.c
cc -Wall -Iinclude -g -o build/jd_opts.o -c src/jd_opts.c
cc -Wall -Iinclude -g -o build/jd core.o jd_opts.o
cc: error: core.o: Нет такого файла или каталога
cc: error: jd_opts.o: Нет такого файла или каталога
cc: fatal error: no input files
compilation terminated.
Makefile:11: ошибка выполнения рецепта для цели «jd»
make: *** [jd] Ошибка 4

Лезу в папку build - файлы там. Если выполнить сборку еще раз без очистки, то соберется все нормально:

Код: Выделить всё

cc -Wall -Iinclude -g -o build/jd build/core.o build/jd_opts.o

Собственно как сделать чтобы объектные файлы в папке build подхватывались сразу?
PS: Если сборку делать в корне проекта (там же где и Makefile), то все нормально.
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20752
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: [РЕШЕНО] Почему make не сразу находит объектные файлы?

Сообщение Bizdelnick »

DetL0k писал(а):
05.01.2017 00:14
Если сборку делать в корне проекта (там же где и Makefile), то все нормально.

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

Код: Выделить всё

all                 : $(OPATH)/jd
$(OPATH)/jd         : $(OPATH)/core.o $(OPATH)/jd_opts.o
    $(CC) $(CFLAGS) $^
$(OPATH)/core.o     : core.c
    $(CC) $(CFLAGS) -c $<
$(OPATH)/jd_opts.o  : jd_opts.c
    $(CC) $(CFLAGS) -c $<
либо добавить Makefile в каталог build (но тогда в нём надо будет указывать путь к исходным файлам). То и другое сказывается на читаемости не лучшим образом.

Ещё попридираюсь к мелочам. Вот эта строчкасмысла не имеет, так как переменная $(CC) по умолчанию и так имеет именно это значение.
Здесь

Код: Выделить всё

CFLAGS              = -Wall -Iinclude -g -o $(OPATH)/$@
много лишнего. -Iinclude — опция препроцессора, и место ей в переменной $(CPPFLAGS), а опция -o никогда в $(CFLAGS) не включается, и указывается непосредственно в рецепте. Дело в том, что переменная CFLAGS часто переопределяется сборщиками, и в Вашем случае это сломает сборку. В принципе может переопределяться и CPPFLAGS, поэтому с ней лучше поступить так:

Код: Выделить всё

CPPFLAGS += -Iinclude
— тогда обязательная опция не потеряется в любом случае.
Ну а если $(CPPFLAGS) и $(CFLAGS) (а также $(LDFLAGS), если она нужна) определены корректно, можно вообще не заморачиваться написанием рецептов, а использовать те, которые захардкожены в make. Тогда весь Makefile станет намного проще:

Код: Выделить всё

CFLAGS              = -Wall -g
CPPFLAGS            += -Iinclude
VPATH               = src

all                 : jd
jd                  : core.o jd_opts.o
clean               :
    rm -f jd core.o jd_opts.o

.PHONY              : all clean
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
ieleja
Сообщения: 307
ОС: Debian 9, macOS, Windows
Контактная информация:

Re: [РЕШЕНО] Почему make не сразу находит объектные файлы?

Сообщение ieleja »

Код: Выделить всё

cc -Wall -Iinclude -g -o build/jd core.o jd_opts.o

ищет в корне проекта а

Код: Выделить всё

cc -Wall -Iinclude -g -o build/core.o -c src/core.c
cc -Wall -Iinclude -g -o build/jd_opts.o -c src/jd_opts.c

компилирует в build/

@Bizdelnick уже разобрал
ad infinitum
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20752
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: [РЕШЕНО] Почему make не сразу находит объектные файлы?

Сообщение Bizdelnick »

Прошу прощения за невнимательность, только сейчас заметил, что Вы используете VPATH. Поначалу не так понял вопрос. Тут дело в том, что, когда make не находит зависимости и пересобирает её, он не выполняет её поиск повторно. Просто считает, что она удовлетворена, даже если фактически соответствующий файл не появился. При повторном запуске он выполняет поиск, находит зависимости, не нуждающиеся в обновлении, и собирает бинарник правильно.
В общем, Ваша задумка корректно работать не сможет, поскольку данная структура каталогов вовсе не является «классической». В «классическом» варианте отдельного каталога для сборки не создаётся. Да и VPATH не используется, а используется рекрсивный вызов make в подкаталогах.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
DetL0k
Сообщения: 11

Re: [РЕШЕНО] Почему make не сразу находит объектные файлы?

Сообщение DetL0k »

Спасибо за разьяснения :)
Думаю в моем случае можно и без рекурсивного make обойтись. Вот что состряпал:

Код: Выделить всё

OPATH                      = obj
JD_OBJS                    = core jd_opts
CFLAGS                     += -Wall -g

all                        : jd
jd                         : $(foreach OBJ, $(JD_OBJS), $(OPATH)/$(OBJ).o)
    $(CC) $(CFLAGS) -o $@ $^
$(OPATH)/%.o               : src/%.c
    $(CC) $(CFLAGS) -Iinclude -o $@ -c $^
clean                      :
    $(RM) -f $(OPATH)/*.o jd

.PHONY                     : all clean
.SILENT                    : clean
Спасибо сказали:
Ответить