zmq、czmq及其他相关动态库的编译和生成

zeromq是非常优秀的开源库,但是由于作者感觉visual studio的编译工具维护起来相当费事,当然也可能是作者更多的是在非windows下工作的原因吧,msvc build不再维护了,这导致了很多在windows下的用户编译zmq非常不方便。尝试了一下,libzmq\builds\deprecated-msvc\vs20xx的工具的确很多已经不工作了。
下面记录一下通过cmake编译windows下的工程的方法及步骤。
我在项目中用到了zmq、czmq、zyre,由于后两个项目都要依赖前一个项目,所以我们需要统一管理起来。
1、建立一个zeromq_v4.3.1目录(我编译的是4.3.1,所以最好带上版本号,方便后期维护);

2、克隆代码
cmd进入此目录,执行:

https://github.com/zeromq/libzmq.git

将libzmq克隆到zeromq_v4.3.1目录下;

执行:

https://github.com/zeromq/czmq.git

将czmq克隆到zeromq_v4.3.1目录下;

执行:

https://github.com/jedisct1/libsodium.git

将libsodium克隆到zeromq_v4.3.1目录下。
libsodium是一个加密库,czmq将要依赖它,所以这里预先准备好。
执行:

https://github.com/zeromq/zyre.git

将zyre克隆到zeromq_v4.3.1目录下。

3、cmake配置zmq库
cd进入libzmq目录,执行:

cmake -H. -Bbuild -G"Visual Studio 14 2015 Win64"

通常cmake都能成功,这就在build目录下生成了一个vs2015的编译工程,名称是ZeroMQ.sln

需要注意的是,ZeroMQ.sln生成的zmq文件名是带版本号的,类似libzmq-mt-gd-4_3_1.dll这样的格式。这会导致我们项目引用配置的频繁更改,也不利于通过dll替换的方式升级zmq,所以把zmq的CMakeLists.txt配置改一下,让他按libzmq.dll文件名的方式生成:

if(MSVC)
# Suppress linker warnings caused by #ifdef omission
# of file content.
set(CMAKE_STATIC_LINKER_FLAGS “${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221”)
set(PDB_OUTPUT_DIRECTORY “${CMAKE_CURRENT_BINARY_DIR}/bin”)
set(PDB_NAME “libzmq${MSVC_TOOLSET}-mt-gd-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}”)
function(enable_vs_guideline_checker target)
set_target_properties(${target} PROPERTIES
VS_GLOBAL_EnableCppCoreCheck true
VS_GLOBAL_CodeAnalysisRuleSet CppCoreCheckRules.ruleset
VS_GLOBAL_RunCodeAnalysis true)
endfunction()
if(BUILD_SHARED)
add_library(libzmq SHARED ${sources} ${public_headers} ${html-docs} ${readme-docs} ${CMAKE_CURRENT_BINARY_DIR}/NSIS.template.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
if(ENABLE_ANALYSIS)
enable_vs_guideline_checker(libzmq)
endif()
set_target_properties(libzmq PROPERTIES
PUBLIC_HEADER “${public_headers}”
#RELEASE_POSTFIX “${MSVC_TOOLSET}-mt-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}”
#RELWITHDEBINFO_POSTFIX “${MSVC_TOOLSET}-mt-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}”
#MINSIZEREL_POSTFIX “${MSVC_TOOLSET}-mt-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}”
#DEBUG_POSTFIX “${MSVC_TOOLSET}-mt-gd-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}”
RUNTIME_OUTPUT_DIRECTORY “${CMAKE_RUNTIME_OUTPUT_DIRECTORY}”
COMPILE_DEFINITIONS “DLL_EXPORT”
OUTPUT_NAME “libzmq”)
endif()

if(BUILD_STATIC)
add_library(libzmq-static STATIC ${sources} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
set_target_properties(libzmq-static PROPERTIES
PUBLIC_HEADER “${public_headers}”
#RELEASE_POSTFIX “${MSVC_TOOLSET}-mt-s-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}”
#RELWITHDEBINFO_POSTFIX “${MSVC_TOOLSET}-mt-s-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}”
#MINSIZEREL_POSTFIX “${MSVC_TOOLSET}-mt-s-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}”
#DEBUG_POSTFIX “${MSVC_TOOLSET}-mt-sgd-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}”
COMPILE_FLAGS “/DZMQ_STATIC”
OUTPUT_NAME “libzmq”)
endif()
else()

……

就是把一些’POSTFIX’注释掉了,让他不要自动在文件名后串接版本号和编译器等信息。

当然还有个方法就是手动修改项目属性,直接在visual studio中,在libzmq工程上mouse right button -> Properties,在弹出来的属性框中,手动把 Configuration Properties -> General -> Target Name 改成 “libzmq”,记得把需要的configuration都改一下(Debug、Release、RelWithDebInfo…)。另外还得把lib文件名也改了:
Configuration Properties -> Linker -> Advanced -> Import Library 改成 “xxxxxxx/libzmq.lib”
同样,如果需要pdb文件,把pdb文件名也改了:
Configuration Properties -> Linker -> Debugging -> Generate Program Database File 改成 “xxxxxxx/libzmq.pdb”。

4、生成zmq库
编译ZeroMQ.sln,一般都能正确编译的。

5、cmake配置czmq库
czmq也抛弃了windows,所以也得自己配置。
czmq配置相对麻烦一些,因为他要依赖zmq,所以我们需要改一下czmq目录下的Findlibzmq.cmake文件,让cmake能正确找到我们刚才编译的zmq的lib文件。

################################################################################
#  THIS FILE IS 100% GENERATED BY ZPROJECT; DO NOT EDIT EXCEPT EXPERIMENTALLY  #
#  Read the zproject/README.md for information about making permanent changes. #
################################################################################

if (NOT MSVC)
    include(FindPkgConfig)
    pkg_check_modules(PC_LIBZMQ "libzmq")
    if (PC_LIBZMQ_FOUND)
        # add CFLAGS from pkg-config file, e.g. draft api.
        add_definitions(${PC_LIBZMQ_CFLAGS} ${PC_LIBZMQ_CFLAGS_OTHER})
        # some libraries install the headers is a subdirectory of the include dir
        # returned by pkg-config, so use a wildcard match to improve chances of finding
        # headers and SOs.
        set(PC_LIBZMQ_INCLUDE_HINTS ${PC_LIBZMQ_INCLUDE_DIRS} ${PC_LIBZMQ_INCLUDE_DIRS}/*)
        set(PC_LIBZMQ_LIBRARY_HINTS ${PC_LIBZMQ_LIBRARY_DIRS} ${PC_LIBZMQ_LIBRARY_DIRS}/*)
    endif(PC_LIBZMQ_FOUND)
else()
	set(PC_LIBZMQ_INCLUDE_DIRS ../libzmq/include)
	set(PC_LIBZMQ_LIBRARY_DIRS ../libzmq/build/lib/Release)	
	set(PC_LIBZMQ_INCLUDE_HINTS ${PC_LIBZMQ_INCLUDE_DIRS} ${PC_LIBZMQ_INCLUDE_DIRS}/*)
	set(PC_LIBZMQ_LIBRARY_HINTS ${PC_LIBZMQ_LIBRARY_DIRS} ${PC_LIBZMQ_LIBRARY_DIRS}/*)
endif (NOT MSVC)

message("######## ${PC_LIBZMQ_INCLUDE_HINTS}")
message("######## ${PC_LIBZMQ_LIBRARY_HINTS}")

find_path (
    LIBZMQ_INCLUDE_DIRS
    NAMES zmq.h
    HINTS ${PC_LIBZMQ_INCLUDE_HINTS}
)

find_library (
    LIBZMQ_LIBRARIES
    NAMES libzmq
    HINTS ${PC_LIBZMQ_LIBRARY_HINTS}
)

include(FindPackageHandleStandardArgs)

find_package_handle_standard_args(
    LIBZMQ
    REQUIRED_VARS LIBZMQ_LIBRARIES LIBZMQ_INCLUDE_DIRS
)
mark_as_advanced(
    LIBZMQ_FOUND
    LIBZMQ_LIBRARIES LIBZMQ_INCLUDE_DIRS
)

################################################################################
#  THIS FILE IS 100% GENERATED BY ZPROJECT; DO NOT EDIT EXCEPT EXPERIMENTALLY  #
#  Read the zproject/README.md for information about making permanent changes. #
################################################################################

czmq依赖的另一个库是libsodium,还好,libsodium的vs编译还在,打开libsodium\builds\msvc\vs2015目录下的libsodium.sln文件,可直接生成对应的libsodium.dll和libsodium.lib
然后在czmq目录下找到Findlibsodium.cmake文件,修改如下:

################################################################################
#  THIS FILE IS 100% GENERATED BY ZPROJECT; DO NOT EDIT EXCEPT EXPERIMENTALLY  #
#  Please refer to the README for information about making permanent changes.  #
################################################################################

if (NOT MSVC)
    include(FindPkgConfig)
    pkg_check_modules(PC_LIBSODIUM "libsodium")
    if (NOT PC_LIBSODIUM_FOUND)
        pkg_check_modules(PC_LIBSODIUM "libsodium")
    endif (NOT PC_LIBSODIUM_FOUND)
    if (PC_LIBSODIUM_FOUND)
        # some libraries install the headers is a subdirectory of the include dir
        # returned by pkg-config, so use a wildcard match to improve chances of finding
        # headers and SOs.
        set(PC_LIBSODIUM_INCLUDE_HINTS ${PC_LIBSODIUM_INCLUDE_DIRS} ${PC_LIBSODIUM_INCLUDE_DIRS}/*)
        set(PC_LIBSODIUM_LIBRARY_HINTS ${PC_LIBSODIUM_LIBRARY_DIRS} ${PC_LIBSODIUM_LIBRARY_DIRS}/*)
    endif(PC_LIBSODIUM_FOUND)
else()
	set(PC_LIBSODIUM_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../libsodium/src/libsodium/include)
	set(PC_LIBSODIUM_LIBRARY_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../libsodium/bin/x64/Release/v140/dynamic)	
	set(PC_LIBSODIUM_INCLUDE_HINTS ${PC_LIBSODIUM_INCLUDE_DIRS} ${PC_LIBSODIUM_INCLUDE_DIRS}/*)
	set(PC_LIBSODIUM_LIBRARY_HINTS ${PC_LIBSODIUM_LIBRARY_DIRS} ${PC_LIBSODIUM_LIBRARY_DIRS}/*)
endif (NOT MSVC)

find_path (
    LIBSODIUM_INCLUDE_DIRS
    NAMES sodium.h
    HINTS ${PC_LIBSODIUM_INCLUDE_HINTS}
)

find_library (
    LIBSODIUM_LIBRARIES
    NAMES libsodium
    HINTS ${PC_LIBSODIUM_LIBRARY_HINTS}
)

include(FindPackageHandleStandardArgs)

find_package_handle_standard_args(
    LIBSODIUM
    REQUIRED_VARS LIBSODIUM_LIBRARIES LIBSODIUM_INCLUDE_DIRS
)
mark_as_advanced(
    LIBSODIUM_FOUND
    LIBSODIUM_LIBRARIES LIBSODIUM_INCLUDE_DIRS
)

################################################################################
#  THIS FILE IS 100% GENERATED BY ZPROJECT; DO NOT EDIT EXCEPT EXPERIMENTALLY  #
#  Please refer to the README for information about making permanent changes.  #
################################################################################

6、生成czmq库
这个就简单了,打开编译就行啦

7、zyre依赖zmq和czmq,参考czmq,把对应的依赖项Findlibzmq.cmake、Findczmq.cmake、Findlibsodium.cmake改为对应的目录和文件就行了。

8、czmq的版本号问题
czmq通过cmake编译完的windows dll是不带版本号的,也就是从dll文件的属性里看不到版本号信息,这让我们在使用时很难确定其版本号,还好builds/msvc目录下有个resource.rc文件,只要在如下地方把这个rc文件加进去就可以了:

# shared
if (CZMQ_BUILD_SHARED)
  IF (MSVC)
    add_library(czmq SHARED ${czmq_sources} ${CMAKE_CURRENT_SOURCE_DIR}/builds/msvc/resource.rc)
  ELSE (MSVC)
    add_library(czmq SHARED
 
lt;TARGET_OBJECTS:czmq_objects>) ENDIF (MSVC) set_target_properties (czmq PROPERTIES PUBLIC_HEADER "${public_headers}" DEFINE_SYMBOL "CZMQ_EXPORTS" SOVERSION "4" VERSION "${CZMQ_VERSION}" COMPILE_DEFINITIONS "DLL_EXPORT" OUTPUT_NAME "czmq" PREFIX "lib" ) target_link_libraries(czmq PUBLIC ${MORE_LIBRARIES} ) install(TARGETS czmq EXPORT czmq-targets LIBRARY DESTINATION "lib${LIB_SUFFIX}" # .so file ARCHIVE DESTINATION "lib${LIB_SUFFIX}" # .lib file RUNTIME DESTINATION bin # .dll file ) target_include_directories(czmq PUBLIC
 
lt;BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
 
lt;INSTALL_INTERFACE:include> ) endif() # static if (CZMQ_BUILD_STATIC) IF (MSVC) add_library(czmq-static STATIC ${czmq_sources} ${CMAKE_CURRENT_SOURCE_DIR}/builds/msvc/resource.rc) ELSE (MSVC) add_library(czmq-static STATIC
 
lt;TARGET_OBJECTS:czmq_objects>) ENDIF (MSVC) set_target_properties(czmq-static PROPERTIES PUBLIC_HEADER "${public_headers}" COMPILE_DEFINITIONS "CZMQ_STATIC" OUTPUT_NAME "czmq" PREFIX "lib" ) target_link_libraries(czmq-static PUBLIC ${MORE_LIBRARIES} ) install(TARGETS czmq-static EXPORT czmq-targets LIBRARY DESTINATION "lib${LIB_SUFFIX}" # .so file ARCHIVE DESTINATION "lib${LIB_SUFFIX}" # .lib file RUNTIME DESTINATION bin # .dll file ) target_include_directories(czmq-static PUBLIC
 
lt;BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
 
lt;INSTALL_INTERFACE:include> ) target_compile_definitions(czmq-static PUBLIC CZMQ_STATIC ) endif()

发表评论

电子邮件地址不会被公开。

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据