windows下编译colmap3.6[colmap][gmp][mfpr]

编译colmap

1 前期准备

1 github上下载colmap稳定版源码:

https://github.com/colmap/colmap/archive/refs/tags/3.6.zip
之后解压进入,执行: git init

2 确保编译环境
  • 1 确保你的vs不是vs2019 16.9.3以及以上,否则会有奇怪的cuda错误, 解决方案是:
    • 1.1 将vs2019卸载
    • 1.2 去https://docs.microsoft.com/en-us/visualstudio/releases/2019/history#installing-an-earlier-release下载vs2019 16.8.5,然后安装v140,v141的生成工具
  • 2 如果本篇博客所有内容都详细读完,任然无法成功编译colmap,那就装VS2015,然后用他的生成工具(cmake -G 参数指定编译器版本,命令行里输入cmake -G),项目打开还是可以用vs2019的。

然后将编译器加入环境变量:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.16.27023\bin\HostX64\x64
输入cl能看到输出即可.

2 依赖安装

2.1 boost 直接安装(推荐下载vs2015版本,我用的是v_1_73)

https://boostorg.jfrog.io/artifactory/main/release/1.64.0/binaries/

boost使用源码编译的静态方式编译:
```sh
.\b2.exe  --toolset=msvc-14.2 `
--address-model=64 `
--architecture=x86 `
--threading=multi `
-sZLIB_SOURCE="F:\BASE_ENV\forOpenMVS\zlib-1.2.11" -sZLIB_INCLUDE="F:\BASE_ENV\forOpenMVS\zlib-1.2.11" `
--with-iostreams --with-iostreams --with-log --with-program_options --with-graph --with-test --with-regex --with-filesystem `
--link=static --runtime-link=shared --build-type=complete `
stage --stagedir="F:\BASE_ENV\forOpenMVS\boost_1_66_0\msvc142_linkStatic_runShared" `
2.2 安装GMP和MFPR
  • 0 不想要自己折腾: 参考: https://github.com/emphasis87/libmpfr-msys2-mingw64,这里面应该有现成的库。
  • 1 安装Cygwin
Setup Environment
Install Cygwin, add the following packages to the default installation: 

gcc-core
gcc-g++
libgcc
m4
make #不知为何安装后在Cygwin根目录下搜不到make程序,见下面步骤2安装make
cmake
bash
Add the following Environment Variable to the User PATH: C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.15.26726\bin\Hostx64\x64
This is so you can use the lib command. Your lib.exe may be located elsewhere.

安装好Cygwin以及一些依赖以后,在其根目录(方便说明记为: CygwinRoot=“D:\CygwinRooto”)下的bin/minnty.exe是其终端入口,然后每次打开该终端,进入的是: C y g w i n R o o t / h o m e / CygwinRoot/home/ CygwinRoot/home/(userName), 运行"cd /"后就可以理解了;

  • 2 下载并安装make

    • 2.1 从如下网址下载make的源码,https://ftp.gnu.org/gnu/make/,然后解压
    • 2.2 打开Cygwin64 Terminal命令行,进入源码根目录,然后运行:configure && ./build.sh
    • 2.3 编译得到了make.exe后将其移动到Cygwin的bin目录下
  • 3 编译gmp
    运行两个: ./configure 和 make install

./configure --prefix=/home/chenxy/mylibs/newTry/gmp-6.2.0/build/static --enable-static --disable-shared
configure: summary of build options:

  Version:           GNU MP 6.2.0
  Host type:         skylake-pc-cygwin
  ABI:               64
  Install prefix:    /home/chenxy/mylibs/newTry/gmp-6.2.0/build/static
  Compiler:          gcc
  Static libraries:  yes
  Shared libraries:  no

编译结果(默认生成的是static的数据):

@nash-5 ~/mylibs/gmp-6.2.0
$ ls /usr/local/include/
gmp.h

@nash-5 ~/mylibs/gmp-6.2.0
$ ls /usr/local/lib/
libgmp.a  libgmp.la  pkgconfig

生成动态连接库(注意: 动态连接库和静态连接库的.h文件不同,所以注意分成2个文件夹,至少对于gmp是如此):

./configure --prefix=/home/chenxy/mylibs/gmp-6.2.0/build/shared --enable-shared --disable-static
  • 4 编译mfpr(需要gmp的依赖,而且是动态连接库)
    进入mfpr的根目录:
    运行./configure:
checking for gmp.h... no
configure: error: gmp.h can't be found, or is unusable.

运行./configure --help

···
  --with-gmp-include=DIR  GMP include directory
  --with-gmp-lib=DIR      GMP lib directory
···

所以:

./configure --prefix=/home/chenxy/mylibs/newTry/mpfr-4.1.0/build/static \
--enable-static --disable-shared \
--with-gmp-include=/home/chenxy/mylibs/newTry/gmp-6.2.0/build/static/include \
--with-gmp-lib=/home/chenxy/mylibs/newTry/gmp-6.2.0/build/staic/lib

make install
./configure --prefix=/home/chenxy/mylibs/mpfr-4.1.0/build/static \
--with-gmp-include=/home/chenxy/mylibs/gmp-6.2.0/build/static/include \
--with-gmp-lib=/home/chenxy/mylibs/gmp-6.2.0/build/static/lib \
--enable-static --disable-shared
2.3 其他依赖build.py会帮你下载编译

确保你能够流畅访问github,否则需要你自己下载然后修改build.py。

3 编译colmap

3.1 对编译文件和某些源文件的修改如下:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7333a04..d73a6ad 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -72,8 +72,10 @@ endif()
 
 if(BOOST_STATIC)
     set(Boost_USE_STATIC_LIBS ON)
+    # message("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ using static boost", ${BOOST_STATIC})
 else()
     add_definitions("-DBOOST_TEST_DYN_LINK")
+    # message("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ using dll boost", ${BOOST_STATIC})
 endif()
 
 ################################################################################
@@ -86,6 +88,7 @@ endif()
 
 find_package(Ceres REQUIRED)
 
+set(Boost_DEBUG ON)
 find_package(Boost REQUIRED COMPONENTS
              program_options
              filesystem
diff --git a/scripts/python/build.py b/scripts/python/build.py
index 89dff59..fe1e4c4 100644
--- a/scripts/python/build.py
+++ b/scripts/python/build.py
@@ -75,10 +75,12 @@ def parse_args():
                         help="The path to the folder containing Boost, "
                              "e.g., under Windows: "
                              "C:/local/boost_1_64_0/lib64-msvc-12.0")
+    parser.add_argument("--boost_include_dir", default="F:/BASE_ENV/forOpenMVS/boost_1_73_0_v140")
+    parser.add_argument("--boost_lib_dir", default="F:/BASE_ENV/forOpenMVS/boost_1_73_0_v140/lib64-msvc-14.0")
     parser.add_argument("--cgal_path", default="",
                         help="The path to the folder containing CGAL, "
                              "e.g., under Windows: C:/dev/CGAL-4.11.2/build")
-    parser.add_argument("--cuda_path", default="",
+    parser.add_argument("--cuda_path", default="C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v10.2",
                         help="The path to the folder containing CUDA, "
                              "e.g., under Windows: C:/Program Files/NVIDIA GPU "
                              "Computing Toolkit/CUDA/v8.0")
@@ -108,7 +110,7 @@ def parse_args():
                         help="Whether to build unit tests")
     parser.add_argument("--build_type", default="Release",
                         help="Build type, e.g., Debug, Release, RelWithDebInfo")
-    parser.add_argument("--cmake_generator", default="",
+    parser.add_argument("--cmake_generator", default="Visual Studio 14",
                         help="CMake generator, e.g., Visual Studio 14")
     parser.add_argument("--no_ssl_verification",
                         dest="ssl_verification", action="store_false",
@@ -429,8 +431,28 @@ def build_colmap(args):
         extra_config_args.append(
             "-DBOOST_ROOT={}".format(args.boost_path))
         extra_config_args.append(
-            "-DBOOST_LIBRARYDIR={}".format(args.boost_path))
-
+            "-DBOOST_INCLUDEDIR={}".format(args.boost_include_dir))
+        extra_config_args.append(
+            "-DBOOST_LIBRARYDIR={}".format(args.boost_lib_dir))
+        # print("BOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOST: ", extra_config_args)
+        # extra_config_args.append("-DBOOST_STATIC=ON")
+        # extra_config_args.append("-DBoost_USE_STATIC_LIBS=ON")
+        # extra_config_args.append("-DBoost_USE_MULTITHREADED=ON")
+        # extra_config_args.append("-DBoost_USE_STATIC_RUNTIME=ON")
+        # extra_config_args.append("-DBOOST_ALL_DYN_LINK=ON")
+    
+    # -DGMP_INCLUDE_DIR="F:\BASE_ENV\forOpenMVS\gmp_mpfr\include" `
+    # -DGMP_LIBRARIES="F:\BASE_ENV\forOpenMVS\gmp_mpfr\lib\libgmp-10.lib" `
+    # -DMPFR_INCLUDE_DIR="F:\BASE_ENV\forOpenMVS\gmp_mpfr\include" `
+    # -DMPFR_LIBRARIES="F:\BASE_ENV\forOpenMVS\gmp_mpfr\lib\libmpfr-4.lib" 
+    extra_config_args.append(
+        "-DGMP_INCLUDE_DIR={}".format("F:/BASE_ENV/forOpenMVS/gmp_mpfr/include"))
+    extra_config_args.append(
+        "-DGMP_LIBRARIES={}".format("F:/BASE_ENV/forOpenMVS/gmp_mpfr/lib/libgmp-10.lib"))
+    extra_config_args.append(
+        "-DMPFR_INCLUDE_DIR={}".format("F:/BASE_ENV/forOpenMVS/gmp_mpfr/include"))
+    extra_config_args.append(
+        "-DMPFR_LIBRARIES={}".format("F:/BASE_ENV/forOpenMVS/gmp_mpfr/lib/libmpfr-4.lib"))
     if args.cuda_path != "":
         extra_config_args.append(
             "-DCUDA_TOOLKIT_ROOT_DIR={}".format(args.cuda_path))
@@ -479,6 +501,8 @@ def build_post_process(args):
                         os.path.basename(lapack_path)))
 
         if args.qt_path:
+            print("copying !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", os.path.join(args.qt_path, "bin/Qt5Core.dll"))
+            print("copying !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", os.path.join(args.install_path, "lib/Qt5Core.dll"))
             copy_file_if_not_exists(
                 os.path.join(args.qt_path, "bin/Qt5Core.dll"),
                 os.path.join(args.install_path, "lib/Qt5Core.dll"))
diff --git a/src/retrieval/utils.h b/src/retrieval/utils.h
index b99bf64..d773220 100644
--- a/src/retrieval/utils.h
+++ b/src/retrieval/utils.h
@@ -52,7 +52,8 @@ struct ImageScore {
 template 
 class HammingDistWeightFunctor {
  public:
-  static const size_t kMaxHammingDistance = static_cast(1.5f * kSigma);
+  // static const size_t kMaxHammingDistance = static_cast(1.5f * kSigma);
+  static const size_t kMaxHammingDistance = 24;
 
   HammingDistWeightFunctor() {
     // Fills the look-up table.

(END)
3.2 编辑CmakeList.txt

set(Boost_DEBUG ON),打开boost的调试信息,boost的链接最容易出问题。(以下的内容仅供了解,无需修改)

主要注意: -DBoost_USE_STATIC_RUNTIME=ON 这个设置是指boost的库在使用cpp的runtime时候将会使用静态库,如果这个选项打开了,则需要往CmakeList.txt(colmap的根目录)中添加:

# set the used type of runtime lib to be static
set(CMAKE_CXX_FLAGS_RELEASE "/MT")
set(CMAKE_CXX_FLAGS_DEBUG "/MTd")

上面意味着运行时库调用时选择静态运行时库(vs中,在项目->cpp->代码生成中有MT/MD的配置), 而且对应的编译出来的boost库,编译时需要带上: --link=static --runtime-link=static --build-type=complete 参数;

3.3 编译执行:

注意我们使用静态的boost避免boost 的链接错误;

python scripts/python/build.py \
    --build_path "F:/prjs/colmap-3.6/build" \
    --colmap_path "F:/prjs/colmap-3.6" \
    --boost_path "F:/BASE_ENV/forOpenMVS/boost_1_73_0_v140" \
    --boost_include_dir "F:/BASE_ENV/forOpenMVS/boost_1_73_0_v140" \
    --boost_lib_dir "F:/BASE_ENV/forOpenMVS/boost_1_73_0_v140\lib64-msvc-14.0" \
    --qt_path "F:/BASE_ENV/forOpenMVS/qt_msvc2015_64/msvc2015_64" \
    --cgal_path "F:/BASE_ENV/forOpenMVS/CGAL-5.1/build" \
    --cmake_generator "Visual Studio 14" \
    --with_cuda \
    --cuda_path "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v10.2" \

上述命令会失败,但是没关系,用code打开F:/prjs/colmap-3.6/build/colmap/build
全局替换的方式删除: BOOST_ALL_DYN_LINK=1,
然后在F:/prjs/colmap-3.6/build/colmap/__build__里找到COLMAP.sln,然后手动用vs打开然后编译;
推荐使用VS2015的工具对colmap进行编译.

4 给出我编译后的库目录结构(最重要的是__install__/lib下面的内容):

其中: install/lib下面的platform中必须要有qwindows.dll,参考问题4。
然后: install/lib里面的cgal*.dll也是不必须的,因为本博客使用的cgal是5.x,5.x的cgal都是header only 的库,所以该dll可以没有,但是其他的dll像是libgmp-10.dll确是必要的,否则将无法运行。

sagar@DESKTOP-QM75KNS MINGW64 /f/prjs/colmap-3.6/build
$ ls
__download__  ceres-solver              colmap  freeimage  glew  suite-sparse
__install__   CGAL-vc140-mt-4.14.3.dll  eigen   gflags     glog
sagar@DESKTOP-QM75KNS MINGW64 /f/prjs/colmap-3.6/build
$ ls __download__/
ceres-solver-1.14.0.zip  freeimage-3.18.0.zip  glew-2.1.0.zip  suite-sparse.zip
eigen-3.3.7.zip          gflags-2.2.2.zip      glog-0.3.5.zip
sagar@DESKTOP-QM75KNS MINGW64 /f/prjs/colmap-3.6/build
$ ls
__download__  ceres-solver              colmap  freeimage  glew  suite-sparse
__install__   CGAL-vc140-mt-4.14.3.dll  eigen   gflags     glog

sagar@DESKTOP-QM75KNS MINGW64 /f/prjs/colmap-3.6/build
$ cd __install__/lib

sagar@DESKTOP-QM75KNS MINGW64 /f/prjs/colmap-3.6/build/__install__/lib
$ tree
.
├── FreeImage.dll
├── FreeImage.lib
├── Qt5Core.dll
├── Qt5Gui.dll
├── Qt5Widgets.dll
├── ceres.lib
├── cmake
│   ├── gflags
│   │   ├── gflags-config-version.cmake
│   │   ├── gflags-config.cmake
│   │   ├── gflags-nonamespace-targets-release.cmake
│   │   ├── gflags-nonamespace-targets.cmake
│   │   ├── gflags-targets-release.cmake
│   │   └── gflags-targets.cmake
│   ├── glew
│   │   ├── CopyImportedTargetProperties.cmake
│   │   ├── glew-config.cmake
│   │   ├── glew-targets-release.cmake
│   │   └── glew-targets.cmake
│   ├── glog
│   │   ├── glog-config-version.cmake
│   │   ├── glog-config.cmake
│   │   ├── glog-targets-release.cmake
│   │   └── glog-targets.cmake
│   └── suitesparse-4.5.0
│       ├── SuiteSparse-targets-release.cmake
│       ├── SuiteSparse-targets.cmake
│       ├── suitesparse-config-version.cmake
│       └── suitesparse-config.cmake
├── colmap
│   ├── colmap.lib
│   ├── colmap_cuda.lib
│   ├── flann.lib
│   ├── graclus.lib
│   ├── lsd.lib
│   ├── pba.lib
│   ├── poisson_recon.lib
│   ├── sift_gpu.lib
│   ├── sqlite3.lib
│   └── vlfeat.lib
├── cudart64_102.dll
├── gflags_nothreads_static.lib
├── gflags_static.lib
├── glew32.dll
├── glew32.lib
├── glog.lib
├── libamd.lib
├── libblas.dll
├── libbtf.lib
├── libcamd.lib
├── libccolamd.lib
├── libcholmod.lib
├── libcolamd.lib
├── libcxsparse.lib
├── libgcc_s_sjlj-1.dll
├── libgfortran-3.dll
├── libglew32.lib
├── libgmp-10.dll
├── libklu.lib
├── liblapack.dll
├── libldl.lib
├── libquadmath-0.dll
├── libspqr.lib
├── libumfpack.lib
├── metis.lib
├── pkgconfig
│   └── glew.pc
├── platforms
│   └── qwindows.dll
└── suitesparseconfig.lib

8 directories, 62 files

5 可能遇到的问题:

  • Q 1 一切都能正常编译通过,但是出现“程序无法正常启动, 0xc000007b”
  • 解决方案: 仔细核对我提供的目录,看看是否是dll少了,一般libgmp-10.dll少了就会报这个错误,可以参照问题4
  • Q 2 boost总是报link2005的重定义错误:
  • 解决方案: 打开colmap.sln,你会发现: 项目->属性c++预处理(宏定义) 中多了BOOST_ALL_DYN_LINK=1,用如下方法全局删除即可:用code打开F:/prjs/colmap-3.6/build/colmap/build
    全局替换的方式删除: BOOST_ALL_DYN_LINK=1,然后vs会让你重载项目配置,再次编译应该可以直接通过。造成的原因可能是boost总是默认enable了autolink,这导致你必须把你的boost库的版本和你的vs版本对上,而且可能默认是全部动态链接(即使你配置了静态链接以后),可能的解决方案是,在项目根目录下面的CMAKELIST.txt中添加:
  • Q 3 libcpmt.lib(ppltasks.obj) : error LNK2001: 无法解析的外部符号 __CxxFrameHandler4报错:
  • 解决方案: 是因为你的库用的是vs2019编译的,然后colmap又用vs2015编译,就会报这个错误。
  • Q 4 Qt platform plugin ‘windows’ not found
  • 解决方案: 是因为你虽然安装了qt,但是没有复制相关的dll到./build/colmap/install/lib下(colmap的运行直接双击__install__/COLMAP.BAT即可),复制方案:(也就是build.py中的编译后处理部分做的事情)
def build_post_process(args):
    if PLATFORM_IS_WINDOWS:
        lapack_paths = glob.glob(
            os.path.join(args.install_path, "lib64/lapack_blas_windows/*.dll"))
        if lapack_paths:
            for lapack_path in lapack_paths:
                copy_file_if_not_exists(
                    lapack_path,
                    os.path.join(
                        args.install_path, "lib",
                        os.path.basename(lapack_path)))

        if args.qt_path:
            copy_file_if_not_exists(
                os.path.join(args.qt_path, "bin/Qt5Core.dll"),
                os.path.join(args.install_path, "lib/Qt5Core.dll"))
            copy_file_if_not_exists(
                os.path.join(args.qt_path, "bin/Qt5Gui.dll"),
                os.path.join(args.install_path, "lib/Qt5Gui.dll"))
            copy_file_if_not_exists(
                os.path.join(args.qt_path, "bin/Qt5Widgets.dll"),
                os.path.join(args.install_path, "lib/Qt5Widgets.dll"))
            mkdir_if_not_exists(
                os.path.join(args.install_path, "lib/platforms"))
            copy_file_if_not_exists(
                os.path.join(args.qt_path, "plugins/platforms/qwindows.dll"),
                os.path.join(args.install_path, "lib/platforms/qwindows.dll"))

        if args.with_cuda and args.cuda_path:
            cudart_lib_path = glob.glob(os.path.join(args.cuda_path,
                                                     "bin/cudart64_*.dll"))[0]
            copy_file_if_not_exists(
                cudart_lib_path,
                os.path.join(args.install_path, "lib",
                             os.path.basename(cudart_lib_path)))

        if args.cgal_path:
            gmp_lib_path = os.path.join(
                args.cgal_path, "auxiliary/gmp/lib/libgmp-10.dll")
            if os.path.exists(gmp_lib_path):
                copy_file_if_not_exists(
                    gmp_lib_path,
                    os.path.join(args.install_path, "lib/libgmp-10.dll"))
            cgal_lib_path = glob.glob(os.path.join(
                args.cgal_path, "bin/CGAL-vc*-mt-*.dll"))
            copy_file_if_not_exists(
                cgal_lib_path[0],
                os.path.join(args.install_path, "lib",
                    os.path.basename(cgal_lib_path[0])))
  • Q 5 莫名其妙报了cuda的编译的错误:error : identifier “__floorf” is undefined in device code
  • 解决方案: vs2019 16.9.3以及以上有这个问题,你需要卸载然后回退到16.8.5
  • Q 6 C2132 编译器错误:表达式的计算结果不是常数
  • 解决方案: 可能是你的编译器对cpp的新特性支持的不够好?,修改 src/retrieval/utils.h 的 55行为:
  // static const size_t kMaxHammingDistance = static_cast(1.5f * kSigma);
  static const size_t kMaxHammingDistance = static_cast(24);

你可能感兴趣的:(windows基础配置,cpp,colmap,windows编译)