如何将源对象编译到另一个目录,然后构建可执行文件?

时间:2019-05-12 16:00:05

标签: makefile directory compilation

美好的一天。我在目录中,在其中Makefile和文件夹src和bin。如何将目标文件编译到bin文件夹中,然后构建可执行文件?

我阅读了一些说明,并在%.o之前添加了$(BIN),但没有帮助,目标文件与makefile一起出现在文件夹中。问题出在哪里?

CC = arm-linux-gnueabihf-gcc
CXX = arm-linux-gnueabihf-g++
CPPFLAGS = -I .
CFLAGS =-g -std=gnu99 -O1 -Wall
CXXFLAGS = -g -std=gnu++11 -O1 -Wall
LDFLAGS = -lrt -lpthread
SRCDIR = src
BIN = bin
SOURCES = $(wildcard $(SRCDIR)/*.cpp) $(wildcard $(SRCDIR)/*.c)*
...
OBJECTS += $(filter %.o,$(SOURCES:%.c=%.o))
OBJECTS += $(filter %.o,$(SOURCES:%.cpp=%.o))
#$(warning OBJECTS=$(OBJECTS))
ifeq ($(filter %.cpp,$(SOURCES)),)
LINKER = $(CC)
LDFLAGS += $(CFLAGS) $(CPPFLAGS)
else
LINKER = $(CXX)
LDFLAGS += $(CXXFLAGS) $(CPPFLAGS)
endif
$(BIN)/%.o:%.c
    $(CC) $(CFLAGS) -c $<
$(BIN)/%.o:%.cpp
    $(CXX) $(CXXFLAGS) -c $<
all: $(TARGET_EXE)
$(TARGET_EXE): $(OBJECTS)
    $(LINKER) $(LDFLAGS) -L. $^ -o $@
.PHONY : dep all run copy-executable debug
dep: depend
depend: $(SOURCES) *.h
    echo '# autogenerat`enter code here`ed dependencies' > depend
ifneq ($(filter %.c,$(SOURCES)),)
    $(CC) $(CFLAGS) $(CPPFLAGS) -w -E -M $(filter %.c,$(SOURCES)) \
      >> depend
endif
ifneq ($(filter %.cpp,$(SOURCES)),)
    $(CXX) $(CXXFLAGS) $(CPPFLAGS) -w -E -M $(filter %.cpp,$(SOURCES)) \
      >> depend
endif
clean:
    rm -f *.o *.a $(OBJECTS) $(TARGET_EXE) connect.gdb depend
...

1 个答案:

答案 0 :(得分:0)

由于您尚未告知Makefile在哪里可以找到源文件(除非您在省略的部分之一中这样做),因此我不清楚此makefile的工作方式如何。

在这些规则中:

$(BIN)/%.o:%.c
    $(CC) $(CFLAGS) -c $<
$(BIN)/%.o:%.cpp
    $(CXX) $(CXXFLAGS) -c $<

您告诉编译器生成目标文件,但没有指定 where 来生成它们,默认是在工作目录中生成它们。您可以使用-o option来覆盖它:

$(BIN)/%.o:%.c
    $(CC) $(CFLAGS) -c $< -o $@
$(BIN)/%.o:%.cpp
    $(CXX) $(CXXFLAGS) -c $< -o $@

一旦将目标文件放在想要的位置(bin/),则必须确保链接规则:

$(TARGET_EXE):$(OBJECTS)
    $(LINKER) $(LDFLAGS) -L. $^ -o $@

可以找到它们。最好的方法是确保OBJECTS包含目标文件的正确路径。我不确定如何建议您这样做,因为从makefile的外观来看,该变量可能不包含您认为的内容。

编辑:

让我们分阶段进行。 假设我们在源文件src/foo.c上。我们想要的是:

src/foo.c -> bin/foo.o
bin/foo.o   -> foo

这需要两个规则,我们可以这样写:

$(BIN)/%.o: src/%.c
    $(CC) $(CFLAGS) -c $< -o $@

$(TARGET_EXE): bin/foo.o
    $(LINKER) $(LDFLAGS) -L. $^ -o $@

我们实际上有很多源文件,其中一些是C ++文件。因此,我们必须为他们制定规则:

$(BIN)/%.o: src/%.cpp
    $(CXX) $(CXXFLAGS) -c $< -o $@

并构造更长的对象列表:

OBJECTS := bin/foo.o bin/bar.o bin/baz.o bin/quartz.o...
$(TARGET_EXE): $(OBJECTS)
$(LINKER) $(LDFLAGS) -L. $^ -o $@

(混合C和C ++对我来说似乎很不健康,但没关系。)

我们如何构造对象列表?我们必须从wildcard可以产生的来源列表开始:

SRC := src
C_SOURCES := $(wildcard $(SRC/*.c)
# this is src/foo.c src/bar.c

SRC := src
CPP_SOURCES := $(wildcard $(SRC/*.cpp)
# this is src/baz.cpp src/quartz.cpp

,然后将它们转换为我们实际想要的目标文件名:

BIN := bin
OBJECTS := $(patsubst $(SRC)/%.cpp,$(BIN)/%.o, $(CPP_SOURCES))
OBJECTS += $(patsubst $(SRC)/%.c,$(BIN)/%.o, $(C_SOURCES))
# this is bin/foo.o bin/bar.o bin/baz.o bin/quartz.o

这应该可以给您想要的效果,如果您了解它,您就会明白为什么旧的makefile没有。