转换autoconf的配置文件为CMake配置文件

转换autoconf的配置文件为CMake配置文件

不少现存的第三方开源程序是用autotools来组织的,将其加入到CMake的代码里的时候,有个麻烦的问题是,makefile的更新会产生不一致,尤其是./configure脚本的执行速度实在不敢恭维,当然希望往Windows上移植的话,是另外一个大问题了。

对于源代码比较少的程序,基本可以通过比照config.h的内容,类比造出一个CMake风格的配置文件,然后利用下述命令:
configure_file(config.h. in config.h)
这个方法可行的根源在于,CMake提供了类似的机制来进行跨平台的检测,具体来说是如下几个Module:

CheckFunctionExists
CheckIncludeFile
CheckIncludeFileCXX
CheckIncludeFiles
CheckLibraryExists
CheckStructHasMember
CheckSymbolExists
CheckTypeSize
CheckVariableExists
< /div> 对于大部分简单的config.h, CheckIncludeFile/CheckIncludeFiles/CheckLibraryExists /CheckFunctionExists就足够了。
需要的工作是,手工写一个config.h.in,另外加一个 Detect.cmake,在config.h.in里边,将对应的声明变化cmakedefine,在Detect.cmake里边,加上查找对应 macro的方法.

  • 头文件
/*Define to 1 if you have <netinet/in.h>*/
#define HAVE_NET_INET_IN_H 1

对应的声明分别为:
// config.h.in
#cmakedefine HAVE_NET_INET_IN_H

// detect.cmake
INCLUDE(CheckIncludeFile)
CHECK_INCLUDE_FILE(netinet
/ in .h HAVE_NET_INET_IN_H)



其内部的工作机制为:根据宏参数构造一个基本的C文件,然后用CC编译看是否有错误,如果没有,则定义上述符号(HAVE_XXX_H),否则,undefine
.

对于某些系统头文件而言,可能头文件自身是不完备的(依赖于其他的头文件),此时需要按照依赖顺序写出对应的头文件序列:
/* Define to 1 if you have xxx/yyy.h */
#define HAVE_XXX_YYY_H
// detect.cmake
INCLUDE(CheckIncludeFiles)
CHECK_INCLUDE_FILES(
" dir1/top1.h;dir2/top2.h;xxx/yyy.h " HAVE_XXX_YYY_H)

  • 库检测已经查找库中的某一个函数
对于检查库存在与否的情况,则稍微有些复杂,config.h通常会如下(autoconf的情况):
/* Define to 1 if you have the library `xxx' */
#define HAVE_LIBXXX对应的定义部分即config.h.in

没有太大差异,照样cmakedefine即可。

对于detect.cmake,需要指明lib中的一个函数:
INCLUDE(CheckLibraryExists)
find_libaray(libloc libname)
#Get the library directory
string (REGEX REPLACE " .*/(.*) "   " \\1 " libloc ${libloc})
CHECK_LIBRARY_EXISTS(XXX fun_in_lib ${libloc} HAVE_LIBXXX)

上述方法可以很检测某个库中是否包含某个需要的函数,只有找到的情况下,才定义对应的宏。

如果只需要知道库是否存在,只需要根据find_library的结果即可:
find_libaray(libloc xxx)
if (libloc)
   
set (HAVE_LIBXXX 1 )
endif()
  • 函数
函数的处理方法则相对简单,只需要如下的cmake代码即可:
INCLUDE(CheckFunctionExists)
CHECK_FUNCTION_EXISTS(testfunc HAVE_TEST_FUNC)

  • 调试
上述代码可能在某些情况下不能正常工作,或者你不知道需要怎样去填入里边的信息(比如多头文件依赖顺序的问题),那么可以自己手工模拟对应CMake模块的工作方法,自己造一个C文件来编译,看看缺少哪些头文件或者链接库。
  • Automation?
如果手边有现成的autotools生成的config.h,并且这个文件比较大,手工一一改动有些太繁琐。注意到autoconf 生成的config.h文件有某些特征,用脚本来做某些自动化转换是可能的,一个可行的思路是,通过正则表达式匹配来检测注释,从而可以得出接下来的宏声明是头文件还是库、函数等,由于宏命名的规律性,可以很容易的推导出对应的头文件名或者函数名。

在我自己实验的一个例子中,用100行的python脚本可以转换得到200个可以正常工作的cmake代码和 config.h.in。

你可能感兴趣的:(转换autoconf的配置文件为CMake配置文件)