diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 57a4710..b650418 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,8 +2,91 @@ name: CI on: [push] jobs: - ubuntu-18_04-gcc: - runs-on: ubuntu-18.04 + + ubuntu-24_04-python3-ggwave-deb: + runs-on: ubuntu-24.04 + + steps: + - name: Clone + uses: actions/checkout@v1 + with: + submodules: recursive + + - name: Dependencies + run: | + sudo apt update + sudo apt install cython3 build-essential debhelper-compat + sudo apt install dh-python python3-all-dev python3-build + sudo apt install python3-cogapp python3-venv + + - name: Build Debian package for Python bindings + run: | + cd bindings/python + make deb + + ubuntu-24_04-libggwave-dev-deb: + runs-on: ubuntu-24.04 + strategy: + matrix: + build: [Release] + + steps: + - name: Clone + uses: actions/checkout@v1 + with: + submodules: recursive + + - name: Dependencies + run: | + sudo apt update + sudo apt install build-essential + + - name: Build Debian package for libggwave + run: | + cmake . -DGGWAVE_BUILD_EXAMPLES=OFF -DCMAKE_BUILD_TYPE=${{ matrix.build }} + make + cpack + + - name: Inspect generated Debian package + run: | + dpkg --contents dist/libggwave-dev_*.deb + dpkg -I dist/libggwave-dev_*.deb + sha256sum dist/libggwave-dev_*.deb + + ubuntu-24_04-target-deb: + runs-on: ubuntu-24.04 + strategy: + matrix: + build: [Release] + + steps: + - name: Clone + uses: actions/checkout@v1 + with: + submodules: recursive + + - name: Dependencies + run: | + sudo apt update + sudo apt install cython3 build-essential debhelper-compat + sudo apt install dh-python python3-all-dev python3-build + sudo apt install python3-cogapp python3-venv + + - name: Build Debian packages + run: | + cmake . -DGGWAVE_BUILD_EXAMPLES=OFF -DCMAKE_BUILD_TYPE=${{ matrix.build }} + make deb + + - name: Inspect generated Debian packages + run: | + dpkg --contents dist/libggwave*.deb + dpkg -I dist/libggwave*.deb + dpkg --contents dist/python3*.deb + dpkg -I dist/python3*.deb + sha256sum dist/*.deb + + ubuntu-24_04-gcc: + runs-on: ubuntu-24.04 strategy: matrix: @@ -17,10 +100,10 @@ jobs: - name: Dependencies run: | - sudo apt-get update - sudo apt-get install build-essential xorg-dev libglu1-mesa-dev - sudo apt-get install cmake; - sudo apt-get install libsdl2-dev; + sudo apt update + sudo apt install build-essential xorg-dev libglu1-mesa-dev + sudo apt install cmake + sudo apt install libsdl2-dev - name: Configure run: cmake . -DCMAKE_BUILD_TYPE=${{ matrix.build }} @@ -31,12 +114,14 @@ jobs: ctest --output-on-failure ./bin/test-ggwave-cpp --full - ubuntu-18_04-python: - runs-on: ubuntu-18.04 + ubuntu-24_04-python: + runs-on: ubuntu-24.04 strategy: + fail-fast: false matrix: - python-version: [3.5, 3.6, 3.7, 3.8] + build: [Release] + python-version: [3.8.18, 3.9.20, 3.11.11, 3.12.9] steps: - name: Clone @@ -51,20 +136,23 @@ jobs: - name: Dependencies run: | - sudo apt-get update - sudo apt-get install build-essential - sudo apt-get install cmake; + sudo apt update + sudo apt install build-essential + sudo apt install cmake + python3 -m venv venv + source venv/bin/activate && pip install setuptools cython cogapp - name: Configure run: cmake . -DGGWAVE_SUPPORT_PYTHON=ON -DGGWAVE_BUILD_EXAMPLES=OFF -DCMAKE_BUILD_TYPE=${{ matrix.build }} - name: Build run: | + source venv/bin/activate make ctest --output-on-failure - ubuntu-18_04-gcc-sanitized: - runs-on: ubuntu-18.04 + ubuntu-24_04-gcc-sanitized: + runs-on: ubuntu-24.04 strategy: matrix: @@ -78,9 +166,9 @@ jobs: - name: Dependencies run: | - sudo apt-get update - sudo apt-get install build-essential - sudo apt-get install cmake; + sudo apt update + sudo apt install build-essential + sudo apt install cmake - name: Configure run: cmake . -DCMAKE_BUILD_TYPE=Debug -DGGWAVE_BUILD_EXAMPLES=OFF -DGGWAVE_SANITIZE_${{ matrix.sanitizer }}=ON @@ -90,8 +178,8 @@ jobs: make ctest --output-on-failure - ubuntu-18_04-clang: - runs-on: ubuntu-18.04 + ubuntu-24_04-clang: + runs-on: ubuntu-24.04 strategy: matrix: @@ -105,10 +193,10 @@ jobs: - name: Dependencies run: | - sudo apt-get update - sudo apt-get install build-essential xorg-dev libglu1-mesa-dev - sudo apt-get install cmake; - sudo apt-get install libsdl2-dev; + sudo apt update + sudo apt install build-essential xorg-dev libglu1-mesa-dev + sudo apt install cmake + sudo apt install libsdl2-dev - name: Configure run: cmake . -DCMAKE_BUILD_TYPE=${{ matrix.build }} -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang @@ -145,7 +233,7 @@ jobs: ctest --output-on-failure emscripten: - runs-on: ubuntu-18.04 + runs-on: ubuntu-24.04 strategy: matrix: @@ -176,28 +264,32 @@ jobs: emcmake cmake . -DCMAKE_BUILD_TYPE=${{ matrix.build }} make && ctest --output-on-failure -# windows-msys2: -# runs-on: windows-latest -# defaults: -# run: -# shell: msys2 {0} -# steps: -# - name: Clone -# uses: actions/checkout@v1 -# with: -# submodules: recursive -# -# - name: Dependencies -# uses: msys2/setup-msys2@v2 -# with: -# msystem: MINGW64 -# update: true -# install: cmake make mingw-w64-x86_64-dlfcn mingw-w64-x86_64-gcc mingw-w64-x86_64-SDL2 -# -# - name: Configure -# run: cmake . -DCMAKE_BUILD_TYPE=${{ matrix.build }} -# -# - name: Build -# run: | -# make -# ctest --output-on-failure + windows-msys2: + runs-on: windows-latest + defaults: + run: + shell: msys2 {0} + strategy: + matrix: + build: [Release] + steps: + - name: Clone + uses: actions/checkout@v1 + with: + submodules: recursive + + - name: Dependencies + uses: msys2/setup-msys2@v2 + with: + msystem: MINGW64 + update: true + install: make mingw-w64-x86_64-cmake mingw-w64-x86_64-dlfcn mingw-w64-x86_64-gcc mingw-w64-x86_64-SDL2 mingw-w64-x86_64-cmake + + - name: Configure + run: cmake . -DCMAKE_BUILD_TYPE=${{ matrix.build }} -G "Unix Makefiles" + + - name: Build + run: | + ls -alh . + make + ctest --output-on-failure diff --git a/CMakeLists.txt b/CMakeLists.txt index 28cd09f..804d2a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,3 +98,74 @@ endif() if (GGWAVE_BUILD_EXAMPLES) add_subdirectory(examples) endif() + + + +set(CPACK_COMPONENTS_GROUPING ALL_COMPONENTS_IN_ONE) +set(CPACK_DEB_COMPONENT_INSTALL YES) +set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) +set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6") +set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/ggerganov/ggwave") +set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Georgi Gerganov") +set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS YES) +set(CPACK_GENERATOR DEB) +SET(CPACK_OUTPUT_FILE_PREFIX "${CMAKE_SOURCE_DIR}/dist") +set(CPACK_PACKAGE_CONTACT "ggerganov@gmail.com") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Tiny data-over-sound library") +set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME}) +set(CPACK_PACKAGE_NAME "libggwave-dev") +set(CPACK_PACKAGE_VENDOR "ggwave") +set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) +set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) +set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") +set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md") +set(CPACK_STRIP_FILES YES) +set(CPACK_VERBATIM_VARIABLES YES) +include(CPack) + +set(DEB_PYTHON_BUILD_DIR "${CMAKE_SOURCE_DIR}/bindings/python/") +set(DEB_PYTHON_OUTPUT_FILE_PREFIX "${DEB_PYTHON_BUILD_DIR}/dist") + +set(ENV{SOURCE_DATE_EPOCH} "0") +execute_process( + COMMAND git log -1 --pretty=%ct + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + TIMEOUT 1 + OUTPUT_VARIABLE SOURCE_DATE_EPOCH + OUTPUT_STRIP_TRAILING_WHITESPACE +) +set(ENV{SOURCE_DATE_EPOCH} ${SOURCE_DATE_EPOCH}) + +add_custom_target(deb_python_binding + COMMAND cd ${DEB_PYTHON_BUILD_DIR} && make deb + COMMENT "Building Debian package for Python binding" + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} +) + +add_custom_target(deb_c_library + COMMAND SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH} cpack + COMMENT "Building Debian package for C library" + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} +) + +add_custom_target(deb_python_move + COMMAND mv ${DEB_PYTHON_OUTPUT_FILE_PREFIX}/*.deb ${CPACK_OUTPUT_FILE_PREFIX}/ + COMMENT "Moving Debian package for Python binding into ${CPACK_OUTPUT_FILE_PREFIX}/" + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + DEPENDS deb_python_binding deb_c_library +) + +add_custom_target(deb + COMMAND sha256sum ${CPACK_OUTPUT_FILE_PREFIX}/* + COMMENT "Debian package sha256 hashes" + DEPENDS deb_c_library deb_python_binding deb_python_move + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} +) + +add_custom_command(TARGET deb + POST_BUILD + COMMAND ls -alh ${CPACK_OUTPUT_FILE_PREFIX}/* + COMMENT "SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH}" + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} +) diff --git a/README-tmpl.md b/README-tmpl.md index 58b1d4b..973e89a 100644 --- a/README-tmpl.md +++ b/README-tmpl.md @@ -157,6 +157,24 @@ make ./bin/ggwave-cli ``` +#### Local Debian packages + +Build reproducible `libggwave-dev` and `python3-ggwave` Debian packages: +```bash +# Fetch source +git clone https://github.com/ggerganov/ggwave --recursive +cd ggwave + +# Configure +cmake . -DGGWAVE_BUILD_EXAMPLES=OFF -DCMAKE_BUILD_TYPE=Release + +# Build +make deb + +# Install +sudo dpkg -i dist/*.deb +``` + ### Emscripten ```bash diff --git a/README.md b/README.md index a4d7223..118def3 100644 --- a/README.md +++ b/README.md @@ -159,6 +159,24 @@ make ./bin/ggwave-cli ``` +#### Local Debian packages + +Build reproducible `libggwave-dev` and `python3-ggwave` Debian packages: +```bash +# Fetch source +git clone https://github.com/ggerganov/ggwave --recursive +cd ggwave + +# Configure +cmake . -DGGWAVE_BUILD_EXAMPLES=OFF -DCMAKE_BUILD_TYPE=Release + +# Build +make deb + +# Install +sudo dpkg -i dist/*.deb +``` + ### Emscripten ```bash diff --git a/bindings/python/Makefile b/bindings/python/Makefile index 679e040..f6d825e 100644 --- a/bindings/python/Makefile +++ b/bindings/python/Makefile @@ -1,12 +1,29 @@ default: build +PKG_NAME := ggwave +DEST := dist/ +VER := $(shell cat setup.py | grep version |cut -d\" -f2) +VERSION := $(strip $(VER)) +ORIG_TGZ := $(PKG_NAME)_$(VERSION).orig.tar.gz +ARCH := $(shell dpkg --print-architecture) +DEB_BUILD_OPTIONS := nocheck +DEB_BUILD_DIR := $(DEST)$(PKG_NAME)-$(VERSION) +DEB_VER := 0 +DEB := python3-$(PKG_NAME)_$(VERSION)-$(DEB_VER)_$(ARCH).deb +SOURCE_DATE_EPOCH := $(shell git log -1 --pretty=%ct) +SOURCE_PKG_CMD := python -m build --sdist +DEB_BUILD_CMD := dpkg-buildpackage -rfakeroot -uc -us +COGAPP ?= $(shell which cog || which cogapp) + .PHONY: ggwave: # create a clean (maybe updated) copy of ggwave src rm -rf ggwave && mkdir ggwave && cp -r ../../include ggwave/ && cp -r ../../src ggwave/ +deps: + echo python -m pip install cogapp cython twine + pyggwave.bycython.cpp: ggwave.pyx cggwave.pxd - python -m pip install cython cython --cleanup=3 --cplus ggwave.pyx -o ggwave.bycython.cpp # To build package, README.rst is needed, because it goes into long description of package, @@ -17,12 +34,30 @@ pyggwave.bycython.cpp: ggwave.pyx cggwave.pxd BUILD_SOURCE_FILES=ggwave pyggwave.bycython.cpp setup.py +$(DEST)$(DEB): $(DEST)$(ORIG_TGZ) + -rm -r $(DEB_BUILD_DIR) + tar -C $(DEST) -xf $(DEST)$(ORIG_TGZ) + cp -arp debian $(DEB_BUILD_DIR) + cd $(DEB_BUILD_DIR) && \ + DEB_BUILD_OPTIONS=$(DEB_BUILD_OPTIONS) $(DEB_BUILD_CMD) + +deb_sdist: $(BUILD_SOURCE_FILES) README.rst + SOURCE_DATE_EPOCH=$(SOURCE_DATE_EPOCH) $(SOURCE_PKG_CMD) + mv $(DEST)$(PKG_NAME)-$(VERSION).tar.gz $(DEST)$(ORIG_TGZ) + +_deb: + @$(eval COGAPP=cogapp) + +deb: _deb deb_sdist $(DEST)$(DEB) + dpkg --contents $(DEST)$(DEB) + ls -alh $(DEST)*$(PKG_NAME)* + sha256sum $(DEST)$(DEB) + buildWithoutREADME.rst: ${BUILD_SOURCE_FILES} GGWAVE_OMIT_README_RST=1 python setup.py build_ext -i README.rst: buildWithoutREADME.rst README-tmpl.rst - python -m pip install cogapp - cog -d -o README.rst README-tmpl.rst + $(COGAPP) -d -o README.rst README-tmpl.rst BUILD_FILES=${BUILD_SOURCE_FILES} README.rst diff --git a/bindings/python/debian/changelog b/bindings/python/debian/changelog new file mode 100644 index 0000000..179c94a --- /dev/null +++ b/bindings/python/debian/changelog @@ -0,0 +1,5 @@ +ggwave (0.4.2-0) unstable; urgency=low + + * Initial release + + -- Georgi Gerganov Sat, 15 Mar 2025 11:17:22 +0000 diff --git a/bindings/python/debian/control b/bindings/python/debian/control new file mode 100644 index 0000000..3cd3454 --- /dev/null +++ b/bindings/python/debian/control @@ -0,0 +1,40 @@ +Source: ggwave +Section: python +Priority: optional +Maintainer: Georgi Gerganov +Build-Depends: debhelper-compat (= 13), + dh-python, + cython3, + python3-all-dev, + python3-setuptools, +Standards-Version: 4.6.2.0 +Testsuite: autopkgtest-pkg-pybuild +Homepage: https://github.com/ggerganov/ggwave +Rules-Requires-Root: no + +Package: python3-ggwave +Architecture: any +Depends: ${misc:Depends}, ${python3:Depends}, ${shlibs:Depends}, +Description: Tiny data-over-sound library + Tiny data-over-sound library. + . + . + .. code:: python + . + # generate audio waveform for string "hello python" + waveform = ggwave.encode("hello python") + . + # decode audio waveform + text = ggwave.decode(instance, waveform) + . + . + -------- + Features + -------- + . + * Audible and ultrasound transmissions available + * Bandwidth of 8-16 bytes/s (depending on the transmission protocol) + * Robust FSK modulation + * Reed-Solomon based error correction + . + ------------ diff --git a/bindings/python/debian/copyright b/bindings/python/debian/copyright new file mode 100644 index 0000000..d8fb91c --- /dev/null +++ b/bindings/python/debian/copyright @@ -0,0 +1,14 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: ggwave +Upstream-Contact: Georgi Gerganov +Source: https://github.com/ggerganov/ggwave + +Files: * +Copyright: Georgi Gerganov +License: MIT + +Files: debian/* +Copyright: Georgi Gerganov +License: MIT + +License: MIT diff --git a/bindings/python/debian/python3-ggwave.docs b/bindings/python/debian/python3-ggwave.docs new file mode 100644 index 0000000..a1320b1 --- /dev/null +++ b/bindings/python/debian/python3-ggwave.docs @@ -0,0 +1 @@ +README.rst diff --git a/bindings/python/debian/rules b/bindings/python/debian/rules new file mode 100755 index 0000000..d202a55 --- /dev/null +++ b/bindings/python/debian/rules @@ -0,0 +1,5 @@ +#! /usr/bin/make -f + +export PYBUILD_NAME=ggwave +%: + dh $@ --with python3 --buildsystem=pybuild diff --git a/bindings/python/debian/source/format b/bindings/python/debian/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/bindings/python/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/bindings/python/debian/source/options b/bindings/python/debian/source/options new file mode 100644 index 0000000..fb8b37b --- /dev/null +++ b/bindings/python/debian/source/options @@ -0,0 +1 @@ +extend-diff-ignore="^[^/]+.(egg-info|dist-info)/"