如何在CMake中找到zlib的静态版本?

如何在CMake中找到zlib的静态版本?,cmake,zlib,Cmake,Zlib,我使用的是cmake版本3.12.1,希望构建一个使用ZLIB的静态可执行文件。我的机器上既有静态库(libz.a)也有共享库(libz.so)。如何让find_package(ZLIB)返回静态版本?也许还有另一种方法可以找到libz.a 我目前的解决方法是指定: SET(CMAKE_EXE_LINKER_FLAGS“${CMAKE_EXE_LINKER_FLAGS}-静态”) 然后: target\u link\u库(my\u二进制z lib1 lib2) 欢迎对这种方法提出批评 考虑到fi

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

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

SET(CMAKE_EXE_LINKER_FLAGS“${CMAKE_EXE_LINKER_FLAGS}-静态”)

然后:

target\u link\u库(my\u二进制z lib1 lib2)


欢迎对这种方法提出批评

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

关于这个话题,已经有一些问题了,但是有些问题比其他问题要老,所以有一些选择

相反,您可以将
-static
标记添加到
目标链接库
调用中,从而在更精细的级别上应用该标记(而不是编辑全局
CMAKE\u EXE\u LINKER\u标记
变量)。这样,它将只应用于该目标——在构建其他非静态目标时非常有用

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

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

如果您可以控制安装
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将找到静态库。

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

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}
)
EXTERNALPROJECT\u ADD(zlib\u external
GIT_存储库https://github.com/madler/zlib.git
GIT_标签v1.2.11
CMAKE_ARGS
-DSKIP_INSTALL_FILES=ON#禁用手动和pkgconfig文件的安装
-DSKIP_INSTALL_LIBRARIES=ON#不自动安装库。它将手动处理以避免安装共享库
-DBUILD\u SHARED\u LIBS=OFF
-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
-DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX}
-DCMAKE_C_FLAGS:STRING=${CMAKE_COMPILE_FLAGS_EXTERNAL}
${EXTERNALPROJECT\u BUILD\u TYPE\u CMD}
INSTALL_DIR${CMAKE_INSTALL_PREFIX}
)
如果(不是WIN32)
set(zlib\u BUILD\u LIB\u PATH)/libz.a)
设置(zlib_路径“${CMAKE_INSTALL_PREFIX}/lib/libz.a”)
else()
set(zlib_BUILD_LIB_PATH)/Release/zlibstatic.LIB)
设置(zlib_路径“${CMAKE_INSTALL_PREFIX}/lib/zlibstatic.lib”)
endif()
外部项目添加步骤(
zlib\u外部zlib\u安装\u静态\u
注释“仅手动安装静态库”
依赖项安装
COMMAND${CMAKE_COMMAND}-E copy${zlib_BUILD_LIB_PATH}${zlib_PATH}
)

我找到的最佳解决方案是在调用CMake时显式命名库:

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