graalvm / native-build-tools

Native-image plugins for various build tools
https://graalvm.github.io/native-build-tools/
Other
366 stars 57 forks source link

Gradle plugin doesn't support mutation of environment variables #545

Closed dlmiles closed 9 months ago

dlmiles commented 10 months ago

Is your feature request related to a problem? Please describe.

How to mutate $PATH into the sub-process spawned for native building.

275 is related, this feature looks part way there, like it can additively put something into the environment

the API is added NativeImageCompileOptions#getEnvionmentVariable() however it can not mutate anything

Describe the solution you'd like

Documentation example of what maybe a common case of the need to setup vcvars.bat like environment variable mutation for the native build aspect of GraalVM plugin. In particular how to inherit whatever existing environment exists and apply a transformation Closure on a key/value basis.

It appears the API call added by #275 is a isNotPresent() by default and so starts as an empty MapProperty that additively modified the environment with no knowledge of what maybe already configured there. So maybe an additional GraalVM extention helper API is needed environmentVariableMutator to allow such a transform:

graalvmNative {
   binaries {
      main {
        // The mutation function would ideally be the LAST environment modification to occur
        //  so called as late as possible, so it has access to the full set of values that would otherwise be used
         environmentVariableMutator { k, v ->
            if(k == "PATH")
              return customMutationFunction(v)
            else
              return v
         }
      }
   }
}

Describe alternatives you've considered

Using Groovy DSL and metaClass to wrap the getEnvironmentVariables() however it doesn't actually have access to the complete environment variable set (the inherited form) the native-sub-process $GRAALVM_HOME\bin\native-image.cmd will be run with. So it can only mutate from System.getenv(""). Also the API intercept is not called at all, if you never use the environmentVariables.someMethod() construct.

Asking Gradle to consider support globally for toplevel environment mutation via settings.gradle.

Asking IntelliJ to allow the integrated Gradle Daemon to have a configurable environment from the IDE. This solution is not ideal, as it is configuration via GUI, which is not ideal for this use case. As MSVC may require over 30 environment variables to be setup and the PATH mutated to add ~20 path-components. configuring this via GUI and unconfiguring it for another toolchain all via GUI is not ideal. It needs to be able to be managed file/programming based.

Obviously I can:

This option is not feasible as by default I try to limit and pick carefully what I want in my global environment. I want per-project documented configuration (visible to other developers) over exactly what building environment is expected/needed to build the project. This makes diagnostic easier for a 3rd party to work through what is documented and validate their setup.

Obviously I can:

I never tried this as I find the thought or running my IDE under different starting environment a little repulsive, as it will now generate new kinds of interaction issues that only affect me, can not be conveyed to another developer working on the same project.

melix commented 10 months ago

I don't think there's anything specific to the native plugin here, it's just regular Gradle APIs. Should you want to "mutate" environment variables (it's not really mutating, since we're spawning a new process which has different environment variables), you can use the regular Gradle APIs.

For example:

graalvmNative {
    binaries {
        main {
            environmentVariables.put("FOO", providers.environmentVariable("FOO").map {
                // convert the value of the env var to upper case
                it.toUpperCase()
            })
        }
    }
}
melix commented 9 months ago

I'm considering this issue resolved given the example I provided. Feel free to reopen if I misunderstood the requirement.