g++中的常用编译参数(持续更新-编译常见错误)

C++编译选项与优化:从64位目标到AVX-512支持
文章详细解释了C++编译器命令行选项,包括生成64位代码、启用各种指令集、优化级别、内存模型设置,以及在Python、Docker和Bazel构建环境中遇到的问题及解决方案。
g++ -m64 -c -o *.o -g -Ofast -std=c++11 -mcx16 -m64 -maes -mfpmath=sse -mavx512f -mavx512dq -mavx512ifma -mavx512cd -mavx512bw -mavx512vl -mavx512vbmi -march=x86-64 -mcmodel=large -Wall -Wno-write-strings -fno-defer-pop -fsigned-char -pipe
  • -m64:生成64位目标文件。指定生成64位代码。
  • -c:只编译源文件,生成目标文件,而不进行链接。常用于生成目标文件以供后续链接。
  • -o *.o:指定编译输出的目标文件名。这里的*.o表示输出的目标文件名是根据源文件自动生成的。
  • -g:生成调试信息。使得编译生成的目标文件包含调试信息,方便调试程序。
  • -Ofast:启用快速优化。该选项打开了多个优化选项,这样编译器可以尽量优化代码运行速度。
  • -std=c++11:指定使用的C++标准版本为C++11。这个参数告诉编译器要按照C++11的标准进行编译。
  • -mcx16:启用扩展处理器功能。该选项启用了对扩展处理器功能的支持。
  • -maes:启用AES指令集。该选项启用了对AES指令集的支持。
  • -mfpmath=sse:使用SSE指令集进行浮点数运算。该选项指定使用SSE指令集进行浮点数运算,提高程序的执行效率。
  • -mavx512f:启用AVX-512指令集的基础指令。该选项启用了AVX-512指令集的基础指令支持。
  • -mavx512dq:启用AVX-512双字队列指令。该选项启用了AVX-512双字队列指令的支持。
  • -mavx512ifma:启用AVX-512整数乘法指令。该选项启用了AVX-512整数乘法指令的支持。
  • -mavx512cd:启用AVX-512冲突检测指令。该选项启用了AVX-512冲突检测指令的支持。
  • -mavx512bw:启用AVX-512字节/字/字块指令。该选项启用了AVX-512字节/字/字块指令的支持。
  • -mavx512vl:启用AVX-512向量长度指令。该选项启用了AVX-512向量长度指令的支持。
  • -mavx512vbmi:启用AVX-512位变换指令。该选项启用了AVX-512位变换指令的支持。
  • -march=x86-64:生成编译针对x86-64架构的代码。指定生成针对x86-64架构的目标代码。
  • -mcmodel=large:使用大模型内存模型。该选项指定使用较大的内存模型,以便处理大型数据和代码。
  • -Wall:打开警告选项。该选项打开所有警告信息,使得编译器可以提示潜在的问题。
  • -Wno-write-strings:关闭字符串字面值警告。该选项关闭字符串字面值赋值给非const char*类型的警告。
  • -fno-defer-pop:不推迟栈指针的修复。该选项告诉编译器不要推迟修复栈指针,以提高程序的性能。
  • -fsigned-char:将char类型视为有符号类型。该选项告诉编译器将char类型视为有符号类型。
  • -pipe:使用管道而不是临时文件。该选项使用管道来进行编译和链接过程中的数据传输,提高编译速度。

其中各个参数可根据自己需要修改,比如m64可以是m32,-Ofast可以是-O3等等,这里仅仅列举了极少部分,但我理解这些指令集应该也比较常用。

1、***.o:(debug_info+0x1e6026):relocation truncated to fit: R_X86_64_32 agaunst ‘.debug_loc’
增加-gno-variable-location-views flag。

2、error: invalid conversion from ‘long int’ to ‘U8*’ {aka ‘unsigned char*’} [-fpermissive]
增加-fpermissive

3、编译libyang时候AttributeError: module ‘pip’ has no attribute ‘locations’ #13
https://github.com/YangCatalog/yang-validator-extractor/issues/13
修改为location = None
try:
import pip.locations as locations
location = locations.distutils_scheme(‘pyang’)
except:
try:
import pip._internal.locations as locations
location = locations.distutils_scheme(‘pyang’)
except:
pass
if location is not None:
self.dirs.append(os.path.join(location[‘data’],
‘share’,‘yang’,‘modules’))

4、python3没有生成libpython3.6m.so.1.0

../configure --enable-shared  --enable-profiling --enable-optimizations

5、docker pull失败 配置 proxy
[root@QCl2opt build]# docker pull hello-world
Using default tag: latest
Error response from daemon: Get “https://registry-1.docker.io/v2/”: proxyconnect tcp: tls: first record does not look like a TLS handshake

mkdir /etc/systemd/system/docker.service.d
vi /etc/systemd/system/docker.service.d/proxy.conf
 
[Service]
 
Environment="HTTP_PROXY=http://10.71.132.38:80" 
Environment="NO_PROXY=localhost,127.0.0.0/8,10.0.0.0/8,192.168.0.0/16,172.16.0.0/12"
Environment="HTTPS_PROXY=http://10.71.132.38:80"
 
systemctl daemon-reload
systemctl restart docker

6、redhat8 bazel编译tcmalloc出错。
https://github.com/google/tcmalloc

[root@QCl2opt tcmalloc]# python
Python 3.6.6 (default, Nov 13 2023, 01:01:46)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from importlib.resources import read_binary
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'importlib.resources'
>>> import importlib.resources
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'importlib.resources'

但其实这个module已经安装了

[root@QCl2opt tcmalloc]# pip install importlib.resources
Requirement already satisfied: importlib.resources in /usr/local/lib/python3.6/site-packages (5.4.0)
Requirement already satisfied: zipp>=3.1.0 in /usr/local/lib/python3.6/site-packages (from importlib.resources) (3.6.0)

使用的 Python 版本太旧导致的。importlib.resources 是在 Python 3.7 版本中引入的模块,因此在 Python 3.6 中使用它可能会出现问题。

要解决这个问题,您可以升级到 Python 3.7 或更高版本,或者尝试使用 importlib_resources 替代 importlib.resourcesimportlib_resources 是一个 Python 包,可以在 Python 2.7、3.4、3.5 和 3.6 中使用,提供了与 importlib.resources 相同的 API。

尝试安装 importlib_resources 并使用它来读取二进制文件:

pip install importlib_resources

然后替换使用以下语句:

from importlib_resources import read_binary

然后遇到

rules_python编译错误bazel

rules_python/python/pip_install/pip_repository.bzl", line 241, column 13, in _pip_repository_impl
                fail("rules_python failed: %s (%s)" % (result.stdout, result.stderr))
Error in fail: rules_python failed:  (Traceback (most recent call last):

pip_repository.bzl 内容如下,241是fail的地方,
    result = rctx.execute(
        args,
        # Manually construct the PYTHONPATH since we cannot use the toolchain here
        environment = _create_repository_execution_environment(rctx),
        timeout = rctx.attr.timeout,
        quiet = rctx.attr.quiet,
    )

    if result.return_code:
        fail("rules_python failed: %s (%s)" % (result.stdout, result.stderr))

升级python从3.6到3.8解决了。

#remove 3.6
whereis python3 |xargs rm -frv
whereis pip
rm /usr/local/bin/pip
#build and install 3.8
wget https://www.python.org/ftp/python/3.8.1/Python-3.8.1.tgz
tar -xf Python-3.8.1.tgz
cd Python-3.8.1/
mkdir build
cd build/
#--shared 生成动态库
../configure --enable-shared --enable-profiling --enable-optimizations
make -j8
make altinstall
ln -s /usr/local/bin/python3.8 /usr/bin/python3
ln -s /usr/local/bin/pip3 /usr/local/bin/pip
#如果找不到python的so,默认安装在这个路径
export LD_LIBRARY_PATH=/usr/local/lib/:$LD_LIBRARY_PATH

然后遇到:

[root@QCl2opt tcmalloc]# bazel test //tcmalloc/...
INFO: Analyzed 924 targets (0 packages loaded, 0 targets configured).
INFO: Found 125 targets and 799 test targets...
ERROR: /root/tcmalloc-4/tcmalloc-master/tcmalloc/internal/BUILD:552:11: Compiling tcmalloc/internal/percpu_rseq_asm.S failed: (Exit 1): gcc failed: error executing command (from target //tcmalloc/internal:percpu) /usr/bin/gcc -U_FORTIFY_SOURCE -fstack-protector -Wall -Wunused-but-set-parameter -Wno-free-nonheap-object -fno-omit-frame-pointer -MD -MF ... (remaining 28 arguments skipped)

Use --sandbox_debug to see verbose messages from the sandbox and retain the sandbox build root for debugging
tcmalloc/internal/percpu_rseq_asm.S: Assembler messages:
tcmalloc/internal/percpu_rseq_asm.S:33: Error: junk at end of line, first unrecognized character is `,'
INFO: Elapsed time: 2.094s, Critical Path: 1.46s

在这里插入图片描述

7、libssh0.7.5 ge25519.h 编译错误
CMakeFiles/ssh_shared.dir/external/ge25519.c.o:/root/qc_int_tcmalloc_repo/5g_platform/build/staging/du/x86/libssh/libssh-0.7.5/include/libssh/ge25519.h:31: multiple definition of `ge25519_base’
CMakeFiles/ssh_shared.dir/external/ed25519.c.o:/root/qc_int_tcmalloc_repo/5g_platform/build/staging/du/x86/libssh/libssh-0.7.5/include/libssh/ge25519.h:31: first defined here
collect2: error: ld returned 1 exit status
make[2]: *** [src/CMakeFiles/ssh_shared.dir/build.make:898: src/libssh.so.4.4.2] Error 1
make[1]: *** [CMakeFiles/Makefile2:148: src/CMakeFiles/ssh_shared.dir/all] Error 2
make: *** [Makefile:156: all] Error 2

ge25519.h

增加extern
extern const ge25519 ge25519_base;

8、add -fPIC flag
/usr/bin/ld: ./obj/*.o: TLS transition from R_X86_64_GOTTPOFF to R_X86_64_TPOFF32 against REGIONID' at 0xa9f4 in section .text’ failed
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
make: *** [makefile:38: du_app] Error 1

9、gcc优化

-march=native 启用特定于给定CPU架构的指令,并且这些指令在不同架构上可能不存在。如果在不同的CPU系统上运行程序,则程序可能根本无法工作,或者速度显着降低(因为它还启用了mtune=native),因此如果您决定使用它,请注意此事项。更多信息here。
-Ofast,如您所述,启用了一些不符合标准的优化,因此也应谨慎使用。更多信息here。
尝试的其他GCC标志

不同标志的详细信息可以在这里找到。

-Ofast 启用 -ffast-math,进而启用 -fno-math-errno,-funsafe-math-optimizations,-ffinite-math-only,-fno-rounding-math,-fno-signaling-nans 和 -fcx-limited-range。您可以通过有选择地添加一些额外的标志,如 -fno-signed-zeros,-fno-trapping-math 等,更进一步地进行 浮点数计算优化。这些标志不包括在 -Ofast 中,但可以在计算中提供一些额外的性能提升,但您必须检查它们是否真正对您有益并且不会破坏任何计算。
GCC 还具有大量其他未由任何 “-O” 选项启用的 其他优化标志。它们被列为“可能产生错误代码的实验性选项”,因此应谨慎使用,并通过测试正确性和基准测试来检查它们的效果。尽管如此,我经常使用 -frename-registers,这个选项从未为我产生过不良结果,并且往往会给出明显的性能提升(即可以在基准测试中测量)。这是一种非常依赖于您的处理器类型的标志。 -funroll-loops 有时也会产生良好的结果(并且还暗示了 -frename-registers),但它取决于您的实际代码。
PGO

GCC具有基于性能分析的优化(Profile-Guided Optimisations)功能。虽然GCC没有太多关于此功能的精确文档,但是让它运行起来非常简单。

首先使用-fprofile-generate编译您的程序。
让程序运行(执行时间会显著变慢,因为代码还会生成.gcda文件中的性能分析信息)。
使用-fprofile-use重新编译程序。如果您的应用程序是多线程的,请添加-fprofile-correction标志。
使用GCC进行PGO可以产生惊人的结果,并且真正显著提高性能(我最近参与的一个项目中看到了15-20%的速度提升)。显然,问题在于拥有一些足够代表您的应用程序执行的数据,这并不总是可用或易于获取。

GCC的并行模式

GCC具有并行模式,该模式是在GCC 4.2编译器发布时首次推出的。

基本上,它为您提供了许多C++标准库算法的并行实现。要在全局范围内启用它们,您只需要向编译器添加-fopenmp和-D_GLIBCXX_PARALLEL标志。您也可以在需要时选择性地启用每个算法,但这将需要进行一些小的代码更改。

如果经常在大型数据结构上使用这些算法,并且有许多硬件线程上下文可用,这些并行实现可以大大提高性能。到目前为止,我只使用了sort的并行实现,但为了给出一个粗略的想法,我设法将排序时间从14秒降低到4秒,测试环境为:具有自定义比较器功能和8个内核的100万对象向量。

额外技巧
与前面的部分不同,这一部分需要对代码进行一些小的更改。它们也是GCC特定的(其中一些也适用于Clang),因此应使用编译时宏来保持代码在其他编译器上的可移植性。该部分包含一些更高级的技术,如果您没有一定的汇编水平理解,则不应使用。还要注意,处理器和编译器现在非常聪明,因此可能很难从这里描述的函数中获得任何显着的好处。
GCC内置函数,可以在这里找到。像__builtin_expect这样的构造可以通过提供分支预测信息帮助编译器进行更好的优化。其他构造,例如__builtin_prefetch将数据带入缓存以在访问之前帮助减少缓存未命中。
函数属性可以在这里找到。特别是,应该查看hot和cold属性;前者将指示编译器函数是程序的热点,并且更积极地优化该函数,并将其置于文本部分的一个特殊子部分,以便更好地定位;后者将为大小优化函数,并将其放置在文本部分的另一个特殊子部分。

<think>我们使用特定的交叉编译工具链(arm-linux-gnueabihf-sigmastar-11.1.0-g++)来编译FFmpeg。首先需要准备好交叉编译工具链,并设置环境变量。然后配置FFmpeg的交叉编译选项,指定目标系统、架构、交叉编译工具前缀等。步骤:1.下载FFmpeg源代码2.准备交叉编译工具链(确保已安装并设置环境变量)3.配置FFmpeg的交叉编译选项,使用指定的交叉编译工具链4.编译并安装注意:交叉编译时可能需要指定目标系统的根文件系统(sysroot),以包含必要的库和头文件。具体步骤:###1.下载FFmpeg源代码```bash#创建目录并进入mkdir-p~/ffmpeg_cross&&cd~/ffmpeg_cross#下载FFmpeg源代码(这里以6.1.1版本为例)wgethttps://ffmpeg.org/releases/ffmpeg-6.1.1.tar.xztarxvfffmpeg-6.1.1.tar.xzcdffmpeg-6.1.1```###2.设置交叉编译工具链假设交叉编译工具链已安装在`/opt/toolchains/arm-linux-gnueabihf-sigmastar-11.1.0`目录下。我们需要设置环境变量,将工具链的`bin`目录加入`PATH`,并设置`CROSS_PREFIX`和`SYSROOT`(如果工具链提供了sysroot)。```bash#设置工具链路径exportTOOLCHAIN_PATH=/opt/toolchains/arm-linux-gnueabihf-sigmastar-11.1.0exportPATH=$TOOLCHAIN_PATH/bin:$PATH#设置交叉编译工具前缀exportCROSS_PREFIX=arm-linux-gnueabihf-sigmastar-#设置sysroot(如果工具链提供了sysroot目录,通常位于工具链目录下的sysroot子目录)exportSYSROOT=$TOOLCHAIN_PATH/arm-buildroot-linux-gnueabihf/sysroot#检查工具链是否可用which${CROSS_PREFIX}g++```###3.配置FFmpeg使用`./configure`配置交叉编译选项。注意指定目标操作系统为linux,架构为arm,并使用上面设置的前缀。```bash./configure\--prefix=./install\#安装到当前目录下的install文件夹--target-os=linux\#目标系统--arch=arm\#目标架构--enable-cross-compile\#启用交叉编译--cross-prefix=$CROSS_PREFIX\#交叉编译工具前缀--sysroot=$SYSROOT\#指定sysroot--extra-cflags="-I$SYSROOT/usr/include"\#额外包含头文件路径--extra-ldflags="-L$SYSROOT/usr/lib"\#额外库文件路径--enable-shared\#编译共享库--disable-static#禁止静态库(可选)```如果目标平台是ARM硬浮点,我们还可以添加`--enable-vfp`和`--enable-neon`等选项以启用硬件加速。###4.编译和安装```bashmake-j$(nproc)#使用多核编译makeinstall#安装到prefix指定的目录```编译完成后,在`./install`目录下将生成可执行文件(如ffmpeg、ffprobe)和库文件。###5.验证将生成的可执行文件复制到目标ARM设备上运行,检查是否正常工作。###注意事项-**依赖库**:如果FFmpeg需要额外的编解码器(如x264、libfdk-aac等),需要先交叉编译这些库,并在配置FFmpeg时通过`--enable-libx264`等选项启用,同时通过`--extra-cflags`和`--extra-ldflags`指定这些库的头文件和库路径。-**工具链兼容性**:确保工具链的版本(gcc11.1.0)与目标系统兼容。如果遇到编译错误,可能需要调整配置选项或打补丁。-**sysroot**:sysroot必须包含目标系统的基本库(如libc,libdl等)。如果工具链没有提供sysroot,可能需要从目标系统复制。###示例:添加libx264支持假设已经交叉编译了libx264,并安装在`$SYSROOT/usr/local`目录下,则配置FFmpeg时可以添加:```bash./configure\...其他选项...\--enable-libx264\--extra-cflags="-I$SYSROOT/usr/local/include"\--extra-ldflags="-L$SYSROOT/usr/local/lib"```###常见问题-**找不到交叉编译工具链**:检查`PATH`环境变量是否设置正确,以及工具链是否安装。-**头文件或库缺失**:检查sysroot是否包含必要的头文件和库,或者通过`--extra-cflags`和`--extra-ldflags`添加额外路径。-**链接错误**:可能是库版本不匹配,或者缺少某些库,需要交叉编译并添加依赖库。§§相关问题§§1.如何为特定交叉编译工具链准备sysroot?2.如何交叉编译FFmpeg的依赖库(如libx264)?3.如何将交叉编译的FFmpeg集成到嵌入式Linux系统中?</think>### 使用 arm-linux-gnueabihf-sigmastar-11.1.0-g++ 交叉编译 FFmpeg 指南 #### 一、准备工作 1. **获取工具链** 确保已安装指定版本的交叉编译工具链: ```bash # 验证工具链是否可用 arm-linux-gnueabihf-sigmastar-11.1.0-g++ --version ``` 若未安装,需从供应商获取工具链包并解压到`/opt/toolchains/`目录[^1]。 2. **设置环境变量** ```bash export TOOLCHAIN_DIR=/opt/toolchains/arm-linux-gnueabihf-sigmastar-11.1.0 export PATH=$TOOLCHAIN_DIR/bin:$PATH export CC=arm-linux-gnueabihf-sigmastar-11.1.0-gcc export CXX=arm-linux-gnueabihf-sigmastar-11.1.0-g++ export AR=arm-linux-gnueabihf-sigmastar-11.1.0-ar export LD=arm-linux-gnueabihf-sigmastar-11.1.0-ld ``` #### 二、下载 FFmpeg 源码 ```bash mkdir -p ~/cross_ffmpeg && cd ~/cross_ffmpeg wget https://ffmpeg.org/releases/ffmpeg-6.1.1.tar.xz tar xvf ffmpeg-6.1.1.tar.xz cd ffmpeg-6.1.1 ``` #### 三、配置交叉编译 ```bash ./configure \ --prefix=$(pwd)/install \ # 安装目录 --target-os=linux \ # 目标系统 --arch=arm \ # ARM架构 --enable-cross-compile \ # 启用交叉编译 --cross-prefix=arm-linux-gnueabihf-sigmastar-11.1.0- \ # 工具链前缀 --sysroot=$TOOLCHAIN_DIR/sysroot \ # 系统根目录[^1] --enable-shared \ # 生成共享库 --disable-static \ # 禁用静态库 --extra-cflags="-march=armv7-a -mfpu=neon -mfloat-abi=hard" \ # ARMv7硬浮点 --extra-ldflags="-Wl,-rpath-link,$TOOLCHAIN_DIR/sysroot/usr/lib" ``` > **关键参数说明**: > - `--sysroot`:指定目标系统的根文件系统路径 > - `-march=armv7-a`:针对ARM Cortex-A系列优化 > - `-mfpu=neon`:启用NEON指令集加速 > - `-mfloat-abi=hard`:使用硬件浮点单元 #### 四、编译与安装 ```bash # 并行编译(使用4个核心) make -j4 # 安装到prefix指定目录 make install ``` 生成文件位于`./install/bin`和`./install/lib` #### 五、验证输出 1. **检查文件格式** ```bash file install/bin/ffmpeg # 应显示: ELF 32-bit LSB executable, ARM, EABI5 version 1... ``` 2. **提取配置信息** ```bash grep "configuration" config.h ``` #### 六、常见问题解决 1. **头文件缺失错误** ```log fatal error: stdio.h: No such file or directory ``` **解决方案**: ```bash # 在sysroot中安装基础头文件 sudo apt install gcc-arm-linux-gnueabihf ``` 2. **链接库失败** ```log cannot find -lz ``` **解决方案**: 交叉编译zlib并添加到`--extra-ldflags`: ```bash LDFLAGS="-L/path/to/cross_zlib/lib" ./configure ... ``` 3. **NEON指令集兼容性** 若目标设备不支持NEON,移除`-mfpu=neon`标志,添加: ```bash --disable-neon --disable-armv6t2 ``` #### 七、部署到目标设备 ```bash # 复制可执行文件和依赖库 scp -r install user@target-device:/opt/ffmpeg # 在目标设备设置环境变量 export LD_LIBRARY_PATH=/opt/ffmpeg/lib:$LD_LIBRARY_PATH ``` > **性能提示**: > 添加`--enable-omx --enable-mmal`可启用树莓派硬件加速(需目标设备支持)
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值