Mingw64-w64 属性(格式) 和 <cinttypes> header
Mingw64-w64 attribute(format) and <cinttypes> header
当 cross-compiling 时,我很难让 cinttypes 在 mingw64-w64 上正常工作。我已经将其简化为在 docker.
中运行的最小(ish)示例
inttypes_test.cpp
#include <cstdio>
#include <cstddef>
#include <cstdint>
#include <cinttypes>
#include <cstdarg>
__attribute__((format(printf, 1, 2))) static void myPrintf(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
int main(int argc, const char** argv)
{
int i32 = 5;
int64_t i64 = 10;
uint64_t u64 = 20;
myPrintf("Testing int: %" PRId32 ", int64 = %" PRId64 ", size_t = %" PRIu64 "\n", i32, i64, u64);
return 0;
}
Dockerfile
FROM ubuntu:18.04
RUN apt-get update -y && \
apt-get install -y g++-mingw-w64-x86-64 && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
ADD inttypes_test.cpp /inttypes-test/
RUN cd "/inttypes-test" && \
/usr/bin/x86_64-w64-mingw32-g++ -Wall -Werror -c inttypes_test.cpp
运行 给出的结果:
inttypes_test.cpp: In function 'int main(int, const char**)':
inttypes_test.cpp:20:100: error: unknown conversion type character 'l' in format [-Werror=format=]
myPrintf("Testing int: %" PRId32 ", int64 = %" PRId64 ", size_t = %" PRIu64 "\n", i32, i64, u64);
^
inttypes_test.cpp:20:100: error: unknown conversion type character 'l' in format [-Werror=format=]
inttypes_test.cpp:20:100: error: too many arguments for format [-Werror=format-extra-args]
所以,我假设 <cinttypes>
header 的全部要点是掩盖这些 platform-specific 差异。我做错了什么吗?
inttypes
是转移注意力,你从 myPrintf("%lld", 1LL);
得到同样的警告。它警告使用 ll
,它在您的程序中由 inttypes 宏(正确)提供。
这是旧版 MinGW 的后遗症,其中 printf 格式通过 MSVCRT 重定向,无法处理 %lld
,因此发出警告是恰当的。
您可以通过向文件添加新的顶行(在任何标准包括之前)来解决问题:
#define __USE_MINGW_ANSI_STDIO 1
然后使用以下属性:
__attribute__((format(__MINGW_PRINTF_FORMAT, 1, 2)))
static void myPrintf(const char* fmt, ...)
这指示 mingw-w64 使用自己符合 ISO 标准的 printf 实现,并相应地匹配 -Wformat
警告。 Link to documentation
在我的系统 (g++ 8.2.1) 上,即使没有第一行,%lld
等的使用实际上也能正常运行,所以我怀疑他们可能已经将其修复为使用 ISO stdio 而不是 MS stdio默认。或者也许 MS stdio 现在知道 %lld
.
错误报告可能值得指出 __attribute__((format(printf
应该根据正在使用的 stdio 自动正常工作,而无需您执行此解决方法。
当 cross-compiling 时,我很难让 cinttypes 在 mingw64-w64 上正常工作。我已经将其简化为在 docker.
中运行的最小(ish)示例inttypes_test.cpp
#include <cstdio>
#include <cstddef>
#include <cstdint>
#include <cinttypes>
#include <cstdarg>
__attribute__((format(printf, 1, 2))) static void myPrintf(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
int main(int argc, const char** argv)
{
int i32 = 5;
int64_t i64 = 10;
uint64_t u64 = 20;
myPrintf("Testing int: %" PRId32 ", int64 = %" PRId64 ", size_t = %" PRIu64 "\n", i32, i64, u64);
return 0;
}
Dockerfile
FROM ubuntu:18.04
RUN apt-get update -y && \
apt-get install -y g++-mingw-w64-x86-64 && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
ADD inttypes_test.cpp /inttypes-test/
RUN cd "/inttypes-test" && \
/usr/bin/x86_64-w64-mingw32-g++ -Wall -Werror -c inttypes_test.cpp
运行 给出的结果:
inttypes_test.cpp: In function 'int main(int, const char**)':
inttypes_test.cpp:20:100: error: unknown conversion type character 'l' in format [-Werror=format=]
myPrintf("Testing int: %" PRId32 ", int64 = %" PRId64 ", size_t = %" PRIu64 "\n", i32, i64, u64);
^
inttypes_test.cpp:20:100: error: unknown conversion type character 'l' in format [-Werror=format=]
inttypes_test.cpp:20:100: error: too many arguments for format [-Werror=format-extra-args]
所以,我假设 <cinttypes>
header 的全部要点是掩盖这些 platform-specific 差异。我做错了什么吗?
inttypes
是转移注意力,你从 myPrintf("%lld", 1LL);
得到同样的警告。它警告使用 ll
,它在您的程序中由 inttypes 宏(正确)提供。
这是旧版 MinGW 的后遗症,其中 printf 格式通过 MSVCRT 重定向,无法处理 %lld
,因此发出警告是恰当的。
您可以通过向文件添加新的顶行(在任何标准包括之前)来解决问题:
#define __USE_MINGW_ANSI_STDIO 1
然后使用以下属性:
__attribute__((format(__MINGW_PRINTF_FORMAT, 1, 2)))
static void myPrintf(const char* fmt, ...)
这指示 mingw-w64 使用自己符合 ISO 标准的 printf 实现,并相应地匹配 -Wformat
警告。 Link to documentation
在我的系统 (g++ 8.2.1) 上,即使没有第一行,%lld
等的使用实际上也能正常运行,所以我怀疑他们可能已经将其修复为使用 ISO stdio 而不是 MS stdio默认。或者也许 MS stdio 现在知道 %lld
.
错误报告可能值得指出 __attribute__((format(printf
应该根据正在使用的 stdio 自动正常工作,而无需您执行此解决方法。