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

Add MacOS bundle distribution #1276

Merged
merged 14 commits into from
Feb 4, 2023
98 changes: 98 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
name: Build

on:
push:
tags:
- '*'

jobs:
build:
strategy:
fail-fast: false
matrix:
include:
- os: macos-12
name: macos
qt_ver: 5
qt_host: mac
qt_version: '5.15.2'
qt_modules: ''
qt_tools: ''

runs-on: ${{ matrix.os }}

steps:
##
# PREPARE
##
- name: Checkout
uses: actions/checkout@v3
with:
submodules: 'true'

- name: Set short version
shell: bash
run: |
ver_short=`git rev-parse --short HEAD`
ver_novelwriter=`awk '/^__version__/{print substr($NF,2,length($NF)-2)}' novelwriter/__init__.py`
echo "VERSION=$ver_novelwriter" >> $GITHUB_ENV
echo "VERSION_SHORT=$ver_short" >> $GITHUB_ENV

- name: Install Qt (Linux)
if: runner.os == 'Linux' && matrix.qt_ver != 6
run: |
sudo apt-get -y install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5

- name: Install Qt (macOS, AppImage & Windows MSVC)
if: runner.os == 'Linux' && matrix.qt_ver == 6 || runner.os == 'macOS' || (runner.os == 'Windows' && matrix.msystem == '')
uses: jurplel/install-qt-action@v3
with:
version: ${{ matrix.qt_version }}
host: ${{ matrix.qt_host }}
target: 'desktop'
arch: ${{ matrix.qt_arch }}
modules: ${{ matrix.qt_modules }}
tools: ${{ matrix.qt_tools }}
cache: true

- name: Setup TeX Live
uses: teatimeguest/setup-texlive-action@v2
with:
packages: >-
scheme-basic
collection-latexextra
latexmk
tex-gyre

- name: Install Dependencies (macOS)
if: runner.os == 'macOS'
run: |
pip3 install sphinx

##
# BUILD
##

- name: Build (macOS)
if: runner.os == 'macOS'
run: |
./setup/macos/build.sh

##
# UPLOAD BUILDS
##

- name: Upload binary zip (macOS)
if: runner.os == 'macOS'
uses: actions/upload-artifact@v3
with:
name: novelWriter-${{ env.VERSION }}-${{ matrix.name }}.app.zip
path: dist_macos/novelWriter-${{ env.VERSION }}.app.zip

- name: Upload dmg (macOS)
if: runner.os == 'macOS'
uses: actions/upload-artifact@v3
with:
name: novelWriter-${{ env.VERSION }}-${{ matrix.name }}.dmg
path: dist_macos/novelWriter-${{ env.VERSION }}.dmg

120 changes: 120 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,25 @@ def getValue(theString):

return numVers, hexVers, relDate

def extractCopyright():
"""Extract the novelWriter copyright notice without having to import
anything else from the main package.
"""
copyright = "Unknown"
initFile = os.path.join("novelwriter", "__init__.py")
try:
with open(initFile, mode="r", encoding="utf-8") as inFile:
for aLine in inFile:
if aLine.startswith("__copyright__"):
copyright = (aLine).partition("=")[2].strip().strip('"')
except Exception as exc:
print("Could not read file: %s" % initFile)
print(str(exc))

print("novelWriter copyright: %s " % (copyright))

return copyright


def compactVersion(numVers):
"""Make the version number more compact."""
Expand Down Expand Up @@ -395,6 +414,102 @@ def buildQtI18nTS(sysArgs):

return

##
# Generage MacOS PList
##

def genMacOSPlist():

# Set Up Folder
# =============

numVers, _, _ = extractVersion()
pkgVers = compactVersion(numVers)

outDir = "setup/macos"

macosBundleName = "novelWriter"
macosBundleExeName = "novelWriter"
macosBundleInfo = "novelWriter: A markdown-like text editor for planning and writing novels."
macosBundleIcon = "novelwriter.icns"
macosBundleIdent = "io.novelwriter.novelWriter"
macosBundleSVers = pkgVers
macosBundleVers = numVers
macosBundleCopyright = extractCopyright()

# These keys are no longer used but are present for compatability
macosBundleVersMajor, macosBundleVersMinor, _ = pkgVers.split(".")


plistXML = (
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
"<plist version=\"1.0\">\n"
"<dict>\n"
"<key>NSPrincipalClass</key>\n"
"<string>NSApplication</string>\n"
"<key>NSHighResolutionCapable</key>\n"
"<string>True</string>\n"
"<key>CFBundleDevelopmentRegion</key>\n"
"<string>English</string>\n"
"<key>CFBundleExecutable</key>\n"
f"<string>{macosBundleExeName}</string>\n"
"<key>CFBundleGetInfoString</key>\n"
f"<string>{macosBundleInfo}</string>\n"
"<key>CFBundleIconFile</key>\n"
f"<string>{macosBundleIcon}</string>\n"
"<key>CFBundleIdentifier</key>\n"
f"<string>{macosBundleIdent}</string>\n"
"<key>CFBundleName</key>\n"
f"<string>{macosBundleName}</string>\n"
"<key>CFBundleDisplayName</key>\n"
f"<string>{macosBundleName}</string>\n"
"<key>CFBundleInfoDictionaryVersion</key>\n"
"<string>6.0</string>\n"
"<key>CFBundleShortVersionString</key>\n"
f"<string>{macosBundleSVers}</string>\n"
"<key>CFBundleSignature</key>\n"
"<string>????</string>\n"
"<key>CFBundleVersion</key>\n"
f"<string>{macosBundleVers}</string>\n"
"<key>CFBundlePackageType</key>\n"
"<string>APPL</string>\n"
"<key>NSHumanReadableCopyright</key>\n"
f"<string>{macosBundleCopyright}</string>\n"
"<key>IFMajorVersion</key>\n"
f"<integer>{macosBundleVersMajor}</integer>\n"
"<key>IFMinorVersion</key>\n"
f"<integer>{macosBundleVersMinor}</integer>\n"
"<key>CFBundleDocumentTypes</key>\n"
" <array>\n"
" <dict>\n"
" <key>CFBundleTypeExtensions</key>\n"
" <array>\n"
" <string>nwx</string>\n"
" </array>\n"
" <key>CFBundleTypeName</key>\n"
" <string>novelWriter Project</string>\n"
" <key>CFBundleTypeOSTypes</key>\n"
" <array>\n"
" <string>TEXT</string>\n"
" <string>utxt</string>\n"
" <string>TUTX</string>\n"
" <string>****</string>\n"
" </array>\n"
" <key>CFBundleTypeRole</key>\n"
" <string>Viewer</string>\n"
" <key>LSHandlerRank</key>\n"
" <string>Alternate</string>\n"
" </dict>\n"
" </array>\n"
"</dict>\n"
"</plist>\n"
)

print(f"Writing Info.plist to {outDir}/Info.plist")

writeFile(f"{outDir}/Info.plist", plistXML)


##
# Sample Project ZIP File Builder (sample)
Expand Down Expand Up @@ -1862,6 +1977,7 @@ def winUninstall():
" The files to be updated must be provided as arguments.",
" qtlrelease Build the language files for internationalisation.",
" clean-assets Delete assets built by manual, sample and qtlrelease.",
" gen-plist Generates an Info.plist for use in a MacOS Bundle",
"",
"Python Packaging:",
"",
Expand Down Expand Up @@ -1943,6 +2059,10 @@ def winUninstall():
if "clean-assets" in sys.argv:
sys.argv.remove("clean-assets")
cleanBuiltAssets()

if "gen-plist" in sys.argv:
sys.argv.remove("gen-plist")
genMacOSPlist()

# Python Packaging
# ================
Expand Down
10 changes: 10 additions & 0 deletions setup/macos/App.entitlements
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
</dict>
</plist>
Loading