【问题标题】:How to find static version of zlib in CMake?如何在 CMake 中找到 zlib 的静态版本?
【发布时间】:2019-10-11 19:14:33
【问题描述】:

我使用的是 cmake 版本 3.12.1,并且想要构建一个使用 ZLIB 的静态可执行文件。我的机器上有静态(libz.a)和共享(libz.so)库。如何告诉find_package(ZLIB) 返回静态版本?也许还有另一种方法可以找到libz.a

我目前的解决方法是指定:

SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")

然后:

target_link_libraries (my_binary z lib1 lib2)

也欢迎对这种方法提出批评!

【问题讨论】:

    标签: cmake zlib


    【解决方案1】:

    鉴于find_package(ZLIB)(特别是FindZLIB.cmake)调用的CMake 模块的限制,您的方法是有效的。虽然其他 FindXXX.cmake 模块具有获取静态库的特殊选项,但 zlib 模块没有。

    关于这个主题已经有一些关于 SO 的问题,但有些问题比其他问题更老,所以有几个选项。

    您可以将-static 标志添加到您的target_link_libraries 调用中,从而更精细地应用-static 标志(而不是编辑全局CMAKE_EXE_LINKER_FLAGS 变量)。这样,它将仅适用于该目标 - 如果您正在构建其他非静态目标,则很有用。

    您还可以通过设置 CMAKE_FIND_LIBRARY_SUFFIXES 来告诉 CMake 显式搜索静态库。当调用find_package 时,CMake 可以使用以下命令搜索以.a 结尾的库:

    SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
    find_package(ZLIB REQUIRED) 
    

    【讨论】:

      【解决方案2】:

      如果您可以控制安装 zlib,例如,您在持续集成设置中安装依赖项,我建议您只删除 zlib 动态库。

      zlib 没有静态或动态构建选项,它会自动生成两个版本。但是FindZlib.cmake 优先考虑动态版本。

      如果您无权修改需要zlib 的第三方存储库CMakeLists.txt,我发现以下方法会更好:

      if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
        set(_compiler_is_msvc ON)
      endif()
      option(ZLIB_FORCE_STATIC "Remove the dynamic libraries after zlib install" ON)
      mark_as_advanced(ZLIB_FORCE_STATIC)
      
      set(OUTPUT_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR} CACHE PATH "Base folder where builds and source folder will be installed: i.e. OUTPUT_BUILD_DIR/zlib")
      
      if(_compiler_is_msvc)
        set(ZLIB_GIT_TAG cacf7f1d4e3d44d871b605da3b647f07d718623f) # Version 1.2.11
        message(STATUS "ZLIB_VERSION: ${ZLIB_GIT_TAG} : Version 1.2.11")
        set(ZLIB_BUILD_DIR ${OUTPUT_BUILD_DIR}/zlib-build)
        set(ZLIB_INSTALL_DIR ${OUTPUT_BUILD_DIR}/zlib)
        set(ZLIB_SRC_FOLDER_NAME zlib-src)
        set(ZLIB_SRC_DIR ${OUTPUT_BUILD_DIR}/${ZLIB_SRC_FOLDER_NAME})
        set(ZLIB_GIT_REPOSITORY "https://github.com/madler/zlib")
      
        ExternalProject_Add(ep_zlib
          GIT_REPOSITORY ${ZLIB_GIT_REPOSITORY}
          GIT_TAG ${ZLIB_GIT_TAG}
          # GIT_SHALLOW TRUE
          GIT_PROGRESS TRUE
          CMAKE_GENERATOR ${CMAKE_GENERATOR}
          SOURCE_DIR ${ZLIB_SRC_DIR}
          BINARY_DIR ${ZLIB_BUILD_DIR}
          CMAKE_ARGS
              -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER}
              -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER}
              -DCMAKE_BUILD_TYPE:STRING=${SGEXT_CMAKE_BUILD_TYPE}
              -DBUILD_SHARED_LIBS:BOOL=OFF
              -DCMAKE_INSTALL_PREFIX=${ZLIB_INSTALL_DIR}
          )
      
        if(ZLIB_FORCE_STATIC)
          ExternalProject_Add_Step(
            ep_zlib zlib_remove_dll
            COMMENT "Remove zlib.lib and zlib.dll, leaves only zlibstatic.lib"
            DEPENDEES install
            COMMAND ${CMAKE_COMMAND} -E remove -f ${ZLIB_INSTALL_DIR}/lib/zlib.lib ${ZLIB_INSTALL_DIR}/bin/zlib.dll
            )
        endif()
      
      endif()
      
      

      最后一步去掉动态版本,所以默认的 FindZLIB 会找到静态库。

      【讨论】:

        【解决方案3】:

        我发现的最佳解决方案是在调用 CMake 时明确命名库:

        cmake -DZLIB_LIBRARY=/usr/lib/x86_64-linux-gnu/libz.a /path/to/source
        

        【讨论】:

          【解决方案4】:

          我不会推荐@phcerdan 提出的解决方案,因为在我的情况下,已安装的共享库与已安装的版本发生冲突,因此唯一的解决方案是确保从一开始就不会安装它。关键思想是使用SKIP_INSTALL_LIBRARIES 完全禁用目标安装,而是手动“安装”静态库。尽管如此,我的解决方案非常相似:

          EXTERNALPROJECT_ADD(zlib_external
               GIT_REPOSITORY    https://github.com/madler/zlib.git
               GIT_TAG           v1.2.11
          
               CMAKE_ARGS
                    -DSKIP_INSTALL_FILES=ON  # Disable install of manual and pkgconfig files
                    -DSKIP_INSTALL_LIBRARIES=ON  # Do not install libraries automatically. It will be handled manually to avoid installing shared libs
                    -DBUILD_SHARED_LIBS=OFF
                    -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
                    -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX}
                    -DCMAKE_C_FLAGS:STRING=${CMAKE_COMPILE_FLAGS_EXTERNAL}
                    ${EXTERNALPROJECT_BUILD_TYPE_CMD}
               INSTALL_DIR ${CMAKE_INSTALL_PREFIX}
          )
          
          if(NOT WIN32)
               set(zlib_BUILD_LIB_PATH "<BINARY_DIR>/libz.a")
               set(zlib_PATH "${CMAKE_INSTALL_PREFIX}/lib/libz.a")
          else()
               set(zlib_BUILD_LIB_PATH "<BINARY_DIR>/Release/zlibstatic.lib")
               set(zlib_PATH "${CMAKE_INSTALL_PREFIX}/lib/zlibstatic.lib")
          endif()
          
          ExternalProject_Add_Step(
               zlib_external zlib_install_static_only
               COMMENT "Manually installing only static library"
               DEPENDEES install
               COMMAND ${CMAKE_COMMAND} -E copy ${zlib_BUILD_LIB_PATH} ${zlib_PATH}
          )
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-10-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多