#c #solaris
#c #solaris
Вопрос:
Я борюсь с портом инструмента с открытым исходным кодом для Solaris. Большинство вещей работает, cmake / pkg-config / и т.д. Есть, зависимости найдены, gmake работает, вызовы компилятора и компоновщика выглядят нормально, и трен, бум:
Undefined first referenced
symbol in file
std::qsort(void*, unsigned int, unsigned int, int (*)(const void*, const void*)) ...
Эту часть я не понимаю. На первый взгляд, std::qsort не имеет смысла, предполагается, что он является частью библиотеки C, а не STL. Итак, я заглянул в stdlib.h и нашел список таких вещей, как using std::sort;
и десятки других стандартных функций, таких как free
, malloc
, atoi
и т.д., Перенаправленных в случае контекста C .
Что Oracle там делает и почему? С какой библиотекой я должен связать, если они перенаправляют ее таким образом? Или почему команда CC не выполняет это автоматически, как это делает GCC? Я пытался добавить -lstdc , но безуспешно.
В качестве альтернативы, простые версии libc, похоже, определены в <iso / stdlib_c99.h> (или <iso /stdlib_iso.h>). Законно ли включать один из этих заголовков напрямую или это приведет к другому случайному хаосу во время соединения?
Редактировать:
поскольку существует множество подозрений в странности системы сборки, вот, в основном, связывающий вызов из выполнения gmake:
/opt/developerstudio12.6/bin/CC -std=c 11 -xO3 -DNDEBUG <i.e. bunch of object files> -o ../systest -L/opt/csw/lib/64 -lintl
Я не вижу там ничего особенного, и я ожидаю, что CC выяснит, что связать, чтобы получить обязательную функциональность.
Комментарии:
1. Реальный вопрос: как, черт возьми, вы создаете это так, чтобы стандартные библиотеки не были связаны с двоичным файлом по умолчанию? Это та часть, которую я не понимаю, если только cmake просто не сломан в Solaris. Компоновщик должен автоматически связать ваше приложение с библиотеками времени выполнения C и C . Если этого не происходит, что-то не так. Перенаправления, о которых вы говорите, интересны, но здесь не имеют значения — они встроены в стандарты (ну, перенаправления — нет, просто наличие связанных символов, и кто бы реализовал такие пары дважды — никто, потому что это глупо — отсюда и перенаправления).
2. Нет, реальный вопрос в том, кто отвечает за ключевую часть процесса? Позвольте мне разобрать это: а) компилятор C , б) вызывающий пользователь, и если (б), то в1) получить имя библиотеки из справочной страницы? или b2) найти его где-то еще? или b3) cmake / autoconf должны разобраться с этим? или b4) пользовательский код проверки для cmake / autoconf должен это выяснить? И что касается смысла: похоже, что Sun / Oracle все равно реализуют код дважды, во время выполнения C и во время выполнения C . Эта часть не имеет смысла. Если пользователь не сможет связывать приложения cpp без libc, только cpp runtime.
3. @UnslanderMonica Опубликованная команда компилятора создаст 32-разрядный двоичный файл. Но
-L
опция указывает, что выполняется поиск в 64-разрядных библиотеках. Эта проблема должна быть исправлена, и поскольку мы не знаем, что находится в/opt/csw/lib/64
, мы не знаем, какие библиотеки не загружаются.
Ответ №1:
Правило заключается в том, что #include <xxx.h>
имена помещаются в глобальное пространство имен, и им также разрешено помещать их в std
. И наоборот, #include <cxxx>
помещает имена в std
, и им также разрешено помещать их в глобальное пространство имен. На практике это означает, что существует два подхода к реализации функций из стандартной библиотеки C в C : объявлять имена стандартных библиотек C в <xxx.h>
заголовках и вводить эти объявления в std
в cxxx
заголовках, или объявлять имена в std
в заголовках и вводить эти объявления в глобальное пространство имен в <xxx.h>
заголовках. При первом подходе имя функции будет qsort
; при последнем оно будет std::qsort
. В любом случае, это сообщение об ошибке обычно указывает на проблему с настройкой компилятора. Компоновщик не находит стандартную библиотеку.
Комментарии:
1. Компоновщик вызывается CC, компилятором C (C ! Не C). И затем он должен правильно настроить компоновщик, чтобы включить правильную библиотеку времени выполнения C . Но, по-видимому, этого не происходит. Как пользователь должен это исправить или обойти? Я не могу найти никакой документации для решения этой проблемы.
Ответ №2:
Эта команда компиляции
/opt/developerstudio12.6/bin/CC -std=c 11 -xO3 -DNDEBUG ...
создаст 32-разрядный исполняемый файл. Согласно справочной странице CC
Oracle:
В Oracle Solaris по умолчанию используется значение
-m32
. В системах Linux, поддерживающих 64-разрядные программы, по умолчанию используется-m64 -xarch=sse2
.
Но этот вариант библиотеки
-L/opt/csw/lib/64
выполняется поиск в каталоге, полном 64-разрядных библиотек.
Либо добавьте -m64
в команду компиляции, либо используйте 32-разрядный путь к библиотеке.
Обновить
Вопрос почти наверняка был бы ответным, если бы он включал полное сообщение об ошибке, которое почти наверняка является чем-то вроде этого:
CC -g qsort.cc -o qsort
"qsort.cc", line 15: Error: Could not find a match for std::qsort(int[4], unsigned, unsigned, int(void*,void*)) needed in main(int, char**).
"/usr/include/iso/stdlib_iso.h", line 184: Note: Candidate 'std::qsort(void*, unsigned, unsigned, extern "C" int(*)(const void*,const void*))' is not viable: argument '4' can't be converted from 'int(void*,void*)' to 'extern "C" int(*)(const void*,const void*)'.
"/usr/include/iso/stdlib_iso.h", line 187: Note: Candidate 'std::qsort(void*, unsigned, unsigned, int(*)(const void*,const void*))' is not viable: argument '4' can't be converted from 'int(void*,void*)' to 'int(*)(const void*,const void*)'.
Этот код отлично работает при компиляции с Oracle Developer Studio 12.6 на Solaris 11.4:
#include <stdlib.h>
int compare( const void *p1, const void *p2 )
{
int i1 = *( ( int * ) p1 );
int i2 = *( ( int * ) p2 );
return( i1 - i2 );
}
int main( int argc, char **argv )
{
int array[ 4 ] = { 5, 8, 12, 4 };
qsort( array, sizeof( array ) / sizeof( array[ 0 ] ),
sizeof( array[ 0 ] ), amp;compare );
}
Комментарии:
1. Ваш намек — это первый шаг в каком-то полезном направлении. Однако становится хуже, когда я пытаюсь это исправить. Даже простое воспроизведение, подобное этому, терпит неудачу:
#include <errno.h> #include <limits.h> #include <stdarg.h>
и создайте это подобным образом,/opt/developerstudio12.6/bin/CC -c repro.cc -std=c 11 -m64 -I/usr/include
и результат таков:"/usr/include/sys/va_impl.h", line 98: Error: Only one of a set of overloaded functions can be extern "C".
. Теперь я испытываю серьезное отвращение к Oracle toolchain и собираюсь попробовать clang следующим.2. @PasterOfMuppets вам не должны были понадобиться
-I/usr/include
. Компилятор Oracle C немного более педантичен в отношении соблюдения стандарта C , чем GCC. Возможно, вам придется использовать#include <cstdarg>
вместо этого, например. Или вам может потребоваться исправить вашу систему, если она не является актуальной.3. @PasterOfMuppets Обратите внимание, что даже оригинальная версия 2004 года,
va_impl.h
разветвленная на Solaris , в исходном коде OpenSolaris имеет комментарии к строке 98. Если ваша система не была обновлена или исправлена, вы, вероятно, пытаетесь выполнить эквивалент использования GCC 9 для компиляции C 11, но на RHEL 2 15-20-летней давности .4. Не обновлены? Что-то из 2004 года? Серьезно? Извините, это образ VirtualBox с сервера Oracle (версия 11.4), созданный несколько недель назад, и я установил последнюю версию Oracle Studio, следуя последним инструкциям по загрузке. Это не моя вина, если Oracle поставляет дерьмовые старые заголовки. Также не моя вина, если компилятор не умеет настраивать включение очень простых заголовков C. И с каких это пор я обязан включать заголовки оболочки C вместо версий C? Вы обвиняете жертву здесь.
5. @PasterOfMuppets Ты не жертва. Компилятор выдал вам полное сообщение об ошибке с большим количеством информации, которую вы не смогли опубликовать. Я бы поспорил, что функция, которую вы передаете,
qsort()
являетсяint compare( void *, void * )
вместо требуемойint compare( const void *, const void * )
.