转:Android 中Makefile的详细分析

article/2025/9/21 18:26:35

http://blog.chinaunix.net/uid-25838286-id-3204120.html


随着移动互联网的发展,移动开发也越来越吃香了,目前最火的莫过于android,android是什么就不用说了,android自从开源以来,就受到很多人的追捧。当然,一部人追捧它是因为它是Google开发的。对一个程序员来说,一个系统值不值得追捧得要拿代码来说话。我这里并不打算分析android的代码,而是android的makefile,也许大家已经知道了在android源码里,我们可以看见很多makefile文件,起初我也不明白,经过一段时间的研究,后来慢慢明白了,我想通过分析andorid的makefile来告诉大家如何写makefile。


对于一个程序新手而言,好的IDE是他们追捧的对象。但当他接触的代码多了之后,就会逐渐发现IDE不够用了,因为有好多东西用IDE是不好做的,例如自动编译,测试,版本控制,编译定制等。这跟政治课上的一句话有点像:资本主义开始的时候是促进生产力发展的,但到了后来又成了阻碍生产力发展的因素了。如果一个程序不能摆脱IDE的限制(不是不用,而是要有选择的用),那么他就很难提高。


要知道,IDE和makefile代表了两种不同的思想:

IDE根据强调的是简化计算机用户的交互;而makefile体现的是自动化。
对于一个一开始就接触linux的人来说,makefile可能是比较容易学的(熟能生巧),对于一个一开始就接触Windows的人来说,makefile就不太好学,这主要是应该很多时候会不自觉地去用Visual Studio(Visual Studio是个好东西,特别是它的调试)。不知道大叫有没有这个的感觉:一个人如果先接触c,再接触java会比较容易点;如果一个人先接触java,再接触c,就会比较反感c。


这个先引用一下百度百科对makefile的一些描述:
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。


makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。 
Make工具最主要也是最基本的功能就是通过makefile文件来描述源程序之间的相互关系并自动维护编译工作。而makefile文件需要按照某种语法进行编写,文件中需要说明如何编译各个源文件并连接生成可执行文件,并要求定义源文件之间的依赖关系。makefile文件是许多编译器--包括 Windows NT 下的编译器--维护编译信息的常用方法,只是在集成开发环境中,用户通过友好的界面修改makefile 文件而已。
对于android而言,android使用的是GNU的make,因此它的makefile格式也是GNU的makefile格式。现在网络上关于makefile最好的文档就是陈皓的《跟我一起写makefile》,这份文档对makefile进行了详细的介绍,因此推荐大家先看这份文档

(电子版可以到http://download.csdn.net/detail/andy_android/3783424下载)。


首先我们来看看android里makefile的写法


(1)Android.mk文件首先需要指定LOCAL_PATH变量,用于查找源文件。由于一般情况下
Android.mk和需要编译的源文件在同一目录下,所以定义成如下形式:
LOCAL_PATH:=$(call my-dir)
上面的语句的意思是将LOCAL_PATH变量定义成本文件所在目录路径。

(2)Android.mk中可以定义多个编译模块,每个编译模块都是以include $(CLEAR_VARS)开始,以include $(BUILD_XXX)结束。
include $(CLEAR_VARS)
CLEAR_VARS由编译系统提供,指定让GNU MAKEFILE为你清除除LOCAL_PATH以外的所有LOCAL_XXX变量,
如LOCAL_MODULE,LOCAL_SRC_FILES,LOCAL_SHARED_LIBRARIES,LOCAL_STATIC_LIBRARIES等。
include $(BUILD_STATIC_LIBRARY)表示编译成静态库
include $(BUILD_SHARED_LIBRARY)表示编译成动态库。
include $(BUILD_EXECUTABLE)表示编译成可执行程序

(3)举例如下(frameworks/base/libs/audioflinger/Android.mk):
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)  模块一
ifeq ($(AUDIO_POLICY_TEST),true)
  ENABLE_AUDIO_DUMP := true
endif
LOCAL_SRC_FILES:= \
    AudioHardwareGeneric.cpp \
    AudioHardwareStub.cpp \
    AudioHardwareInterface.cpp
ifeq ($(ENABLE_AUDIO_DUMP),true)
  LOCAL_SRC_FILES += AudioDumpInterface.cpp
  LOCAL_CFLAGS += -DENABLE_AUDIO_DUMP
endif
LOCAL_SHARED_LIBRARIES := \
    libcutils \
    libutils \
    libbinder \
    libmedia \
    libhardware_legacy
ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)
  LOCAL_CFLAGS += -DGENERIC_AUDIO
endif
LOCAL_MODULE:= libaudiointerface
ifeq ($(BOARD_HAVE_BLUETOOTH),true)
  LOCAL_SRC_FILES += A2dpAudioInterface.cpp
  LOCAL_SHARED_LIBRARIES += liba2dp
  LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP
  LOCAL_C_INCLUDES += $(call include-path-for, bluez)
endif
include $(BUILD_STATIC_LIBRARY)  模块一编译成静态库
include $(CLEAR_VARS)  模块二
LOCAL_SRC_FILES:=               \
    AudioPolicyManagerBase.cpp
LOCAL_SHARED_LIBRARIES := \
    libcutils \
    libutils \
    libmedia
ifeq ($(TARGET_SIMULATOR),true)
 LOCAL_LDLIBS += -ldl
else
 LOCAL_SHARED_LIBRARIES += libdl
endif
LOCAL_MODULE:= libaudiopolicybase
ifeq ($(BOARD_HAVE_BLUETOOTH),true)
  LOCAL_CFLAGS += -DWITH_A2DP
endif
ifeq ($(AUDIO_POLICY_TEST),true)
  LOCAL_CFLAGS += -DAUDIO_POLICY_TEST
endif
include $(BUILD_STATIC_LIBRARY) 模块二编译成静态库
include $(CLEAR_VARS) 模块三
LOCAL_SRC_FILES:=               \
    AudioFlinger.cpp            \
    AudioMixer.cpp.arm          \
    AudioResampler.cpp.arm      \
    AudioResamplerSinc.cpp.arm  \
    AudioResamplerCubic.cpp.arm \
    AudioPolicyService.cpp
LOCAL_SHARED_LIBRARIES := \
    libcutils \
    libutils \
    libbinder \
    libmedia \
    libhardware_legacy
ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)
  LOCAL_STATIC_LIBRARIES += libaudiointerface libaudiopolicybase
  LOCAL_CFLAGS += -DGENERIC_AUDIO
else
  LOCAL_SHARED_LIBRARIES += libaudio libaudiopolicy
endif
ifeq ($(TARGET_SIMULATOR),true)
 LOCAL_LDLIBS += -ldl
else
 LOCAL_SHARED_LIBRARIES += libdl
endif
LOCAL_MODULE:= libaudioflinger
ifeq ($(BOARD_HAVE_BLUETOOTH),true)
  LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP
  LOCAL_SHARED_LIBRARIES += liba2dp
endif
ifeq ($(AUDIO_POLICY_TEST),true)
  LOCAL_CFLAGS += -DAUDIO_POLICY_TEST
endif
ifeq ($(TARGET_SIMULATOR),true)
    ifeq ($(HOST_OS),linux)
        LOCAL_LDLIBS += -lrt -lpthread
    endif
endif
ifeq ($(BOARD_USE_LVMX),true)
    LOCAL_CFLAGS += -DLVMX
    LOCAL_C_INCLUDES += vendor/nxp
    LOCAL_STATIC_LIBRARIES += liblifevibes
    LOCAL_SHARED_LIBRARIES += liblvmxservice
#    LOCAL_SHARED_LIBRARIES += liblvmxipc
endif
include $(BUILD_SHARED_LIBRARY) 模块三编译成动态库


(4)编译一个应用程序(APK)
  LOCAL_PATH := $(call my-dir)
  include $(CLEAR_VARS)
   
  # Build all java files in the java subdirectory-->直译(建立在java子目录中的所有Java文件
  LOCAL_SRC_FILES := $(call all-subdir-java-files)
   
  # Name of the APK to build-->直译(创建APK的名称
  LOCAL_PACKAGE_NAME := LocalPackage
   
  # Tell it to build an APK-->直译(告诉它来建立一个APK
  include $(BUILD_PACKAGE)

(5)编译一个依赖于静态Java库(static.jar)的应用程序
  LOCAL_PATH := $(call my-dir)
  include $(CLEAR_VARS)
   
  # List of static libraries to include in the package
  LOCAL_STATIC_JAVA_LIBRARIES := static-library
   
  # Build all java files in the java subdirectory
  LOCAL_SRC_FILES := $(call all-subdir-java-files)
   
  # Name of the APK to build
  LOCAL_PACKAGE_NAME := LocalPackage
   
  # Tell it to build an APK
  include $(BUILD_PACKAGE)

(6)编译一个需要用平台的key签名的应用程序
  LOCAL_PATH := $(call my-dir)
  include $(CLEAR_VARS)
   
  # Build all java files in the java subdirectory
  LOCAL_SRC_FILES := $(call all-subdir-java-files)
   
  # Name of the APK to build
  LOCAL_PACKAGE_NAME := LocalPackage
   
  LOCAL_CERTIFICATE := platform
   
  # Tell it to build an APK
  include $(BUILD_PACKAGE)


(7)编译一个需要用特定key前面的应用程序
  LOCAL_PATH := $(call my-dir)
  include $(CLEAR_VARS)
   
  # Build all java files in the java subdirectory
  LOCAL_SRC_FILES := $(call all-subdir-java-files)
   
  # Name of the APK to build
  LOCAL_PACKAGE_NAME := LocalPackage
   
  LOCAL_CERTIFICATE := vendor/example/certs/app
   
  # Tell it to build an APK
  include $(BUILD_PACKAGE)

(8)添加一个预编译应用程序
  LOCAL_PATH := $(call my-dir)
  include $(CLEAR_VARS)
   
  # Module name should match apk name to be installed.
  LOCAL_MODULE := LocalModuleName
  LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
  LOCAL_MODULE_CLASS := APPS
  LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
   
  include $(BUILD_PREBUILT)

(9)添加一个静态JAVA库
  LOCAL_PATH := $(call my-dir)
  include $(CLEAR_VARS)
   
  # Build all java files in the java subdirectory
  LOCAL_SRC_FILES := $(call all-subdir-java-files)
   
  # Any libraries that this library depends on
  LOCAL_JAVA_LIBRARIES := android.test.runner
   
  # The name of the jar file to create
  LOCAL_MODULE := sample
   
  # Build a static jar file.
  include $(BUILD_STATIC_JAVA_LIBRARY)

(10)Android.mk的编译模块中间可以定义相关的编译内容,也就是指定相关的变量如下:
LOCAL_AAPT_FLAGS

LOCAL_ACP_UNAVAILABLE 

LOCAL_ADDITIONAL_JAVA_DIR 
 
LOCAL_AIDL_INCLUDES 

LOCAL_ALLOW_UNDEFINED_SYMBOLS 

LOCAL_ARM_MODE 

LOCAL_ASFLAGS 

LOCAL_ASSET_DIR 

LOCAL_ASSET_FILES 在Android.mk文件中编译应用程序(BUILD_PACKAGE)时设置此变量,表示资源文件,
                  通常会定义成LOCAL_ASSET_FILES += $(call find-subdir-assets)
 
LOCAL_BUILT_MODULE_STEM  
LOCAL_C_INCLUDES 额外的C/C++编译头文件路径,用LOCAL_PATH表示本文件所在目录
                 举例如下:
                 LOCAL_C_INCLUDES += extlibs/zlib-1.2.3
                 LOCAL_C_INCLUDES += $(LOCAL_PATH)/src 
 
LOCAL_CC 指定C编译器

LOCAL_CERTIFICATE  签名认证

LOCAL_CFLAGS 为C/C++编译器定义额外的标志(如宏定义),举例:LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1
 
LOCAL_CLASSPATH 

LOCAL_COMPRESS_MODULE_SYMBOLS 

LOCAL_COPY_HEADERS install应用程序时需要复制的头文件,必须同时定义LOCAL_COPY_HEADERS_TO
 
LOCAL_COPY_HEADERS_TO install应用程序时复制头文件的目的路径

LOCAL_CPP_EXTENSION 如果你的C++文件不是以cpp为文件后缀,你可以通过LOCAL_CPP_EXTENSION指定C++文件后缀名 
                    如:LOCAL_CPP_EXTENSION := .cc
                    注意统一模块中C++文件后缀必须保持一致。

LOCAL_CPPFLAGS 传递额外的标志给C++编译器,如:LOCAL_CPPFLAGS += -ffriend-injection

LOCAL_CXX 指定C++编译器
 
LOCAL_DX_FLAGS

LOCAL_EXPORT_PACKAGE_RESOURCES

LOCAL_FORCE_STATIC_EXECUTABLE 如果编译的可执行程序要进行静态链接(执行时不依赖于任何动态库),则设置LOCAL_FORCE_STATIC_EXECUTABLE:=true 
                              目前只有libc有静态库形式,这个只有文件系统中/sbin目录下的应用程序会用到,这个目录下的应用程序在运行时通常
                              文件系统的其它部分还没有加载,所以必须进行静态链接。
 
LOCAL_GENERATED_SOURCES
 
LOCAL_INSTRUMENTATION_FOR

LOCAL_INSTRUMENTATION_FOR_PACKAGE_NAME

LOCAL_INTERMEDIATE_SOURCES

LOCAL_INTERMEDIATE_TARGETS

LOCAL_IS_HOST_MODULE

LOCAL_JAR_MANIFEST

LOCAL_JARJAR_RULES

LOCAL_JAVA_LIBRARIES 编译java应用程序和库的时候指定包含的java类库,目前有core和framework两种
                     多数情况下定义成:LOCAL_JAVA_LIBRARIES := core framework
                     注意LOCAL_JAVA_LIBRARIES不是必须的,而且编译APK时不允许定义(系统会自动添加)
 
LOCAL_JAVA_RESOURCE_DIRS 

LOCAL_JAVA_RESOURCE_FILES 

LOCAL_JNI_SHARED_LIBRARIES 

LOCAL_LDFLAGS 传递额外的参数给连接器(务必注意参数的顺序)
 
LOCAL_LDLIBS 为可执行程序或者库的编译指定额外的库,指定库以"-lxxx"格式,举例:
             LOCAL_LDLIBS += -lcurses -lpthread
             LOCAL_LDLIBS += -Wl,-z,origin 
 
LOCAL_MODULE 生成的模块的名称(注意应用程序名称用LOCAL_PACKAGE_NAME而不是LOCAL_MODULE)

LOCAL_MODULE_PATH 生成模块的路径
 
LOCAL_MODULE_STEM 
 
LOCAL_MODULE_TAGS 生成模块的标记 
 
LOCAL_NO_DEFAULT_COMPILER_FLAGS 

LOCAL_NO_EMMA_COMPILE 

LOCAL_NO_EMMA_INSTRUMENT 

LOCAL_NO_STANDARD_LIBRARIES 

LOCAL_OVERRIDES_PACKAGES 

LOCAL_PACKAGE_NAME APK应用程序的名称 

LOCAL_POST_PROCESS_COMMAND
 
LOCAL_PREBUILT_EXECUTABLES 预编译including $(BUILD_PREBUILT)或者$(BUILD_HOST_PREBUILT)时所用,指定需要复制的可执行文件

LOCAL_PREBUILT_JAVA_LIBRARIES 

LOCAL_PREBUILT_LIBS 预编译including $(BUILD_PREBUILT)或者$(BUILD_HOST_PREBUILT)时所用, 指定需要复制的库.

LOCAL_PREBUILT_OBJ_FILES 

LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES  
 
LOCAL_PRELINK_MODULE 是否需要预连接处理(默认需要,用来做动态库优化)

LOCAL_REQUIRED_MODULES 指定模块运行所依赖的模块(模块安装时将会同步安装它所依赖的模块)
 
LOCAL_RESOURCE_DIR

LOCAL_SDK_VERSION

LOCAL_SHARED_LIBRARIES 可链接动态库
 
LOCAL_SRC_FILES 编译源文件


LOCAL_STATIC_JAVA_LIBRARIES 

LOCAL_STATIC_LIBRARIES 可链接静态库 
 
LOCAL_UNINSTALLABLE_MODULE 

LOCAL_UNSTRIPPED_PATH
 
LOCAL_WHOLE_STATIC_LIBRARIES 指定模块所需要载入的完整静态库(这些精通库在链接是不允许链接器删除其中无用的代码)
 
LOCAL_YACCFLAGS
 
OVERRIDE_BUILT_MODULE_PATH


接下来我们详细看一下android里的makefile文件


android最顶层的目录结构如下:
.   
|-- Makefile        (全局的Makefile)    
|-- bionic          (Bionic含义为仿生,这里面是一些基础的库的源代码)    
|-- bootloader      (引导加载器)    
|-- build           (build目录中的内容不是目标所用的代码,而是编译和配置所需要的脚本和工具)    
|-- dalvik          (JAVA 虚拟机 )    
|-- development     (程序开发所需要的模板和工具)    
|-- external        (目标机器使用的一些库)    
|-- frameworks      ( 应用程序 的框架层)    
|-- hardware        (与硬件相关的库)    
|-- kernel          (Linux2.6的源代码)    
|-- packages        (Android的各种 应用 程序)    
|-- prebuilt        (Android在各种平台下编译的预置脚本)    
|-- recovery        (与目标的恢复功能相关)    
`-- system          (Android的底层的一些库)
本文将要分析的是build目录下的makefile和 shell 文件,android的代码是1.5的版本。
主要的目录结构如下:
1.makefile入门
    1.1 makefile helloworld
    1.2 用makefile构建交叉编译环境
    1.3 makefile里面的一些技巧
2.android makefile分析
    2.1 android shell分析
    2.2 android build下的各个makefile分析
3. android其他目录的android.mk分析

大家先通过网络的一些文章来了解一下andoroid的makefile。
1.
Android build system
2.
Android Building System 分析
3.
Android Build System(介绍使用)
1.1 makefile helloworld
  
Makefile 的规则如下:
  
target ... : prerequisites ... 
  
command ... ...
  
target可以是一个目标文件,也可以是Object File(例如helloworld.obj),也可以是执行文件和标签。
  
prerequisites就是生成target所需要的文件或是目标。
  
command
也就是要达到target这个目标所需要执行的命令。这里没有说“使用生成target所需要执行的命令”,是因为target可能是标签。需要注意的是
command前面必须是TAB键,而不是空格,因此喜欢在编辑器里面将TAB键用空格替换的人需要特别小心了。
  
我们写程序一般喜欢写helloworld,当我们写了一个c的helloworld之后,我们该如何写helloworld来编译helloworld.c呢?
  
下面就是编译helloworld的makefile。
                       
helloworld : helloworld.o
          
    cc -o helloworld helloworld .o
          
helloworld.o : helloworld.c 
          
    cc -c main.c
          
clean:
          
    rm helloworld helloworl.o
                 
之后我们执行make就可以编译helloworld.c了,执行make clean就可以清除编译结果了(其实就是删除helloworld helloworl.o)。
  
可能有人问为什么执行make就会生成helloworld呢?这得从make的默认处理说起:make将makefile的第一个target作为作为最终的  
target,凡是这个规则依赖的规则都将被执行,否则就不会执行。所以在执行make的时候,clean这个规则就没有被执行。
  
面的是最简单的makefile,复杂点makefile就开始使用高级点的技巧了,例如使用变量,使用隐式规则,执行负责点shell命令(常见的是字 符串处理和文件处理等),这里不打算介绍这些规则,后面在分析android的makefile时会结合具体代码进行具体分析,大家可以先看看陈皓的《跟 我一起写makefile》来了解了解。
  
makefile的大体的结构是程序树形的,如下:
  
                                                     


  
这样写起makefile也简单,我们将要达到的目标作为第一个规则,然后将目标分解成子目标,然后一个个写规则,依次类推,直到最下面的规则很容易实现为止。这其实和算法里面的分治法很像,将一个复杂的问题分而治之。
  
到树,我想到了编译原理里面的语法分析,语法分析里面有自顶而下的分析方法和自底而下的分析方法。当然makefile并不是要做语法分析,而是要做与语 法分析分析相反的事。(语法分析要做的是一个句子是不是根据语法可以推出来,而makefile要做的是根据规则生成一个command 执行队列。)不过makefile的规则和词法分析还是很像的。下面出一道编译原理上面的一个例子,大家可以理解一下makefile和词法分析的不同点 和相同点:
  
  ->     
      -> |||ε     
    ->      
    -> |ε     
    -> +     
    -> -     
   -> >     
    -> >=
  

  
最后,介绍一下autoconf,automake,使用这两个工具可以自动生成makefile。
  

  
上面的图可以看出,通过autoscan,我们可以根据代码生成一个叫做configure.scan的文件,然后我们编辑这个文件,参数一个
configure.in的文件。接着我们写一个makefile.am的文件,然后就可以用automake生成makefile.in,最后,根据 makefile.in和configure就可以生成makefile了。在很多开源的工程里面,我们都可以看到 makefile.am,configure.in,makefine.in,configure文件,还有可能看到一个十分复杂的makefile文 件,许多人学习makefile的时候想通过看这个文件来学习,最终却发现太复杂了。如果我们知道这个文件是自动生成的,就理解这个makefile文件 为什么这个复杂了。
  
欲更加详细的理解automake等工具,可以参考 http://www.ibm.com/developerworks/cn/linux/l-makefile/


1.2 用makefile构建交叉编译环境
  
这节的内容请参考http://blog.csdn.net/absurd/category/228434.aspx里面的交叉编译场景分析,我只是说一下我做的步骤:
  
1.下载交叉编译环境(http://www.codesourcery.com/downloads/public/gnu_toolchain/arm-none-linux-gnueabi)并安装,一般解压就可以了,然后将里面的bin目录加到环境变量的PATH里面,我的做法是在~/.bashrc最下面加一行:export PATH=$PATH:~/arm-2009q1/bin。
  
2.在用户的home目录(cd ~)建一个目录cross-compile
  
3.在cross-compile创建一个文件cross.env,内容如下:
  
export WORK_DIR=~/cross-compile   
export ROOTFS_DIR=$WORK_DIR/rootfs    
export ARCH=arm    
export PKG_CONFIG_PATH=$ROOTFS_DIR/usr/local/lib/pkgconfig:$ROOTFS_DIR/usr/lib/pkgconfig:$ROOTFS_DIR/usr/X11R6/lib/pkgconfig    
if [ ! -e "$ROOTFS_DIR/usr/local/include" ]; then mkdir -p $ROOTFS_DIR/usr/local/include;fi;    
if [ ! -e "$ROOTFS_DIR/usr/local/lib" ]; then mkdir -p $ROOTFS_DIR/usr/local/lib; fi;    
if [ ! -e "$ROOTFS_DIR/usr/local/etc" ]; then mkdir -p $ROOTFS_DIR/usr/local/etc; fi;    
if [ ! -e "$ROOTFS_DIR/usr/local/bin" ]; then mkdir -p $ROOTFS_DIR/usr/local/bin; fi;    
if [ ! -e "$ROOTFS_DIR/usr/local/share" ]; then mkdir -p $ROOTFS_DIR/usr/local/share; fi;    
if [ ! -e "$ROOTFS_DIR/usr/local/man" ]; then mkdir -p $ROOTFS_DIR/usr/local/man; fi;    
if [ ! -e "$ROOTFS_DIR/usr/include" ]; then mkdir -p $ROOTFS_DIR/usr/include; fi;    
if [ ! -e "$ROOTFS_DIR/usr/lib" ]; then mkdir -p $ROOTFS_DIR/usr/lib; fi;    
if [ ! -e "$ROOTFS_DIR/usr/etc" ]; then mkdir -p $ROOTFS_DIR/usr/etc; fi;    
if [ ! -e "$ROOTFS_DIR/usr/bin" ]; then mkdir -p $ROOTFS_DIR/usr/bin; fi;    
if [ ! -e "$ROOTFS_DIR/usr/share" ]; then mkdir -p $ROOTFS_DIR/usr/share; fi;    
if [ ! -e "$ROOTFS_DIR/usr/man" ]; then mkdir -p $ROOTFS_DIR/usr/man; fi;
  
4.开启命令行,进入cross-compile目录下,执行. cross.env
  
5.将编译linux时生产的头文件,so等拷贝到cross-compile目录下rootfs/usr对应的目录(头文件一般可以拷pc的,so一定要拷arm版的)。
  
5.下载要编译的源代码,并放在cross-compile目录下
  
6.按照里面的方法写makefile文件,放在cross-compile目录下


http://chatgpt.dhexx.cn/article/wuriDZtr.shtml

相关文章

Python数据分析理论与实战完整版本

Python数据分析基础 一、Python数据分析初探二、数据获取2.1 数据获取的手段2.2 数据仓库2.3 检测与抓取2.4 填写、埋点、日志2.5 计算2.6 数据学习网站 三、单因子探索分析与可视化3.1 理论铺垫3.2 数据分类3.3 单属性分析3.4 单因子分析实战3.5 可视化小节 四、多因子探索分析…

223.主成分分析PCA

主成分分析 PCA 本节作者:刘华,中国科学技术大学 版本1.0.3,更新日期:2020年6月18日 什么是PCA(Principal Component Analysis) 相关背景 在许多领域的研究与应用中,通常需要对含有多个变量的数据进行观测,…

探索性数据分析EDA(二)—— 缺失值处理

接上一篇 《探索性数据分析(1)—— 变量识别和分析》, 这篇笔记主要内容为缺失值处理方法介绍,以及相关python工具包sklearn.impute的使用介绍。 目录 1. 为什么需要处理缺失值2. 为什么数据有缺失值a) 完全随机缺失(…

数据分析汇总

一、本文说明: 本文为自己学习的笔记,用来记录数分的相关知识,方便记录查阅。 二、指标体系建设与数据分析: 1、指标体系概念: ①:什么是指标体系: 企业指标的集合 ②:好…

5whys分析法在美团工程师中的实践

2019独角兽企业重金招聘Python工程师标准>>> 前言 网站的质量和稳定性对于用户和公司来说至关重要,但是在网站的快速发展过程中,由于各种原因导致事故不可避免的发生,这些大大小小的事故对公司难免会造成一些负面的影响&#xff0…

单因素方差分析的计算过程详解

统计分析之单因素方差分析计算过程详解 Excel方差分析 用Excel计算方差分析,三种方法: 一步步手推法 用Excel的数据分析→单因素方差分析自动生成 在1的基础上通过SUMX2MY2优化法 Excel版操作步骤可参见 Excel单因素方差分析操作详解 P…

哈佛大学——差异表达分析(九)DESeq2步骤描述

文章目录 学习目标DESeq2差异基因表达分析流程第一步:估计大小因子第二步:估计基因离散(gene-wise dispersion)第三步:拟合曲线到基因的分散估计第四步:将基因离散估计值向曲线预测值收缩MOV10 DE分析:探讨离散估计和评…

数学建模之层次分析法(AHP)

层次分析法(Analytic Hierarchy Process) AHP是对一些较为复杂的,较为模糊的问题作出决策的简易方法,它特别适用于那些难以完全定量分析的问题。由美国运筹学家T.L.Saaty教授于上世纪70年代初期提出。 目录 层次分析法&#xff0…

时序分析-季节因素

目录 1时序分析的基础 1.1 简介 1.2 分类 2 分析套路 3 主流时序分析模型 3.1移动平均 3.2 指数平滑法 3.3 组合模型 3.4 ARIMA 4 研究细分领域 4.1 异常值检测 4.2 季节序列分析 4.1 同期平均法 4.1.1 简单季节指数法 4.1.2 趋势季节指数法 4.2 长期趋势剔除法…

html5播放器的示例代码

本次的分享是一个基于HTML5标签实现的一个自定义视频播放器。其中实现了播放暂停、进度拖拽、音量控制及全屏等功能。 效果预览 核心思路 我相信一定会有些没有接触过制作自定义播放器的童鞋对于 标签的认识会停留在此。 <video controls"controls" autoplay"…

HTML5音乐播放器

明月浩空-HTML5浮窗音乐播放器研发于2014年&#xff0c;并持续更新至今 是基于QQ音乐、酷狗音乐、网易云音乐等歌曲ID全自动解析的网页音乐播放器 依靠服务器强大的接口功能&#xff0c;只需要一个ID既可获取全部信息 同时播放器主体会跟随专辑图片主色值自动变色&#xff0c;歌…

h5的开源播放器组件

哈喽&#xff0c;大家好&#xff0c;今天我要给大家推荐一个非常棒的看片神器&#xff0c;那就是【moovie】.它是一款专注于电影的HTML5 播放器。 先展示一下效果&#xff0c;测试了一下&#xff0c;支持倍速播放、快捷键操作、字幕偏移即时调整&#xff0c;还有一些参数展示&a…

H5播放器使用方法。

1.使用webkit-playsinline playsinline 在iOS微信webview中视频不会弹出来&#xff0c;直接播放。 <video id"test_video" class"test_video" webkit-playsinline playsinlinesrc"http://res.imtt.qq.com/qqbrowser/js/advideo.mp4"control…

H5,Audio音乐播放器(移动版)

有些时候&#xff0c;总是感觉自己进步的没有以前快了。于是就怀疑自己是不是也被时间磨灭了&#xff0c;这可真是一件不幸的事儿。可能是自己会的东西太少了&#xff0c;总是有种莫名的危机感。 前一段时间&#xff0c;想写一个移动版音乐播放器&#xff0c;于是就开始利用下班…

H5 video 播放器demo

H5 video 播放器demo 前言 最近在做一个wap端的项目&#xff0c;需要视频播放功能。大家也知道wap对flash支持很差&#xff0c;所以优先考虑使用h5播放器video,在这里我介绍用video实现视频播放方法。之后在介绍几个插件和第三方视频实现方法。 H5 video 因为video样式是原…

SkeyeWebPlayer.js H5播放器开发之播放器video动态创建(三)

SkeyeWebPlayer.js H5播放器是由成都视开信息科技开发和维护的一个完善的RTSP、FLV、HLS等多种流媒体协议播放&#xff0c;视频编码支持H.264&#xff0c;H.265&#xff0c;音频支持AAC&#xff0c;支持TCP/UDP协议&#xff0c;是一套极佳的且适合用于综合安防视频云服务播放组…

H5音乐播放器(包含源码与示例)

H5音乐播放器&#xff08;包含源码与示例&#xff09; 基于Angularionic的H5音乐播放器&#xff0c;源码&#xff1a;https://gitee.com/CrimsonHu/h5-music-player 示例地址 建议使用原版chrome或edge访问&#xff1a;http://intelyes.club:5300/ 功能 实时歌词显示支持歌…

基于H5+js开发一款音乐播放器

前言&#xff1a;当下音乐播放器不胜其数&#xff0c;为了更好的掌握一些东西&#xff0c;我们来自己制作一个音乐播放器。 文章目录&#xff1a; 一.开发环境&#xff1a;二.页面视图&#xff1a;1.主文件入口&#xff08;首页&#xff09;&#xff1a;2.音乐播放界面&#…

H5纯原生播放器 【学习video】

这是一个纯原生的H5播放器&#xff0c;尽管网上有很多第三方库&#xff0c;但是基础打的牢固&#xff0c;一定会帮你走的更远。 大厂也非常重视基础&#xff0c;再说了那些第三方库也是基础一点点搭起来的&#xff0c;所以有兴趣学习的同学可以下载来学习。 代码中的细节我都…

MuiPlayer - 一款优秀的 H5 视频播放器框架

Mui Player Gitee | Docs | 中文文档 介绍 MuiPlayer 是一款 HTML5 视频播放插件&#xff0c;其默认配置了精美可操作的的播放控件&#xff0c;涉及了常用的播放场景&#xff0c;例如全屏播放、播放快进、循环播放、音量调节、视频解码等功能。 支持 mp4、m3u8、flv 等多…