ptrdiff_t typedef Столкновение - Google-тест и Intel Anaconda - PullRequest
0 голосов
/ 24 июня 2018

Контекст

Я занимаюсь разработкой проекта, который требует дистрибутива Intel Anaconda, и мы используем googletest для тестирования наших нативных пользователей. Я использую Clang для моего компилятора. Когда я строю googletest через cmake, я получаю это:

In file included from /foo/home/bar/native/build/gradle_unittest_build/googletest-src/googletest/src/gtest-all.cc:39:
In file included from /foo/home/bar/native/build/gradle_unittest_build/googletest-src/googletest/include/gtest/gtest.h:58:
In file included from /foo/home/bar/native/build/gradle_unittest_build/googletest-src/googletest/include/gtest/internal/gtest-internal.h:39:
In file included from /foo/home/bar/native/build/gradle_unittest_build/googletest-src/googletest/include/gtest/internal/gtest-port.h:452:
In file included from /foo/anaconda3/envs/idp3/include/regex.h:4:
/foo/anaconda3/envs/idp3/include/tclInt.h:60:16: error: typedef redefinition with different types
      ('int' vs 'long')
   typedef int ptrdiff_t;
Library/Developer/CommandLineTools/usr/lib/clang/9.1.0/include/stddef.h:51:26: note: previous definition is here
typedef __PTRDIFF_TYPE__ ptrdiff_t;

Мое понимание проблемы

Между clang/9.1.0 и google-test на ptrdiff_t произошла коллизия typedef, где Google включает regex.h, который включает собственный tclInt.h от conda, который имеет typedef. tclInt.h устанавливается необходимыми пакетами каналов conda intel. При удалении он понижает mkl и tbb до различных версий.

Вот плохо нарисованный график зависимостей, который показывает, где (я думаю) произошел typdef:

project native tests <-- googletest <-- regex.h <-- tclInt.h "typedef ptrdiff_t int;" 
                          ^
                          |
                   stddef.h "typedef ptrdiff_t long" (from clang)

Я не совсем уверен, как подойти к этой проблеме столкновения typedef и распутать ее. Один из вариантов - использовать gcc-8, но даже если я запускаю make для сборки googletest с экспортированными переменными env:

CXX=g++-8
CC=gcc-8

заголовок tclInt.h все еще извлекается из папки clang, как указано в дампе ошибок, который я прикрепил.

Способы ее решения (?)

Определенно есть и другие варианты, которые мне не хватает, но возможный способ решить эту проблему - иметь tclInt.h, у которого нет этой проблемы, или, возможно, gcc-8 имеет набор заголовков включения, которые не имеют не определить ptrdiff_t, и я могу кое-что сделать, чтобы указать на этот компилятор.


Примечание: я могу быть совершенно неправ, но это моя гипотеза. Любая помощь приветствуется.

Если кто-то хочет увидеть всю трассировку стека, то вы идете:

In file included from /foo/home/bar/native/build/gradle_unittest_build/googletest-src/googletest/src/gtest-all.cc:39:
In file included from /foo/home/bar/native/build/gradle_unittest_build/googletest-src/googletest/include/gtest/gtest.h:58:
In file included from /foo/home/bar/native/build/gradle_unittest_build/googletest-src/googletest/include/gtest/internal/gtest-internal.h:39:
In file included from /foo/home/bar/native/build/gradle_unittest_build/googletest-src/googletest/include/gtest/internal/gtest-port.h:452:
In file included from /foo/anaconda3/envs/idp3/include/regex.h:4:
/foo/anaconda3/envs/idp3/include/tclInt.h:60:16: error: typedef redefinition with different types ('int' vs 'long')
   typedef int ptrdiff_t;
               ^
/Library/Developer/CommandLineTools/usr/lib/clang/9.1.0/include/stddef.h:51:26: note: previous definition is here
typedef __PTRDIFF_TYPE__ ptrdiff_t;
                         ^
In file included from /foo/home/bar/native/build/gradle_unittest_build/googletest-src/googletest/src/gtest-all.cc:45:
/foo/home/bar/native/build/gradle_unittest_build/googletest-src/googletest/src/gtest-port.cc:597:10: error: use of undeclared identifier 'regexec'
  return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
         ^
/foo/home/bar/native/build/gradle_unittest_build/googletest-src/googletest/src/gtest-port.cc:606:10: error: use of undeclared identifier 'regexec'
  return regexec(&re.partial_regex_, str, 1, &match, 0) == 0;
         ^
/foo/home/bar/native/build/gradle_unittest_build/googletest-src/googletest/src/gtest-port.cc:619:15: error: use of undeclared identifier 'regcomp'
  is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0;
              ^
/foo/home/bar/native/build/gradle_unittest_build/googletest-src/googletest/src/gtest-port.cc:630:17: error: use of undeclared identifier 'regcomp'
    is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
                ^
5 errors generated.

1 Ответ

0 голосов
/ 24 июня 2018

Как правило, файл заголовка Tcl <tclInt.h> имеет условия препроцессора, которые определяют, следует ли определять ptrdiff_t или включать <stddef.h>:

#if defined(STDC_HEADERS) || defined(__STDC__) || defined(__C99__FUNC__) \
     || defined(__cplusplus) || defined(_MSC_VER)
#include <stddef.h>
#else
typedef int ptrdiff_t;
#endif

Однако Intel исправила это в своих tcl-8.6.4-19.tar.bz2 файл для распространения по адресу:

#ifdef STDC_HEADERS
#include <stddef.h>
#else
#ifdef __ICC
#  ifndef _PTRDIFF_T
#  define _PTRDIFF_T
   typedef int ptrdiff_t;
#  endif
#else
   typedef int ptrdiff_t;
#endif
#endif

Возможно, они думали, что должны что-то сделать с зависимостью _MSC_VER, хотя в этом контексте это безвредно.Это работает с ICC, потому что <stddef.h> предоставляется компилятором, и его версия заголовка, по-видимому, проверяет макрос _PTRDIFF_T перед его определением.

Обычно это не видно, потому что при использовании tclInt.h, вы должны использовать флаги компилятора, предоставленные tclConfig.sh, которые определяют STDC_HEADERS, поэтому <stddef.h> используется безоговорочно.

Но использование Tcl здесь кажется совершенно случайным, поскольку дистрибутив Intel Tcl включает в себязаголовок regex.h, который переопределяет системный заголовок <regex.h>, и это то, что googletest хочет включить сюда.Использование неправильного заголовочного файла также может привести к другим проблемам.(Вот почему другие дистрибутивы устанавливают заголовки Tcl в каталогах, таких как /usr/include/tcl8.6, и даже помещают внутренние заголовки, такие как regex.h, в отдельный подкаталог.)

Я бы попытался удалить дистрибутив Tcl из сборки.среда.Надеюсь, в этом нет особой необходимости, поэтому коллизия заголовочных файлов исчезнет.

...