链接 LLVM IR 库

Linking LLVM IR Libraries

我正在关注 LLVM Kaleidoscope Tutorial (Ch. 3),并且在尝试 link LLVM IR 库后遇到错误(毫无疑问来自我的 Makefile)。我的 Makefile 和项目结构:

CPP=clang++
CFLAGS=-g -Wall -std=c++14
LDFLAGS:=$(shell llvm-config --cxxflags --ldflags --system-libs --libs core)

EXEC=comp.out
SRCS:=$(shell find src -type f -name '*.cpp')
OBJS:=$(patsubst %.cpp,%.o,$(SRCS))

all: $(EXEC)

$(EXEC): $(OBJS)
    $(CPP) $(CFLAGS) -o $@ $^

src/%.o: src/%.cpp
    $(CPP) $(CFLAGS) $(LDFLAGS) -o $@ $<

src/ast/%.o: src/ast/%.cpp
    $(CPP) $(CFLAGS) $(LDFLAGS) -o $@ $<

.PHONY: clean
clean:
    rm -f $(shell find src -type f -name '*.o')
    rm -f $(EXEC)
.
└── src
    ├── main.cpp
    ├── [.cpp files]
    │
    ├── ast
    │   ├── [.cpp files]
    │   │
    │   └── include
    │       └── [.h files]
    │  
    └── include
        └── [.h files]

制作时出现错误:

clang++ -g -Wall -std=c++14 -I/usr/local/Cellar/llvm/12.0.1/include -std=c++14 -stdlib=libc++   -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -L/usr/local/Cellar/llvm/12.0.1/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM-12 src/IMRep.cpp -o src/IMRep.o
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang-12: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Makefile:19: src/IMRep.o] Error 1

从上面的错误来看,main.cpp 在编译错误出现之前从未编译过。它只到达 src/IMRep.cpp 文件(不确定这是否重要)。如果我添加 -c 标志使其成为:

src/%.o: src/%.cpp
    $(CPP) $(CFLAGS) $(LDFLAGS) -c $< -o $@

src/ast/%.o: src/ast/%.cpp
    $(CPP) $(CFLAGS) $(LDFLAGS) -c $< -o $@

尽管有大量警告消息说 linker inputs/arguments 未使用,但我能够成功 运行 程序。这些警告是预料之中的,因为 -c 只编译而不 link.

main.cpp中:

#include <iostream>

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

所以这个问题不会被标记为骗局:

: main.cpp 包含在 OBJS
[2]:添加了 -c 标志并收到许多关于未使用 linker arguments/input 的警告(因为 -c 用于编译,而不是 linkage)
:我只在有一个依赖的地方使用$<,在有多个
的地方使用$^ : 无法应用此问题的答案
[5]: SRCSOBJS 中的所有文件都是正确的文件。我通过制定 'verbose' 规则并打印这些值和 make verbose

来验证这一点

这让我相信我没有正确地link使用这些库。

事实上,您的问题与那里的 #2 答案重复。

当您想要创建目标文件时,您必须 使用-c 选项。这就是 -c 选项的意思。

如果您不想要“大量警告消息说链接器 inputs/arguments 未使用”,那么,您知道的,不要添加链接器输入和参数 当你生成目标文件时!这些参数用于链接,而不是编译。

您的 .o 规则应该是:

src/%.o: src/%.cpp
        $(CPP) $(CFLAGS) -c $< -o $@

src/ast/%.o: src/ast/%.cpp
        $(CPP) $(CFLAGS) -c $< -o $@

只是指出您不需要上述两种模式规则。如果您希望目标文件与源文件位于同一目录中,您可以这样写:

%.o: %.cpp
        $(CPP) $(CFLAGS) -c $< -o $@

而且,如果您改用标准 make 变量而不是使用非标准变量:

# CPP is the C preprocessor, not C++
CXX = clang++
# CFLAGS is flags for the C compiler, not C++
CXXFLAGS := -g -Wall -std=c++14 $(shell llvm-config --cxxflags core)

LDFLAGS := $(shell llvm-config --ldflags --system-libs --libs core)

那么你根本不需要定义自己的模式规则,因为 make 有一个内置规则,它知道如何将 C++ 源文件编译成目标文件。