跨平台编译ceres for Android
折腾了几乎一天,记录一下。
最大的坑是官网给出的
1.进入ceres源代码目录下的jni目录
2.EIGEN_PATH="指向eigen库目录,即包含EIGEN文件夹的那个文件夹” ndk-build
这方法的确编译出了一个近700M的静态库,但使用时总是未定义链接错误。现在想想跟以前编译OpenCV时遇到的错误相似,
解决的办法也相似,通过cmake调用ndk的工具链编译。
我编译动态库的命令
/home/hk/Android/Sdk/cmake/3.10.2.4988404/bin/cmake -DCMAKE_TOOLCHAIN_FILE=/home/hk/Android/Sdk/ndk/20.0.5594570/build/cmake/android.toolchain.cmake -DEIGEN_INCLUDE_DIR=/home/hk/ndk/eigen-git-mirror-3.3.6 -DANDROID_ABI=arm64-v8a -DANDROID_STL=c++_shared -DANDROID_NATIVE_API_LEVEL=android-27 -DBUILD_SHARED_LIBS=ON -DBUILD_TESTING=OFF -DBUILD_EXAMPLES=OFF -DMINIGLOG=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS="-s" /home/hk/ndk/ceres-solver-master
注意一定要在一行,否则可能配置错误,生成Lunix格式的库。可先在文本文档里写好,然后复制到终端。这里用到的cmake是android studio安装的
,本来装的是3.5版本,这里要求高版本。
详细的解释下
#这部分是指定工具链,工具链在ndk里
-DCMAKE_TOOLCHAIN_FILE=/home/hk/Android/Sdk/ndk/20.0.5594570/build/cmake/android.toolchain.cmake
#这部分指定Eigen库路径,要求3.3.4以上
-DEIGEN_INCLUDE_DIR=/home/hk/ndk/eigen-git-mirror-3.3.6
#这部分指定abi,我是arm64-v8a
-DANDROID_ABI=arm64-v8a
#这部分指定STL,这里可能要跟项目用的一致,就是要跟项目编译c++文件的那个STL一致,若选择c++_static应该也可以,一致就行,项目选择STL在
#gradle里设置,这在下面介绍
-DANDROID_STL=c++_shared
#指定android版本27对应android 8.1.0
-DANDROID_NATIVE_API_LEVEL=android-27
#ON就是动态库,OFF就是静态库
-DBUILD_SHARED_LIBS=ON
#不编译测试,没意义,不可能在LINUX上运行的,库是android的格式
-DBUILD_TESTING=OFF
#不编译列子
-DBUILD_EXAMPLES=OFF
#不依赖glog源码了,这里是重点,这里选择ON会使用ceres目录下/ceres-solver-master/internal/ceres/miniglog里的代码代替glog
#当库放入android项目时需要将这个目录里的头文件也加入项目,比如可直接将这个目录加入项目的头文件路径
-DMINIGLOG=ON
#非调试版本
-DCMAKE_BUILD_TYPE=Release
#不懂
-DCMAKE_C_FLAGS="-s"
#指定ceres目录,即CMakeLists.txt所在的目录路径
/home/hk/ndk/ceres-solver-master
配置成功的特点是
.........
-- Check for working C compiler: /home/hk/Android/Sdk/ndk/20.0.5594570/toolchains/llvm/prebuilt/linux-x86_64/bin/clang
-- Check for working C compiler: /home/hk/Android/Sdk/ndk/20.0.5594570/toolchains/llvm/prebuilt/linux-x86_64/bin/clang -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /home/hk/Android/Sdk/ndk/20.0.5594570/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++
-- Check for working CXX compiler: /home/hk/Android/Sdk/ndk/20.0.5594570/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ -- works
.........
即cmake选择的默认编译器是clang和clang++
配置好后sudo make
生成好后将.so库放入app下的libs里,我是新建arm64-v8a文件夹,然后放在里面的。
libs里新建include,头文件都放在这里。重点是,差个 config.h,cmake生成库的那个目录里搜索下,有个新生成的config.h,将其放到指定地方即可。指定的地方错误提示会指出。
注意,这个libs文件夹没有跟jniLibs相关联,里面的.so不会放入.apk,关联在gradle里设置,下面会给出完整的配置。
看看libs文件夹的内容

gradle配置
apply plugin: 'com.android.application'
android {
compileSdkVersion
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.example.myapplication"
minSdkVersion
targetSdkVersion
versionCode
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
//项目的ndk配置需和使用的库一致,项目的配置在这里设置
externalNativeBuild {
cmake {
cppFlags "-std=c++11"
//arguments '-DANDROID_STL=c++_static'
arguments '-DANDROID_STL=c++_shared'
abiFilters "arm64-v8a"
}
}
//指定jniLibs目录只有这个目录里的.so动态库会被加载到.apk
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}
cmake配置
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.) #要求支持c++
set(CMAKE_CXX_STANDARD )
set(CMAKE_CXX_STANDARD_REQUIRED ON) #设置第三方库目录路径参数
set(libs_path ${CMAKE_SOURCE_DIR}/../../../libs) #引入glog头文件
include_directories( ${libs_path}/include ) ##########添加Ceres静态库 begin#########
add_library(
ceres #库名字 去掉了 lib 与 .a
SHARED #必须的
IMPORTED #必须的
)
#指定Ceres静态库位置
set_target_properties(
ceres
PROPERTIES IMPORTED_LOCATION
${libs_path}/arm64-v8a/libceres.so
)
#引入Ceres的头文件
include_directories( ${libs_path}/include )
##########添加Ceres静态库 end######### ##########添加Eigen库 begin#########
#引入Eigen的头文件
include_directories( ${libs_path}/include )
##########添加Eigen库 begin######### ##########添加添加native-lib动态库 begin#########
add_library(
native-lib
SHARED
native-lib.cpp
)
#查找要链接的android log库
find_library(
log-lib
log )
#链接库
target_link_libraries(
native-lib
${log-lib}
ceres
#openmap库
#若编译Ceres时使用了 -DCERES_USE_OPENMP
#则在使用Ceres时必须链接上OpenMap库
#omp
)
##########添加添加native-lib动态库 end#########
测试代码就是ceres的hello ceres示列,将其放入jni函数里
#include <jni.h>
#include <string> #include "ceres/ceres.h"
#include "glog/logging.h" using ceres::AutoDiffCostFunction;
using ceres::CostFunction;
using ceres::Problem;
using ceres::Solver;
using ceres::Solve; // A templated cost functor that implements the residual r = 10 -
// x. The method operator() is templated so that we can then use an
// automatic differentiation wrapper around it to generate its
// derivatives.
struct CostFunctor {
template <typename T> bool operator()(const T* const x, T* residual) const {
residual[] = 10.0 - x[];
return true;
}
}; extern "C" JNIEXPORT jstring JNICALL
Java_com_example_myapplication_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello Ceres"; // The variable to solve for with its initial value. It will be
// mutated in place by the solver.
double x = 0.5;
const double initial_x = x; // Build the problem.
Problem problem; // Set up the only cost function (also known as residual). This uses
// auto-differentiation to obtain the derivative (jacobian).
CostFunction* cost_function =
new AutoDiffCostFunction<CostFunctor, , >(new CostFunctor);
problem.AddResidualBlock(cost_function, NULL, &x); // Run the solver!
Solver::Options options;
options.minimizer_progress_to_stdout = true;
Solver::Summary summary;
Solve(options, &problem, &summary); std::cout << summary.BriefReport() << "\n";
std::cout << "x : " << initial_x
<< " -> " << x << "\n"; return env->NewStringUTF(summary.BriefReport().c_str());
}
跨平台编译ceres for Android的更多相关文章
- ceres for Android 太慢的解决方法
跨平台编译了ceres,结果在android平台上运行的太慢,优化一次要0.3秒左右,时不时要一两秒.这太扯了.没辙了,在google上瞎搜索,看到 Jacobian evaluation is ve ...
- 编译可在Android上运行的qemu user mode
前言 本文在Ubuntu 64位系统上对qemu项目进行交叉编译,并且只编译与qemu user mode有关的代码. 下文中的”NDK”若无特殊说明均指”Android NDK”. 下文中”$NDK ...
- 系列篇|编译可在Android上运行的依赖库(一):glib库
前言 这是系列文章,它们由<编译可在Android上运行的glib库>及其他4篇文章组成,这4篇文章在“编译依赖库”一节中列出.由于glib库依赖于其他第三方库,所以需要先将依赖的第三方库 ...
- 在Windows/Ubuntu下安装OpenGL环境(GLUT/freeglut)与跨平台编译(mingw/g++)
GLUT/freeglut 是什么? OpenGL 和它们有什么关系? OpenGL只是一个标准,它的实现一般自带在操作系统里,只要确保显卡驱动足够新就可以使用.如果需要在程序里直接使用OpenGL, ...
- win下 golang 跨平台编译
mac 下编译其他平台的执行文件方式请参看这篇文章,http://www.cnblogs.com/ghj1976/archive/2013/04/19/3030703.html 本篇文章是win下的 ...
- 【转】在Ubuntu上下载、编译和安装Android最新源代码
原文网址:http://blog.csdn.net/luoshengyang/article/details/6559955 看完了前面说的几本书之后,对Linux Kernel和Android有一定 ...
- 在Ubuntu上下载、编译和安装Android最新源码
看完了前面说的几本书之后,对Linux Kernel和Android有一定的认识了,是不是心里蠢蠢欲动,想小试牛刀自己编译一把Android源码了呢?一直习惯使用Windows系统,而Android源 ...
- 在Ubuntu上下载、编译和安装Android最新内核源代码(Linux Kernel)
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6564592 在前一篇文章提到,从源代码树下载下 ...
- 在Ubuntu上下载、编译和安装Android最新源代码
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6559955 看完了前面说的几本书之后,对Lin ...
随机推荐
- 02 MySQL之数据表的基本操作
01-创建数据表 # 切换数据库 use test_db; # 创建数据表 语法规则如下: create table 表名 ( 字段名1, 数据类型 [列级别约束条件] [默认值], 字段名2, 数据 ...
- [Jenkins]局域网内可访问配置方法 -windows
如果是把jenkins.war放在tomcat中运行,则当jenkins宿主机,启动tomcat服务之后,则直接可以通过局域网访问jenkins 下面这种情况是,直接通过jenkins.exe安装的 ...
- openstack核心组件--nova计算服务(3)
一.nova介绍: Nova 是 OpenStack 最核心的服务,负责维护和管理云环境的计算资源.OpenStack 作为 IaaS 的云操作系统,虚拟机生命周期管理也就是通过 Nova ...
- React Native使用Mobx总结
参考博客: http://www.jianshu.com/p/505d9d9fe36a 这是我看的学习Mobx目前为止觉得最详细学习的博客了. 下面只是记录下我的学习和一些简单的使用: 需要引入 ...
- 使用kubeadm安装kubernetes1.12.2版本脚本【h】
Master节点脚本: #!/bin/sh#使用系统的PATH环境export PATH=`echo $PATH` #停止firewall防火墙,并禁止开机自启动 systemctl stop fir ...
- 【JAVA系列】使用JavaScript实现网站访问次数统计代码
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[JAVA系列]使用JavaScript实现网站 ...
- DP经典问题—————(LCIS)最长公共上升子序列
这道题是LIS(最长上升子序列)与LCS(最长公共子序列)问题的综合版本,有关这两个问题可以看一下我的文章:https://www.cnblogs.com/myhnb/p/11305551.html ...
- Tool.js(javascript帮助类)
//string.format $.format = function (source, params) { ) return function () { var args = $.makeArray ...
- Flume原理分析与使用案例
1.flume的特点: flume是一个分布式.可靠.和高可用的海量日志采集.聚合和传输的系统.支持在日志系统中定制各类数据发送方,用于收集数据:同时,Flume提供对数据进行简单处理,并写到各种数据 ...
- 自学电脑游戏第四天(Swing)
继续之前的 3.组合框(JComboBox) 例题:利用JComboBox设计一个选择城市的程序. import java.awt.*; import javax.swing.*; public cl ...