A là BusyBox behaviour

Hi,

I have more and more applications using Juce running at the same time, each one using its own static blob of binary juce classpath.

As I can’t get Juce to build as a shared lib under linux (is it even possible, and if yes, how ?), I was wondering if a behaviour à la Busybox would be easy to implement.

Basically, BusyBox compiles all functions (“ls”, “cp”, “more”, etc…) in a single binary which is symbolic linked and use the argv[0] to call the appropriate “main”.

For example, a “ls /usr/bin” in a busybox system gives:

ls => /usr/bin/busybox
cp => /usr/bin/busybox 

etc…

Then, in the busybox binary, you’ll have a code like this:

int ls_main(int argc, char ** argv) { ...}
int cp_main(int argc, char ** argv) { ...}
int main(...)
{
    if argv[0] == "cp" return cp_main(argc, argv);
    if argv[0] == "ls" return ls_main(...etc...

I was wondering what Juce does of its argv[0], is it possible to get it in the JUCEApplication ?

Busyboxes are a neat trick.

I think juce throws the argv[0] away, because it’s not necessarily always available on all platforms - I think on windows it might not be there (and it’d be hard to implement a busybox on windows anyway because of the lack of proper file links). Of course if you’re doing a command line app with your own main() then it’s no problem.

What are the implication of modifying the “JUCEApplication::getApplicationName()” method ?
It’s not used in any demo.

That is, if I change this part, would you include it in baseboard Juce ?

Or maybe it’s better to add a “getSymbolicName” method in there, that returns “GetModuleName(NULL)” under Windows, and argv[0] under linux and OSX.

The File::currentExecutableFile might already give you that information…? If not, the best place for it would probably be another SpecialLocationType value for it.

currentExecutableFile returns dladdr.filename of the main segment of code, that is, the actual binary file.

Looking at JUCEApplication::main code, there is:

int JUCEApplication::main (int argc, char* argv[],
                           JUCEApplication* const newApp)
{
#if JUCE_IPHONE
    const ScopedAutoReleasePool pool;
    return juce_IPhoneMain (argc, argv, newApp);
#else

#if JUCE_MAC
    const ScopedAutoReleasePool pool;
#endif

    String cmd;
    for (int i = 1; i < argc; ++i)
        cmd << String::fromUTF8 ((const uint8*) argv[i]) << T(' ');

    return JUCEApplication::main (cmd, newApp);
#endif
}

So, the argv[0] is ignored. What about saving it in a extern String, that’ll be accessed in File::getSpecialLocation ?
Something like:

juce::String invocationName = juce::String::empty;

int JUCEApplication::main (int argc, char* argv[],
                           JUCEApplication* const newApp)
{
#if JUCE_IPHONE
    const ScopedAutoReleasePool pool;
    return juce_IPhoneMain (argc, argv, newApp);
#else

#if JUCE_MAC
    const ScopedAutoReleasePool pool;
#endif

    invocationName = String::fromUTF8((const uint8*) argv[0]);

    String cmd;
    for (int i = 1; i < argc; ++i)
        cmd << String::fromUTF8 ((const uint8*) argv[i]) << T(' ');

    return JUCEApplication::main (cmd, newApp);
#endif
}

// In File getSpecialLocation (posix)
extern juce::String invocationName;
const File File::getSpecialLocation (const SpecialLocationType type)
{
    switch (type)
    {
   [...]
    case InvocationName:
          return invocationName;
    break;
[...]

For windows, it might be even simpler, as it would only require adding a case InvocationName above case currentExecutableName

I’ve made a patch, if you’re interested, I can send it to you by mail.

Seems like a good idea, I’ll get that sorted for you.

Ok, I’ve updated my version (not without pain), and it’s working perfectly.
Thank you very much.