Как правильно обрабатывать необязательные общедоступные типы / функции для библиотеки с помощью automake? - PullRequest
0 голосов
/ 25 февраля 2012

В библиотеке, которую я поддерживаю, есть несколько функций, которые зависят от pthreads. В проекте используется automake. Я хочу создать опцию конфигурации, чтобы отключить зависимость от pthreads, которая просто не должна компилировать эти функции. (Причина заключается в определенных кросс-компиляции и внедренных целях.)

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

  1. Какой правильный подход здесь, с точки зрения обслуживания библиотеки?
  2. Как правильно сделать типы или функции необязательными в публичных заголовках?

Изначально я подумал, что должен превратить заголовки во входные файлы autoconf (.in) и сгенерировать заголовки с необязательным удалением этих функций и типов.

Но тогда как насчет систем, в которых одновременно могут быть установлены разные версии библиотеки? Обычно они должны иметь возможность совместно использовать заголовки.

Должен ли я сделать заголовки условным препроцессором, чтобы избежать этих функций, и использовать pkg-config, чтобы указать его в качестве параметра командной строки?

Другая идея состоит в том, чтобы переместить эти функции и типы в их собственный заголовок и избегать установки этого заголовка, когда pthreads отключены. Это означало бы немного испортить организацию заголовков, но, возможно, это лучшая идея. Я хочу узнать ваше мнение, как лучше всего работать с дополнительными функциями в публичных заголовках библиотеки?

Ответы [ 2 ]

1 голос
/ 25 февраля 2012

Один из способов заключается в том, чтобы ваши функции, требующие потоков, продолжали существовать на встроенной платформе, но возвращали код ошибки в случае их вызова.Таким образом, API остается одинаковым для всех платформ, что очень желательно для кода, использующего вашу библиотеку («Программа»), поскольку Program не нуждается в autoconf-подобных тестах на наличие функций в вашей библиотеке, а может просто использовать ихи использовать уровень исходного кода ifs для определения их функциональности.

int mylib_thread_frenzy(void)
{
#ifdef HAVE_PTHREAD_CREATE
       int ret = pthread_create(...);
       if (ret < 0)
               return -errno;
       return 0;
#else
       return -ENOSYS;
#endif
}

.

/* Program */
int ret = mylib_thread_frenzy();
if (ret == -ENOSYS) {
    /* Hm, castrated platform. Try something else... */
    printf("Or just tell the user the platform is too weak.\n");
} else {
    printf("World domination acquired\n");
}

В любом случае, не пытайтесь #include «config.h» в mylib.hи также не отправляйте этот config.h, поскольку определения, указанные в вашем config.h, могут конфликтовать с определениями другой библиотеки и / или Программы.

Если вы действительно хотите удалить функции из mylib.h, я думаю, это приходит на ум:

/* mylib.h.in */
#if 0@HAVE_PTHREAD_CREATE@
extern int mylib_pthread_frenzy(void);
#endif

/* configure.ac */
AC_SEARCH_LIBS([pthread_create], [pthread],
  [HAVE_PTHREAD_CREATE=1
   AC_SUBST([HAVE_PTHREAD_CREATE])
  ])
AC_CONFIG_FILES([mylib.h.in])
AC_OUTPUT

Мне, однако, не нравится второй подход, потому что он означает, что configure должен перезапускаться всякий раз, когда mylib.h.in изменяется.

0 голосов
/ 27 февраля 2012

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

Это был бы самый чистый выбор. Когда вы включаете опцию через AC_ARG_ENABLE, вы, конечно, можете обойти и все настройки pthreads. С помощью этой опции пакеты, зависящие от вашей библиотеки, смогут легко (через AC_TRY_COMPILE) сказать, что дополнительные функции pthread отсутствуют вместо AC_TRY_RUN, чтобы посмотреть, работают ли эти функции во время выполнения.

...