在'所有'中制作多个目标

时间:2012-06-07 09:17:34

标签: 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_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_rel.soprogram_NAME_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)

规则集如下所示(包括隐式目标文件生成的替代):

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

$(program_RELEASE_NAME): $(RELEASE_OBJS)
    $(RELEASE_LINK.c) -shared -Wl,-soname,$@ $^ -o $(BUILD_DIR)/release/$@

# rule to build object files (replaces implicit rule)
$(BUILD_DIR)/debug/%.o: %.c
    $(DEBUG_LINK.c) $< -c -o $@

$(BUILD_DIR)/release/%.o: %.c
    $(RELEASE_LINK.c) $< -c -o $@

并完成我修改干净以处理所有新文件:

clean:
    @- $(RM) $(BUILD_DIR)/debug/$(program_DEBUG_NAME)
    @- $(RM) $(DEBUG_OBJS)
    @- $(RM) $(BUILD_DIR)/release/$(program_RELEASE_NAME)
    @- $(RM) $(RELEASE_OBJS)

这有助于我使用单个Makefile在Linux和Windows平台上生成我的库的调试和发布版本,例如: $ make -k

2 个答案:

答案 0 :(得分:2)

首先要做的事情。您似乎想要两个库的目标文件的不同版本,但此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_OBJSDEBUG_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)

我们可以使用Automatic Variables让它们更简洁:

$(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_RELEASE)移动到它所属的先决条件列表中:

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会将它们删除。当我们只能$(CP)时,就不需要$(RM)然后mv。并且没有必要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: $(SOURCE_DIR)/%.c
    $(CC) $(DEBUG_FLAGS) $< -o $@

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

(只要确保这些目录存在 - 你也可以自动化,但是你在一天内做了足够的更改。)

答案 1 :(得分:1)

这种改变应该这样做:

all: $(program_NAME_DEBUG) $(program_NAME_RELEASE)

否则,make all无法生成$(program_NAME_RELEASE),这就是错误消息告诉您的内容。

相关问题