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

Update build scripts #1829

Merged
merged 16 commits into from
Apr 21, 2024
Merged
58 changes: 45 additions & 13 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
- name: Python Setup
uses: actions/setup-python@v5
with:
python-version: "3.11"
python-version: "3.12"
architecture: x64

- name: Install Packages (apt)
Expand All @@ -35,15 +35,14 @@ jobs:
novelwriter/assets/manual.pdf
novelwriter/assets/i18n/*.qm
if-no-files-found: error
retention-days: 1
retention-days: 14

buildLinux:
needs: buildAssets
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11"]
linux-tag: ["manylinux_2_24_x86_64", "manylinux_2_28_x86_64"]
env:
PYTHON_VERSION: "3.12"
LINUX_TAG: "manylinux_2_28_x86_64"
steps:
- name: Python Setup
uses: actions/setup-python@v5
Expand All @@ -64,19 +63,52 @@ jobs:
path: novelwriter/assets

- name: Build AppImage
run: python pkgutils.py build-appimage --linux-tag ${{ matrix.linux-tag }} --python-version ${{ matrix.python-version }}
run: python pkgutils.py build-appimage --linux-tag $LINUX_TAG --python-version $PYTHON_VERSION

- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: AppImage-${{ matrix.python-version }}-${{ matrix.linux-tag }}
name: Linux-AppImage
path: dist_appimage
if-no-files-found: error
retention-days: 1
retention-days: 14

buildMac:
buildMac-AMD64:
needs: buildAssets
# Stay on macos-12 due to https://github.com/create-dmg/create-dmg/issues/143
runs-on: macos-12
env:
PYTHON_VERSION: "3.12"
PACKAGE_ARCH: x86_64
MINICONDA_ARCH: x86_64
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Download Artifacts
uses: actions/download-artifact@v4
with:
name: nw-assets
path: novelwriter/assets

- name: Build App Bundle
run: ./setup/macos/build.sh $PYTHON_VERSION $PACKAGE_ARCH $MINICONDA_ARCH

- name: Upload DMG
uses: actions/upload-artifact@v4
with:
name: MacOS-AMD64-DMG
path: dist_macos
if-no-files-found: error
retention-days: 14

buildMac-M1:
needs: buildAssets
runs-on: macos-14
env:
PYTHON_VERSION: "3.12"
PACKAGE_ARCH: aarch64
MINICONDA_ARCH: arm64
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All @@ -88,12 +120,12 @@ jobs:
path: novelwriter/assets

- name: Build App Bundle
run: ./setup/macos/build.sh
run: ./setup/macos/build.sh $PYTHON_VERSION $PACKAGE_ARCH $MINICONDA_ARCH

- name: Upload DMG
uses: actions/upload-artifact@v4
with:
name: MacOS-DMG
name: MacOS-M1-DMG
path: dist_macos
if-no-files-found: error
retention-days: 1
retention-days: 14
13 changes: 5 additions & 8 deletions novelwriter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from PyQt5.QtWidgets import QApplication, QErrorMessage

from novelwriter.config import Config
from novelwriter.error import exceptionHandler, logException
from novelwriter.error import exceptionHandler
from novelwriter.shared import SharedData

if TYPE_CHECKING: # pragma: no cover
Expand Down Expand Up @@ -198,24 +198,21 @@ def main(sysArgs: list | None = None) -> GuiMain | None:
# Finish initialising config
CONFIG.initConfig(confPath, dataPath)

if CONFIG.osDarwin:
if sys.platform == "darwin":
try:
from Foundation import NSBundle # type: ignore
bundle = NSBundle.mainBundle()
info = bundle.localizedInfoDictionary() or bundle.infoDictionary()
info["CFBundleName"] = "novelWriter"
except Exception:
logger.error("Failed to set application name")
logException()

elif CONFIG.osWindows:
pass # Quietly ignore error
elif sys.platform == "win32":
try:
import ctypes
appID = f"io.novelwriter.{__version__}"
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(appID) # type: ignore
except Exception:
logger.error("Failed to set application name")
logException()
pass # Quietly ignore error

# Import GUI (after dependency checks), and launch
from novelwriter.guimain import GuiMain
Expand Down
9 changes: 1 addition & 8 deletions pkgutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1073,15 +1073,8 @@ def makeAppImage(sysArgs: list[str]) -> list[str]:
print("")
sys.exit(1)

linuxLabel = ""
if not linuxTag.startswith("manylinux_2_28"):
linuxLabel = "-oldlinux"
if not linuxTag.endswith("x86_64"):
# manylinux_2_28 only comes in 64 bit, so this one only applies to older images
linuxLabel += "-32bit"

bldFile = glob.glob(f"{bldDir}/*.AppImage")[0]
outFile = f"{bldDir}/novelWriter-{pkgVers}{linuxLabel}.AppImage"
outFile = f"{bldDir}/novelWriter-{pkgVers}.AppImage"
os.rename(bldFile, outFile)
shaFile = makeCheckSum(os.path.basename(outFile), cwd=bldDir)

Expand Down
31 changes: 22 additions & 9 deletions setup/macos/build.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
#! /bin/bash

if [[ -z "$1" || -z "$2" || -z "$3" ]]; then
echo "Not enouch input arguments"
exit 1
fi

PYTHON="$1"
ARCH="$2"
CONDA="$3"

echo "Python Version: $PYTHON"
echo "Architecture: $ARCH"
echo "Miniconda Architecture: $CONDA"

# Use RAM disk if possible
if [ -d /dev/shm ]; then
TEMP_BASE=/dev/shm
Expand Down Expand Up @@ -76,13 +89,13 @@ pushd "$BUILD_DIR"/ || exit 1
# --- Create Miniconda Env ---------------------------------------------------------------------- #

echo "Downloading Miniconda ..."
curl -LO https://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-x86_64.sh
bash Miniconda3-latest-MacOSX-x86_64.sh -b -p ~/miniconda -f
rm Miniconda3-latest-MacOSX-x86_64.sh
curl -LO https://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-$CONDA.sh
bash Miniconda3-latest-MacOSX-$CONDA.sh -b -p ~/miniconda -f
rm Miniconda3-latest-MacOSX-$CONDA.sh
export PATH="$HOME/miniconda/bin:$PATH"

echo "Creating Conda env ..."
conda create -n novelWriter -c conda-forge python=3.11 --yes
conda create -n novelWriter -c conda-forge python=$PYTHON --yes
source activate novelWriter

echo "Installing dictionaries ..."
Expand Down Expand Up @@ -123,10 +136,10 @@ cp $SRC_DIR/setup/macos/novelwriter.icns novelWriter.app/Contents/Resources/

# Create entry script
echo "Creating entry script ..."
cat > novelWriter.app/Contents/MacOS/novelWriter <<\EOF
cat > novelWriter.app/Contents/MacOS/novelWriter << EOF
#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
$DIR/../Resources/bin/python -sE $DIR/../Resources/novelWriter/novelWriter.py $@
DIR="\$( cd "\$( dirname "\${BASH_SOURCE[0]}" )" && pwd )"
\$DIR/../Resources/bin/python -sE \$DIR/../Resources/novelWriter/novelWriter.py \$@
EOF

# Make it executable
Expand Down Expand Up @@ -173,8 +186,8 @@ brew install create-dmg
create-dmg --volname "novelWriter $VERSION" --volicon $SRC_DIR/setup/macos/novelwriter.icns \
--window-pos 200 120 --window-size 800 400 --icon-size 100 \
--icon novelWriter.app 200 190 --hide-extension novelWriter.app \
--app-drop-link 600 185 $RLS_DIR/novelWriter-"${VERSION}"-amd64.dmg "$BUILD_DIR"/
--app-drop-link 600 185 $RLS_DIR/novelWriter-"${VERSION}"-$ARCH.dmg "$BUILD_DIR"/

pushd $RLS_DIR || exit 1
shasum -a 256 novelWriter-"${VERSION}"-amd64.dmg | tee novelWriter-"${VERSION}"-amd64.dmg.sha256
shasum -a 256 novelWriter-"${VERSION}"-$ARCH.dmg | tee novelWriter-"${VERSION}"-$ARCH.dmg.sha256
popd || exit 1
10 changes: 3 additions & 7 deletions tests/test_base/test_base_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ def testBaseInit_Launch(caplog, monkeypatch, fncPath):
mp.setitem(sys.modules, "Foundation", None)
nwGUI = main(["--testmode", f"--config={fncPath}", f"--data={fncPath}"])
assert isinstance(nwGUI, MockGuiMain)
assert "Failed" in caplog.text

CONFIG.osDarwin = osDarwin

Expand All @@ -58,9 +57,6 @@ def testBaseInit_Launch(caplog, monkeypatch, fncPath):
mp.setitem(sys.modules, "ctypes", None)
nwGUI = main(["--testmode", f"--config={fncPath}", f"--data={fncPath}"])
assert isinstance(nwGUI, MockGuiMain)
if not sys.platform.startswith("darwin"):
# For some reason, the test doesn't work on macOS
assert "Failed" in caplog.text

CONFIG.osWindows = osWindows

Expand Down Expand Up @@ -161,9 +157,9 @@ def testBaseInit_Imports(caplog, monkeypatch, fncPath):
["--testmode", f"--config={fncPath}", f"--data={fncPath}"]
)

assert ex.value.code & 4 == 4 # Python version not satisfied
assert ex.value.code & 8 == 8 # Qt version not satisfied
assert ex.value.code & 16 == 16 # PyQt version not satisfied
assert ex.value.code & 4 == 4 # Python version not satisfied # type: ignore
assert ex.value.code & 8 == 8 # Qt version not satisfied # type: ignore
assert ex.value.code & 16 == 16 # PyQt version not satisfied # type: ignore

assert "At least Python" in caplog.messages[0]
assert "At least Qt5" in caplog.messages[1]
Expand Down