前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >cmake:vs2015/MinGW静态编译leveldb

cmake:vs2015/MinGW静态编译leveldb

作者头像
10km
发布2018-01-03 14:23:51
2.3K0
发布2018-01-03 14:23:51
举报
文章被收录于专栏:10km的专栏10km的专栏10km的专栏

leveldb是google的开源项目(https://github.com/google/leveldb), 在linux下编译很方便,然而官方版本却没有提供在windows下的编译方式,好麻烦。还好,开源的世界热心人很多,同样在github上找到了cmake编译版本(https://github.com/bureau14/leveldb),有了cmake版本,windows下编译的问题就解决了一大半,下载这个版本的源码在windows用vs2015编译通过。但执行nmake install后发现,cmake脚本提供的安装功能不完整,只安装了bin文件夹。于是手工修改了CMakeLists.txt,才能完整安装。

修改CMakeLists.txt

修改后的CMakeLists.txt如下(搜索guyadong标记,可以找到所有添加的代码)

cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)

project(leveldb CXX)    
set(CMAKE_DEBUG_POSTFIX "d")

set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREAD ON)
set(Boost_USE_STATIC_RUNTIME OFF)

find_package(Boost COMPONENTS 
    date_time
    filesystem
    system
    REQUIRED)

set(SNAPPY_LIBRARY "")

string(REGEX MATCH "clang" CLANG ${CMAKE_CXX_COMPILER})

if(CMAKE_COMPILER_IS_GNUCXX OR CLANG)
    find_library(Pthread_LIBRARY pthread)
    find_library(Realtime_LIBRARY rt)
    # find library can be problematic with stdc++ which is why we hardwire the link
    set(Stdcpp_LIBRARY stdc++)
else(CMAKE_COMPILER_IS_GNUCXX OR CLANG)
    set(Pthread_LIBRARY "")
    set(Realtime_LIBRARY "")
    set(Stdcpp_LIBRARY "")
endif(CMAKE_COMPILER_IS_GNUCXX OR CLANG)

include_directories(${Boost_INCLUDE_DIRS}
    ${CMAKE_CURRENT_SOURCE_DIR}
    include)

if(MSVC)
    add_compile_options(
        /D_CRT_SECURE_NO_WARNINGS
        /wd4389 # signed/unsigned mismatch
        /wd4800 # constructor never returns, potential memory leak because of a singleton pattern
        /wd4722 # unreachable code because of singleton pattern
        /wd4702 # bool cast performance warning
    )
else()
    add_compile_options(
        -Wno-sign-compare
        -std=c++11
    )
endif()

add_definitions(
    -DLEVELDB_ATOMIC_PRESENT
)

set(LEVEL_DB_FILES
    include/leveldb/c.h
    include/leveldb/cache.h
    include/leveldb/comparator.h
    include/leveldb/db.h
    include/leveldb/dumpfile.h
    include/leveldb/env.h
    include/leveldb/iterator.h
    include/leveldb/filter_policy.h
    include/leveldb/iterator.h
    include/leveldb/options.h
    include/leveldb/slice.h
    include/leveldb/status.h
    include/leveldb/table.h
    include/leveldb/table_builder.h
    include/leveldb/write_batch.h
    db/builder.cc
    db/builder.h
    db/db_impl.cc
    db/db_impl.h
    db/db_iter.cc
    db/db_iter.h
    db/dbformat.cc
    db/dbformat.h
    db/dumpfile.cc
    db/filename.cc
    db/filename.h
    db/log_format.h
    db/log_reader.cc
    db/log_reader.h
    db/log_writer.cc
    db/log_writer.h
    db/skiplist.h
    db/snapshot.h
    db/memtable.cc
    db/memtable.h
    db/repair.cc
    db/table_cache.cc
    db/table_cache.h
    db/version_edit.cc
    db/version_edit.h
    db/version_set.cc
    db/version_set.h
    db/write_batch.cc
    table/block.cc
    table/block.h
    table/block_builder.cc
    table/block_builder.h
    table/filter_block.cc
    table/filter_block.h
    table/format.cc
    table/format.h
    table/iterator.cc
    table/iterator_wrapper.h
    table/merger.cc
    table/merger.h
    table/table.cc
    table/table_builder.cc
    table/two_level_iterator.cc
    table/two_level_iterator.h
    util/arena.cc
    util/arena.h
    util/bloom.cc
    util/cache.cc
    util/coding.cc
    util/coding.h
    util/comparator.cc
    util/crc32c.cc
    util/crc32c.h
    util/env.cc
    util/filter_policy.cc
    util/hash.cc
    util/hash.h
    util/histogram.cc
    util/histogram.h
    util/logging.cc
    util/logging.h
    util/mutexlock.h
    util/options.cc
    util/random.h
    util/status.cc
    port/port.h)

if(WIN32)
    list(APPEND LEVEL_DB_FILES
        port/port_win.h
        port/port_win.cc
        util/win_logger.h
        util/win_logger.cc
        util/env_boost.cc)
else()
    list(APPEND LEVEL_DB_FILES
        port/port_posix.h
        port/port_posix.cc
        util/posix_logger.h
        util/env_posix.cc)
endif()

add_library(leveldb ${LEVEL_DB_FILES})

target_include_directories(leveldb 
    PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
    PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} 
)

target_link_libraries(leveldb 
    PRIVATE
    ${Boost_LIBRARIES}
    ${Pthread_LIBRARY}
)

add_executable(leveldbutil
    db/leveldb_main.cc)

target_link_libraries(leveldbutil
    leveldb)

set_target_properties(leveldbutil PROPERTIES
    DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})

# we distribute the leveldbutil as it might be useful
install(TARGETS leveldbutil
    RUNTIME DESTINATION bin
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib)
# modified by guyadong
# 将 leveldb 库安装到 lib下
install(TARGETS leveldb
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib)
# 复制 include 文件夹
install(DIRECTORY include DESTINATION .)
# end of modified by guyadong
##################################### TESTS #######################################
# Every leveldb test file has to be compiled as an independant binary
# because of the test framework used by leveldb.
add_library(leveldb_test_rt 
    util/testutil.h
    util/testutil.cc
    util/testharness.h
    util/testharness.cc)

target_include_directories(leveldb_test_rt
    PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include
)

add_custom_target(RUN_LEVELDB_UNIT_TESTS
    COMMAND ${CMAKE_CTEST_COMMAND}
        --build-config ${CMAKE_CFG_INTDIR}
        --output-log LevelDB_test_${CMAKE_CFG_INTDIR}.log
        --output-on-failure
        --tests-regex leveldb
    COMMENT "Running all LevelDB unit tests"
)

function(LEVELDB_ADD_TEST TESTNAME TESTFILE)
    if(NOT TESTNAME)
        message(SEND_ERROR "Error: LEVELDB_ADD_TEST called without test name")
        return()
    endif(NOT TESTNAME)

    if(NOT TESTFILE)
        message(SEND_ERROR "Error: LEVELDB_ADD_TEST called without test file")
        return()
    endif(NOT TESTFILE)

    add_executable(leveldb_${TESTNAME}_test
        ${TESTFILE})

    target_link_libraries(leveldb_${TESTNAME}_test
        leveldb_test_rt
        leveldb)

    set_target_properties(leveldb_${TESTNAME}_test PROPERTIES
        DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})

    add_test(NAME leveldb_${TESTNAME}_test COMMAND leveldb_${TESTNAME}_test)

    add_dependencies(RUN_LEVELDB_UNIT_TESTS leveldb_${TESTNAME}_test)
    # modified by guyadong
    # 将所有测试程序安装到 bin 下
    install(TARGETS leveldb_${TESTNAME}_test  RUNTIME DESTINATION bin)
    # end of modified by guyadong
endfunction(LEVELDB_ADD_TEST)

LEVELDB_ADD_TEST(env          util/env_test.cc)
LEVELDB_ADD_TEST(crc32        util/crc32c_test.cc)
LEVELDB_ADD_TEST(coding       util/coding_test.cc)
LEVELDB_ADD_TEST(arena        util/arena_test.cc)
LEVELDB_ADD_TEST(cache        util/cache_test.cc)
LEVELDB_ADD_TEST(table        table/table_test.cc)
# IMPORTANT: Commented a test that fails randomly.
# LEVELDB_ADD_TEST(autocompact  db/autocompact_test.cc)
LEVELDB_ADD_TEST(corruption   db/corruption_test.cc)
LEVELDB_ADD_TEST(dbformat     db/dbformat_test.cc)
LEVELDB_ADD_TEST(filename     db/filename_test.cc)
LEVELDB_ADD_TEST(log          db/log_test.cc)
LEVELDB_ADD_TEST(skiplist     db/skiplist_test.cc)
LEVELDB_ADD_TEST(version_edit db/version_edit_test.cc)
LEVELDB_ADD_TEST(write_batch  db/write_batch_test.cc)
LEVELDB_ADD_TEST(version_set  db/version_set_test.cc)
LEVELDB_ADD_TEST(filter_block table/filter_block_test.cc)
LEVELDB_ADD_TEST(bloom        util/bloom_test.cc)
LEVELDB_ADD_TEST(hash         util/hash_test.cc)
LEVELDB_ADD_TEST(db_bench     db/db_bench.cc)
LEVELDB_ADD_TEST(db           db/db_test.cc)

可以从这里下载修改后的CMakeLists.txt https://code.csdn.net/10km/caffe-static/tree/master/patch/leveldb-master/CMakeLists.txt

cmake编译leveldb

修改好CMakeLists.txt后,开始cmake 编译leveldb。下面是脚本编译过程

rem 创建 vs2015 x64编译环境
rem 如果要编译32位版本,则将后面的x86_amd64改为x86
call "%VS140COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64
mkdir build.gcc
cd build.gcc
rem %install_path% 安装路径
rem %boost_root% boost 安装路径
rem 注意这个版本的leveldb需要 boost 支持,编译前请确保有安装boost
rem (我用的boost版本是 1.62) 
rem BOOST_ROOT 用于指定 boost 的安装位置
rem 如果你的boost是默认安装到C:\boost,不指定BOOST_ROOT,cmake也能找到boost的位置
cmake .. -G "NMake Makefiles" -DCMAKE_BUILD_TYPE:STRING=RELEASE ^
    -DBOOST_ROOT=%boost_root% ^
    -DBUILD_SHARED_LIBS=off ^
    -DCMAKE_INSTALL_PREFIX=%install_path%
rem 编译并安装到CMAKE_INSTALL_PREFIX指定的位置
nmake install
cd .. 

解决MinGW编译报错

利用上面的CMakeLists.txt也可以用MinGW编译。 但如果用MinGW编译,会有如下报错:

[  1%] Building CXX object CMakeFiles/leveldb.dir/port/port_win.cc.obj
In file included from P:/MinGW/mingw64/x86_64-w64-mingw32/include/locale.h:12:0,
                 from P:/MinGW/mingw64/x86_64-w64-mingw32/include/c++/clocale:42,
                 from P:/MinGW/mingw64/x86_64-w64-mingw32/include/c++/x86_64-w64-mingw32/bits/c++locale.h:41,
                 from P:/MinGW/mingw64/x86_64-w64-mingw32/include/c++/bits/localefwd.h:40,
                 from P:/MinGW/mingw64/x86_64-w64-mingw32/include/c++/string:43,
                 from D:/caffe-static/source/leveldb-master/port/port_win.h:44,
                 from D:\caffe-static\source\leveldb-master\port\port_win.cc:31:
P:/MinGW/mingw64/x86_64-w64-mingw32/include/stdio.h:528:110: error: conflicting declaration of 'int _snprintf(char*, size_t, const char*, ...)' with 'C' linkage
   _CRTIMP int __cdecl _snprintf(char * __restrict__ _Dest,size_t _Count,const char * __restrict__ _Format,...) __MINGW_ATTRIB_DEPRECATED_SEC_WARN;
                                                                                                              ^
In file included from D:\caffe-static\source\leveldb-master\port\port_win.cc:31:0:
D:/caffe-static/source/leveldb-master/port/port_win.h:35:18: note: previous declaration with 'C++' linkage
 #define snprintf _snprintf
                  ^
In file included from P:/MinGW/mingw64/x86_64-w64-mingw32/include/c++/ext/string_conversions.h:43:0,
                 from P:/MinGW/mingw64/x86_64-w64-mingw32/include/c++/bits/basic_string.h:5247,
                 from P:/MinGW/mingw64/x86_64-w64-mingw32/include/c++/string:52,
                 from D:/caffe-static/source/leveldb-master/port/port_win.h:44,
                 from D:\caffe-static\source\leveldb-master\port\port_win.cc:31:
P:/MinGW/mingw64/x86_64-w64-mingw32/include/c++/cstdio:175:11: error: '::snprintf' has not been declared
   using ::snprintf;
           ^
P:/MinGW/mingw64/x86_64-w64-mingw32/include/c++/cstdio:185:22: error: '__gnu_cxx::snprintf' has not been declared
   using ::__gnu_cxx::snprintf;
                      ^
CMakeFiles\leveldb.dir\build.make:962: recipe for target 'CMakeFiles/leveldb.dir/port/port_win.cc.obj' failed
make[2]: *** [CMakeFiles/leveldb.dir/port/port_win.cc.obj] Error 1
CMakeFiles\Makefile2:141: recipe for target 'CMakeFiles/leveldb.dir/all' failed
make[1]: *** [CMakeFiles/leveldb.dir/all] Error 2
makefile:128: recipe for target 'all' failed
make: *** [all] Error 2

原因是port/port_win.h中关于snprintf的宏定义#if判断语句有漏洞,只考虑了MSVC编译的情况,却没有考虑MinGW的情况。所以要做如下修改

// 原来的判断只考虑了MSVC,当用MinGW编译时 _MSC_VER < 1900条件也成立,所以就出错了,
// 所以这里多加一个条件限制 defined(_MSC_VER),MinGW编译时就不会进入这个分支
//#if _MSC_VER < 1900
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
#endif

解决了这个问题,再make,编译是通过了,但连接时会报错:

libleveldb.a(env_boost.cc.obj):env_boost.cc:(.text+0x46b): undefined reference to `std::basic_filebuf<char, std::char_traits<char> >::_close()'
libleveldb.a(env_boost.cc.obj):env_boost.cc:(.text+0x64b): undefined reference to `std::basic_filebuf<char, std::char_traits<char> >::_close()'
libleveldb.a(env_boost.cc.obj):env_boost.cc:(.text+0x2a46): undefined reference to `std::basic_filebuf<char, std::char_traits<char> >::_close()'
libleveldb.a(env_boost.cc.obj):env_boost.cc:(.text+0x2be9): undefined reference to `std::basic_filebuf<char, std::char_traits<char> >::_close()'
libleveldb.a(env_boost.cc.obj):env_boost.cc:(.text+0x3235): undefined reference to `std::basic_filebuf<char, std::char_traits<char> >::_close()'
libleveldb.a(env_boost.cc.obj):env_boost.cc:(.text+0x3b19): more undefined references to `std::basic_filebuf<char, std::char_traits<char> >::_close()' follow

其实问题还是出在port/port_win.h,就在我们刚才修改的那段代码下面有一行

#define close _close

就是它造成的。注释掉这一行代码,即可,并且注释掉这一行代码在MSVC(VS2013,VS2015)也都不会报错

可以从这里下载修改后的port_win.h https://code.csdn.net/10km/caffe-static/tree/master/patch/leveldb-master/port/port_win.h

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017年06月21日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 修改CMakeLists.txt
  • cmake编译leveldb
  • 解决MinGW编译报错
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档