Two questions:
1) According to some AI familiar with Apple, the:
/Applications/program.app/Contents/MacOS/program
program had to be a real DWARF executable, albeit on my old Intel machine, on a simpler application, I can use an actual shell script. Has Apple tightened security or the AI is wrong?
Mmm, this sounds familiar.
For my product, Rush, I include a bunch of submit scripts
written in both python and perl.
I found on macs one could not simply click from the Finder on
a bare script and have it
run properly, show an icon, etc.
What I found was best was to make an Applications subdirectory
in the directory with all
the .py and .pl scripts, and in there, create a separate .app
for each script.
So if the script was foo.py, there was a
./Applications/foo.app bundle, and inside the MacOS
directory was a copy of the same "wrapper binary" described
above, which simply walks up
the path from the executable to find a script of the same name
in the directory containing
the Applications subdir, and then exec'ed that.
This seemed to give the best results, and once the script was
running this way, the icon
remained associated with it, and the script could run
normally.
The wrapper executable does some logic specific to my design
requirements, but basically
the main() does the following:
1) Walks a list of interpreters based on the script's
filename extension, e.g.
// Map filename extensions to interpreter commands
typedef struct {
const char *ext;
const char *cmd;
} Interpreter;
..
int main(..) {
Interpreter interpreter[] = {
// EXT CMD
// --- -----------------------------
{ ".pl", "perl" },
{ ".py", "python" },
{ ".pyw", "python" },
{ 0, 0 }
};
..
// SEARCH FOR PERL AND PYTHON SCRIPTS
for ( int t=0; interpreter[t].ext; t++ )
{
const char *ext = interpreter[t].ext;
const char *cmd = interpreter[t].cmd;
if ( G_debug ) fprintf(stderr, "WORKING ON '%s' (%s):\n", cmd, ext);
string filename;
filename += string(argv[0]); // "/path/to/foo.app/Contents/MacOS/foo"
filename += string(ext); // "/path/to/foo.app/Contents/MacOS/foo.pl"
// TRY TO EXECUTE THE SCRIPT (IF IT EXISTS) IN VARIOUS WAYS
// On success, this will not return; script's interpreter replaces current process
//
Exec(filename.c_str(), ext, cmd);
}
..fail message..
}
The Exec() function above does a bit of work finding the script
by first checking the same directory the wrapper executable is in
(assumes full path in argv[0]) for a .pl/.py script of the same name
as the .app.