Search code examples
javacwindowscygwinshared-libraries

Launching CYGWIN-built executable from Java on Windows 7 fails with "error while loading shared libraries: ?: No such file or directory"


The code in question has worked in more or less the exact same configuration on earlier releases of Windows, however, it is not known to have run on Windows 7 YET! That's what I need to solve now.

Briefly, some C code performs some configuration and security checks before launching a java program, passing some data that would be neigh-into-impossible to do easily in Java. The Java in turn, at the appropriate time launches the same C code which then itself launches a different Java program. The second program launch needs to be completely independent, (think nohup) hence the second launch.

What's happening now is that the C program launches the Java program in the ordinary way, but when the Java tries to launch the C program, it errors out like this:

/cygdrive/c/opt/ST/v3.3/bin/ST.exe: error while loading shared libraries: ?: cannot open shared object file: No such file or directory

Because Windows has been such a bear over the years, the C code is written in the posix environment of Cygwin, but all it really does is ordinary C types of things (nothing about it is unique to Cygwin and, indeed, in the past it has been built with Microsoft's development tools, but that environ is not available at present). The Cygwin environ adds a lot of other great benefits, like command-line management of services (cygrunsrv) and a full-on 'nix-like environment (bash, etc). In fact, because Windows has changed how one launches a program from Java so many times, Cygwin helps standardize the Java launch code. Here's an excerpt:

  if (ClientOS.indexOf("Windows") != -1)
  {
     if (ClientOS.equals("Windows 95"))
     {
        cmd = "command.com /C ";
     } else if (ClientOS.equals("Windows 98"))
     {
        cmd = "command.com /C ";
        //cmd = "cmd.exe /C ";
     } else if (ClientOS.equals("Windows NT"))
     {
        cmd = "cmd.exe /C ";
     } else if (ClientOS.equals("Windows 2000"))
     {
        cmd = "cmd.exe /C ";
     } else if (ClientOS.equals("Windows XP"))
     {
        cmd = "cmd.exe /C ";
     } else {
        cmd = "cmd.exe /C ";
     }
     if (cygwin)
     {
        cmd += Shell+" '"+Command+"'";
     } else {
        cmd += Command;
     }
  } else {
     cmd = Command;
  }

(Yes, the if structure could be better optimized.)

In this case, "Shell" equals:

Shell=C:/cygwin/bin/bash -c

And, there's a test program to ensure the above and supporting code works OK - it runs a bit of shell program and ensures it got back what it thought it should. It says:

Checking the ability to run a program using a shell... Yes, shell programs work fine.

The final contents of cmd look something like this:

cmd.exe /C C:/cygwin/bin/bash -c '/cygdrive/c/opt/ST/v3.3/bin/ST.exe'

WHAT I SUSPECT:

I suspect what's going on is that the Cygwin1.DLL file isn't being found properly. It lives in C:/cygwin/bin/cygwin1.dll

NOTE THAT both the system-level PATH and the Cygwin PATH include the path to the cygwin .dll files. Moving a copy of cygwin1.dll to the bin directory where the target executable lives didn't work either.

Would LD_LIBRARY_PATH lend any help here? If so, any idea how it is to be set?

Other ideas?

Thanks.


Solution

  • C:/cygwin/bin/bash -c '/cygdrive/c/opt/ST/v3.3/bin/ST.exe'
    

    This won't work because your working directory is where you reside when you executed this command. You will have to copy the cygwin dependent dlls to the directory you execute this from. Othwerwise, you will have to place the cygwin bin directory in your system PATH variable, not sure you want to do that, can cause dll hell.

    Also, if you're using anything in your profile, you need to add --login parameter to bash:

    bash --login -c
    

    Also, print the final command out at the end, before you spawn the process:

    printf('%s\n',cmd)
    

    Just to be sure it's exactly what you want.

    You may also run the program with strace, if you're unsure about the dlls being referenced.