在ubuntu16.04下安装ceres之后,想要编译使用ceres库的测试代码,对于cmake, g++,clang:
一、cmake
直接按照别的博客中说的方法,在CMakeLists.txt文件中加入以下几行:
list( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules )
find_package( Ceres REQUIRED )
include_directories( ${CERES_INCLUDE_DIRS} )
target_link_libraries(ceres_test ${CERES_LIBRARIES} ) // 这里的ceres_test是我在上面add_executable的名字,可根据自己的情况修改
二、g++
g++ -fopenmp main.cpp -o ceres_test -rdynamic /usr/local/lib/libceres.a -lcholmod -llapack -lf77blas -lcxsparse -lglog -I/usr/loca/include -isystem /usr/include/eigen3 -I/usr/include/suitesparse
这个也是直接从别处拷贝过来的,在命令行中执行,可以直接使用、、
三、clang
因为我的ceres要配合之前写好的一个工程里面的东西用,里面只有Makefile,里面用的是clang,所以就折腾了好久,终于用clang可以编译了
中间会报一些bug:
bug1:
/usr/bin/ld: /usr/local/lib/libceres.a(problem_impl.cc.o): undefined reference to symbol 'pthread_rwlock_wrlock@@GLIBC_2.2.5'
//lib/x86_64-linux-gnu/libpthread.so.0: error adding symbols: DSO missing from command line
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Makefile:33: recipe for target 'ceres_test' failed
make: *** [ceres_test] Error 1
这个错误在网上查了很久,说是要加 -lpthread,但是我直接加了这个之后,还是编译不通过,会出现如下显示的信息:
/usr/local/lib/libceres.a(problem_impl.cc.o): In function `ceres::internal::ProgramEvaluator<ceres::internal::ScratchEvaluatePreparer, ceres::internal::CompressedRowJacobianWriter, ceres::internal::NullJacobianFinalizer>::Evaluate(ceres::internal::Evaluator::EvaluateOptions const&, double const*, double*, double*, double*, ceres::internal::SparseMatrix*) [clone ._omp_fn.0]':
problem_impl.cc:(.text._ZN5ceres8internal16ProgramEvaluatorINS0_23ScratchEvaluatePreparerENS0_27CompressedRowJacobianWriterENS0_21NullJacobianFinalizerEE8EvaluateERKNS0_9Evaluator15EvaluateOptionsEPKdPdSC_SC_PNS0_12SparseMatrixE._omp_fn.0[_ZN5ceres8internal16ProgramEvaluatorINS0_23ScratchEvaluatePreparerENS0_27CompressedRowJacobianWriterENS0_21NullJacobianFinalizerEE8EvaluateERKNS0_9Evaluator15EvaluateOptionsEPKdPdSC_SC_PNS0_12SparseMatrixE]+0x28): undefined reference to `omp_get_num_threads'
problem_impl.cc:(.text._ZN5ceres8internal16ProgramEvaluatorINS0_23ScratchEvaluatePreparerENS0_27CompressedRowJacobianWriterENS0_21NullJacobianFinalizerEE8EvaluateERKNS0_9Evaluator15EvaluateOptionsEPKdPdSC_SC_PNS0_12SparseMatrixE._omp_fn.0[_ZN5ceres8internal16ProgramEvaluatorINS0_23ScratchEvaluatePreparerENS0_27CompressedRowJacobianWriterENS0_21NullJacobianFinalizerEE8EvaluateERKNS0_9Evaluator15EvaluateOptionsEPKdPdSC_SC_PNS0_12SparseMatrixE]+0x2f): undefined reference to `omp_get_thread_num'
/usr/local/lib/libceres.a(problem_impl.cc.o): In function `ceres::internal::ProgramEvaluator<ceres::internal::ScratchEvaluatePreparer, ceres::internal::CompressedRowJacobianWriter, ceres::internal::NullJacobianFinalizer>::Evaluate(ceres::internal::Evaluator::EvaluateOptions const&, double const*, double*, double*, double*, ceres::internal::SparseMatrix*)':
problem_impl.cc:
然后中间很长时间,陷入死循环,在去掉-lpthread和加上它之间折腾,也在网上搜,也没有搜到有效的信息。
后来又试了cmake,直接编译和链接成功了。就去看了cmake产生的各种.make文件,最终发现它的link.txt里面会有一项-lgomp,后来又加上了-fopenmp,这个时候会发现一直说找不到omp.h 或者没有libomp.so的错误,上网搜,会发现llvm可以支持,但是并没有默认安装这个库,所以就去官方下载,手动安装了,再把libomp.so 和omp.h分别拷到了 /usr/lib 和/usr/include下面,就可以用了。
附上最终的makefile:
EXECUTABLE = ceres_test
OBJS = build/main.o
CXX = clang++
LINK = clang++SRC ?= ./
FLAGS += -O3 -std=c++11 -fopenmp -g -I/usr/include/eigen3 -I/usr/local/include -I/usr/include -I/usr/local/include -I/usr/include/eigen3 -I/usr/include/suitesparse
LFLAGS += -std=c++11 -g -L/usr/lib -L/usr/lib/x86_64-linux-gnu -L/usr/local/lib -lceres -lcholmod -llapack -lf77blas -lcxsparse -lglog -lgflags -lspqr -lcholmod -lccolamd -lcamd -lamd -lsuitesparseconfig -lpthread -lgompifeq ($(UNAME), Darwin)
LFLAGS += -pagezero_size 10000 -image_base 100000000endif
ifeq ($(UNAME), Linux)
LFLAGS += -Wl,-rpath, -lpthreadS4 = 64
endif
.SUFFIXES:
.PHONY: all purge clean
all: $(EXECUTABLE)
附:
编译openmp:
1、到llvm官网下载源码:http://releases.llvm.org/download.html#3.8.0 (因为我的clang之前安装的是3.8.0版本的,所以下了这个版本,可以根据自己clang版本去下载对应的)
2、把下下来的源码解压,新建build文件夹,进入build文件夹,然后分别执行:
cmake ..
make
3. 把编译好的.h文件和libomp.so (都在openmp-3.8.0.src/build/runtime/src里面)文件拷贝到 /usr/include 和/usr/lib文件夹下面