遵循本教程:
http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/
它有3个文件,其中2个是.c
个文件和1个.h
文件。本教程是关于设置makefile的,前几步是有效的。最后一步涉及为.h
和.c
文件设置目录路径。我已将.c
个文件放在src文件中,将.h
个文件放在包含文件中。
看起来像/home/bob/testcode/src
< - 包含.c
个文件。
/home/bob/testcode/include
< - 包含.h
个文件。
代码:
IDIR =../include
CC=gcc
CFLAGS=-I$(IDIR)
ODIR=obj
LDIR =../lib
_DEPS = hellomake.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
_OBJ = hellomake.o hellofunc.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
$(ODIR)/%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
hellomake: $(OBJ)
gcc -o $@ $^ $(CFLAGS)
.PHONY: clean
clean:
rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~
我想了解它是如何工作的,然后在我正在使用的库上使用它。有人可以指点我如何设置此代码?我已经尝试了很多选项"/home/bob/testcode/include/"
w /和"
以及/
,但我仍然无法使用它。
目标是使用包含60多个头文件和30个源文件的库,从这些文件中我必须运行1个main,所以我真的需要让这个基本的makefile工作,所以我可以扩展它
一般问题是这些线路是否开放:
IDIR =../include
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
和
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
我已尝试过多种不同的路径替换,但我生成的错误说:
gcc -o hellomake -I../include
gcc: fatal error: no input files
compilation terminated.
make: *** [hellomake] Error 4
请提前帮助,谢谢。
答案 0 :(得分:29)
你的教程会促进不良做法,你应该避免它恕我直言。
在你的规则中:
$(ODIR)/%.o: %.c $(DEPS)
当您的源文件位于src
目录中时,您告诉make查看当前目录,因此从未使用此模式,并且您没有合适的模式。
确保按照以下方式组织项目目录:
+ include/
|-- all .h files here
+ lib/
|-- all thirdparty library files (.a files) here
+ obj/
|-- all .o files will be placed here
+ src/
|-- all .c files here
+ Makefile
然后让我们一步一步地使用好的做法。
首先,如果您不需要,请不要定义任何内容。 Make有很多预定义的变量和函数,在尝试手动执行之前应该使用它们。事实上,他有这么多,你甚至可以编译一个简单的项目,甚至根本没有Makefile!
命名您的最终目标,即您的可执行文件:
EXE = hellomake
列出您的源和构建输出目录:
SRC_DIR = src
OBJ_DIR = obj
列出您的源文件:
SRC = $(wildcard $(SRC_DIR)/*.c)
从源文件中列出目标文件:
OBJ = $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) # patsubst is far less readable
# You can also do it like that
OBJ = $(addprefix $(OBJ_DIR)/, $(notdir $(SRC)))
有一些预处理器标志要通过吗?继续。
CPPFLAGS += -Iinclude # -I is a preprocessor flag, not a compiler flag
要添加一些编译器标志吗?你走了。
CFLAGS += -Wall # some warnings about bad code
有一些链接器标志吗?
LDFLAGS += -Llib # -L is a linker flag
有一些第三方库要链接吗?
LDLIBS += -lm # Left empty if no libs are needed
好的,现在我们已经正确地填充了一些食谱。
广泛传播的默认目标应该称为all
。为简单起见,它应该是Makefile中的第一个目标,它的先决条件应该是您在命令行上编写make
时要构建的目标:
all: $(EXE)
现在列出构建可执行文件的先决条件,并填写其配方以告知如何处理这些:
$(EXE): $(OBJ)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
一些快速说明:
$(CC)
是一个内置变量,已包含在C中编译和链接时所需的内容,$(LDFLAGS)
和$(LDLIBS)
无用,编译阶段已经结束,这是链接阶段。下一步,由于您的源文件和目标文件不共享相同的前缀,因此您需要告诉make确切要做什么,因为其内置规则不会涵盖您的具体案例:
$(CPPFLAGS)
好的,现在可执行文件应该很好地构建,如果需要,我们可以清理构建目录:
$(CFLAGS)
最后一件事。您应该指明规则何时不生成具有$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
特殊规则的任何目标输出:
clean:
$(RM) $(OBJ)
最终结果:
.PHONY
答案 1 :(得分:0)
简单的Makefile定义对我来说似乎没问题,因为它们出现在您的问题中。尝试在文件名之前指定编译器选项:
$(ODIR)/%.o: %.c $(DEPS)
$(CC) $(CFLAGS) -c -o $@ $<
hellomake: $(OBJ)
gcc $(CFLAGS) -o $@ $^
您需要从源目录运行make
。
答案 2 :(得分:0)
make实用程序,没有特定的&#39;目标&#39;将成为文件中的第一个目标。
第一个目标通常命名为&#39; all&#39;
对于已发布的文件,将生成目标文件,并且在命令行中未指定目标时将不会继续生成可执行文件
建议如下:
SHELL := /bin/sh
# following so could define executable name on command line
# using the '-D' parameter
#ifndef $(NAME)
NAME := hellomake
#endif
# use ':=' so macros only evaluated once
MAKE := /usr/bin/make
CC := /usr/bin/gcc
CFLAGS := -g -Wall -Wextra -pedantic
LFLAGS :=
ODIR := obj
IDIR := ../include
LIBS :=
LIBPATH := ../lib
DEPS := $(wildcard $(IDIR)/*.h)
SRCS := $(wildcard *.c)
OBJS := $(SRCS:.c=.o)
.PHONY: all
all: $(NAME) $(OBJS)
$(ODIR)/%.o: %.c $(DEPS)
$(CC) $(CFLAGS) -c -o $@ $< -I$(DEPS)
$(NAME): $(OBJS)
$(CC) $(LFLAGS) -o $@ $^ -L$(LIBPATH) -l$(LIBS)
.PHONY: clean
clean:
rm -f $(ODIR)/*.o
rm -f $(NAME)
however, in your proposed project,
not every source file needs every header file
so should use either gcc or sed to generate the dependency files
then use makefile rules similar to the following,
which may need a little 'tweaking' for your project
because the include files are not in the same directory
as the source files:
DEP := $(SRCS:.c=.d)
#
#create dependency files
#
%.d: %.c
#
# ========= START $< TO $@ =========
$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
# ========= END $< TO $@ =========
#
# compile the .c files into .o files using the compiler flags
#
%.o: %.c %.d
#
# ========= START $< TO $@ =========
$(CC) $(CCFLAGS) -c $< -o $@ -I$(IDIR)
# ========= END $< TO $@ =========
#
# include the contents of all the .d files
# note: the .d files contain:
# <filename>.o:<filename>.c plus all the dependencies for that .c file
# I.E. the #include'd header files
# wrap with ifneg... so will not rebuild *.d files when goal is 'clean'
#
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEP)
endif