I'm building a python app which is to pack up as a single executable and work on Windows, MacOS and Linux. Have made a lot of progress and am using a workflow on Github to build using pyinstaller for each OS. Most things are working fine.
Right now I am working on getting an icon onto the executable instead of the default system icon.
I have a spec
file for pyinstaller and I have a section where the icon is mentioned:
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='my_app_name',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon='images/my_icon.ico'
)
This seems to work well for Windows and the output exe file has my icon which is great.
My question is, is there a way to do this for Linux. I know that normally for Linux you need to build a .desktop
file, so I guess the question is three-fold:
or
or
Thanks
OK, so I found a a way to do it - not really in pyinstaller, but it works for me.
I am building my app(s) using Github's Workflow feature - so we have a file called python_build.yml
under /.github/workflows
So, after building the executable with pyinstaller into a single file I have:
- name: Assign artifacts
if: github.event_name == 'release'
uses: knicknic/os-specific-run@v1.0.4
with:
macos: echo "artifact_path=My_app.dmg" >> $GITHUB_ENV
windows: echo "artifact_path=dist/my_app.exe" >> $env:GITHUB_ENV
linux: echo "artifact_path=dist/my_app.deb" >> $GITHUB_ENV
- name: Create DMG app (for MacOS)
if: github.event_name == 'release' && runner.os == 'macOS'
run: |
rm -rf dist/my_app
brew install create-dmg
create-dmg --app-drop-link 100 100 "${{env.artifact_path}}" dist/
- name: Create DEB file for Ubuntu
if: github.event_name == 'release' && runner.os == 'linux'
run: |
cp dist/my_app my-app/usr/share/bin/my_app
rm -rf my-app/usr/share/bin/hold
fakeroot dpkg-deb --build my-app
- name: Sleep while DEB build happens
if: github.event_name == 'release' && runner.os == 'linux'
run: sleep 30s
shell: bash
- name: Copy over DEB to dist folder
if: github.event_name == 'release' && runner.os == 'linux'
run: |
cp my-app.deb dist/my-appi.deb
rm -rf dist/my_app
- name: Add artifacts to release
if: github.event_name == 'release'
uses: ncipollo/release-action@v1.11.2
with:
allowUpdates: true
replacesArtifacts: false
artifacts: ${{env.artifact_path}}
So, there's a couple of important points to add to this. I have saved in my Git repository a small directory structure named my-app. I don't think this is the web page I used but it's similar. Basically a folder named my-app with two folders underneath it : DEBIAN
and usr
. In the DEBIAN
there is one file called control
with something like this in it:
Package: my-app
Version: 1.1-7
Section: Utility
Priority: optional
Architecture: i386
Depends:
Homepage: https://www.ourwebsite.com/
Maintainer: Kibi Hofmann <kibi@ourwebsite.com>
Installed-Size: 31300
Description: Useful app for your use
No dependencies or significant conflicts.
This app is used to do your stuff
Under usr
is a folder share
which has three more folders under it applications
, bin
and icons
.
The bin
folder has (in my Git repository) an empty file called hold
just so that the directory structure is maintained in Git - you can see that the hold
file is deleted and replaced by the compiled binary after pyinstaller is finished. The Desktop file itself is under applications
and looks like this:
[Desktop Entry]
Type=Application
Name=My App
GenericName=My cool app
Comment=Keep your computer happy
Exec=/usr/share/bin/my-app
Icon=myr_icon
Terminal=false
Categories=Application
Hope this helps someone!