Linux C++ 编译错误 <emmintrin.h>

Cer*_*dia 5 c++ gcc spdlog stb-image

我正在尝试使用 stb_image.h 加载图像,但在 gcc 提供的 <emmintrin.h> 版本中遇到两个编译器错误。我认为可能需要一个编译器选项,但我一直无法找到它是什么。

错误代码:

/usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/include/emmintrin.h:1230:10: error: the last argument must be an 8-bit immediate
 1230 |   return (__m128i)__builtin_ia32_pslldqi128 (__A, __N * 8);
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/include/emmintrin.h:1224:10: error: the last argument must be an 8-bit immediate
 1224 |   return (__m128i)__builtin_ia32_psrldqi128 (__A, __N * 8);
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

<emmintrin.h> 中的相关代码:

extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_srli_si128 (__m128i __A, const int __N)
{
  return (__m128i)__builtin_ia32_psrldqi128 (__A, __N * 8);
}

extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_slli_si128 (__m128i __A, const int __N)
{
  return (__m128i)__builtin_ia32_pslldqi128 (__A, __N * 8);
}
Run Code Online (Sandbox Code Playgroud)

编辑:它与 spdlog 有关。我删除了 spdlog 的所有包含内容并将日志记录宏更改为空,并且编译成功

最小可重现示例:

主程序

#include "pch.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

int main() {
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

pch.h:

#include <spdlog/spdlog.h>
Run Code Online (Sandbox Code Playgroud)

cmakelists.txt:

cmake_minimum_required(VERSION 3.22)
project(untitled2)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_COMPILER /usr/bin/g++)

add_executable(untitled2 main.cpp stb_image.h pch.h)
target_precompile_headers(untitled2 PUBLIC pch.h)

add_subdirectory(spdlog)
target_link_libraries(untitled2 spdlog)
Run Code Online (Sandbox Code Playgroud)

Ove*_*ted 2

当您的程序未使用优化进行编译,而是选择和emmintrin.h的优化版本时,就会发生这种情况,因为 fmt (spdlog 的依赖项)在此处定义。_mm_srli_si128_mm_slli_si128__OPTIMIZE__

有关更多信息,请查看https://github.com/nothings/stb/discussions/1432#discussioncomment-4595273

可能的解决方法:

  1. 禁用正在实现 stb_image 的翻译单元的预编译标头(例如,将其移动到另一个 CMake 目标(如果正在使用 CMake))
  2. __OPTIMIZE__在实现 stb_image 的翻译单元上取消定义:
#if defined(__GNUC__) && !defined(NDEBUG) && defined(__OPTIMIZE__)
    #warning "Undefing __OPTIMIZE__ because of fmt"
    #undef __OPTIMIZE__
#endif
Run Code Online (Sandbox Code Playgroud)

如果需要,请随意删除生成的警告。