如何为具有SRC、OBJ和BIN子目录的C项目创建Makefile?
几个月前,我为学校作业提出了以下通用如何为具有SRC、OBJ和BIN子目录的C项目创建Makefile?,c,makefile,C,Makefile,几个月前,我为学校作业提出了以下通用Makefile: # ------------------------------------------------ # Generic Makefile # # Author: yanick.rochon@gmail.com # Date : 2010-11-05 # # Changelog : # 0.01 - first version # ------------------------------------------------ #
Makefile
:
# ------------------------------------------------
# Generic Makefile
#
# Author: yanick.rochon@gmail.com
# Date : 2010-11-05
#
# Changelog :
# 0.01 - first version
# ------------------------------------------------
# project name (generate executable with this name)
TARGET = projectname
CC = gcc -std=c99 -c
# compiling flags here
CFLAGS = -Wall -I.
LINKER = gcc -o
# linking flags here
LFLAGS = -Wall
SOURCES := $(wildcard *.c)
INCLUDES := $(wildcard *.h)
OBJECTS := $(SOURCES:.c=*.o)
rm = rm -f
$(TARGET): obj
@$(LINKER) $(TARGET) $(LFLAGS) $(OBJECTS)
@echo "Linking complete!"
obj: $(SOURCES) $(INCLUDES)
@$(CC) $(CFLAGS) $(SOURCES)
@echo "Compilation complete!"
clean:
@$(rm) $(TARGET) $(OBJECTS)
@echo "Cleanup complete!"
这将基本上编译每个.c
和.h
文件,以生成.o
文件和可执行文件projectname
都在同一文件夹中
现在,我想把这个推一推如何编写Makefile来编译具有以下目录结构的C项目?
./
./Makefile
./src/*.c;*.h
./obj/*.o
./bin/<executable>
您可以将
-I
标志添加到编译器标志(CFLAGS)中,以指示编译器应在何处查找源文件,-o标志指示二进制文件应保留在何处:
CFLAGS = -Wall -I./src
TARGETPATH = ./bin
$(TARGET): obj
@$(LINKER) $(TARGETPATH)/$(TARGET) $(LFLAGS) $(OBJECTS)
@echo "Linking complete!"
要将目标文件放入obj
目录,请在编译时使用-o
选项。另外,请查看$@
和$
通过查看makefile,我意识到您正在使用-o
标志。好。继续使用它,但添加一个目标目录变量以指示输出文件应写入的位置。首先,您的$(对象)
规则有问题,因为:
这有点不分青红皂白,把所有来源都当作每个物体的先决条件
它经常使用错误的源代码(正如您在file1.o
和file2.o
中发现的那样)
它尝试构建可执行文件,而不是停止在对象上,并且
目标(foo.o
)的名称不是规则实际生成的名称(obj/foo.o
)
我建议如下:
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $@
@echo "Compiled "$<" successfully!"
<>这一切都是有序的,你可能会考虑更复杂的依赖处理;如果修改其中一个头文件,此生成文件将不知道必须重建哪些对象/可执行文件。但这可以再等一天
编辑:
对不起,我省略了上面的$(OBJECTS)
规则的一部分;我已经改正了。(我希望我可以在代码示例中使用“strike”)这些天我已经停止编写makefiles,如果您的目的是学习继续,否则您就有eclipse CDT附带的好的makefile生成器。如果您希望在构建树中提供一些可维护性/多项目支持,请查看以下内容-
我觉得这个很好 这里的具体问题是什么?我不确定我是否理解你想要做什么。更新了Makefile
。我接近了,但我在自动变量方面有问题,所以不管怎样,我似乎刚刚找到了一个解决方案。如果有人想找到更好的,Makefile仍然可以改进。@YanickRochon我不是想批评你的英语技能。但是对于那些虚假的目标来说,你绝对不能写香蕉;)你能说得更具体些吗?您的意思是将-l…
添加到CFLAGS
和。。。链接器(linker
)已经有了-o
参数是的,CFLAGS,是的,继续使用-o,只需添加TARGETPATH变量。谢谢,我已经做了修改,但似乎仍然缺少一些东西(请参阅问题的更新)只是make
,从Makefile所在的位置可以读取正在执行的命令吗?例如gcc-cyadayada。非常确定有一个变量不包含您所建议的更改所需的内容,我得到:obj/file1.o:在函数“main”中:\n main.c:(.text+0x0):“main”的多个定义\n obj/main.o:main.c:(.text+0x0):首先在这里定义
@Yanick Rochon:您有多个main
函数吗?可能一个在file1.c
中,一个在main.c
中?如果是这样,您将无法链接这些对象;可执行文件中只能有一个main
。不,我没有。我在问题中发布的最后一个版本一切正常。当我将Makefile更改为您建议的内容时(我确实理解您所说内容的好处),这就是我得到的。我刚刚粘贴了file1.c
,但它为项目的每个文件提供了相同的消息。而main.c
是唯一一个具有main函数的。。。和main.c
导入file1.h
和file2.h
(在file1.c
和file2.c
之间没有关系),但我怀疑问题来自哪里。@Yanick Rochon:我粘贴$(对象)
规则的第一行时出错;我已经编辑过了。我有一个错误,但不是你的错误…基于观点。没有回答OP的问题。假定为Eclipse环境。
CFLAGS= -g -Wall -O3
OBJDIR= ./obj
SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o )
all:$(OBJS)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $(OBJDIR)/$@
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $@
@echo "Compiled "$<" successfully!"
$(BINDIR)/$(TARGET): $(OBJECTS)
$(LINKER) $@ $(LFLAGS) $(OBJECTS)
@echo "Linking complete!"