解析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
 

走马观花

最近的回复

  • 如果对操作不是很熟悉或者是操作不便的话,也可以在Windows的命令行执行NDK的安装。参数是一样的:
    Windows命令行安装NDK

    read more
  • 忘记补充图片了。这里需要点击更新安装才行。😆
    点击更新安装

    read more
  • 问:
    如何在Qt Creator安装NDK呢?
    除了那个🔽 按钮外,还有别的办法吗?
    答:
    Qt Creaator 4.11中更加整合了Android SDK Manager。其实大家都可以不运行默认的Android SDK Manager,直接在Qt Creator中选项->设备->Android,就可以进行操作了。

    通过````高级选项……,启动一些Android SDK Manager,只需要带上参数ndk-bundle```。原来没有NDK的你,也可以通过Android SDK Manager安装了。很简单吧。
    Android SDK Manager安装NDK

    read more
  • 挺好的分享,谢谢。1515759557.jpg

    read more

关注我们

微博
QQ群