绕过CMake无法编译zlib的问题

最近研究CMake,发现如gtest,zlib这些项目都支持CMake,于是拿来编译了一下,gtest一切正常,zlib则是windows下正常,Ubuntu下出了问题

CMake Error at lib/zlib/CMakeLists.txt:65 (message):
You must remove lib/zlib/zconf.h from the source
tree.  This file is included with zlib but CMake generates this file for
you automatically in the build directory.

到zlib目录下干掉zconf.h,在重新编译:

Scanning dependencies of target zlib
Linking C shared library libz.so
CMake Error: cmake_symlink_library: System Error: Operation not supported
CMake Error: cmake_symlink_library: System Error: Operation not supported
make[2]: *** [lib/zlib/libz.so.1.2.5] 错误 1
make[1]: *** [lib/zlib/CMakeFiles/zlib.dir/all] 错误 2
make: *** [all] 错误 2

这是个满郁闷的问题,CMake也没有给出错误的log,后来反复试不知道怎么着又莫名其妙的出现ErrorLog:

Determining if the function pthread_create exists in the pthreads failed with the following output:
Change Dir: bin/gcc/CMakeFiles/CMakeTmp

Run Build Command:/usr/bin/make "cmTryCompileExec/fast"
/usr/bin/make -f CMakeFiles/cmTryCompileExec.dir/build.make CMakeFiles/cmTryCompileExec.dir/build
make[1]: 正在进入目录 `bin/gcc/CMakeFiles/CMakeTmp’
/usr/bin/cmake -E cmake_progress_report bin/gcc/CMakeFiles/CMakeTmp/CMakeFiles 1
Building C object CMakeFiles/cmTryCompileExec.dir/CheckFunctionExists.c.o
/usr/bin/gcc   -DCHECK_FUNCTION_EXISTS=pthread_create   -o CMakeFiles/cmTryCompileExec.dir/CheckFunctionExists.c.o   -c /usr/share/cmake-2.8/Modules/CheckFunctionExists.c
Linking C executable cmTryCompileExec
/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec.dir/link.txt –verbose=1
/usr/bin/gcc     -DCHECK_FUNCTION_EXISTS=pthread_create   CMakeFiles/cmTryCompileExec.dir/CheckFunctionExists.c.o  -o cmTryCompileExec -rdynamic -lpthreads
/usr/bin/ld: cannot find -lpthreads
collect2: ld returned 1 exit status
make[1]:正在离开目录 `/mnt/hgfs/BookStar/trunk/bin/gcc/CMakeFiles/CMakeTmp’
make[1]: *** [cmTryCompileExec] 错误 1
make: *** [cmTryCompileExec/fast] 错误 2

一头雾水,虽然是错误的log,怎么看都不像是zlib导致的,不过既然缺少pthreads库,就下一个,可问题在于是只有pthread库,没有pthreads库(起码我没找到),所以问题还是没有解决。

后来想到既然和链接有关系,索性把zlib提供的链接选项都屏蔽掉试试,果然发现问题了

add_library(zlib ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)

set_target_properties(zlib PROPERTIES SOVERSION 1)

if(NOT CYGWIN)
    # This property causes shared libraries on Linux to have the full version
    # encoded into their final filename.  We disable this on Cygwin because
    # it causes cygz-${ZLIB_FULL_VERSION}.dll to be created when cygz.dll
    # seems to be the default.
    #
    # This has no effect with MSVC, on that platform the version info for
    # the DLL comes from the resource file win32/zlib1.rc
    set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION})
endif()

只要屏蔽掉设置SOVERSION和VERSION 的两条就可以顺利通过,不过编译出的结果就变成libz.so而不是libz.so.1。

动态库带版本号貌似是linux的一个习惯,zlib也是承接这个习惯,即使在windows下也会编译为zlib1.dll,其中1就是版本号1.2.5的1(虽然每次我都习惯把名字手工修改一下)。

在CMake中,SOVERSION代表API版本号,VERSION指动态库的版本,这是CMake的基本机制,但为什么在ubuntu中CMake(2.8.0)会出现不支持的情况,还是没有最后搞清楚,不过不管怎样问题算是绕过去了,以后有机会再研究了。当然也欢迎哪位高人指点一二。

Leave a Reply

Your email address will not be published. Required fields are marked *