├── .gitignore ├── CMakeLists.txt ├── README.org └── cmake ├── examples ├── CMakeLists.MSVC.in ├── Makefile_shared.in ├── Makefile_shared_macos.in ├── Makefile_static.in ├── README.txt ├── clang_visitor.c └── sample.H └── modules ├── Download.cmake ├── GatherArchives.cmake ├── LibClangBuild.cmake ├── LinuxMacosBuild.cmake └── MSVCBuild.cmake /.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /include/ 3 | /lib/ 4 | /doc/ 5 | /share/ 6 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | project(libclang-static-build) 3 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") 4 | set(LIBCLANG_EXAMPLES "${CMAKE_CURRENT_SOURCE_DIR}/cmake/examples") 5 | if(NOT (MSVC OR APPLE OR UNIX)) 6 | message(FATAL_ERROR "This build currenly works only with macOS, Microsoft Visual Studio and Linux.") 7 | endif() 8 | if(APPLE OR UNIX) 9 | find_program(CMAKE_LIBTOOL libtool) 10 | if(NOT CMAKE_LIBTOOL) 11 | message(FATAL_ERROR "'libtool' is necessary for building static archives") 12 | endif() 13 | include(LinuxMacosBuild) 14 | else() 15 | include(MSVCBuild) 16 | endif() 17 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Static Builds Of Libclang 13 2 | #+AUTHOR: Aditya Siram 3 | #+OPTIONS: ^:nil ;; let an underscore be an underscore, disable sub-superscripting 4 | #+OPTIONS: timestamp:nil 5 | 6 | * Table Of Contents :TOC_3: 7 | - [[#introduction][Introduction]] 8 | - [[#motivation][Motivation]] 9 | - [[#getting-started][Getting Started]] 10 | - [[#linux-and-macos][Linux and macOS]] 11 | - [[#building][Building]] 12 | - [[#running-the-examples][Running The Examples]] 13 | - [[#windows-10][Windows 10]] 14 | - [[#building-1][Building]] 15 | - [[#running-the-example][Running The Example]] 16 | - [[#implementation][Implementation]] 17 | - [[#preamble][Preamble]] 18 | - [[#linux-and-macos-1][Linux and macOS]] 19 | - [[#clang-and-ncurses-download-urls][Clang and NCurses Download URLs]] 20 | - [[#download-libclang-ncurses-and-z3][Download Libclang, NCurses and Z3]] 21 | - [[#configure-ncurses-as-an-external-project][Configure NCurses as an external project]] 22 | - [[#setup-cmake-paths-and-includes][Setup CMake Paths And Includes]] 23 | - [[#build-a-static-libclang][Build A Static Libclang]] 24 | - [[#windows][Windows]] 25 | - [[#other-helper-modules][Other Helper Modules]] 26 | - [[#build-time-downloads-downloadcmake][Build Time Downloads (Download.cmake)]] 27 | - [[#libclang-sources-headers-and-static-libs-libclangbuildcmake][Libclang sources, headers and static libs (LibClangBuild.cmake)]] 28 | - [[#add-absolute-path-to-sources-and-headers-libclangbuildcmake][Add absolute path to sources and headers (LibClangBuild.cmake)]] 29 | - [[#gather-names-of-static-archives-and-common-directory][Gather Names Of Static Archives And Common Directory]] 30 | - [[#examples][Examples]] 31 | - [[#static-makefile][Static Makefile]] 32 | - [[#shared-makefile][Shared Makefile]] 33 | - [[#shared-makefile-macos][Shared Makefile MacOS]] 34 | - [[#cmakelists-msvc][CMakeLists MSVC]] 35 | - [[#windows-readme][Windows README]] 36 | - [[#sample-c-file][Sample C++ File]] 37 | - [[#example-visitor][Example Visitor]] 38 | - [[#issues-with-gcc--10-on-linux][Issues with GCC < 10 on Linux]] 39 | 40 | * Introduction 41 | This package consists of a set of [[https://cmake.org][CMake]] scripts that download and compile 42 | [[https://clang.llvm.org/docs/Tooling.html][libclang]] into a single static archive containing all LLVM and third party 43 | dependencies so applications which link against it can be easily deployed. The 44 | build also produces a bundled shared library which allows faster iteration 45 | during development time by avoiding link time slowdowns. The build takes only 46 | about 7 minutes on my modestly provisioned 7 year old i5/16GB RAM Thinkpad 47 | instead of 5-7 hours for a normal from-scratch LLVM build. 48 | 49 | I tested it on Manjaro Linux with GCC 11.1.0, macOS Mojave and Windows 10 using 50 | the MS Visual C++ toolchain. As an aside the Windows build is only possible 51 | because the [[https://ziglang.org/][Zig]] project generously provides [[https://github.com/ziglang/zig/wiki/Building-Zig-on-Windows][prebuilt statically linked LLVM 52 | libraries]] for Windows, if you are benefiting please consider [[https://github.com/sponsors/andrewrk][contributing]], it's 53 | immensely annoying and time-consuming to build ~LLVM~ and ~clang~ from scratch 54 | and we should support Andy Kelley for saving us the trouble. 55 | 56 | A small easy-to-build demo app ~clang_visitor~ that parses some C++ is also 57 | included to help you get started. And to convince you the build works as 58 | advertised below are the minimal runtime dependencies on each of the supported 59 | platforms when the app is linked against the static archive: 60 | - Linux 61 | #+BEGIN_EXAMPLE 62 | > $ ldd ./clang_visitor 63 | linux-vdso.so.1 (0x00007ffce8bfb000) 64 | libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007fdb9954a000) 65 | libm.so.6 => /usr/lib/libm.so.6 (0x00007fdb99404000) 66 | libdl.so.2 => /usr/lib/libdl.so.2 (0x00007fdb993ff000) 67 | libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007fdb993dd000) 68 | libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007fdb993c3000) 69 | libc.so.6 => /usr/lib/libc.so.6 (0x00007fdb991fd000) 70 | /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fdb9ea9b000) 71 | #+END_EXAMPLE 72 | - macOS Mojave: 73 | #+BEGIN_EXAMPLE 74 | > otool -L clang_visitor 75 | clang_visitor: 76 | /usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11) 77 | /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4) 78 | /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.250.1) 79 | #+END_EXAMPLE 80 | - ... and Windows 10 81 | #+BEGIN_EXAMPLE 82 | > dumpbin.exe /DEPENDENTS clang_visitor.exe 83 | Microsoft (R) COFF/PE Dumper Version 14.25.28614.0 84 | Copyright (C) Microsoft Corporation.  All rights reserved. 85 | 86 | 87 | Dump of file clang_visitor_static.exe 88 | 89 | File Type: EXECUTABLE IMAGE 90 | 91 |   Image has the following dependencies: 92 | 93 |     VERSION.dll 94 |     KERNEL32.dll 95 |     SHELL32.dll 96 |     ole32.dll 97 |     OLEAUT32.dll 98 |     ADVAPI32.dll 99 |     VCRUNTIME140.dll 100 |     VCRUNTIME140_1.dll 101 |     api-ms-win-crt-stdio-l1-1-0.dll 102 |     api-ms-win-crt-runtime-l1-1-0.dll 103 |     api-ms-win-crt-heap-l1-1-0.dll 104 |     api-ms-win-crt-utility-l1-1-0.dll 105 |     api-ms-win-crt-environment-l1-1-0.dll 106 |     api-ms-win-crt-string-l1-1-0.dll 107 |     api-ms-win-crt-convert-l1-1-0.dll 108 |     api-ms-win-crt-time-l1-1-0.dll 109 |     api-ms-win-crt-math-l1-1-0.dll 110 |     api-ms-win-crt-locale-l1-1-0.dll 111 |     api-ms-win-crt-filesystem-l1-1-0.dll 112 | 113 |   Summary 114 | 115 |       2C4000 .data 116 |       123000 .pdata 117 |      15CB000 .rdata 118 |        7D000 .reloc 119 |         1000 .rsrc 120 |      2105000 .text 121 | #+END_EXAMPLE 122 | 123 | * Motivation 124 | Currently the best way to statically analyze C and C++ source is [[https://clang.llvm.org/docs/Tooling.html][libclang]]. 125 | Unfortunately applications built against ~libclang~ aren't very portable or easy 126 | to deploy because of dependencies on third party libraries like [[https://invisible-island.net/ncurses/][ncurses]] and [[https://github.com/Z3Prover/z3][z3]] 127 | and the ~libclang~ shared library itself. Package managers do a decent job of 128 | orchestrating the install but it's still hard to deploy an application that's 129 | pinned to a specific version of ~libclang~ or to ship binaries between Linux 130 | distributions. There's always containers or [[https://nixos.org/nix/][Nix]] or [[https://guix.gnu.org/][Guix]] but I think asking 131 | people to get up to speed on purely functional package managers or have [[https://www.docker.com/][Docker]] 132 | running just to use ~libclang~ apps is a non-starter. With this package all you 133 | need is [[https://cmake.org][CMake]] on macOS and Linux and additionally [[https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019][Visual Studio Build Tools]] on 134 | Windows. 135 | 136 | * Getting Started 137 | Below are some instructions on getting up and running on Linux, macOS and 138 | Windows 10. Everything beyond that is the full build as a literate program and 139 | only interesting if you care about implementation details. If you just want to 140 | use this package it can be safely skipped. Enjoy! 141 | ** Linux and macOS 142 | *** Building 143 | First make sure you have a ~cmake~ version greater that 3.13: 144 | #+BEGIN_EXAMPLE 145 | > cmake --version 146 | cmake version 3.17.0 147 | 148 | CMake suite maintained and supported by Kitware (kitware.com/cmake). 149 | #+END_EXAMPLE 150 | 151 | and ~gcc~/~g++~ > 10: 152 | #+begin_example 153 | > g++ --version 154 | g++ (Debian 10.2.1-6) 10.2.1 20210110 155 | Copyright (C) 2020 Free Software Foundation, Inc. 156 | This is free software; see the source for copying conditions. There is NO 157 | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 158 | #+end_example 159 | 160 | Clone this repo, create a ~build~ directory inside it and run the build and install: 161 | #+BEGIN_EXAMPLE 162 | > git clone https://github.com/deech/libclang-static-build 163 | > cd libclang-static-build 164 | > mkdir build; cd build 165 | > cmake .. -DCMAKE_INSTALL_PREFIX=.. 166 | > make install 167 | #+END_EXAMPLE 168 | The ~install~ step copies all the artifacts to the directory into which you 169 | cloned this repo just above the ~build~ directory. Nothing else on the system is 170 | touched. 171 | 172 | Once it's done installing there will be 3 new directories in repo directory, 173 | ~lib~, ~include~ and ~share~. The first contains a big ~libclang~ static archive 174 | with all dependencies bundled and shared versions of those libraries for quicker 175 | compilation during development, the second contains the ~libclang~ headers and 176 | the third has two directories ~share/doc/examples/static~ and 177 | ~share/doc/examples/shared~ both of which contain a couple of identical small 178 | examples that shows how to create static and shared ~libclang~ apps. 179 | *** Running The Examples 180 | The two example directories ~share/doc/examples/static~ and 181 | ~share/doc/examples/shared~ both of which contain an identical small example 182 | program that walks a C++ header file containing an ~enum~, the first builds a 183 | large (100MB+) statically linked executable with minimal dependencies and the 184 | second a much smaller shared executable which depends ~libclang~, ~ncurses~ and 185 | ~z3~ at runtime. To build them run ~make~ in their respective directories: 186 | #+BEGIN_EXAMPLE 187 | > cd libclang-static-build 188 | > cd doc/example/static 189 | > make 190 | > ./clang_visitor 191 | Cursor spelling, kind: __ENUM__, macro definition 192 | Cursor spelling, kind: Enum, EnumDecl 193 | Cursor spelling, kind: RED, EnumConstantDecl 194 | Cursor spelling, kind: , UnexposedExpr 195 | Cursor spelling, kind: , IntegerLiteral 196 | Cursor spelling, kind: , IntegerLiteral 197 | Cursor spelling, kind: GREEN, EnumConstantDecl 198 | Cursor spelling, kind: , UnexposedExpr 199 | Cursor spelling, kind: , BinaryOperator 200 | Cursor spelling, kind: , BinaryOperator 201 | Cursor spelling, kind: , IntegerLiteral 202 | Cursor spelling, kind: , IntegerLiteral 203 | Cursor spelling, kind: BLUE, EnumConstantDecl 204 | Cursor spelling, kind: , UnexposedExpr 205 | Cursor spelling, kind: , BinaryOperator 206 | Cursor spelling, kind: , BinaryOperator 207 | Cursor spelling, kind: RED, DeclRefExpr 208 | Cursor spelling, kind: GREEN, DeclRefExpr 209 | #+END_EXAMPLE 210 | ** Windows 10 211 | *** Building 212 | First install [[https://cmake.org/download/][CMake]] and [[https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019][Build Tools For Visual Studio 2019]], then clone this 213 | repo, create a ~build~ directory inside it, run the build and install: 214 | #+begin_example 215 | > git.exe clone https://github.com/deech/libclang-static-build 216 | > cd libclang-static-build 217 | > mkdir build 218 | > cd build 219 | > cmake.exe .. -Thost=x64 -G "Visual Studio 16 2019" -A x64 -DCMAKE_INSTALL_PREFIX=.. -DCMAKE_BUILD_TYPE=Release -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD="AVR" -DLLVM_ENABLE_LIBXML2=OFF -DLLVM_USE_CRT_RELEASE=MT 220 | > "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\MSBuild.exe" /m -p:Configuration=Release INSTALL.vcxproj 221 | #+end_example 222 | At the final step I needed to give the full path to ~MSBuild.exe~ even though I 223 | asked MS Build Tools to add it to the ~PATH~ so I reproduced it here so you 224 | don't have to go hunt it down. 225 | 226 | There should now be 3 new directories in the repo directory, ~lib~, ~include~, 227 | and ~share~. The first contains ~clang_static_bundled.lib~ which is a 400MB 228 | static archive, ~include~ has all the headers needed to build ~libclang~ apps 229 | and ~share~ has a single statically linked demo app. 230 | *** Running The Example 231 | The example directory ~share/doc/examples/static~ contains a small demo 232 | that parses out a C++ ~enum~ from a header file. To build it: 233 | #+begin_example 234 | > cd libclang-static-build\share\doc\examples\static 235 | > mkdir build 236 | > cd build 237 | > cmake.exe -G "Visual Studio 16 2019" .. -DCMAKE_INSTALL_PREFIX=.. 238 | > "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\MSBuild.exe" /m -p:Configuration=Release INSTALL.vcxproj 239 | #+end_example 240 | The directory above the ~build~ directory now contains ~bin~ which contains the 241 | example app ~clang_visitor.exe~: 242 | #+begin_example 243 | >cd ..\bin 244 | >clang_visitor_static.exe 245 | Cursor spelling, kind: __ENUM__, macro definition 246 | Cursor spelling, kind: Enum, EnumDecl 247 | Cursor spelling, kind: RED, EnumConstantDecl 248 | Cursor spelling, kind: , IntegerLiteral 249 | Cursor spelling, kind: GREEN, EnumConstantDecl 250 | Cursor spelling, kind: , BinaryOperator 251 | Cursor spelling, kind: , IntegerLiteral 252 | Cursor spelling, kind: , IntegerLiteral 253 | Cursor spelling, kind: BLUE, EnumConstantDecl 254 | Cursor spelling, kind: , BinaryOperator 255 | Cursor spelling, kind: RED, DeclRefExpr 256 | Cursor spelling, kind: GREEN, DeclRefExpr 257 | #+end_example 258 | * Implementation 259 | At a high level to build a bundled shared and static library I grab the 260 | prebuilt ~clang+LLVM~ static archives and ~libclang~ sources, build the latter 261 | from scratch locally and then bundle it along with all the prebuilt archives 262 | into one large library that an executable can link against. 263 | 264 | Additionally on Linux and macOS ~libclang~ depends[[https://github.com/Z3Prover/z3][ z3]] and [[https://invisible-island.net/ncurses/announce.html][ncurses]]. While the 265 | former has official prebuilt releases the latter does not and so we have to 266 | build from source locally. Both are then folded into the resulting library. 267 | 268 | On Windows 10 the situation is nicer because [[https://ziglang.org/][the Zig project]] provides [[https://github.com/ziglang/zig/wiki/Building-Zig-on-Windows][prebuilt 269 | LLVM archives]] with no dependency on ~z3~ so the build actually goes quite a bit 270 | faster than the other platforms. Do [[https://github.com/sponsors/andrewrk][support Zig]] if you can. 271 | 272 | And finally we generate a small demo that traverses a C++ header; on Linux and 273 | macOS it's a standard Make project and a CMake project on Windows. 274 | ** Preamble 275 | #+BEGIN_SRC cmake :tangle CMakeLists.txt 276 | cmake_minimum_required(VERSION 3.13) 277 | project(libclang-static-build) 278 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") 279 | set(LIBCLANG_EXAMPLES "${CMAKE_CURRENT_SOURCE_DIR}/cmake/examples") 280 | if(NOT (MSVC OR APPLE OR UNIX)) 281 | message(FATAL_ERROR "This build currenly works only with macOS, Microsoft Visual Studio and Linux.") 282 | endif() 283 | if(APPLE OR UNIX) 284 | find_program(CMAKE_LIBTOOL libtool) 285 | if(NOT CMAKE_LIBTOOL) 286 | message(FATAL_ERROR "'libtool' is necessary for building static archives") 287 | endif() 288 | include(LinuxMacosBuild) 289 | else() 290 | include(MSVCBuild) 291 | endif() 292 | #+END_SRC 293 | ** Linux and macOS 294 | *** Clang and NCurses Download URLs 295 | "Reproducibility" is achieved by hard-coding the URLs from which to get the 296 | dependencies, I'm sure there's more principled ways but this works ok for now. 297 | #+BEGIN_SRC cmake :tangle cmake/modules/LinuxMacosBuild.cmake 298 | if(APPLE) 299 | set(LIBCLANG_PREBUILT_URL https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.0/clang+llvm-13.0.0-x86_64-apple-darwin.tar.xz) 300 | else() 301 | set(LIBCLANG_PREBUILT_URL https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.0/clang+llvm-13.0.0-x86_64-linux-gnu-ubuntu-20.04.tar.xz) 302 | endif() 303 | set(CLANG_SOURCES_URL https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.0/clang-13.0.0.src.tar.xz) 304 | set(NCURSES_SOURCES_URL https://ftp.gnu.org/pub/gnu/ncurses/ncurses-6.2.tar.gz) 305 | if(APPLE) 306 | set(Z3_PREBUILT_URL https://github.com/Z3Prover/z3/releases/download/z3-4.8.7/z3-4.8.7-x64-osx-10.14.6.zip) 307 | else() 308 | set(Z3_PREBUILT_URL https://github.com/Z3Prover/z3/releases/download/z3-4.8.7/z3-4.8.7-x64-ubuntu-16.04.zip) 309 | endif() 310 | #+END_SRC 311 | *** Download Libclang, NCurses and Z3 312 | The dependencies are then downloaded and unpacked at *build* *time* ... 313 | #+BEGIN_SRC cmake :tangle cmake/modules/LinuxMacosBuild.cmake 314 | include(Download) 315 | message(STATUS "Downloading ncurses sources, prebuilt z3 & prebuilt libclang with sources; this is ~500MB, please be patient, 'libclang_prebuilt' will take several minutes ...") 316 | set(NCURSES_SOURCE_DIR) 317 | download(ncurses_sources ${NCURSES_SOURCES_URL} NCURSES_DOWNLOAD_DIR) 318 | set(LIBCLANG_SOURCES_DIR) 319 | download(clang_sources ${CLANG_SOURCES_URL} LIBCLANG_SOURCES_DIR) 320 | set(Z3_PREBUILT_DIR) 321 | download(z3_prebuilt ${Z3_PREBUILT_URL} Z3_PREBUILT_DIR) 322 | set(LIBCLANG_PREBUILT_DIR) 323 | download(libclang_prebuilt ${LIBCLANG_PREBUILT_URL} LIBCLANG_PREBUILT_DIR) 324 | #+END_SRC 325 | *** Configure NCurses as an external project 326 | Since ~ncurses~ does not provide prebuilt static archives we build it locally 327 | using a recipe stolen from Arch scripts: 328 | #+BEGIN_SRC cmake :tangle cmake/modules/LinuxMacosBuild.cmake 329 | include(ExternalProject) 330 | ExternalProject_Add(ncurses 331 | SOURCE_DIR ${NCURSES_DOWNLOAD_DIR} 332 | CONFIGURE_COMMAND /configure --enable-rpath --prefix=${CMAKE_INSTALL_PREFIX} --with-shared --with-static --with-normal --without-debug --without-ada --enable-widec --disable-pc-files --with-cxx-binding --without-cxx-shared --with-abi-version=5 333 | BUILD_COMMAND make 334 | INSTALL_COMMAND "" 335 | ) 336 | #+END_SRC 337 | *** Setup CMake Paths And Includes 338 | This part is why I used CMake for this project in the first place, the LLVM 339 | project provides CMake scripts that contain useful functions and macros which 340 | take care of the nitty gritty C++ compiler and inclusion flags that allow 341 | building ~libclang~ from source, without them this project would have been 342 | impossible. 343 | #+BEGIN_SRC cmake :tangle cmake/modules/LinuxMacosBuild.cmake 344 | list(APPEND CMAKE_MODULE_PATH "${LIBCLANG_PREBUILT_DIR}/lib/cmake/clang") 345 | list(APPEND CMAKE_MODULE_PATH "${LIBCLANG_PREBUILT_DIR}/lib/cmake/llvm") 346 | list(APPEND CMAKE_MODULE_PATH "${LIBCLANG_SOURCES_DIR}/cmake/modules") 347 | include(LibClangBuild) 348 | include(HandleLLVMOptions) 349 | include(AddLLVM) 350 | include(AddClang) 351 | include(GatherArchives) 352 | #+END_SRC 353 | *** Build A Static Libclang 354 | For some reason ~macOS~ needs to be told to use C++14 and it doesn't hurt to 355 | include it for Linux as well: 356 | #+BEGIN_SRC cmake :tangle cmake/modules/LinuxMacosBuild.cmake 357 | set(CMAKE_CXX_STANDARD 14) 358 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 359 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti") 360 | #+END_SRC 361 | 362 | ~get_libclang_sources_and_headers~ populates the last three arguments with 363 | _absolute_ paths to headers, ~libclang~ sources and the included LLVM archives. 364 | #+BEGIN_SRC cmake :tangle cmake/modules/LinuxMacosBuild.cmake 365 | get_libclang_sources_and_headers( 366 | ${LIBCLANG_SOURCES_DIR} 367 | ${LIBCLANG_PREBUILT_DIR} 368 | LIBCLANG_SOURCES 369 | LIBCLANG_ADDITIONAL_HEADERS 370 | LIBCLANG_PREBUILT_LIBS 371 | ) 372 | #+END_SRC 373 | Now we have to tell the CMake recipe where to find the shared libraries for the ~z3~ and ~ncurses~ dependencies: 374 | #+BEGIN_SRC cmake :tangle cmake/modules/LinuxMacosBuild.cmake 375 | include_directories(${LIBCLANG_PREBUILT_DIR}/include) 376 | 377 | ExternalProject_Get_Property(ncurses BINARY_DIR) 378 | set(NCURSES_BINARY_DIR ${BINARY_DIR}) 379 | set(NCURSES_SHARED_LIB) 380 | if(APPLE) 381 | set(NCURSES_SHARED_LIB ${NCURSES_BINARY_DIR}/lib/libncursesw.dylib ${NCURSES_BINARY_DIR}/lib/libncursesw.5.dylib) 382 | else() 383 | set(NCURSES_SHARED_LIB ${NCURSES_BINARY_DIR}/lib/libncursesw.so ${NCURSES_BINARY_DIR}/lib/libncursesw.so.5 ${NCURSES_BINARY_DIR}/lib/libncursesw.so.5.9) 384 | endif() 385 | unset(BINARY_DIR) 386 | 387 | if(APPLE) 388 | set(Z3_SHARED_LIB ${Z3_PREBUILT_DIR}/bin/libz3.dylib) 389 | else() 390 | set(Z3_SHARED_LIB ${Z3_PREBUILT_DIR}/bin/libz3.so) 391 | endif() 392 | #+END_SRC 393 | 394 | ~add_clang_library~ is a ~libclang~ provided CMake function that does all the 395 | hard work of generating Makefiles to build a ~clang~ and LLVM based library or 396 | executable. It's used twice, once to generate a static archive and once more for 397 | a shared library. I'm building it twice because building with both ~SHARED~ and 398 | ~STATIC~ in a single call seems to produce objects compiled with ~-fPIC~ so 399 | building the shared library fails. I'm probably doing something wrong but this 400 | seems to work for now. 401 | #+BEGIN_SRC cmake :tangle cmake/modules/LinuxMacosBuild.cmake 402 | add_clang_library(libclang 403 | SHARED 404 | OUTPUT_NAME clang 405 | ${LIBCLANG_SOURCES} 406 | ADDITIONAL_HEADERS ${LIBCLANG_ADDITIONAL_HEADERS} 407 | LINK_LIBS 408 | ${LIBCLANG_PREBUILT_LIBS} ${NCURSES_SHARED_LIB} dl pthread z 409 | LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} 410 | DEPENDS ncurses 411 | ) 412 | 413 | add_clang_library(libclang_static 414 | STATIC 415 | OUTPUT_NAME clang_static 416 | ${LIBCLANG_SOURCES} 417 | ADDITIONAL_HEADERS ${LIBCLANG_ADDITIONAL_HEADERS} 418 | DEPENDS ncurses 419 | ) 420 | 421 | set_target_properties(libclang PROPERTIES VERSION 12) 422 | #+END_SRC 423 | 424 | This bit is pretty much copy-pasta'ed from the CMake build scripts that come 425 | with ~clang~ sources probably doesn't do much. 426 | #+BEGIN_SRC cmake :tangle cmake/modules/LinuxMacosBuild.cmake 427 | if(APPLE) 428 | set(LIBCLANG_LINK_FLAGS " -Wl,-compatibility_version -Wl,1") 429 | set_property(TARGET libclang APPEND_STRING PROPERTY 430 | LINK_FLAGS ${LIBCLANG_LINK_FLAGS}) 431 | else() 432 | set_target_properties(libclang 433 | PROPERTIES 434 | DEFINE_SYMBOL _CINDEX_LIB_) 435 | endif() 436 | #+END_SRC 437 | 438 | On MacOS ~libtool~ can reliably nest multiple archives into one by simply 439 | passing them in as arguments. 440 | 441 | Unfortunately Linux is more complicated. Due to limitations of ~ar~ I have to 442 | make a [[https://en.wikipedia.org/wiki/Ar_(Unix)#Thin_archive][thin archive]], a static archive which doesn't actually contain the other 443 | archives but references them, by calling ~ar~ with the ~T~ (for thin) argument. 444 | 445 | Then I copy all archives I need to bundle into one directory 446 | ~ALL_ARCHIVES_DIRECTORY~ and build the thin archive there because a thin archive 447 | finds referenced archives by where they were relative to it when it was created. 448 | At install time the thin archives are the referenced archives are copied the 449 | same final location so the relative paths are intact and apps can transparently 450 | link with the thin archive. 451 | 452 | The call to ~gather_archives~ populates ~ALL_ARCHIVES_DIRECTORY~ with a 453 | hard-coded path local to the CMake ~build~ directory, ~ALL_ARCHIVE_NAMES~ with a 454 | list of the archives basenames (just the filename without parents) so they can 455 | be passed to ~ar~ and ~ALL_ARCHIVE_PATHS~ with a list of archives /with/ their 456 | full paths which is used at install time to copy them to the same location. This 457 | is not good code. 458 | #+BEGIN_SRC cmake :tangle cmake/modules/LinuxMacosBuild.cmake 459 | if(APPLE) 460 | add_custom_target( 461 | libclang_bundled ALL 462 | COMMAND ${CMAKE_LIBTOOL} -static -o libclang_bundled.a 463 | ${CMAKE_CURRENT_BINARY_DIR}/libclang_static.a 464 | ${LIBCLANG_PREBUILT_LIBS} 465 | ${NCURSES_BINARY_DIR}/lib/libncursesw.a 466 | ${Z3_PREBUILT_DIR}/bin/libz3.a 467 | DEPENDS ncurses libclang libclang_static 468 | ) 469 | else() 470 | gatherArchives( 471 | ALL_ARCHIVES_DIRECTORY 472 | ALL_ARCHIVE_NAMES 473 | ALL_ARCHIVE_PATHS 474 | ${CMAKE_CURRENT_BINARY_DIR}/libclang_static.a 475 | ${LIBCLANG_PREBUILT_LIBS} 476 | ${NCURSES_BINARY_DIR}/lib/libncursesw.a 477 | ${Z3_PREBUILT_DIR}/bin/libz3.a 478 | ) 479 | add_custom_target( 480 | gather_archives ALL 481 | COMMAND ${CMAKE_COMMAND} -E make_directory ${ALL_ARCHIVES_DIRECTORY} 482 | COMMAND ${CMAKE_COMMAND} -E copy 483 | ${CMAKE_CURRENT_BINARY_DIR}/libclang_static.a 484 | ${LIBCLANG_PREBUILT_LIBS} 485 | ${NCURSES_BINARY_DIR}/lib/libncursesw.a 486 | ${Z3_PREBUILT_DIR}/bin/libz3.a 487 | ${ALL_ARCHIVES_DIRECTORY} 488 | DEPENDS ncurses libclang libclang_static 489 | ) 490 | add_custom_target( 491 | libclang_bundled ALL 492 | COMMAND ${CMAKE_AR} crsT libclang_bundled.a ${ALL_ARCHIVE_NAMES} 493 | WORKING_DIRECTORY ${ALL_ARCHIVES_DIRECTORY} 494 | DEPENDS gather_archives 495 | ) 496 | endif() 497 | #+END_SRC 498 | 499 | Now it's time to create the example app, Makefiles are generated using the 500 | Makefile templates covered in [[Static Makefile][Static Makefile]] and [[Shared Makefile][Shared Makefile]] and they are 501 | all copied into an overall ~examples~ directory in ~CMAKE_CURRENT_BINARY_DIR~, 502 | the CMake ~build~ directory. 503 | 504 | That ~CMAKE_OSX_SYSROOT~ thing is simply so ~libclang~ headers can find the 505 | ~time.h~ on macOS. I'm really not sure why it isn't in the standard location. 506 | #+BEGIN_SRC cmake :tangle cmake/modules/LinuxMacosBuild.cmake 507 | set(MAKEFILE_LIBCLANG_INCLUDE ${CMAKE_INSTALL_PREFIX}/include) 508 | if(APPLE) 509 | set(MAKEFILE_LIBCLANG_INCLUDE "${MAKEFILE_LIBCLANG_INCLUDE} -I${CMAKE_OSX_SYSROOT}/usr/include") 510 | endif() 511 | set(MAKEFILE_LIBCLANG_LIBDIR ${CMAKE_INSTALL_PREFIX}/lib) 512 | 513 | file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/examples/static) 514 | configure_file(${LIBCLANG_EXAMPLES}/Makefile_static.in ${CMAKE_CURRENT_BINARY_DIR}/examples/static/Makefile) 515 | if(APPLE) 516 | configure_file(${LIBCLANG_EXAMPLES}/Makefile_shared_macos.in ${CMAKE_CURRENT_BINARY_DIR}/examples/shared/Makefile) 517 | else() 518 | configure_file(${LIBCLANG_EXAMPLES}/Makefile_shared.in ${CMAKE_CURRENT_BINARY_DIR}/examples/shared/Makefile) 519 | endif() 520 | 521 | file(COPY ${LIBCLANG_EXAMPLES}/clang_visitor.c DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/examples/static) 522 | file(COPY ${LIBCLANG_EXAMPLES}/sample.H DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/examples/static) 523 | file(COPY ${LIBCLANG_EXAMPLES}/clang_visitor.c DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/examples/shared) 524 | file(COPY ${LIBCLANG_EXAMPLES}/sample.H DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/examples/shared) 525 | #+END_SRC 526 | 527 | Now everything is installed relative to the ~CMAKE_INSTALL_PREFIX~, the 528 | libraries under ~lib~, ~clang~ headers under ~include/clang-c~ and ~examples~ 529 | under ~share/doc~. 530 | #+BEGIN_SRC cmake :tangle cmake/modules/LinuxMacosBuild.cmake 531 | if(APPLE) 532 | set(LIBCLANG_INSTALL_LIBS 533 | ${CMAKE_CURRENT_BINARY_DIR}/libclang_bundled.a 534 | ${Z3_PREBUILT_DIR}/bin/libz3.a 535 | ${Z3_SHARED_LIB} 536 | ${NCURSES_BINARY_DIR}/lib/libncursesw.a 537 | ${NCURSES_SHARED_LIB} 538 | ) 539 | else() 540 | set(LIBCLANG_INSTALL_LIBS 541 | ${ALL_ARCHIVES_DIRECTORY}/libclang_bundled.a 542 | ${ALL_ARCHIVE_PATHS} 543 | ${Z3_SHARED_LIB} 544 | ${NCURSES_SHARED_LIB} 545 | ) 546 | endif() 547 | 548 | install(PROGRAMS ${LIBCLANG_INSTALL_LIBS} DESTINATION lib) 549 | install(DIRECTORY ${LIBCLANG_PREBUILT_DIR}/include/clang-c DESTINATION include) 550 | install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/examples DESTINATION share/doc) 551 | #+END_SRC 552 | ** Windows 553 | The Windows build has the same overall idea as [[*Build A Static Libclang][Linux/macOS]] it's just different 554 | enough that it's easier to start over than share code. 555 | 556 | The initial bits are similar, this time the prebuilt LLVM is downloaded from the 557 | [[https://ziglang.org][Zig project]] and it has all the dependencies built in so nothing more is needed 558 | except the ~clang~ sources. 559 | #+BEGIN_SRC cmake :tangle cmake/modules/MSVCBuild.cmake 560 | set(LIBCLANG_PREBUILT_URL https://ziglang.org/deps/llvm+clang+lld-13.0.0-x86_64-windows-msvc-release-mt.tar.xz) 561 | set(CLANG_SOURCES_URL https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.0/clang-13.0.0.src.tar.xz) 562 | 563 | include(Download) 564 | message(STATUS "Downloading prebuilt libclang with sources; this is ~500MB, please be patient, 'libclang_prebuilt' will take several minutes ...") 565 | download(clang_sources ${CLANG_SOURCES_URL} LIBCLANG_SOURCES_DIR) 566 | download(libclang_prebuilt ${LIBCLANG_PREBUILT_URL} LIBCLANG_PREBUILT_DIR) 567 | #+END_SRC 568 | 569 | Then I pull the the LLVM CMake scripts into scope just as [[*Setup CMake Paths And Includes][before]] 570 | #+BEGIN_SRC cmake :tangle cmake/modules/MSVCBuild.cmake 571 | list(APPEND CMAKE_MODULE_PATH "${LIBCLANG_PREBUILT_DIR}/lib/cmake/clang") 572 | list(APPEND CMAKE_MODULE_PATH "${LIBCLANG_PREBUILT_DIR}/lib/cmake/llvm") 573 | list(APPEND CMAKE_MODULE_PATH "${LIBCLANG_SOURCES_DIR}/cmake/modules") 574 | 575 | set(CMAKE_CXX_STANDARD 14) 576 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 577 | include(LibClangBuild) 578 | include(HandleLLVMOptions) 579 | include(AddLLVM) 580 | include(AddClang) 581 | 582 | get_libclang_sources_and_headers( 583 | ${LIBCLANG_SOURCES_DIR} 584 | ${LIBCLANG_PREBUILT_DIR} 585 | LIBCLANG_SOURCES 586 | LIBCLANG_ADDITIONAL_HEADERS 587 | LIBCLANG_PREBUILT_LIBS 588 | ) 589 | include_directories(${LIBCLANG_PREBUILT_DIR}/include) 590 | add_clang_library(libclang 591 | SHARED 592 | STATIC 593 | OUTPUT_NAME clang 594 | ${LIBCLANG_SOURCES} 595 | LINK_LIBS ${LIBCLANG_PREBUILT_LIBS} Version 596 | ADDITIONAL_HEADERS ${LIBCLANG_ADDITIONAL_HEADERS} 597 | ) 598 | 599 | set_target_properties(libclang PROPERTIES VERSION 12) 600 | #+END_SRC 601 | 602 | This bit is important, without it every object file spews a [[https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-1-c4273?view=vs-2019][inconsistent DLL 603 | linkage warning]]. More importantly for reasons I don't understand, I have to do 604 | this as opposed to how the LLVM project does it: ~set_target_properties(libclang 605 | PROPERTIES DEFINE_SYMBOL _CINDEX_LIB_)~ 606 | 607 | #+BEGIN_SRC cmake :tangle cmake/modules/MSVCBuild.cmake 608 | target_compile_definitions(obj.libclang PUBLIC "_CINDEX_LIB_") 609 | #+END_SRC 610 | 611 | While the ~clang~ build function provided by LLVM produces a static library 612 | called ~clang_static.lib~ any app that links against it /also/ requires 613 | ~libclang.dll~ at runtime, so we have just created a 400MB static library that 614 | doesn't do anything. I guess static libs that also carry a dependency on DLLs is 615 | a common idiom on Windows but defeats the purpose of this project. 616 | 617 | *However* I found an intermediate static archive ~obj.libclang.lib~ that also 618 | gets generated and does what I want so I pass that to the archive tool instead. 619 | I'm sure there is a better way but this seems to work for now. 620 | 621 | ~LIBCLANG_INSTALL_LIBS~ is used at install time to copy the fat archive to the 622 | right place. 623 | #+BEGIN_SRC cmake :tangle cmake/modules/MSVCBuild.cmake 624 | find_program(lib_tool lib) 625 | if(NOT lib_tool) 626 | get_filename_component(CXX_COMPILER_DIRECTORY "${CMAKE_CXX_COMPILER}" PATH) 627 | set(lib_tool "${CXX_COMPILER_DIRECTORY}/lib.exe") 628 | endif() 629 | set(AR_COMMAND ${lib_tool} /NOLOGO /OUT:${CMAKE_CURRENT_BINARY_DIR}/clang_static_bundled.lib "${CMAKE_CURRENT_BINARY_DIR}/obj.libclang.dir/Release/obj.libclang.lib" ${LIBCLANG_PREBUILT_LIBS}) 630 | 631 | add_custom_target(libclang_static_bundled ALL 632 | COMMAND ${AR_COMMAND} 633 | DEPENDS libclang 634 | BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/clang_static_bundled.lib 635 | ) 636 | set(LIBCLANG_INSTALL_LIBS ${CMAKE_CURRENT_BINARY_DIR}/clang_static_bundled.lib) 637 | #+END_SRC 638 | 639 | And now for the example demo, I fill out the [[*CMakeLists MSVC][template CMake build recipe]], copy 640 | the sources and build scripts to an ~examples~ directory in the local ~build~ 641 | directory ... 642 | #+BEGIN_SRC cmake :tangle cmake/modules/MSVCBuild.cmake 643 | set(CMAKE_MSVC_LIB_DIR ${CMAKE_INSTALL_PREFIX}/lib) 644 | set(CMAKE_MSVC_INCLUDE_DIR ${CMAKE_INSTALL_PREFIX}/include) 645 | configure_file(${LIBCLANG_EXAMPLES}/CMakeLists.MSVC.in ${CMAKE_CURRENT_BINARY_DIR}/examples/static/CMakeLists.txt) 646 | file(COPY ${LIBCLANG_EXAMPLES}/sample.H DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/examples/static/bin) 647 | file(COPY ${LIBCLANG_EXAMPLES}/clang_visitor.c DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/examples/static) 648 | file(COPY ${LIBCLANG_EXAMPLES}/README.txt DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/examples/static) 649 | #+END_SRC 650 | 651 | ... and install the library, ~clang~ headers and demos under 652 | ~CMAKE_INSTALL_PREFIX\{lib,include,share}~ respectively 653 | #+BEGIN_SRC cmake :tangle cmake/modules/MSVCBuild.cmake 654 | install(PROGRAMS ${LIBCLANG_INSTALL_LIBS} DESTINATION lib) 655 | install(DIRECTORY ${LIBCLANG_PREBUILT_DIR}/include/clang-c DESTINATION include) 656 | install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/examples DESTINATION share/doc) 657 | #+END_SRC 658 | ** Other Helper Modules 659 | *** Build Time Downloads (Download.cmake) 660 | #+BEGIN_SRC cmake :tangle cmake/modules/Download.cmake 661 | include(FetchContent) 662 | function (download name url source_dir) 663 | FetchContent_Declare(${name} URL ${url}) 664 | if(NOT ${name}_POPULATED) 665 | message(STATUS "* Downloading ${name} from ${url}") 666 | FetchContent_Populate(${name}) 667 | endif() 668 | set(${source_dir} ${${name}_SOURCE_DIR} PARENT_SCOPE) 669 | endfunction() 670 | #+END_SRC 671 | *** Libclang sources, headers and static libs (LibClangBuild.cmake) 672 | These are the ~clang~ source files and headers needed to build ~libclang~, most 673 | have been copied wholesale from the ~CMakeLists.txt~ provided with the project. 674 | #+BEGIN_SRC cmake :tangle cmake/modules/LibClangBuild.cmake 675 | set(LIBCLANG_SOURCE_PATH tools/libclang) 676 | set(LIBCLANG_INCLUDE_PATH include/clang-c) 677 | set(LIBCLANG_SOURCE_FILES 678 | ARCMigrate.cpp 679 | BuildSystem.cpp 680 | CIndex.cpp 681 | CIndexCXX.cpp 682 | CIndexCodeCompletion.cpp 683 | CIndexDiagnostic.cpp 684 | CIndexHigh.cpp 685 | CIndexInclusionStack.cpp 686 | CIndexUSRs.cpp 687 | CIndexer.cpp 688 | CXComment.cpp 689 | CXCursor.cpp 690 | CXIndexDataConsumer.cpp 691 | CXCompilationDatabase.cpp 692 | CXLoadedDiagnostic.cpp 693 | CXSourceLocation.cpp 694 | CXStoredDiagnostic.cpp 695 | CXString.cpp 696 | CXType.cpp 697 | Indexing.cpp 698 | FatalErrorHandler.cpp 699 | ) 700 | set(LIBCLANG_ADDITIONAL_HEADER_FILES 701 | CIndexDiagnostic.h 702 | CIndexer.h 703 | CXCursor.h 704 | CXLoadedDiagnostic.h 705 | CXSourceLocation.h 706 | CXString.h 707 | CXTranslationUnit.h 708 | CXType.h 709 | Index_Internal.h 710 | ) 711 | set(LIBCLANG_INDEX_H Index.h) 712 | #+END_SRC 713 | 714 | This list of static archives to an ~libclang~ app needs to link against took 715 | some experimentation, apparently we need all them in this approximate order to 716 | link successfully, I have no idea why I just tried stuff until it worked. 717 | #+BEGIN_SRC cmake :tangle cmake/modules/LibClangBuild.cmake 718 | set(LIBCLANG_LINK_LIBS 719 | clangAST 720 | clangBasic 721 | clangDriver 722 | clangFrontend 723 | clangIndex 724 | clangLex 725 | clangSema 726 | clangSerialization 727 | clangTooling 728 | clangARCMigrate 729 | LLVMAArch64CodeGen 730 | LLVMAArch64AsmParser 731 | LLVMAArch64Desc 732 | LLVMAArch64Disassembler 733 | LLVMAArch64Info 734 | LLVMAArch64Utils 735 | LLVMAMDGPUCodeGen 736 | LLVMAMDGPUAsmParser 737 | LLVMAMDGPUDesc 738 | LLVMAMDGPUDisassembler 739 | LLVMAMDGPUInfo 740 | LLVMAMDGPUUtils 741 | LLVMARMCodeGen 742 | LLVMARMAsmParser 743 | LLVMARMDesc 744 | LLVMARMDisassembler 745 | LLVMARMInfo 746 | LLVMARMUtils 747 | LLVMBPFCodeGen 748 | LLVMBPFAsmParser 749 | LLVMBPFDesc 750 | LLVMBPFDisassembler 751 | LLVMBPFInfo 752 | LLVMHexagonCodeGen 753 | LLVMHexagonAsmParser 754 | LLVMHexagonDesc 755 | LLVMHexagonDisassembler 756 | LLVMHexagonInfo 757 | LLVMLanaiCodeGen 758 | LLVMLanaiAsmParser 759 | LLVMLanaiDesc 760 | LLVMLanaiDisassembler 761 | LLVMLanaiInfo 762 | LLVMMipsCodeGen 763 | LLVMMipsAsmParser 764 | LLVMMipsDesc 765 | LLVMMipsDisassembler 766 | LLVMMipsInfo 767 | LLVMMSP430CodeGen 768 | LLVMMSP430AsmParser 769 | LLVMMSP430Desc 770 | LLVMMSP430Disassembler 771 | LLVMMSP430Info 772 | LLVMNVPTXCodeGen 773 | LLVMNVPTXDesc 774 | LLVMNVPTXInfo 775 | LLVMPowerPCCodeGen 776 | LLVMPowerPCAsmParser 777 | LLVMPowerPCDesc 778 | LLVMPowerPCDisassembler 779 | LLVMPowerPCInfo 780 | LLVMRISCVCodeGen 781 | LLVMRISCVAsmParser 782 | LLVMRISCVDesc 783 | LLVMRISCVDisassembler 784 | LLVMRISCVInfo 785 | LLVMSparcCodeGen 786 | LLVMSparcAsmParser 787 | LLVMSparcDesc 788 | LLVMSparcDisassembler 789 | LLVMSparcInfo 790 | LLVMSystemZCodeGen 791 | LLVMSystemZAsmParser 792 | LLVMSystemZDesc 793 | LLVMSystemZDisassembler 794 | LLVMSystemZInfo 795 | LLVMWebAssemblyCodeGen 796 | LLVMWebAssemblyAsmParser 797 | LLVMWebAssemblyDesc 798 | LLVMWebAssemblyDisassembler 799 | LLVMWebAssemblyUtils 800 | LLVMWebAssemblyInfo 801 | LLVMX86CodeGen 802 | LLVMX86AsmParser 803 | LLVMX86Desc 804 | LLVMX86Disassembler 805 | LLVMX86Info 806 | LLVMXCoreCodeGen 807 | LLVMXCoreDesc 808 | LLVMXCoreDisassembler 809 | LLVMXCoreInfo 810 | LLVMCore 811 | LLVMSupport 812 | clangFormat 813 | clangToolingInclusions 814 | clangToolingCore 815 | clangFrontend 816 | clangDriver 817 | LLVMOption 818 | clangParse 819 | clangSerialization 820 | clangSema 821 | clangEdit 822 | clangRewrite 823 | clangAnalysis 824 | clangASTMatchers 825 | clangAST 826 | clangLex 827 | clangBasic 828 | LLVMAArch64Desc 829 | LLVMAArch64Info 830 | LLVMAArch64Utils 831 | LLVMMIRParser 832 | LLVMAMDGPUDesc 833 | LLVMAMDGPUInfo 834 | LLVMAMDGPUUtils 835 | LLVMARMDesc 836 | LLVMARMInfo 837 | LLVMARMUtils 838 | LLVMHexagonDesc 839 | LLVMHexagonInfo 840 | LLVMLanaiDesc 841 | LLVMLanaiInfo 842 | LLVMipo 843 | LLVMVectorize 844 | LLVMIRReader 845 | LLVMAsmParser 846 | LLVMInstrumentation 847 | LLVMLinker 848 | LLVMSystemZDesc 849 | LLVMSystemZInfo 850 | LLVMWebAssemblyDesc 851 | LLVMWebAssemblyInfo 852 | LLVMGlobalISel 853 | LLVMAsmPrinter 854 | LLVMDebugInfoDWARF 855 | LLVMSelectionDAG 856 | LLVMCodeGen 857 | LLVMScalarOpts 858 | LLVMAggressiveInstCombine 859 | LLVMInstCombine 860 | LLVMBitWriter 861 | LLVMTransformUtils 862 | LLVMTarget 863 | LLVMAnalysis 864 | LLVMProfileData 865 | LLVMTextAPI 866 | LLVMObject 867 | LLVMBitReader 868 | LLVMCore 869 | LLVMRemarks 870 | LLVMBitstreamReader 871 | LLVMMCParser 872 | LLVMMCDisassembler 873 | LLVMMC 874 | LLVMBinaryFormat 875 | LLVMDebugInfoCodeView 876 | LLVMDebugInfoMSF 877 | LLVMSupport 878 | LLVMCFGuard 879 | LLVMFrontendOpenMP 880 | LLVMDemangle 881 | LLVMAVRCodeGen 882 | LLVMAVRAsmParser 883 | LLVMAVRDisassembler 884 | LLVMAVRDesc 885 | LLVMAVRInfo 886 | LLVMPasses 887 | LLVMCoroutines 888 | LLVMSupport 889 | LLVMObjCARCOpts 890 | ) 891 | #+END_SRC 892 | *** Add absolute path to sources and headers (LibClangBuild.cmake) 893 | #+BEGIN_SRC cmake :tangle cmake/modules/LibClangBuild.cmake 894 | function(get_libclang_sources_and_headers clang_source_path clang_prebuilt_path result_sources result_headers result_required_libs) 895 | list(TRANSFORM LIBCLANG_SOURCE_FILES PREPEND ${clang_source_path}/${LIBCLANG_SOURCE_PATH}/ OUTPUT_VARIABLE RES) 896 | set(${result_sources} ${RES} PARENT_SCOPE) 897 | unset(RES) 898 | list(TRANSFORM LIBCLANG_ADDITIONAL_HEADER_FILES PREPEND ${clang_source_path}/${LIBCLANG_SOURCE_PATH}/ OUTPUT_VARIABLE RES) 899 | list(TRANSFORM LIBCLANG_INDEX_H PREPEND ${clang_source_path}/${LIBCLANG_INCLUDE_PATH}/ OUTPUT_VARIABLE RES1) 900 | list(APPEND RES ${RES1}) 901 | set(${result_headers} ${RES} PARENT_SCOPE) 902 | unset(RES) 903 | if(MSVC) 904 | list(TRANSFORM LIBCLANG_LINK_LIBS PREPEND ${clang_prebuilt_path}/lib/ OUTPUT_VARIABLE RES) 905 | list(TRANSFORM RES APPEND .lib OUTPUT_VARIABLE RES) 906 | else() 907 | list(TRANSFORM LIBCLANG_LINK_LIBS PREPEND ${clang_prebuilt_path}/lib/lib OUTPUT_VARIABLE RES) 908 | list(TRANSFORM RES APPEND .a OUTPUT_VARIABLE RES) 909 | endif() 910 | set(${result_required_libs} ${RES} PARENT_SCOPE) 911 | unset(RES) 912 | endfunction() 913 | #+END_SRC 914 | *** Gather Names Of Static Archives And Common Directory 915 | #+begin_src cmake :tangle cmake/modules/GatherArchives.cmake 916 | function (gatherArchives all_archives_directory all_archive_names all_archive_paths) 917 | set(ALL_ARCHIVES_DIRECTORY_LOCAL ${CMAKE_CURRENT_BINARY_DIR}/_all_archives) 918 | foreach(archive_path ${ARGN}) 919 | get_filename_component(archive_name ${archive_path} NAME) 920 | list(APPEND ARCHIVE_NAMES_LOCAL ${archive_name}) 921 | list(APPEND ARCHIVE_PATHS_LOCAL ${ALL_ARCHIVES_DIRECTORY_LOCAL}/${archive_name}) 922 | endforeach() 923 | set(${all_archives_directory} ${ALL_ARCHIVES_DIRECTORY_LOCAL} PARENT_SCOPE) 924 | set(${all_archive_names} ${ARCHIVE_NAMES_LOCAL} PARENT_SCOPE) 925 | set(${all_archive_paths} ${ARCHIVE_PATHS_LOCAL} PARENT_SCOPE) 926 | endfunction() 927 | #+end_src 928 | ** Examples 929 | *** Static Makefile 930 | #+BEGIN_SRC makefile :tangle cmake/examples/Makefile_static.in 931 | CC=@CMAKE_C_COMPILER@ 932 | CFLAGS=-I@MAKEFILE_LIBCLANG_INCLUDE@ 933 | LIBS=-L@MAKEFILE_LIBCLANG_LIBDIR@ -lclang_bundled -lstdc++ -lm -ldl -lpthread -lz 934 | OBJ=clang_visitor.o 935 | 936 | %.o: %.c 937 | $(CC) -c -o $@ $< $(CFLAGS) 938 | 939 | clang_visitor: $(OBJ) 940 | $(CC) -o $@ $^ $(CFLAGS) $(LIBS) 941 | 942 | .PHONY: clean 943 | 944 | clean: 945 | rm *.o clang_visitor 946 | #+END_SRC 947 | *** Shared Makefile 948 | #+BEGIN_SRC makefile :tangle cmake/examples/Makefile_shared.in 949 | CC=@CMAKE_C_COMPILER@ 950 | CFLAGS=-I@MAKEFILE_LIBCLANG_INCLUDE@ 951 | LIBS=-L@MAKEFILE_LIBCLANG_LIBDIR@ -lclang -lstdc++ -lm -ldl -lpthread -Wl,-rpath=@MAKEFILE_LIBCLANG_LIBDIR@ 952 | OBJ=clang_visitor.o 953 | 954 | %.o: %.c 955 | $(CC) -c -o $@ $< $(CFLAGS) 956 | 957 | clang_visitor: $(OBJ) 958 | $(CC) -o $@ $^ $(CFLAGS) $(LIBS) 959 | 960 | .PHONY: clean 961 | 962 | clean: 963 | rm *.o clang_visitor 964 | #+END_SRC 965 | *** Shared Makefile MacOS 966 | #+BEGIN_SRC makefile :tangle cmake/examples/Makefile_shared_macos.in 967 | CC=@CMAKE_C_COMPILER@ 968 | CFLAGS=-I@MAKEFILE_LIBCLANG_INCLUDE@ 969 | LIBDIR=@MAKEFILE_LIBCLANG_LIBDIR@ 970 | LIBS=-lclang -lz3 -lstdc++ -ldl -lpthread 971 | OBJ=clang_visitor.o 972 | 973 | %.o: %.c 974 | $(CC) -c -o $@ $< $(CFLAGS) 975 | 976 | clang_visitor: $(OBJ) 977 | $(CC) -o $@ $^ $(CFLAGS) -L$(LIBDIR) $(LIBS); \ 978 | install_name_tool -change libz3.dylib $(LIBDIR)/libz3.dylib $@; \ 979 | install_name_tool -add_rpath $(LIBDIR) $@; 980 | .PHONY: clean 981 | 982 | clean: 983 | rm *.o clang_visitor 984 | #+END_SRC 985 | *** CMakeLists MSVC 986 | #+BEGIN_SRC cmake :tangle cmake/examples/CMakeLists.MSVC.in 987 | cmake_minimum_required(VERSION 3.13) 988 | project(clang_visitor) 989 | add_library(LibclangStatic SHARED IMPORTED) 990 | set_property(TARGET LibclangStatic PROPERTY IMPORTED_LOCATION "@CMAKE_MSVC_LIB_DIR@/clang_static_bundled.lib") 991 | set_property(TARGET LibclangStatic PROPERTY IMPORTED_IMPLIB "@CMAKE_MSVC_LIB_DIR@/clang_static_bundled.lib") 992 | include_directories("@CMAKE_MSVC_INCLUDE_DIR@") 993 | add_executable(clang_visitor clang_visitor.c) 994 | target_link_libraries(clang_visitor LibclangStatic Version) 995 | target_compile_definitions(clang_visitor PUBLIC -D_CINDEX_LIB_) 996 | target_link_options(clang_visitor PUBLIC /NODEFAULTLIB:libcmt.lib) 997 | install(TARGETS clang_visitor) 998 | #+END_SRC 999 | *** Windows README 1000 | #+BEGIN_SRC text :tangle cmake/examples/README.txt 1001 | To build this project: 1002 | > mkdir build 1003 | > cd build 1004 | > "C:\Program Files\CMake\bin\cmake.exe" -G "Visual Studio 16 2019" .. -DCMAKE_INSTALL_PREFIX=.. 1005 | > "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\MSBuild.exe" /m -p:Configuration=Release INSTALL.vcxproj 1006 | 1007 | To run: 1008 | > cd ..\bin 1009 | > clang_visitor.exe 1010 | #+END_SRC 1011 | *** Sample C++ File 1012 | #+BEGIN_SRC c :tangle cmake/examples/sample.H 1013 | #ifndef __ENUM__ 1014 | #define __ENUM__ 1015 | 1016 | enum Enum 1017 | { 1018 | RED = 10, 1019 | GREEN = 10 << 2, 1020 | BLUE = RED + GREEN 1021 | }; 1022 | 1023 | 1024 | #endif // __ENUM__ 1025 | #+END_SRC 1026 | *** Example Visitor 1027 | #+BEGIN_SRC c :tangle cmake/examples/clang_visitor.c 1028 | #include 1029 | #include 1030 | #include 1031 | #include 1032 | 1033 | enum CXChildVisitResult visitor(CXCursor cursor, CXCursor parent, CXClientData data) { 1034 | CXSourceLocation location = clang_getCursorLocation( cursor ); 1035 | if(!clang_Location_isFromMainFile(location)) 1036 | return CXChildVisit_Continue; 1037 | CXString cxspelling = clang_getCursorSpelling(cursor); 1038 | const char* spelling = clang_getCString(cxspelling); 1039 | CXString cxkind = clang_getCursorKindSpelling(clang_getCursorKind(cursor)); 1040 | const char* kind = clang_getCString(cxkind); 1041 | printf("Cursor spelling, kind: %s, %s\n", spelling, kind); 1042 | clang_disposeString(cxspelling); 1043 | clang_disposeString(cxkind); 1044 | return CXChildVisit_Recurse; 1045 | } 1046 | 1047 | int main(int argc, char** argv) { 1048 | CXIndex idx = clang_createIndex(1,1); 1049 | CXTranslationUnit tu = clang_createTranslationUnitFromSourceFile(idx, "sample.H", 0, 0, 0, 0); 1050 | clang_visitChildren(clang_getTranslationUnitCursor(tu), visitor, 0); 1051 | return 0; 1052 | } 1053 | #+END_SRC 1054 | * Issues with GCC < 10 on Linux 1055 | When building if you get linker errors that look like: 1056 | #+begin_example 1057 | undefined reference to `std::_Sp_make_shared_tag::_S_eq(std::type_info const&) 1058 | #+end_example 1059 | that means you have a gcc/g++ version less than 10 and need to upgrade. I ran 1060 | into this issue with Debian Buster which is still on 8.3.0 and moving to 1061 | Bullseye worked. 1062 | 1063 | If upgrading isn't possible the [[https://github.com/deech/libclang-static-build/commit/f3e41db2f59e3ca850883b621ffc550736258ff1][libclang 10 static build]] will work 1064 | with older versions. 1065 | 1066 | -------------------------------------------------------------------------------- /cmake/examples/CMakeLists.MSVC.in: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | project(clang_visitor) 3 | add_library(LibclangStatic SHARED IMPORTED) 4 | set_property(TARGET LibclangStatic PROPERTY IMPORTED_LOCATION "@CMAKE_MSVC_LIB_DIR@/clang_static_bundled.lib") 5 | set_property(TARGET LibclangStatic PROPERTY IMPORTED_IMPLIB "@CMAKE_MSVC_LIB_DIR@/clang_static_bundled.lib") 6 | include_directories("@CMAKE_MSVC_INCLUDE_DIR@") 7 | add_executable(clang_visitor clang_visitor.c) 8 | target_link_libraries(clang_visitor LibclangStatic Version) 9 | target_compile_definitions(clang_visitor PUBLIC -D_CINDEX_LIB_) 10 | target_link_options(clang_visitor PUBLIC /NODEFAULTLIB:libcmt.lib) 11 | install(TARGETS clang_visitor) 12 | -------------------------------------------------------------------------------- /cmake/examples/Makefile_shared.in: -------------------------------------------------------------------------------- 1 | CC=@CMAKE_C_COMPILER@ 2 | CFLAGS=-I@MAKEFILE_LIBCLANG_INCLUDE@ 3 | LIBS=-L@MAKEFILE_LIBCLANG_LIBDIR@ -lclang -lstdc++ -lm -ldl -lpthread -Wl,-rpath=@MAKEFILE_LIBCLANG_LIBDIR@ 4 | OBJ=clang_visitor.o 5 | 6 | %.o: %.c 7 | $(CC) -c -o $@ $< $(CFLAGS) 8 | 9 | clang_visitor: $(OBJ) 10 | $(CC) -o $@ $^ $(CFLAGS) $(LIBS) 11 | 12 | .PHONY: clean 13 | 14 | clean: 15 | rm *.o clang_visitor 16 | -------------------------------------------------------------------------------- /cmake/examples/Makefile_shared_macos.in: -------------------------------------------------------------------------------- 1 | CC=@CMAKE_C_COMPILER@ 2 | CFLAGS=-I@MAKEFILE_LIBCLANG_INCLUDE@ 3 | LIBDIR=@MAKEFILE_LIBCLANG_LIBDIR@ 4 | LIBS=-lclang -lz3 -lstdc++ -ldl -lpthread 5 | OBJ=clang_visitor.o 6 | 7 | %.o: %.c 8 | $(CC) -c -o $@ $< $(CFLAGS) 9 | 10 | clang_visitor: $(OBJ) 11 | $(CC) -o $@ $^ $(CFLAGS) -L$(LIBDIR) $(LIBS); \ 12 | install_name_tool -change libz3.dylib $(LIBDIR)/libz3.dylib $@; \ 13 | install_name_tool -add_rpath $(LIBDIR) $@; 14 | .PHONY: clean 15 | 16 | clean: 17 | rm *.o clang_visitor 18 | -------------------------------------------------------------------------------- /cmake/examples/Makefile_static.in: -------------------------------------------------------------------------------- 1 | CC=@CMAKE_C_COMPILER@ 2 | CFLAGS=-I@MAKEFILE_LIBCLANG_INCLUDE@ 3 | LIBS=-L@MAKEFILE_LIBCLANG_LIBDIR@ -lclang_bundled -lstdc++ -lm -ldl -lpthread -lz 4 | OBJ=clang_visitor.o 5 | 6 | %.o: %.c 7 | $(CC) -c -o $@ $< $(CFLAGS) 8 | 9 | clang_visitor: $(OBJ) 10 | $(CC) -o $@ $^ $(CFLAGS) $(LIBS) 11 | 12 | .PHONY: clean 13 | 14 | clean: 15 | rm *.o clang_visitor 16 | -------------------------------------------------------------------------------- /cmake/examples/README.txt: -------------------------------------------------------------------------------- 1 | To build this project: 2 | > mkdir build 3 | > cd build 4 | > "C:\Program Files\CMake\bin\cmake.exe" -G "Visual Studio 16 2019" .. -DCMAKE_INSTALL_PREFIX=.. 5 | > "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\MSBuild.exe" /m -p:Configuration=Release INSTALL.vcxproj 6 | 7 | To run: 8 | > cd ..\bin 9 | > clang_visitor.exe 10 | -------------------------------------------------------------------------------- /cmake/examples/clang_visitor.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | enum CXChildVisitResult visitor(CXCursor cursor, CXCursor parent, CXClientData data) { 7 | CXSourceLocation location = clang_getCursorLocation( cursor ); 8 | if(!clang_Location_isFromMainFile(location)) 9 | return CXChildVisit_Continue; 10 | CXString cxspelling = clang_getCursorSpelling(cursor); 11 | const char* spelling = clang_getCString(cxspelling); 12 | CXString cxkind = clang_getCursorKindSpelling(clang_getCursorKind(cursor)); 13 | const char* kind = clang_getCString(cxkind); 14 | printf("Cursor spelling, kind: %s, %s\n", spelling, kind); 15 | clang_disposeString(cxspelling); 16 | clang_disposeString(cxkind); 17 | return CXChildVisit_Recurse; 18 | } 19 | 20 | int main(int argc, char** argv) { 21 | CXIndex idx = clang_createIndex(1,1); 22 | CXTranslationUnit tu = clang_createTranslationUnitFromSourceFile(idx, "sample.H", 0, 0, 0, 0); 23 | clang_visitChildren(clang_getTranslationUnitCursor(tu), visitor, 0); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /cmake/examples/sample.H: -------------------------------------------------------------------------------- 1 | #ifndef __ENUM__ 2 | #define __ENUM__ 3 | 4 | enum Enum 5 | { 6 | RED = 10, 7 | GREEN = 10 << 2, 8 | BLUE = RED + GREEN 9 | }; 10 | 11 | 12 | #endif // __ENUM__ 13 | -------------------------------------------------------------------------------- /cmake/modules/Download.cmake: -------------------------------------------------------------------------------- 1 | include(FetchContent) 2 | function (download name url source_dir) 3 | FetchContent_Declare(${name} URL ${url}) 4 | if(NOT ${name}_POPULATED) 5 | message(STATUS "* Downloading ${name} from ${url}") 6 | FetchContent_Populate(${name}) 7 | endif() 8 | set(${source_dir} ${${name}_SOURCE_DIR} PARENT_SCOPE) 9 | endfunction() 10 | -------------------------------------------------------------------------------- /cmake/modules/GatherArchives.cmake: -------------------------------------------------------------------------------- 1 | function (gatherArchives all_archives_directory all_archive_names all_archive_paths) 2 | set(ALL_ARCHIVES_DIRECTORY_LOCAL ${CMAKE_CURRENT_BINARY_DIR}/_all_archives) 3 | foreach(archive_path ${ARGN}) 4 | get_filename_component(archive_name ${archive_path} NAME) 5 | list(APPEND ARCHIVE_NAMES_LOCAL ${archive_name}) 6 | list(APPEND ARCHIVE_PATHS_LOCAL ${ALL_ARCHIVES_DIRECTORY_LOCAL}/${archive_name}) 7 | endforeach() 8 | set(${all_archives_directory} ${ALL_ARCHIVES_DIRECTORY_LOCAL} PARENT_SCOPE) 9 | set(${all_archive_names} ${ARCHIVE_NAMES_LOCAL} PARENT_SCOPE) 10 | set(${all_archive_paths} ${ARCHIVE_PATHS_LOCAL} PARENT_SCOPE) 11 | endfunction() 12 | -------------------------------------------------------------------------------- /cmake/modules/LibClangBuild.cmake: -------------------------------------------------------------------------------- 1 | set(LIBCLANG_SOURCE_PATH tools/libclang) 2 | set(LIBCLANG_INCLUDE_PATH include/clang-c) 3 | set(LIBCLANG_SOURCE_FILES 4 | ARCMigrate.cpp 5 | BuildSystem.cpp 6 | CIndex.cpp 7 | CIndexCXX.cpp 8 | CIndexCodeCompletion.cpp 9 | CIndexDiagnostic.cpp 10 | CIndexHigh.cpp 11 | CIndexInclusionStack.cpp 12 | CIndexUSRs.cpp 13 | CIndexer.cpp 14 | CXComment.cpp 15 | CXCursor.cpp 16 | CXIndexDataConsumer.cpp 17 | CXCompilationDatabase.cpp 18 | CXLoadedDiagnostic.cpp 19 | CXSourceLocation.cpp 20 | CXStoredDiagnostic.cpp 21 | CXString.cpp 22 | CXType.cpp 23 | Indexing.cpp 24 | FatalErrorHandler.cpp 25 | ) 26 | set(LIBCLANG_ADDITIONAL_HEADER_FILES 27 | CIndexDiagnostic.h 28 | CIndexer.h 29 | CXCursor.h 30 | CXLoadedDiagnostic.h 31 | CXSourceLocation.h 32 | CXString.h 33 | CXTranslationUnit.h 34 | CXType.h 35 | Index_Internal.h 36 | ) 37 | set(LIBCLANG_INDEX_H Index.h) 38 | 39 | set(LIBCLANG_LINK_LIBS 40 | clangAST 41 | clangBasic 42 | clangDriver 43 | clangFrontend 44 | clangIndex 45 | clangLex 46 | clangSema 47 | clangSerialization 48 | clangTooling 49 | clangARCMigrate 50 | LLVMAArch64CodeGen 51 | LLVMAArch64AsmParser 52 | LLVMAArch64Desc 53 | LLVMAArch64Disassembler 54 | LLVMAArch64Info 55 | LLVMAArch64Utils 56 | LLVMAMDGPUCodeGen 57 | LLVMAMDGPUAsmParser 58 | LLVMAMDGPUDesc 59 | LLVMAMDGPUDisassembler 60 | LLVMAMDGPUInfo 61 | LLVMAMDGPUUtils 62 | LLVMARMCodeGen 63 | LLVMARMAsmParser 64 | LLVMARMDesc 65 | LLVMARMDisassembler 66 | LLVMARMInfo 67 | LLVMARMUtils 68 | LLVMBPFCodeGen 69 | LLVMBPFAsmParser 70 | LLVMBPFDesc 71 | LLVMBPFDisassembler 72 | LLVMBPFInfo 73 | LLVMHexagonCodeGen 74 | LLVMHexagonAsmParser 75 | LLVMHexagonDesc 76 | LLVMHexagonDisassembler 77 | LLVMHexagonInfo 78 | LLVMLanaiCodeGen 79 | LLVMLanaiAsmParser 80 | LLVMLanaiDesc 81 | LLVMLanaiDisassembler 82 | LLVMLanaiInfo 83 | LLVMMipsCodeGen 84 | LLVMMipsAsmParser 85 | LLVMMipsDesc 86 | LLVMMipsDisassembler 87 | LLVMMipsInfo 88 | LLVMMSP430CodeGen 89 | LLVMMSP430AsmParser 90 | LLVMMSP430Desc 91 | LLVMMSP430Disassembler 92 | LLVMMSP430Info 93 | LLVMNVPTXCodeGen 94 | LLVMNVPTXDesc 95 | LLVMNVPTXInfo 96 | LLVMPowerPCCodeGen 97 | LLVMPowerPCAsmParser 98 | LLVMPowerPCDesc 99 | LLVMPowerPCDisassembler 100 | LLVMPowerPCInfo 101 | LLVMRISCVCodeGen 102 | LLVMRISCVAsmParser 103 | LLVMRISCVDesc 104 | LLVMRISCVDisassembler 105 | LLVMRISCVInfo 106 | LLVMSparcCodeGen 107 | LLVMSparcAsmParser 108 | LLVMSparcDesc 109 | LLVMSparcDisassembler 110 | LLVMSparcInfo 111 | LLVMSystemZCodeGen 112 | LLVMSystemZAsmParser 113 | LLVMSystemZDesc 114 | LLVMSystemZDisassembler 115 | LLVMSystemZInfo 116 | LLVMWebAssemblyCodeGen 117 | LLVMWebAssemblyAsmParser 118 | LLVMWebAssemblyDesc 119 | LLVMWebAssemblyDisassembler 120 | LLVMWebAssemblyUtils 121 | LLVMWebAssemblyInfo 122 | LLVMWebAssemblyUtils 123 | LLVMX86CodeGen 124 | LLVMX86AsmParser 125 | LLVMX86Desc 126 | LLVMX86Disassembler 127 | LLVMX86Info 128 | LLVMXCoreCodeGen 129 | LLVMXCoreDesc 130 | LLVMXCoreDisassembler 131 | LLVMXCoreInfo 132 | LLVMCore 133 | LLVMSupport 134 | clangFormat 135 | clangToolingInclusions 136 | clangToolingCore 137 | clangFrontend 138 | clangDriver 139 | LLVMOption 140 | clangParse 141 | clangSerialization 142 | clangSema 143 | clangEdit 144 | clangRewrite 145 | clangAnalysis 146 | clangASTMatchers 147 | clangAST 148 | clangLex 149 | clangBasic 150 | LLVMAArch64Desc 151 | LLVMAArch64Info 152 | LLVMAArch64Utils 153 | LLVMMIRParser 154 | LLVMAMDGPUDesc 155 | LLVMAMDGPUInfo 156 | LLVMAMDGPUUtils 157 | LLVMARMDesc 158 | LLVMARMInfo 159 | LLVMARMUtils 160 | LLVMHexagonDesc 161 | LLVMHexagonInfo 162 | LLVMLanaiDesc 163 | LLVMLanaiInfo 164 | LLVMipo 165 | LLVMVectorize 166 | LLVMIRReader 167 | LLVMAsmParser 168 | LLVMInstrumentation 169 | LLVMLinker 170 | LLVMSystemZDesc 171 | LLVMSystemZInfo 172 | LLVMWebAssemblyDesc 173 | LLVMWebAssemblyInfo 174 | LLVMGlobalISel 175 | LLVMAsmPrinter 176 | LLVMDebugInfoDWARF 177 | LLVMSelectionDAG 178 | LLVMCodeGen 179 | LLVMScalarOpts 180 | LLVMAggressiveInstCombine 181 | LLVMInstCombine 182 | LLVMBitWriter 183 | LLVMTransformUtils 184 | LLVMTarget 185 | LLVMAnalysis 186 | LLVMProfileData 187 | LLVMTextAPI 188 | LLVMObject 189 | LLVMBitReader 190 | LLVMCore 191 | LLVMRemarks 192 | LLVMBitstreamReader 193 | LLVMMCParser 194 | LLVMMCDisassembler 195 | LLVMMC 196 | LLVMBinaryFormat 197 | LLVMDebugInfoCodeView 198 | LLVMDebugInfoMSF 199 | LLVMSupport 200 | LLVMCFGuard 201 | LLVMFrontendOpenMP 202 | LLVMDemangle 203 | LLVMAVRCodeGen 204 | LLVMAVRAsmParser 205 | LLVMAVRDisassembler 206 | LLVMAVRDesc 207 | LLVMAVRInfo 208 | LLVMPasses 209 | LLVMCoroutines 210 | LLVMSupport 211 | LLVMObjCARCOpts 212 | ) 213 | 214 | function(get_libclang_sources_and_headers clang_source_path clang_prebuilt_path result_sources result_headers result_required_libs) 215 | list(TRANSFORM LIBCLANG_SOURCE_FILES PREPEND ${clang_source_path}/${LIBCLANG_SOURCE_PATH}/ OUTPUT_VARIABLE RES) 216 | set(${result_sources} ${RES} PARENT_SCOPE) 217 | unset(RES) 218 | list(TRANSFORM LIBCLANG_ADDITIONAL_HEADER_FILES PREPEND ${clang_source_path}/${LIBCLANG_SOURCE_PATH}/ OUTPUT_VARIABLE RES) 219 | list(TRANSFORM LIBCLANG_INDEX_H PREPEND ${clang_source_path}/${LIBCLANG_INCLUDE_PATH}/ OUTPUT_VARIABLE RES1) 220 | list(APPEND RES ${RES1}) 221 | set(${result_headers} ${RES} PARENT_SCOPE) 222 | unset(RES) 223 | if(MSVC) 224 | list(TRANSFORM LIBCLANG_LINK_LIBS PREPEND ${clang_prebuilt_path}/lib/ OUTPUT_VARIABLE RES) 225 | list(TRANSFORM RES APPEND .lib OUTPUT_VARIABLE RES) 226 | else() 227 | list(TRANSFORM LIBCLANG_LINK_LIBS PREPEND ${clang_prebuilt_path}/lib/lib OUTPUT_VARIABLE RES) 228 | list(TRANSFORM RES APPEND .a OUTPUT_VARIABLE RES) 229 | endif() 230 | set(${result_required_libs} ${RES} PARENT_SCOPE) 231 | unset(RES) 232 | endfunction() 233 | -------------------------------------------------------------------------------- /cmake/modules/LinuxMacosBuild.cmake: -------------------------------------------------------------------------------- 1 | if(APPLE) 2 | set(LIBCLANG_PREBUILT_URL https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.0/clang+llvm-13.0.0-x86_64-apple-darwin.tar.xz) 3 | else() 4 | set(LIBCLANG_PREBUILT_URL https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.0/clang+llvm-13.0.0-x86_64-linux-gnu-ubuntu-20.04.tar.xz) 5 | endif() 6 | set(CLANG_SOURCES_URL https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.0/clang-13.0.0.src.tar.xz) 7 | set(NCURSES_SOURCES_URL https://ftp.gnu.org/pub/gnu/ncurses/ncurses-6.2.tar.gz) 8 | if(APPLE) 9 | set(Z3_PREBUILT_URL https://github.com/Z3Prover/z3/releases/download/z3-4.8.7/z3-4.8.7-x64-osx-10.14.6.zip) 10 | else() 11 | set(Z3_PREBUILT_URL https://github.com/Z3Prover/z3/releases/download/z3-4.8.7/z3-4.8.7-x64-ubuntu-16.04.zip) 12 | endif() 13 | 14 | include(Download) 15 | message(STATUS "Downloading ncurses sources, prebuilt z3 & prebuilt libclang with sources; this is ~500MB, please be patient, 'libclang_prebuilt' will take several minutes ...") 16 | set(NCURSES_SOURCE_DIR) 17 | download(ncurses_sources ${NCURSES_SOURCES_URL} NCURSES_DOWNLOAD_DIR) 18 | set(LIBCLANG_SOURCES_DIR) 19 | download(clang_sources ${CLANG_SOURCES_URL} LIBCLANG_SOURCES_DIR) 20 | set(Z3_PREBUILT_DIR) 21 | download(z3_prebuilt ${Z3_PREBUILT_URL} Z3_PREBUILT_DIR) 22 | set(LIBCLANG_PREBUILT_DIR) 23 | download(libclang_prebuilt ${LIBCLANG_PREBUILT_URL} LIBCLANG_PREBUILT_DIR) 24 | 25 | include(ExternalProject) 26 | ExternalProject_Add(ncurses 27 | SOURCE_DIR ${NCURSES_DOWNLOAD_DIR} 28 | CONFIGURE_COMMAND /configure --enable-rpath --prefix=${CMAKE_INSTALL_PREFIX} --with-shared --with-static --with-normal --without-debug --without-ada --enable-widec --disable-pc-files --with-cxx-binding --without-cxx-shared --with-abi-version=5 29 | BUILD_COMMAND make 30 | INSTALL_COMMAND "" 31 | ) 32 | 33 | list(APPEND CMAKE_MODULE_PATH "${LIBCLANG_PREBUILT_DIR}/lib/cmake/clang") 34 | list(APPEND CMAKE_MODULE_PATH "${LIBCLANG_PREBUILT_DIR}/lib/cmake/llvm") 35 | list(APPEND CMAKE_MODULE_PATH "${LIBCLANG_SOURCES_DIR}/cmake/modules") 36 | include(LibClangBuild) 37 | include(HandleLLVMOptions) 38 | include(AddLLVM) 39 | include(AddClang) 40 | include(GatherArchives) 41 | 42 | set(CMAKE_CXX_STANDARD 14) 43 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 44 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti") 45 | 46 | get_libclang_sources_and_headers( 47 | ${LIBCLANG_SOURCES_DIR} 48 | ${LIBCLANG_PREBUILT_DIR} 49 | LIBCLANG_SOURCES 50 | LIBCLANG_ADDITIONAL_HEADERS 51 | LIBCLANG_PREBUILT_LIBS 52 | ) 53 | 54 | include_directories(${LIBCLANG_PREBUILT_DIR}/include) 55 | 56 | ExternalProject_Get_Property(ncurses BINARY_DIR) 57 | set(NCURSES_BINARY_DIR ${BINARY_DIR}) 58 | set(NCURSES_SHARED_LIB) 59 | if(APPLE) 60 | set(NCURSES_SHARED_LIB ${NCURSES_BINARY_DIR}/lib/libncursesw.dylib ${NCURSES_BINARY_DIR}/lib/libncursesw.5.dylib) 61 | else() 62 | set(NCURSES_SHARED_LIB ${NCURSES_BINARY_DIR}/lib/libncursesw.so ${NCURSES_BINARY_DIR}/lib/libncursesw.so.5 ${NCURSES_BINARY_DIR}/lib/libncursesw.so.5.9) 63 | endif() 64 | unset(BINARY_DIR) 65 | 66 | if(APPLE) 67 | set(Z3_SHARED_LIB ${Z3_PREBUILT_DIR}/bin/libz3.dylib) 68 | else() 69 | set(Z3_SHARED_LIB ${Z3_PREBUILT_DIR}/bin/libz3.so) 70 | endif() 71 | 72 | add_clang_library(libclang 73 | SHARED 74 | OUTPUT_NAME clang 75 | ${LIBCLANG_SOURCES} 76 | ADDITIONAL_HEADERS ${LIBCLANG_ADDITIONAL_HEADERS} 77 | LINK_LIBS 78 | ${LIBCLANG_PREBUILT_LIBS} ${NCURSES_SHARED_LIB} dl pthread z 79 | LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} 80 | DEPENDS ncurses 81 | ) 82 | 83 | add_clang_library(libclang_static 84 | STATIC 85 | OUTPUT_NAME clang_static 86 | ${LIBCLANG_SOURCES} 87 | ADDITIONAL_HEADERS ${LIBCLANG_ADDITIONAL_HEADERS} 88 | DEPENDS ncurses 89 | ) 90 | 91 | set_target_properties(libclang PROPERTIES VERSION 13) 92 | 93 | if(APPLE) 94 | set(LIBCLANG_LINK_FLAGS " -Wl,-compatibility_version -Wl,1") 95 | set_property(TARGET libclang APPEND_STRING PROPERTY 96 | LINK_FLAGS ${LIBCLANG_LINK_FLAGS}) 97 | else() 98 | set_target_properties(libclang 99 | PROPERTIES 100 | DEFINE_SYMBOL _CINDEX_LIB_) 101 | endif() 102 | 103 | if(APPLE) 104 | add_custom_target( 105 | libclang_bundled ALL 106 | COMMAND ${CMAKE_LIBTOOL} -static -o libclang_bundled.a 107 | ${CMAKE_CURRENT_BINARY_DIR}/libclang_static.a 108 | ${LIBCLANG_PREBUILT_LIBS} 109 | ${NCURSES_BINARY_DIR}/lib/libncursesw.a 110 | ${Z3_PREBUILT_DIR}/bin/libz3.a 111 | DEPENDS ncurses libclang libclang_static 112 | ) 113 | else() 114 | gatherArchives( 115 | ALL_ARCHIVES_DIRECTORY 116 | ALL_ARCHIVE_NAMES 117 | ALL_ARCHIVE_PATHS 118 | ${CMAKE_CURRENT_BINARY_DIR}/libclang_static.a 119 | ${LIBCLANG_PREBUILT_LIBS} 120 | ${NCURSES_BINARY_DIR}/lib/libncursesw.a 121 | ${Z3_PREBUILT_DIR}/bin/libz3.a 122 | ) 123 | add_custom_target( 124 | gather_archives ALL 125 | COMMAND ${CMAKE_COMMAND} -E make_directory ${ALL_ARCHIVES_DIRECTORY} 126 | COMMAND ${CMAKE_COMMAND} -E copy 127 | ${CMAKE_CURRENT_BINARY_DIR}/libclang_static.a 128 | ${LIBCLANG_PREBUILT_LIBS} 129 | ${NCURSES_BINARY_DIR}/lib/libncursesw.a 130 | ${Z3_PREBUILT_DIR}/bin/libz3.a 131 | ${ALL_ARCHIVES_DIRECTORY} 132 | DEPENDS ncurses libclang libclang_static 133 | ) 134 | add_custom_target( 135 | libclang_bundled ALL 136 | COMMAND ${CMAKE_AR} crsT libclang_bundled.a ${ALL_ARCHIVE_NAMES} 137 | WORKING_DIRECTORY ${ALL_ARCHIVES_DIRECTORY} 138 | DEPENDS gather_archives 139 | ) 140 | endif() 141 | 142 | set(MAKEFILE_LIBCLANG_INCLUDE ${CMAKE_INSTALL_PREFIX}/include) 143 | if(APPLE) 144 | set(MAKEFILE_LIBCLANG_INCLUDE "${MAKEFILE_LIBCLANG_INCLUDE} -I${CMAKE_OSX_SYSROOT}/usr/include") 145 | endif() 146 | set(MAKEFILE_LIBCLANG_LIBDIR ${CMAKE_INSTALL_PREFIX}/lib) 147 | 148 | file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/examples/static) 149 | configure_file(${LIBCLANG_EXAMPLES}/Makefile_static.in ${CMAKE_CURRENT_BINARY_DIR}/examples/static/Makefile) 150 | if(APPLE) 151 | configure_file(${LIBCLANG_EXAMPLES}/Makefile_shared_macos.in ${CMAKE_CURRENT_BINARY_DIR}/examples/shared/Makefile) 152 | else() 153 | configure_file(${LIBCLANG_EXAMPLES}/Makefile_shared.in ${CMAKE_CURRENT_BINARY_DIR}/examples/shared/Makefile) 154 | endif() 155 | 156 | file(COPY ${LIBCLANG_EXAMPLES}/clang_visitor.c DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/examples/static) 157 | file(COPY ${LIBCLANG_EXAMPLES}/sample.H DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/examples/static) 158 | file(COPY ${LIBCLANG_EXAMPLES}/clang_visitor.c DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/examples/shared) 159 | file(COPY ${LIBCLANG_EXAMPLES}/sample.H DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/examples/shared) 160 | 161 | if(APPLE) 162 | set(LIBCLANG_INSTALL_LIBS 163 | ${CMAKE_CURRENT_BINARY_DIR}/libclang_bundled.a 164 | ${Z3_PREBUILT_DIR}/bin/libz3.a 165 | ${Z3_SHARED_LIB} 166 | ${NCURSES_BINARY_DIR}/lib/libncursesw.a 167 | ${NCURSES_SHARED_LIB} 168 | ) 169 | else() 170 | set(LIBCLANG_INSTALL_LIBS 171 | ${ALL_ARCHIVES_DIRECTORY}/libclang_bundled.a 172 | ${ALL_ARCHIVE_PATHS} 173 | ${Z3_SHARED_LIB} 174 | ${NCURSES_SHARED_LIB} 175 | ) 176 | endif() 177 | 178 | install(PROGRAMS ${LIBCLANG_INSTALL_LIBS} DESTINATION lib) 179 | install(DIRECTORY ${LIBCLANG_PREBUILT_DIR}/include/clang-c DESTINATION include) 180 | install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/examples DESTINATION share/doc) 181 | -------------------------------------------------------------------------------- /cmake/modules/MSVCBuild.cmake: -------------------------------------------------------------------------------- 1 | set(LIBCLANG_PREBUILT_URL https://ziglang.org/deps/llvm+clang+lld-13.0.0-x86_64-windows-msvc-release-mt.tar.xz) 2 | set(CLANG_SOURCES_URL https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.0/clang-13.0.0.src.tar.xz) 3 | 4 | include(Download) 5 | message(STATUS "Downloading prebuilt libclang with sources; this is ~500MB, please be patient, 'libclang_prebuilt' will take several minutes ...") 6 | download(clang_sources ${CLANG_SOURCES_URL} LIBCLANG_SOURCES_DIR) 7 | download(libclang_prebuilt ${LIBCLANG_PREBUILT_URL} LIBCLANG_PREBUILT_DIR) 8 | 9 | list(APPEND CMAKE_MODULE_PATH "${LIBCLANG_PREBUILT_DIR}/lib/cmake/clang") 10 | list(APPEND CMAKE_MODULE_PATH "${LIBCLANG_PREBUILT_DIR}/lib/cmake/llvm") 11 | list(APPEND CMAKE_MODULE_PATH "${LIBCLANG_SOURCES_DIR}/cmake/modules") 12 | 13 | set(CMAKE_CXX_STANDARD 14) 14 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 15 | include(LibClangBuild) 16 | include(HandleLLVMOptions) 17 | include(AddLLVM) 18 | include(AddClang) 19 | 20 | get_libclang_sources_and_headers( 21 | ${LIBCLANG_SOURCES_DIR} 22 | ${LIBCLANG_PREBUILT_DIR} 23 | LIBCLANG_SOURCES 24 | LIBCLANG_ADDITIONAL_HEADERS 25 | LIBCLANG_PREBUILT_LIBS 26 | ) 27 | include_directories(${LIBCLANG_PREBUILT_DIR}/include) 28 | add_clang_library(libclang 29 | SHARED 30 | STATIC 31 | OUTPUT_NAME clang 32 | ${LIBCLANG_SOURCES} 33 | LINK_LIBS ${LIBCLANG_PREBUILT_LIBS} Version 34 | ADDITIONAL_HEADERS ${LIBCLANG_ADDITIONAL_HEADERS} 35 | ) 36 | 37 | set_target_properties(libclang PROPERTIES VERSION 12) 38 | 39 | target_compile_definitions(obj.libclang PUBLIC "_CINDEX_LIB_") 40 | 41 | find_program(lib_tool lib) 42 | if(NOT lib_tool) 43 | get_filename_component(CXX_COMPILER_DIRECTORY "${CMAKE_CXX_COMPILER}" PATH) 44 | set(lib_tool "${CXX_COMPILER_DIRECTORY}/lib.exe") 45 | endif() 46 | set(AR_COMMAND ${lib_tool} /NOLOGO /OUT:${CMAKE_CURRENT_BINARY_DIR}/clang_static_bundled.lib "${CMAKE_CURRENT_BINARY_DIR}/obj.libclang.dir/Release/obj.libclang.lib" ${LIBCLANG_PREBUILT_LIBS}) 47 | 48 | add_custom_target(libclang_static_bundled ALL 49 | COMMAND ${AR_COMMAND} 50 | DEPENDS libclang 51 | BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/clang_static_bundled.lib 52 | ) 53 | set(LIBCLANG_INSTALL_LIBS ${CMAKE_CURRENT_BINARY_DIR}/clang_static_bundled.lib) 54 | 55 | set(CMAKE_MSVC_LIB_DIR ${CMAKE_INSTALL_PREFIX}/lib) 56 | set(CMAKE_MSVC_INCLUDE_DIR ${CMAKE_INSTALL_PREFIX}/include) 57 | configure_file(${LIBCLANG_EXAMPLES}/CMakeLists.MSVC.in ${CMAKE_CURRENT_BINARY_DIR}/examples/static/CMakeLists.txt) 58 | file(COPY ${LIBCLANG_EXAMPLES}/sample.H DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/examples/static/bin) 59 | file(COPY ${LIBCLANG_EXAMPLES}/clang_visitor.c DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/examples/static) 60 | file(COPY ${LIBCLANG_EXAMPLES}/README.txt DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/examples/static) 61 | 62 | install(PROGRAMS ${LIBCLANG_INSTALL_LIBS} DESTINATION lib) 63 | install(DIRECTORY ${LIBCLANG_PREBUILT_DIR}/include/clang-c DESTINATION include) 64 | install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/examples DESTINATION share/doc) 65 | --------------------------------------------------------------------------------