A là BusyBox behaviour


#1

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 ?


#2

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.


#3

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.


#4

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


#5

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


#6

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


#7

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


#8

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


#9