使用automake处理库的可选公共类型/函数的正确方法是什么



在我维护的库中,有一些函数依赖于pthreads。该项目使用automake。我想创建一个配置选项来禁用对pthreads的依赖,因为pthreads不应该编译这些函数。(原因是某些交叉编译和嵌入式目标。)

到目前为止,避免编译包含这些函数的文件还可以,但现在我意识到这些函数和它们使用的一个结构是在公共头中定义的。

  1. 从图书馆维护的角度来看,正确的方法是什么
  2. 使类型或函数在公共标头中可选的正确方法是什么

最初,我认为应该将头文件转换为autoconf输入(.in)文件,并生成带有可选删除的这些函数和类型的头文件。

但是,那些可能同时安装了不同版本库的系统呢?通常情况下,它们应该能够共享标头。

我是否应该使用预处理器条件来避免这些函数,并使用pkg-config将其指定为命令行选项?

另一个想法是将这些函数和类型移动到它们自己的头中,并避免在pthreads被禁用时安装这个头。这意味着要稍微打乱标题的组织,但这可能是最好的主意。不过,我想听听你的意见,处理库公共标头中可选功能的最佳方式是什么?

一种方法是让需要函数的线程继续存在于嵌入式平台上,但在调用它们时返回错误代码。这样,API在各个平台上保持不变,这对于使用库("程序")的代码来说是非常理想的,因为程序不需要对库中函数的存在进行类似自动f的测试,而只需要使用它们并利用源代码级别的if来确定它们的功能。

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 acquiredn");
}

在任何情况下,都不要尝试在mylib.h中#包含"config.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

然而,我不喜欢第二种方法,因为这意味着只要mylib.h.in发生更改,就必须重新运行configure。

另一个想法是将这些函数和类型移动到它们自己的头中,并避免在pthreads被禁用时安装这个头。

那将是最干净的选择。当您通过AC_ARG_ENABLE启用该选项时,当然也可以绕过所有pthreads设置。有了这个选项,依赖于库的包将能够很容易地(通过AC_TRY_COMPILE)告知pthread可选函数不在那里,而不是AC_TRY_RUN,以查看这些函数是否在运行时工作。

最新更新