Cross-Compiling OpenOCD: A Step-by-Step Walkthrough
Learn how to build OpenOCD binaries on Ubuntu 22.04 for both the ARM64 and AMD64 target architectures. A great way to share a consistent OpenOCD build across your Debian systems

Last time we built OpenOCD from source on a Raspberry Pi, but I wasn't a fan of that setup. I have a desktop machine that also needs the latest OpenOCD and building the same binary twice, once for ARM64 and again for AMD64, is a pain. Plus, installing all those build tools can clutter the system. So, I started thinking about what's a better way to do this? The answer was quite obvious, I will use a dedicated build machine, a virtual machine to be precise, and cross-compile the binaries for both architectures at the same time. For the virtual machine we will use Ubuntu 22.04 as the Raspberry Pi OS and my Debian machine are both based on the Bookworm version.

Compiling for AMD64 Architecture
The steps required to compile OpenOCD on Ubuntu 22.04 are quite similar to the steps we did when we compiled it on our Raspberry Pi. Let's go over them one more time, this time we speed run that. First of all, we update our system and install all the required tools and libraries. Next we clone the repository and configure the build, finally we build the binary.
sudo apt update && sudo apt upgrade
sudo apt install git libtool autoconf automake pkg-config libusb-1.0-0-dev libhidapi-dev libjim-dev
git clone --recursive https://github.com/openocd-org/openocd.git
cd openocd
./bootstrap
./configure --prefix=/usr --enable-cmsis-dap
make -j$(nproc)
The built binary file is created in the src/
directory. To be able to use the built binary we need to copy the binary and the whole content of the scripts
directory. For example on the same machine we could use cp
to copy all the necessary files and directories to /usr
.
sudo cp src/openocd /usr/local/bin/
sudo mkdir -p /usr/local/share/openocd/scripts/
sudo cp -r tcl/* /usr/local/share/openocd/scripts/
Nice!!! No problems building OpenOCD on Ubuntu. So, let's move on to ARM64 architecture.
Compiling for ARM64 Architecture
By default our AMD64 Linux VM will not have the ARM64 packages installed, and therefore we can't cross-compile. First things first, we need to tell our system to support the ARM64 architecture. We can do that with the Debian package management tool.
sudo dpkg --add-architecture arm64
Next, we need to provide the system with the necessary info about ARM64 repositories in the Debian registry. But first we need update the source.list
file to indicate the entries present are intended for the amd64 architecture. The following sed
command will add [arch=amd64]
to all the lines that start with deb h
.
sudo sed -i "s/deb h/deb [arch=amd64] h/g" /etc/apt/sources.list
Next we need to add the correct sources for the arm64
architecture. Add the following line to /etc/apt/sources.list
# arm64 repositories
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy main restricted universe multiverse
deb-src [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy main restricted universe multiverse
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates main restricted universe multiverse
deb-src [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates main restricted universe multiverse
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-backports main restricted universe multiverse
deb-src [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-backports main restricted universe multiverse
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security main restricted universe multiverse
deb-src [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security main restricted universe multiverse
deb [arch=arm64] http://archive.canonical.com/ubuntu jammy partner
deb-src [arch=arm64] http://archive.canonical.com/ubuntu jammy partner
Save the file and exit the editor. Then, run apt update
to fetch the new package lists.
sudo apt update
In the previous step we installed required tools and libraries as before, but this time we also need some additional cross compile and dedicated ARM libraries.
sudo apt install libusb-1.0-0-dev:arm64 libhidapi-dev:arm64 libjim-dev:arm64
sudo apt install build-essential zlib1g-dev crossbuild-essential-arm64
As we already have the repository and probably files from the last build still scattered around we should make a clean first.
make clean
Next we set up the cross-compilation environment for ARM:
--host=aarch64-linux-gnu
: Specifies the target architecture (ARM64 for Raspberry Pi 4).--prefix=/usr
: Installs the binaries to/usr
in the final package.
./bootstrap
./configure --host=aarch64-linux-gnu --prefix=/usr
Finally we build the software:
make -j$(nproc)
We can also verify that the built file is now intended for the ARM64 architecture with the file
command. Once we run it we will get quite an informative output.
$ file ./src/openocd
./src/openocd: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=1b732f50bf017fc1ed1c31cbb3cece071874bc8b, for GNU/Linux 3.7.0, with debug_info, not stripped
Uuh...that was a lot of work...but now we have the build setup in place!

Adding Source Repositories to Ubuntu 24.04
I would also like to take a minute to go over adding the required sources in Ubuntu 24.04 as of the 9th of August 2025 Debian announced the release of Debian 13 (Trixie). Ubuntu 24.04 and hopefully soon the new Pi OS version will be based on Trixie. With Ubuntu 24.04 (Noble Numbat), Ubuntu is now using a new deb822
format for its APT source files. The deb822
format uses a multi-line, key-value structure instead of the traditional single-line format.
To add the ARM64 repositories, we will need to add a new file in /etc/apt/sources.list.d/
with the correct deb822
syntax.
sudo nano /etc/apt/sources.list.d/ubuntu-ports.sources
Inside the new file, we need to input the following content, as you will notice the content is quite similar to the older source.list
file used in e.g. Ubuntu 22.04.
Types: deb deb-src
URIs: http://ports.ubuntu.com/ubuntu-ports
Suites: noble noble-updates noble-backports noble-security
Components: main restricted universe multiverse
Architectures: arm64
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
And that is it, we can now continue from the apt update
step for Ubuntu 24.04 the same as we did for Ubuntu 22.04.
Installing Needed Libraries
Now we have the binaries that we could copy to our machines, but we would still need to install some required libraries as OpenOCD is a dynamically linked application. It can be messy understanding what libraries we need, but there is a good way of having a look. We can use objdump
with the -p
flag to display object format specific file header content.
$ objdump -p out/amd64/openocd
Dynamic Section:
NEEDED libusb-1.0.so.0
NEEDED libftdi.so.1
NEEDED libhidapi-hidraw.so.0
NEEDED libm.so.6
NEEDED libjim.so.0.81
NEEDED libc.so.6
From here we can see the the needed dynamic libraries that we must install. The Linux libraries follow the following format lib<name>.so.<version>
. Now we can use apt install
to install the required libraries.
That's about it, we can now use our build machine compiled binaries in our Debian machines.
What's Next?
This is good, but we can do even better. Next up, we'll look at creating a Debian package for OpenOCD, with that we can install our built binary like any other program using apt install
. Be sure to check it out!
Enjoyed This Post?
Love tinkering with embedded systems and hands-on projects? Join our email list, and we’ll share our latest posts, tips, and discoveries with you - no spam, just the good stuff!

Including External Libraries in CMake Projects
Learn how to use CMake’s FetchContent module to automatically download and integrate libraries like CMSIS into your embedded projects, eliminating the hassle of manual copying and updates.

How to Find the Memory Address of a Symbol in an ELF File
A quick and useful tip for locating symbol memory addresses in ELF files using arm-none-eabi-nm combined with grep—perfect for embedded debugging scenarios like setting up SEGGER RTT or inspecting linker placements and runtime symbols.

Remote Debugging with OpenOCD on Raspberry Pi
Learn how to turn a Raspberry Pi into a remote debugging server for the RP2040 using OpenOCD, a complete with step-by-step setup and instructions for building OpenOCD from source to resolve hardware compatibility issues.
Whether you're building something new, fixing stability issues, or automating what slows your team down — we can help.