Mac vs. Windows: 在 Ant 构建文件中读取环境变量

huangapple go评论89阅读模式
英文:

Mac vs. Windows: Reading environment variable in Ant build files

问题

<property environment="env" />
<!-- RESOLVE -->
<target name="{target}">
    <if>
        <isset property="env.MY_HOME"/>
        <then>
            <property name="my.home" value="${env.MY_HOME}"/>
        </then>
        <else>
            <property name="my.home" value="${env.USERPROFILE}/me"/>
        </else>
    </if>
</target>

settings file does not exist

UPDATE: Even the environment variables in my *pom.xml* aren't being read:

<systemPath>${env.JAVA_HOME}/lib/myJarFile.jar</systemPath>

If I make changes in my *build.xml* file, even my repo doesn't pick up that the file has been changed. Why would that be? I'm guessing ANT properties are immutable.

I have to hardcode the path to get it to work:

<systemPath>{pathToMyJar}</systemPath>

Why would I, as a Mac user, run into this issue, whereas Windows users don't even have to set the environment variables and can still build fine?

UPDATE:
It works for my Windows colleagues because there is a default USERPROFILE environment variable. But on a Mac, the equivalent is `$HOME`. How can I fix that? I have tried `export USERPROFILE=$HOME` in my `.profile` and `.bash_profile` files, but it's still trying to read `env.USERPROFILE`.

Here it is in `mybuild.xml` (another ant file triggered for local development from `build.xml`):

<target name="init-my-stuff">
    <if>
        <isset property="env.MY_HOME"/>
        <then>
            <property name="my.home" value="${env.MY_HOME}"/>
        </then>
        <else>
            <property name="my.home" value="${env.USERPROFILE}/me"/>
        </else>
    </if>
</target>
英文:

I've got a project that references environment variables in the Ant build file.

&lt;property environment=&quot;env&quot; /&gt;
&lt;!-- RESOLVE --&gt;
&lt;target name=&quot;{target}&quot;&gt;
	&lt;if&gt;
		&lt;isset property=&quot;env.MY_HOME&quot;/&gt;
		&lt;then&gt;
			&lt;property name=&quot;my.home&quot; value=&quot;${env.MY_HOME}&quot;/&gt;
		&lt;/then&gt;
		&lt;else&gt;
			&lt;property name=&quot;my.home&quot; value=&quot;${env.USERPROFILE}/me&quot;/&gt;
		&lt;/else&gt;
	&lt;/if&gt;	
&lt;/target&gt;

Other developers on Windows machines don't even have to define the env.IVY_HOME or env.USERPROFILE variables. But I, as a Mac user, am getting the following error during the build process:

settings file does not exist

Now, I have successfully added and echoed IVY_HOME and even USERPROFILE in my .bash_profile file but I still get that same error.


UPDATE: Even the environment variables in my pom.xml aren't being read:

&lt;systemPath&gt;${env.JAVA_HOME}/lib/myJarFile.jar&lt;/systemPath&gt;	

If I make changes in my build.xml file even my repo doesn't pick up that the file has been changed. Why would that be? I'm guessing ANT properties are immutable.

I have to hardcode the path to get it to work:

&lt;systemPath&gt;{pathToMyJar}&lt;/systemPath&gt;

Why would me, as a Mac user, run into this issue whereas Windows users don't even have to set the environment variables and can still build fine?


UPDATE:
It works for my Windows colleagues because there is a default USERPROFILE environment variable. But, on a Mac, the equivalent is $HOME. How can I fix that? I have tried export USERPROFILE=$HOME in my .profile and .bash_profile files but it's still trying to read env.USERPROFILE.

Here it is in mybuild.xml (I guess another ant file that is triggered for local development from build.xml):

&lt;target name=&quot;init-my-stuff&quot;&gt;
	&lt;if&gt;
		&lt;isset property=&quot;env.MY_HOME&quot;/&gt;
		&lt;then&gt;
			&lt;property name=&quot;my.home&quot; value=&quot;${env.MY_HOME}&quot;/&gt;
		&lt;/then&gt;
		&lt;else&gt;
			&lt;property name=&quot;my.home&quot; value=&quot;${env.USERPROFILE}/me&quot;/&gt;
		&lt;/else&gt;
	&lt;/if&gt;	

&lt;/target&gt;

答案1

得分: 1

这个示例 在我的 Mac 上可以工作。build.xml 文件与你的问题中的那个类似。我使用的是 Ant 1.9.6、Ivy 2.5.0 和 Ant Contrib 1.0b3。

为了测试,我在 Bash 中使用以下的 run.sh 脚本。它相当基础,所以这会是一个有用的测试,看看它是否适用于你:

#!/bin/bash

unset IVY_HOME
unset USERPROFILE

# 尝试下面任选一项:
# export IVY_HOME=~/tools/apache-ivy/apache-ivy-2.5.0
export USERPROFILE=~/tools/apache-ivy/apache-ivy-2.5.0

ant init-ivy 

当然,你需要根据你的机器修改路径。通过注释掉相应的 IVY_HOMEUSERPROFILE,Ant 将会按预期使用 <then><else> 分支。

英文:

This example works on my Mac. The build.xml is similar to the one in your question. I'm using Ant 1.9.6, Ivy 2.5.0, and Ant Contrib 1.0b3.

To test, I'm using the following run.sh in Bash. It is fairly basic, so it will be a useful test to see if it works for you:

#!/bin/bash

unset IVY_HOME
unset USERPROFILE

# try either of these:
# export IVY_HOME=~/tools/apache-ivy/apache-ivy-2.5.0
export USERPROFILE=~/tools/apache-ivy/apache-ivy-2.5.0

ant init-ivy 

Of course, you will have to change the paths to be specific for your machine. By commenting out IVY_HOME or USERPROFILE as appropriate, Ant will use the &lt;then&gt; or &lt;else&gt; branch as expected.

答案2

得分: 1

是的,ant 属性是不可变的。一旦设置,它们就不能再被更改。有一些方法可以解决这个问题 - 你可以仅为单个目标设置一个变量,使用 <local> 任务,例如,或者使用宏,但这似乎与你的问题无关,所以让我们来解决缺失的 env.IVY_HOME 变量的谜团。

特别是在 Linux/macOS 上,每个进程都会获得一个全新的“环境”(用 Java 的术语来说,基本上是一个 Map<String, String>),如果生成进程决定这样做,它可能会被初始化以保存一堆额外的值。

关键是,如果你的 bash 告诉你 IVY_HOME 存在,这并不意味着你的 ant 进程会看到它!

这就是 export 的作用;如果你像这样设置一个属性 IVY_HOME=....,那么你的 shell 将不会将其复制到任何新生成的进程中。如果在前面加上 export,就会复制。一个非常简单的测试是在你的 ant 中生成一个 bash,并要求它打印出所有属性:

<project name="test" default="test">
  <target name="test">
    <exec executable="/bin/bash">
      <arg value="-c" />
      <arg value="set" />
    </exec>
  </target>
</project>

说明:将上述内容保存到一个新目录中的 build.xml,然后运行 ant 命令。

运行上述命令,我敢打赌 IVY_HOME、USERPROFILE 等在列表中并不在第一位,这表明你首先没有设置这些属性。要么你没有导出它们,要么你遇到了一个不同的问题,即“交互变量”和“非交互变量”的概念。这并不是内置到 sysenv 系统中的,而是内置到大多数 Linux/macOS 的 shell 设置中:有许多在启动新 shell 时读取的 shell 脚本。有 ~/.bashrc~/.profileetc/bash_profile/etc_profile,有时还有 /etc/profile.d 目录,其中包含许多脚本等等。

在启动 shell 时,哪些脚本实际上会被调用取决于你启动的是什么 shell 以及它是否是“交互式”的。很有可能你将 export IVY_HOME=.... 添加到一个甚至没有被读取的文件中。

你想要在全局范围内使用的环境变量可能应该放在 ~/.profile 中。

你总是可以告诉 bash 将一些环境变量传递给你的进程。尝试一下这个:

FOO=hello ant

在与上面的“调用 bash -c set 作为测试”脚本位于同一目录中。这是一种你可以强制执行的方式;通过运行类似 IVY_HOME=/path/to JAVAHOME=/path/to ant build 的命令(等号分隔的字符串放在命令前告诉 bash 将该键/值对放入它正在为该进程创建的哈希映射中)。

如果最后一个示例仍然无法使你的 ant 脚本获取到 env.IVY_HOME,那么可能出现了一些非常奇怪的情况,这时候可能需要贴出完整的脚本。

英文:

Yes, ant properties are immutable. Once set they cannot be changed anymore. There are ways around this - you can set a variable only for within a single target using the &lt;local&gt; task. for example, or use macros, but that doesn't appear to be relevant for your question, so let's get to the mystery of the missing env.IVY_HOME variable.

On linux/mac in particular, every process gets a brand new fresh 'environment' (in java terms, basically a Map&lt;String, String&gt;), which may be initialized to hold a bunch of extra values if the spawning process decides it wants to do that.

The key point is, if your bash tells you IVY_HOME exists, that does not imply your ant process will see that!

That's what export is for; if you set a property as with IVY_HOME=.... then your shell will not copy that one over to any newly spawned processes. If you stick export in front, it should. One easy enough test is to spawn a bash from within your ant and ask it to print all properties:

&lt;project name=&quot;test&quot; default=&quot;test&quot;&gt;
  &lt;target name=&quot;test&quot;&gt;
    &lt;exec executable=&quot;/bin/bash&quot;&gt;
      &lt;arg value=&quot;-c&quot; /&gt;
      &lt;arg value=&quot;set&quot; /&gt;
    &lt;/exec&gt;
  &lt;/target&gt;
&lt;/project&gt;

Instructions: Save above to build.xml in a new dir, then run ant.

run the above and I bet that IVY_HOME, USERPROFILE etc aren't in the list in the first place, which suggests that you did not 'set' these properties in the first place. Either you did not export them, or, you're running into a different problem, the concept of 'interactive variables' and 'non-interactive variables'. This isn't baked into the sysenv system, but into most linux/mac setups of shells: There are a whole bunch of shell scripts that are read in when a new shell is started. THere's ~/.bashrc, ~/.profile, etc/bash_profile, /etc_profile, sometimes an /etc/profile.d dir with many scripts, and more.

Which ones actually get invoked when you fire up a shell depends on what shell you're firing up and whether it is 'interactive' or not. It is quite possible you've added export IVY_HOME=.... to a file that isn't even being read in.

Environment variables you want globally available should probably go in ~/.profile.

You can always tell bash to specifically pass some env vars to your process. Try this:

FOO=hello ant

in the same dir as the invoke bash -c set as a test script above. That's one way you can force the issue; by running IVY_HOME=/path/to JAVAHOME=/path/to ant build or whatnot (any equals-sign-separated string put in front of a command tells bash to put that key/value pair into the hashmap it is making for that process).

If that last one still doesn't result in your ant script picking up env.IVY_HOME, then something really weird is going on, and it's time to paste the full script, I think.

huangapple
  • 本文由 发表于 2020年10月27日 02:28:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/64542959.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定