我正在尝试为新项目创建一个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。 文件层次结构是:
答案 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
变量的定义。