LLVM 3.1 測試經驗談

Copyright (c) 2012 陳韋任 (Chen Wei-Ren)

*** 此篇文章技術性不高,純粹是分享替 LLVM 做測試的經驗。***

一切都從 [3.1 Release] Call For Testers! 這一封徵求 LLVM 3.1 Release Tester 的信開始。我純粹抱著試試看的心態,回信給 Bill Wendling 問他新手如我是否也能參與 LLVM 3.1 Release Testing。在約莫一個禮拜之後,Bill 通知所有曾經回信給他的人關於 LLVM Testing 大致的流程以及相關注意事項。我這裡簡單做個摘要:

    1. 一開始 Bill 會要求所有測試者寄給他測試平台的相關資訊,諸如作業系統和編譯器版本。Bill 需要這個資訊以便知道測試覆蓋程度如何。以我的例子,我會回覆他:

    Two pandaboard:

    arm linux (ubuntu 11.04), gcc 4.5.2

    注意! 基本上不鼓勵在測試期間更新作業系統和編譯器版本。

    2. Bill 會在郵件列表上公布測試的時程表,一般測試為期一個月。這次公布的時程如下:

    April 16th: Branching for 3.1 release
    April 16-22: Phase 1 testing
    April 23-29: Bug fixing for Phase 1 issues, all features completed
    April 30-May 6: Phase 2 testing
    May 7-13: Addressing Phase 2 issues, final binary generation
    May 14th: Release of 3.1!

    基本上是維持一個禮拜測試,下一個禮拜修正錯誤的循環。Bill 會視情況決定是否延長測試的時間。

    3. 在測試期間所發現的臭蟲,一律送交 Bugzilla。Bill 會要求你回報臭蟲的同時,將他加進 CC list 以便他監控臭蟲修正的進度。基本上,只要不是太嚴重的臭蟲都不會阻礙 LLVM release 的時程。另外,非主流平台 (x86 除外) 上的臭蟲通常都需要測試者幫忙修正。測試者可以在郵件列表或是聊天室尋求幫助。
    4. ${LLVM_SRC}/utils/release 目錄底下提供幾個腳本協助測試者進行測試。測試分為兩類: 一類是所謂的回歸測試 (regression test),這類測試位在 ${LLVM_SRC}/test 底下。主要用來確保 LLVM/Clang 的正確性。第二類是評量 LLVM 在效能上是否有退步,這類測試位在 ${LLVM_SRC}/projects/test-suite。測試分底下三個步驟:

    a. 以不同模式 (Debug、Assert 或是 Release) 編譯 LLVM/Clang 3.1 pre-release
    candidate,也就是所謂的 RC (release candidate),並進行回歸測試。這一步最為
    重要,事實上我這次的測試也只有做到這一步。

    b. 下載 LLVM/Clang 3.0 代碼並編譯,運行 test-suite 得到一組分數作為比較基準
    (baseline)。

    c. 以編譯好的 LLVM/Clang 3.1 pre-release candidate “手動” 運行 test-suite,
    並得到一組分數。將此分數與前述 baseline 做比較,若有退步便回報。

    整個測試工具的使用可以參考 LLVM Testing Infrastructure Guide

O.K.,現在就等 LLVM 從 trunk 替 3.1 release 開一個 branch,接著就可以準備測試。Bill 會在郵件列表上發布 3.1 Has Branched 的消息。但別急! 一切都等待 Bill 這位 release manager 的指示,他會通知測試者 release candidate 的代碼該從哪裡下載,並給出較之前為詳細的指示。你可能會收到類似 “Release Candidate 1 Ready for Testing” 的信件,我這裡簡單做個摘要:

    1. 隨信的附件中會有幾個腳本供測試者使用,你同樣可以在 ${LLVM_SRC}/utils/release 找到底下幾個腳本:

    • test-release.sh
    • findRegressions-simple.py
    • findRegressions-nightly.py

    後兩個是用來比較 test-suite 分數。我主要使用的是 test-release.sh 這支腳本。

    2. Bill 會描述如何使用 test-release.sh。以測試 LLVM 3.1 RC1 為例,

    $ test-release.sh -release 3.1 -rc 1 -no-64bit -no-compare-files

    因為我是測試 ARM 平台,所以不測試 64 bit。整個編譯流程跟 GCC 極為類似,總共
    有三個階段。Phase 1 是以系統工具鏈編譯 LLVM/Clang,Phase 2 是使用 Phase 1
    編譯所得的 clang 編譯 LLVM/Clang,Phase 3 是使用 Phase 2 編譯所得的 clang
    編譯 LLVM/Clang,最後比較 Phase 2 和 Phase 3 的結果。因為某些不知名的原因,
    Bill 稱此次 Phase 2 與 Phase 3 的目的檔有所不同,但可忽略,他建議我們使用
    -no-compare-files 跳過 Phase 2 與 Phase 3 的比較。`test-release.sh -help`
    可以得到更多訊息。注意! 請確定最後執行回歸測試所用的是 Phase 3 的
    LLVM/Clang。剛開始進行測試的時候,我多下了 “-disable-clang” 這個選項,導致
    只有 Phase 1 的結果,用 Phase 1 進行回歸測試得到的結果是不準確的。回歸測試
    的結果相當重要,有臭蟲皆需要立即回報給 Bugzilla (http://llvm.org/bugs),
    並 CC 給 Bill,由他決定該臭蟲是否會阻礙 LLVM release 的時程。

    3. 分別以 LLVM 3.0 和 LLVM 3.1 RC 運行 test suite,並以 findRegressions-simple.py
    和 findRegressions-nightly.py 比較兩者的結果。這次我並沒有認真地運行 test
    suite。
    4. 打包 Phase 3 所得結果,並交由 Bill 上傳至 LLVM 官網。基本指令如下:

    $ cd rc1/Phase3/Release
    $ tar zcvf llvmCore-3.1-rc1.install-arm-ubuntu_11.04.tar.gz llvmCore-3.1-rc1.install/

至此就算是告一個段落,爾後的 RC2 亦或是 RC3 基本上都是依循上述流程。這次測試過程中有個小插曲,RC2 的代碼在 ARM 上編譯不過。這時要盡快回報給 Bill,同時自己這邊也要做 bisect 抓出出錯的版本號。基本流程如下:

    1. 取得正常可運作的版本號,這裡我取 RC1 (r155062)。

    $ svn log http://llvm.org/svn/llvm-project/llvm/tags/RELEASE_31/rc1 –stop-on-copy
    ————————————————————————
    r155062 | void | 2012-04-19 06:10:56 +0800 (四, 19 4 2012) | 1 line

    Creating release candidate rc1 from release_31 branch

    2. 取得出錯的版本號,這裡我取 RC2 (r156037)。

    $ svn log http://llvm.org/svn/llvm-project/llvm/tags/RELEASE_31/rc2 –stop-on-copy
    ————————————————————————
    r156037 | void | 2012-05-03 08:11:00 +0800 (四, 03 5 2012) | 1 line

    Creating release candidate rc2 from release_31 branch

    3. 透過 svn-bisect 用二分法找出一開始出問題的版本。注意! LLVM 和 Clang
    分屬不同的 SVN,但是在糾錯時請保持 LLVM 和 Clang 的版本一致。

    $ cd rc2/llvm.src
    # 好 壞
    $ svn-bisect start 155062 156037
    Switching to r155672 …
    # 手動將 Clang 切換至 r155672
    $ cd rc2/cfe.src
    $ svn up -r 155672
    # 開始編譯。-no-checkout 是要求直接使用當前目錄下的代碼,不從 SVN checkout。
    $ cd rc2
    $ ./test-release.sh -release 3.1 -rc 2 -no-checkout -no-64bit -no-compare-files
    # 如果 r155672 編譯出錯,將其標定為 bad,svn-bisect 會切換到下一個應該要檢測的
    # 版本。
    $ svn-bisect bad 155672
    Switching to r155374 …

    幸運的是,在我 bisect 出錯誤版本之前,Bill 已經先我一步找到出問題的版本號。
    要知道在 ARM 機器上編譯 LLVM/Clang 可以頗為耗時的一件事。:-)

    4. 等待 Bill 重新發布下一個修正過後的測試版本,RC3。

最後進入 final release 時,測試者只需編譯好 LLVM/Clang,無須再跑回歸測試或是 test suite,直接將 Phase 3 打包送給 Bill 即可。剩下的就是靜待 LLVM 3.1 Release
的發布。我這裡提一下提交臭蟲至 Bugzilla 時,應該要有的格式。以 Test case Sema/arm-neon-types.c fail on ARM 為例,標題寫明是在 ARM 平台上,Sema/arm-neon-types.c 這個測試失敗。在內容描述裡面,把 `make check-all` 所吐出的訊息貼上去。基本上 test-release.sh 這支腳本在編譯完 Phase 3 LLVM/Clang 後會運行回歸測試,即 `make check-all`,同時會留下 log。你只需要將該 log 的內容檢視一遍,將出錯的測試回報給 Bugzilla 即可。非 x86 平台的測試者需要自己主動修正錯誤,你可以在郵件列表和聊天室尋求幫助。

修正臭蟲之後就可以送 patch,以 Fix test case failure due to C++ ABI difference on ARM 為例,標題簡明扼要的描述這個 patch 修正了什麼問題,信件正文再較為詳細的敘述這個 patch 的意圖,必要時附帶上輔助資料,最後以附件形式附上 patch。

整個測試過程中,如果有 “任何” 疑問,不要遲疑,發信到郵件列表或是 release manager 尋求協助。最後,你可以在 Chris Lattner 發布的 LLVM 3.1 Release! 公告上看見你的名字。

本篇文章沒有技術含量,純粹是希望鼓勵更多人參與 LLVM 的開發,不論是以何種形式。:-)

[1] http://lists.cs.uiuc.edu/pipermail/llvmdev/2012-March/048355.html
[2] http://llvm.org/docs/TestingGuide.html
[3] http://lists.cs.uiuc.edu/pipermail/llvmdev/2012-April/048961.html
[4] http://llvm.org/bugs/show_bug.cgi?id=12694
[5] http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20120430/056982.html
[6] http://lists.cs.uiuc.edu/pipermail/llvm-announce/2012-May/000041.html

简析gcc configure.ac

Copyright (c) 2012 邢明杰(xmj@hellogcc)

GCC使用configure.ac(通过autoconf)来生成configure文件。顶层目录下的configure.ac有三千多行,用来在配置阶段做各种测试检测,并将结果替换到Makefile.in中,生成最终的Makefile。本文简单介绍了configure.ac中所要做的事请,并没有覆盖所有的细节问题。

1、导出原始的configure参数

progname=$0
# if PWD already has a value, it is probably wrong.
if test -n "$PWD" ; then PWD=`${PWDCMD-pwd}`; fi

# Export original configure arguments for use by sub-configures.
# Quote arguments with shell meta charatcers.
TOPLEVEL_CONFIGURE_ARGUMENTS=
set -- "$progname" "$@"
for ac_arg
do
  case "$ac_arg" in
  *" "*|*"      "*|*[[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\']]*)
    ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"`
    # if the argument is of the form -foo=baz, quote the baz part only
    ac_arg=`echo "'$ac_arg'" | sed "s/^'\([[-a-zA-Z0-9]]*=\)/\\1'/"` ;;
  *) ;;
  esac
  # Add the quoted argument to the list.
  TOPLEVEL_CONFIGURE_ARGUMENTS="$TOPLEVEL_CONFIGURE_ARGUMENTS $ac_arg"
done
if test "$silent" = yes; then
  TOPLEVEL_CONFIGURE_ARGUMENTS="$TOPLEVEL_CONFIGURE_ARGUMENTS --silent"
fi
# Remove the initial space we just introduced and, as these will be
# expanded by make, quote '$'.
TOPLEVEL_CONFIGURE_ARGUMENTS=`echo "x$TOPLEVEL_CONFIGURE_ARGUMENTS" | sed -e 's/^x *//' -e 's,\\$,$$,g'`
AC_SUBST(TOPLEVEL_CONFIGURE_ARGUMENTS)

这部分代码位于38-64行,用来将configure的参数保存到变量TOPLEVEL_CONFIGURE_ARGUMENTS中,以供子目录的configure使用。

2、一些基本的测试

# Find the build, host, and target systems.
ACX_NONCANONICAL_BUILD
ACX_NONCANONICAL_HOST
ACX_NONCANONICAL_TARGET
... ...
AC_CANONICAL_SYSTEM
AC_ARG_PROGRAM

m4_pattern_allow([^AS_FOR_TARGET$])dnl
m4_pattern_allow([^AS_FOR_BUILD$])dnl

# Get 'install' or 'install-sh' and its variants.
AC_PROG_INSTALL
ACX_PROG_LN
AC_PROG_LN_S
AC_PROG_SED
AC_PROG_AWK
...

从66到108行,测试build,host,target系统(这些命令在acx.m4中定义),测试install,ln,sed,awk。

3、确定哪些库和工具将被配置

# these library is used by various programs built for the build
# environment
#
build_libs="build-libiberty"

# these tools are built for the build environment
build_tools="build-texinfo build-flex build-bison build-m4 build-fixincludes"

# these libraries are used by various programs built for the host environment
#
host_libs="intl libiberty opcodes bfd readline tcl tk itcl libgui zlib libcpp libdecnumber gmp mpfr mpc isl cloog libelf libiconv"

# these tools are built for the host environment
# Note, the powerpc-eabi build depends on sim occurring before gdb in order to
# know that we are building the simulator.
# binutils, gas and ld appear in that order because it makes sense to run
# "make check" in that particular order.
# If --enable-gold is used, "gold" may replace "ld".
host_tools="texinfo flex bison binutils gas ld fixincludes gcc cgen sid sim gdb gprof etc expect dejagnu m4 utils guile fastjar gnattools"

# libgcj represents the runtime libraries only used by gcj.
libgcj="target-libffi \
        target-zlib \
        target-libjava"

# these libraries are built for the target environment, and are built after
# the host libraries and the host tools (which may be a cross compiler)
# Note that libiberty is not a target library.
target_libraries="target-libgcc \
                target-libgloss \
                target-newlib \
                target-libgomp \
                target-libatomic \
                target-libitm \
                target-libstdc++-v3 \
                target-libmudflap \
                target-libssp \
                target-libquadmath \
                target-libgfortran \
                target-boehm-gc \
                ${libgcj} \
                target-libobjc \
                target-libada \
                target-libgo"

# these tools are built using the target libraries, and are intended to
# run only in the target environment
#
# note: any program that *uses* libraries that are in the "target_libraries"
# list belongs in this list.
#
target_tools="target-rda"

这部分代码位于112-2036行,这部分代码主要是为了确定哪些库和工具将被配置。首先,定义变量build_libs, build_tools, host_libs, host_tools, target_libraries(这里没有使用target_libs,是因为target_libs变量在config-lang.in中已经被定义使用了,参见http://gcc.gnu.org/ml/gcc-patches/2003-06/msg02977.html), target_tools,用来列出所有可能需要的库和工具。

## All tools belong in one of the four categories, and are assigned above
## We assign ${configdirs} this way to remove all embedded newlines.  This
## is important because configure will choke if they ever get through.
## ${configdirs} is directories we build using the host tools.
## ${target_configdirs} is directories we build using the target tools.
configdirs=`echo ${host_libs} ${host_tools}`
target_configdirs=`echo ${target_libraries} ${target_tools}`
build_configdirs=`echo ${build_libs} ${build_tools}`

然后,定义变量configdirs, target_configdirs, build_configdirs,用来列出这些库和工具所对应的将要进行配置的源码目录。

# Skipdirs are removed silently.
skipdirs=
# Noconfigdirs are removed loudly.
noconfigdirs=""

然后,定义变量skipdirs和noconfigdirs,用来列出哪些目录将被跳过,或者不进行配置。其中skipdirs中的目录将被隐式的跳过,而noconfigdirs中的目录将会在终端显式的打印出消息,告知这些目录将不被配置。

use_gnu_ld=
# Make sure we don't let GNU ld be added if we didn't want it.
if test x$with_gnu_ld = xno ; then
  use_gnu_ld=no
  noconfigdirs="$noconfigdirs ld gold"
fi

use_gnu_as=
# Make sure we don't let GNU as be added if we didn't want it.
if test x$with_gnu_as = xno ; then
  use_gnu_as=no
  noconfigdirs="$noconfigdirs gas"
fi
... ...

接下来,就是根据configure的各种选项,来设置skipdirs和noconfigdirs的值。

# Remove the entries in $skipdirs and $noconfigdirs from $configdirs,
# $build_configdirs and $target_configdirs.
# If we have the source for $noconfigdirs entries, add them to $notsupp.

notsupp=""
for dir in . $skipdirs $noconfigdirs ; do
  dirname=`echo $dir | sed -e s/target-//g -e s/build-//g`
  if test $dir != .  && echo " ${configdirs} " | grep " ${dir} " >/dev/null 2>&1; then
    configdirs=`echo " ${configdirs} " | sed -e "s/ ${dir} / /"`
    if test -r $srcdir/$dirname/configure ; then
      if echo " ${skipdirs} " | grep " ${dir} " >/dev/null 2>&1; then
        true
      else
        notsupp="$notsupp $dir"
      fi
    fi
  fi
  if test $dir != .  && echo " ${build_configdirs} " | grep " ${dir} " >/dev/null 2>&1; then
    build_configdirs=`echo " ${build_configdirs} " | sed -e "s/ ${dir} / /"`
    if test -r $srcdir/$dirname/configure ; then
      if echo " ${skipdirs} " | grep " ${dir} " >/dev/null 2>&1; then
        true
      else
        notsupp="$notsupp $dir"
      fi
    fi
  fi
  if test $dir != . && echo " ${target_configdirs} " | grep " ${dir} " >/dev/null 2>&1; then
    target_configdirs=`echo " ${target_configdirs} " | sed -e "s/ ${dir} / /"`
    if test -r $srcdir/$dirname/configure ; then
      if echo " ${skipdirs} " | grep " ${dir} " >/dev/null 2>&1; then
        true
      else
        notsupp="$notsupp $dir"
      fi
    fi
  fi
done
... ...

最后,从configdirs, target_configdirs, build_configdirs中,移除在skipdirs和noconfigdirs中存在的目录项。并且,移除那些无法进行配置(没有configure文件)的目录。

4、测试flags,复制目录

AC_ARG_WITH([build-sysroot],
  [AS_HELP_STRING([--with-build-sysroot=SYSROOT],
                  [use sysroot as the system root during the build])],
  [if test x"$withval" != x ; then
     SYSROOT_CFLAGS_FOR_TARGET="--sysroot=$withval"
   fi],
  [SYSROOT_CFLAGS_FOR_TARGET=])
AC_SUBST(SYSROOT_CFLAGS_FOR_TARGET)
... ...

从2046到2206行,这部分代码设定了CFLAGS_FOR_TARGET,CXXFLAGS_FOR_TARGET,LDFLAGS_FOR_TARGET;并且对选项–with-headers=XXX,–with-libs=XXX做了处理,分别将目录下的内容复制到$(tooldir)/sys-include和$(tooldir)/lib下。

5、设定Makefile片段(frag)

# Work in distributions that contain no compiler tools, like Autoconf.
host_makefile_frag=/dev/null
if test -d ${srcdir}/config ; then
case "${host}" in
  i[[3456789]]86-*-msdosdjgpp*)
    host_makefile_frag="config/mh-djgpp"
    ;;
  *-cygwin*)
    ACX_CHECK_CYGWIN_CAT_WORKS
    host_makefile_frag="config/mh-cygwin"
    ;;
... ...
# Makefile fragments.
for frag in host_makefile_frag target_makefile_frag alphaieee_frag ospace_frag;
do
  eval fragval=\$$frag
  if test $fragval != /dev/null; then
    eval $frag=${srcdir}/$fragval
  fi
done
AC_SUBST_FILE(host_makefile_frag)
AC_SUBST_FILE(target_makefile_frag)
AC_SUBST_FILE(alphaieee_frag)
AC_SUBST_FILE(ospace_frag)

这部分代码位于1074-1107,2226-2280,2871-2882行,用来设定host_makefile_frag,target_makefile_frag,alphaieee_frag,ospace_frag这些makefile片段的值。

6、gdb相关

# Create a .gdbinit file which runs the one in srcdir
# and tells GDB to look there for source files.

if test -r ${srcdir}/.gdbinit ; then
  case ${srcdir} in
    .) ;;
    *) cat > ./.gdbinit <

代码2287-2301行,用来创建.gdbinit文件,方便调试gcc。

# Determine whether gdb needs tk/tcl or not.
# Use 'maybe' since enable_gdbtk might be true even if tk isn't available
# and in that case we want gdb to be built without tk.  Ugh!
# In fact I believe gdb is the *only* package directly dependent on tk,
# so we should be able to put the 'maybe's in unconditionally and
# leave out the maybe dependencies when enable_gdbtk is false.  I'm not
# 100% sure that that's safe though.

gdb_tk="maybe-all-tcl maybe-all-tk maybe-all-itcl maybe-all-libgui"
case "$enable_gdbtk" in
  no)
    GDB_TK="" ;;
  yes)
    GDB_TK="${gdb_tk}" ;;
  *)
    # Only add the dependency on gdbtk when GDBtk is part of the gdb
    # distro.  Eventually someone will fix this and move Insight, nee
    # gdbtk to a separate directory.
    if test -d ${srcdir}/gdb/gdbtk ; then
      GDB_TK="${gdb_tk}"
    else
      GDB_TK=""
    fi
    ;;
esac
CONFIGURE_GDB_TK=`echo ${GDB_TK} | sed s/-all-/-configure-/g`
INSTALL_GDB_TK=`echo ${GDB_TK} | sed s/-all-/-install-/g`

代码2352-2378行,用来确定gdb是否需要tk/tcl。这里作者提到一个他认为可以进行改进,但又不太确定的地方。

7、去掉Makefile中不需要的目标(target)

extrasub_build=
for module in ${build_configdirs} ; do
  if test -z "${no_recursion}" \
     && test -f ${build_subdir}/${module}/Makefile; then
    echo 1>&2 "*** removing ${build_subdir}/${module}/Makefile to force reconfigure"
    rm -f ${build_subdir}/${module}/Makefile
  fi
  extrasub_build="$extrasub_build
/^@if build-$module\$/d
/^@endif build-$module\$/d
/^@if build-$module-$bootstrap_suffix\$/d
/^@endif build-$module-$bootstrap_suffix\$/d"
done
... ...
AC_CONFIG_FILES([Makefile],
  [sed "$extrasub_build" Makefile |
   sed "$extrasub_host" |
   sed "$extrasub_target" > mf$$
   mv -f mf$$ Makefile],
  [extrasub_build="$extrasub_build"
   extrasub_host="$extrasub_host"
   extrasub_target="$extrasub_target"])
AC_OUTPUT

这部分代码位于2382-2392,2445-2497,3199-3207行,用来删除掉Makefile(或者Makefile.in)中不需要的目标。
Makefile.in文件中有许多@if和@endif包裹的模块。configure.ac中定义了变量extrasub_build,extrasub_host,
extrasub_target,它们是根据build_configdirs,configdirs,target_configdirs的内容而定义的sed语句。

在最后的AC_CONFIG_FILES命令中,将会调用这些sed语句,修改Makefile,对@if语句块进行选择性的删除。

8、设定BUILD_CONFIG变量,以调整顶层makefile

# Adjust the toplevel makefile according to whether bootstrap was selected.
case $enable_bootstrap in
  yes)
    bootstrap_suffix=bootstrap
    BUILD_CONFIG=bootstrap-debug
    ;;
  no)
    bootstrap_suffix=no-bootstrap
    BUILD_CONFIG=
    ;;
esac
... ...
AC_MSG_RESULT($BUILD_CONFIG)

这部分代码位于2401-2443行,根据是否选择了bootstrap,来设定BUILD_CONFIG变量的值。
Makefile中会根据该变量的值将config子目录下相应的mk文件包含进来。

9、串行化configure

# Create the serialization dependencies.  This uses a temporary file.

AC_ARG_ENABLE([serial-configure],
[AS_HELP_STRING([[--enable-serial-[{host,target,build}-]configure]],
                [force sequential configuration of
                 sub-packages for the host, target or build
                 machine, or all sub-packages])])
... ...
serialization_dependencies=serdep.tmp
AC_SUBST_FILE(serialization_dependencies)

这部分代码位于2499-2547行,用来实现对串行化configure的支持。

10、对自举(bootstrap)的支持

# ---------------------
# GCC bootstrap support
# ---------------------

# Stage specific cflags for build.
stage1_cflags="-g"
case $build in
  vax-*-*)
    case ${GCC} in
      yes) stage1_cflags="-g -Wa,-J" ;;
      *) stage1_cflags="-g -J" ;;
    esac ;;
esac
... ...

这部分代码位于3118-3197行,用来设定不同阶段的命令行选项(比如stage1_cflags),
指定哪些文件在自举过程中不需要进行比较操作。

1

GNU Tools Cauldron (1)

[第一篇和技术无关,关心技术的读者可以直接跳到第二篇]

今年年初的时候,无缘无故的收到老板的邀请,可以来参加今年的 GNU Tools Cauldron,在布拉格。那个时候,这个活动正在call for participant。一口就答应了,高兴之余,就开始订机票,酒店,还有签证。签证比较麻烦,前后折腾了两个礼拜,不过后来的结果证明这两个礼拜还是值得的。

七月七日上午,天气十分闷热,我打车去机场,和teawater汇合。担心的暴雨没有下,一切顺利,登机起飞。飞机上感觉挺舒服,9个小时后,我们就到了德国的法兰克福。没有左右乱看,就去找转机的登机口。入关,安检一切顺利。找到登机口以后,感觉踏实一些,看到了旁边的一个咖啡馆,有卖啤酒的。想着,来了德国,不喝啤酒多可惜,就要了两杯啤酒。喝着还行吧。

去布拉格的飞机,是小飞机。让我吃惊的是,竟然需要做摆渡车才能到飞机那里。五十分钟就到布拉格,但是飞机晚起飞了一个小时,不过飞机上的点心,很好吃,也就没有太多抱怨了。

到了布拉格,我在等行李,teawater去换钱,打车。机场到酒店大概不到20公里吧,到了酒店,check in,下午六点多。东西放了,出去转了转。晚上九点吃了在布拉格的第一顿,还不错。

周日一天都在外边转,到了晚上,GNU Tools Cauldron有个接待会,我们去那里,登记,领了一件体恤,然后大厅里边就是玲琅满目的吃的和喝的。每个人都有一个胸牌,写着自己的名字。大家就开始互相聊天了。见到了Pedro, Stan,Luis, 这些人以前都见过。剩下的人就都没有见过了,看着别人的胸牌。第一个看到的是Diego,人比照片上看着老一些,不过和很多人都认识,我没有搭讪。后来,碰到了David Edelson,一如既往的梳着小辫子。他是IBM的,所以,我六年前就知道他,知道他留着辫子。和他聊了聊GROW,他好像办的还很高兴,我告诉他我们每年在中国也有类似的关于gcc的活动,他并不吃惊。只是说,他们知道中国最近对gcc很有兴趣,也在考虑这么来到中国。后来,我找到了一个网名在kcc的俄罗斯人,我们很早之前在网上交流过,关于race detector的一些讨论。聊了聊他们的工作,和我为什么不继续做race detector了。他们做的很不错,在对native程序检查方面,但是好像他们在java方面还是没有太多进展。后来见到了Jan,很害羞的一个人,不怎么爱说话,还挺帅。最后,看见了RMS,他一个人过来,竟然没有一个人答理他,所有人继续聊自己的。他和几个人说了几句,就不见了。

到了晚上十点多,就散了,我们几个继续到一个酒吧,喝点啤酒,继续聊天。