makefile с g cc возвращает фатальную ошибку: нет входных файлов - PullRequest
0 голосов
/ 21 апреля 2020

Я пытаюсь создать make-файл для нового проекта. проект пока содержит только некоторые базовые c main fun c и несколько объявлений funcs. Мой make-файл создает объекты из исходных файлов, но исполняемый файл не компилируется. завершиться с ошибкой:

mkdir -p build/./src/app/
gcc -std=gnu99 -Wall  -I./src -I./src/app -I./src/include -I./src/lib  -c src/app/main.c -o build/./src/app/main.o
mkdir -p build/./src/app/
gcc -std=gnu99 -Wall  -I./src -I./src/app -I./src/include -I./src/lib  -c src/app/Emsg.c -o build/./src/app/Emsg.o
gcc -std=gnu99 -Wall  -I./src -I./src/app -I./src/include -I./src/lib   -o bin/Main
gcc: fatal error: no input files
compilation terminated.
Makefile:59: recipe for target 'all' failed
make: *** [all] Error 1

это мой make-файл:

CFLAGS := -std=gnu99 -Wall

ifeq ($(STRIP), yes)
    CFLAGS := $(CFLAGS) -s
endif

BUILD_DIR :=        ./build
BIN_DIR :=      ./bin

SRC_DIRS :=         ./
SRC_APPS :=         ./src
SRC_TESTS :=        ./test

SRCS_APPS :=        $(shell find $(SRC_APPS) -name '*.c')
SRCS_TESTS :=       $(shell find $(SRC_TESTS) -name '*.c')

OBJS_APPS :=        $(SRCS_APPS:%.c=$(BUILD_DIR)/%.o)
OBJS_TESTS :=       $(SRCS_TESTS:%.c=$(BUILD_DIR)/%.o)
OBJS_ALL :=     $(OBJS_APPS)
OBJS_ALL_TESTS :=   $(OBJS_ALL) $(OBJS_TESTS)

INC_APPS_DIRS :=    $(shell find ./src -type d)
INC_INCLUDES  :=    src/include
INC_TESTS_DIRS :=   test/

INC_APPS_FLAGS :=   $(addprefix -I,$(INC_APPS_DIRS))
INCLUDE_ALL :=      $(INC_APPS_FLAGS) 

CC :=           gcc

ifeq ($(TEST), yes)
    CFLAGS :=   $(CFLAGS) -D TEST 
    OBJECTS :=  $(OBJS_APPS) $(OBJS_TESTS)
    INCLUDE :=  $(INC_TESTS_LIBS_FLAGS) $(INC_TESTS_FLAGS) 
    DEPEND_LST :=   apps tests

    COMP_ARGS :=    $(CC) $(CFLAGS) $(INCLUDE) $(OBJECTS) -L$(INC_TEST_LIBS) -o bin/Test

else
    DEPEND_LST :=   apps
    COMP_ARGS :=    $(CC) $(CFLAGS)  $(INCLUDE_ALL) $(OBJECTS) -o bin/Main
endif

# All
all: $(DEPEND_LST)
    $(COMP_ARGS)

#Tests
tests: $(OBJS_TESTS)

$(BUILD_DIR)/%.o: %.c
    $(MKDIR_P) $(dir $@)
    $(CC) $(CFLAGS)  $(INCLUDE_ALL) -c $< -o $@

# Apps
apps: $(OBJS_APPS)

$(BUILD_DIR)/%.o: %.c
    $(MKDIR_P) $(dir $@)
    $(CC) $(CFLAGS)  $(INCLUDE_ALL) -c $< -o $@

# Clean
clean:
    $(RM) -r $(BUILD_DIR)

# not sure what these two lines do..
-include $(DEPS)

MKDIR_P ?= mkdir -p

Я просто запускаю make. иерархия файлов:

  • sr c dir
    • app dir (содержит main. c и более файлов)
    • include dir (содержит некоторые .h файлы)
    • lib dir (пусто)
  • test dir (содержит другой основной. c файл)
  • Makefile файл

Ответы [ 2 ]

0 голосов
/ 22 апреля 2020

Вывод Make представляет команды, которые он запускает. По крайней мере, для последовательной сборки это однозначно сообщает, какая команда произвела каждое сообщение диагностики c. В вашем случае команда, вызвавшая ошибку, сразу же предшествует ей в выводе:

gcc -std=gnu99 -Wall  -I./src -I./src/app -I./src/include -I./src/lib   -o bin/Main

Так что же с этим не так? Почему именно то, что говорит диагностика c: в нем не указаны входные файлы для работы. Нет C исходных файлов для компиляции, нет объектных файлов или библиотек для ссылок. Ничего, из чего можно создать указанный выходной файл.

Предположим, что вы представили полный make-файл, который создает для вас проблему, эта команда должна исходить из попытки создать цель all с помощью этого правила:

all: $(DEPEND_LST)
    $(COMP_ARGS)

Это немного подозрительно, потому что цель all обычно предоставляет только список предварительных условий, а не рецепт. Каждое предварительное условие, которое может потребоваться построить, будет иметь свое собственное правило. Но по сути не является неправильным предоставление рецепта, и мы должны рассмотреть сам рецепт, чтобы определить природу вашей проблемы. В этом случае у нас есть подозрительный момент № 2: рецепт определяется целиком через одну переменную. Но я уже знал это, потому что мне пришлось проследить это, чтобы сначала определить это правило как источник ошибки.

В частности, единственное место, где текст bin/Main появляется в make-файле. находится в этом else блоке:

else
    DEPEND_LST :=   apps
    COMP_ARGS :=    $(CC) $(CFLAGS)  $(INCLUDE_ALL) $(OBJECTS) -o bin/Main
endif

Это действительно обеспечивает переменную командной строки, на которую ссылается цель all (и ничто иное), и она точно совпадает с командой, которая вызывает ошибку , И что мы находим, когда сопоставляем биты командной строки с переменными, из которых построена эта версия COMP_ARGS? Мы обнаруживаем, что все биты покрыты переменными, отличными от OBJECTS, которые, очевидно, расширяются до нуля (вы даже можете видеть отдельные символы начального и конечного пробелов вокруг его пустого значения). И почему OBJECTS расширяется до пустого значения? Поскольку никогда не устанавливается , когда выполняется эта ветвь условного выражения.

Лично я был бы склонен переписать весь make-файл, чтобы он был более идиоматическим c и меньше полагался на GNU make расширений, но простейшим шагом вперед, вероятно, было бы поместить соответствующее определение переменной OBJECTS в блоке else, на который я указал.

0 голосов
/ 22 апреля 2020

Установите GNU римейк и запустите remake -X.

Это поместит вас в отладчик, а затем вы сможете запустить step, чтобы шаг за шагом увидеть, что делает make-файл. Вот что применимо к вашему Makefile:

$ remake -X 
Reading makefiles...
Updating makefiles...
Updating goal targets...
-> (/tmp/so/Makefile:45)
all: apps
remake<0> step
 File 'all' does not exist.
   File 'apps' does not exist.
  Must remake target 'apps'.
  Successfully remade target file 'apps'.
<- (/tmp/so/Makefile:56)
apps
remake<1> where
=>#0  apps at Makefile:56
  #1  all at Makefile:45
remake<3> x OBJS_APPS
Makefile:17 (origin: makefile) OBJS_APPS := ...

Смотрите ссылку на видео. Или https://github.com/rocky/remake для некоторых снимков экрана

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...