Skip to main content
Redhat Developers  Logo
  • Products

    Platforms

    • Red Hat Enterprise Linux
      Red Hat Enterprise Linux Icon
    • Red Hat AI
      Red Hat AI
    • Red Hat OpenShift
      Openshift icon
    • Red Hat Ansible Automation Platform
      Ansible icon
    • View All Red Hat Products

    Featured

    • Red Hat build of OpenJDK
    • Red Hat Developer Hub
    • Red Hat JBoss Enterprise Application Platform
    • Red Hat OpenShift Dev Spaces
    • Red Hat OpenShift Local
    • Red Hat Developer Sandbox

      Try Red Hat products and technologies without setup or configuration fees for 30 days with this shared Openshift and Kubernetes cluster.
    • Try at no cost
  • Technologies

    Featured

    • AI/ML
      AI/ML Icon
    • Linux
      Linux Icon
    • Kubernetes
      Cloud icon
    • Automation
      Automation Icon showing arrows moving in a circle around a gear
    • View All Technologies
    • Programming Languages & Frameworks

      • Java
      • Python
      • JavaScript
    • System Design & Architecture

      • Red Hat architecture and design patterns
      • Microservices
      • Event-Driven Architecture
      • Databases
    • Developer Productivity

      • Developer productivity
      • Developer Tools
      • GitOps
    • Automated Data Processing

      • AI/ML
      • Data Science
      • Apache Kafka on Kubernetes
    • Platform Engineering

      • DevOps
      • DevSecOps
      • Ansible automation for applications and services
    • Secure Development & Architectures

      • Security
      • Secure coding
  • Learn

    Featured

    • Kubernetes & Cloud Native
      Openshift icon
    • Linux
      Rhel icon
    • Automation
      Ansible cloud icon
    • AI/ML
      AI/ML Icon
    • View All Learning Resources

    E-Books

    • GitOps Cookbook
    • Podman in Action
    • Kubernetes Operators
    • The Path to GitOps
    • View All E-books

    Cheat Sheets

    • Linux Commands
    • Bash Commands
    • Git
    • systemd Commands
    • View All Cheat Sheets

    Documentation

    • Product Documentation
    • API Catalog
    • Legacy Documentation
  • Developer Sandbox

    Developer Sandbox

    • Access Red Hat’s products and technologies without setup or configuration, and start developing quicker than ever before with our new, no-cost sandbox environments.
    • Explore Developer Sandbox

    Featured Developer Sandbox activities

    • Get started with your Developer Sandbox
    • OpenShift virtualization and application modernization using the Developer Sandbox
    • Explore all Developer Sandbox activities

    Ready to start developing apps?

    • Try at no cost
  • Blog
  • Events
  • Videos

Remote LLVM development with Visual Studio Code

April 22, 2021
Konrad Kleine
Related topics:
C, C#, C++IDEsLinux
Related products:
Developer Tools

Share:

    I used the Qt Creator IDE for most of my C++ work in the past. Then I joined Red Hat around mid-2016 and worked on a project with Go for three years. I quickly realized that I wanted something similar to Qt Creator. I’m a regular Vim user, but use it only for plain-text editing and not much more. I gave Vim a shot when really I was looking for something that works out of the box and can still be customized. As usual for a modern project, I needed to be able to do more than edit the files of one programming realm. Enter Visual Studio Code (VS Code).

    I can't say that VS Code worked out of the box. But being new to Go, I figured I would give it a try, especially because others were using it. Three years later, in 2019, I needed a change and joined our debuggers group to work on LLDB, a debugger that is part of the much larger LLVM project. LLVM also hosts Clang, a well-known compiler front-end for C-like languages.

    I began by checking out the LLVM codebase—which is huge, by the way—and compiling it on my local machine, which was very slow. You can read about my initial endeavor to speed up the compilation in this article. To sum things up: A notebook isn’t ideal when you want to code and compile with LLVM. The speed of compilation isn’t the only thing that matters. It’s the linking, as well, that can easily freeze my laptop. That said, distributed compilation using distcc or similar tools doesn't cut it.

    Our group in Red Hat has access to high-powered shared machines in Toronto (e.g., 56 cores with 256 GB of memory). I live in Germany, and at first I was skeptical whether I could successfully use those machines without too much latency. Qt Creator wasn’t a true option for editing files remotely because, as far as I know, it needed to run next to the code it was supposed to compile. After giving Vim and Emacs another shot for coding and compiling remotely, I went back to VS Code and found out that there’s a remote SSH extension. This article navigates you through how I’ve been using VS Code's remote SSH extension for editing and compiling LLVM, step by step.

    Prerequisites

    My base system is a laptop running the Fedora 32 operating system. For the sake of this tutorial, we’ll call the remote host just remote-host. If you want to follow the tutorial step by step, you can put the following into your ~/.ssh/config file to create an alias to whatever host you want:

    Host remote-host
      HostName YOUR_OWN_REMOTE_HOST_GOES_HERE
      User USER_NAME_WITH_WHICH_YOU_LOGIN_TO_YOUR_REMOTE_HOST

    Replace the obvious bits in that definition. Make sure you can log in to the remote host without entering a password by copying the public part of your SSH-key to the remote host: ssh-copy-id remote-host.

    Double-check that you can now log in using ssh remote-host. Now log back out.

    Setting up VS Code

    First, make sure you have a recent copy of VS Code or grab it from the download site. Once it's installed, you will need a bunch of extensions. To install the extensions I find useful when building and editing LLVM, run this snippet in the command line:

    $ for i in ms-vscode.cmake-tools \
    ms-vscode-remote.remote-ssh \
    ms-python.python \
    ms-vscode.cpptools \
    twxs.cmake \
    rreverser.llvm \
    jakob-erzar.llvm-tablegen \
    xaver.clang-format \
    pkief.material-icon-theme; do code --install-extension $i; done

    Preparing the remote host

    In my case, the architecture of the remote host (Fedora 31) and my laptop is the same: x86_64. I'm not sure if this always needs to be the case. I can confirm that instead of my Linux laptop and Linux remote host, I can use a Mac laptop and a Linux remote host. I'm sure the same is true for Windows.

    Log in to the remote host with:

    $ ssh remote-host

    Your remote host needs to have all the development tools installed that are required to build LLVM.

    Let's decide where to download LLVM and refer to it with an environment variable for now. In my case, the directory is not ~/ which would have simplified things a bit:

    $ export MYHOME=/opt/notnfs/kkleine/ # replace this with ~/

    Navigate to $MYHOME:

    $ cd $MYHOME

    Fetch the LLVM source tree:

    $ git clone https://github.com/llvm/llvm-project

    Now create a build directory inside the source directory:

    $ mkdir llvm-project/build

    This directory makes it simpler to find build files within the VS Code IDE later.

    Firing up VS Code

    When you start VS Code, it presents a screen like Figure 1.

    VS Code startup screen
    Figure 1: The VS Code startup screen.

    Notice the little green icon in the lower left corner of the screen. Click on it and select Remote-SSH: Connect Current Window to Host... as shown in Figure 2.

    Remote SSH Extension drop down
    Figure 2: Select 'Remote-SSH: Connect Current Window to Host...' from the menu.

    If you've configured your ~/.ssh/config properly, you can now select remote-host from the drop-down list. Notice that the green icon from before now shows Opening Remote ... and then turns into SSH: remote-host once you have connected successfully.

    Congratulations: You can now edit files on your remote host using VS Code. To test this, go to File—>Open File... and open the main CMakeLists.txt file from the LLVM project that you checked out earlier: /opt/notnfs/kkleine/llvm-project/llvm/CMakeLists.txt.

    Installing extensions remotely

    Let's head over to the extensions by clicking on the extensions symbol, which is a grid of squares. Notice that the side panel shows locally installed extensions and marks some with Install in SSH: remote-host. Click that little green icon to view all the extensions that can be installed on the remote host. Once that's done, click the blue Reload Required icon and enjoy all the extensions when developing remotely.

    Adjusting the settings

    We need to adjust some settings for CMake to work properly. Press Ctrl+Shift+P to open the command palette in Visual Studio Code and start typing >open remote set, as shown in Figure 3.

    Autofill in the command palette
    Figure 3: Autofill in the command palette.

    Then, click on Preferences: Open Remote Settings (SSH: remote-host). This should open up a settings.json file in a new tab, as shown in Figure 4.

    Open the remote settings file
    Figure 4: Open the remote settings file.

    This file is an empty JSON settings file, in my case. If you already have configurations in there, I assume that you have used VS Code before and know how to integrate my settings into yours. If your file is empty, you can copy the settings here:

    {
        //--------------------------------------------------------------------------
        //              C++
        //--------------------------------------------------------------------------
        "clang-format.fallbackStyle": "LLVM",
        "clang-format.style": "LLVM",
        "C_Cpp.clang_format_style": "LLVM",
        "C_Cpp.default.cppStandard": "c++14",
        "C_Cpp.default.cStandard": "c11",
        //--------------------------------------------------------------------------
        //              CMake
        //--------------------------------------------------------------------------
        "cmake.generator": "Ninja",
        // Adjust this path to the expansion of $MYHOME/llvm-project/llvm.
        "cmake.sourceDirectory": "/opt/notnfs/kkleine/llvm-project/llvm",
        // Adjust this path to the expansion of $MYHOME/llvm-project/build.
        "cmake.buildDirectory": "/opt/notnfs/kkleine/llvm-project/build",
        "cmake.configureSettings": {
            "LLVM_ENABLE_PROJECTS": ["clang","clang-tools-extra","compiler-rt","lld","mlir"],
            "CMAKE_EXPORT_COMPILE_COMMANDS": 1,
            "BUILD_SHARED_LIBS": "Off",
            "LLVM_BUILD_LLVM_DYLIB": "On",
            "LLVM_LINK_LLVM_DYLIB": "On",
            "CLANG_LINK_CLANG_DYLIB": "On",
            // I only need LLVM Backends to produce X86, decide what you need here!
            "LLVM_TARGETS_TO_BUILD": "X86",
            "LLVM_ENABLE_LDD": "On",
            "LLVM_CCACHE_BUILD": "On",
            "LLVM_CCACHE_MAXSIZE": "20G",
            "LLVM_ENABLE_IDE": "On",
            "LLVM_ENABLE_ASSERTIONS": "On",
            "LLVM_BUILD_EXAMPLES": "On",
            "LLVM_LIT_ARGS": "-v --xunit-xml-output test-results.xml",
            "PYTHON_EXECUTABLE": "/usr/bin/python3",
        },
        //--------------------------------------------------------------------------
        //              Editor
        //--------------------------------------------------------------------------
        "editor.mouseWheelZoom": true,
        "editor.renderIndentGuides": false,
        "editor.rulers": [80],
        "editor.formatOnPaste": false,
        "editor.renderWhitespace": "all",
        //--------------------------------------------------------------------------
        //              Misc
        //--------------------------------------------------------------------------
        "telemetry.enableTelemetry": false,
        "telemetry.enableCrashReporter": false,
        "[cpp]": {
            "editor.defaultFormatter": "xaver.clang-format"
        },
        "workbench.iconTheme": "material-icon-theme",
    }

    I've added a minimum of my personal settings to the JSON file. You can omit the Editor and Misc sections if you don't want them. When you are done, save the file with Ctrl+S.

    Configuring the LLVM project with CMake

    Click on File—>Open Folder and type in the expansion of $MYHOME/llvm-project (e.g.,~/llvm-project), as shown in Figure 5.

    Open folder dialog
    Figure 5: Type in the absolute path to the llvm-project folder.

    Open up the command palette in VS Code again by typing Ctrl+Shift+P followed by >cmake. This should bring up the list in Figure 6, from which you can select CMake: Select a Kit.

    CMake Select a Kit
    Figure 6: Select the 'CMake: Select a Kit' option.

    In the next dialog, shown in Figure 7, pick the compiler you want to use for compiling LLVM, or select [Scan for kits] if you don't see any options. (I chose Clang 9.0.1.)

    Select a Kit for LLVM Project
    Figure 7: VS Code presents the available compiler options.

    Next, you need to decide on the build variant in which CMake will configure your project. Bring back the command palette with Ctrl+Shift+P and Type CMake Select Variant, as shown in Figure 8.

    CMake Select Variant
    Figure 8: Select a build variant through 'CMake Select Variant'.

    Next, choose Release, as shown in Figure 9.

    Build Variant selection
    Figure 9: Choose Release as the build variant.

    Notice that the Status bar now looks like Figure 10. From now on, you can control which target you want to build from this bar.

    Status bar
    Figure 10: The status bar after choosing a build variant.

    If an output pane shows something like the following when the configuration is done, you've successfully configured LLVM:

    [cmake] -- Performing Test HAVE_POSIX_REGEX -- success
    [cmake] -- Performing Test HAVE_STEADY_CLOCK -- success
    [cmake] -- Configuring done
    [cmake] -- Generating done
    [cmake] -- Build files have been written to: /opt/notnfs/kkleine/llvm-project/build

    Note: You can read more about CMake in VS Code in the article Get started with CMake Tools on Linux.

    First build of Clang with VS Code

    Let's do our first build of Clang. Click on [all] in the status bar and type in clang to select the clang Executable. Notice that the status bar now shows [clang] instead of [all].

    Don't be afraid to hit that [Build] button to build the selected target.

    Something interesting is that VS Code doesn't care whether you chose Ninja or Make to build your project, because it calls CMake to invoke the underlying build system:

    [main] Building folder: llvm-project
    [build] Starting build
    [proc] Executing command: /usr/bin/cmake --build /opt/notnfs/kkleine/llvm-project/build --config Release --target clang -- -j 58
    [build] [58/2573   0% :: 0.383] Building CXX object lib/Support/CMakeFiles/LLVMSupport.dir/ABIBreak.cpp.o
    [build] [59/2573   0% :: 0.462] Building CXX object lib/Support/CMakeFiles/LLVMSupport.dir/COM.cpp.o/usr/bin/cmake --build /opt/notnfs/kkleine/llvm-project/build --config Release --target clang -- -j 58

    Bringing in a terminal

    VS Code does come with a terminal window. You can open it with Ctrl+` (the backtick character). The terminal looks like Figure 11.

    VS Code Terminal
    Figure 11: A command-line interface in the VS Code terminal window.

    Try testing your freshly built compiler with this snippet:

    $ cd build
    $ echo "int main(){return 42;}" | ./bin/clang++ -x c++ -
    $ ./a.out ; echo $?
    42

    I typically run some commands like ./bin/llvm-lit -v sometest in the terminal window. One nice thing about the terminal is that you can Ctrl+Click on any of the file paths to open them in the current VS Code window in a new tab. That makes opening and navigating files from the terminal extremely convenient.

    From here onward you can use all the goodies of VS Code, such as autocompletion, go-to declaration, switching between header and implementation, and so forth.

    Launching the configuration for LLVM-LIT

    To run llvm-lit -av current_file from inside VS Code, without using the terminal, you can bring back the command palette with Ctrl+Shift+P and type >launch to open the launch.json file. The menu displayed looks similar to Figure 12.

    Open Launch.json
    Figure 12: The menu displayed when you type '>launch' into the command palette.

    This file can contain multiple semi-generic configurations for programs you want to launch from time to time. Here's a configuration that will launch llvm-lit on the current file:

    {
        "version": "0.2.0",
        "configurations": [
            {
                "name": "llvm-lit current file",
                "type": "python",
                "request": "launch",
                "program": "/opt/notnfs/kkleine/llvm-project/build/bin/llvm-lit",
                "args": ["${fileBasename}"],
                "cwd": "${fileDirname}",
            }
            {
                "name": "llvm-lit all tests in current dir",
                "type": "python",
                "request": "launch",
                "program": "/opt/notnfs/kkleine/llvm-project/build/bin/llvm-lit",
                "args": ["."],
                "cwd": "${fileDirname}",
            }
        ]
    }

    You just need to adjust the path to point to your llvm-lit binary.

    Note: If the file hasn't been built yet, try building the all target or the check-llvm-tools-llvm-lit target.

    Let's open a specific lit file by pressing Ctrl+P. This opens a fuzzy dialog. Type ast-dump-decl.c and observe where the file is found (shown in Figure 13).

    Fuzzy file opening

    Once the file is opened, click on the debug symbol in the left-side bar to open a debugging pane. At this point we're not interested in debugging in the classic sense; we just want to launch llvm-lit. Click the small Play button (the triangle icon) next to your launch target name at the top of the screen. In this case, the launch target is llvm-lit current file. A terminal will open and show results like the following:

    $ cd /opt/notnfs/kkleine/llvm-project/clang/test/AST ; env /usr/bin/python /home/kkleine/.vscode-server/extensions/ms-python.python-2020.6.91350/pythonFiles/lib/python/debugpy/launcher 44349 -- /opt/notnfs/kkleine/llvm-project/build/bin/llvm-lit ast-dump-decl.c
    llvm-lit: /opt/notnfs/kkleine/llvm-project/build/bin/../../llvm/utils/lit/lit/llvm/config.py:347: note: using clang: /opt/notnfs/kkleine/llvm-project/build/bin/clang
    -- Testing: 1 tests, 1 workers --
    PASS: Clang :: AST/ast-dump-decl.c (1 of 1)
    
    Testing Time: 1.90s
      Passed: 1

    Feel free to run all the tests within the same directory as the current test file by selecting the other launch target, which is called llvm-lit all tests in current dir.

    Conclusion

    I hope you enjoyed reading this article—happy coding!

    Last updated: February 5, 2024

    Recent Posts

    • How to run OpenAI's gpt-oss models locally with RamaLama

    • Using DNS over TLS in OpenShift to secure communications

    • Scaling DeepSeek and Sparse MoE models in vLLM with llm-d

    • Multicluster authentication with Ansible Automation Platform

    • Verify Cosign bring-your-own PKI signature on OpenShift

    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Products

    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform

    Build

    • Developer Sandbox
    • Developer Tools
    • Interactive Tutorials
    • API Catalog

    Quicklinks

    • Learning Resources
    • E-books
    • Cheat Sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site Status Dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit
    © 2025 Red Hat

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Report a website issue