之前筆者寫過一篇博文ubuntu使用LLVM官方發布的tar.xz來安裝Clang編譯器介紹了Ubuntu下使用官方發布的tar.xz包來安裝Clang編譯。官方發布的版本中也有MacOS版本的tar.xz,那MacOS應該也是可以安裝的。
筆者2015款MBP筆記本,CPU是intel
的,出廠系統是MacOS10.12(Sierra),后面自己升級安裝到10.13(由于只有128G硬盤,不能安裝太新的系統):
目前的Clang
編譯器是9.0
,__cplusplus
版本是201406
,支持C++14
,部分支持C++17
,如果想使用新一點的C++標準,就需要更新編譯器。
一、安裝Clang編譯器
LLVM官方在LLVM 15及之前是有出Intel版本的tar.xz安裝包的,后面有的版本沒macOS
版本的,有的版本有macOS
的,但是是ARM CPU的,后面19.0開始有macOS版本的了,而且ARM與Intel的都有。
只可惜筆者的MBP系統太老,不能安裝最新版本的,只能退而求其次,安裝LLVM 15.0.7,而且有Intel CPU的x86_64版本:
先下載clang+llvm-15.0.7-x86_64-apple-darwin21.0.tar.xz
,再使用下面的命令解壓:
tar -xf clang+llvm-15.0.7-x86_64-apple-darwin21.0.tar.xz
解壓后,可以將目錄改名為llvm-15
,然后移動到/usr/local/
目錄下,為了確保獨立性,不弄臟/usr/local/
目錄,直接將整個llvm-15
目錄移動,而不是移動llvm-15
下的子目錄。
然后在~/.bash_profile
中設置PATH
,將/usr/local/llvm-15/bin
添加到PATH變量中:
export PATH=/usr/local/llvm-15/bin:$PATH
二、測試、使用
1.簡單測試
添加好后,新開一個終端進行簡單測試,測試clang
沒問題:
$ clang -v
clang version 15.0.7
Target: x86_64-apple-darwin17.7.0
Thread model: posix
InstalledDir: /usr/local/llvm-15/bin
但是測試lldb
就報錯了:
$ lldb
dyld: Library not loaded: @rpath/liblldb.15.0.7.dylibReferenced from: /usr/local/llvm-15/bin/lldbReason: no suitable image found. Did find:/usr/local/llvm-15/bin/../lib/liblldb.15.0.7.dylib: cannot load 'liblldb.15.0.7.dylib' (load command 0x80000034 is unknown)/usr/local/llvm-15/bin/../lib/liblldb.15.0.7.dylib: stat() failed with errno=1
Abort trap: 6
使用otool -l /usr/local/llvm-15/lib/liblldb.15.0.7.dylib
指令查看:
$ otool -l /usr/local/llvm-15/lib/liblldb.15.0.7.dylib
/usr/local/llvm-15/lib/liblldb.15.0.7.dylib:
Mach headermagic cputype cpusubtype caps filetype ncmds sizeofcmds flags0xfeedfacf 16777223 3 0x00 6 31 3400 0x00910085
Load command 0cmd LC_SEGMENT_64cmdsize 872segname __TEXTvmaddr 0x0000000000000000vmsize 0x00000000067c8000fileoff 0filesize 108822528maxprot 0x00000005initprot 0x00000005nsects 10flags 0x0
Sectionsectname __text……Load command 4cmd LC_ID_DYLIBcmdsize 56name @rpath/liblldb.15.0.7.dylib (offset 24)time stamp 1 Thu Jan 1 08:00:01 1970current version 15.0.7
compatibility version 0.0.0
Load command 5cmd ?(0x80000034)cmdsize 16
Load command 6cmd ?(0x80000033)cmdsize 16
Load command 7cmd LC_SYMTABcmdsize 24symoff 119381816nsyms 180001stroff 122268616strsize 16367424
Load command 8cmd LC_DYSYMTAB
發現還真是有未知命令:cmd ?(0x80000034)
,cmd ?(0x80000033)
,暫時無法解決,就還是使用系統自帶的lldb
吧。
2. 使用VSCode測試
只要設置好Clang
的路徑在PATH
變量中,打開VSCode,重新掃描工具包,即可搜索到新的Clang版本。
切換到Clang 15,VSCode會自動重新執行CMake命令:
[cmake] FAILED: cmTC_d20cb
[cmake] : && /usr/local/llvm-15/bin/clang -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/cmTC_d20cb.dir/testCCompiler.c.o -o cmTC_d20cb && :
[cmake] ld: unknown option: -platform_version
[cmake] clang-15: error: linker command failed with exit code 1 (use -v to see invocation)
[cmake] ninja: build stopped: subcommand failed.
無法正確執行CMake,CMake在編譯簡單的測試程序時,無法通過。
ld: unknown option: -platform_version
提示是ld
找到不到參數,原因是新版本的Clang編譯器與系統的鏈接器ld
不匹配,需要使用Clang自己的鏈接器lld
,由于是CMake在測試編譯器時報的錯,那就需要在它之前設置使用lld
。
CMake中要設置鏈接器使用lld
,有兩種方法:
- 可以在cmake命令行參數中設置如下變量:
- CMAKE_EXE_LINKER_FLAGS:設置可執行文件鏈接器的變量,用法:
-DCMAKE_EXE_LINKER_FLAGS=-fuse-ld=lld
,注意大小寫 - CMAKE_SHARED_LINKER_FLAGS:設置動態鏈接庫鏈接器的變量,用法:
-DCMAKE_SHARED_LINKER_FLAGS=-fuse-ld=lld
- CMAKE_LINK_LIBRARY_FLAG:設置靜態鏈接庫鏈接器的旗標,用法:
-DCMAKE_LINK_LIBRARY_FLAG=-fuse-ld=lld
- CMAKE_LINKER_TYPE:在3.29版本添加的新變量,用法:
-DCMAKE_LINKER_TYPE=LLD
,注意LLD
是大寫
在VSCode中需要在settings.json
配置文件中設置:
"cmake.configureArgs": ["-DCMAKE_EXE_LINKER_FLAGS=-fuse-ld=lld","-DCMAKE_SHARED_LINKER_FLAGS=-fuse-ld=lld","-DCMAKE_LINK_LIBRARY_FLAG=-fuse-ld=lld","-DCMAKE_LINKER_TYPE=LLD" // CMake3.29+才能使用
],
- 在
CMakeLists.txt
中設置
如果是在CMakeLists.txt
中設置,一定要在最頂層的CMakeLists.txt
中project
命令之前設置:
cmake_minimum_required(VERSION 3.25)
set(CMAKE_EXE_LINKER_FLAGS -fuse-ld=lld)
set(CMAKE_SHARED_LINKER_FLAGS -fuse-ld=lld)
set(CMAKE_LINK_LIBRARY_FLAG -fuse-ld=lld)
set(CMAKE_LINKER_TYPE LLD)
project(demo)
編譯鏈接都沒問題了。
3. 使用QtCreator測試
筆者在MBP上安裝的是QtCreator 5.03版本,基于Qt5.15.2的:
但Qt的SDK是5.14.2:
可以先使用QtCreator的自動檢測,看是否能檢測到Clang15,如果不能,手動添加:
在Kits中克隆一個原來的配置,將下面的C/C++編譯器設置為clang 15:
并在CMake Configuration
中添加如下配置:
CMAKE_EXE_LINKER_FLAGS:STRING=-fuse-ld=lld
CMAKE_LINK_LIBRARY_FLAG:STRING=-fuse-ld=lld
CMAKE_SHARED_LINKER_FLAGS:STRING=-fuse-ld=lld
如下圖所示:
在Qt項目中使用新的Kits編譯即可。
但是筆者在設置好后,QtCreator會有一個警告:
cstdlib
源碼:
#if !defined(_LIBCPP_CXX03_LANG)
using ::at_quick_exit _LIBCPP_USING_IF_EXISTS;
using ::quick_exit _LIBCPP_USING_IF_EXISTS;
#endif
#if _LIBCPP_STD_VER > 14
using ::aligned_alloc _LIBCPP_USING_IF_EXISTS;
#endif
原因是at_quick_exit
和quick_exit
函數在C11中添加,而std::at_quick_exit
和std::quick_exit
函數在C++11中添加,參見:
https://cppreference.cn/w/c/program/at_quick_exit
https://cppreference.cn/w/cpp/utility/program/at_quick_exit
aligned_alloc
是在C11中添加,而std::aligned_alloc
是在C++17中添加,參見:
https://cppreference.cn/w/c/memory/aligned_alloc
https://cppreference.cn/w/cpp/memory/c/aligned_alloc
筆者MacOS系統原來的C庫缺少這幾個函數的,可以在一個頭文件中聲明一下,不讓QtCreator報警告:
lost.h
#ifndef LOST_H
#define LOST_H#include <_ctype.h>int at_quick_exit(void (*)());
int quick_exit(void (*)());
void *aligned_alloc(size_t alignment, size_t size);
int timespec_get(struct timespec* const time_spec,int const base
);#endif // LOST_H
然后在#include <cstdlib>
之前先#include "lost.h"
即可。
不報警告了,但是在代碼中不能使用這幾個函數,因為系統中沒有相應的實現。
如果對你有幫助,歡迎點贊收藏!