cmake:vs2015/MinGW静态编译leveldb
来源:互联网 发布:观看仙侠学院 网络电影 编辑:程序博客网 时间:2024/06/06 12:35
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 usefulinstall(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 guyadongendfunction(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改为x86call "%VS140COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64mkdir build.gcccd build.gccrem %install_path% 安装路径rem %boost_root% boost 安装路径rem 注意这个版本的leveldb需要 boost 支持,编译前请确保有安装boostrem (我用的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 installcd ..
解决MinGW编译报错
利用上面的CMakeLists.txt也可以用MinGW编译。
但如果用MinGW编译,会有如下报错:
[ 1%] Building CXX object CMakeFiles/leveldb.dir/port/port_win.cc.objIn 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' failedmake[2]: *** [CMakeFiles/leveldb.dir/port/port_win.cc.obj] Error 1CMakeFiles\Makefile2:141: recipe for target 'CMakeFiles/leveldb.dir/all' failedmake[1]: *** [CMakeFiles/leveldb.dir/all] Error 2makefile:128: recipe for target 'all' failedmake: *** [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
- cmake:vs2015/MinGW静态编译leveldb
- VS2015+CMake编译OpenCV2.4.13静态库
- Windows下使用CMake+MinGW静态编译发布.exe程序
- CMake编译VS2015+OpenCV3.1
- glog/gflags:linux下用cmake通过MinGW-w64交叉编译生成windows版本静态库
- mingw下使用vs2015编译器编译FFMPEG
- vs2015使用MinGW编译的动态库
- opencv eclipse cmake mingw 编译 配置
- QTCreator+MingW+cmake环境编译nana库
- CMake+MinGW编译OpenCV-2.4.7
- CMake+mingw-w64编译opencv-3.3.1
- vs2015用cmake编译opencv问题总结
- win10X64 + vs2015通过Cmake编译Opencv
- opencv3.3.0+vs2015+cmake编译opencv x86
- 关于使用VS2015静态编译
- Qt5.9.1+VS2015静态编译
- openssl vs2015编译静态库
- QT(MinGW)静态库+Opencv静态编译
- sql
- Leetcode:207. Course Schedule
- POJ
- PAT甲级真题及训练集(10)--1036. Boys vs Girls (25)
- Kotlin Reference (八) 可见性修饰符, data class,object Claz
- cmake:vs2015/MinGW静态编译leveldb
- 安卓学习第一天:打造布局
- 百度地图SDK配置 运行报错:INSTALL_FAILED_NO_MATCHING_ABIS
- 水果消除(搜索之DFS)
- JavaScript记录
- Ubuntu 16.04 安装Anaconda3
- 1.swoole 简介
- [1] 开通博客
- Ubuntu环境QT出现:-1: error: cannot find -lGL(已解决)