设置临时环境 ($PATH)
Posted
技术标签:
【中文标题】设置临时环境 ($PATH)【英文标题】:Set a temporary environment ($PATH) 【发布时间】:2015-07-29 15:16:24 【问题描述】:我可能会遇到这个问题的 X-Y 问题,如果我错了,我鼓励你们纠正我。
我想配置一个可以在不同平台和编译器版本上工作的工具链环境。我最初编写了一个长的 Perl 脚本,它生成一个只包含变量的配置 Makefile。我想要简单,所以我没有使用 automake 或 autoconf 编写任何复杂的东西。此外,我希望重新配置过程非常快。就我而言,我自己写的./configure
在不到一秒的时间内完成了所有工作。我对此感到非常高兴。
但是我觉得我可以使用环境变量来使用更好的方法。我可以直接设置当前的 shell 环境,而不是编写带有特定变量的 Makefile。例如:
export cc=gcc
不幸的是,一些变量已经在 $PATH 中声明了。解决办法是在另一个前面加上新的$PATH:
export PATH=/new/toolchain/path:$PATH
echo $PATH
/new/toolchain/path:/old/toolchain/path:/usr/bin:/bin...
我觉得这很难看,我想在添加新路径之前删除旧路径。
总结:
-
使用环境而不是自定义 makefile 来设置构建配置是否更好?
如何正确调整现有环境变量?
【问题讨论】:
您是否尝试过使用 SCons、CMake、autoconf 等高级构建系统? 好吧,CMake 使用 make 并且我希望让事情尽可能简单。所以在我的情况下 make 会更好。 Autoconf 看起来很复杂,我真的应该找到一个很好的教程。我仍然迷失了它。我真的应该看看 SCons。我不知道。 请注意:您发布的导出命令没有指向您发布的路径(缺少$
符号)。
@MichaelJaros 对,我修好了。
Rake
或 tup
也不错。除了最基本的东西,做任何事情都很糟糕。
【参考方案1】:
当我有几个变量要设置时,我会编写一个 wrapper 脚本,然后将其用作要修改的命令的前缀。这让我也可以使用前缀
应用于单个命令,例如make
,或
初始化 shell,以便后续命令使用更改后的设置。
我使用包装器
设置编译器选项(例如clang
,设置CC
变量,使配置脚本“看到”它作为选择的编译器),
设置语言环境变量,使用 POSIX 测试 C
与 en_US
与 en_US.UTF-8
等。
在简化的环境中进行测试,例如在cron
中。
每个包装器都会执行识别正确的PATH
、LD_LIBRARY_PATH
和类似变量所需的操作。
例如,我在大约十年前编写了这个临时脚本,以使用本地构建的 python 进行测试:
#!/bin/bash
ver=2.4.2
export TOP=/usr/local/python-$ver
export PATH=$TOP/bin:$PATH
export LD_LIBRARY_PATH=`newpath -n LD_LIBRARY_PATH -bd $TOP/lib $TOP/lib/gcc/i686-pc-linux-gnu/$ver`
if test -d $TOP
then
exec $*
else
echo no $TOP
exit 1
fi
并将其用作with-python-2.4.2
myscript。
一些包装器只是调用另一个脚本。 例如,我在 configure 脚本周围使用这个包装器来设置变量以进行交叉编译:
#!/bin/sh
# $Id: cfg-mingw,v 1.7 2014/09/20 20:49:31 tom Exp $
# configure to cross-compile using mingw32
BUILD_CC=$CC:-gcc
unset CC
unset CXX
TARGET=`choose-mingw32`
if test -n "$TARGET"
then
PREFIX=
test -d /usr/$TARGET && PREFIX="--prefix=/usr/$TARGET"
cfg-normal \
--with-build-cc=$BUILD_CC \
--host=$TARGET \
--target=$TARGET \
$PREFIX "$@"
else
echo "? cannot find MinGW compiler in path"
exit 1
fi
其中choose-mingw32
和cfg-normal
是(a) 为交叉编译器查找可用目标名称和(b) 为配置脚本提供附加选项的脚本。
其他人可能会建议 shell aliases 或 functions。我不会将这些用于此目的,因为我的命令行 shell 通常是 tcsh
,而我从 (a) 其他 shell 脚本、(b) directory editor 或 (c) text-editor 运行这些命令。那些使用 POSIX shell(当然,对于需要特定功能的脚本除外),使别名或功能很少使用。
【讨论】:
【参考方案2】:您可以为特定的命令调用创建个性化环境:
VAR1=val1 VAR2=val2 VAR3=val3 make
我觉得这样做比这样做更干净:
export VAR1=val1
export VAR2=val2
export VAR3=val3
make
除非您在包装脚本中,甚至可能与
VAR1=val1 VAR2=val2 VAR3=val3 make
VAR
变量将是它们在 make 调用之前的任何内容(包括但不限于未导出和不存在)。
长行不是问题,您可以随时将其拆分为多行:
VAR1=val1\
VAR2=val2\
VAR3=val3\
make
您可以为任何 Unix 命令设置这样的环境变量。
shell会全部设置好。
一些应用程序(例如make
或rake
)会根据看起来像变量定义的参数修改它们的环境(参见prodev_paris 的答案),但这取决于应用程序。
【讨论】:
感谢您的提议。我会考虑的。【参考方案3】:众所周知,最好为构建产品等任务集成标准工具,而不是创建自己的方法。从长远来看,这种努力通常会有所回报。
话虽如此,一个简单的方法是为您的不同产品定义不同的环境文件(例如build-phone.env
)设置工作目录、PATH
、CC
等,并根据需要以交互方式获取您的环境文件:
. /path/to/build-phone.env
[your build commands]
. /path/to/build-watch.env
[your build commands]
【讨论】:
【参考方案4】:使用环境而不是自定义 makefile 来设置构建配置更好吗?
构建系统的最佳实践是完全不依赖任何环境变量。因此,构建您的项目只需要:
git clone ... my_project
make -C my_project
必须设置环境变量容易出错,并可能导致构建不一致。
如何正确调整已有的环境变量?
您可能根本不需要调整这些。通过使用编译器等工具的完整路径,您可以将构建系统与环境分离。
【讨论】:
我同意你的观点,但是这可能会导致相当大的开销,因为项目必须每天重新配置几次。总是重新检查依赖关系可能需要一些时间。当基本代码只有几个 C 文件时,我总是对./configure
浪费多少时间印象深刻。
好吧,你可以运行 ./configure
几次,保存结果并制作一个 shell 脚本,使用特定配置调用 make
,例如make-arm-v7.sh
、make-arv-v8.sh
等。构建out-of-tree,这样你在不同目标架构之间切换时就不必清理你的构建目录。【参考方案5】:
我认为在调用 makefile 时使用直接变量定义可能会受益,如下所示:
make FOO=bar target
其中FOO
是您要设置为值bar
的变量。
请注意,在这种情况下,它优先于环境定义!因此,您可以轻松覆盖 PATH 变量...
请查看此详细主题以获取更多信息:https://***.com/a/2826178/4716013
【讨论】:
很好的解决方案,但在我的情况下,我需要设置大约 10 个变量(产品类型、架构、编译器、版本等)。总是写 make ARCH=... CC=... ... all 会适得其反 据我了解您的情况,您也许可以编写一个“简单”脚本来为您执行此操作:) 这就是我所做的。我有一个自定义 Perl 脚本,它生成主 Makefile 使用的config.mak
。以上是关于设置临时环境 ($PATH)的主要内容,如果未能解决你的问题,请参考以下文章