I need to run a Gradle task inside a shell environment, which must be created before the task is launched. Using commandLine
or executable
is not appropriate, as I need to run the task in the same process as the shell script. Originally, I called the script directly inside gradlew
, but later I decided to source it from build.gradle.kts
and call subsequent tasks through gradlew
:
val setupRosEnv by tasks.creating(Exec::class) {
executable = "bash"
args("-c", "source $rosPath/setup.sh && source gradlew myTask")
}
I can build everything by running ./gradlew setupRosEnv
from the CLI. Besides sourcing the script then running gradlew
, is there a way to achieve this using the Gradle API? The current solution seems a bit hacky, and is clunky for other tasks to depend on setupRosEnv
, as this will lead to an infinite loop or must be explicitly handled to prevent tasks being run more than once.
As the shell script itself is generated by ROS, it cannot be translated to Gradle or easily parsed.
If you are using an IDE, go to run, edit configurations, gradle, select gradle task and update the environment variables. See the picture below. Alternatively, if you are executing gradle commands using terminal, just type 'export KEY=VALUE', and your job is done. Save this answer.
In File Explorer right-click on the This PC (or Computer ) icon, then click Properties -> Advanced System Settings -> Environmental Variables . Under System Variables select Path , then click Edit . Add an entry for C:\Gradle\gradle-7.5.1\bin . Click OK to save.
Gradle uses whatever JDK it finds in your path. Alternatively, you can set the JAVA_HOME environment variable to point to the installation directory of the desired JDK. See the full compatibility notes for Java, Groovy, Kotlin and Android.
It depends how your gradle task myTask
use the environment. If it use the environment by System.getenv
, you can do use the following step.
env.sh
and load all variables into Properties
java.lang.ProcessEnvironment
by reflectionBelow is just roughly an example code copied from Java with minor modification, but it works fine in gradle build task.
task myEnvironInjected << {
println("task with injected enviroment")
}
task myBuildTask(dependsOn: myEnvironInjected) << {
def v1 = System.getenv("V1")
println("my build task running V1=${v1}")
}
myEnvironInjected.doFirst {
final Map<String, String> bashEnvMap = new HashMap<>();
try {
// a simple simulation of bash command source env.sh
// use it carefully
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream
("/path/to/env.sh")));
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
String line;
while ((line = reader.readLine()) != null) {
if (line.length() > 0 && line.startsWith("export ")) {
String newLine = line.trim().replaceFirst("^export ", "");
// remove single or double quote from the value if it has
int quoteIndex = newLine.indexOf('=')+1;
if (quoteIndex < newLine.length() && (newLine.charAt(quoteIndex) == ('"' as char) ||
newLine.charAt(quoteIndex) == ('\'' as char))) {
newLine = newLine.substring(0, quoteIndex) + newLine.substring(quoteIndex+1, newLine.length()-1);
}
writer.write(newLine);
writer.newLine();
}
}
writer.flush();
writer.close();
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
Properties properties = new Properties();
properties.load(inputStream);
for (Map.Entry<Object, Object> entry : properties.entrySet()) {
bashEnvMap.put(((String) entry.getKey()), ((String) entry.getValue()));
}
outputStream.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
for (Class<?> aClass : Collections.class.getDeclaredClasses()) {
if ("java.util.Collections\$UnmodifiableMap".equals(aClass.getName())) {
try {
Field mapField = aClass.getDeclaredField("m");
mapField.setAccessible(true);
Object mapObject = mapField.get(System.getenv());
Map<String, String> environMap = ((Map<String, String>) mapObject);
environMap.putAll(bashEnvMap);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
for (Map.Entry<String, String> envEntry : System.getenv().entrySet()) {
System.out.println(envEntry.getKey() + "=" + envEntry.getValue());
}
}
My test file env.sh
looks like this.
export V1="v1 vvv"
export V2='v 2222'
export V3=v33333
If your build task use the environment variables not by System.getenv
, your hacking method might be the best solution.
task myBuildTaskWithSourceEnv(type: Exec) {
commandLine '/bin/bash'
setArgs(['-c', 'source ../env.sh;set;../gradlew :app:assembleDebug'])
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With