【问题标题】:Compile using variable names in bash script在 bash 脚本中使用变量名进行编译
【发布时间】:2017-05-26 01:51:31
【问题描述】:

我正在尝试编写一个自动安装的 bash 脚本(我知道,我知道,我应该使用 make),它的目的是通用的:支持不同的编译器和构建标志。

例如,我有以下几行:

$FORTRAN_COMPILER $LINKERFLAGS lagrit_main.o lagrit_main.f
$FORTRAN_COMPILER $LINKERFLAGS lagrit_fdate.o lagrit_fdate.f
make $MAKEFLAG lib
$FORTRAN_COMPILER $BUILDFLAGS $LAGRIT_NAME $BUILDLIBS $BUILDSUFFIX

变量设置为

FORTRAN_COMPILER=gfortran
LINKERFLAGS="-O -fcray-pointer -fdefault-integer-8 -m64 -Dlinx64 -c -o"
BUILDFLAGS="-O -Dlinx64 -fcray-pointer -fdefault-integer-8 -fno-sign-zero -o"
BUILDLIBS="lagrit_main.o lagrit_fdate.o lagrit_ulin64_o_gcc.a $LAGRIT_UTIL_DIR/util_ulin64_o_gcc.a"
BUILDSUFFIX="-L$ACCESS -lexodus -lexoIIv2for -lnetcdf -lm -lstdc++"
MAKEFLAG="MOPT=64"

返回这些错误:

 gfortran: error: lagrit_main.o: No such file or directory
 gfortran: error: lagrit_fdate.o: No such file or directory

 gfortran: error: lagrit: No such file or directory
 gfortran: error: lagrit_main.o lagrit_fdate.o  lagrit_ulin64_o_gcc.a /scratch/sft/livingston/build/shared/LaGriT/lg_util/src/util_ulin64_o_gcc.a: No such file or directory

但是,当我以长格式(即gfortran -O -fcray-pointer -fdefault-integer-8 -m64 -Dlinx64 -c -o lagrit_main.o lagrit_main.f)运行相同的命令时,它的构建没有问题。

我在这里缺少什么?我尝试了变量行的不同排列,包括:

gfortran $LINKERFLAGS lagrit_main.o lagrit_main.f
"$FORTRAN_COMPILER" "$LINKER_FLAGS" lagrit_main.o lagrit_main.f
${FORTRAN_COMPILER} ${LINKER_FLAGS} lagrit_main.o lagrit_main.f

都会导致相同的错误。

编辑:为澄清起见,这是在 Ubuntu 16.04 上

【问题讨论】:

  • 是否所有变量都在同一个 Bash 脚本中声明?如果没有,您可能缺少export VAR...
  • 他们是;事实上,我已经完成了echo "$FORTRAN_COMPILER $BUILDFLAGS $LAGRIT_NAME $BUILDLIBS $BUILDSUFFIX"(连同其他两行),输出与硬编码的gfortran 命令完全匹配。
  • 如果您将 -o 移出变量并进入最终调用行,问题是否解决?
  • 因为引用禁止分词,你不应该像"$LINKER_FLAGS"一样引用XXX_FLAGS。您可以使用set -x#!/bin/bash -x 来检查真正执行的命令。
  • 添加#!/bin/bash -x后,发现终端将Fortran行解释为:gfortran '-O -fcray-pointer -fdefault-integer-8 -m64 -Dlinx64 -c -o' lagrit_main.o lagrit_main.f。单引号表示标志正在作为字符串传递给 gfortran,它不知道如何处理。

标签: bash shell ubuntu fortran gfortran


【解决方案1】:

当这个命令运行时:

$FORTRAN_COMPILER $LINKERFLAGS lagrit_main.o lagrit_main.f

终端是这样解析的:

gfortran '-O -fcray-pointer -fdefault-integer-8 -m64 -Dlinx64 -c -o' lagrit_main.o lagrit_main.f

您可以看到链接器标志被解释为字符串,并作为字符串传递给 gfortran。这是错误的根源。

解决方案是将链接器标志定义为一个数组,每个参数都是该数组中的一个元素:

LINKERFLAGS=(-O  -fcray-pointer -fdefault-integer-8 -m64 -Dlinx64 -c -o)
$FORTRAN_COMPILER ${LINKERFLAGS[*]} lagrit_main.o lagrit_main.f || exit 1

【讨论】:

  • 在我遇到的每个 shell 中,都会发生分词,并且 $FORTRAN_COMPILER $LINKERFLAGS 将 $LINKERFLAGS 的组件作为单独的参数传递给 $FORTRAN_COMPILER。如果这是实际的解决方案,使用的是哪个版本的 shell?
  • 我通常会遇到同样的事情。但是,无论出于何种原因,这个脚本的行为方式都不是这样。我已经在 bash 4.3.46 (Ubuntu 16.04) 和 zsh 5.2 w/bash 3.2.57 (macOS Sierra) 上运行它。其他在不同环境中使用此脚本的人报告了同样的事情。
猜你喜欢
  • 1970-01-01
  • 2021-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-10
  • 2023-03-30
  • 2014-03-02
相关资源
最近更新 更多