Clang: Difference between revisions
(→Tips) |
|||
(8 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
== Links == |
|||
=== Clang on Windows === |
|||
==== LLVM-MinGW ==== |
|||
* Get packages from https://github.com/mstorsjo/llvm-mingw |
|||
The best port of LLVM/Clang on Windows I tried. |
|||
* No dependency on Visual Studio. |
|||
* Support 32-bit and 64-bit targets. |
|||
* Support sanitizers (ASAN, UBSAN). |
|||
==== MSYS2 ==== |
|||
MSYS2 now provides clang 9.0 packages. |
|||
* No dependency on Visual Studio. |
|||
* Support 32-bit and 64-bit targets. |
|||
* But {{red|'''does not'''}} support sanitizers (ASAN, UBSAN). |
|||
==== Official LLVM ==== |
|||
Packages from the official LLVM at http://releases.llvm.org/download.html. |
|||
* {{red|'''DEPEND'''}} on Visual Studio for linking |
|||
* Support 32-bit and 64-bit targets. |
|||
* (Maybe) support sanitizers (ASAN, UBSAN). |
|||
== Tips == |
== Tips == |
||
=== Get Stack Pointer === |
=== Get Stack Pointer === |
||
Line 17: | Line 45: | ||
=== Enable all warnings: <code>-Weverything</code> === |
=== Enable all warnings: <code>-Weverything</code> === |
||
<code>-Weverything</code> means enable all current and future warnings. See [http://amattn.com/p/better_apps_clang_weverything_or_wall_is_a_lie.html Better Apps with Clang's Weverything or Wall is a Lie!] |
<code>-Weverything</code> means enable all current and future warnings. See [http://amattn.com/p/better_apps_clang_weverything_or_wall_is_a_lie.html Better Apps with Clang's Weverything or Wall is a Lie!] |
||
=== Make deterministic / reproducible builds === |
|||
* Reference: https://blog.conan.io/2019/09/02/Deterministic-builds-with-C-C++.html |
|||
Things to look at: |
|||
* <code>__DATE__</code> and <code>__TIME__</code>. On clang, we can do <code>export ZERO_AR_DATE=1</code>. |
|||
* <code>__FILE__</code>. On clang, we can add a flag <code>-ffile-prefix-map=/some/local/build/path=.</code>. |
|||
* <code>__LINE__</code>. |
|||
* some randomness introduced by compiler: Use flag <code>-frandom-seed=0x${checksum}</code>. |
|||
Some script I used: |
|||
<source lang="bash"> |
|||
ag -l __LINE__ | xargs sed -ri 's/__LINE__/1/g' |
|||
make NODEBUG=1 some.elf # Optional, but ideally build without flag -g |
|||
strip --strip-all some.elf |
|||
sha256sum some.elf |
|||
</source> |
|||
=== Get list of standard compiler defines === |
|||
<source lang="bash"> |
|||
clang -dM -E -x c /dev/null |
|||
# #define _LP64 1 |
|||
# #define __ATOMIC_ACQUIRE 2 |
|||
# #define __ATOMIC_ACQ_REL 4 |
|||
# #define __ATOMIC_CONSUME 1 |
|||
# #define __ATOMIC_RELAXED 0 |
|||
</source> |
|||
=== Detect optimization levels === |
|||
This can't detect all levels but at least some of them (from [https://stackoverflow.com/questions/31718637/determine-optimization-level-in-preprocessor SO]): |
|||
<source lang="bash"> |
|||
clang -Xpreprocessor -dM -E - < /dev/null > 1 |
|||
clang -Xpreprocessor -dM -O -E - < /dev/null > 2 |
|||
diff 1 2 |
|||
# 53a54 |
|||
# > #define __OPTIMIZE__ 1 |
|||
# 154d155 |
|||
# < #define __NO_INLINE__ 1 |
|||
</source> |
|||
== Troubleshoot == |
|||
=== iostream not found === |
|||
This is a funny one. Simple Hello, World program that fails with an |
|||
<source lang="c"> |
|||
#include <iostream> |
|||
using namespace std; |
|||
int main() { |
|||
cout << "Hello, World" << endl; |
|||
return 0; |
|||
} |
|||
</source> |
|||
<source lang="bash"> |
|||
clang++ main.cpp |
|||
# main.cpp:1:10: fatal error: 'iostream' file not found |
|||
# #include <iostream> |
|||
# ^~~~~~~~~~ |
|||
# 1 error generated. |
|||
</source> |
|||
Luckily [https://stackoverflow.com/questions/54521402/locating-iostream-in-clang-fatal-error-iostream-file-not-found StackOverflow] comes to the rescue. |
|||
The problem is that we have several gcc/g++ installation, and the one selected by clang doesn't have the c++ headers. |
|||
<source lang="bash"> |
|||
$ clang++ -v main.cpp |
|||
clang version 7.0.1-8 (tags/RELEASE_701/final) |
|||
Target: x86_64-pc-linux-gnu |
|||
Thread model: posix |
|||
InstalledDir: /usr/bin |
|||
Found candidate GCC installation: /usr/bin/../lib/gcc/i686-linux-gnu/10 |
|||
Found candidate GCC installation: /usr/bin/../lib/gcc/i686-linux-gnu/8 |
|||
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/10 |
|||
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/8 |
|||
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/9 |
|||
Found candidate GCC installation: /usr/lib/gcc/i686-linux-gnu/10 |
|||
Found candidate GCC installation: /usr/lib/gcc/i686-linux-gnu/8 |
|||
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/10 |
|||
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/8 |
|||
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9 |
|||
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/9 |
|||
Candidate multilib: .;@m64 |
|||
Selected multilib: .;@m64 |
|||
"/usr/lib/llvm-7/bin/clang" -cc1 [...] |
|||
clang -cc1 version 7.0.1 based upon LLVM 7.0.1 default target x86_64-pc-linux-gnu |
|||
ignoring nonexistent directory "/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/x86_64-linux-gnu" |
|||
ignoring nonexistent directory "/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/backward" |
|||
ignoring nonexistent directory "/include" |
|||
ignoring duplicate directory "/usr/include/clang/7.0.1/include" |
|||
#include "..." search starts here: |
|||
#include <...> search starts here: |
|||
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++ |
|||
/usr/include/clang/7.0.1/include |
|||
/usr/local/include |
|||
/usr/include/x86_64-linux-gnu |
|||
/usr/include |
|||
End of search list. |
|||
main.cpp:1:10: fatal error: 'iostream' file not found |
|||
#include <iostream> |
|||
^~~~~~~~~~ |
|||
1 error generated. |
|||
</source> |
|||
The simplest for us was to uninstall gcc-9. Another solution is to install g++-9. Also it seems that clang uses some kind of prioritization, so in fact reinstalling gcc-8/g++-8 may work as well. |
|||
=== UBSAN / ASAN troubleshooting === |
|||
;References |
|||
* https://clang.llvm.org/docs/AddressSanitizer.html |
|||
* https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html |
|||
;Build |
|||
* For ASAN: |
|||
:* Use compile and link flags <code>-fsanitize=address</code>. |
|||
:* It is also recommended to use compile flag <code>-fno-omit-frame-pointer</code> for better stack trace. |
|||
<source lang="bash"> |
|||
# Compile |
|||
clang++ -O1 -g -fsanitize=address -fno-omit-frame-pointer -c example_UseAfterFree.cc |
|||
# Link |
|||
clang++ -g -fsanitize=address example_UseAfterFree.o |
|||
</source> |
|||
* For UBSAN: |
|||
:* Use compile and link flags <code>-fsanitize=undefined</code>. |
|||
;Troubleshoot: |
|||
* Error <code>undefined reference to typeinfo</code> when linking [https://stackoverflow.com/questions/37358573/why-does-fsanitize-undefined-cause-undefined-reference-to-typeinfo SO] |
|||
:* Fix is to flag <code>-fno-sanitize=vptr</code>. |
|||
=== No debug symbols === |
|||
Recent version of clang uses DWARF V5. The old debug info can still be used with compile and link flag j<code>-fdebug-default-version=4</code>. |
Latest revision as of 23:00, 11 May 2023
Links
Clang on Windows
LLVM-MinGW
- Get packages from https://github.com/mstorsjo/llvm-mingw
The best port of LLVM/Clang on Windows I tried.
- No dependency on Visual Studio.
- Support 32-bit and 64-bit targets.
- Support sanitizers (ASAN, UBSAN).
MSYS2
MSYS2 now provides clang 9.0 packages.
- No dependency on Visual Studio.
- Support 32-bit and 64-bit targets.
- But does not support sanitizers (ASAN, UBSAN).
Official LLVM
Packages from the official LLVM at http://releases.llvm.org/download.html.
- DEPEND on Visual Studio for linking
- Support 32-bit and 64-bit targets.
- (Maybe) support sanitizers (ASAN, UBSAN).
Tips
Get Stack Pointer
Use this macro [1]:
#define current_stack_pointer ({ \
register unsigned long esp asm("esp"); \
asm("" : "=r"(esp)); \
esp; \
})
Turn errors into warning
-Wno-error=foo Turn warning “foo” into an warning even if -Werror is specified.
Enable all warnings: -Weverything
-Weverything
means enable all current and future warnings. See Better Apps with Clang's Weverything or Wall is a Lie!
Make deterministic / reproducible builds
Things to look at:
__DATE__
and__TIME__
. On clang, we can doexport ZERO_AR_DATE=1
.__FILE__
. On clang, we can add a flag-ffile-prefix-map=/some/local/build/path=.
.__LINE__
.- some randomness introduced by compiler: Use flag
-frandom-seed=0x${checksum}
.
Some script I used:
ag -l __LINE__ | xargs sed -ri 's/__LINE__/1/g'
make NODEBUG=1 some.elf # Optional, but ideally build without flag -g
strip --strip-all some.elf
sha256sum some.elf
Get list of standard compiler defines
clang -dM -E -x c /dev/null
# #define _LP64 1
# #define __ATOMIC_ACQUIRE 2
# #define __ATOMIC_ACQ_REL 4
# #define __ATOMIC_CONSUME 1
# #define __ATOMIC_RELAXED 0
Detect optimization levels
This can't detect all levels but at least some of them (from SO):
clang -Xpreprocessor -dM -E - < /dev/null > 1
clang -Xpreprocessor -dM -O -E - < /dev/null > 2
diff 1 2
# 53a54
# > #define __OPTIMIZE__ 1
# 154d155
# < #define __NO_INLINE__ 1
Troubleshoot
iostream not found
This is a funny one. Simple Hello, World program that fails with an
#include <iostream>
using namespace std;
int main() {
cout << "Hello, World" << endl;
return 0;
}
clang++ main.cpp
# main.cpp:1:10: fatal error: 'iostream' file not found
# #include <iostream>
# ^~~~~~~~~~
# 1 error generated.
Luckily StackOverflow comes to the rescue.
The problem is that we have several gcc/g++ installation, and the one selected by clang doesn't have the c++ headers.
$ clang++ -v main.cpp
clang version 7.0.1-8 (tags/RELEASE_701/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/i686-linux-gnu/10
Found candidate GCC installation: /usr/bin/../lib/gcc/i686-linux-gnu/8
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/10
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/8
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/9
Found candidate GCC installation: /usr/lib/gcc/i686-linux-gnu/10
Found candidate GCC installation: /usr/lib/gcc/i686-linux-gnu/8
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/10
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/8
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/9
Candidate multilib: .;@m64
Selected multilib: .;@m64
"/usr/lib/llvm-7/bin/clang" -cc1 [...]
clang -cc1 version 7.0.1 based upon LLVM 7.0.1 default target x86_64-pc-linux-gnu
ignoring nonexistent directory "/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/backward"
ignoring nonexistent directory "/include"
ignoring duplicate directory "/usr/include/clang/7.0.1/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++
/usr/include/clang/7.0.1/include
/usr/local/include
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
main.cpp:1:10: fatal error: 'iostream' file not found
#include <iostream>
^~~~~~~~~~
1 error generated.
The simplest for us was to uninstall gcc-9. Another solution is to install g++-9. Also it seems that clang uses some kind of prioritization, so in fact reinstalling gcc-8/g++-8 may work as well.
UBSAN / ASAN troubleshooting
- References
- https://clang.llvm.org/docs/AddressSanitizer.html
- https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
- Build
- For ASAN:
- Use compile and link flags
-fsanitize=address
. - It is also recommended to use compile flag
-fno-omit-frame-pointer
for better stack trace.
- Use compile and link flags
# Compile
clang++ -O1 -g -fsanitize=address -fno-omit-frame-pointer -c example_UseAfterFree.cc
# Link
clang++ -g -fsanitize=address example_UseAfterFree.o
- For UBSAN:
- Use compile and link flags
-fsanitize=undefined
.
- Use compile and link flags
- Troubleshoot
- Error
undefined reference to typeinfo
when linking SO
- Fix is to flag
-fno-sanitize=vptr
.
- Fix is to flag
No debug symbols
Recent version of clang uses DWARF V5. The old debug info can still be used with compile and link flag j-fdebug-default-version=4
.