Skip to content

How to set up cross compilation of hidapi using Docker

Gary Rowe edited this page Apr 1, 2024 · 8 revisions

Introduction

You typically won't need to compile hidapi yourself as the hid4java project provides compiled versions of the latest version. However, there may be times when you need to explore a whole new platform for yourself (e.g. linux-riscv64 support) or you have a need to fork the upstream project for a time. Please do consider feeding your improvements back via a Pull Request so that others may benefit.

Prerequisites

If you are building a complete development environment from scratch you will need the following packages installed (macOS Homebrew commands provided but Windows/Linux equivalents can be found easily enough):

# Install XCode support for macOS to enable darwin compilation
xcode-select --install

# Install GCC support for hidapi compilation
brew install gcc automake autoconf

# Configure and compile hidapi DLLs/dylibs/libraries etc
cd hidapi
./bootstrap
./configure
make clean
make

# If aclocal.m4 gives trouble on macOS ARM run
autoreconf -f -i

# Verify that your hidapi platform contains a new library
# Example output on macOS could be 'Mach-O 64-bit dynamically linked shared library arm64'
file -b mac/.libs/libhidapi.0.dylib

Be aware that the make process for hidapi leaves a lot of build artifacts scattered around the project which can result in the compiler deciding not to do any work. These can be cleaned up through git but will result in a complete project reset (your IDE project configuration will be nuked):

# Remove all untracked files (note the -x which will kill IDE project files)
git clean -fdx

# Reset all tracked files
git reset --hard

Dockcross background

The hidapi libraries can be compiled using the popular dockcross project.

Essentially you use Docker containers that represent the build environment you are targeting (e.g. Windows x86) and can then perform the build there. The /work directory represents the root of the hidapi project and the resulting compiled library can then be copied to the hid4java project under a suitably named sub-directory.

Example of general cross-compilation process

The typical process for cross-compiling a shared Windows x86 target (DLL) on macOS is shown below. It assumes that you have Docker running but have not cloned either hidapi or dockcross.

# Start your Docker environment (Docker Desktop works best on macOS)
# Ensure that /usr/local/bin is in your shell's PATH

# Swap to your general working directory
cd workspaces/docker

# Clone the Dockcross project
git clone https://github.com/dockcross/dockcross.git 

# Configure Dockcross Docker script for Windows x86 so it is executable and on path
cd dockcross
docker run --rm dockcross/windows-shared-x86 > ./dockcross-windows-shared-x86
chmod +x ./dockcross-windows-shared-x86
mv ./dockcross-windows-shared-x86 /usr/local/bin

# Clone the native hidapi project (contains native code for a variety of OSes)
git clone https://github.com/libusb/hidapi.git

# Cross-compile hidapi (the Docker container will see the hidapi project root as /work)
cd ../hidapi
dockcross-windows-shared-x86 bash -c 'sudo ./bootstrap && sudo ./configure --host=i686-w64-mingw32 && sudo make'

# Examine the output (hidtest is not required)
cd windows/.libs
file -b libhidapi-0.dll  
# Output:
# libhidapi-0.dll: PE32 executable (DLL) (console) Intel 80386, for MS Windows

# Move and rename the DLL into hid4java structure
mv libhidapi-0.dll <hid4java root>/src/main/resources/win32-x86/hidapi.dll

Some of the older versions of the hidapi native libraries were removed in version 0.6.0, so if you have a particular requirement and can demonstrate a good case to include it in the standard build, please raise an issue to get it looked at.

Using the build-hidapi.sh script (recommended)

The build-hidapi.sh script will enable you to cross-compile the various hidapi libraries locally. Dockcross does the heavy lifting to create compilation environments for other platforms.

It's not intended for general use so comes with hard-coded directory paths and currently only works on an macOS native build machine. With a bit of tweaking, variants for Linux and Windows could be created so if you find yourself doing this, please raise an issue and submit your contribution so others may benefit.

It expects a workspace directory layout as follows (although this can be configured within the script):

+ ~/Workspaces
  + /Docker/dockcross - where dockcross/dockcross has been cloned
  + /Cpp/hidapi - where libusb/hidapi has been cloned
  + /Java/Personal/hid4java - where gary-rowe/hid4java has been cloned
+ 

You can provide some command line parameters to streamline the process:

  • update - update dockcross and hidapi then build all Docker containers and shortcuts (no hidapi builds)
  • all - build all variants
  • windows - build all Windows variants
  • linux - build all Linux variants
  • darwin - build all macOS variants (requires running on macOS)
  • darwin-x86-64 - macOS 64-bit
  • darwin-aarch64 - macOS ARM64
  • linux-aarch64 - Linux ARMv8 64-bit only
  • linux-amd64 - Linux AMD 64-bit only
  • linux-arm - Linux ARMv7 hard float 32-bit only
  • linux-armel - Linux ARMv5 soft float 32-bit
  • linux-riscv64 - Linux RISC-V 64-bit
  • linux-x86-64 - Linux x86 64-bit only
  • linux-x86 - Linux x86 32-bit only
  • win32-x86 - Windows 32-bit only
  • win32-x86-64 - Windows 64-bit only
  • win32-aarch64 - Windows 64-bit ARM64

Assuming you've done an initial checkout of dockcross and hidapi you should be able to work entirely from the hid4java project workspace as follows:

# Start your Docker environment (Docker Desktop works best on macOS)

# Perform a one-off update to catch up
build-hidapi.sh update

# Perform a one-off full update of all hidapi libraries
# Failed/problem builds will usually result in the target being removed from hid4java (restore with git reset)
build-hidapi.sh all

# Example of building just the Windows 64-bit ARM64 version of hidapi
build-hidapi.sh win32-aarch64

Typical workflow is to do the initial update, then target platforms one by one verifying the output with the report. As each is completed, commit the change so that subsequent alterations (if any) can be quickly identified.