我使用的是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)
也欢迎对此方法提出批评!
答案 0 :(得分:2)
考虑到find_package(ZLIB)
,特别是FindZLIB.cmake
调用的CMake模块的局限性,您的方法是有效的。尽管其他FindXXX.cmake
模块具有用于获取静态库的特殊选项,但zlib模块没有。
关于此主题,已经有一些关于SO的问题,但是有些问题比其他的早,因此有一些选择。
您可以通过将其添加到-static
调用中,来更精细地应用CMAKE_EXE_LINKER_FLAGS
标志(而不是编辑全局target_link_libraries
变量)。这样,它仅适用于该目标-在构建其他非静态目标时很有用。
您还可以通过设置CMAKE_FIND_LIBRARY_SUFFIXES
告诉CMake明确搜索静态库。调用find_package
时,CMake可以使用以下命令搜索以.a
结尾的库:
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
find_package(ZLIB REQUIRED)
答案 1 :(得分:1)
例如,如果您有安装zlib
的控制权,并且要在“持续集成”设置中安装依赖项,我建议只删除zlib动态库。
zlib无法选择静态或动态构建,而是自动生成两个版本。但是FindZlib.cmake
优先考虑动态版本。
如果您无权修改需要CMakeLists.txt
的第三方存储库zlib
,我发现以下方法会更好:
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将查找静态库。
答案 2 :(得分:0)
我不推荐@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}
)
答案 3 :(得分:0)
我发现的最佳解决方案是在调用 CMake 时明确命名库:
cmake -DZLIB_LIBRARY=/usr/lib/x86_64-linux-gnu/libz.a /path/to/source