Я пытаюсь перекрестно скомпилировать SDK Azure IoT C. Компиляция проходит нормально для нативных сборок, но при кросс-компиляции я получаю
[ 33%] Building C object out/uamqp/CMakeFiles/uamqp.dir/src/header_detect_io.c.o
In file included from /home/abertulli/two_lidars/azure-iot-sdk-c/uamqp/inc/azure_uamqp_c/server_protocol_io.h:11:0,
from /home/abertulli/two_lidars/azure-iot-sdk-c/uamqp/src/header_detect_io.c:13:
/opt/box-root-fs/usr/include/stdint.h:266:0: error: "SIZE_MAX" redefined [-Werror]
# define SIZE_MAX (4294967295U)
In file included from /home/abertulli/two_lidars/azure-iot-sdk-c/uamqp/src/header_detect_io.c:11:0:
/home/abertulli/two_lidars/azure-iot-sdk-c/c-utility/inc/azure_c_shared_utility/safe_math.h:8:0: note: this is the location of the previous definition
#define SIZE_MAX ((size_t)((size_t)~(size_t)0))
cc1: all warnings being treated as errors
make[2]: *** [out/uamqp/CMakeFiles/uamqp.dir/build.make:202: out/uamqp/CMakeFiles/uamqp.dir/src/header_detect_io.c.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:594: out/uamqp/CMakeFiles/uamqp.dir/all] Error 2
make: *** [Makefile:136: all] Error 2
Но я вижу в /opt/box-root-fs/usr/include/stdint.h
(в корневом каталоге компилятора)
/* Limit of `size_t' type. */
# if __WORDSIZE == 64
# define SIZE_MAX (18446744073709551615UL)
# else
# ifdef __WORDSIZE32_SIZE_ULONG
# define SIZE_MAX (4294967295UL)
# else
# define SIZE_MAX (4294967295U) // <-------- HERE
# endif
# endif
и в ~/two_lidars/azure-iot-sdk-c/c-utility/inc/azure_c_shared_utility/safe_math.h
#ifndef SIZE_MAX
#define SIZE_MAX ((size_t)((size_t)~(size_t)0)) // <---------- HERE
#endif
Почему его переопределяют, даже если есть #ifndef
? Я предполагаю, что второй файл компилируется первым, но почему такое поведение проявляется только при кросс-компиляции? И чтобы это исправить, нужно ли мне поставить #ifndef
в sysroot-файл?
Вероятно, где-то отсутствует явный #include <stdint.h>
, и он случайно включается в встроенную сборку.
Только один из файлов заголовков проверяет, определен ли уже SIZE_MAX
, поэтому, если этот файл заголовка включен первым, то другой файл заголовка попытается его переопределить.
«И чтобы это исправить, нужно ли мне поместить #ifndef в sysroot-файл?» Нет, но вы можете сначала попробовать вручную, включив stdint.h
. В этом случае защита включения в заголовках должна гарантировать ожидаемый результат.
Интересно, почему они вообще включили этот фрагмент в «safe_math.h»? Я знаю, что исторически у MSVC не было <stdint.h>
.
Действительно, @IanAbbott. И, сделав этот выбор, мне интересно, почему они выбрали эту мерзость определения с дополнительными приведениями. Но Microsoft никогда не была настолько хороша во внедрении C, поэтому, думаю, неудивительно, что они также посредственно его используют.
@JohnBollinger Да, им удалось определить его таким образом, что его нельзя использовать в константных выражениях препроцессора.
Сообщения о коммитах git, связанные с добавлением и изменением Safe_math.h, также довольно пусты.
why this behaviour shows up only when cross-compiling?
Когда поведение не проявляется? Вы занимаетесь кросс-компиляцией? Какой компилятор и какие параметры компилятора используются, какую цепочку инструментов и какую стандартную библиотеку C?
Спасибо всем за комментарии, вы помогли выявить проблему. Очевидно, это была проблема неправильного порядка/неправильного размещения #include
в коде Azure SDK. Защита #define
в stdint.h
решила проблему, хотя, конечно, это временное решение, которое нельзя использовать в рабочем коде! В конце концов я открыл проблему в репозитории Azure, где менеджеры любезно и быстро устранили проблему.
РЕДАКТИРОВАТЬ вот в чем проблема, если вы заинтересованы в исправлении, пока оно ожидает объединения
Было бы лучше, если бы вы могли дать ссылку на проблему в этом ответе.
Сообщение об ошибке выглядит так, будто проблема в том, что в первом поле нет
#ifndef
, а во втором поле было определение. примечание: это местоположение предыдущего определения #define SIZE_MAX ((size_t)((size_t)~(size_t)0))