记录动态库so 和静态库lib编译,Makefile, Android.mk技巧。

1. gcc 命令编译

1.1 编译静态库

(1)用源文件创建目标文件

   gcc -I/**** -c encypt.c -o encypt.o 
   gcc -c checksum.c -o checksum.o 

(2)用创建的.o目标文件,创建.a静态库

    ar -rcs libhfsecurity.a encypt.o checksum.o 

(3)使用.a静态库,编译最终生成件

   gcc bank_vault.c -I . -L . -lhfsecurity -o bank_vault 
rcs:r表示如果.a文件存在就更新它 
     c表示创建存档时不显示反馈信息 
     s告诉ar要在.a文件开头创建索引 
     -I告诉编译器头文件存放位置 
     -L告诉编译器库存放路径 

1.2 编译动态so库

gcc -shared hfcal.o -o c:\libs\hfcal.dll   #windows上的MinGW 
gcc -shared hfcal.o -o /libs/libhfcal.dll.a   #windows上的cygwin 
gcc -shared hfcal.o -o /libs/libhfcal.so #linux或者unix 
gcc -shared hfcal.o -o /libs/libfcal.dylib #mac 
gcc -I/include -c elliptical.c -o elliptical.o 
gcc elliptical.o -L/libs -lhfcal  -o elliptical 

1.3 编写Makefile

1.3.1 Makefile生成执行文件

target… : prerequisites … command

target也就是一个目标文件,可以是Object File,也可以是执行文件。还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。

prerequisites就是,要生成那个target所需要的文件或是目标。

command也就是make需要执行的命令。(任意的Shell命令)

  1 test_main: test.o test1.o test2.o
  2     cc -o test_main test.o test1.o test2.o
  3
  4 test.o:test.c
  5     cc -c test.c
  6 test1.o:test1.c
  7     cc -c test1.c
  8 test2.o:test2.c
  9     cc -c test2.c
 10
 11 clean :
 12     rm test_main test1.o test2.o

上述为最原始简单的makefile文件写法,test_main为目标文件,冒号后面的为生成test_main所需要的文件。

cc才是真正执行的命令。

在Makefile中还可以定义变量引用。

参考文献:其他高级技巧参见已有makefile以及如下网页 http://blog.csdn.net/ruglcc/article/details/7814546/

1.3.2 Makefile生成静态库
 #!/bin/bash
#设置编译工具
CC = 
LD = 
AR = 
#头文件路径
DIR_INC = ./
#源码路径
DIR_SRC = ./
#生成目标文件路径
DIR_OBJ = ./
#生成二进制文件路径
DIR_BIN = ./
#生成库文件名称
LIB_OBJECT = $(DIR_BIN)test.a
#源文件路径,wildcard扩展通配符,把DIR_SRC目录下的所有后缀都是.c的文件都展开。
SRC = $(wildcard ${DIR_SRC}/*.c)
#patsubst把$(SRC)中的变量符合后缀是.c的全部替换成.o
OBJ = $(patsubst %.c, %.o, $(SRC))
#配置编译选项
FLAG := -02 -mfloat-abi=softfp -mfpu=neon -fno-exceptions -I${DIR_INC} -std=c11
#生成的库文件需要依赖的文件$(OBJ)
#调用AR工具打包
#$@--目标文件,$^--所有的依赖文件,$<--第一个依赖文件
#--strip-debug 去除调试信息
$(LIB_OBJECT):$(OBJ)
    $(AR) -rcs -o $@ $^
    arm-none-eabi-strip --strip-debug $@
#表示所有的目标文件及其依赖文件
%.o:%.c
    $(CC) $(FLAG) -c $< -o $@
#make clean需要删除的文件
clean:
    rm -f ./*o ./*.a

2. Android 编译

NDK单独编译或者放到Android源码中编译。

2.1 静态库

2.1.1 NDK-build编译库文件,NDK编译需要使用到两个mk文件.

Android.mk

LOCAL_PATH :=$(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := lib***
LOCAL_SRC_FILES := ***.c
include $(BUILD_STATIC_LIBRARY)

Application.mk

#同时支持两种指令集
APP_ABI := arm64-v8a armeabi-v7a
#支持平台
APP_PLATFORM :=android-21
#优化选项APP_OPTIM
此变量是可选的,其值可以为'release'或'debug'.此变量用来修改优先等级.默认情况下为release.在release模式下,将编译生成被优化了的二进制的机器码,而debug模块用来生成便于调试的未被优化的二进制机器码。
APP_OPTIM :=release
#标准库
APP_STL:= gnustl_static
#编译选项
APP_CFLAGS += -Wno-error=format-security

在本地新建jni目录,配置好连个mk文件,在目录下,运行NDK-build即可生成对应的静态文件。

2.1.2 NDK将第三方静态库ndk编译为动态库
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := name
LOCAL_SRC_FILES := lib***.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := test
LOCAL_STATIC_LIBRARIES := ***
LOCAL_SRC_FILES := *.c
include $(BUILD_SHARED_LIBRARY)

2.2 Android源码中编译动态库及可执行程序

Android.mk与NDK下写法大致一样。 在编译之前需要配置好运行环境

source build/envsetup.sh 
Lunch 选择angler相关选项(如果需要编译其他内核,选择对应即可)
make bootimage -j4