Change CI to create Debian Package to Release (#2521)
Some checks failed
Run Test / ${{ matrix.config.name }} (map[arch:x64 build-system:cmake diet-build:OFF enable-asan:OFF name:ubuntu-22.04 x64 cmake os:ubuntu-22.04]) (push) Has been cancelled
Run Test / ${{ matrix.config.name }} (map[arch:x64 build-system:cmake diet-build:OFF enable-asan:ON name:ubuntu-24.04 x64 ASAN os:ubuntu-24.04]) (push) Has been cancelled
Run Test / ${{ matrix.config.name }} (map[arch:x64 build-system:make diet-build:OFF enable-asan:OFF name:ubuntu-22.04 x64 make os:ubuntu-22.04]) (push) Has been cancelled
Run Test / ${{ matrix.config.name }} (map[arch:x64 name:windows x64 MSVC 64bit os:windows-latest platform:windows python-arch:x64 python-version:3.9]) (push) Has been cancelled
RELEASE BUILD - PyPI 📦 Distribution / Build wheels on ${{ matrix.os }} (macos-latest) (push) Has been cancelled
RELEASE BUILD - PyPI 📦 Distribution / Build wheels on ${{ matrix.os }} (ubuntu-latest) (push) Has been cancelled
RELEASE BUILD - PyPI 📦 Distribution / Build wheels on ${{ matrix.os }} (windows-latest) (push) Has been cancelled
RELEASE BUILD - PyPI 📦 Distribution / Make SDist (push) Has been cancelled
Python Package CI / build (macOS-14, 3.12) (push) Has been cancelled
Python Package CI / build (macOS-14, 3.8) (push) Has been cancelled
Python Package CI / build (ubuntu-24.04, 3.12) (push) Has been cancelled
Python Package CI / build (ubuntu-24.04, 3.8) (push) Has been cancelled
Python Package CI / build (windows-2022, 3.12) (push) Has been cancelled
Python Package CI / build (windows-2022, 3.8) (push) Has been cancelled
RELEASE BUILD - PyPI 📦 Distribution / publish (push) Has been cancelled

* Updating CI to create Debian package and version is assigned by tag
version. Also updating release CI to not use end-of-life workflows

* Clear up usage of static libraries.

- Python bindings only use the dynamic lib. But built and copied the static ones sometimes nonetheless.
- Add toggles to build only static, static/dyn or only dynamic.

---------

Co-authored-by: Rot127 <unisono@quyllur.org>
This commit is contained in:
Andrew 2024-11-04 07:32:53 -05:00 committed by GitHub
parent f6f967961b
commit d7be5f9f9f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 298 additions and 78 deletions

21
.dockerignore Normal file
View File

@ -0,0 +1,21 @@
# Ignore source control directories
.git
.svn
# Ignore build directories
build
dist
# Ignore dependency directories
node_modules
vendor
# Ignore temporary files
*.log
*.tmp
# Ignore environment files
.env
# Ignore tests
tests

3
.gitattributes vendored
View File

@ -1 +1,4 @@
/arch/**/*.inc linguist-language=C
# Ensure shell scripts have LF line endings
*.sh text eol=lf

View File

@ -11,9 +11,32 @@ jobs:
name: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
submodules: true
- name: Make setup.sh and check_capstone.sh are executable
run: |
chmod +x debian/setup.sh
chmod +x debian/check_capstone.sh
- name: Build Debian Package
working-directory: ./debian
run: ./setup.sh ${{ github.event.release.tag_name }}
- name: Run sanity checks on the Debian package
working-directory: ./debian
run: |
./check_capstone.sh ./libcapstone-dev.deb ${{ github.event.release.tag_name }}
- name: Upload debian package to release
uses: softprops/action-gh-release@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.event.release.tag_name }}
files: |
./debian/*.deb
- name: archive
id: archive
@ -27,24 +50,15 @@ jobs:
TARBALL=$PKGNAME.tar.xz
tar cJf $TARBALL $PKGNAME
sha256sum $TARBALL > $SHASUM
echo "::set-output name=tarball::$TARBALL"
echo "::set-output name=shasum::$SHASUM"
- name: upload tarball
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: ./${{ steps.archive.outputs.tarball }}
asset_name: ${{ steps.archive.outputs.tarball }}
asset_content_type: application/gzip
echo "tarball=$TARBALL" >> $GITHUB_OUTPUT
echo "shasum=$SHASUM" >> $GITHUB_OUTPUT
- name: upload shasum
uses: actions/upload-release-asset@v1
- name: Upload tarball and shasum to release
uses: softprops/action-gh-release@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: ./${{ steps.archive.outputs.shasum }}
asset_name: ${{ steps.archive.outputs.shasum }}
asset_content_type: text/plain
tag_name: ${{ github.event.release.tag_name }}
files: |
${{ steps.archive.outputs.tarball }}
${{ steps.archive.outputs.shasum }}

View File

@ -55,7 +55,8 @@ endif()
# to configure the options specify them in the command line or change them in the cmake UI.
# Don't edit the makefile!
option(BUILD_SHARED_LIBS "Build shared library" OFF)
option(CAPSTONE_BUILD_STATIC_RUNTIME "Embed static runtime" ${BUILD_SHARED_LIBS})
option(BUILD_STATIC_LIBS "Build static library" ON)
option(BUILD_STATIC_RUNTIME "Embed static MSVC runtime (Windows only). Always set if BUILD_SHARED_LIBS=ON" ${BUILD_SHARED_LIBS})
option(CAPSTONE_BUILD_MACOS_THIN "Disable universal2 builds on macOS" OFF)
option(CAPSTONE_BUILD_DIET "Build diet library" OFF)
option(CAPSTONE_BUILD_LEGACY_TESTS "Build legacy tests" ${PROJECT_IS_TOP_LEVEL})
@ -69,6 +70,10 @@ option(CAPSTONE_INSTALL "Generate install target" ${PROJECT_IS_TOP_LEVEL})
option(ENABLE_ASAN "Enable address sanitizer" OFF)
option(ENABLE_COVERAGE "Enable test coverage" OFF)
if (NOT BUILD_SHARED_LIBS AND NOT BUILD_STATIC_LIBS)
FATAL_ERROR("BUILD_SHARED_LIBS and BUILD_STATIC_LIBS are both unset. Nothing to build.")
endif()
if (ENABLE_ASAN)
message("Enabling ASAN")
add_definitions(-DASAN_ENABLED)
@ -154,7 +159,7 @@ if(CAPSTONE_DEBUG OR CMAKE_BUILD_TYPE STREQUAL "Debug")
endif()
# Force static runtime libraries
if(CAPSTONE_BUILD_STATIC_RUNTIME)
if(BUILD_STATIC_RUNTIME)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif()
@ -761,19 +766,34 @@ set(ALL_HEADERS
set_property(GLOBAL PROPERTY VERSION ${PROJECT_VERSION})
## targets
add_library(capstone ${ALL_SOURCES} ${ALL_HEADERS})
add_library(capstone::capstone ALIAS capstone)
add_library(capstone OBJECT ${ALL_SOURCES} ${ALL_HEADERS})
set_property(TARGET capstone PROPERTY C_STANDARD 99)
target_include_directories(capstone PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
)
set_property(TARGET capstone PROPERTY C_STANDARD 99)
if(BUILD_STATIC_LIBS)
add_library(capstone_static STATIC $<TARGET_OBJECTS:capstone>)
# Use normal capstone name. Otherwise we get libcapstone_static.a
set_target_properties(capstone_static PROPERTIES OUTPUT_NAME "capstone")
target_include_directories(capstone_static PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
)
endif()
if(BUILD_SHARED_LIBS)
target_compile_definitions(capstone PUBLIC CAPSTONE_SHARED)
set_target_properties(capstone PROPERTIES
set_property(TARGET capstone PROPERTY POSITION_INDEPENDENT_CODE 1)
add_library(capstone_shared SHARED $<TARGET_OBJECTS:capstone>)
# Use normal capstone name. Otherwise we get libcapstone_shared.so
set_target_properties(capstone_shared PROPERTIES OUTPUT_NAME "capstone")
set_target_properties(capstone_shared PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
)
target_include_directories(capstone_shared PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
)
target_compile_definitions(capstone PUBLIC CAPSTONE_SHARED)
endif()
# Fuzzer if this is moved to it's own CMakeLists.txt (as it should be)
@ -878,12 +898,20 @@ if(CAPSTONE_INSTALL)
DESTINATION ${CAPSTONE_CMAKE_CONFIG_INSTALL_DIR}
)
install(TARGETS capstone
EXPORT capstone-targets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
if(BUILD_SHARED_LIBS)
set(LIB_INSTALL_TARGETS capstone_shared)
endif()
if (BUILD_STATIC_LIBS)
set(LIB_INSTALL_TARGETS ${LIB_INSTALL_TARGETS} capstone_static)
endif()
install(TARGETS ${LIB_INSTALL_TARGETS}
EXPORT capstone-targets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
install(EXPORT capstone-targets

View File

@ -62,15 +62,12 @@ else:
if SYSTEM == 'darwin':
VERSIONED_LIBRARY_FILE = "libcapstone.{PKG_MAJOR}.dylib".format(**VERSION_DATA)
LIBRARY_FILE = "libcapstone.dylib"
STATIC_LIBRARY_FILE = 'libcapstone.a'
elif SYSTEM in ('win32', 'cygwin'):
VERSIONED_LIBRARY_FILE = "capstone.dll"
LIBRARY_FILE = "capstone.dll"
STATIC_LIBRARY_FILE = None
else:
VERSIONED_LIBRARY_FILE = "libcapstone.so.{PKG_MAJOR}".format(**VERSION_DATA)
LIBRARY_FILE = "libcapstone.so"
STATIC_LIBRARY_FILE = 'libcapstone.a'
def clean_bins():
@ -123,12 +120,9 @@ def build_libraries():
shutil.copytree(os.path.join(BUILD_DIR, 'include', 'capstone'), os.path.join(HEADERS_DIR, 'capstone'))
# if prebuilt libraries are available, use those and cancel build
if os.path.exists(os.path.join(ROOT_DIR, 'prebuilt', LIBRARY_FILE)) and \
(not STATIC_LIBRARY_FILE or os.path.exists(os.path.join(ROOT_DIR, 'prebuilt', STATIC_LIBRARY_FILE))):
if os.path.exists(os.path.join(ROOT_DIR, 'prebuilt', LIBRARY_FILE)):
logger.info('Using prebuilt libraries')
shutil.copy(os.path.join(ROOT_DIR, 'prebuilt', LIBRARY_FILE), LIBS_DIR)
if STATIC_LIBRARY_FILE is not None:
shutil.copy(os.path.join(ROOT_DIR, 'prebuilt', STATIC_LIBRARY_FILE), LIBS_DIR)
return
os.chdir(BUILD_DIR)
@ -141,8 +135,8 @@ def build_libraries():
os.chdir("build_py")
print("Build Directory: {}\n".format(os.getcwd()))
# Only build capstone.dll / libcapstone.dylib
if SYSTEM == "win32":
os.system('cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCAPSTONE_BUILD_LEGACY_TESTS=OFF -DCAPSTONE_BUILD_CSTOOL=OFF -G "NMake Makefiles" ..')
if SYSTEM in ('win32', 'cygwin'):
os.system('cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DBUILD_STATIC_LIBS=OFF -DCAPSTONE_BUILD_LEGACY_TESTS=OFF -DCAPSTONE_BUILD_CSTOOL=OFF -G "NMake Makefiles" ..')
elif 'AFL_NOOPT' in os.environ:
# build for test_corpus
os.system('cmake -DBUILD_SHARED_LIBS=ON -DCAPSTONE_BUILD_LEGACY_TESTS=OFF -DCAPSTONE_BUILD_CSTOOL=OFF ..')
@ -151,10 +145,6 @@ def build_libraries():
os.system("cmake --build .")
shutil.copy(VERSIONED_LIBRARY_FILE, os.path.join(LIBS_DIR, LIBRARY_FILE))
# only copy static library if it exists (it's a build option)
if STATIC_LIBRARY_FILE and os.path.exists(STATIC_LIBRARY_FILE):
shutil.copy(STATIC_LIBRARY_FILE, LIBS_DIR)
os.chdir(cwd)

2
debian/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.deb
*.txt

61
debian/Dockerfile vendored Normal file
View File

@ -0,0 +1,61 @@
ARG VERSION=""
# Assume this is run from capstone/debian directory
# Run in the root of the repo
# docker build -f ./debian/Dockerfile -t packager .
FROM debian:bookworm-slim
# Install necessary tools for packaging
RUN apt-get -qq update && \
DEBIAN_FRONTEND=noninteractive apt-get -qq install -y \
fakeroot dpkg-dev dos2unix cmake
# Copy your project files into the container
RUN mkdir /capstone
COPY . /capstone
WORKDIR /capstone/
# Using cmake, see BUILDING.md file
# For debug build change "Release" to "Debug"
RUN cmake -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=1
RUN cmake --build build
# List files before cmake install
# RUN find / -type f > /before-install.txt
# Run cmake install, by default everything goes into /usr/local
RUN cmake --install build
# List files after cmake install
# RUN find / -type f > /after-install.txt
# Make directories as needed
RUN mkdir -p /package-root/usr/local/include/capstone/
RUN mkdir -p /package-root/usr/local/lib/pkgconfig/
RUN mkdir -p /package-root/usr/local/bin/
# Copy /usr/local/include/capstone/ to /package-root/usr/local/include/capstone/ and all other cases
RUN cp -r /usr/local/include/capstone/* /package-root/usr/local/include/capstone/
RUN cp -r /usr/local/lib/libcapstone* /package-root/usr/local/lib/
RUN cp -r /usr/local/lib/pkgconfig/capstone* /package-root/usr/local/lib/pkgconfig/
RUN cp -r /usr/local/bin/cstool /package-root/usr/local/bin/
# Create DEBIAN directory and control file
COPY ./debian/control /package-root/DEBIAN/control
# Update capstone.pc file with the correct version and remove archs field
# Update control file with the correct version
ARG VERSION
RUN sed -i "s/^Version:.*/Version: ${VERSION}/" /package-root/DEBIAN/control
RUN sed -i "s/^Version:.*/Version: ${VERSION}/" /package-root/usr/local/lib/pkgconfig/capstone.pc
RUN sed -i "/^archs=/d" /package-root/usr/local/lib/pkgconfig/capstone.pc
# Add postinst script to run ldconfig after installation
COPY ./debian/postinst /package-root/DEBIAN/postinst
RUN chmod 755 /package-root/DEBIAN/postinst
# Build the package
RUN fakeroot dpkg-deb --build /package-root /libcapstone-dev.deb
# The user can now extract the .deb file from the container with something like
# docker run --rm -v $(pwd):/out packager bash -c "cp /libcapstone-dev.deb /out"

68
debian/check_capstone.sh vendored Normal file
View File

@ -0,0 +1,68 @@
#!/bin/bash
# Usage: ./check_capstone_pc.sh <path_to_deb_file> <expected_version>
DEB_FILE=$1
EXPECTED_VERSION=$2
# Check if the deb file exists
if [[ ! -f "$DEB_FILE" ]]; then
echo "Debian package file not found!"
exit 1
fi
# Create a temporary directory to extract the deb file
TEMP_DIR=$(mktemp -d)
# Extract the deb file
dpkg-deb -x "$DEB_FILE" "$TEMP_DIR"
# Path to the capstone.pc file
CAPSTONE_PC="$TEMP_DIR/usr/local/lib/pkgconfig/capstone.pc"
# Check if the capstone.pc file exists
if [[ ! -f "$CAPSTONE_PC" ]]; then
echo "capstone.pc file not found in the package!"
rm -rf "$TEMP_DIR"
exit 1
fi
# Remove leading 'v' if present, e. g. v1.5.1 -> 1.5.1
if [[ "$EXPECTED_VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
EXPECTED_VERSION=${EXPECTED_VERSION:1}
fi
# Check if the version follows the format X.Y.Z, e. g. 1.5.1 or 1.9.1
if [[ ! "$EXPECTED_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "ERROR: Version must be in the format X.Y.Z"
exit 1
fi
# Check the version in the capstone.pc file
ACTUAL_VERSION=$(grep "^Version:" "$CAPSTONE_PC" | awk '{print $2}')
if [[ "$ACTUAL_VERSION" != "$EXPECTED_VERSION" ]]; then
echo "Version mismatch! Expected: $EXPECTED_VERSION, Found: $ACTUAL_VERSION"
rm -rf "$TEMP_DIR"
exit 1
fi
# Check if libcapstone.a is included in the package
LIBCAPSTONE_A="$TEMP_DIR/usr/local/lib/libcapstone.a"
if [[ ! -f "$LIBCAPSTONE_A" ]]; then
echo "libcapstone.a not found in the package!"
rm -rf "$TEMP_DIR"
exit 1
fi
# Check if libcapstone.so is included in the package
LIBCAPSTONE_SO="$TEMP_DIR/usr/local/lib/libcapstone.so"
if [[ ! -f "$LIBCAPSTONE_SO" ]]; then
echo "libcapstone.so not found in the package!"
rm -rf "$TEMP_DIR"
exit 1
fi
echo "libcapstone-dev.deb file is correct."
rm -rf "$TEMP_DIR"
exit 0

8
debian/control vendored Normal file
View File

@ -0,0 +1,8 @@
Package: capstone
Version: <version-placeholder>
Architecture: all
Maintainer: Rot127 <unisono@quyllur.org>
Description: Capstone is a lightweight multi-platform, multi-architecture disassembly framework.
Capstone supports the following frameworks;
Alpha, BPF, Ethereum VM, HPPA, LoongArch, M68K, M680X, Mips, MOS65XX, PPC, RISC-V(rv32G/rv64G),
SH, Sparc, SystemZ, TMS320C64X, TriCore, Webassembly, XCore and X86.

6
debian/postinst vendored Normal file
View File

@ -0,0 +1,6 @@
#!/bin/bash
# postinst script for capstone package
set -e
# Update the shared library cache
ldconfig

53
debian/setup.sh vendored Normal file
View File

@ -0,0 +1,53 @@
# !/bin/bash
set -eu
# Function to get the current Ubuntu version
get_os_version() {
lsb_release -i -s 2>/dev/null
}
# Check if the script is running in the ./debian folder
if [[ $(basename "$PWD") != "debian" ]]; then
echo "ERROR: Script must be run from the ./debian directory"
exit 1
fi
OS_VERSION=$(get_os_version)
if [[ "$OS_VERSION" != "Ubuntu" && "$OS_VERSION" != "Debian" ]]; then
echo "ERROR: OS is not Ubuntu or Debian and unsupported"
exit 1
fi
# Get the version number as an input
# Check if version argument is provided
if [[ $# -ne 1 ]]; then
echo "ERROR: Version argument is required"
exit 1
fi
# Get the version number as an input
version=$1
# Remove leading 'v' if present, e. g. v1.5.1 -> 1.5.1
if [[ "$version" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
version=${version:1}
fi
# Check if the version follows the format X.Y.Z, e. g. 1.5.1 or 1.9.1
if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "ERROR: Version must be in the format X.Y.Z"
exit 1
fi
# Now build the packager container from that
pushd ../
docker build -f ./debian/Dockerfile -t packager --build-arg VERSION="${version}" .
popd
# Copy deb file out of container to host
docker run --rm -v $(pwd):/out packager bash -c "cp /libcapstone-dev.deb /out"
# Check which files existed before and after 'make install' was executed.
# docker run --rm -v $(pwd):/out packager bash -c "cp /before-install.txt /out"
# docker run --rm -v $(pwd):/out packager bash -c "cp /after-install.txt /out"
# diff before-install.txt after-install.txt

View File

@ -1,34 +0,0 @@
:: Capstone disassembler engine (www.capstone-engine.org)
:: Build Capstone libs (capstone.dll & capstone.lib) on Windows with CMake & Nmake
:: By Nguyen Anh Quynh, Jorn Vernee, 2017, 2019
@echo off
set flags="-DCMAKE_BUILD_TYPE=Release -DCAPSTONE_BUILD_STATIC_RUNTIME=ON"
if "%1"=="ARM" set %arch%=ARM
if "%1"=="ARM64" set %arch%=ARM64
if "%1"=="M68K" set %arch%=M68K
if "%1"=="MIPS" set %arch%=MIPS
if "%1"=="PowerPC" set %arch%=PPC
if "%1"=="Sparc" set %arch%=SPARC
if "%1"=="SystemZ" set %arch%=SYSZ
if "%1"=="XCore" set %arch%=XCORE
if "%1"=="x86" set %arch%=X86
if "%1"=="TMS320C64x" set %arch%=TMS320C64X
if "%1"=="M680x" set %arch%=M680X
if "%1"=="EVM" set %arch%=EVM
if "%1"=="MOS65XX" set %arch%=MOS65XX
if "%1"=="WASM" set %arch%=WASM
if "%1"=="BPF" set %arch%=BPF
if "%1"=="RISCV" set %arch%=RISCV
if "%1"=="ALPHA" set %arch%=ALPHA
if "%1"=="HPPA" set %arch%=HPPA
if "%1"=="LOONGARCH" set %arch%=LOONGARCH
if "%1"=="XTENSA" set %arch%=XTENSA
if not "%arch%"=="" set flags=%flags% and " -DCAPSTONE_ARCHITECTURE_DEFAULT=OFF -DCAPSTONE_%arch%_SUPPORT=ON"
cmake %flags% -G "NMake Makefiles" ..
nmake