带有gcc的makefile返回致命错误:无输入文件

时间:2020-04-21 15:22:09

标签: c makefile

我正在尝试为新项目创建一个makefile。到目前为止,该项目仅包含一些基本的main函数和一些func声明。 我的makefile从源文件中创建对象,但是没有编译可执行文件。错误退出:

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

这是我的制作文件:

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。 文件层次结构是:

  • src目录
    • 应用程序目录(包含main.c和更多文件)
    • include dir(包含一些.h文件)
    • lib目录(空)
  • 测试目录(包含另一个main.c文件)
  • Makefile文件

2 个答案:

答案 0 :(得分:0)

安装GNU remake并运行remake -X

它将带您进入调试器,然后您可以运行step一步一步查看makefile在做什么。这是应用于您的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拍摄一些屏幕截图

答案 1 :(得分:0)

Make的输出显示其运行的命令。至少对于串行构建,这明确传达了产生每个诊断消息的命令产生的方式。在您的情况下,导致错误的命令将立即出现在输出中:

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

那怎么了?为什么呢,正是诊断程序所说的:它没有指定要操作的任何输入文件。无需编译C源文件,无需链接目标文件或库。没有什么可用来构建指定的输出文件的。

假设您已经提交了一个完整的makefile来产生问题,那么该命令必须来自尝试通过以下规则构建目标all

all: $(DEPEND_LST)
    $(COMP_ARGS)

表面上有点可疑,因为all目标通常仅提供先决条件列表,而不提供配方。然后可能需要构建的每个前提条件都有其自己的规则。但是提供食谱并非天生就错误,我们需要考虑食谱本身来确定问题的性质。在这种情况下,我们有第二点可疑:配方完全通过单个变量指定。但是我已经知道了,因为我必须首先进行追溯,才能将该规则确定为错误的来源。

特别是,文本bin/Main在makefile中出现的唯一位置是在此else块中:

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

这确实提供了all目标引用的命令行变量(并且没有其他内容),并且与导致错误的命令完全匹配。当将命令行的位与构建COMP_ARGS版本的变量匹配时,我们会发现什么?我们发现所有位都被OBJECTS以外的变量所覆盖,这些变量显然扩展为空(您甚至可以在其空值周围看到单独的前导和尾随空格字符)。为什么OBJECTS扩展为空值?因为在条件分支执行时永远不会设置

就个人而言,我倾向于重写整个makefile,使之更加惯用,并减少对GNU make扩展的依赖,但是最简单的前进方式可能是提出一个适当的建议。我指出的OBJECTS块中else变量的定义。