1

我修改了gcc/g++ 选项,将所有对象文件放到我的场景的单独目录中。但是,运行时返回错误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

例如。:

主文件

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

using namespace std;

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

源.h

#include "Source.h"

#ifndef SOURCE_H
#define SOURCE_H

#include <iostream>

using namespace std;

class Source {

    public:
        static void hello();

};

#endif

源.cpp

#include "Source.h"

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

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

问题:make link

错误:

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.

我不知道如何解决。知道有什么问题吗?

4

1 回答 1

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不在同一个目录中,所以第一个规则不起作用。

我还添加.PHONY了 for和compile,因为它们不是“真正的目标”,它们只是用来告诉你想要做什么的名称。没关系,直到某个时候你碰巧有一个名为在你的目录中调用compile,并且不依赖任何其他东西,所以根据make没有什么可以做的)。linkcleancompilelinkcleancompile

(为了我自己的利益,我还添加了compileto的依赖项link,所以我不必键入make clean compile link,但可以使用 just make clean link)。

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

VPATH我认为可以使用例如变量或变量来做某事$(<F)......但我现在不知道怎么做。

于 2013-09-14T23:24:40.507 回答