Makefile: нет правил для создания цели: как установить правильные правила? - PullRequest
0 голосов
/ 10 октября 2018

У меня есть проект, для которого я пытаюсь создать Makefile.Структура папок выглядит следующим образом:

|-- bin
|-- build
|-- Makefile
|-- src
|   |-- some_files.cpp
|   |-- some_files.h
|   |-- ForestFactory
|   |-- MMParSet
|   |-- century
|       |-- century_carbon.cpp
|       |-- century_carbon.h
|   `-- grass
`-- src_multithread
    |-- __history

, и я попытался использовать эту ссылку для создания файла Makefile.У меня есть Makefile

CC := g++

SRCDIR := src
BUILDDIR := build
TARGETDIR := bin
INSTALLBINDIR := /usr/local/bin
TARGET := bin/formind

# CPP files
SOURCES := $(shell find $(SRCDIR) -type f -name *.cpp)
# remove the src path and add the build path and the .o extension
OBJECTS := $(addprefix $(BUILDDIR)/,$(patsubst %.cpp,%.o,$(notdir $(SOURCES))))

CFLAGS := -std=c++11 -stdlib=libc++

INC := -I/usr/local/include -I $(SRCDIR) -I $(SRCDIR)/century -I $(SRCDIR)/grass -I $(SRCDIR)/MMParSet -I $(SRCDIR)/ForestFactory

$(TARGET): $(OBJECTS)
    @mkdir -p $(TARGETDIR)
    @echo " Linking..."
    @echo " $(CC) $^ -o $(TARGET)"
    $(CC) $^ -o $(TARGET)

$(BUILDDIR)/%.o: $(SRCDIR)/%.cpp
    @mkdir -p $(BUILDDIR)
    @echo " $(CC) $(CFLAGS) $(INC) -c -o $@ $<"
    $(CC) $(CFLAGS) $(INC) -c -o $@ $<

clean:
    @echo " Cleaning...";
    @echo " $(RM) -r $(BUILDDIR) $(TARGET)"
    $(RM) -r $(BUILDDIR) $(TARGET)


.PHONY: clean

Когда я пытаюсь make, я получаю следующее сообщение об ошибке:

make: *** No rule to make target `build/century_carbon.o', needed by `bin/formind'.  Stop.

Исходные файлы поступают из вложенного набора подкаталогов внутри src.Насколько я понимаю, переменная OBJECTS должна содержать полные пути к конечным объектным файлам, так что у меня есть что-то вроде

$SOURCES = src/century/century_carbon.cpp ... src/for_branching.cpp ... src/grass/grass_log.cpp ...

$OBJECTS = build/century_carbon.o ... build/for_branching.o ... build/grass_log.o ...

Что-то не так в том, как я написал правила компиляции?

1 Ответ

0 голосов
/ 11 октября 2018

Проблема с вложенным исходным каталогом century.Если вы добавите в make-файл:

info:
    @echo " Info..."
    @echo " SOURCES = $(SOURCES)"
    @echo " OBJECTS = $(OBJECTS)"

, то make info даст:

  Info...
  SOURCES = src/century/century_carbon.cpp src/some_files.cpp
  OBJECTS = build/century_carbon.o build/some_files.o

Эта проверка показывает, что ваша конструкция этих макросов в порядке.И это также показывает, как вы сообщаете, что make тогда скажет нам:

make: *** No rule to make target 'build/century_carbon.o', needed by 'bin/formind'.  Stop.

Если вы добавите дополнительное правило с указанным каталогом century:

$(BUILDDIR)/%.o: $(SRCDIR)/century/%.cpp
    @mkdir -p $(BUILDDIR)
    $(CC) $(CFLAGS) $(INC) -c -o $@ $<

тогда ваша сборка будет продолжена.


Альтернативное решение - использовать VPATH.Добавьте строку:

VPATH = src:src/century

, а также удалите $(SRCDIR)/ из своего правила, которое теперь становится:

$(BUILDDIR)/%.o: %.cpp
    @mkdir -p $(BUILDDIR)
    $(CC) $(CFLAGS) $(INC) -c -o $@ $<

Обновление: Ответ вышеможет быть улучшено двумя способами:

  • Используйте vpath вместо VPATH для более точного управления поиском.

  • Автоматическисоздать аргумент для vpath / VPATH.

Это удивительно просто: просто замените мою жестко запрограммированную строку VPATH на:

vpath %.cpp $(sort $(dir $(SOURCES)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...