Сделать переменные окружения доступными для задачи Gradle - PullRequest
0 голосов
/ 23 октября 2018

Мне нужно запустить задачу Gradle в среде оболочки, которая должна быть создана до запуска задачи.Использование commandLine или executable не подходит, так как мне нужно запустить задачу в том же процессе, что и сценарий оболочки.Первоначально я вызывал скрипт прямо внутри gradlew, но позже я решил получить его из build.gradle.kts и вызывать последующие задачи через gradlew:

val setupRosEnv by tasks.creating(Exec::class) {
    executable = "bash"

    args("-c", "source $rosPath/setup.sh && source gradlew myTask")
}

Я могу собрать все, запустив ./gradlew setupRosEnvиз CLI.Помимо поиска сценария, запускающего gradlew, есть ли способ добиться этого с помощью Gradle API?Текущее решение кажется немного хакерским и неуклюжим, поскольку другие задачи зависят от setupRosEnv, поскольку это приведет к бесконечному циклу или должно быть явно обработано, чтобы предотвратить запуск задач более одного раза.

Каксам скрипт оболочки генерируется ROS, его нельзя преобразовать в Gradle или легко разобрать.

1 Ответ

0 голосов
/ 23 октября 2018

Зависит от того, как ваша задача Gradle myTask использует среду.Если он использует среду по System.getenv, вы можете выполнить следующий шаг:

  1. проанализировать файл окружения bash env.sh и загрузить все переменные в Properties
  2. appendпеременные окружения для текущего процесса в java.lang.ProcessEnvironment с помощью отражения
  3. используют внедренные переменные окружения в вашей задаче сборки

Ниже приведен примерный код, скопированный из 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'])
}
...