如何使用LLVM命令将GHC LLVM后端生成的*.ll文件编译为可执行文件
问题解答及操作步骤
关于Paths_projectname.ll的必要性
该文件是Stack自动生成的辅助模块,仅存储项目版本、安装路径等元数据:
- 如果你的
Main.hs、Lib.hs中没有导入Paths_<你的项目名>模块,也没有调用该模块提供的路径查询类接口,完全不需要使用该文件参与编译 - 只有当代码显式依赖该模块时才需要加入编译链路
完整编译操作步骤
你之前操作失败的核心原因是GHC生成的LLVM IR依赖GHC运行时系统(RTS)及Haskell核心库符号,仅编译自有代码生成的目标文件会缺失依赖。完整操作流程如下:
版本兼容性校验
首先确认你使用的LLVM版本和当前GHC版本匹配,比如GHC 9.2对应LLVM 12、GHC 9.4对应LLVM 14,版本不兼容会导致llc生成异常目标文件。将LLVM IR转为比特码
llvm-as Main.ll -o Main.bc llvm-as Lib.ll -o Lib.bc # 如需使用Paths模块则加下一行 # llvm-as Paths_projectname.ll -o Paths_projectname.bc
- 链接自有比特码文件
# 不需要Paths模块就去掉参数里的Paths_projectname.bc llvm-link Main.bc Lib.bc Paths_projectname.bc -o merged.bc
- 比特码转目标文件
llc -filetype=obj -relocation-model=pic merged.bc -o project.o
- 链接生成可执行文件
两种方案可选,优先选第一种避免手动处理依赖:
- 方案1:用GHC完成最终链接(自动补全RTS及依赖库参数)
ghc project.o -o project-exe - 方案2:手动用gcc/clang链接,先执行
ghc --print-libdir获取GHC库目录,再执行:gcc project.o -o project-exe -L<替换为你的GHC库目录> -lHSrts-<替换为你的GHC版本> -lbase-<替换为base库版本> -lm -ldl -lpthread # 用到其他Haskell依赖的话,对应添加-l<包名>-<版本号>-ghc<版本号>参数即可
常见问题排查
- 出现大量未定义符号:优先检查是否漏加依赖库、LLVM与GHC版本是否匹配
- 运行可执行文件提示找不到动态库:将GHC库目录加入
LD_LIBRARY_PATH环境变量即可
内容的提问来源于stack exchange,提问作者Anon
相关产品推荐
相关产品推荐

