使用文件夹的多个可执行文件的Makefile [英] Makefile for multiple executables with folders
问题描述
如何创建一个Makefile文件,该文件在具有多个可执行文件的项目中是简洁的。
我试着直接从Makefile文档中学习,但对我来说是压倒性的。
这是我的项目的一个例子。我发现了相关的问题,但他们只有一个可执行文件,我有兴趣编译所有不同的单元测试。
├──bin
├──include
│├── Action.h
│├──Consts.h
│├──Inventory.h
│├──Link.h
│├──Object.h
│├──Player.h
│├──Set.h
│├──Space.h
│├──World.h
│└──WorldXMLReader .h
├──主电源
│├──Prototype.c
│└──...使用main()的更多源文件
├──obj
│├──Makefile
│├──Set.o
│└──...更多目标文件
├──README.md
├──src
│├──Action.c
│├──Inventory.c
│├──Link.c
│├──Object.c
│├─ ─Player.c
│├──Set.c
│├──Space.c
│├──World.c
│└──WorldXMLReader.c
└──unitTest s
├──UT_Inventory.c
├──UT_Link.c
└──UT_Object.c
大多数make教程几乎没有涉及到这种情况:以通用的方式处理不同的文件集。
- 某些文件只是提供了一些实现(即使它们不会被编译为静态或动态库文件,也可以调用这些lib文件),
- 其他文件包含一个
main()
函数,并且每个函数都必须生成一个可执行二进制文件,并与前一个文件进行链接。
我不会在这里为您提供完整的makefile,但会尝试显示全局方法来处理这种情况。
首先,定义不同的源文件夹和目标文件夹:
SRC_DIR_LIB = src
SRC_DIR_EXE =主电源
OBJ_DIR_LIB = obj / lib
OBJ_DIR_EXE = obj / exe
BIN_DIR = bin
HEAD_DIR = i nclude
(这非常有用,因为如果有一天树组织发生变化,您只需要在一个点上编辑更改。)
而且,是的,您应该有单独的目标文件文件夹。
然后,定义源文件集:
SRC_FILES_LIB = $(通配符$(SRC_DIR_LIB) /*.c)
SRC_FILES_EXE = $(通配符$(SRC_DIR_EXE)/ *。c)
HEAD_FILES = $(通配符$(HEAD_DIR)/ *。h)
$ c $让make生成一组目标文件:
<$ c $ c> OBJ_FILES_LIB = $(patsubst $(SRC_DIR_LIB)/%。c,$(OBJ_DIR_LIB)/%。o,$(SRC_FILES_LIB))
OBJ_FILES_EXE = $(patsubst $(SRC_DIR_EXE)/%。c,$ (OBJ_DIR_EXE)/%。o,$(SRC_FILES_EXE))
让make生成一组可执行文件:
$ b
EXEC_FILES = $(patsubst $(SRC_DIR_EXE)/%。c,$(BIN_DIR)/%,$(SRC_FILES_EXE) )
这些是l是你的最终目标,你告诉你做:
全部:$(EXEC_FILES)
为了确保您拥有所有这些变量,您可以添加 show
目标到您的makefile:
show:
@echoSRC_FILES_LIB = $(SRC_FILES_LIB)
@ echoSRC_FILES_EXE = $(SRC_FILES_EXE)
..等等所有其他
尝试 make show
,并仔细检查。
$ b $ $ $ $ $(OBJ_DIR_EXE)/%。$(SRC_DIR_EXE)/%。c $( HEAD_FILES)
$(CC)-o $ @ -c $< $(CFLAGS)
$(OBJ_DIR_LIB)/%。o:$(SRC_DIR_LIB)/%。c $(HEAD_FILES)
$(CC)-o $ @ -c $< $(CFLAGS)
程序的链接步骤使用 subst()
函数:
$ $ $ $ BIN_DIR $%OBJ_DIR_EXE / %.o
$(CC)-o $ @ -s $(subst $(BIN_DIR)/,$(OBJ_DIR_EXE)/,$ @)。$(OBJ_FILES_LIB)$(LDFLAGS)
最终评论:
编辑: ,程序名称通常没有扩展名。如果是Windows,您可能需要在几处添加 .exe
。
How do you create a Makefile that is concise in a project with multiple executables. I tried learning directly from the Makefile documentation but it's overwhelming for me. This is an example of my project. I found questions that are related but they only have one executable and I'm interested in compiling all the different Unit-tests. I'm using gcc.
├── bin
├── include
│ ├── Action.h
│ ├── Consts.h
│ ├── Inventory.h
│ ├── Link.h
│ ├── Object.h
│ ├── Player.h
│ ├── Set.h
│ ├── Space.h
│ ├── World.h
│ └── WorldXMLReader.h
├── Mains
│ ├── Prototype.c
│ └── ... more source files with main()
├── obj
│ ├── Makefile
│ ├── Set.o
│ └── ... more object files
├── README.md
├── src
│ ├── Action.c
│ ├── Inventory.c
│ ├── Link.c
│ ├── Object.c
│ ├── Player.c
│ ├── Set.c
│ ├── Space.c
│ ├── World.c
│ └── WorldXMLReader.c
└── unitTests
├── UT_Inventory.c
├── UT_Link.c
└── UT_Object.c
You have a situation that is barely covered by most of the "make" tutorials: handling different sets of files in a generic way.
- Some files just provide some implementation (lets call these "lib" files, even if they are not going to be compiled into a static or dynamic library file),
- other files hold a
main()
function and each of these must produce an executable binary, and links with the previous.
I won't here give you an all-finished makefile, but will try to show a global method on how to handle this situation.
So first, define the different source and object folders:
SRC_DIR_LIB=src
SRC_DIR_EXE=Mains
OBJ_DIR_LIB=obj/lib
OBJ_DIR_EXE=obj/exe
BIN_DIR=bin
HEAD_DIR=include
(This is very useful because if one day the tree organisation changes, you will only have to edit the changes at a single point.)
And, yes, you should have separate folders for object files.
Then, define the sets of source files:
SRC_FILES_LIB = $(wildcard $(SRC_DIR_LIB)/*.c)
SRC_FILES_EXE = $(wildcard $(SRC_DIR_EXE)/*.c)
HEAD_FILES = $(wildcard $(HEAD_DIR)/*.h)
Let make generate the set of object files:
OBJ_FILES_LIB = $(patsubst $(SRC_DIR_LIB)/%.c,$(OBJ_DIR_LIB)/%.o,$(SRC_FILES_LIB))
OBJ_FILES_EXE = $(patsubst $(SRC_DIR_EXE)/%.c,$(OBJ_DIR_EXE)/%.o,$(SRC_FILES_EXE))
Let make generate the set of executable files:
EXEC_FILES = $(patsubst $(SRC_DIR_EXE)/%.c,$(BIN_DIR)/%,$(SRC_FILES_EXE))
These will be your final target, you tell that to make with:
all: $(EXEC_FILES)
To make sure you have all these variables right, you can add a show
target to your makefile:
show:
@echo "SRC_FILES_LIB=$(SRC_FILES_LIB)"
@echo "SRC_FILES_EXE=$(SRC_FILES_EXE)"
.. and so on for all the others
Try a make show
, and carefully check.
Then tell make how to do the real job. You need two separate compile targets:
$(OBJ_DIR_EXE)/%.o: $(SRC_DIR_EXE)/%.c $(HEAD_FILES)
$(CC) -o $@ -c $< $(CFLAGS)
$(OBJ_DIR_LIB)/%.o: $(SRC_DIR_LIB)/%.c $(HEAD_FILES)
$(CC) -o $@ -c $< $(CFLAGS)
And the linking step for the programs, that makes use of the subst()
function:
$(BIN_DIR)/%: $(OBJ_DIR_EXE)/%.o
$(CC) -o $@ -s $(subst $(BIN_DIR)/,$(OBJ_DIR_EXE)/,$@).o $(OBJ_FILES_LIB) $(LDFLAGS)
Final comments:
- here, only basic dependency checking is done: any editing of any header file will result in a rebuild of all the files. This is not acceptable for a large project, but is ok for a small project as the one you describe.
- I did not here consider the "test" programs that need to be build here, but once you understand whats up here, it should not be difficult to handle these.
- I did not test this (instead, kinda copy'n'pasted from a makefile of my own, that was a C++ project), so there might be some minor changes left. Manual writing of makefiles is an art...
Edit: This is targeted for a Linux based environment, where program names usually have no extension. If Windows, you probably will need to add .exe
at several places.
这篇关于使用文件夹的多个可执行文件的Makefile的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!