Makefile 在'中创建多个目标;全部';

Makefile 在'中创建多个目标;全部';,makefile,Makefile,我正在尝试使用Makefile构建一个库的调试和发布版本,并将这些库复制到相关的构建目录,例如 .PHONY: all clean distclean all: $(program_NAME_DEBUG) $(CP) $(program_NAME_DEBUG) $(BUILD_DIR)/debug/$(program_NAME_DEBUG) $(RM) $(program_NAME_DEBUG) $(RM) $(program_OBJS) $(program_N

我正在尝试使用Makefile构建一个库的调试和发布版本,并将这些库复制到相关的构建目录,例如

.PHONY: all clean distclean

all: $(program_NAME_DEBUG)
    $(CP) $(program_NAME_DEBUG) $(BUILD_DIR)/debug/$(program_NAME_DEBUG)
    $(RM) $(program_NAME_DEBUG)
    $(RM) $(program_OBJS)
    $(program_NAME_RELEASE)
    $(CP) $(program_NAME_RELEASE) $(BUILD_DIR)/release/$(program_NAME_RELEASE)
    $(RM) $(program_NAME_RELEASE)
    $(RM) $(program_OBJS)

$(program_NAME_DEBUG): $(program_OBJS)
    $(LINK_DEBUG.c) -shared -Wl,-soname,$(program_NAME_DEBUG) $(program_OBJS) -o $(program_NAME_DEBUG)

$(program_NAME_RELEASE): $(program_OBJS)
    $(LINK_RELEASE.c) -shared -Wl,-soname,$(program_NAME_RELEASE) $(program_OBJS) -o $(program_NAME_RELEASE)
第一个目标(program_NAME_DEBUG)编译正常,但第二个目标(program_NAME_RELEASE)生成以下错误:

libGlam_rel.so
make: libGlam_rel.so: Command not found
make: *** [all] Error 127
libGlam\u rel.so
program\u NAME\u RELEASE

它似乎没有像识别第一个目标那样识别第二个目标

编辑

终于让它工作了

一个问题是在多个目录中有src文件,使用VPATH对其进行排序,例如

# specify dirs other then current dir to search for src files
VPATH = ../../pulse_IO/src ../../../g2/src
在平台条件文件中添加了其他库目标,例如

# Platform specific conditional compilation
UNAME := $(shell uname)

TARGET := Glam

ifeq ($(UNAME), Linux)
# LINUX version
program_NAME := lib$(TARGET).so
program_DEBUG_NAME := lib$(TARGET)_dbg.so
program_RELEASE_NAME := lib$(TARGET)_rel.so
BUILD_DIR = ../build/linux
endif

ifeq ($(UNAME), MINGW32_NT-6.1)
# WINDOWS version
program_NAME := lib$(TARGET).dll
program_DEBUG_NAME := lib$(TARGET)_dbg.dll
program_RELEASE_NAME := lib$(TARGET)_rel.dll
BUILD_DIR = ../build/windows
endif
添加了新的调试和发布对象文件:

DEBUG_OBJS := $(addprefix $(BUILD_DIR)/debug/,${program_OBJS})
RELEASE_OBJS := $(addprefix $(BUILD_DIR)/release/,${program_OBJS})
设置我的调试和发布CFLAGS:

DEBUG_CFLAGS := -fPIC -g -Wall -DDEBUG=1
RELEASE_CFLAGS := -fPIC -O2 -Wall -DDEBUG=0
整理了所有调试和发布编译器选项:

DEBUG_LINK.c := $(CC) $(DEBUG_CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
RELEASE_LINK.c := $(CC) $(RELEASE_CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
将我的新规则添加到“全部”目标:

.PHONY: all clean

all: $(program_DEBUG_NAME) $(program_RELEASE_NAME)
规则集如下所示(包括隐式对象文件生成的替代):


这使我能够使用单个Makefile跨linux和windows平台生成库的调试和发布版本,例如,
$make-k

此更改应该可以:

all: $(program_NAME_DEBUG) $(program_NAME_RELEASE)

否则,
make all
将无法生成
$(程序名称发布)
,这就是错误消息告诉您的。

首先要做的事情。您似乎希望为这两个库提供不同版本的对象文件,但是这个makefile中没有提供这一点

有几种方法可以做到这一点。最干净的可能是有两个目录:

debug_objs/
  ang.o
  naur.o
  gul.o

release_objs/
  ang.o
  naur.o
  gul.o
第二个最干净的方法是使用不同的文件名:

  ang_debug.o
  naur_debug.o
  gul_debug.o

  ang_rel.o
  naur_rel.o
  gul_rel.o
无论哪种方式,您都可以为
RELEASE_OBJS
DEBUG_OBJS
编写规则(如果需要,我们可以提供帮助)

现在看一下库规则:

$(program_NAME_DEBUG): $(DEBUG_OBJS)
    $(LINK_DEBUG.c) -shared -Wl,-soname,$(program_NAME_DEBUG) $(DEBUG_OBJS) -o $(program_NAME_DEBUG)

$(program_NAME_RELEASE): $(RELEASE_OBJS)
    $(LINK_RELEASE.c) -shared -Wl,-soname,$(program_NAME_RELEASE) $(RELEASE_OBJS) -o $(program_NAME_RELEASE)
我们可以使用以下方法使其更加简洁:

$(program_NAME_DEBUG): $(DEBUG_OBJS)
    $(LINK_DEBUG.c) -shared -Wl,-soname,$@ $^ -o $@

$(program_NAME_RELEASE): $(RELEASE_OBJS)
    $(LINK_RELEASE.c) -shared -Wl,-soname,$@ $^ -o $@
(我们可以再往前走一点,但不要推。)

现在查看
所有
。我们将
$(程序名称发布)
移动到它所属的先决条件列表中:

all: $(program_NAME_DEBUG) $(program_NAME_RELEASE)
    $(CP) $(program_NAME_DEBUG) $(BUILD_DIR)/debug/$(program_NAME_DEBUG)
    $(RM) $(program_NAME_DEBUG)
    $(RM) $(DEBUG_OBJS)
    $(CP) $(program_NAME_RELEASE) $(BUILD_DIR)/release/$(program_NAME_RELEASE)
    $(RM) $(program_NAME_RELEASE)
    $(RM) $(RELEASE_OBJS)
但是没有理由删除对象文件,因为它们不会碰撞,如果它们是中间文件,Make将删除它们。当我们只需要
mv
时,就不需要
$(CP)
然后
$(RM)
。而且不需要
mv
;如果那是图书馆的所在地,我们可以首先在那里建立它们:

all: $(program_NAME_DEBUG) $(program_NAME_RELEASE)

$(program_NAME_DEBUG): $(DEBUG_OBJS)
    $(LINK_DEBUG.c) -shared -Wl,-soname,$@ $^ -o $(BUILD_DIR)/debug/$@

$(program_NAME_RELEASE): $(RELEASE_OBJS)
    $(LINK_RELEASE.c) -shared -Wl,-soname,$@ $^ -o $(BUILD_DIR)/release/$@
编辑:
要构建对象文件(我猜您使用的是C):

OBJS:=ang.o naur.o gul.o
DEBUG_OBJS:=$(addprefix DEBUG_OBJS/,$(OBJS))
RELEASE_OBJS:=$(addprefix RELEASE_OBJS/,$(OBJS))
debug_objs/%.o:$(源目录)/%.c
$(CC)$(调试标志)$<-o$@
release_objs/%.o:$(SOURCE_DIR)/%.c
$(CC)$(发布标志)$<-o$@

(只需确保这些目录存在——您也可以自动执行,但您一天内所做的更改已经足够了。)

谢谢您的尝试,但删除目标文件的顺序是否正确,例如,在构建库的调试版本和发布版本之间?这在构建这两个库时都有效,但是,因为在每种情况下都使用相同的对象文件(即,在构建之间不会删除它们),所以我实际上是在构建同一个库两次,而不是;这不是我想做的,我明白了。Makefiles可能很棘手,所以让我们仔细考虑一下。
$(program\u NAME\u DEBUG):
目标显然没有构建
libGlamdring\u rel.so
。您希望吗?嗯,编译标志是否应用于链接阶段?例如,相同的对象文件可用于构建调试和发布版本?通过您的修改,似乎为调试和发布版本生成了相同的库,即它们的大小完全相同,以前,当我使用不同的makefile构建调试版本和发布版本时,它们的大小不同,发布版本更小。这是一次尝试,让一个Makefile生成两个版本,而我不必在编译之间修改任何内容。这看起来很棒-我想我的部分困惑是,对象文件是自动生成的,而这不是我想要的,正如你所说,我希望有两个目标将这些对象文件生成两个dir,一个调试和一个发布目录-你是如何做到的?我可能会把简洁性的改进留给它生成文件的新手impenetrable@Hiett,我想改进图书馆的规则,但我不想一下子给你太多的打击…@Hiett,让我们一步一步来。你能构建一个对象(例如,
使debug_objs/ang.o
)吗?@Hiett,你确定吗?我知道makefiles有一个严酷的学习曲线,但这一条并没有那么糟糕,我很乐意带你走过它…为什么?我想我在这里正确地使用了vpath,即搜索源而不是目标?对于一个简单的makefile来说这很好,如果这就是你想要的,那就没关系了。如果您的项目开始使用相同名称的文件(尽管路径不同),您将遇到问题是的,我可以看出这将是一个潜在的问题
all: $(program_NAME_DEBUG) $(program_NAME_RELEASE)
    $(CP) $(program_NAME_DEBUG) $(BUILD_DIR)/debug/$(program_NAME_DEBUG)
    $(RM) $(program_NAME_DEBUG)
    $(RM) $(DEBUG_OBJS)
    $(CP) $(program_NAME_RELEASE) $(BUILD_DIR)/release/$(program_NAME_RELEASE)
    $(RM) $(program_NAME_RELEASE)
    $(RM) $(RELEASE_OBJS)
all: $(program_NAME_DEBUG) $(program_NAME_RELEASE)

$(program_NAME_DEBUG): $(DEBUG_OBJS)
    $(LINK_DEBUG.c) -shared -Wl,-soname,$@ $^ -o $(BUILD_DIR)/debug/$@

$(program_NAME_RELEASE): $(RELEASE_OBJS)
    $(LINK_RELEASE.c) -shared -Wl,-soname,$@ $^ -o $(BUILD_DIR)/release/$@
OBJS:= ang.o naur.o gul.o
DEBUG_OBJS := $(addprefix debug_objs/,$(OBJS))
RELEASE_OBJS := $(addprefix release_objs/,$(OBJS))

debug_objs/%.o: $(SOURCE_DIR)/%.c
    $(CC) $(DEBUG_FLAGS) $< -o $@

release_objs/%.o: $(SOURCE_DIR)/%.c
    $(CC) $(RELEASE_FLAGS) $< -o $@