diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a1132ae..4613761 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,47 +3,48 @@ name: Build on: push: pull_request: - #schedule: - # - cron: '0 */2 * * *' jobs: - build-linux: + build-linux-x86_64: runs-on: ubuntu-latest timeout-minutes: 90 env: - OS_NAME: unknown - ARCH_NAME: unknown - DLL_NAME: libasyncprocess.so - RESULT_NAME: result-linux - RESULT_PATH: result-linux + OS_NAME: Linux + ARCH_NAME: x86_64 + LIB_NAME: libasyncprocess.a + RESULT_NAME: result-linux-x86_64 + RESULT_PATH: result-linux-x86_64 RESULT_PATH_SUB: result-async/static steps: - - uses: actions/checkout@v2 - - name: Set environment variables - run: | - pwd - uname - uname -m - OS_NAME=`uname` - ARCH_NAME=`uname -m` - echo "OS_NAME=$OS_NAME" >> $GITHUB_ENV - echo "ARCH_NAME=$ARCH_NAME" >> $GITHUB_ENV + - uses: actions/checkout@v4 - name: Install run: | + sudo apt-get update sudo apt-get install libtool automake - name: Build run: | gcc -v - rm static/$ARCH_NAME/$OS_NAME/$DLL_NAME - ./bootstrap + # Generate build system + libtoolize --copy --force --quiet + aclocal + autoheader + automake --add-missing --copy --foreign + autoconf + # Configure for static library build + ./configure --enable-static --disable-shared + make + - name: Verify static library + run: | + file .libs/$LIB_NAME + ls -lh .libs/$LIB_NAME - name: Copy Result if: always() run: | mkdir -p $RESULT_PATH/$RESULT_PATH_SUB/$ARCH_NAME/$OS_NAME - cp static/$ARCH_NAME/$OS_NAME/$DLL_NAME $RESULT_PATH/$RESULT_PATH_SUB/$ARCH_NAME/$OS_NAME + cp .libs/$LIB_NAME $RESULT_PATH/$RESULT_PATH_SUB/$ARCH_NAME/$OS_NAME/ - name: Upload Result if: always() - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: ${{ env.RESULT_NAME }} path: ${{ env.RESULT_PATH }} @@ -54,82 +55,174 @@ jobs: env: OS_NAME: Linux ARCH_NAME: aarch64 - DLL_NAME: libasyncprocess.so + LIB_NAME: libasyncprocess.a RESULT_NAME: result-linux-aarch64 RESULT_PATH: result-linux-aarch64 RESULT_PATH_SUB: result-async/static steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Build on aarch64 (arm64) - id: runcmd - uses: uraimo/run-on-arch-action@v1.0.5 + uses: uraimo/run-on-arch-action@v2 with: - architecture: aarch64 - distribution: ubuntu18.04 + arch: aarch64 + distro: ubuntu22.04 + githubToken: ${{ github.token }} + install: | + apt-get update -q -y + apt-get install -q -y build-essential automake libtool file run: | - apt-get update - apt-get -y install build-essential - apt-get -y install automake - apt-get -y install libtool pwd - uname - uname -m - gcc -v - rm static/${{ env.ARCH_NAME }}/${{ env.OS_NAME }}/${{ env.DLL_NAME }} - ./bootstrap + uname -a + gcc --version + # Generate build system + libtoolize --copy --force --quiet + aclocal + autoheader + automake --add-missing --copy --foreign + autoconf + # Configure for static library build + ./configure --enable-static --disable-shared + make + # Verify static library + file .libs/libasyncprocess.a + ls -lh .libs/libasyncprocess.a - name: Copy Result if: always() run: | mkdir -p $RESULT_PATH/$RESULT_PATH_SUB/$ARCH_NAME/$OS_NAME - cp static/$ARCH_NAME/$OS_NAME/$DLL_NAME $RESULT_PATH/$RESULT_PATH_SUB/$ARCH_NAME/$OS_NAME + cp .libs/$LIB_NAME $RESULT_PATH/$RESULT_PATH_SUB/$ARCH_NAME/$OS_NAME/ - name: Upload Result if: always() - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: ${{ env.RESULT_NAME }} path: ${{ env.RESULT_PATH }} - build-osx: - runs-on: macos-latest + build-osx-aarch64: + runs-on: macos-14 # macOS 14 runs on Apple Silicon (aarch64/arm64) timeout-minutes: 90 env: - OS_NAME: unknown - ARCH_NAME: unknown - DLL_NAME: libasyncprocess.so - RESULT_NAME: result-osx - RESULT_PATH: result-osx + OS_NAME: Darwin + ARCH_NAME: aarch64 + LIB_NAME: libasyncprocess.a + RESULT_NAME: result-osx-aarch64 + RESULT_PATH: result-osx-aarch64 RESULT_PATH_SUB: result-async/static steps: - - uses: actions/checkout@v2 - - name: Set environment variables + - uses: actions/checkout@v4 + - name: Install tools run: | - pwd - uname - uname -m - OS_NAME=`uname` - ARCH_NAME=`uname -m` - echo "OS_NAME=$OS_NAME" >> $GITHUB_ENV - echo "ARCH_NAME=$ARCH_NAME" >> $GITHUB_ENV + brew install automake + brew install libtool + - name: Build + run: | + gcc -v + # Generate build system + glibtoolize --copy --force --quiet + aclocal + autoheader + automake --add-missing --copy --foreign + autoconf + # Configure for static library build + ./configure --enable-static --disable-shared + make + - name: Verify static library + run: | + file .libs/$LIB_NAME + ls -lh .libs/$LIB_NAME + lipo -info .libs/$LIB_NAME + - name: Copy Result + if: always() + run: | + mkdir -p $RESULT_PATH/$RESULT_PATH_SUB/$ARCH_NAME/$OS_NAME + cp .libs/$LIB_NAME $RESULT_PATH/$RESULT_PATH_SUB/$ARCH_NAME/$OS_NAME/ + - name: Upload Result + if: always() + uses: actions/upload-artifact@v4 + with: + name: ${{ env.RESULT_NAME }} + path: ${{ env.RESULT_PATH }} + + build-osx-x86_64: + runs-on: macos-13 # macOS 13 runs on Intel (x86_64) + timeout-minutes: 90 + env: + OS_NAME: Darwin + ARCH_NAME: x86_64 + LIB_NAME: libasyncprocess.a + RESULT_NAME: result-osx-x86_64 + RESULT_PATH: result-osx-x86_64 + RESULT_PATH_SUB: result-async/static + steps: + - uses: actions/checkout@v4 - name: Install tools run: | brew install automake - #brew install libtool - which glibtoolize - ln -s /usr/local/bin/glibtoolize /usr/local/bin/libtoolize - which libtoolize + brew install libtool - name: Build run: | gcc -v - rm static/$ARCH_NAME/$OS_NAME/$DLL_NAME - ./bootstrap + # Generate build system + glibtoolize --copy --force --quiet + aclocal + autoheader + automake --add-missing --copy --foreign + autoconf + # Configure for static library build + ./configure --enable-static --disable-shared + make + - name: Verify static library + run: | + file .libs/$LIB_NAME + ls -lh .libs/$LIB_NAME + lipo -info .libs/$LIB_NAME - name: Copy Result if: always() run: | mkdir -p $RESULT_PATH/$RESULT_PATH_SUB/$ARCH_NAME/$OS_NAME - cp static/$ARCH_NAME/$OS_NAME/$DLL_NAME $RESULT_PATH/$RESULT_PATH_SUB/$ARCH_NAME/$OS_NAME + cp .libs/$LIB_NAME $RESULT_PATH/$RESULT_PATH_SUB/$ARCH_NAME/$OS_NAME/ - name: Upload Result if: always() - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: ${{ env.RESULT_NAME }} path: ${{ env.RESULT_PATH }} + + release: + runs-on: ubuntu-latest + needs: [build-linux-x86_64, build-linux-aarch64, build-osx-aarch64, build-osx-x86_64] + if: startsWith(github.ref, 'refs/tags/') + steps: + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + + - name: Prepare release files + run: | + mkdir -p release-files + echo "Finding all .a files in artifacts..." + find artifacts -name "*.a" -type f + echo "" + echo "Creating uniquely named release files..." + # Find and rename all library files with their arch and os + find artifacts -name "*.a" -type f | while read file; do + # Extract the directory structure to get arch and os + dir=$(dirname "$file") + arch=$(basename "$(dirname "$dir")") + os=$(basename "$dir") + # Normalize OS name to lowercase for consistency + os_lower=$(echo "$os" | tr '[:upper:]' '[:lower:]') + # Create a unique filename: libasyncprocess.{os}.{arch}.a + output_name="libasyncprocess.${os_lower}.${arch}.a" + echo " $file -> release-files/$output_name" + cp "$file" "release-files/$output_name" + done + echo "" + echo "Release files ready for upload:" + ls -lh release-files/ + + - name: Create Release + uses: softprops/action-gh-release@v1 + with: + files: release-files/* \ No newline at end of file diff --git a/GNUmakefile b/GNUmakefile new file mode 100644 index 0000000..4323451 --- /dev/null +++ b/GNUmakefile @@ -0,0 +1,63 @@ +PREFIX ?= /usr/local + +GENERATED_MAKEFILE := $(wildcard Makefile) + +.PHONY: distclean +distclean: + @if [ -f Makefile ]; then \ + echo "Running make distclean..."; \ + $(MAKE) -f Makefile distclean 2>/dev/null || true; \ + fi + @echo "Removing autotools generated files..." + @rm -rf Makefile Makefile.in configure config.* libtool aclocal.m4 stamp-h1 autom4te.cache + @rm -rf compile config.guess config.sub depcomp install-sh ltmain.sh missing + @rm -rf .libs .deps src/.libs src/.deps + @rm -f *.lo *.la src/*.lo src/*.la + @echo "All generated files removed. Run 'make' to rebuild." + +# If Makefile exists, delegate to it +ifneq ($(GENERATED_MAKEFILE),) + +.DEFAULT_GOAL := all + +%: + $(MAKE) -f Makefile $@ + +else + +# No Makefile - need to generate build system +.DEFAULT_GOAL := all + +configure: configure.ac Makefile.am + @echo "Generating build system..." + @which glibtoolize > /dev/null 2>&1 && glibtoolize --copy --force --quiet || libtoolize --copy --force --quiet + @aclocal + @autoheader + @automake --add-missing --copy --foreign + @autoconf + @echo "" + +Makefile: configure + @echo "Running configure..." + @./configure --prefix=$(PREFIX) + @echo "" + +.PHONY: all +all: Makefile + @$(MAKE) -f Makefile all + @echo "" + @echo "Build complete. Install with: make install" + @echo "" + +.PHONY: build +build: all + +.PHONY: install +install: Makefile + @$(MAKE) -f Makefile install + +.PHONY: clean +clean: Makefile + @$(MAKE) -f Makefile clean + +endif diff --git a/Makefile.am b/Makefile.am index e1c2429..a4f6213 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,16 +1,8 @@ -pkglib_LTLIBRARIES = libasyncprocess.la -libasyncprocess_la_LDFLAGS = -module -avoid-version -no-undefined -libasyncprocess_la_SOURCES = src/async-process.c src/async-process_windows.c +lib_LTLIBRARIES = libasyncprocess.la +libasyncprocess_la_LDFLAGS = -version-info @LT_VERSION_INFO@ -no-undefined +libasyncprocess_la_SOURCES = src/async-process.c -copy: - $(MKDIR_P) static/`uname -m`/`uname` - cp -f .libs/libasyncprocess.so static/`uname -m`/`uname`/libasyncprocess.so|true - cp -f .libs/libasyncprocess.dylib static/`uname -m`/`uname`/libasyncprocess.dylib|true - case "$(MSYSTEM)" in \ - MINGW32) \ - $(MKDIR_P) static/x86/windows ;\ - cp -f .libs/libasyncprocess.dll static/x86/windows/libasyncprocess.dll|true;; \ - *) \ - $(MKDIR_P) static/`uname -m`/windows ;\ - cp -f .libs/libasyncprocess.dll static/`uname -m`/windows/libasyncprocess.dll|true;; \ - esac +include_HEADERS = src/async-process.h + +install-exec-hook: + rm -f $(DESTDIR)$(libdir)/libasyncprocess.la diff --git a/README.md b/README.md index 3368015..3372846 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,62 @@ # async-process +A Common Lisp library for creating and managing asynchronous processes with PTY support. + +## Platform Support + +- **Linux**: Full support via C library using PTY +- **BSD**: Full support via C library using PTY +- **macOS**: Full support via C library using PTY +- **Windows**: Full support via pure Lisp CFFI implementation (no C compilation required) + +## Installation + +### Unix-like Systems (Linux, FreeBSD, macOS) +using GNU make, `gmake` on Freebsd and macOS. + +```bash +git clone https://github.com/soppelmann/async-process.git +cd async-process +make +sudo make install +``` + +The library installs to `/usr/local` by default. To install elsewhere: + +```bash +make install PREFIX=/usr +make install PREFIX=$HOME/.local +``` + +#### Configuration options +Build as a static library as follows + +```bash +make +./configure --enable-static +make all +sudo make install +``` + +### Windows + +On Windows, no C compilation is required. The library uses a pure Lisp implementation via CFFI: + +```bash +git clone https://github.com/soppelmann/async-process.git +cd async-process +``` + +Then simply load the library in your Lisp environment: + +```lisp +(ql:quickload :async-process) +``` + +The ASDF system will automatically load the Windows-specific implementation (`src/async-process_windows.lisp`) when on Windows platforms. + +## Usage + ``` CL-USER> (ql:quickload :async-process) To load "async-process": diff --git a/bootstrap b/bootstrap deleted file mode 100755 index e127d68..0000000 --- a/bootstrap +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -libtoolize -aclocal -autoheader -automake -a -autoconf - -./configure -make -make copy diff --git a/cleanup-all b/cleanup-all deleted file mode 100644 index 1ba99f8..0000000 --- a/cleanup-all +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -if [ -f Makefile ]; then - make distclean -fi - -rm -rf .deps -rm -rf autom4te.cache -rm -f aclocal.m4 compile config.guess config.h.in config.sub \ - configure depcomp install-sh ltmain.sh Makefile.in missing - diff --git a/configure.ac b/configure.ac index abb6781..abe74b0 100644 --- a/configure.ac +++ b/configure.ac @@ -1,12 +1,24 @@ AC_INIT([async-process], [0.1]) -AM_CONFIG_HEADER(config.h) +AC_CONFIG_HEADERS([config.h]) -AM_INIT_AUTOMAKE([foreign]) -LT_INIT(shared win32-dll) +# Library versioning (current:revision:age) +AC_SUBST([LT_VERSION_INFO], [0:0:0]) + +# Set default prefix based on platform if not specified +AC_PREFIX_DEFAULT([/usr/local]) + +AM_INIT_AUTOMAKE([foreign subdir-objects]) + +# Must detect C compiler before initializing libtool AC_PROG_CC +# Initialize libtool (disable static by default, enable with --enable-static) +LT_INIT([disable-static]) -AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h windows.h]) +AC_CANONICAL_HOST +test "$prefix" = NONE && prefix=/usr/local + +AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h]) AC_CHECK_HEADER_STDBOOL AC_TYPE_PID_T @@ -17,3 +29,32 @@ AC_CHECK_FUNCS([dup2 strerror]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT + +# Print configuration summary +AC_MSG_NOTICE([ + async-process configuration summary: + + Installation prefix: $prefix + Library directory: $libdir + Include directory: $includedir + C Compiler: $CC + Host system: $host_os + Build shared: $enable_shared + Build static: $enable_static + + Note: This C library is for Unix-like systems only (Linux, FreeBSD, macOS). + Windows support is provided via pure Lisp CFFI implementation and does not + require C compilation. + + You can now run 'make' to build the library. + After building, run 'make install' to install to the prefix. + + To install to a different location, reconfigure with: + ./configure --prefix=/your/custom/path + + To build static library: + ./configure --enable-static + + To build only static (no shared): + ./configure --enable-static --disable-shared +]) diff --git a/static/aarch64/Linux-musl/libasyncprocess.so b/static/aarch64/Linux-musl/libasyncprocess.so deleted file mode 100755 index afd46e0..0000000 Binary files a/static/aarch64/Linux-musl/libasyncprocess.so and /dev/null differ diff --git a/static/aarch64/Linux/libasyncprocess.so b/static/aarch64/Linux/libasyncprocess.so deleted file mode 100755 index 2759b7c..0000000 Binary files a/static/aarch64/Linux/libasyncprocess.so and /dev/null differ diff --git a/static/arm64/Darwin/libasyncprocess.so b/static/arm64/Darwin/libasyncprocess.so deleted file mode 100755 index 80b14ac..0000000 Binary files a/static/arm64/Darwin/libasyncprocess.so and /dev/null differ diff --git a/static/x86_64/Darwin/libasyncprocess.so b/static/x86_64/Darwin/libasyncprocess.so deleted file mode 100755 index 133305c..0000000 Binary files a/static/x86_64/Darwin/libasyncprocess.so and /dev/null differ diff --git a/static/x86_64/Linux-musl/libasyncprocess.so b/static/x86_64/Linux-musl/libasyncprocess.so deleted file mode 100755 index 2d2ca23..0000000 Binary files a/static/x86_64/Linux-musl/libasyncprocess.so and /dev/null differ diff --git a/static/x86_64/Linux/libasyncprocess.so b/static/x86_64/Linux/libasyncprocess.so deleted file mode 100755 index c7fdee1..0000000 Binary files a/static/x86_64/Linux/libasyncprocess.so and /dev/null differ diff --git a/static_old0001-819cbf6/aarch64/Linux/libasyncprocess.so b/static_old0001-819cbf6/aarch64/Linux/libasyncprocess.so deleted file mode 100644 index 2b6178c..0000000 Binary files a/static_old0001-819cbf6/aarch64/Linux/libasyncprocess.so and /dev/null differ diff --git a/static_old0001-819cbf6/x86/windows/libasyncprocess.dll b/static_old0001-819cbf6/x86/windows/libasyncprocess.dll deleted file mode 100644 index 12952d8..0000000 Binary files a/static_old0001-819cbf6/x86/windows/libasyncprocess.dll and /dev/null differ diff --git a/static_old0001-819cbf6/x86_64/Darwin/libasyncprocess.so b/static_old0001-819cbf6/x86_64/Darwin/libasyncprocess.so deleted file mode 100644 index ff00e07..0000000 Binary files a/static_old0001-819cbf6/x86_64/Darwin/libasyncprocess.so and /dev/null differ diff --git a/static_old0001-819cbf6/x86_64/Linux/libasyncprocess.so b/static_old0001-819cbf6/x86_64/Linux/libasyncprocess.so deleted file mode 100644 index 949b0ce..0000000 Binary files a/static_old0001-819cbf6/x86_64/Linux/libasyncprocess.so and /dev/null differ diff --git a/static_old0001-819cbf6/x86_64/windows/libasyncprocess.dll b/static_old0001-819cbf6/x86_64/windows/libasyncprocess.dll deleted file mode 100644 index 67add3e..0000000 Binary files a/static_old0001-819cbf6/x86_64/windows/libasyncprocess.dll and /dev/null differ