I need to build an app which reads a file which is external to the Shoes package I'll be distributing it in.
In my app, Dir.pwd points to the temp dir (at least in Windows) where the script is unpacked to be ran. I've been trying to get the directory where the exe is running from, that is, the package I'm distributing.
The app needs to read a file which is distributed besides this package and then write another one in the same directory.
It seems that the Shoes runtime does not set any env variable with this directory either. Any pointers?
nachokb
I run into this problem a while ago and hadn't file a straight solution. I ended up with two workarounds:
At application installation time, put the files at a directory inside of the user home dir ~/ (the home indirection also works in windows)
Package the files together with the shoes generated executable so that it is unzip at the same place as the app and therefore accessible with Dir.pwd
If you find another way, please point it out.
Have you tried something like the following:
DIR = File.expand_path __FILE__
__FILE__ is a reference to the current file and File.expand_path gives you the full system path. Works in my shoes apps :-)
Shoes on!
Tobi
Related
I would like to release my program that wrote in ruby language, I need to pack ruby to appimage file and send it to my client ubuntu PC first.
so I create the folder "ruby-img", then copy my compiled ruby which in "/app/ruby" folder to "ruby-img/app/ruby" and then made a link as "ln -r -s app/ruby/bin/ruby usr/bin/." in "ruby-img" folder.
then I create the desktop file and put png file to "ruby-img", using appimagetool to create ruby-x86_64.AppImage. sadly it can not run, AFAIK that ruby.AppImage still using /app/ruby/lib folder to find some library of ruby but not in "ruby-img/app/ruby/lib" related folder.
so I tried re-compile ruby as --prefix=/tmp/ruby or --prefix=/usr/local/ruby, then copy them to "ruby-img/usr/local/ruby" or "ruby-img/tmp/ruby" then maka some link as above, and repack to AppImage but ruby.AppImage still not working...
any idea can help me ?
AppImages contain of a filesystem with all the content you provide plus a small executable stub that will mount the AppImage filesystem, then run the AppRun executable to be found inside.
With that knowledge it is utmost important that you provide an executable in the root directory along with the .desktop and icon files. I suggest you do not create AppRun yourself. Use the precompiled one from https://github.com/AppImage/AppImageKit/releases/tag/continuous (do not forget to rename it to exactly 'AppRun').
Now when this AppRun gets invoked, it will perform a few checks, cd into the /usr directory and try to start the executable specified in the .desktop file. Check it's source code and you can see that it also sets a few environment variables.
Therefore it is best you provide your entrypoint as /usr/bin/ruby.sh and register that in the desktop file. Remember if /usr/bin/ruby.sh gets called, the current work directory is /usr. So ruby.sh can set further environment variables such as LD_LIBRARY_PATH so that the libraries you configured for /usr/lib will actually be loaded.
With that I hope you have at least as much success as I had.
If I can run an app (built in Go but not really necessary) like so from its own directory:
./some_app
How can I run it from a different directory?
You should just be able to add the path to the app you are trying to run to your command. For example if the app is stored in /Users/example/apps/some_app, then you can just directly run "/Users/example/apps/some_app". You can find which directory your app is sitting in (if you are currently in that directory) with the pwd command.
Say you are in the home directory, and the app is under ~/app/some_app then you can run it with app/some_app
If you want to be able to call it with only some_app, it has to be accessible in your $PATH variable.
In go, when you do go install ./... the executable will end up in $GOPATH/bin/ which is normally part of your path if you have a correct configuration.
Using Shoes (v3.2) to 'Package my App'. Package directory with start script.
Including full copy of shoes.
Opening the packaged app e.g. double click icon, the error console opens:
No such file or directory # rb_sysopen -
/private/var/folders/20/9wqryt1n76s1f0b9mpq500nc0000gp/T/shoes-upload-gui.40507/upload-gui.shy
Visiting the temp directory the shy file is not packaged as part of that directory.
I have tried
putting the shy into the directory then packaging again works, but the package is now twice as big
creating a dummy (zero byte) .shy file in the directory and packaging it. This fails with a different error (seems to be trying to unpack the shy and it fails to open - no surprise)
run the app from command line via shoes-launch e.g /Applications/Shoes.app/Contents/MacOS/shoes-launch rubystart.rb console log error never appears
i have noticed that if run shoes-launch with an additional argument e.g /Applications/Shoes.app/Contents/MacOS/shoes-launch rubystart.rb blah then i get the same No such file or directory # rb_sysopen - blah error for that file
so it seems like the ruby-shoes packager is trying to call shoes-launch with additional command line parameters (its own shy file?)
anyone come across or fixed this e.g. not needed to put the full shy package within itself?
thanks
Ben
I never fixed the shoes packager. I had to manipulate the final xxx.app as follows
remove the .shy file
copy over my ruby files
ensure gems copied over into lib/gems/... (Note i had issues with gems being picked up via rvm anyhow )
edit XXX-launch script removing .shy file with my own ruby file
and it all works. there is no error when opening the app.
conclusion: something in the .shy file perhaps? shoes is being upgraded to shoes 4 anyhow, and all this was on shoes 3.
It seems to happen only when trying to package the whole directory.
(Which also requires creation of a .shy file)
My workaround would be: Package a single file and copy the rest into the bundled application.
I only tryed this on MacOSX and the path inside the App would be "Contents/MacOS/".
After doing this everything worked fine, my app is very simple though.
I've made a simple server based on another thread here on SO: Shutting down python TCPServer by custom handler
I wrapped this up into an .exe using pyinstaller like so:
pyinstaller C:\PATH TO FILE\server.py --distpath=\PATH TO FILE\ --onedir --onefile --noconsole
This works wonderfully on Windows (currently testing on Win 7 x64). I can copy this exe to any folder and get a webserver at that location. I did it this way because I am wrapping this up into a process that would be distributed with another application. The users of this application might not have python installed and they might have a browser that blocks the types of things I would like to serve during the application process.
This should also work on osx, but when I try to wrap the same python script with pyinstaller, instead of serving up the current directory, I get a server at my /Users/Username location and not the directory from where the app was run.
My process to get this to work on both Win and OSX was to begin from the python shell and run the scripts there. This works on both platforms. If I use Terminal, cd to the directory where I want to serve files, and run the python script from there, things work fine. But any attempt I make to wrap the script into something executable leads me back to the same result of serving from /Users/Username, so I'm obviously missing something fundamental of how the wrapping is working. I am assuming it has to do with shell scripting and the script being tied to the current user?
I'd like to continue to use pyinstaller for this process since it would be the same process on Windows and OSX, but I cannot seem to get the resulting app to serve files from the directory from which it is run. Any guidance on what is happening, and how to fix it through pyinstaller (or other method) would be greatly appreciated.
#tallforasmurf on the pyinstaller Github pointed out that I missed something in the pyinstaller docs that is very important:
Adapting to being "frozen"
In some apps it is necessary to learn at run-time whether the app is
running "live" (from source) or "frozen" (part of a bundle). For
example, you might have a configuration file that, when running
"live", is found based on a module's file attribute. That won't
work when the code is bundled.
When your application needs access to a data file, for example a
configuration file or an icon image file, you get the path to the file
with the following code:
import sys
import os
...
if getattr(sys, 'frozen', False):
# we are running in a |PyInstaller| bundle
basedir = sys._MEIPASS
else:
# we are running in a normal Python environment
basedir = os.path.dirname(__file__)
The PyInstaller bootloader adds the attribute frozen to the sys
module. If that attribute exists, your script has been launched by the
bootloader. When that is true, sys._MEIPASS (note the underscore in
the name) contains the path to the folder containing your script and
any other files or folders bundled with it. For one-folder mode this
is the distribution folder. For one-file mode it is the temporary
folder created by the bootloader .
When your program was not started by the bootloader, the standard
Python variable file is the full path to the script now executing,
and os.path.dirname() extracts the path to the folder that contains
it.
I was able to os.chdir(basedir) after going up a few levels past the .app bundle directory and properly serve the files in the same directory as the .app bundle.
I have a finished Ruby project that has the standard structure for a multiple file Ruby program:
project/
lib/ # Files the driver program uses go here.
bin/ # Driver program goes here.
tests/ # Unit tests go here.
What I want to be able to do is type in project into the command line from any directory and have my program run (which means it needs to be in my $PATH). My question is how do I do add a multiple file Ruby project to my PATH so that I can call by name in the terminal? (Or perhaps my approach is wrong, and I should do something else like make it into a Gem? I just don't know what is normally done).
package it as a gem and install that gem. If not and you're on linux then you can set your shebang line to be the right ruby, and chmod to make your script executable, and add your bin dir to your path (or what not).
You could go the quick and dirty route, and write a bash script that calls your main function to run the project, and then stick the bash script over in /usr/bin.