构建CPython时禁用编译器优化

时间:2018-08-12 04:33:09

标签: python c makefile gdb

我一直与Philip Guo的excellent series一起关注CPython的内部结构,并一直在GDB中浏览解释器的代码。不幸的是,当我单步执行代码,不按顺序执行指令(例如一系列赋值操作,没什么花哨的东西)时,GDB似乎跳了很多。

据我了解,这是由于编译器优化所致。实际上,CPython的configure文件似乎默认为-O2。在使用./configuremake编译Python 2.7.15时,情况就是这样:

gcc -pthread -c -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes  -I. -IInclude -I./Include   -DPy_BUILD_CORE -o Modules/python.o ./Modules/python.c
gcc -pthread -c -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes  -I. -IInclude -I./Include   -DPy_BUILD_CORE -o Parser/acceler.o Parser/acceler.c
gcc -pthread -c -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes  -I. -IInclude -I./Include   -DPy_BUILD_CORE -o Parser/grammar1.o Parser/grammar1.c
gcc -pthread -c -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes  -I. -IInclude -I./Include   -DPy_BUILD_CORE -o Parser/listnode.o Parser/listnode.c
...

我尝试通过不进行优化而通过./configure CFLAGS="-g -O0"进行配置并再次使用make进行编译来解决此问题(请注意,将每一行从-fno-strict-aliasing -g -O2更改为-fno-strict-aliasing -g -O0):

gcc -pthread -c -fno-strict-aliasing -g -O0 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes  -I. -IInclude -I./Include   -DPy_BUILD_CORE -o Modules/python.o ./Modules/python.c
gcc -pthread -c -fno-strict-aliasing -g -O0 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes  -I. -IInclude -I./Include   -DPy_BUILD_CORE -o Parser/acceler.o Parser/acceler.c
gcc -pthread -c -fno-strict-aliasing -g -O0 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes  -I. -IInclude -I./Include   -DPy_BUILD_CORE -o Parser/grammar1.o Parser/grammar1.c
gcc -pthread -c -fno-strict-aliasing -g -O0 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes  -I. -IInclude -I./Include   -DPy_BUILD_CORE -o Parser/listnode.o Parser/listnode.c
...

不幸的是,当我单步执行代码时,GDB仍然跳来跳去。为了完整起见,这是我与GDB一起运行的命令:

gdb --args ./python test.py

test.py的内容只是一些基本的算术和打印函数,它们实际上并不相关。

我对这些步骤中至少一个的理解必须是不完整的。我是否将优化标志设置不正确? GDB是否由于其他原因在指令之间跳转?任何建议将不胜感激。谢谢!

1 个答案:

答案 0 :(得分:1)

tl; dr:您需要configure设置--with-pydebug

-O3之后的命令行上有一个-O2,因此将-O2更改为-O0并没有任何好处。 -O3仍然会覆盖它。您需要找出-O3的来源并将其删除。

如果您查看生成的Makefile,应该会看到类似这样的内容:

# Compiler options
OPT=        -DNDEBUG -g -fwrapv -O3 -Wall
# ...
# Avoid assigning CFLAGS, LDFLAGS, etc. so users can use them on the
# command line to append to these values without stomping the pre-set
# values.
PY_CFLAGS=  $(BASECFLAGS) $(OPT) $(CONFIGURE_CFLAGS) $(CFLAGS) $(EXTRA_CFLAGS)

您当然可以编辑生成的Makefile,将-O3更改为-O0。但是,如果您查看configure脚本和Makefile.pre的内部,则可以看到它的来源:它是默认值,在这种情况下仅被替换:

case $ac_cv_prog_cc_g in
yes)
    if test "$Py_DEBUG" = 'true' ; then
    # Optimization messes up debuggers, so turn it off for
    # debug builds.
            if "$CC" -v --help 2>/dev/null |grep -- -Og > /dev/null; then
                OPT="-g -Og -Wall"
            else
                OPT="-g -O0 -Wall"
            fi
    else
    OPT="-g $WRAP -O3 -Wall"
    fi
    ;;

这还会为gcc以外的其他编译器设置正确的标志。

但是,--with-pydebug的主要作用是启用Py_DEBUG,如果您正在对CPython进行源调试,则可能需要启用{{3}},但这与-O0是分开的。是您真正要问的问题。因此,据我所知,如果只想要 -O0,您唯一可以做的就是编辑Makefile(或提出一些复杂的env变量集和configure参数引诱它进行调试构建,但随后未启用Py_DEBUG)。