Windows下基於CMake編譯配置官方Caffe/Caffe-SSD

Windows下基於CMake編譯配置Caffe/SSD

by ChrisZZ, imzhuo@foxmail.comc++

簡要說明

最近須要在Windows下開發,在Windows下基於CMake編譯配置了Caffe/PyCaffe,記錄一下。git

特色:github

  • 能夠修改caffe依賴庫存放目錄
  • 能夠指定opencv版本
  • 能夠用於1080Ti等顯卡的正確編譯
  • 給出了基於CMake調用Caffe.lib的例子
  • 使用caffe.lib的項目中也可調試到caffe源碼中
  • 支持caffe-SSD,包括boost regex報錯的正確處理

1. 環境說明

系統: Win7/Win10
編譯器:Visual Studio 2013
構建器:CMake 3.13
Python: python2.7,用anaconda裝的。注意python.exe所在目錄放到系統PATH環境變量中。
CUDA: 9.2 (可選)
CuDNN:7.0(可選)
終端: cmd窗口
Caffe源碼: 官方Caffe的windows分支 。後續考慮SSD代碼算法

2. 配置官方Caffe

2.1 下載Caffe源碼和Windows依賴包

Caffe源碼
進cmd敲:express

d:
cd work
git clone https://github.com/BVLC/caffe caffe-BVLC
cd caffe-BVLC
git checkout -b windows origin/windows

或者從官方網頁 下載壓縮包。windows

Caffe的Windows依賴包
源碼中cmake腳本里會自動下載依賴包,但爲了不cmake下載遭遇網絡問題,以及修改配置項的方便,根據scripts/download_prebuilt_dependencies.py手動下載依賴文件:
(若是你網路還能夠,那麼忽略這一小節,腳本會自動下載)網絡

WIN_DEPENDENCIES_URLS = {
    ('v120', '2.7'):("https://github.com/willyd/caffe-builder/releases/download/v1.1.0/libraries_v120_x64_py27_1.1.0.tar.bz2",
                  "ba833d86d19b162a04d68b09b06df5e0dad947d4"),
    ('v140', '2.7'):("https://github.com/willyd/caffe-builder/releases/download/v1.1.0/libraries_v140_x64_py27_1.1.0.tar.bz2",
                  "17eecb095bd3b0774a87a38624a77ce35e497cd2"),
    ('v140', '3.5'):("https://github.com/willyd/caffe-builder/releases/download/v1.1.0/libraries_v140_x64_py35_1.1.0.tar.bz2",
                  "f060403fd1a7448d866d27c0e5b7dced39c0a607"),
}

依賴包存放目錄:架構

  • 默認方式下,放到C:\Users\<UserName>\.caffe\dependencies\download\目錄。app

  • 若是怕C盤空間佔用,也能夠在別的目錄存放依賴包,後續CMake階段指定-DCAFFE_DEPENDENCIES_ROOT_DIR=xxx便可,例如我放到了D:/lib/caffe_windows_deps/download/libraries_v120_x64_py27_1.1.0.tar.bz2

  • 爲了方便討論,咱們把C:\Users\<UserName>\.caffe\dependencies目錄或D:/lib/caffe_windows_deps/記作CAFFE_DEPENDENCIES_ROOT_DIR

2.2 修改cuda配置(可選)

cpu模式編譯的調過這一小節。

cmake/Cuda.cmake,第7行,去掉20和21的算力支持(不然新版cuda會報錯),改爲:

set(Caffe_known_gpu_archs "30 35 50 52 60 61")

cmake/Cuda.cmake,第40行左右,手動設定nvcc架構版本,例如我是1080Ti顯卡,使用6.1:

# if(__nvcc_res EQUAL 0)
    #   # nvcc outputs text containing line breaks when building with MSVC.
    #   # The line below prevents CMake from inserting a variable with line
    #   # breaks in the cache
    #   string(REGEX MATCH "([1-9].[0-9])" __nvcc_out "${__nvcc_out}")
    #   string(REPLACE "2.1" "2.1(2.0)" __nvcc_out "${__nvcc_out}")
    #   set(CUDA_gpu_detect_output ${__nvcc_out} CACHE INTERNAL "Returned GPU architetures from caffe_detect_gpus tool" FORCE)      
    # endif()
    set(__nvcc_out "6.1")

(爲啥這裏的自動獲取計算能力版本有問題?大概是字符編碼致使輸出不少警告,警告信息影響了正確結果的獲取)
(每一個Nvidia顯卡型號對應的compute ability表見:https://blog.csdn.net/real_myth/article/details/44308169)

CAFFE_DEPENDENCIES_ROOT_DIR目錄下的libraries_v120_x64_py27_1.1.0\libraries\include\boost-1_61\boost\config\compiler\nvcc.hpp:註釋掉最後三行:

#if !defined(__CUDACC_VER__) || (__CUDACC_VER__ < 70500)
#   define BOOST_NO_CXX11_VARIADIC_TEMPLATES
#endif

(緣由:cuda7.5之後,__CUDACC_VER__被廢除,應當使用__CUDACC_VER_MAJOR___CUDACC_VER_MINOR__等,若是不註釋掉,會報錯:

libraries_v140_x64_py35_1.1.0/libraries/include/boost-1_61\boost/config/compiler/nv
cc.hpp(22): fatal error C1017: invalid integer constant expression

參考https://github.com/BVLC/caffe/issues/599四、https://blog.csdn.net/qq_37817177/article/details/80604294)。

2.3 使用官方提供的步驟編譯

這種方式下,調用的是.\scripts\build_win.cmd腳本,CMake依賴包必須放到C:\Users\<UserName>\.caffe\dependencies\download\目錄。缺點是:
1.浪費C盤空間;

2.定製項被寫死了,不靈活。
例如opencv版本被限定死了爲3.1。例如imread讀取jpg在[3.0.0, 3.4.1]版本區間內的結果是一種,在2.4.x和>=3.4.2版本中的結果是另外一種,輸入數據的不一致會致使卷積網計算結果不一致。

所以,這種方式主要適合小白入門用用,實際項目開發中不方便。其具體操做爲:

回到剛纔的cmd,繼續敲(#後面是註釋,不用敲進去)

set PATH=%PATH%;C:\Windows\Microsoft.NET\Framework\v4.0.30319  #臨時添加MSBuild.exe的路徑
set MSVC_VERSION=12 #12對應到我用的vs2013.  build_win.cmd中默認爲vs2015,也就是13
set WITH_NINJA=0  # 不使用ninja,用visual studio。由於編譯中間出了問題在vs裏面好查看。
# set CPU_ONLY=1  # 若是沒有GPU,或者就是想編譯CPU版本,則開啓
set RUN_INSTALL=1 #安裝。默認走的非appveyor分支,RUN_INSTALL爲0,這不是坑人麼。

.\scripts\build_win.cmd # 前面我寫明的修改項都完成後,本行會順利執行。

編譯期間出現「錕斤拷」的亂碼能夠忽略,最後:
成功編譯

成功編譯和安裝

build_win.cmd腳本中的設定,默認編譯的是release模式的。修改腳本,或者乾脆打開cmake生成的build/Caffe.sln工程來編譯debug版本。

2.4 手動CMake構建,使用官方依賴包

.\scripts\build_win.cmd腳本包含了太多內容,對於本地開發來講沒有用還干擾視線。

caffe根目錄下建立編輯compile-xxx.bat腳本,手動調用CMake,簡化流程。

vs2013, cpu模式,使用官方依賴包
compile-vs2013-cpu.bat

set BUILD_DIR=build-vs2013
if exist %BUILD_DIR% rd /s /q %BUILD_DIR%
md %BUILD_DIR%
cd %BUILD_DIR%

set DEP_ROOT=F:/zhangzhuo/lib/caffe_windows_deps

cmake -G "Visual Studio 12 2013 Win64" ^
    -DCAFFE_DEPENDENCIES_ROOT_DIR=%DEP_ROOT% ^
    -DCPU_ONLY=ON ^
    -DBLAS=Open ^
    ..

cd ..

vs2013, 手工指定opencv目錄、動態庫
opencv249的windows pack同時提供動態共享庫和靜態庫,默認靜態庫。編譯caffe須要共享庫,須要手動開啓:OpenCV_STATIC=OFF

set BUILD_DIR=build-vs2013-opencv249
if exist %BUILD_DIR% rd /s /q %BUILD_DIR%
md %BUILD_DIR%
cd %BUILD_DIR%

set DEP_ROOT=D:/lib/caffe_windows_deps
set OpenCV_DIR=D:/lib/opencv_249/build

cmake -G "Visual Studio 12 2013 Win64" ^
    -DCAFFE_DEPENDENCIES_ROOT_DIR=%DEP_ROOT% ^
    -DCPU_ONLY=ON ^
    -DBLAS=Open ^
    -DOpenCV_DIR=%OpenCV_DIR% ^
    -DOpenCV_STATIC=OFF ^
    ..

cd ..

opencv310windows pack只提供了動態庫,因此不用指定-DOpenCV_STATIC=OFF

set BUILD_DIR=build-vs2013-opencv310
if exist %BUILD_DIR% rd /s /q %BUILD_DIR%
md %BUILD_DIR%
cd %BUILD_DIR%

set DEP_ROOT=F:/zhangzhuo/lib/caffe_windows_deps
set OpenCV_DIR=F:/zhangzhuo/lib/opencv_310/build

cmake -G "Visual Studio 12 2013 Win64" ^
    -DCAFFE_DEPENDENCIES_ROOT_DIR=%DEP_ROOT% ^
    -DCPU_ONLY=ON ^
    -DBLAS=Open ^
    -DOpenCV_DIR=%OpenCV_DIR% ^
    ..

cd ..

執行完compile-xxx.bat腳本後,打開生成的.sln文件,分別Release和Debug模式,執行CMakeTargets/INSTALL

2.5 配置pycaffe

若是系統只有一個pycaffe版本
方便點,把build/install/python/caffe文件夾,拷貝到D:\soft\Anaconda2\Lib下。之後再開VSCode時,import caffe不再會報紅了。

系統有多個版本的pycaffe

#coding: utf-8
import sys
sys.path.insert(0, '/path/to/caffe/build/pycaffe')

3. 配置Caffe-SSD

目標檢測算法SSD,其論文做者官方代碼是基於Caffe的魔改版本,我稱其爲Caffe-SSD。在Windows上基於CMake編譯Caffe-SSD,步驟與Caffe-BVLC的windows分支思路一致,都須要排查編譯錯誤、修改少許源碼從而編譯成功。在前面一步中成功的在Windows下基於CMake和官方依賴包進行構建的基礎上,編譯配置Caffe-SSD不難,步驟以下:

3.1 下載代碼、依賴項

cd /d/work
git clone https://github.com/weiliu89/caffe caffe-SSD
cd caffe-SSD
git checkout -b ssd origin/ssd

依賴包的話,使用Caffe-BVLC官方windows分支的依賴包,下載地址、存放目錄見前一節。

3.2 替換CMake腳本

鑑於Caffe-BVLC的windows分支已經爲windows適配作了不少,這裏直接拿來用。從Caffe-BVLC的windows分支裏,拷貝並替換下列文件到Caffe-SSD中:

  • 整個cmake子目錄
  • 根目錄CMakeLists.txt
  • src/caffe/CMakeLists.txt
  • src/gtest/CMakeLists.txt
  • tools/CMakeLists.txt
  • python/CMakeLists.txt

3.3 編寫編譯腳本

參考本文 2.4小節 "手動CMake構建,使用官方依賴包"。

3.4 CPU編譯相關的報錯和解決辦法

我遇到的編譯報錯和解決辦法以下。若是你但願省時間,那麼先按照個人解決方案改一遍再編譯;若是你但願體驗自行修改Caffe-SSD以在windows下成功編譯的快感,不妨先編譯,遇到報錯按照我下面的方法來修改。(我的仍是比較推崇reproducable的modification的

D:\work\caffe-SSD\src\caffe\common.cpp(36): error C3861: 「getpid」: 找不到標識符

解決辦法:common.cpp添加

#ifdef _MSC_VER
#include <process.h>
#endif

fatal error C1083: 沒法打開包括文件: 「gtest/gtest.h」: No such file or directory

解決辦法:net.cpp,註釋掉:

//#include "caffe/test/test_caffe_main.hpp"

error C3861: 「snprintf」: 找不到標識符

解決辦法:bbox_util.hpp添加:

#ifdef _MSC_VER
#define snprintf _snprintf
#endif

error C3861: 「mkdir」: 找不到標識符

解決辦法:在db_lmdb.cpp頭部添加:

#if defined(_MSC_VER)
#include <direct.h>
#define mkdir(X, Y) _mkdir(X)
#endif

src\caffe\util\hdf5.cpp(34): error C2360: 「occurrences_32」的初始化操做由「case」標籤跳過

緣由:使用的LOG_FIRST_N宏,逐層展開後有定義變量。在switch-case的case後若是定義了變量,應當使用花括號包起來。
解決辦法:
src/caffe/util/hdf5.cpp中找到LOG_FIRST_N宏,使用花括號包裹case後的語句塊:

case H5T_INTEGER:
      LOG_FIRST_N(INFO, 1) << "Datatype class: H5T_INTEGER";
      break;
case H5T_INTEGER:
  {
      LOG_FIRST_N(INFO, 1) << "Datatype class: H5T_INTEGER";
  }
  break;

src\caffe\util\io.cpp(44): error C3861: 「open」: 找不到標識符

解決辦法:src/caffe/util/io.cpp#include <fcntl.h>後添加:

#if defined(_MSC_VER)
#include <io.h>
#endif

src\caffe\util\signal_handler.cpp(16): error C2065: 「SIGHUP」: 未聲明的標識符
解決辦法:src/caffe/util/signal_handler.cpp,16行開始幾行,原有的:

case SIGHUP:
      got_sighup = true;
      break;

修改成:

#ifdef _MSC_VER
    case SIGBREAK:  // there is no SIGHUP in windows, take SIGBREAK instead.
      got_sighup = true;
      break;
#else
    case SIGHUP:
      got_sighup = true;
      break;
#endif

src\caffe\util\signal_handler.cpp(37): error C2079: 「sa」使用未定義的 struct「`anonymous-namespace'::HookupHandler::sigaction」

解決辦法:src/caffe/util/signal_handler.cpp,37行開始幾行,原有的:

struct sigaction sa;
    // Setup the handler
    sa.sa_handler = &handle_signal;
    // Restart the system call, if at all possible
    sa.sa_flags = SA_RESTART;
    // Block every signal during the handler
    sigfillset(&sa.sa_mask);
    // Intercept SIGHUP and SIGINT
    if (sigaction(SIGHUP, &sa, NULL) == -1) {
      LOG(FATAL) << "Cannot install SIGHUP handler.";
    }
    if (sigaction(SIGINT, &sa, NULL) == -1) {
      LOG(FATAL) << "Cannot install SIGINT handler.";
    }

修改成:

#ifdef _MSC_VER
    if (signal(SIGBREAK, handle_signal) == SIG_ERR) {
      LOG(FATAL) << "Cannot install SIGBREAK handler.";
    }
    if (signal(SIGINT, handle_signal) == SIG_ERR) {
      LOG(FATAL) << "Cannot install SIGINT handler.";
    }
#else
    struct sigaction sa;
    // Setup the handler
    sa.sa_handler = &handle_signal;
    // Restart the system call, if at all possible
    sa.sa_flags = SA_RESTART;
    // Block every signal during the handler
    sigfillset(&sa.sa_mask);
    // Intercept SIGHUP and SIGINT
    if (sigaction(SIGHUP, &sa, NULL) == -1) {
      LOG(FATAL) << "Cannot install SIGHUP handler.";
    }
    if (sigaction(SIGINT, &sa, NULL) == -1) {
      LOG(FATAL) << "Cannot install SIGINT handler.";
    }
#endif

一樣的,UnhookHandler函數也作相似修改:原來的:

struct sigaction sa;
        // Setup the sighub handler
        sa.sa_handler = SIG_DFL;
        // Restart the system call, if at all possible
        sa.sa_flags = SA_RESTART;
        // Block every signal during the handler
        sigfillset(&sa.sa_mask);
        // Intercept SIGHUP and SIGINT
        if (sigaction(SIGHUP, &sa, NULL) == -1) {
            LOG(FATAL) << "Cannot uninstall SIGHUP handler.";
        }
        if (sigaction(SIGINT, &sa, NULL) == -1) {
            LOG(FATAL) << "Cannot uninstall SIGINT handler.";
        }

修改成:

#ifdef _MSC_VER
        if (signal(SIGBREAK, SIG_DFL) == SIG_ERR) {
            LOG(FATAL) << "Cannot uninstall SIGBREAK handler.";
        }
        if (signal(SIGINT, SIG_DFL) == SIG_ERR) {
            LOG(FATAL) << "Cannot uninstall SIGINT handler.";
        }
#else
        struct sigaction sa;
        // Setup the sighub handler
        sa.sa_handler = SIG_DFL;
        // Restart the system call, if at all possible
        sa.sa_flags = SA_RESTART;
        // Block every signal during the handler
        sigfillset(&sa.sa_mask);
        // Intercept SIGHUP and SIGINT
        if (sigaction(SIGHUP, &sa, NULL) == -1) {
            LOG(FATAL) << "Cannot uninstall SIGHUP handler.";
        }
        if (sigaction(SIGINT, &sa, NULL) == -1) {
            LOG(FATAL) << "Cannot uninstall SIGINT handler.";
        }
#endif

LINK : fatal error LNK1149: 輸出文件名匹配輸入文件名「D:\work\caffe-SSD\build-vs2013-opencv249\lib\Debug\caffe-d.lib」

報錯的意思是,目標輸出的文件與輸入的文件重名了。
解決辦法:使用caffe-BVLC-windows/tools/CMakeLists.txt進行替換

**common.obj) : error LNK2019: 沒法解析的外部符號 "__declspec(dllimport) void __cdecl google::InstallFailureSignalHandler(void**
解決辦法:
common.cpp,56行左右,原來的:

::google::InstallFailureSignalHandler();

修改成:

#if !defined(_MSC_VER)
  ::google::InstallFailureSignalHandler();
#endif

LINK : fatal error LNK1104: 沒法打開文件「python27_d.lib」
緣由:間接的包含了pyconfig.h(anaconda安裝路徑下的),這個文件裏面有這樣幾行:

#           ifdef _DEBUG
#               pragma comment(lib,"python27_d.lib")
#           else
#               pragma comment(lib,"python27.lib")
#           endif /* _DEBUG */

看到網上有人說「修改pyconfig.h」,顯然這沒有必要也不正確。

解決方法:
_caffe.cpp,去掉第一行的:

#include <Python.h>  // NOLINT(build/include_alpha)

Python.h會間接的包含pyconfig.h致使引入python27_d.lib

若是你是VS2015,那麼極可能還須要在_caffe.cpp中,#define BP_REGISTER_SHARED_PTR_TO_PYTHON(PTR)後面,添加這個:

#if defined(_MSC_VER) && (_MSC_FULL_VER >= 190024210)
// Workaround for VS 2015 Update 3 which breaks boost python
// See: http://stackoverflow.com/questions/38261530/unresolved-external-symbols-since-visual-studio-2015-update-3-boost-python-link
// and https://msdn.microsoft.com/vs-knownissues/vs2015-update3
#define BP_GET_POINTER(cls) \
namespace boost { \
template <> \
const volatile caffe::cls * \
get_pointer(const volatile caffe::cls *c) { \
    return c; \
} \
}

#define BP_GET_POINTER_T(cls, dtype) BP_GET_POINTER(cls<dtype>)

// forward declare the NCCL class
// in case we are not using NCCL
namespace caffe {
template <typename Dtype> class NCCL;
}

BP_GET_POINTER_T(Net, float);
BP_GET_POINTER_T(Layer, float);
BP_GET_POINTER_T(Solver, float);
BP_GET_POINTER_T(SGDSolver, float);
BP_GET_POINTER_T(NesterovSolver, float);
BP_GET_POINTER_T(AdaGradSolver, float);
BP_GET_POINTER_T(RMSPropSolver, float);
BP_GET_POINTER_T(AdaDeltaSolver, float);
BP_GET_POINTER_T(AdamSolver, float);
BP_GET_POINTER_T(NCCL, float);
BP_GET_POINTER(Timer);

#endif

3.5 GPU(cuda)編譯相關的報錯和解決辦法

src/caffe/layers/bnll_layer.cu(35): error : identifier "caffe::kBNLL_THRESHOLD" is undefined in device code
解決辦法:
修改kBNLL_THRESHOLD的定義,從:

const float kBNLL_THRESHOLD = 50.;

修改成

#ifdef _MSC_VER
__constant__ float kBNLL_THRESHOLD = 50.;
#else
const float kBNLL_THRESHOLD = 50.;
#endif

libraries_v120_x64_py27_1.1.0\libraries\include\boost-1_61\boost/regex/v4/perl_matcher.hpp(362): error C2292: 'boost::re_detail_106100::perl_matcher<const char ,std::allocator<boost::sub_match<const char >>,boost::regex_traits<char,boost::w32_regex_traits >>': best case inheritance representation: 'virtual_inheritance' declared but 'single_inheritance' required

這個錯誤,網上絕大多數博客給出的解決辦法是「註釋掉regex和rv相關的代碼」。但我以爲這就像是「幹掉了提出問題的人」,過於粗暴。個人解決辦法:
在caffe windows依賴包中修改libraries_v120_x64_py27_1.1.0\libraries\include\boost-1_61\boost\regex\v4\perl_matcher.hpp文件:
#include <boost/regex/v4/iterator_category.hpp>後,添加:

#ifdef _MSC_VER
#pragma pointers_to_members( full_generality, single_inheritance )
#endif

解釋一下:

MSDN上對於pointer_to_memmers的解釋 提到,其語法爲:

#pragma pointers_to_members( pointer-declaration, [most-general-representation] )

而且,most-general-representation的默認值爲best_case
經過google檢索#pragma pointers_to_members發現,這個宏應該是cl.exe特有的,gcc的話我沒有找到,llvm的話彷佛有人提issue要去實現。

以上是我遇到的編譯報錯和解決方法。所有修改掉後,Visual Studio裏分別在Debug和Release模式下執行"CMakeTargets/INSTALL"這一目標,完成編譯和安裝。


4. 在C++項目中使用Caffe

好比不想在原始的caffe工程中添加本身的代碼,這樣保持了caffe自身代碼不變,只要在本身的使用了caffe庫的工程中正確設定,就獨立的開發本身的代碼了。

假設本身的這個工程也是基於cmake構建,最關鍵的一點是,正確配置了前面編譯的caffe的依賴項,而不是本身再去從新配一遍..

注意使用caffe-builder-config.cmake文件

set(CAFFE_DEPENDENCIES_DIR "C:/Users/Administrator/.caffe/dependencies/libraries_v120_x64_py27_1.1.0")
include(${CAFFE_DEPENDENCIES_DIR}/libraries/caffe-builder-config.cmake)

注意opencv版本一致
編譯Caffe用的opencv版本,和須要使用caffe.lib的項目中的opencv版本,應當保持一致。

樣例CMakeLists.txt

cmake_minimum_required(VERSION 3.1)

project(caffe_cpp_play)
set (CMAKE_CXX_STANDARD 11)

#--- caffe dependencies ---
set(CAFFE_DEPENDENCIES_DIR "D:/work/caffe_windows_deps/libraries_v120_x64_py27_1.1.0")
include(${CAFFE_DEPENDENCIES_DIR}/libraries/caffe-builder-config.cmake)

set(PROJ_LINKER_LIBS "")
set(PROJ_INCLUDE_DIR "")

set(CMAKE_VERBOSE_MAKEFILE OFF)


# --- options ---
option(use_opencv "Use OpenCV?" ON)
option(use_cuda "Use CUDA?" OFF)
option(use_glog "Use Glog?" ON)
option(use_gflags "Use GFlags?" ON)
option(use_protobuf "Use Protobuf?" ON)
option(use_caffe "Use Caffe?" ON)
option(use_boost "Use Boost?" ON)

# --- pthread ---
# windows does not need it
#find_package(Threads REQUIRED)
#message("CMAKE_THREAD_LIBS_INIT: ${CMAKE_THREAD_LIBS_INIT}")


# --- opencv ---
if (use_opencv)
    list(APPEND CMAKE_PREFIX_PATH "D:/lib/opencv_249/build")
    find_package(OpenCV REQUIRED)
    message(STATUS "OpenCV library status:")
    message(STATUS "    version: ${OpenCV_VERSION}")
    message(STATUS "    libraries: ${OpenCV_LIBS}")
    message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")
    list(APPEND PROJ_LINKER_LIBS ${OpenCV_LIBS})
endif()


# --- cuda ---
if (use_cuda)
    if (CMAKE_SYSTEM_NAME MATCHES "Windows")
    set(CUDA_DIR "$ENV{CUDA_PATH}")
    else()
        set(CUDA_DIR "/usr/local/cuda")
    endif()
    find_package(CUDA REQUIRED)
    include_directories(${CUDA_DIR}/include)
endif()


#--- Glog & GFlags & Protobuf ---
if (use_glog)
    find_package (Glog REQUIRED)         #OK
    list(APPEND PROJ_LINKER_LIBS ${GLOG_LIBRARIES})
endif()
if (use_gflags)
    find_package (GFlags REQUIRED)       #OK
    list(APPEND PROJ_LINKER_LIBS ${GFLAGS_LIBRARIES})
endif()
if (use_protobuf)
    find_package(Protobuf REQUIRED)      #OK
    list(APPEND PROJ_LINKER_LIBS ${PROTOBUF_LIBRARIES})
endif()


#--- caffe ---
if (use_caffe)
    list(APPEND CMAKE_PREFIX_PATH "D:/work/caffe-BVLC/build-vs2013-opencv249-cuda/install")
    find_package (Caffe REQUIRED)       #OK
    message(STATUS "Caffe library status:")
    message(STATUS "    Caffe_DIR: ${Caffe_DIR}")
    message(STATUS "    Caffe_LIBRARIES: ${Caffe_LIBRARIES}")
    message(STATUS "    CAFFE_INCLUDE_DIRS: ${Caffe_INCLUDE_DIRS}")
    list(APPEND PROJ_LINKER_LIBS ${Caffe_LIBRARIES})
endif()

# --- boost ---
if (use_boost)
    find_package(Boost 1.54 REQUIRED COMPONENTS system thread filesystem regex)
    message(STATUS "Boost library status:")
    message(STATUS "    Boost_INCLUDE_DIRS: ${Boost_INCLUDE_DIRS}")
    message(STATUS "    Boost_LIBRARIES: ${Boost_LIBRARIES}")
    list(APPEND PROJ_LINKER_LIBS ${Boost_LIBRARIES})
endif()


# 添加頭文件搜索路徑
include_directories(${Caffe_INCLUDE_DIRS})


# 添加可執行文件
add_executable(net_demo src/net_demo.cpp)

# Link your application with OpenCV libraries
target_link_libraries(net_demo ${PROJ_LINKER_LIBS})

完整的例子見:
https://github.com/zchrissirhcz/z-toolbox/tree/master/cmake_examples/caffe_cpp_play_better

值得注意的是:前面編譯出來的caffe-BVLC的,其構建類型要與本身的工程一致,也就是debug搭配debug,release搭配release。我這裏實驗發現debug模式下個別庫名字不對,缺乏「d」或者"-d",在Visual Studio裏手動改一下就能夠了。

5. reference

caffe_pvanet,cuda7.5,VS2013

6. changelog

2018-08-24 23:35:41 建立博客,支持Caffe-BVLC Windows分支的編譯 2019-04-06 11:58:08 增長」指定opencv版本和依賴包路徑「相關內容 2019-04-07 14:49:58 增長Caffe-SSD的Windows CPU編譯 2019-04-12 09:13:11 增長Caffe-SSD的Windows GPU編譯

相關文章
相關標籤/搜索