【问题标题】:Linking LLVM IR Libraries链接 LLVM IR 库
【发布时间】:2021-08-08 12:23:11
【问题描述】:

我正在关注LLVM Kaleidoscope Tutorial (Ch. 3),在尝试链接 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 $@

尽管有大量警告消息说链接器输入/参数未使用,但我仍然能够成功运行程序。这些警告是意料之中的,因为-c 只编译而不链接。

main.cpp:

#include <iostream>

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

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

[1]main.cpp 包含在OBJS
[2]:添加了-c 标志并收到许多关于未使用的链接器参数/输入的警告(因为-c 用于编译,而不是链接)
[3]:我只在有一个依赖的地方使用$&lt;,在有多个依赖的地方使用$^
[4]:无法应用此问题的答案
[5]:全部SRCSOBJS 中的文件是正确的文件。我通过制定“详细”规则并打印这些值和make verbose

来验证这一点

这让我相信我没有正确链接这些库。

【问题讨论】:

  • @AlexF 我项目中的所有.cpp 文件,包括main.cpp
  • 你在 src/IMRep.cpp 中有什么?那里有 main 函数吗?
  • @MaximChetrusca 只是一个包含 LLVM IR 标头的类定义

标签: c++ makefile llvm-ir


【解决方案1】:

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

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

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

您的.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++ 源文件编译成目标文件。

【讨论】:

  • 感谢您的意见。但是我不需要添加链接器参数来引入 LLVM IR 库吗?如果我不包含参数,我只会从我的包含中得到"llvm/ir/*.h" file not found 错误。也许我对这整个过程有错误的想法。
  • 您将库添加到链接行而不是编译行。您在编译行而不是链接行中添加包含目录(以查找标题)。我用一个例子更新了我的答案。
猜你喜欢
  • 2017-03-14
  • 2017-03-14
  • 1970-01-01
  • 1970-01-01
  • 2013-11-17
  • 1970-01-01
  • 1970-01-01
  • 2017-04-09
  • 2014-10-30
相关资源
最近更新 更多