C语言 如何为带有 SRC、OBJ 和 BIN 子目录的 C 项目创建 Makefile?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7004702/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I create a Makefile for C projects with SRC, OBJ, and BIN subdirectories?
提问by Yanick Rochon
A few months ago, I came up with the following generic Makefilefor school assignments:
几个月前,我Makefile为学校作业提出了以下通用规则:
# ------------------------------------------------
# Generic Makefile
#
# Author: [email protected]
# 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!"
This will basically compile every .cand .hfile to generate .ofiles and the executable projectnameall in the same folder.
这将基本上每次编译.c和.h文件来生成.o文件和可执行文件projectname在同一文件夹的所有。
Now, I'd like to push this a little. How can I write a Makefile to compile a C project with the following directory structure?
现在,我想稍微推动一下。如何编写 Makefile 来编译具有以下目录结构的 C 项目?
./
./Makefile
./src/*.c;*.h
./obj/*.o
./bin/<executable>
In other words, I'd like to have a Makefile that compiles C sources from ./src/into ./obj/and then link everything to create the executable in ./bin/.
换句话说,我想有一个Makefile从编译C源文件./src/到./obj/,然后链接到的一切中创建可执行文件./bin/。
I've tried to read different Makefiles, but I simply can't make them work for the project structure above; instead, the project fails to compile with all sorts of errors. Sure, I could use full blown IDE (Monodevelop, Anjuta, etc.), but I honestly prefer to stick with gEdit and the good ol' terminal.
我尝试阅读不同的 Makefile,但我根本无法使它们适用于上面的项目结构;相反,该项目无法编译并出现各种错误。当然,我可以使用成熟的 IDE(Monodevelop、Anjuta 等),但老实说我更喜欢坚持使用 gEdit 和好的终端。
Is there a guru who can give me a working solution, or clear information about how this can be done? Thank you!
有没有大师可以给我一个可行的解决方案,或者关于如何做到这一点的明确信息?谢谢!
** UPDATE (v4)**
**更新 (v4)**
The final solution :
最终的解决方案 :
# ------------------------------------------------
# Generic Makefile
#
# Author: [email protected]
# Date : 2011-08-10
#
# Changelog :
# 2010-11-05 - first version
# 2011-08-10 - added structure : sources, objects, binaries
# thanks to http://stackoverflow.com/users/128940/beta
# 2017-04-24 - changed order of linker params
# ------------------------------------------------
# project name (generate executable with this name)
TARGET = projectname
CC = gcc
# compiling flags here
CFLAGS = -std=c99 -Wall -I.
LINKER = gcc
# linking flags here
LFLAGS = -Wall -I. -lm
# change these to proper directories where each file should be
SRCDIR = src
OBJDIR = obj
BINDIR = bin
SOURCES := $(wildcard $(SRCDIR)/*.c)
INCLUDES := $(wildcard $(SRCDIR)/*.h)
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
rm = rm -f
$(BINDIR)/$(TARGET): $(OBJECTS)
@$(LINKER) $(OBJECTS) $(LFLAGS) -o $@
@echo "Linking complete!"
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
@$(CC) $(CFLAGS) -c $< -o $@
@echo "Compiled "$<" successfully!"
.PHONY: clean
clean:
@$(rm) $(OBJECTS)
@echo "Cleanup complete!"
.PHONY: remove
remove: clean
@$(rm) $(BINDIR)/$(TARGET)
@echo "Executable removed!"
采纳答案by Beta
First, your $(OBJECTS)rule is problematic, because:
首先,您的$(OBJECTS)规则有问题,因为:
- it's kind of indiscriminate, making allsources prerequisites of every object,
- it often uses the wrong source(as you discovered with
file1.oandfile2.o) - it tries to build executables instead of stopping at objects, and
- the name of the target (
foo.o) is not what the rule will actually produce (obj/foo.o).
- 这有点不分青红皂白,使所有来源成为每个对象的先决条件,
- 它往往使用错误的来源(如你发现
file1.o和file2.o) - 它尝试构建可执行文件而不是停留在对象上,并且
- 目标名称 (
foo.o) 不是规则实际生成的名称 (obj/foo.o)。
I suggest the following:
我建议如下:
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $@
@echo "Compiled "$<" successfully!"
The $(TARGET)rule has the same problem that the target name does not actually describe what the rule builds. For that reason, if you type makeseveral times, Make will rebuild the target each time, even though there is no reason to. A small change fixes that:
该$(TARGET)规则具有相同的问题,即目标名称实际上并未描述规则构建的内容。因此,如果您make多次键入,Make 每次都会重建目标,即使没有理由这样做。一个小的改变修复了:
$(BINDIR)/$(TARGET): $(OBJECTS)
$(LINKER) $@ $(LFLAGS) $(OBJECTS)
@echo "Linking complete!"
Once that's all in order, you might consider more sophisticated dependency handling; if you modify one of the header files, this makefile will not know which objects/executables must be rebuilt. But that can wait for another day.
一旦一切就绪,您可能会考虑更复杂的依赖处理;如果您修改了其中一个头文件,则此 makefile 将不知道必须重建哪些对象/可执行文件。但这可以等到另一天。
EDIT:
Sorry, I omitted part of the $(OBJECTS)rule above; I've corrected it. (I wish I could use "strike" inside a code sample.)
编辑:
对不起,我省略了$(OBJECTS)上面规则的一部分;我已经改正了。(我希望我可以在代码示例中使用“strike”。)
回答by Tom
You can add the -Iflag to the compiler flags (CFLAGS) to indicate where the compiler should look for source files , and the -o flag to indicate where the binary should be left:
您可以将-I标志添加到编译器标志 (CFLAGS) 以指示编译器应在何处查找源文件,并添加 -o 标志以指示应将二进制文件留在何处:
CFLAGS = -Wall -I./src
TARGETPATH = ./bin
$(TARGET): obj
@$(LINKER) $(TARGETPATH)/$(TARGET) $(LFLAGS) $(OBJECTS)
@echo "Linking complete!"
In order to drop the object files into the objdirectory, use the -ooption when compiling. Also, look at the $@and $<automatic variables.
为了将目标文件放入obj目录中,请-o在编译时使用该选项。另外,看看$@和$<自动变量。
For example, consider this simple Makefile
例如,考虑这个简单的 Makefile
CFLAGS= -g -Wall -O3
OBJDIR= ./obj
SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o )
all:$(OBJS)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $(OBJDIR)/$@
Update>
更新>
By looking at your makefile, I realize you are using the -oflag. Good. Continue using it, but add a target directory variable to indicate where the output file should be written.
通过查看您的 makefile,我意识到您正在使用该-o标志。好的。继续使用它,但添加一个目标目录变量来指示应该写入输出文件的位置。
回答by Kamath
I have stopped writing makefiles these days, if your intention is to learn go ahead, else you have good makefile generator that comes with eclipse CDT. If you want some maintainability / multiple project support with in your build tree, have a look at the following -
这些天我已经停止编写 makefile,如果您的目的是学习,请继续,否则您拥有 eclipse CDT 附带的良好 makefile 生成器。如果您想在构建树中获得一些可维护性/多项目支持,请查看以下内容 -
https://github.com/dmoulding/boilermakeI found this pretty good..!
https://github.com/dmolding/boilermake我发现这很不错..!

