Gradle + LLVM

This short post may be useful for those who would like to quickly start working with LLVM , without bothering with downloading the sources and a spacious framework. Who would not want to poke around in obscure CMake scripts to achieve the expected result, and finally, just for the lazy :)



Iโ€™ll tell you how to do it gracefully, just a couple of lines in the Gradle build script.



Faced with the need to write code under LLVM, I realized that โ€œhitโ€. :) โ€œHitโ€ is already at the build configuration stage for the project. I needed the project to be built uniformly under both Linux and Windows. Of course, every time along with the project I didnโ€™t want to build the entire LLVM at all. And, at first, I relied on pre-built versions of the library from their official site, but as it turned out, in fact, there are only Linux binaries built without RTTI and exceptions. Under Windows there is an installer, but despite the fact that it is called LLVM-xxx-win64.exe inside only clang.



Well, in the appendage of the build, there is a CMake system in which for building in the release version for Linux you need to set at the configuration stage:



cmake -DCMAKE_BUILD_TYPE=Release
      
      





And under Windows this, for some reason, is not enough and you still have to additionally change the configuration in the build command itself:



 cmake --build . --config Release
      
      





In general, I decided to turn my eyes to Gradle and write a good plugin that would take the trouble to configure a build for me and save me from unnecessary routine, leaving only the most necessary and high-level things in sight.



Actually, the discussion below will be exclusively about him: cpp-llvm .

Here is the minimum configuration required to integrate with LLVM:



 plugins { id 'org.bitbucket.akornilov.cpp-llvm' version '0.1' } llvm { version = '9.0.0' // Required version. }
      
      





Requirements for work:





Supported versions of LLVM:





Unofficial builds for x86_64 on Windows (msvc 2019) and Linux (Debian 10.0 + CLang 10.0). Built with RTTI enabled and exceptions in two versions Release and Debug.





Official builds from LLVM servers, only x86_64 under Linux with RTTI turned off and exceptions.



To see the list of supported versions for the current platform, you can use the following command:



 gradle llvmVersions
      
      





 > Task :llvm-app:llvmVersions 9.0.0 8.0.0 BUILD SUCCESSFUL in 2s 1 actionable task: 1 executed
      
      





All LLVM binaries necessary for the build are loaded into the local cache (in the gradle folder in the user directory) and reused for other builds.



At the first start, preparation for construction can take a considerable time, because about 300MB for the debug version or 30MB for the release version will be downloaded from the network (official versions also weigh about 300MB).



Only static linking is used. for some unknown reason, the build LLVM binding is not able to create dynamic libraries under MSVC.



Other plugin configuration



You can specify a specific address for downloading the archive with binaries (.tar.xz or .tar.gz).



 llvm { version = '7.0.1' serverUrl = 'http://releases.llvm.org/7.0.1/clang%2bllvm-7.0.1-x86_64-linux-gnu-ubuntu-18.04.tar.xz' }
      
      





The main thing is that the specified version (version = xxx) coincides with the one that is real in the archive selected for download, otherwise the build configuration may be incorrect.



You can work with ready-made LLVM binaries (downloaded or built yourself) autonomously



 llvm { version = '7.0.1' localPath = '<path to unpacked LLVM build>' }
      
      





localPath should point to an existing folder on the local file system inside which the plugin expects to see the subdirectories 'include' and 'lib', i.e. directory structure used in official builds. If after self-tuning you have a different folder structure, you will need to โ€œcombโ€ it. :)



The versions should also match, as already noted, in the previous paragraph.

In this case, nothing related to LLVM will be loaded from the network.



Work with individual components:



 llvm { version = '9.0.0' components = ['Engine', 'OrcJIT'] }
      
      





If you work only with a specific part of LLVM, then you certainly need to pay attention to this parameter. If, for example, you only need OrcJIT, why link all one hundred and forty-five static libraries? The choice of specific components will greatly facilitate the life of the linker, and you will save time.



A list of all available components can be found like this:



 gradle llvmComponents
      
      





On Linux, you can significantly reduce the link time in the debug version, if you use this option



 llvm { version = '9.0.0' forceReleaseLinux = true }
      
      





In this case, the LLVM release version is forcibly used in the debug version of your build. In most cases, I would recommend using it unless you need to debug LLVM itself. This option does not affect the assembly on Windows, because, unfortunately, MSVC 2019 does not allow mixing release and debug libraries in one build.



Well, in conclusion, of course, I would recommend using this plugin in conjunction with my other plugins :), which can be read about in this article .



cpp-build-tuner will help optimize compilation time and the size of the resulting binary.



cpp-ide-generator will give you easy integration with several IDEs, in the configuration of which there will already be paths to LLVM headers and the IDE will be able to correctly index them.







Possible problem when using cpp-ide-generator:



 FAILURE: Build failed with an exception. * What went wrong: A problem occurred configuring project ':llvm-app'. > Cannot change dependencies of configuration ':llvm-app:cppCompileDebug' after it has been resolved.
      
      





If you saw this, then it just means that cpp-ide-generator should be added after cpp-llvm, as here:



 plugins { id 'cpp-application' id 'org.bitbucket.akornilov.cpp-build-tuner' version '0.7' id 'org.bitbucket.akornilov.cpp-llvm' version '0.1' id 'org.bitbucket.akornilov.cpp-ide-generator' version '0.5' }
      
      





A complete example of using the plugin can be found here .



All Articles