LLVM 5.0链接错误,使用llvm :: Module :: dump()方法

6
我过去两天一直在尝试将LLVM与我的C++项目链接,终于成功了,但问题是当我使用dump()方法时,会出现链接器错误。我认为问题出在我所链接的库中,所以我已经将可执行文件链接到了所有LLVM库(模块),但并没有成功。所以这是LLVM5.0代码库中的一个bug还是我做错了什么?我特别提到LLVM5.0是因为我在其他地方读到过(LLVM-5.0 Makefile undefined reference fail)评论部分中说使用LLVM4.0编译相同的代码没有问题,我当然也搜索了其他解决方案,但没有找到。 llvm_test.cpp:
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"

llvm::LLVMContext context;

int main(){
    llvm::Module*module = new llvm::Module("llvm-module",context);
    module->dump();
}

命令:

clang++ -O3  -Wall -std=c++11 `llvm-config --cppflags --ldflags` `llvm-config --libs core --system-libs` toy.cpp 

我已经链接了所有模块:

关于这一点,我已经链接了所有模块:

clang++ -O3 -Wall -std=c++11 `llvm-config --cxxflags --ldflags` `llvm-config --libs all --system-libs` toy.cpp 

编译器:Apple Clang 8.0.0 x86_64

操作系统:macOS 10.12.5

提前感谢您的任何帮助。


1
很遗憾,LLVM 5在发布模式下不包括转储实现。您必须使用调试构建或使用替代函数(例如print)。 - Kuba Beránek
2个回答

16

好的,我查看了llvm的代码,你实际上可以更容易地完成它。你所需做的就是停止使用dump,而是:

module->print(llvm::errs(), nullptr);

这正是 `dump` 内部所做的。


2
所以,在解决问题后,我终于找到了一个简单的方法来解决问题。解决方案的一部分是回答上面链接中的那个人提供的,但我将为该问题提供完整的解决方案。在回答问题之前,我需要引起您的注意,这个解决方案适用于LLVM5.0,所以我不知道它是否适用于其他版本。
首先,我复制了llvm::LLVMContext::dump的定义,从文件AsmWriter.cpp中,您可以在此文件的末尾找到各种llvm::Dump方法的定义,我复制了它们以备将来使用。我将写出我使用的LLVMDump.cpp的内容。
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/AssemblyAnnotationWriter.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSlotTracker.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/Statepoint.h"
#include "llvm/IR/TypeFinder.h"
#include "llvm/IR/UseListOrder.h"
#include "llvm/IR/ValueSymbolTable.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include <algorithm>
#include <cctype>
using namespace llvm;
LLVM_DUMP_METHOD
void Value::dump() const { print(dbgs(), /*IsForDebug=*/true); dbgs() << '\n'; }

// Type::dump - allow easy printing of Types from the debugger.
LLVM_DUMP_METHOD
void Type::dump() const { print(dbgs(), /*IsForDebug=*/true); dbgs() << '\n'; }

// Module::dump() - Allow printing of Modules from the debugger.
LLVM_DUMP_METHOD
void Module::dump() const {
    print(dbgs(), nullptr,
            /*ShouldPreserveUseListOrder=*/false, /*IsForDebug=*/true);
}

// \brief Allow printing of Comdats from the debugger.
LLVM_DUMP_METHOD
void Comdat::dump() const { print(dbgs(), /*IsForDebug=*/true); }

// NamedMDNode::dump() - Allow printing of NamedMDNodes from the debugger.
LLVM_DUMP_METHOD
void NamedMDNode::dump() const { print(dbgs(), /*IsForDebug=*/true); }

LLVM_DUMP_METHOD
void Metadata::dump() const { dump(nullptr); }

LLVM_DUMP_METHOD
void Metadata::dump(const Module *M) const {
    print(dbgs(), M, /*IsForDebug=*/true);
    dbgs() << '\n';
}

请注意,我已将旧的包含目录 #include "llvm/Support/Dwarf.h" 更改为 #include "llvm/BinaryFormat/Dwarf.h"
其次,我已将 LLVMDUmp.cpp 编译为静态库,以便在需要时链接使用。
如果您不知道如何在 Mac 上创建静态链接库,因为 -static 标志在 Mac 上无法与 clang 或 gcc 一起使用。
clang++ -std=c++1z -O3 -c LLVMDump.cpp -o LLVMDump.o 

接下来是创建静态链接库的步骤

ar -rv libLLVMDump.a LLVMDump.o 

现在只需将libLLVMDump.a移动到计算机上的lib目录中,以便在需要时使用它(如果您不知道应从llvm安装中设置lib目录的位置),请使用llvm-config。

llvm-config --lib-dir

它会显示你应该把llvm/lib目录放在哪里,这是安装位置。

测试:如果您想要,可以使用问题中的代码。

clang++ -O3 -Wall -std=c++1z -L /path/lib -lLLVMCore -lLLVMBinaryFormat -lLLVMSupport -lLLVMDemangle -lLLVMDump  llvmtest.cpp

请注意,LLVMDump是我们刚刚创建的。

希望这能对大家有所帮助,祝编程愉快。


1
这似乎非常复杂。我遇到了同样的问题,我正在使用bazel构建,但我希望有更好的方法来处理这个问题 :-/ - gruszczy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接