Closed nartamonov closed 2 years ago
This reminds me a bit of a problem I had with ocra ( https://github.com/larsch/ocra ) in ruby. I could bundle things on windows, but I also was using local yaml files (.yml) which then could not be found since they were not part of the ocra bundle. Made me re-consider depending on .yml files and provide sane defaults in the event no .yml file could be found.
So while my above description is not fitting 1:1 to the threadstarter's rationale given ("might need to calculate the path to the target program relative to himself"), I very much agree with the underlying perception of an issue in regards to paths that may be different or unable to be queried.
I've done it like this before:
import java.net.URISyntaxException;
import java.nio.file.Path;
public class ExePath {
public static void main(String[] args) throws URISyntaxException {
Path path = Path.of(
ExePath.class.getProtectionDomain()
.getCodeSource()
.getLocation()
.toURI()
).getParent();
System.out.println(path);
}
}
I know it works on windows, don't know about other platforms. But I don't see why it wouldn't work the same way.
This gives you the folder in which the exe is located, no matter where you call it from. It only works in native-image, as the getLocation
call returns null
when running in jvm.
@kkriske thank you for the advice! I tested that approach on Windows 10 and Linux with GraalVM 21.3.0 and JVM11. Works fine in both cases! I suppose it will work on MacOS too.
I think we can close the issue but it would be helpful for community if the trick will be documented in native-image
user manual. I can try to propose a PR if the devs tell where the sources of docs are.
@nartamonov I did a bit more searching and found this one as part of the native-image SDK: https://github.com/oracle/graal/blob/dff76ed3958669b80c6d20c881fcd5eb448c633c/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/ProcessProperties.java#L59
The ProtectionDomain workaround ends up delegating to that same call in native-image, so you should probably just use it directly.
Edit: The implementation does actually call GetModuleFileName
for windows, uses /proc/self/exe
on linux and calls NSGetExecutablePath
on MacOS.
@kkriske thanks again, I tried and it works fine! 😃 Turns out there is a whole NativeImage-specific API in the package org.graalvm.nativeimage. Didn't know it. So I suppose it completely settles the issue.
Feature request
Is your feature request related to a problem? Please describe. Native-image could be used to replace scripts (for example, .sh or .cmd) for various system tasks: launchers, backups, utilities, etc. Often such scripts need a way to find out their own directory in order to calculate path to some adjacent directories. For example if we write a launcher that pefrorms some preparatory tasks and then starts another program, in order to start that program launcher might need to calculate the path to the target program relative to himself.
Describe the solution you'd like. Native-image should implement some way to provide the path of running executable module. Ideally that way should be cross-platform.
For example, on Win32 it can use GetModuleFileName while on Linux it can use something like
readlink /proc/self/exe
.Describe who do you think will benefit the most. The feature appears to be the most useful for the users of GraalVM which use it to implement system scripts and utilities: developers, system administrators, maybe devops.
Describe alternatives you've considered. I can't find an alternative to the feature. Of course we can use JNI to call Win32 API but it's too much work for simple purposes like writing a script.