diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 92910f6..790d6da 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,7 +27,7 @@ jobs: # To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list. matrix: - os: [ubuntu-latest-large, windows-latest-large, macos-latest-large] # windows-11-arm doesnt have working msys2 yet + os: [ubuntu-latest-large] # windows-11-arm doesnt have working msys2 yet defaults: run: @@ -107,6 +107,9 @@ jobs: if: ${{ ! contains(matrix.os, 'windows') }} run: ./build.sh -s -t -m -x -i + - name: Build AppImage + if: contains(matrix.os, 'ubuntu') + run: ./build.sh -a - name: Run Regression run: ./build.sh -r @@ -116,12 +119,17 @@ jobs: uses: actions/upload-artifact@v4 with: name: xyce-${{ matrix.os }} - path: _install + path: _install_* + + - name: Upload AppImage as artifact + if: contains(matrix.os, 'ubuntu') + uses: actions/upload-artifact@v4 + with: + name: xyce-appimage-${{ matrix.os }} + path: _build_*/Xyce-*.AppImage - name: Upload regression results as artifact uses: actions/upload-artifact@v4 with: name: xyce-regression-${{ matrix.os }} path: _build_*/Xyce-Regression - - diff --git a/Dockerfile b/Dockerfile index b499da8..c38d451 100644 --- a/Dockerfile +++ b/Dockerfile @@ -93,7 +93,7 @@ RUN --mount=type=cache,target=/ccache,uid=1001 ./build.sh -x #-------------------------- # Install Xyce and XDM #-------------------------- -RUN --mount=type=cache,target=/ccache,uid=1001 ./build.sh -i _install +RUN --mount=type=cache,target=/ccache,uid=1001 ./build.sh -i #-------------------------- # Run regression tests @@ -115,7 +115,32 @@ RUN ls -la _install_Linux/bin/ && \ RUN ls -laR . > file.list -#FROM scratch -#COPY --from=build /home/builder/_build_Linux /_build_Linux -#COPY --from=build /home/builder/_install_Linux /_install_Linux -#COPY --from=build /home/builder/file.list /file.list +#-------------------------- +# Build AppImage +#-------------------------- +FROM xyce AS appimage + +COPY --chown=builder:builder scripts/build-appimage.sh /home/builder/scripts/build-appimage.sh +COPY --chown=builder:builder data/AppImageBuilder.yml /home/builder/data/AppImageBuilder.yml +COPY --chown=builder:builder data/Xyce.desktop /home/builder/data/Xyce.desktop +COPY --chown=builder:builder data/xyce.png /home/builder/data/xyce.png + +USER builder +WORKDIR /home/builder + +# Install appimage-builder and dependencies +USER root +RUN apt-get update && apt-get install -y wget gtk-update-icon-cache squashfs-tools && rm -rf /var/lib/apt/lists/* +USER builder + +RUN --mount=type=cache,target=/ccache,uid=1001 ./build.sh -a + +# Verify the AppImage was created +RUN ls -lh _build_Linux/Xyce-*.AppImage || echo "AppImage build completed" + +#-------------------------- +# Export stage for easy artifact extraction +#-------------------------- +FROM scratch AS export +COPY --from=appimage /home/builder/_build_Linux/Xyce-*.AppImage / +COPY --from=appimage /home/builder/_install_Linux /install/ diff --git a/build.sh b/build.sh index a671f7c..d98c563 100755 --- a/build.sh +++ b/build.sh @@ -9,15 +9,16 @@ Help() # Display Help echo "Xyce build script for Ubuntu, Windows and macOS, 64 bit x86_64 or aarch64" echo - echo "Syntax: $0 [-h] [-s] [-d] [-t] [-x] [-i install-dir] [-- []]" + echo "Syntax: $0 [-h] [-s] [-d] [-t] [-x] [-i] [-a] [-- []]" echo "options:" echo " -d: Debug build" echo " -s: Fetch source" echo " -t: Build Trilinos" echo " -m: Build XDM" echo " -x: Build Xyce" - echo " -i: Install XDM and Xyce in the given directory" + echo " -i: Install XDM and Xyce" echo " -r: Run the regression suite" + echo " -a: Build AppImage (requires Xyce to be installed)" echo " -h: Display this help" echo " : Arbitary options to pass to ./configure :" echo @@ -45,12 +46,13 @@ unset BUILD_XDM unset BUILD_XYCE unset RUN_REGRESSION unset INSTALL_XYCE +unset BUILD_APPIMAGE ############################################################ # Process the input options. Add options as needed. # ############################################################ # Get the options -while getopts ":hdtxmsri:" option; do +while getopts ":hdtxmsrai" option; do case $option in h) # display Help Help @@ -80,9 +82,12 @@ while getopts ":hdtxmsri:" option; do RUN_REGRESSION=1 option_passed=1 ;; + a) # Build AppImage + BUILD_APPIMAGE=1 + option_passed=1 + ;; i) # Install INSTALL_XYCE=1 - INSTALL_DIR=${OPTARG} option_passed=1 ;; \?) # Invalid option @@ -273,4 +278,6 @@ if [ -n "$INSTALL_XYCE" ]; then ./scripts/install-xdm.sh || exit 1 fi - +if [ -n "$BUILD_APPIMAGE" ]; then + ./scripts/build-appimage.sh || exit 1 +fi diff --git a/data/AppImageBuilder.yml b/data/AppImageBuilder.yml new file mode 100644 index 0000000..c2b5a7d --- /dev/null +++ b/data/AppImageBuilder.yml @@ -0,0 +1,60 @@ +version: 1 + +script: + - mkdir -p $TARGET_APPDIR/usr + - cp -r _install_Linux/* $TARGET_APPDIR/usr/ + - mkdir -p $TARGET_APPDIR/usr/share/icons/hicolor/256x256/apps/ + - cp data/xyce.png $TARGET_APPDIR/usr/share/icons/hicolor/256x256/apps/xyce.png + - mkdir -p $TARGET_APPDIR/usr/share/applications/ + - cp data/Xyce.desktop $TARGET_APPDIR/usr/share/applications/org.sandia.xyce.desktop + +AppDir: + path: ./AppDir + app_info: + id: org.sandia.xyce + name: Xyce + icon: xyce + version: 1.0.0 + exec: usr/bin/Xyce + exec_args: $@ + + apt: + arch: amd64 + sources: + - sourceline: 'deb http://archive.ubuntu.com/ubuntu/ jammy main universe' + key_url: 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x871920D1991BC93C' + include: + # Xyce dependencies + - libblas3 + - liblapack3 + - libfftw3-3 + - libsuitesparseconfig5 + - libsuitesparse-dev + - libboost-python1.74.0 + # OpenMPI for parallel circuit simulation + - openmpi-bin + - libopenmpi3 + # Additional runtime dependencies + - libgomp1 + - libgfortran5 + - libgcc-s1 + - libc6 + - libstdc++6 + exclude: + # Exclude development packages to reduce size + - libopenmpi-dev + - libblas-dev + - liblapack-dev + + runtime: + env: + # OpenMPI configuration for AppImage environment + OPAL_PREFIX: '$APPDIR/usr' + OMPI_MCA_prefix: '$APPDIR/usr' + path_mappings: + # Map OpenMPI paths to AppDir locations + - /usr/share/openmpi:$APPDIR/usr/share/openmpi + - /etc/openmpi:$APPDIR/etc/openmpi + +AppImage: + arch: x86_64 diff --git a/data/Xyce.desktop b/data/Xyce.desktop new file mode 100644 index 0000000..17b12a0 --- /dev/null +++ b/data/Xyce.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Type=Application +Name=Xyce +GenericName=Circuit Simulator +Comment=Parallel Electronic Circuit Simulator +Exec=Xyce +Icon=xyce +Terminal=true +Categories=Science;Engineering;Electronics; +Keywords=circuit;simulation;spice;electronics; diff --git a/data/xyce.png b/data/xyce.png new file mode 100644 index 0000000..e4a81c7 Binary files /dev/null and b/data/xyce.png differ diff --git a/scripts/build-appimage-docker.sh b/scripts/build-appimage-docker.sh new file mode 100755 index 0000000..211dc6a --- /dev/null +++ b/scripts/build-appimage-docker.sh @@ -0,0 +1,22 @@ +#!/bin/bash +set -e + +echo "Building Xyce AppImage using Docker..." +echo "This will build all stages and extract the AppImage to the current directory." +echo + +# Determine output directory +OUTPUT_DIR="${1:-.}" +mkdir -p "$OUTPUT_DIR" + +echo "Building Docker image (this may take a while)..." +docker build --target export --output "$OUTPUT_DIR" . + +echo +echo "Build complete! AppImage extracted to:" +ls -lh "$OUTPUT_DIR"/Xyce-*.AppImage + +echo +echo "To run the AppImage:" +echo " chmod +x $OUTPUT_DIR/Xyce-*.AppImage" +echo " $OUTPUT_DIR/Xyce-*.AppImage --version" diff --git a/scripts/build-appimage.sh b/scripts/build-appimage.sh new file mode 100755 index 0000000..769a7ef --- /dev/null +++ b/scripts/build-appimage.sh @@ -0,0 +1,80 @@ +#!/bin/bash +set -e +set -o pipefail + +echo "Building Xyce AppImage using appimage-builder..." + +# Ensure we're in the correct directory +if [ -z "$ROOT" ]; then + ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +fi + +cd "$ROOT" + +# Ensure INSTALL_PATH is set +if [ -z "$INSTALL_PATH" ]; then + echo "ERROR: INSTALL_PATH must be set" + exit 1 +fi + +# Check if Xyce is installed +if [ ! -f "$INSTALL_PATH/bin/Xyce" ]; then + echo "ERROR: Xyce not found at $INSTALL_PATH/bin/Xyce" + exit 1 +fi + +# Check if AppImageBuilder recipe exists +if [ ! -f "data/AppImageBuilder.yml" ]; then + echo "ERROR: data/AppImageBuilder.yml not found" + exit 1 +fi + +# Set version from Xyce binary if available +VERSION="unknown" +if [ -f "$INSTALL_PATH/bin/Xyce" ]; then + VERSION=$("$INSTALL_PATH/bin/Xyce" --version 2>&1 | head -n1 | grep -oP '\d+\.\d+(\.\d+)?' || echo "unknown") +fi + +echo "Building AppImage for Xyce version: $VERSION" + +# Export version for AppImageBuilder +export VERSION="$VERSION" + +# Clean any existing AppDir +rm -rf AppDir + +# Create the AppImage using appimage-builder +echo "Running appimage-builder..." +wget -O appimage-builder-x86_64.AppImage https://github.com/AppImageCrafters/appimage-builder/releases/download/v1.1.0/appimage-builder-1.1.0-x86_64.AppImage +chmod +x appimage-builder-x86_64.AppImage +./appimage-builder-x86_64.AppImage --appimage-extract-and-run --recipe data/AppImageBuilder.yml + +# Find any Xyce AppImage file +echo "Looking for Xyce AppImage file..." +APPIMAGE_OUTPUT="" + +# Look for Xyce AppImage files +for appimage_file in Xyce*.AppImage; do + if [ -f "$appimage_file" ]; then + APPIMAGE_OUTPUT="$appimage_file" + break + fi +done + +if [ -n "$APPIMAGE_OUTPUT" ] && [ -f "$APPIMAGE_OUTPUT" ]; then + echo "AppImage created successfully: $APPIMAGE_OUTPUT" + ls -lh "$APPIMAGE_OUTPUT" + + # Move to build directory if it exists + if [ -n "$BUILDDIR" ] && [ -d "$ROOT/$BUILDDIR" ]; then + mv "$APPIMAGE_OUTPUT" "$ROOT/$BUILDDIR/" + echo "AppImage moved to: $ROOT/$BUILDDIR/$(basename "$APPIMAGE_OUTPUT")" + fi +else + echo "ERROR: AppImage was not created" + echo "Checking for any AppImage files in current directory:" + ls -la *.AppImage 2>/dev/null || echo "No AppImage files found" + exit 1 +fi + +echo "AppImage build completed successfully!"