当srcdir!= objdir时的Makefile

时间:2013-09-14 21:42:12

标签: c++ makefile

我修改了我的方案的gcc/g++ option to place all object files into separate directory帖子。但是,运行make link时返回错误。

项目树

|--- bin
|    |--- main
|--- obj
|    |--- object1.o
|    |--- object2.o
|    |--- ...
|--- src
|    |--- source1.cpp
|    |--- source2.cpp
|    |--- ...
|--- main.cpp

生成文件

SRCDIR = ./src
OBJDIR = ./obj
BINDIR = ./bin
INCDIR = ./src

CC = g++

EXEC = main
SRC = $(wildcard $(SRCDIR)/*.cpp main.cpp)
OBJ = $(addprefix $(OBJDIR)/,$(notdir $(SRC:.cpp=.o)))

compile: $(OBJ)

$(OBJ): $(SRC)
    $(CC) -c $< -o $@

link:
    $(CC) -o $(EXEC) $(OBJ)

clean:
    find -type f -name "$(EXEC)" -delete
    find -type f -name "*.o" -delete
    find -type f -name "*~" -delete

例如:

的main.cpp

#include <iostream>
#include "Source.h"

using namespace std;

int main(int argc, char* argv[]) {
    Source::hello();
    return 0;
}

Source.h

#include "Source.h"

#ifndef SOURCE_H
#define SOURCE_H

#include <iostream>

using namespace std;

class Source {

    public:
        static void hello();

};

#endif

Source.cpp

#include "Source.h"

void Source::hello() {
    cout << "Hello Makefile" << endl;
}

make compile好的!创建所有对象(obj / * .o)

问题:make link

Erro:

g++ -o main ./obj/Source.o ./obj/main.o
./obj/main.o: In function `Source::hello()':
Source.cpp:(.text+0x0): multiple definition of `Source::hello()'

我知道问题

g++ -c src/Source.cpp -o obj/Source.o

g++ -c src/Source.cpp -o obj/main.o.

我不知道如何解决。 知道什么可能是错的吗?

1 个答案:

答案 0 :(得分:2)

它可能不是完美的解决方案,但这有效:

SRCDIR = ./src
OBJDIR = ./obj
BINDIR = ./bin
INCDIR = ./src

CC = g++

EXEC = main
SRC = $(wildcard $(SRCDIR)/*.cpp main.cpp)
OBJ = $(addprefix $(OBJDIR)/,$(notdir $(SRC:.cpp=.o)))

CXX_FLAGS = -I $(INCDIR) -Wall

.PHONY : compile
compile: $(OBJ)

$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
    $(CC) -c $(CXX_FLAGS) $< -o $@

$(OBJDIR)/main.o: main.cpp
    $(CC) -c $(CXX_FLAGS) $< -o $@

.PHONY : link
link: compile
    $(CC) -o $(EXEC) $(OBJ)

.PHONY : clean
clean:
    find -type f -name "$(EXEC)" -delete
    find -type f -name "*.o" -delete
    find -type f -name "*~" -delete

请注意,我已经制定了自动规则来编译所有SRCDIR来源,然后是main的特殊规则,因为main不在同一目录中,所以第一条规则不起作用。

我还为.PHONYcompilelink添加了clean,因为这些不是“真正的目标”,它们只是用来告诉你想做什么的名字完成。没关系,直到某个时候你碰巧在目录中有一个名为compilelinkclean的文件 - 此时你的makefile突然无法正常工作(例如,它没有“编译”,因为在你的目录中有一个名为compile的文件,compile不依赖于任何其他内容,因此根据make没有任何事情要做。)

(为了我自己的利益,我还为compile添加了link的依赖关系,因此我不必输入make clean compile link,而只能使用make clean link )。

正如评论中所讨论的,问题是由$<扩展为“规则中的第一个元素”引起的,它始终是srcdir/Source.cpp,而不是“对应于目标文件的任何源。

我认为可以使用例如VPATH$(<F)变量来做某事......但我现在无法弄明白。