编译可执行so库和可执行程序

# 编译so库/可执行程序

前面我们了解Android.mk的文件结构,我们也尝试编译了jar包,app,接下来我们看看C++程序的编译和库的打包

Android.mk (opens new window)

前面我们完成了java的编译,编译成jar包,编译成apk。

接下来我们看看C/C++的编译,编译成静态库/动态库,编译成可执行文件。

静态库和动态库(共享库)的说明在前面已经和大家讲了。

# 编译so库

先给大家表演编译so库,后面的编译可执行程序时,我们可以依赖so库,这样子比较全。

所以就先学习一下如何编译库吧。

库也一样,我们分动态库和静态库。

先写个库吧,我写个简单的,比如说log输出。

头文件:log.h

#define TAG "SOB-LOG"
#include <string>
using namespace std;
namespace sob{
	void log(const string msg);
}
1
2
3
4
5
6

c++文件log.cpp

#include <iostream>
#include <string>
#include "log.h"

using namespace std;
namespace sob {
	void log(const string msg)
	{
		cout << TAG << " : " << msg << endl;
	}
}
1
2
3
4
5
6
7
8
9
10
11

就这么简单,现在,我们把它编译成共享库

编写Android.mk文件

还记得前面我们的Android.mk的结构吗?

于是,我们的脚本这样写了:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

#放到vender目录下
LOCAL_VENDOR_MODULE = true
LOCAL_MODULE_TAGS := optional

LOCAL_MODULE:= libsoblog

LOCAL_C_INCLUDES := external/libcxx/include

LOCAL_SHARED_LIBRARIES := \
	libc++

LOCAL_SRC_FILES:= \
	log.cpp

include $(BUILD_SHARED_LIBRARY)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

编译结果

hdc@ubuntu:~/Android5.1/packages/apps/HardwearTest/loglib$ mm
make: Entering directory '/home/hdc/Android5.1'
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=5.1
TARGET_PRODUCT=aosp_x86
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=x86
TARGET_ARCH_VARIANT=x86
TARGET_CPU_VARIANT=
TARGET_2ND_ARCH=
TARGET_2ND_ARCH_VARIANT=
TARGET_2ND_CPU_VARIANT=
HOST_ARCH=x86_64
HOST_OS=linux
HOST_OS_EXTRA=Linux-5.11.0-40-generic-x86_64-with-Ubuntu-20.04-focal
HOST_BUILD_TYPE=release
BUILD_ID=LMY47D
OUT_DIR=out
============================================
make: Circular out/target/product/generic_x86/obj/SHARED_LIBRARIES/liblog_intermediates/LINKED/liblog.so <- out/target/product/generic_x86/obj/lib/liblog.so dependency dropped.
make: Circular out/target/product/generic_x86/system/lib/liblog.so <- out/target/product/generic_x86/system/lib/liblog.so dependency dropped.
make: Nothing to be done for 'all_modules'.
make: Leaving directory '/home/hdc/Android5.1'

#### make completed successfully (1 seconds) ####

hdc@ubuntu:~/Android5.1/packages/apps/HardwearTest/loglib$
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

也就是在这个out/target/product/generic_x86/system/lib/liblog.so目录下有生成。

接下来我们编译一下可执行文件,然后依赖我们的log库。

# 编译成可执行文件

比如说最近写的一个程序,去查询是否有GSensor的,当然,这个是模拟器,就不是真的能测试,只是模拟给大家看如何编译一个可执行程序。

#include "loglib/log.h"
#include <string>

using namespace std;
using namespace sob;

void printHelp(void)
{
	log("帮助内容:");
	log("checkGyroscope 检查是否支持陀螺仪,1表示支持,-1表示不支持");
	log("getGsensorType 检查是否支持重力传感器,0-不支持,1-QMA7981,2-SC7A21,3-DA217");
	log("使用示例:hardwaretest checkGyroscope");
}

void handleCmd(char* cmd)
{
	//对命令进行判断和执行
	log("参数内容:");
	string cmdStr;
	cmdStr = cmd;

	//log("cmdStr ==> "+ cmdStr);
	if("checkGyroscope"==cmdStr)
	{
		log("测试是否有陀螺仪");
		//TODO:去检查是否有陀螺仪
	}else if("getGsensorType"==cmdStr)
	{
		log("检查重力传感器的类型");
		//TODO:去检查是否有重力传感器
	}else
	{
		printHelp();
	}
}


//argc是参数个数,argv[]是参数内容
int main(int argc, char *argv[]){
	log("do hardware test...");
	int i = 0;
	for(;i<argc;i++)
	{
		if(argc==1)
		{
			//打开帮助
			printHelp();
		}
		if(i>0){
			handleCmd(argv[i]);
		}
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

按前面的套路,我们这样写Android.mk

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

# 编译出来的名称
LOCAL_MODULE := hardweartest

#源代码
LOCAL_SRC_FILES := \
	hardwaretest.cpp

#添加头部依赖
LOCAL_C_INCLUDES := external/libcxx/include

#添加依赖库
LOCAL_SHARED_LIBRARIES := \
	libsoblog \
	libc \
	libc++

include $(BUILD_EXECUTABLE)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

编译结果:

hdc@ubuntu:~/Android5.1/packages/apps/HardwearTest$ mm
make: Entering directory '/home/hdc/Android5.1'
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=5.1
TARGET_PRODUCT=aosp_x86
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=x86
TARGET_ARCH_VARIANT=x86
TARGET_CPU_VARIANT=
TARGET_2ND_ARCH=
TARGET_2ND_ARCH_VARIANT=
TARGET_2ND_CPU_VARIANT=
HOST_ARCH=x86_64
HOST_OS=linux
HOST_OS_EXTRA=Linux-5.11.0-40-generic-x86_64-with-Ubuntu-20.04-focal
HOST_BUILD_TYPE=release
BUILD_ID=LMY47D
OUT_DIR=out
============================================
Import includes file: out/target/product/generic_x86/obj/EXECUTABLES/hardweartest_intermediates/import_includes
target  C++: hardweartest <= packages/apps/HardwearTest/hardwaretest.cpp
target Executable: hardweartest (out/target/product/generic_x86/obj/EXECUTABLES/hardweartest_intermediates/LINKED/hardweartest)
target Symbolic: hardweartest (out/target/product/generic_x86/symbols/system/bin/hardweartest)
Export includes file: packages/apps/HardwearTest/Android.mk -- out/target/product/generic_x86/obj/EXECUTABLES/hardweartest_intermediates/export_includes
target Strip: hardweartest (out/target/product/generic_x86/obj/EXECUTABLES/hardweartest_intermediates/hardweartest)
Install: out/target/product/generic_x86/system/bin/hardweartest
make: Leaving directory '/home/hdc/Android5.1'

#### make completed successfully (1 seconds) ####
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

从输出的Log上看,我们可以知道它在这里:out/target/product/generic_x86/system/bin/hardweartest

编译到system/bin目录下,可是,我们现在的镜像并没有这个程序

所以我们要重新打包镜像

怎么打包叫经?

make snod
1

执行结果

hdc@ubuntu:~/Android5.1$ make snod
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=5.1
TARGET_PRODUCT=aosp_x86
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=x86
TARGET_ARCH_VARIANT=x86
TARGET_CPU_VARIANT=
TARGET_2ND_ARCH=
TARGET_2ND_ARCH_VARIANT=
TARGET_2ND_CPU_VARIANT=
HOST_ARCH=x86_64
HOST_OS=linux
HOST_OS_EXTRA=Linux-5.11.0-40-generic-x86_64-with-Ubuntu-20.04-focal
HOST_BUILD_TYPE=release
BUILD_ID=LMY47D
OUT_DIR=out
============================================
build/core/Makefile:1013: Warning: with dexpreopt enabled, you may need a full rebuild.
make snod: ignoring dependencies
Target system fs image: out/target/product/generic_x86/system.img
Running:  mkuserimg.sh out/target/product/generic_x86/system out/target/product/generic_x86/system.img ext4 system 786432000 out/target/product/generic_x86/root/file_contexts
make_ext4fs -T -1 -S out/target/product/generic_x86/root/file_contexts -l 786432000 -a system out/target/product/generic_x86/system.img out/target/product/generic_x86/system
Creating filesystem with parameters:
    Size: 786432000
    Block size: 4096
    Blocks per group: 32768
    Inodes per group: 8000
    Inode size: 256
    Journal blocks: 3000
    Label: 
    Blocks: 192000
    Block groups: 6
    Reserved block group size: 47
Created filesystem with 1463/48000 inodes and 130394/192000 blocks
out/target/product/generic_x86/system.img maxsize=802897920 blocksize=2112 total=786432000 reserve=8110080

#### make completed successfully (2 seconds) ####

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

运行结果

运行模拟器

emulator
1

把模拟器启动起来以后,我们adb shell 进去android系统里

进入到system/bin目录下,查看是否有我们的程序hardweartest

如果有直接执行即可:

图片描述

到次,就和大家了解完了可执行程序的编译和库的编译了

# 如何添加到系统遍中

以上我们只是手动编译出来的,然后打包镜像。

如果我们直接从无到有,如果告诉系统我们的库是需要编译的呢?

这个请看我们后面的产品创建了

上次更新: 2022/03/28, 23:04:38