2

我正在尝试使用 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.so是的价值program_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 以处理所有新文件:

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

4

2 回答 2

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_OBJS无论哪种方式,您都可以为and编写规则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_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 $@

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

于 2012-06-07T15:56:10.910 回答
1

这种改变应该做到:

all: $(program_NAME_DEBUG) $(program_NAME_RELEASE)

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

于 2012-06-07T09:29:40.290 回答