本文是F7LY开发中遇到的一个问题,裸机环境本来都是freestanding的,记录一下解决过程。
当我发现一个for循环语法用不了时,我想把cpp的标准从17提升到20进行编译,但是一提升报了一万个错出来 提示的都是各种重定义:
from kernel/boot/riscv/main.cc:12:
kernel/libs/klib.hh:56:16: error: conflicting declaration of ‘int vsnprintf(char*, size_t, const char*, va_list)’ with ‘C++’ linkage
56 | int vsnprintf( char *str, size_t size, const char *format, va_list ap );
| ^~~~~~~~~
In file included from /usr/riscv64-linux-gnu/include/features.h:502,
from /usr/riscv64-linux-gnu/include/sys/types.h:25,
from kernel/devs/../types.hh:4,
from kernel/devs/spinlock.hh:5,
from kernel/devs/uart.hh:3,
from kernel/boot/riscv/main.cc:1:
/usr/riscv64-linux-gnu/include/bits/stdio2.h:65:1: note: previous declaration with ‘C’ linkage
65 | __NTH (vsnprintf (char *__restrict __s, size_t __n,
| ^~~~~
In file included from /usr/riscv64-linux-gnu/include/time.h:33,
from /usr/riscv64-linux-gnu/include/pthread.h:23,
from /usr/riscv64-linux-gnu/include/c++/11/riscv64-linux-gnu/bits/gthr-default.h:35,
from /usr/riscv64-linux-gnu/include/c++/11/riscv64-linux-gnu/bits/gthr.h:148,
from /usr/riscv64-linux-gnu/include/c++/11/bits/atomic_wait.h:38,
from /usr/riscv64-linux-gnu/include/c++/11/bits/atomic_base.h:41,
from /usr/riscv64-linux-gnu/include/c++/11/atomic:41,
from kernel/devs/spinlock.hh:7,
from kernel/devs/uart.hh:3,
from kernel/boot/riscv/main.cc:1:
kernel/tm/time.hh:28:17: error: expected identifier before numeric constant
28 | CLOCK_REALTIME = 0,
| ^~~~~~~~~~~~~~fuck 不管加多少个-ffreestanding,-nostdlib这种标志都没用。 仔细一看unistd.h,这是怎么包含进来的,我怎么都不会用到这个库吧? 于是陷入深深的崩溃之中。 经高人指点,告诉我可以搜索什么地方可能会包含unistd。所以对所有的包含了的标准库都开始检索。 下面是<atomic>里面<atomic_base>的代码
#if __cplusplus > 201703L && _GLIBCXX_HOSTED
#include <bits/atomic_wait.h>
#endif那很明显就是17一改就多包含了 然后在atomic_wait里就看到了那几个报错的源头:
#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
# include <cerrno>
# include <climits>
# include <unistd.h>
# include <syscall.h>
# include <bits/functexcept.h>
#endif好的,那么这个宏我怎么取消呢?这个宏(包括 _GLIBCXX_HOSTED)定义在c++config里面
/* Define to 1 if you have the <link.h> header file. */
#define _GLIBCXX_HAVE_LINK_H 1
/* Define if futex syscall is available. */
#define _GLIBCXX_HAVE_LINUX_FUTEX 1
/* Define to 1 if you have the <linux/random.h> header file. */
#define _GLIBCXX_HAVE_LINUX_RANDOM_H 1然后根本无法被重覆盖定义,如果改这个文件,以后用cpp的时候有你好看的。 怎么办呢? 那么,为什么学长他们的代码没有爆呢?我们重读一下代码
#include <atomic>
namespace hsai
{
...确实是包含了atomic,当我看了下别人修改学长的时候,发现别人的突然变成了
#include <EASTL/atomic.h>欸怎么就没有了。 然后我满心欢喜地去改我的,然后发现EASTL没有atomic,噢原来是.h啊,那没事.
不过蒙老师又告诉我是可以修的,_GLIBCXX_HOSTED这个宏应该是主机环境生效
/* Define to 1 if a full hosted library is built, or 0 if freestanding. */
#define _GLIBCXX_HOSTED __STDC_HOSTED__但是,我加了-ffreestanding依然没有生效,为什么呢?
高人又让我看看编译参数的顺序 ,有时候顺序也会出问题
CFLAGS := -Wall -Werror -ffreestanding -O2 -fno-builtin -g -fno-stack-protector $(ARCH_CFLAGS)
CXXFLAGS := $(CFLAGS) -std=c++23 -nostdlib \
-DEA_PLATFORM_LINUX -DEA_PLATFORM_POSIX \
-DEA_PROCESSOR_RISCV -DEA_ENDIAN_LITTLE=1 \
-Wno-deprecated-declarations -Wno-strict-aliasing \
-fno-exceptions -fno-rtti -Wno-maybe-uninitialized但是这里确实使用了-ffreestanding 网上似乎有信息。 103626 – _GLIBCXX_HOSTED should respect -ffreestanding_
Jonathan Wakely 2021-12-09 11:05:34 UTC
Libstdc++ should not define _GLIBCXX_HOSTED to 1 when __STD_HOSTED__ == 0 i.e. when -ffreestanding is used.但是我发现这个是21年的bug,已经被修复了,修复的方法就是#define _GLIBCXX_HOSTED __STDC_HOSTED__,那为什么还有bug?注意这一句评论:
Jonathan Wakely 2022-09-17 22:19:14 UTC
I don't think we need to add the #error to every header. For a start, users never include the bits/* headers directly, and if they do, it's their problem. So we only need to mark the standard headers as hosted-only. And if we add it to <iosfwd>, that already covers a large number of them, because they include that.所以这个b说我们不应该直接包含bits文件夹下的文件,那不然是我们的问题。但是我包含了<atomic>也会包含你们bit目录下的文件,也没有被控制到。 他们的意见是:
- 不需要特别处理内部头文件(比如
bits/*),因为它们在 freestanding 下不会被安装。- 这部分标记和处理是冗余的,他说他会清理掉这部分。 呃,所以好像这就是bug。不过我没有发现bug的原因,这里应该是__STD_HOSTED__ 这个宏就出错了。
我尝试直接打印出那个宏来
printfBlue("_GLIBCXX_HOSTED:%d\n",_GLIBCXX_HOSTED);_GLIBCXX_HOSTED:1
那我就很费解,于是加了一行
printfBlue("__STDC_HOSTED__:%d\n", __STDC_HOSTED__);STDC_HOSTED:0 好的,关键信息来了。我们查资料知道了旧版本中它是硬编码 1 的,无论是否 freestanding。 这个问题在 GCC 11 被记录,在 GCC 13 中被修复(取决于你使用的具体发行版或交叉工具链版本)。
所以,可能是我工具链的版本问题
$ riscv64-linux-gnu-g++ --version
riscv64-linux-gnu-g++ (Ubuntu 11.4.0-9ubuntu1) 11.4.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.好的,意味着我要换版本,最新版13已经没有问题。