OpenBMC debug build
为了进行 gdb 调试,构建调试版本是前提,可以通过定义 `DEBUG_BUILD` 来启用调试版本的构建。

build type

OpenBMC 的构建类型及选项由如下变量定义:

// meta/conf/bitbake.conf
DEBUG_FLAGS ?= "-g -feliminate-unused-debug-types ${DEBUG_PREFIX_MAP}"

FULL_OPTIMIZATION = "-O2 -pipe ${DEBUG_FLAGS}"
DEBUG_OPTIMIZATION = "-Og ${DEBUG_FLAGS} -pipe"
SELECTED_OPTIMIZATION = "${@d.getVar(oe.utils.vartrue('DEBUG_BUILD', 'DEBUG_OPTIMIZATION', 'FULL_OPTIMIZATION', d))}"
BUILD_OPTIMIZATION = "${@oe.utils.vartrue('DEBUG_BUILD', '-Og -g -feliminate-unused-debug-types', '-O2', d)} -pipe"
  • FULL_OPTIMIZATION
    The options to pass in TARGET_CFLAGS and CFLAGS when compiling an optimized system. This variable defaults to “-O2 -pipe ${DEBUG_FLAGS}”.

  • DEBUG_OPTIMIZATION
    The options to pass in TARGET_CFLAGS and CFLAGS when compiling a system for debugging. This variable defaults to “-O -fno-omit-frame-pointer ${DEBUG_FLAGS} -pipe”.

To improve the debug information accuracy, you can reduce the level of optimization used by the compiler. For example, when adding the following line to your local.conf file, you will reduce optimization from FULL_OPTIMIZATION of “-O2” to DEBUG_OPTIMIZATION of “-O -fno-omit-frame-pointer”.

Debugging Tools and Techniques
https://docs.yoctoproject.org/dev-manual/debugging.html

debug build

通过定义 DEBUG_BUILD 变量可以使能调试版本的构建:

❯ vi build/romulus/conf/local.conf
DEBUG_BUILD = "1"
DEBUG_FLAGS = "-ggdb3 ${DEBUG_PREFIX_MAP}"
BUILD_OPTIMIZATION = ""

这些选项也可以加到 bb/bbapend 文件中,这样就只针对单个应用生效。

❯ bitbake bmcweb -e | grep ^DEBUG_BUILD
DEBUG_BUILD="1"

❯ bitbake bmcweb -e | grep ^DEBUG_FLAGS
DEBUG_FLAGS="-ggdb3 -fcanon-prefix-map  -fmacro-prefix-map=/home/runsisi/working/bmc/openbmc/build/romulus/workspace/sources/bmcweb=/usr/src/debug/bmcweb/1.0+git  -fdebug-prefix-map=/home/runsisi/working/bmc/openbmc/build/romulus/workspace/sources/bmcweb=/usr/src/debug/bmcweb/1.0+git  -fmacro-prefix-map=/home/runsisi/working/bmc/openbmc/build/romulus/tmp/work/arm1176jzs-openbmc-linux-gnueabi/bmcweb/1.0+git/bmcweb-1.0+git=/usr/src/debug/bmcweb/1.0+git  -fdebug-prefix-map=/home/runsisi/working/bmc/openbmc/build/romulus/tmp/work/arm1176jzs-openbmc-linux-gnueabi/bmcweb/1.0+git/bmcweb-1.0+git=/usr/src/debug/bmcweb/1.0+git  -fdebug-prefix-map=/home/runsisi/working/bmc/openbmc/build/romulus/tmp/work/arm1176jzs-openbmc-linux-gnueabi/bmcweb/1.0+git/recipe-sysroot=  -fmacro-prefix-map=/home/runsisi/working/bmc/openbmc/build/romulus/tmp/work/arm1176jzs-openbmc-linux-gnueabi/bmcweb/1.0+git/recipe-sysroot=  -fdebug-prefix-map=/home/runsisi/working/bmc/openbmc/build/romulus/tmp/work/arm1176jzs-openbmc-linux-gnueabi/bmcweb/1.0+git/recipe-sysroot-native= "

❯ bitbake bmcweb -e | grep ^BUILD_OPTIMIZATION
BUILD_OPTIMIZATION=""

注意不能去掉 DEBUG_OPTIMIZATION 定义中的 -Og,否则会出现如下的错误:

/home/runsisi/working/bmc/openbmc/build/romulus/tmp/work/arm1176jzs-openbmc-linux-gnueabi/glibc/2.38+git/build-arm-openbmc-linux-gnueabi/dl-tunable-list.h
| In file included from <command-line>:
| ./../include/libc-symbols.h:75:3: error: #error "glibc cannot be compiled without optimization"
|    75 | # error "glibc cannot be compiled without optimization"
|       |   ^~~~~
| sed -e 's/#.*$//' -e '/^[     ]*$/d' ../abi-tags | \
| while read conf tagos tagver; do \
|   test `expr 'arm-openbmc-linux-gnueabi' \
|            : "$conf"` != 0 || continue; \
|   ( echo "$tagos" | \
|     sed -e 's/[^0-9xXa-fA-F   ]//' \
|       -e 's/^/#define __ABI_TAG_OS /'; \
|     echo "#ifndef __ABI_TAG_VERSION"; \
|     echo "$tagver" | \
|     sed -e 's/[^0-9xXa-fA-F]/ /g' -e 's/ *$//' \
|       -e 's/ /,/g' -e 's/^/# define __ABI_TAG_VERSION /'; \
|     echo "#endif" ) > /home/runsisi/working/bmc/openbmc/build/romulus/tmp/work/arm1176jzs-openbmc-linux-gnueabi/glibc/2.38+git/build-arm-openbmc-linux-gnueabi/csu/abi-tag.h.new; \
| done
| make[2]: *** [../Makeconfig:1258: /home/runsisi/working/bmc/openbmc/build/romulus/tmp/work/arm1176jzs-openbmc-linux-gnueabi/glibc/2.38+git/build-arm-openbmc-linux-gnueabi/gcc-macros.h.in] Error 1
| make[2]: *** Waiting for unfinished jobs....

Normally later options on the line override ones passed previously.

How does GCC behave if passed conflicting compiler flags?
https://stackoverflow.com/questions/15909788/how-does-gcc-behave-if-passed-conflicting-compiler-flags

boolean value

之所以上面 DEBUG_BUILD 的值可以是 1 也可以是 true 是因为如下的处理:

// bitbake/lib/bb/utils.py

def to_boolean(string, default=None):
    """
    Check input string and return boolean value True/False/None
    depending upon the checks
    """
    if not string:
        return default

    if isinstance(string, int):
        return string != 0

    normalized = string.lower()
    if normalized in ("y", "yes", "1", "true"):
        return True
    elif normalized in ("n", "no", "0", "false"):
        return False
    else:
        raise ValueError("Invalid value for to_boolean: %s" % string)

最后修改于 2024-01-03