Linux and WSL - Install Clang 9 with libc++ and compile C++17 and C++20 programs
Posted on December 13, 2017 by Paul
Updated 23 September 2019
In this article, I will show you how to install Clang with libc++ on Ubuntu Linux and Windows System for Linux. Same procedure should work on other Debian based Linux distributions. Latest version of Clang supports the C++17 standard and has experimental support for C++20.
If you want to compile Clang from sources check my previous post.
Alternatively, if you are using Docker, you can install Clang 9 in a Docker container.
Open a Terminal (on Windows 10, you can open a Command Prompt or a PowerShell window and write bash to start WSL) and make sure your system is updated:
1 sudo apt update
2 sudo apt upgrade
Next, we need to install a few prerequisites for running Clang:
1 sudo apt install build-essential xz-utils curl
Download and extract latest binary of Clang, which is 9.0.0 at the time of this writing:
1 curl -SL http://releases.llvm.org/9.0.0/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz | tar -xJC .
2 mv clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-18.04 clang_9.0.0
3 sudo mv clang_9.0.0 /usr/local
Next, you will need to add Clang to your system PATH:
1 export PATH=/usr/local/clang_9.0.0/bin:$PATH
2 export LD_LIBRARY_PATH=/usr/local/clang_9.0.0/lib:$LD_LIBRARY_PATH
Let’s try to compile and run a C++17 code that uses an if block with init-statement (the example is a bit silly, but it will show you how to compile C++17 programs):
1 #include <iostream>
2
3 int main() {
4 // if block with init-statement:
5 if(int a = 5; a < 8) {
6 std::cout << "Local variable a is < 8\n";
7 } else {
8 std::cout << "Local variable a is >= 8\n";
9 }
10 return 0;
11 }
Save the above code in a file named if_test.cpp and compile it with:
1 clang++ -std=c++17 -stdlib=libc++ -Wall -pedantic if_test.cpp -o if_test
This is what I see on my machine:
1 ~ $ clang++ -std=c++17 -stdlib=libc++ -Wall -pedantic if_test.cpp -o if_test
2 ~ $ ./if_test
3 Local variable a is < 8
4 ~ $
Next, let’s try to compile a program that uses the C++17 Filesystem:
1 #include <iostream>
2 #include <filesystem>
3
4 int main() {
5 for(auto &file : std::filesystem::recursive_directory_iterator("./")) {
6 std::cout << file.path() << '\n';
7 }
8 }
Save the above file as test_fs.cpp and compile it with:
1 clang++ -std=c++17 -stdlib=libc++ -Wall -pedantic test_fs.cpp -o test_fs
This is what I see on my machine if I run the above code (you should see a list of files that are present in the folder where you have the executable):
1 ~ $ clang++ -std=c++17 -stdlib=libc++ -Wall -pedantic test_fs.cpp -o test_fs
2 ~ $ ./test_fs
3 "./test_1.cpp"
4 "./test_fs"
5 "./test_0.c"
6 "./if_test"
7 "./if_test.cpp"
8 "./test_fs.cpp"
9 ~ $
Finally, let’s test if we can use C++17 std::optional:
1 // C++17 optional test.
2 // You can compile the code with:
3 // clang++ -std=c++17 -stdlib=libc++ -Wall -pedantic test_optional.cpp -o test_optional
4 #include <iostream>
5 #include <optional>
6
7 void show_optional_value(const std::optional<int> &o) {
8 // Print the optional has a value if it is not empty
9 if(o) {
10 std::cout << "Optional value is: " << *o << '\n';
11 } else {
12 std::cout << "Optional is empty\n";
13 }
14 }
15 int main() {
16 // Create an empty optional
17 std::optional<int> o1;
18
19 // Show the optional value
20 show_optional_value(o1);
21
22 // Store a value in the above optional variable
23 o1 = -33;
24
25 // Show the optional value
26 show_optional_value(o1);
27 }
This is what I see if I build and run the above code:
1 ~ $ clang++ -std=c++17 -stdlib=libc++ -Wall -pedantic test_optional.cpp -o test_optional
2 ~ $ ./test_optional
3 Optional is empty
4 Optional value is: -33
5 ~ $
Clang 9 has experimental support for the new C++20 standard, at this time you’ll need to use std=c++2a in order to enforce the C++20 standard. Here is an example of using the new C++20 std::span:
1 // C++20 span test
2 // you can build the code with:
3 // clang++ -std=c++2a -stdlib=libc++ -Wall -Wextra -pedantic span_test.cpp -o span_test
4
5 #include <vector>
6 #include <span>
7
8 void print_content(std::span<int> container) {
9 for(const auto &e : container) {
10 std::cout << e << ' ';
11 }
12 std::cout << '\n';
13 }
14
15 int main() {
16 int a[]{23, 45, 67, 89};
17 print_content(a);
18
19 std::vector<int> v{1, 2, 3, 4, 5};
20 print_content(v);
21 }
This is what I see if I build and run the above code:
1 ~ $ clang++ -std=c++2a -stdlib=libc++ -Wall -Wextra -pedantic span_test.cpp -o span_test
2 ~ $ ./span_test
3 23 45 67 89
4 1 2 3 4 5
5 ~ $
If you are interested to learn more about modern C++ I would recommend reading A tour of C++ by Bjarne Stroustrup.
or Effective Modern C++ by Scott Meyers.