一个完整的cmake+clang+llvm编译链接hello-world过程

本文详细介绍如何使用Clang+LLVM编译器,并通过CMake进行项目配置,包括设置编译器、编译选项、链接库等步骤,提供了一个完整的hello-world示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

相信目前使用clang+llvm大有人在,我的系统ubuntu18.04前段时间刚安装了不少软件,习惯性的也会装上gcc/g++和clang/clang++,关于如何在两个编译器之间切换这里不再赘述,可能参考下面的链接:
Switching between GCC and Clang/LLVM using CMake

写这个贴子是因为clang/clang++在网上大都没有一个完整的例子,大部分讲完clang就完事了,后面的链接部分语焉不详,所以这里给出一个完整的hello-world记录。

源码

main.c

#include <stdio.h>

int main() {
	printf("Hello World.\n");
	
	return 0;
}

CMakeLists.txt
(参考:https://releases.llvm.org/5.0.0/docs/CMake.html )
(参考:https://llvm.org/docs/CMake.html)

cmake_minimum_required(VERSION 3.7.1)

project(hello-world)

find_package(LLVM REQUIRED CONFIG)

set(SOURCE_FILES main.c)

message(STATUS "This is BINARY dir " ${PROJECT_BINARY_DIR})
message(STATUS "This is SOURCE dir " ${PROJECT_SOURCE_DIR})
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")

# Set your project compile flags.
# E.g. if using the C++ header files
# you will need to enable C++11 support
# for your compiler.

include_directories(${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})

# Now build our tools
add_executable(hello-world ${SOURCE_FILES})


# Find the libraries that correspond to the LLVM components
# that we wish to use
llvm_map_components_to_libnames(llvm_libs support core irreader)

# Link against LLVM libraries
target_link_libraries(hello-world ${llvm_libs})

linux.toolchain.cmake

cmake_minimum_required( VERSION 2.6.3 )
set(CMAKE_SYSTEM_NAME Linux )

SET (CMAKE_C_COMPILER             "/usr/bin/clang")
SET (CMAKE_C_FLAGS                "-Wall -std=c99")
SET (CMAKE_C_FLAGS_DEBUG          "-g")
SET (CMAKE_C_FLAGS_MINSIZEREL     "-Os -DNDEBUG")
SET (CMAKE_C_FLAGS_RELEASE        "-O4 -DNDEBUG")
SET (CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g")

SET (CMAKE_CXX_COMPILER             "/usr/bin/clang++")
SET (CMAKE_CXX_FLAGS                "-Wall")
SET (CMAKE_CXX_FLAGS_DEBUG          "-g")
SET (CMAKE_CXX_FLAGS_MINSIZEREL     "-Os -DNDEBUG")
SET (CMAKE_CXX_FLAGS_RELEASE        "-O4 -DNDEBUG")
SET (CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")

SET (CMAKE_AR      "/usr/bin/llvm-ar")
SET (CMAKE_LINKER  "/usr/bin/llvm-ld")
SET (CMAKE_NM      "/usr/bin/llvm-nm")
SET (CMAKE_OBJDUMP "/usr/bin/llvm-objdump")
SET (CMAKE_RANLIB  "/usr/bin/llvm-ranlib")

 

编译生成

这个其实就两条命令:
$ cmake  -DCMAKE_TOOLCHAIN_FILE=./linux.toolchain.cmake  .
$ make VERBOSE=1
VERBOSE是因为要输出更多的信息(毕竟是在学习嘛),可以看到链接的详细情况。

$ cmake  -DCMAKE_TOOLCHAIN_FILE=./linux.toolchain.cmake  .
-- The C compiler identification is Clang 6.0.0
-- The CXX compiler identification is Clang 6.0.0
-- Check for working C compiler: /usr/bin/clang
-- Check for working C compiler: /usr/bin/clang -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/clang++
-- Check for working CXX compiler: /usr/bin/clang++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- This is BINARY dir /home/matthew/devc/cmake/hello-world
-- This is SOURCE dir /home/matthew/devc/cmake/hello-world
-- Found LLVM 6.0.0
-- Using LLVMConfig.cmake in: /usr/lib/llvm-6.0/cmake
-- Configuring done
-- Generating done
-- Build files have been written to: /home/matthew/devc/cmake/hello-world

$ make VERBOSE=1
/usr/bin/cmake -H/home/matthew/devc/cmake/hello-world -B/home/matthew/devc/cmake/hello-world --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /home/matthew/devc/cmake/hello-world/CMakeFiles /home/matthew/devc/cmake/hello-world/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: 进入目录“/home/matthew/devc/cmake/hello-world”
make -f CMakeFiles/hello-world.dir/build.make CMakeFiles/hello-world.dir/depend
make[2]: 进入目录“/home/matthew/devc/cmake/hello-world”
cd /home/matthew/devc/cmake/hello-world && /usr/bin/cmake -E cmake_depends "Unix Makefiles" 
/home/matthew/devc/cmake/hello-world /home/matthew/devc/cmake/hello-world 
/home/matthew/devc/cmake/hello-world /home/matthew/devc/cmake/hello-world 
/home/matthew/devc/cmake/hello-world/CMakeFiles/hello-world.dir/DependInfo.cmake --color=
make[2]: 离开目录“/home/matthew/devc/cmake/hello-world”
make -f CMakeFiles/hello-world.dir/build.make CMakeFiles/hello-world.dir/build
make[2]: 进入目录“/home/matthew/devc/cmake/hello-world”
[ 50%] Linking CXX executable hello-world
/usr/bin/cmake -E cmake_link_script CMakeFiles/hello-world.dir/link.txt --verbose=1
/usr/bin/clang++     CMakeFiles/hello-world.dir/main.c.o  -o hello-world 
/usr/lib/llvm-6.0/lib/libLLVMSupport.a /usr/lib/llvm-6.0/lib/libLLVMCore.a 
/usr/lib/llvm-6.0/lib/libLLVMIRReader.a /usr/lib/llvm-6.0/lib/libLLVMAsmParser.a 
/usr/lib/llvm-6.0/lib/libLLVMBitReader.a /usr/lib/llvm-6.0/lib/libLLVMCore.a 
/usr/lib/llvm-6.0/lib/libLLVMBinaryFormat.a /usr/lib/llvm-6.0/lib/libLLVMSupport.a 
-lz -lrt -ldl -ltinfo -lpthread -lm /usr/lib/llvm-6.0/lib/libLLVMDemangle.a 
make[2]: 离开目录“/home/matthew/devc/cmake/hello-world”
[100%] Built target hello-world
make[1]: 离开目录“/home/matthew/devc/cmake/hello-world”
/usr/bin/cmake -E cmake_progress_start /home/matthew/devc/cmake/hello-world/CMakeFiles 0

注意,如果不在当前目录下,则需要根据实际情况设置目录,如

export  CURRENT_SCRIPT_DIR=/home/matthew/devc/cmake/hello-world
cmake  -DCMAKE_TOOLCHAIN_FILE=${CURRENT_SCRIPT_DIR}/linux.toolchain.cmake  .

关于LLVM宏定义

LLVM相关的宏定义都在文件LLVMConfig.cmake中,一般情况下默认的路径如下所示
 /usr/lib/llvm-6.0/cmake/LLVMConfig.cmake

如果你仔细阅读一下就会发现,LLVM_INCLUDE_DIRSLLVM_INCLUDE_DIR是完全一样的,如下,
set(LLVM_INSTALL_PREFIX "/usr/lib/llvm-6.0")
......
set(LLVM_INCLUDE_DIRS "${LLVM_INSTALL_PREFIX}/include")
set(LLVM_LIBRARY_DIRS "${LLVM_INSTALL_PREFIX}/lib${LLVM_LIBDIR_SUFFIX}")
# These variables are duplicated, but they must match the LLVM variables of the
# same name. The variables ending in "S" could some day become lists, and are
# preserved for convention and compatibility.
set(LLVM_INCLUDE_DIR "${LLVM_INSTALL_PREFIX}/include")
set(LLVM_LIBRARY_DIR "${LLVM_INSTALL_PREFIX}/lib${LLVM_LIBDIR_SUFFIX}")

参考资料

下面是一些写得比较好的贴子或文档网址,记录一下,
https://blog.youkuaiyun.com/dashuniuniu/article/details/50385528
https://www.ibm.com/developerworks/cn/opensource/os-cn-clang/
https://llvm.org/pubs/

### clang++ 编译错误解决方案 当遇到 `clang++` 报错 `/usr/bin/ld: cannot find -lc++abi` 或者 `fatal error: 'iostream' file not found` 时,通常是因为编译环境配置不正确或者缺少必要的依赖项。 #### 1. 安装缺失的库 如果提示无法找到 `-lc++abi`,这表明系统中可能未安装 `libc++abi` 库。可以通过包管理工具安装该库: 对于基于 Debian 的 Linux 发行版(如 Ubuntu),可以执行以下命令来安装所需的库: ```bash sudo apt-get update sudo apt-get install libc++-dev libc++abi-dev ``` 对于 macOS 用户,确保已通过 Homebrew 安装 LLVM 和其相关组件: ```bash brew install llvm ``` 之后,在编译时指定正确的路径以定位标准库文件[^1]。 --- #### 2. 配置正确的头文件路径 如果仍然存在 `'iostream' file not found` 错误,则可能是编译器未能正确识别 C++ 标准库的位置。尝试显式设置 `-I` 参数指向标准库目录。例如: ```bash clang++ example.cc -o example -I/usr/include/c++/v1/ ``` 此方法适用于某些发行版中默认路径未被自动检测的情况。另外,也可以检查是否需要更新或重新安装 GCC/C++ 开发工具链[^3]。 --- #### 3. 统一使用 `<iostream>` 并修正命名空间问题 根据引用说明,应移除旧式的 `<iostream.h>` 头文件并改用现代版本 `<iostream>`。同时建议始终限定作用域为 `std::` 来避免潜在冲突。以下是调整后的代码模板: ```cpp #include <iostream> int main() { std::cout << "Hello, world!" << std::endl; return 0; } ``` 上述更改有助于消除因混合使用不同风格而导致的一系列问题[^2]。 --- #### 4. 调整 OpenMP 支持下的编译选项 针对涉及多线程编程 (OpenMP) 场景下发生的类似错误 (`<stdlib.h> file not found`) ,需确认所使用的 Clang 版本支持相应功能,并附加适当标志完成构建过程。具体做法如下所示: ```bash clang++ xx.cpp -o xx -fopenmp -L/usr/local/lib -lomp ``` 这里假设 OMP 实现位于 `/usr/local/lib` 中;实际位置取决于本地安装情况。 --- #### 总结 综合以上分析可知,解决此类问题的关键在于补充必要软件包、校正包含指令以及合理运用扩展特性。务必参照官方文档验证当前平台的最佳实践指南。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值