Closed caver456 closed 2 years ago
making a .pkg - use built-in pkgbuild command line tool
http://thegreyblog.blogspot.com/2014/06/os-x-creating-packages-from-command_2.html
using "mdfind kMDItemKind == 'Application'" to get the list of what's installed, rather than just listing the /Applications folder. Wrapping it like so:
def getDarwinApps():
return str(subprocess.run(['mdfind',"kMDItemKind == 'Application'"],capture_output=True).stdout).split('\\n')
and then calling it like so:
gpsbabel_appdir=str([x for x in getDarwinApps() if 'GPSBabel' in x][0]) # sometimes it returns bytes!
if gpsbabel_appdir:
print('gpsbabel_appdir:'+str(gpsbabel_appdir))
gpsbabel_exe=os.path.join(gpsbabel_appdir,'Contents','MacOS','gpsbabel')
sometimes, the result is a bytes array which causes failure:
gpsbabel_appdir:b'/Applications/GPSBabelFE.app
checking for: b'/Applications/GPSBabelFE.app/Contents/MacOS/gpsbabel
g1:[True, None]
2. GPSBabel : FAILED
but sometimes it's a string which passes:
gpsbabel_appdir:/Applications/GPSBabelFE.app
checking for: /Applications/GPSBabelFE.app/Contents/MacOS/gpsbabel
g1:[True, '/Applications/GPSBabelFE.app/Contents/MacOS/gpsbabel']
2. GPSBabel : previous installation verified
Can't figure out a pattern just yet. Would be best to figure out why this happens and resolve it; otherwise, the parser could just be made to deal with either string or bytes array (the str() in the code above obviously does not work)
subprocess return is bytes; that's where the decoding has to happen. After that, escaping the \ in the split is not needed. This fixed it (note this fix does not close this issue):
def getDarwinApps():
return str(subprocess.run(['mdfind',"kMDItemKind == 'Application'"],capture_output=True).stdout,'utf-8').split('\n')
so close... used pkgbuild (by sourcing installer/build_mac which assembles the files then calls pkgbuild). The pkg installer failed, showing a dialog saying that python3 isn't installed. Turns out macs ship with python2 rather than python3.
So, a few options to explore:
Good progress with pyinstaller:
Since support files are needed (gpsio-host.ini, gpsio-host-macfile.py, gpsio-osa1_template.txt, gpsio-osa2.txt) you need to build to a dist directory i.e. don't use the onefile option.
This is proof-of-concept - not polished.
Then it works!
gpsio-host.spec is generated initially from pyinstaller gpsio-host.py, then edited to include the support files:
datas=[('gpsio-host.ini', '.'),('gpsio-osa1_template.txt','.'),('gpsio-osa2.txt','.')],
This also causes permission request popups that are a bit more clear, and gpsio-host shows up as its own entry in System Preferences --> Security and Privacy --> Files and Folders --> Privacy --> Files and Folders which is great.
This brings up the question - can we maybe get rid of the osascripts, such that gpsio-host will ask for access to remote drives with a popup???
promising: write a simple python script (test.py) to do os.listdir on the removable drive, then turn that into an executable with pyinstaller (no supporting files - just 'pyinstaller test.py') - then point the extension manifest to that executable. On the first attempt, it asks:
and also asks:
and it shows up in the security list:
So - give it a shot - try commenting out the entire 'if darwin' clause in gpsio-host.py which invokes the osascripts etc. That would win.
The main possibility for failure here is if an antivirus flags the pyinstaller result as a threat in the same manner as what it does for Windows.
Guess what: virustotal.com shows ZERO out of 58 virus scan programs that flagged gpsio-host (executable) as a threat. And ZERO out of 59 for test (executable). Very interesting!
This all appears to work nicely. Pushed a new version of the mac installer, the test of that installer on another mac should happen in the next few days.
Other user's test failed again with the same symptom as the 'so close...' comment above - a dialog pops up during installation saying that python3 needs to be installed. Duh - the popup shows during installation, meaning that it's the postinstall script that needs python3. The work between then and now addressed the fact that the >host< needs its own python3 - which is true and important and resolved above with pyinstaller, so it wasn't wasted work - but the immediate symptom was that the >installer< needs python3. Duh.
The windows installer already accounts for this, running the embeddable python interpreter provided by the NSIS self-extracting-archive, since the NSIS installer calls this line for each installation stage:
!define py "$INSTDIR/host/dist/python.exe $INSTDIR/install-gpsio.py"
So we need to see if we can do something similar for mac.
Back-porting to python2 is an option but that would completely invalidate the current cross-platform installer script: no sense in back-porting the Windows install script to python2 since it's already running with the embeddable python3.
So, maybe try pyinstaller onefile to make the executable, and use that as the postinstall script?
pyinstaller --onefile install-gpsio.py (then incorporating the resulting executable as the pkgbuild postinstall script) did the trick. The other user's test worked out. Closing this ticket. Note that the other user's test revealed a new issue #36.
Wait to start this issue until the Windows installer is done.