Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creating a functional Debian Package for Capstone v5 #2569

Merged
merged 2 commits into from
Dec 17, 2024
Merged
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
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
/arch/**/*.inc linguist-language=C

# Ensure shell scripts have LF line endings
*.sh text eol=lf
52 changes: 33 additions & 19 deletions .github/workflows/build_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,33 @@ 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 ./packages/deb/setup.sh
chmod +x ./packages/deb/check_capstone.sh

- name: Build Debian Package
working-directory: ./packages/deb
run: ./setup.sh ${{ github.event.release.tag_name }}

- name: Run sanity checks on the Debian package
working-directory: ./packages/deb
run: |
./check_capstone.sh ./libcapstone-dev_${{ github.event.release.tag_name }}_amd64.deb

- 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: |
./packages/deb/*.deb

- name: archive
id: archive
run: |
Expand All @@ -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

- name: upload shasum
uses: actions/upload-release-asset@v1
echo "tarball=$TARBALL" >> $GITHUB_OUTPUT
echo "shasum=$SHASUM" >> $GITHUB_OUTPUT

- 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 }}
67 changes: 50 additions & 17 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,16 @@ cmake_policy(SET CMP0042 NEW)
# Enable support for MSVC_RUNTIME_LIBRARY
cmake_policy(SET CMP0091 NEW)

project(capstone
VERSION 5.0.3
)
# Check if VERSION is provided externally, otherwise default to 5.0.3
if(NOT DEFINED PROJECT_VERSION)
set(PROJECT_VERSION "5.0.3")
endif()

# Extract the major, minor, and patch versions
string(REGEX MATCH "^[0-9]+\\.[0-9]+\\.[0-9]+" PROJECT_VERSION_BASE ${PROJECT_VERSION})

# Set the project version without the pre-release identifier
project(capstone VERSION ${PROJECT_VERSION_BASE})

if (MSVC)
add_compile_options(/W1 /w14189)
Expand All @@ -35,7 +42,8 @@ endif()
# to configure the options specify them in 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_TESTS "Build tests" ${PROJECT_IS_TOP_LEVEL})
Expand All @@ -46,6 +54,10 @@ option(CAPSTONE_ARCHITECTURE_DEFAULT "Whether architectures are enabled by defau
option(CAPSTONE_DEBUG "Whether to enable extra debug assertions" OFF)
option(CAPSTONE_INSTALL "Generate install target" ${PROJECT_IS_TOP_LEVEL})

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()

set(SUPPORTED_ARCHITECTURES ARM ARM64 M68K MIPS PPC SPARC SYSZ XCORE X86 TMS320C64X M680X EVM MOS65XX WASM BPF RISCV SH TRICORE)
set(SUPPORTED_ARCHITECTURE_LABELS ARM ARM64 M68K MIPS PowerPC Sparc SystemZ XCore x86 TMS320C64x M680x EVM MOS65XX WASM BPF RISCV SH TriCore)

Expand Down Expand Up @@ -109,7 +121,7 @@ if(CAPSTONE_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()

Expand Down Expand Up @@ -631,19 +643,33 @@ 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()

if(CAPSTONE_BUILD_TESTS)
Expand Down Expand Up @@ -712,7 +738,6 @@ source_group("Include\\TriCore" FILES ${HEADERS_TRICORE})
## installation
if(CAPSTONE_INSTALL)
include(GNUInstallDirs)

install(FILES ${HEADERS_COMMON} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/capstone)

# Support absolute installation paths (discussion: https://github.com/NixOS/nixpkgs/issues/144170)
Expand Down Expand Up @@ -753,12 +778,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
Expand Down
16 changes: 3 additions & 13 deletions bindings/python/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,12 @@
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():
shutil.rmtree(LIBS_DIR, ignore_errors=True)
Expand Down Expand Up @@ -124,12 +121,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)
Expand All @@ -145,19 +139,15 @@ def build_libraries():
os.chdir("build")
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_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_TESTS=OFF -DCAPSTONE_BUILD_CSTOOL=OFF -G "NMake Makefiles" ..')
else:
os.system('cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCAPSTONE_BUILD_TESTS=OFF -DCAPSTONE_BUILD_CSTOOL=OFF -G "Unix Makefiles" ..')
os.system("cmake --build .")
else: # Unix incl. cygwin
os.system("CAPSTONE_BUILD_CORE_ONLY=yes bash ./make.sh")

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)


Expand Down
1 change: 0 additions & 1 deletion capstone.pc.in
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,3 @@ URL: https://www.capstone-engine.org/
archive=${libdir}/libcapstone.a
Libs: -L${libdir} -lcapstone
Cflags: -I${includedir}/capstone
archs=@CAPSTONE_ARCHITECTURES@
30 changes: 0 additions & 30 deletions nmake.bat

This file was deleted.

2 changes: 2 additions & 0 deletions packages/deb/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.deb
*.txt
69 changes: 69 additions & 0 deletions packages/deb/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# SPDX-License-Identifier: MIT
# Copyright (C) 2024 Andrew Quijano
# Contact: [email protected]
ARG VERSION=""
AndrewQuijano marked this conversation as resolved.
Show resolved Hide resolved

# Run in the root of the repo
# docker build -f ./packages/deb/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 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"
ARG VERSION
RUN cmake -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=1 -DPROJECT_VERSION=${VERSION} -DCMAKE_INSTALL_PREFIX=/usr
RUN cmake --build build

# List files before cmake install
# RUN find / -type f > /before-install.txt

# Make directories as needed
RUN mkdir -p /package-root/usr/include/capstone/
RUN mkdir -p /package-root/usr/lib/pkgconfig/
RUN mkdir -p /package-root/usr/bin/
RUN mkdir -p /package-root/usr/share/doc/libcapstone-dev

# Run cmake install
RUN cmake --install build --prefix /package-root/usr/

# List files after cmake install
# RUN find / -type f > /after-install.txt

# Create DEBIAN directory and control file
COPY ./packages/deb/control /package-root/DEBIAN/control

# Copy documentation over
COPY ./ChangeLog /package-root/usr/share/doc/libcapstone-dev
COPY ./CREDITS.TXT /package-root/usr/share/doc/libcapstone-dev
COPY ./HACK.TXT /package-root/usr/share/doc/libcapstone-dev
COPY ./LICENSE.TXT /package-root/usr/share/doc/libcapstone-dev
COPY ./README.md /package-root/usr/share/doc/libcapstone-dev
COPY ./SPONSORS.TXT /package-root/usr/share/doc/libcapstone-dev

# Generate MD5 checksums for all files and save to DEBIAN/md5sums
RUN cd /package-root && \
find . -type f ! -path './DEBIAN/*' -exec md5sum {} + | sed 's| \./| |' > /package-root/DEBIAN/md5sums

# Update control file with the correct information
ARG VERSION
RUN INSTALLED_SIZE=$(du -sk /package-root | cut -f1) && \
sed -i "s/^Installed-Size:.*/Installed-Size: ${INSTALLED_SIZE}/" /package-root/DEBIAN/control
RUN sed -i "s/^Version:.*/Version: ${VERSION}/" /package-root/DEBIAN/control

# Add triggers script to run ldconfig after installation
COPY ./packages/deb/triggers /package-root/DEBIAN/triggers

# Build the package
RUN fakeroot dpkg-deb --build /package-root /libcapstone-dev_${VERSION}_amd64.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"
Loading
Loading