There can be easier ways, or I might have done something redundant (let me know what can be removed), but here's a surefire way.
If you download the LLVM binaries from LLVM releases, do Step 1 - a and not Step 1 - b.
Step 1 - a
Download the LLVM + Clang binaries of your choice.
Copy the toolchain from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain
and paste it in ~/Library/Developer/Toolchains
.
Right click -> Show package Contents.
- Change the identifier in
ToolchainInfo.plist
file to what you want "MyAmazingToolchain".
- Replace all the bin include lib libexec folders with what you got from LLVM.
Move on to Step 2.
Step 1 - b
Build llvm with
cmake -G "Sublime Text 2 - Ninja" -DCMAKE_BUILD_TYPE=Release \
-DLLVM_ENABLE_PROJECTS=“clang;libcxx;libcxxabi” -DCMAKE_CXX_STANDARD=17 -DLLVM_INCLUDE_TESTS=OFF \
-DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_CCACHE_BUILD=ON -DLLVM_CREATE_XCODE_TOOLCHAIN=ON \
-DCMAKE_INSTALL_PREFIX="easy to clean location"\
-DLLVM_ENABLE_RTTI=OFF \
../llvm
libcxxabi
is required or linking libcxx
will fail with:
ld: library not found for -lcxxabi_shared
clang: error: linker command failed with exit code 1 (use -v to see invocation)
DLLVM_CCACHE_BUILD
requires https://ccache.dev (use brew if you wish). First build will be very slow. Rebuilds will be faster.
After the above is done and ninja compiles around 3000 files, run
ninja install all
ninja install-xcode-toolchain
Find the created toolchain in location you chose above/Toolchains
. Copy it to ~/Library/Developer/Toolchains/
Step 2
If Xcode is open, close it and reopen. In Xcode app menu > Toolchains > choose the new one, llvm12git.
Create a new c++ project normally and go to its project's build settings.
Search for COMPILER_INDEX_STORE_ENABLE
or Enable index-while-building functionality
and set it to "No". Otherwise, build fails with "unrecognised option" about indexing.
Step 3
Change "C++ language dialect" to "c++20" or "c++2a"

Build the project normally. However, warnings may not go away while the code successfully builds due to indexing disabled. :( Adding header search path helps with warnings.
Make sure to check feature status:
Code I tested:
#include <compare>
#include <concepts>
struct Aggr {
int i;
char c;
auto operator<=>(Aggr const &) const = default;
};
struct A {
int x;
int y;
int z;
};
int main()
{
// A a{.y = 2,.x = 1}; // error; designator order does not match declaration
// order
A b{.x = 1, .z = 2}; // ok, b.y initialized to 0
return 0;
}