我需要在外壳环境中运行Gradle任务,该任务必须在启动任务之前创建。使用commandLine
或executable
是不合适的,因为我需要在与Shell脚本相同的过程中运行任务。最初,我直接在gradlew
内部调用了脚本,但是后来我决定从build.gradle.kts
来获取脚本,并通过gradlew
调用后续任务:
val setupRosEnv by tasks.creating(Exec::class) {
executable = "bash"
args("-c", "source $rosPath/setup.sh && source gradlew myTask")
}
我可以通过从CLI运行./gradlew setupRosEnv
来构建所有内容。除了采购脚本然后运行gradlew
外,还有没有一种方法可以使用Gradle API来实现?当前的解决方案似乎有点笨拙,并且对于依赖于setupRosEnv
的其他任务来说笨拙,因为这将导致无限循环,或者必须进行显式处理以防止任务多次运行。
由于shell脚本本身是由ROS生成的,因此无法将其转换为Gradle或轻松地对其进行解析。
答案 0 :(得分:5)
这取决于您的gradle任务myTask
如何使用环境。如果System.getenv
使用了环境,则可以执行以下步骤。
env.sh
并将所有变量加载到Properties
java.lang.ProcessEnvironment
中的当前进程中以下大致是从Java复制的示例代码,但进行了少量修改,但在gradle构建任务中工作正常。
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());
}
}
我的测试文件env.sh
如下。
export V1="v1 vvv"
export V2='v 2222'
export V3=v33333
如果您的构建任务不是使用System.getenv
来使用环境变量,那么您的黑客方法可能是最好的解决方案。
task myBuildTaskWithSourceEnv(type: Exec) {
commandLine '/bin/bash'
setArgs(['-c', 'source ../env.sh;set;../gradlew :app:assembleDebug'])
}