解析zlib的CMakeLists.txt文件



  • zlib是一个历史悠久,并且被无数开源闭源项目使用的压缩库。它的核心部分虽然简单,但是浓缩了开源项目的精华。我这回打算从它的项目文件CMakeLists.txt入手,逐步了解zlib这个库的设置以及CMake的用法。

    下载

    一开始当然要对zlib进行下载啦。下载也很简单,直接通过zlib.net这个地址来下载。软件是一个压缩包的形式,需要通过相应的软件解压才行。

    解压

    这里就不赘述了。解压到合适的位置就好了。

    找到CMakeLists.txt文件

    如果你们使用cmake进行构建的话,那么就可以利用CMakeLists.txt文件对当前项目进行构建,我这里为了学习cmake以及zlib的一些配置选项,因此打开CMakeLists.txt文件学习一下。



  • 下面是我从最新版本zlib1.2.11中获取的CMakeLists.txt文件内容:

    cmake_minimum_required(VERSION 2.4.4)
    set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
    
    project(zlib C)
    
    set(VERSION "1.2.11")
    
    option(ASM686 "Enable building i686 assembly implementation")
    option(AMD64 "Enable building amd64 assembly implementation")
    
    set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
    set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
    set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers")
    set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages")
    set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files")
    
    include(CheckTypeSize)
    include(CheckFunctionExists)
    include(CheckIncludeFile)
    include(CheckCSourceCompiles)
    enable_testing()
    
    check_include_file(sys/types.h HAVE_SYS_TYPES_H)
    check_include_file(stdint.h    HAVE_STDINT_H)
    check_include_file(stddef.h    HAVE_STDDEF_H)
    
    #
    # Check to see if we have large file support
    #
    set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1)
    # We add these other definitions here because CheckTypeSize.cmake
    # in CMake 2.4.x does not automatically do so and we want
    # compatibility with CMake 2.4.x.
    if(HAVE_SYS_TYPES_H)
        list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H)
    endif()
    if(HAVE_STDINT_H)
        list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H)
    endif()
    if(HAVE_STDDEF_H)
        list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H)
    endif()
    check_type_size(off64_t OFF64_T)
    if(HAVE_OFF64_T)
       add_definitions(-D_LARGEFILE64_SOURCE=1)
    endif()
    set(CMAKE_REQUIRED_DEFINITIONS) # clear variable
    
    #
    # Check for fseeko
    #
    check_function_exists(fseeko HAVE_FSEEKO)
    if(NOT HAVE_FSEEKO)
        add_definitions(-DNO_FSEEKO)
    endif()
    
    #
    # Check for unistd.h
    #
    check_include_file(unistd.h Z_HAVE_UNISTD_H)
    
    if(MSVC)
        set(CMAKE_DEBUG_POSTFIX "d")
        add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
        add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
        include_directories(${CMAKE_CURRENT_SOURCE_DIR})
    endif()
    
    if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
        # If we're doing an out of source build and the user has a zconf.h
        # in their source tree...
        if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h)
            message(STATUS "Renaming")
            message(STATUS "    ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h")
            message(STATUS "to 'zconf.h.included' because this file is included with zlib")
            message(STATUS "but CMake generates it automatically in the build directory.")
            file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included)
      endif()
    endif()
    
    set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc)
    configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein
    		${ZLIB_PC} @ONLY)
    configure_file(	${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein
    		${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY)
    include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR})
    
    
    #============================================================================
    # zlib
    #============================================================================
    
    set(ZLIB_PUBLIC_HDRS
        ${CMAKE_CURRENT_BINARY_DIR}/zconf.h
        zlib.h
    )
    set(ZLIB_PRIVATE_HDRS
        crc32.h
        deflate.h
        gzguts.h
        inffast.h
        inffixed.h
        inflate.h
        inftrees.h
        trees.h
        zutil.h
    )
    set(ZLIB_SRCS
        adler32.c
        compress.c
        crc32.c
        deflate.c
        gzclose.c
        gzlib.c
        gzread.c
        gzwrite.c
        inflate.c
        infback.c
        inftrees.c
        inffast.c
        trees.c
        uncompr.c
        zutil.c
    )
    
    if(NOT MINGW)
        set(ZLIB_DLL_SRCS
            win32/zlib1.rc # If present will override custom build rule below.
        )
    endif()
    
    if(CMAKE_COMPILER_IS_GNUCC)
        if(ASM686)
            set(ZLIB_ASMS contrib/asm686/match.S)
        elseif (AMD64)
            set(ZLIB_ASMS contrib/amd64/amd64-match.S)
        endif ()
    
    	if(ZLIB_ASMS)
    		add_definitions(-DASMV)
    		set_source_files_properties(${ZLIB_ASMS} PROPERTIES LANGUAGE C COMPILE_FLAGS -DNO_UNDERLINE)
    	endif()
    endif()
    
    if(MSVC)
        if(ASM686)
    		ENABLE_LANGUAGE(ASM_MASM)
            set(ZLIB_ASMS
    			contrib/masmx86/inffas32.asm
    			contrib/masmx86/match686.asm
    		)
        elseif (AMD64)
    		ENABLE_LANGUAGE(ASM_MASM)
            set(ZLIB_ASMS
    			contrib/masmx64/gvmat64.asm
    			contrib/masmx64/inffasx64.asm
    		)
        endif()
    
    	if(ZLIB_ASMS)
    		add_definitions(-DASMV -DASMINF)
    	endif()
    endif()
    
    # parse the full version number from zlib.h and include in ZLIB_FULL_VERSION
    file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents)
    string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*"
        "\\1" ZLIB_FULL_VERSION ${_zlib_h_contents})
    
    if(MINGW)
        # This gets us DLL resource information when compiling on MinGW.
        if(NOT CMAKE_RC_COMPILER)
            set(CMAKE_RC_COMPILER windres.exe)
        endif()
    
        add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
                           COMMAND ${CMAKE_RC_COMPILER}
                                -D GCC_WINDRES
                                -I ${CMAKE_CURRENT_SOURCE_DIR}
                                -I ${CMAKE_CURRENT_BINARY_DIR}
                                -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
                                -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc)
        set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj)
    endif(MINGW)
    
    add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
    add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${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()
    
    if(UNIX)
        # On unix-like platforms the library is almost always called libz
       set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z)
       if(NOT APPLE)
         set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"")
       endif()
    elseif(BUILD_SHARED_LIBS AND WIN32)
        # Creates zlib1.dll when building shared library version
        set_target_properties(zlib PROPERTIES SUFFIX "1.dll")
    endif()
    
    if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL )
        install(TARGETS zlib zlibstatic
            RUNTIME DESTINATION "${INSTALL_BIN_DIR}"
            ARCHIVE DESTINATION "${INSTALL_LIB_DIR}"
            LIBRARY DESTINATION "${INSTALL_LIB_DIR}" )
    endif()
    if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL )
        install(FILES ${ZLIB_PUBLIC_HDRS} DESTINATION "${INSTALL_INC_DIR}")
    endif()
    if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
        install(FILES zlib.3 DESTINATION "${INSTALL_MAN_DIR}/man3")
    endif()
    if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
        install(FILES ${ZLIB_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}")
    endif()
    
    #============================================================================
    # Example binaries
    #============================================================================
    
    add_executable(example test/example.c)
    target_link_libraries(example zlib)
    add_test(example example)
    
    add_executable(minigzip test/minigzip.c)
    target_link_libraries(minigzip zlib)
    
    if(HAVE_OFF64_T)
        add_executable(example64 test/example.c)
        target_link_libraries(example64 zlib)
        set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
        add_test(example64 example64)
    
        add_executable(minigzip64 test/minigzip.c)
        target_link_libraries(minigzip64 zlib)
        set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
    endif()
    

    这里呢,我们会摘取相关的点来学习。



  • 首先我看到的就是option选项。这个选项在cmake中的文档是这样的:

    Now let us consider making the MathFunctions library optional. In this tutorial there really isn’t any reason to do so, but with larger libraries or libraries that rely on third party code you might want to. The first step is to add an option to the top level CMakeLists file.

    # should we use our own math functions?
    option (USE_MYMATH 
            "Use tutorial provided math implementation" ON) 
    

    This will show up in the CMake GUI with a default value of ON that the user can change as desired. This setting will be stored in the cache so that the user does not need to keep setting it each time they run CMake on this project. The next change is to make the build and linking of the MathFunctions library conditional. To do this we change the end of the top level CMakeLists file to look like the following:

    # add the MathFunctions library?
    #
    if (USE_MYMATH)
      include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
      add_subdirectory (MathFunctions)
      set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
    endif (USE_MYMATH)
     
    # add the executable
    add_executable (Tutorial tutorial.cxx)
    target_link_libraries (Tutorial  ${EXTRA_LIBS})
    
    参考来源:这里

    在我看来,cmake中的option命令更像是一个宏,规定了是否定义这个宏以及这个宏所带来的连锁反应。option规定的这个宏,通过ON的设定来表示是否定义。



  • 做得还不错的嘛。希望继续呢。



  • 看到过很多代码都有用这个


Log in to reply
 

走马观花

最近的回复

  • 这张图或许阐述了这个问题。
    有效打造个人品牌.png

    其实对于我们职场人员,尤其是程序员,都有很强的作用。我们虽然产品意识比较弱,但是我们对产品的敏感性强,尤其是我们有制作过产品的经验,这反而是一个优势。

    read more
  • @jiangcaiyang 给你一个大大的赞!
    论坛最近打算再次启用iframely服务了。试试看!

    https://community.nodebb.org/topic/4401

    read more

关注我们

微博
QQ群