Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/399.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Windows上构建Java应用程序时,如何在编译时访问环境变量?_Java_Environment Variables_Javac - Fatal编程技术网

在Windows上构建Java应用程序时,如何在编译时访问环境变量?

在Windows上构建Java应用程序时,如何在编译时访问环境变量?,java,environment-variables,javac,Java,Environment Variables,Javac,我有一个适用于Windows的Java应用程序。我希望Java应用程序在运行时在磁盘上创建一个包含版本号的文件名的新文件。当Java应用程序由my Azure Dev Ops(ADO)管道构建时,该版本号可作为OS环境变量使用。ADO管道使用CMake(运行javac命令)构建我的代码 解决方案是使用Maven作为构建系统。我在我的构建系统中找不到同样的方法,它不使用Maven和pom.xml。在使用javac命令行时,有没有办法做到这一点 谢谢 达伦 CMake在许多平台上运行 不过,mave

我有一个适用于Windows的Java应用程序。我希望Java应用程序在运行时在磁盘上创建一个包含版本号的文件名的新文件。当Java应用程序由my Azure Dev Ops(ADO)管道构建时,该版本号可作为OS环境变量使用。ADO管道使用CMake(运行javac命令)构建我的代码

解决方案是使用Maven作为构建系统。我在我的构建系统中找不到同样的方法,它不使用Maven和pom.xml。在使用javac命令行时,有没有办法做到这一点

谢谢

达伦

CMake在许多平台上运行

不过,maven也会继续跑下去

在构建Java应用程序时,该版本号可用作环境变量

javac
完全不支持预处理,而且无法做到这一点。预处理和IDE大多彼此憎恨,这可能解释了java生态系统和社区极不喜欢预处理器的概念;他们喜欢IDE

直接回答你的问题 因此,你必须去别处看看。例如,您可以在java源文件中包含一些令牌值,例如:

private static final String FULL_VERSION_ID = "{@@ INJECT_VERSION_HERE @@}";
然后,在调用
javac
之前,使用
sed
或其他搜索和替换工具。但是,这会使构建变得相当复杂:您必须获取该源文件(它实际上不再是实际的源文件,现在是源文件的模板),复制它(动态应用sed转换),然后编译它。这意味着源文件必须存在于其他地方或具有不同的扩展名,这对编辑器造成了极大的破坏,因为这在java社区中是不“正常”的,所以没有工具支持这类事情。由于(IDE)缺少文件,您的IDE将变得混乱,并在代码中显示各种错误

另一个解决方案是一些创造性的黑客,其中
sed
将在飞行中修改文件:

private static final String FULL_VERSION_TEMPLATE = "{@@ INJECT_VERSION_HERE @@}1.12";
private static final String FULL_VERSION = 
  FULL_VERSION_TEMPLATE.substring(FULL_VERSION_TEMPLATE.indexOf("@@}") + 3);
然后您的sed工具就可以“当场替换”,使用一个regexp可以找到整个内容,它保留
{@@}
标记不变,只替换1.12(从标记后到第一个引号,然后你需要一条规则,版本不能包含引号。我希望你能做出承诺,否则这会变得更复杂

CMake会使用文件修改时间戳,对吗?噢。好吧,试着让它离开80年代后期,而使用散列,否则这将导致不必要的重新编译。或者,如果请求的更改最终是不可操作的,试着让sed不更新时间戳

但是等等。。。 你确定你想进入那个又深又黑的兔子洞吗?你不能做这个更像java风格、更简单的事情吗

除了修改源文件,您是否可以在最终结果中添加1个非类文件(我假设您的CMake工具最终生成了一个dex或jar或类似的东西)?例如,确保jar文件的“根”中有version.txt。在java中,您可以编写以下代码:“嘿,看看你要找的正是构成这个应用程序的类文件的地方,然后给我其中一个em的内容:”


这样就可以了。这似乎简单多了:现在你的CMake脚本只需要确保
version.txt
中有正确的版本,并且包含在jar中,或者包含在构建管道的输出中(我承认我不熟悉ADO是什么).

ADO可以使用Maven构建。Visual Studio支持Maven。为什么要使用很少有项目会使用的特定于平台的工具?CMake运行在许多平台上,这就是为什么我们在ADO管道中使用它。此Java代码为Linux、Android、iOS和Windows构建。我要做的更改(上面讨论过)但是,仅适用于此代码的Widnows版本。访问Windows OS环境变量?本质上,您必须在编译时捕获变量的值。我对您的版本系统一无所知,但我建议将版本号写入一个文件,然后将该文件作为资源包含在jar中,该资源将在编译时可用jar已经运行了。@Darren-我不是说它不起作用。汇编语言程序需要付出足够的努力才能工作。但是,如果你在Java世界,CMAKE不是一个正常的构建工具。逆流程运行有时是有用的,但是有很多很多构建工具,我只是鼓励你使用一些在Java世界里有点不太实用的工具更标准。感谢@rzwitserroot提供的非常详细的答复!这非常有帮助,我感谢您为回答我的问题所做的努力。我喜欢插入version.txt文件的想法,今天将对此进行研究。
public class MyApp {
  public static void main(String[] args) {
    System.out.println(readVersion());
  }
  public static String readVersion() {
    try {
      try (var in = MyApp.class.getResourceAsStream("/version.txt")) {
        return new String(in.readAllBytes(), StandardCharsets.UTF_8).trim();
      }
    } catch (IOException e) {
      throw new InternalError("version.txt not found");
    }
  }
}