我正在尝试编写一个 shell 脚本,它将转换传递给它的位置参数,如下所示。
shell 脚本将这些参数传递给ffigen
从gcc 4.0
前端派生的二进制可执行文件 ( ),因此后面的命令行参数也是gcc
参数,并且与 的含义相同gcc
。
考虑以下命令行
./htest.sh -I/usr/include/gtk-2.0 -I /usr/include/glib-2.0 -include \
/usr/include/gtk-2.0/gtk/gtk.h -include/usr/include/bar.h /usr/include/myheader.h
这里本质上有两个不同的选项,一个-I
选项,它传递一个目录来gcc
搜索包含文件,另一个选项-include
,它处理一个头文件,就好像#include "file"
出现在主源文件的第一行一样。
这里给出的两个不同版本的不同之处在于选项标志和参数之间是否有空格。看来两者都是允许的。
目前上游出现的唯一版本是
-I/usr/include/gtk-2.0 and -include /usr/include/gtk-2.0/gtk/gtk.h
但尝试使此代码面向未来似乎并不是一个坏主意,以防有人稍后添加这些其他形式。
大多数情况下,上游脚本的作用是将参数添加到CFLAGS
,然后将最终参数传递给ffigen
。这里什么ffigen
并不重要——我的问题是关于 的返回值
CFLAGS
。这是上游的脚本。
while [ $# -gt 1 ]
do
echo $CFLAGS
case ${1} in
-pthread*)
CFLAGS="${CFLAGS} -D_REENTRANT"
shift
;;
-x)
shift
shift
;;
*)
CFLAGS="${CFLAGS} ${1}"
shift
;;
esac
done
echo $CFLAGS
我想要做的是在上面的行中指定头文件名,即将它们转换为相对于包含目录的相对路径名。所以,我希望看到的返回值CFLAGS
是
-I/usr/include/gtk-2.0 -I /usr/include/glib-2.0 -include gtk-2.0/gtk/gtk.h -includebar.h
上游产生的只是未更改的参数。
-I/usr/include/gtk-2.0 -I /usr/include/glib-2.0 -include \
/usr/include/gtk-2.0/gtk/gtk.h -include/usr/include/bar.h
理由:由于 Debian 已切换到 multilib,头文件不再位于其传统位置。现在,ffigen
像它的父级一样gcc
,可以搜索头文件的包含路径,假如
仅指定相对路径。如果指定了绝对路径,那么当然就不会了。
理想情况下,人们希望使用一种设计用于多架构的工具,但一种快速而肮脏的解决方法是简单地将头文件绝对路径剥离为相对路径名,并且如果 ffigen 提供了正确的包含路径,它将搜索查找并发现头文件。
我目前拥有的版本如下。它产生
-I/usr/include/gtk-2.0 -I glib-2.0 -include gtk-2.0/gtk/gtk.h bar.h
这很糟糕,但确实正确处理了上游实际发生的两种情况。正确处理所有四种情况的版本将是最受欢迎的。是的,我很懒。我对 shell 脚本也很烂。
while [ $# -gt 1 ]
do
echo $CFLAGS
case ${1} in
-pthread*)
CFLAGS="${CFLAGS} -D_REENTRANT"
shift
;;
-x)
shift
shift
;;
-I*)
CFLAGS="${CFLAGS} ${1}"
shift
;;
*)
RELPATH_AFTER_INCLUDE="${1##*include/}"
CFLAGS="${CFLAGS} ${RELPATH_AFTER_INCLUDE}"
shift
;;
esac
done
echo $CFLAGS
这是我用来测试这个的一个小脚本
#!/bin/sh
PROGRAM=htest.sh
#PROGRAM=upstream.sh
./${PROGRAM} -I/usr/include/gtk-2.0 -I /usr/include/glib-2.0 -include \
/usr/include/gtk-2.0/gtk/gtk.h -include/usr/include/bar.h /usr/include/myheader.h
关于可移植性的最后一点。上面的脚本在破折号下运行,看起来它们对我来说是可移植的。因此,可移植的版本会很好,但不是必需的。我没有看到这段代码在上游,所以...如果不可移植,那么 bash 就可以了。
###################################################################
对于任何对此背景感兴趣的人,这是在包装的背景下Clozure Common Lisp对于 Debian。
看Debian 包装特别是 README.源文件。
查看上游补丁
http://svn.clozure.com/publicsvn/ffigen4/trunk/ffigen4/source/h-to-ffi-common
和
http://svn.clozure.com/publicsvn/ffigen4/trunk/ffigen4/source/linuxx8664-gcc-4.0.0-h-to-ffi.sh
,它们结合起来制作上游脚本h-to-ffi.sh
,我在这里讨论其中的一部分。
对于我在这里尝试处理的具体问题,请参阅线程 在 Debian 多架构上构建接口数据库时出现问题。
关于我上面的基本原理的讨论是在该线程的第三条消息中,从我到底部。
答案1
因为有时-I
或之后有一个空格,-include
有时没有,所以不能指望$1
保留该选项和价值。
我会坚持使用原始版本,大小写选择为“-pthread*”、“-x”和“*”。然后,在累积 CFLAGS 变量后,调用 sed 仅删除 -include 选项的部分路径:
CFLAGS=$(echo "$CFLAGS" | sed 's#\(-include \?\)/usr/include/#\1#g')
答案2
以下内容有效,但有点冗长。欢迎提出改进建议。
while [ $# -gt 1 ]
do
echo $CFLAGS
case ${1} in
-pthread*)
CFLAGS="${CFLAGS} -D_REENTRANT"
shift
;;
-x)
shift
shift
;;
-I)
CFLAGS="${CFLAGS} ${1}"
shift
CFLAGS="${CFLAGS} ${1}"
shift
;;
-include)
CFLAGS="${CFLAGS} ${1}"
shift
RELPATH_AFTER_INCLUDE="${1##*include/}"
CFLAGS="${CFLAGS} ${RELPATH_AFTER_INCLUDE}"
shift
;;
-I*)
CFLAGS="${CFLAGS} ${1}"
shift
;;
-include*)
# strip off leading -include
REMOVE_LEADING_INCLUDE="${1##-include}"
echo "REMOVE-LEADING-INCLUDE" ${REMOVE_LEADING_INCLUDE}
RELPATH_AFTER_INCLUDE="${REMOVE_LEADING_INCLUDE##*include/}"
CFLAGS="${CFLAGS} -include${RELPATH_AFTER_INCLUDE}"
shift
;;
*)
CFLAGS="${CFLAGS} ${1}"
shift
;;
esac
done
echo $CFLAGS