Makefile如何使用不同的目录来存放源代码和二进制文件?

27

我希望能够将我的二进制文件和代码文件分成不同的目录,因为在当前状态下管理变得困难。

理想情况下,我希望有

project_dir
|-Makefile
|-run_tests.sh
|
|__source
|  |-program1.cpp
|  |-program2.cpp
|
|__bin
   |-program1
   |-program2

然而,我无法在当前系统中使其工作,而不必手动为每个程序编写规则(请注意,每个程序都是单独的程序,而不是一系列链接在一起的对象)。

#Current make system
BIN=./bin/
SOURCE=./source/

LIST=program1 program2...

all: $(LIST)

%:  $(SOURCE)%.cpp
    $(CC) $(INC) $< $(CFLAGS) -o $(BIN)$@ $(LIBS)

这个代码有效,但是它不能在当前路径中找到目标,因此它会认为即使源文件没有改变,也需要重新构建二进制文件。

我现在唯一的想法是编写一个程序来生成makefile,但我不想这样做。


传统方法是将源代码目录称为“src”,在其中构建二进制文件,并有一个单独的步骤“安装”,该步骤将二进制文件复制到“bin”目录中 - 甚至有一种特殊的工具“install”来执行此操作。 - reinierpost
4个回答

29

你已经接近成功了...

#Current make system
BIN=./bin/
SOURCE=./source/

LIST=$(BIN)/program1 $(BIN)/program2...

all: $(LIST)

$(BIN)/%:  $(SOURCE)%.cpp
    $(CC) $(INC) $< $(CFLAGS) -o $@ $(LIBS)

您还可以通过使用以下方式使LIST更加简单:

PROG=program1 program2
LIST=$(addprefix $(BIN)/, $(PROG))

也许是个愚蠢的问题,但有没有办法在命令行上使用“%”变量(即无名称目录)。因此,“gcc blah blah -D%”(这样程序就知道它自己的名称)。 - 111111
3
可以使用 $* 获取词干。 - Didier Trosset
太好了,我觉得我的 makefile 差不多完成了,感谢你的所有帮助。 - 111111
我刚看到你添加了“addprefix”,这真是太好了,再次感谢 :) - 111111

6
这里是一个完整的Makefile版本,可以直接使用。
请按照以下目录结构准备文件夹: - .o文件:/build/ - .cpp文件:/src/ - 二进制文件:/bin/
然后在根目录(/)使用以下Makefile即可。
CC          = g++
LD          = g++ 
CFLAG       = -Wall
PROG_NAME   = prog

SRC_DIR     = ./src
BUILD_DIR   = ./build
BIN_DIR     = ./bin
SRC_LIST = $(wildcard $(SRC_DIR)/*.cpp)
OBJ_LIST = $(BUILD_DIR)/$(notdir $(SRC_LIST:.cpp=.o))

.PHONY: all clean $(PROG_NAME) compile

all: $(PROG_NAME)

compile: 
    $(CC) -c $(CFLAG) $(SRC_LIST) -o $(OBJ_LIST)

$(PROG_NAME): compile
    $(LD) $(OBJ_LIST) -o $(BIN_DIR)/$@

clean:
    rm -f $(BIN_DIR)/$(PROG_NAME) $(BUILD_DIR)/*.o

你的最终程序将被命名为/bin/中的prog,在每次编译代码时,二进制文件将分离到/build/以使源代码目录非常整洁干净。


3
您的解决方案可行,但会重建所有内容,有点可惜。 - Gabriel Devillers
3
这不仅仅是 "有点悲伤",而是完全违背了使用化妆品的初衷。-1 - Przemek D

2
简单的解决方法:使用automake
如果您想手动完成此操作,您需要使用vpath指令或VPATH环境变量。GNU make手册中有关于它们的一个部分。将Makefile直接放入bin目录中,将VPATH设置为源目录,隐式规则将再次起作用。

2
如果可以用一个良好制作的 make 文件完成,我不太喜欢 automake。 - 111111
升级了 vpath;不过,我不会说 autotools 很“容易”。 - Victor Sergienko

0

我有一个类似的情况,但是在C代码中,我尝试了上面的解决方案,但是没有一个对我有效(在Mac OSX操作系统上),所以我尝试了其他在stackoverflow上找到的解决方案,例如:https://dev59.com/c6_la4cB1Zd3GeqPu5En#53138757,结果将像下面的代码一样(您需要在相同的make文件目录下创建build文件夹,并随意更改变量中的其他文件夹名称以适合您的项目):

MKDIR    = mkdir
RMDIR    = rm -rf
CC       = clang    
BIN      = build/bin
OBJ      = build/obj
INCLUDE  = include
SRC      = src
CFLAGS   = -Wall -g -I$(INCLUDE)
LDLIBS   = -lm
SRCS     = $(wildcard $(SRC)/*.c)
OBJS     = $(patsubst $(SRC)/%.c,$(OBJ)/%.o,$(SRCS))
EXE      = $(patsubst $(SRC)/%.c,$(BIN)/%.exe,$(SRCS))

.PHONY: all clean

all: $(EXE)

$(EXE): $(OBJS) | $(BIN)

# linker
$(BIN)/%.exe: $(OBJ)/%.o
    $(CC) $(LDFLAGS) $< -o $@ $(LDLIBS)

# compiler  
$(OBJ)/%.o: $(SRC)/%.c | $(OBJ)
    $(CC) $(CFLAGS) -c $< -o $@

$(BIN) $(OBJ):
    $(MKDIR) $@

clean:
    $(RMDIR) $(OBJ) $(BIN)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接