Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 178 additions & 0 deletions .github/workflows/CrossBuilds.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
name: Cross Build Tests
on:
push:
paths-ignore:
- ".gitignore"
- "docs/**"
- "ChangeLog"
- "CREDITS.TXT"
- "COMPILE_MAKE.TXT"
- "BUILDING.md"
- "CONTRIBUTING.md"
- "LICENSE.TXT"
- "LICENSE_LLVM.TXT"
- "README.md"
- "RELEASE_NOTES"
- "SPONSORS.TXT"
- "TODO"
pull_request:

# Stop previous runs on the same branch on new push
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
CI: true
UBSAN_OPTIONS: "halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1"
ASAN_OPTIONS: "halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1"
LSAN_OPTIONS: "halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1"

jobs:
Linux:
runs-on: ${{ matrix.config.os }}
name: ${{ matrix.config.name }}
strategy:
fail-fast: false
matrix:
config:
- {
name: 'QEMU Linux s390x',
os: ubuntu-24.04,
arch: x64,
build-system: 'cmake',
diet-build: 'OFF',
build_type: 'Debug',
diet_build: false,
packages: 'gcc-s390x-linux-gnu g++-s390x-linux-gnu binutils-s390x-linux-gnu libc6-dev-s390x-cross qemu-user-static',
cross_file: 'cross_configs/linux_s390x_ubuntu24.cmake',
}
# - {
# name: 'QEMU Linux Mips 32',
# os: ubuntu-24.04,
# arch: x64,
# build-system: 'cmake',
# diet-build: 'OFF',
# build_type: 'Debug',
# diet_build: false,
# packages: 'gcc-mips-linux-gnu g++-mips-linux-gnu binutils-mips-linux-gnu libc6-dev-mips-cross qemu-user-static',
# cross_file: 'cross_configs/linux_mips_ubuntu24.cmake',
# }
- {
name: 'QEMU Linux Mips64el',
os: ubuntu-24.04,
arch: x64,
build-system: 'cmake',
diet-build: 'OFF',
build_type: 'Debug',
diet_build: false,
packages: 'gcc-mips64el-linux-gnuabi64 g++-mips64el-linux-gnuabi64 binutils-mips64el-linux-gnuabi64 libc6-dev-mips64el-cross qemu-user-static',
cross_file: 'cross_configs/linux_mips64_ubuntu24.cmake',
}
- {
name: 'QEMU Linux PPC64',
os: ubuntu-24.04,
arch: x64,
build-system: 'cmake',
diet-build: 'OFF',
build_type: 'Debug',
diet_build: false,
packages: 'gcc-powerpc64-linux-gnu g++-powerpc64-linux-gnu binutils-powerpc64-linux-gnu libc6-dev-ppc64-cross qemu-user-static',
cross_file: 'cross_configs/linux_ppc64_ubuntu24.cmake',
}
- {
name: '[BUILD ONLY] Android 35 (arm64_v8a) NDK 29',
os: ubuntu-24.04,
arch: x64,
build-system: 'cmake',
build_option: '-DANDROID_NDK=ndk/ -DANDROID_PLATFORM=android-35 -DANDROID_ABI=arm64-v8a',
diet-build: 'OFF',
build_type: 'Debug',
diet_build: false,
# QEMU alone can't emulate the binaries, because the NDK doesn't
# provide dynamic linker.
skip_tests: true,
packages: 'qemu-user-static',
ndk_version: 'r29',
cross_file: 'ndk/build/cmake/android.toolchain.cmake',
qemu: 'qemu-aarch64-static'
}

steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.config.python-version }}

- name: Install cross build dependencies
if: ${{ matrix.config.packages != '' }}
env:
packages: ${{ matrix.config.packages }}
run: |
sudo apt-get install -y ${packages}

- name: Setup Android NDK
if: contains(matrix.config.name, 'Android')
env:
ndk_version: ${{ matrix.config.ndk_version }}
qemu: ${{ matrix.config.qemu }}
cross_file: ${{ matrix.config.cross_file }}
run: |
wget -q https://dl.google.com/android/repository/android-ndk-${ndk_version}-linux.zip
mkdir ndk
unzip -q -d ndk android-ndk-${ndk_version}-linux.zip
mv ndk/*/* ndk/
cat ndk/source.properties

- name: cmake (cross build)
env:
build_option: ${{ matrix.config.build_option }}
build_type: ${{ matrix.config.build_type }}
cross_file: ${{ matrix.config.cross_file }}
run: |
cmake -DCMAKE_BUILD_TYPE=${build_type} \
-DCAPSTONE_BUILD_STATIC_LIBS=ON \
-S . \
-DCAPSTONE_BUILD_CSTEST=ON \
-DCAPSTONE_BUILD_DIET=${diet_build} \
-DCMAKE_TOOLCHAIN_FILE=${cross_file} \
${build_option} \
-B build .
cmake --build build --config ${build_type}

- name: unit tests
if: ${{ matrix.config.skip_tests != true }}
run: |
ctest --test-dir build --output-on-failure -R unit_*

- name: "Integration tests"
if: ${{ matrix.config.skip_tests != true }}
run: |
ctest --test-dir build --output-on-failure -R integration_c_*

- name: cstest MC
if: ${{ matrix.config.skip_tests != true }}
run: |
ctest --test-dir build --output-on-failure -R MCTests

- name: cstest details
if: ${{ matrix.config.skip_tests != true }}
run: |
ctest --test-dir build --output-on-failure -R DetailTests

- name: cstest issues
if: ${{ matrix.config.skip_tests != true }}
run: |
ctest --test-dir build --output-on-failure -R IssueTests

- name: cstest features
if: ${{ matrix.config.skip_tests != true }}
run: |
ctest --test-dir build --output-on-failure -R FeaturesTests

- name: Legacy integration tests
if: ${{ matrix.config.skip_tests != true }}
run: |
ctest --test-dir build --output-on-failure -R legacy*
37 changes: 36 additions & 1 deletion BUILDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,40 @@ By default, Capstone use system dynamic memory management, and both DIET and X86
modes are disabled. To use your own memory allocations, turn ON both DIET &
X86_REDUCE, run "cmake" with: `-DCAPSTONE_USE_SYS_DYN_MEM=0`, `-DCAPSTONE_BUILD_DIET=1`, `-DCAPSTONE_X86_REDUCE=1`

### Cross compilation

We have some example configurations for cross builds in [cross_configs](cross_configs/).
Build them with the following command (static build is of course optional):

```bash
cmake -DCMAKE_TOOLCHAIN_FILE=cross_configs/<cross_build_config>.cmake -DCAPSTONE_BUILD_STATIC_LIBS=ON -S . -B build
cmake --build build
```

See the cmake cross compilation [documentation](https://cmake.org/cmake/help/book/mastering-cmake/chapter/Cross%20Compiling%20With%20CMake.html)
for more details.

**Android**

The [Android SDK provides](https://developer.android.com/ndk/guides/cmake) a toolchain file for CMake.
It is the most reliable way to build Capstone for Android.

_Example:_

```bash
cmake -B build -DCMAKE_TOOLCHAIN_FILE=$NDK_PATH/build/cmake/android.toolchain.cmake -DANDROID_NDK=$NDK_PATH -DANDROID_ABI=arm64-v8a
cmake --build build
```

#### Test cross build with QEMU

Running the binaries with QEMU (here an example for s390x on Fedora 40)
is usually done with a command like this:

```bash
QEMU_LD_PREFIX=/usr/s390x-redhat-linux/sys-root/fc40/usr/ qemu-s390x-static ./build/cstool -d aarch64 01421bd501423bd5
```

### Developer specific options

- `CAPSTONE_DEBUG`: Change this to ON to enable extra debug assertions. Automatically enabled with `Debug` build.
Expand All @@ -106,8 +140,9 @@ X86_REDUCE, run "cmake" with: `-DCAPSTONE_USE_SYS_DYN_MEM=0`, `-DCAPSTONE_BUILD_
`cstest` is build together with Capstone by adding the flag `-DCAPSTONE_BUILD_CSTEST`.

The build requires `libyaml`. It is a fairly common package and should be provided by your package manager.
If not present it will attempt to build it from source.

_Note:_ Currently `cstest` us only supported on Linux.
_Note:_ Currently `cstest` is only tested on Linux.

If you run another operation system, please install `cstest_py`.
See `bindings/python/BUILDING.md` for instructions.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@ if(CAPSTONE_BUILD_STATIC_MSVC_RUNTIME)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif()

# The directory for external project patches.
set(EXTERNAL_PROJ_PATCH_DIR ${PROJECT_SOURCE_DIR}/ext_patches/)

## sources
set(SOURCES_ENGINE
cs.c
Expand Down
6 changes: 3 additions & 3 deletions CPackConfig.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
set(CPACK_DEBIAN_PACKAGE_MULTIARCH "same")

# Determine architecture for Debian package
if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")
if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64")
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i386" OR ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i686")
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "i386" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "i686")
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "i386")
elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm")
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "arm")
if(CMAKE_SIZE_OF_VOID_P EQUAL 4)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "armhf")
else()
Expand Down
5 changes: 5 additions & 0 deletions cross_configs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Cross Compilation Configs

This directory holds example cross compilation configs for cmake.

Files are named like: `<targetOS>_<targetMachine>_<hostOS>.cmake`
17 changes: 17 additions & 0 deletions cross_configs/linux_mips64_ubuntu24.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# This example file is for builds on Ubunutu 24.04.
# Search for required packages (compiler + libc) with `apt search mips64`
# sudo apt install gcc-mips64el-linux-gnuabi64 g++-mips64el-linux-gnuabi64 binutils-mips64el-linux-gnuabi64 libc6-dev-mips64el-cross qemu-user-static
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR mips64el)

set(CMAKE_C_COMPILER mips64el-linux-gnuabi64-gcc)
set(CMAKE_ASM_COMPILER mips64el-linux-gnuabi64-gcc)
set(CMAKE_CROSS_COMPILING 1)

set(CMAKE_SYSROOT /usr/mips64el-linux-gnuabi64/usr/)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

set(CMAKE_CROSSCOMPILING_EMULATOR qemu-mips64el-static;-L;/usr/mips64el-linux-gnuabi64/)
17 changes: 17 additions & 0 deletions cross_configs/linux_mips_ubuntu24.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# This example file is for builds on Ubunutu 24.04.
# Search for required packages (compiler + libc) with `apt search mips`
# sudo apt install gcc-mips-linux-gnu g++-mips-linux-gnu binutils-mips-linux-gnu libc6-dev-mips-cross qemu-user-static
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR mips)

set(CMAKE_C_COMPILER mips-linux-gnu-gcc)
set(CMAKE_ASM_COMPILER mips-linux-gnu-gcc)
set(CMAKE_CROSS_COMPILING 1)

set(CMAKE_SYSROOT /usr/mips-linux-gnu/usr/)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

set(CMAKE_CROSSCOMPILING_EMULATOR qemu-mips-static;-L;/usr/mips-linux-gnu/)
17 changes: 17 additions & 0 deletions cross_configs/linux_ppc64_ubuntu24.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# This example file is for builds on Ubunutu 24.04.
# Search for required packages (compiler + libc) with `apt search PPC64`
# sudo apt install gcc-powerpc64-linux-gnu g++-powerpc64-linux-gnu binutils-powerpc64-linux-gnu libc6-dev-ppc64-cross qemu-user-static
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR ppc64)

set(CMAKE_C_COMPILER powerpc64-linux-gnu-gcc)
set(CMAKE_ASM_COMPILER powerpc64-linux-gnu-gcc)
set(CMAKE_CROSS_COMPILING 1)

set(CMAKE_SYSROOT /usr/powerpc64-linux-gnu/usr)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

set(CMAKE_CROSSCOMPILING_EMULATOR qemu-ppc64-static;-L;/usr/powerpc64-linux-gnu)
20 changes: 20 additions & 0 deletions cross_configs/linux_s390x_fedora42.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# This example file is for build on Fedora 42.
# Search for required packages with `dnf search s390x`

# Bug of cmake not passing sysroot early enough
# https://stackoverflow.com/questions/36195791/cmake-missing-sysroot-when-cross-compiling
set(CMAKE_C_COMPILE_OPTIONS_SYSROOT "--sysroot=")
set(CMAKE_CXX_COMPILE_OPTIONS_SYSROOT "--sysroot=")


set(CMAKE_C_COMPILER /usr/bin/s390x-linux-gnu-gcc)
set(CMAKE_ASM_COMPILER /usr/bin/s390x-linux-gnu-gcc)
set(CMAKE_CROSS_COMPILING 1)

set(CMAKE_SYSROOT /usr/s390x-redhat-linux/sys-root/fc42/)
set(CMAKE_FIND_ROOT_PATH /usr/s390x-redhat-linux/sys-root/fc42/)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

set(CMAKE_CROSSCOMPILING_EMULATOR "qemu-s390x-static;-L;${CMAKE_SYSROOT}/usr/")
17 changes: 17 additions & 0 deletions cross_configs/linux_s390x_ubuntu24.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# This example file is for builds on Ubunutu 24.04.
# Search for required packages (compiler + libc) with `apt search s390x`
set(CMAKE_C_COMPILER /usr/bin/s390x-linux-gnu-gcc)
set(CMAKE_ASM_COMPILER /usr/bin/s390x-linux-gnu-gcc)
set(CMAKE_CROSS_COMPILING 1)

set(CMAKE_SYSTEM_NAME Linux)

set(CMAKE_SYSROOT /usr/s390x-linux-gnu/usr/)

set(CMAKE_SYSTEM_PROCESSOR "s390x")

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

set(CMAKE_CROSSCOMPILING_EMULATOR "qemu-s390x-static;-L;/usr/s390x-linux-gnu/")
24 changes: 24 additions & 0 deletions cross_configs/linux_x86.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# SPDX-FileCopyrightText: 2025 Rot127 <[email protected]>
# SPDX-License-Identifier: LGPL-3.0-only

# Requires the 32bit libc like glibc-devel.i686 libgcc.i686 (Fedora) or similar
# for other distributions.
# This example was tested on Fedora 43

# the name of the target operating system
set(CMAKE_SYSTEM_NAME Linux)

# which compilers to use for C and C++
set(CMAKE_C_COMPILER gcc)
set(CMAKE_C_FLAGS -m32)
set(CMAKE_CXX_COMPILER g++)
set(CMAKE_CXX_FLAGS -m32)

# where is the target environment located
set(CMAKE_FIND_ROOT_PATH /)

set(CMAKE_SYSTEM_PROCESSOR "i686")

# search headers and libraries in the target environment
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
2 changes: 2 additions & 0 deletions docs/cs_v6_release_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,12 +219,14 @@ Nonetheless, we hope this additional information is useful to you.
- Testing was re-written from scratch. Now allowing fine-grained testing of all details and is more convenient to use by contributors.
- Architecture modules from a static library, can be initialized on demand to decrease footprint (see: `cmake` option `CAPSTONE_USE_ARCH_REGISTRATION`).
- New `cmake` option to choose between fat and thin binary for Apple.
- Cross compilation support improved.

**Code quality**

- ASAN: All tests are now run with the address sanitizer enabled. This includes checking for leaks.
- Coverity code scanning workflow added and all reported bugs fixed.
- `clang-tidy` workflow added. All reported defects were fixed.
- CI runs tests for s390x, Mips, PPC, and Android targets.

### Instruction Alias

Expand Down
1 change: 1 addition & 0 deletions ext_patches/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Patches for external build dependencies.
Loading
Loading