1. 程式人生 > >Android studio中NDK開發(一):CMakeLists.txt編寫入門

Android studio中NDK開發(一):CMakeLists.txt編寫入門

自定義變數

主要有隱式定義和顯式定義兩種。 
隱式定義的一個例子是PROJECT指令,它會隱式的定義< projectname >_BINARY_DIR< projectname >_SOURCE_DIR兩個變數;顯式定義使用SET指令構建自定義變數,比如:SET(HELLO_SRCmain.c)就可以通過${HELLO_SRC}來引用這個自定義變量了。

變數引用方式

使用${}進行變數的引用;在IF等語句中,是直接使用變數名而不通過${}取值。

常用變數

CMAKE_BINARY_DIR 
PROJECT_BINARY_DIR

 
< projectname >_BINARY_DIR 
這三個變數指代的內容是一致的,如果是in-source編譯,指得就是工程頂層目錄;如果是out-of-source編譯,指的是工程編譯發生的目錄。PROJECT_BINARY_DIR跟其它指令稍有區別,目前可以認為它們是一致的。

CMAKE_SOURCE_DIR 
PROJECT_SOURCE_DIR 
< projectname >_SOURCE_DIR 
這三個變數指代的內容是一致的,不論採用何種編譯方式,都是工程頂層目錄。也就是在in-source編譯時,他跟CMAKE_BINARY_DIR

等變數一致。PROJECT_SOURCE_DIR跟其它指令稍有區別,目前可以認為它們是一致的。 
(out-of-source build與in-source build相對,指是否在CMakeLists.txt所在目錄進行編譯。)

CMAKE_CURRENT_SOURCE_DIR 
當前處理的CMakeLists.txt所在的路徑,比如上面我們提到的src子目錄。

CMAKE_CURRRENT_BINARY_DIR 
如果是in-source編譯,它跟CMAKE_CURRENT_SOURCE_DIR一致;如果是out-of-source編譯,指的是target編譯目錄。使用ADD_SUBDIRECTORY(src bin)

可以更改這個變數的值。使用SET(EXECUTABLE_OUTPUT_PATH <新路徑>)並不會對這個變數造成影響,它僅僅修改了最終目標檔案存放的路徑。

CMAKE_CURRENT_LIST_FILE 
輸出呼叫這個變數的CMakeLists.txt的完整路徑

CMAKE_CURRENT_LIST_LINE 
輸出這個變數所在的行

CMAKE_MODULE_PATH 
這個變數用來定義自己的cmake模組所在的路徑。如果工程比較複雜,有可能會自己編寫一些cmake模組,這些cmake模組是隨工程釋出的,為了讓cmake在處理CMakeLists.txt時找到這些模組,你需要通過SET指令將cmake模組路徑設定一下。比如SET(CMAKE_MODULE_PATH,${PROJECT_SOURCE_DIR}/cmake) 
這時候就可以通過INCLUDE指令來呼叫自己的模組了。

EXECUTABLE_OUTPUT_PATH 
新定義最終結果的存放目錄

LIBRARY_OUTPUT_PATH 
新定義最終結果的存放目錄

PROJECT_NAME 
返回通過PROJECT指令定義的專案名稱。

cmake呼叫環境變數的方式

使用$ENV{NAME}指令就可以呼叫系統的環境變量了。比如MESSAGE(STATUS "HOME dir: $ENV{HOME}")設定環境變數的方式是SET(ENV{變數名} 值)。

  1. CMAKE_INCLUDE_CURRENT_DIR 
    自動新增CMAKE_CURRENT_BINARY_DIR和CMAKE_CURRENT_SOURCE_DIR到當前處理的CMakeLists.txt,相當於在每個CMakeLists.txt加入:INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})

  2. CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE 
    將工程提供的標頭檔案目錄始終置於系統標頭檔案目錄的前面,當定義的標頭檔案確實跟系統發生衝突時可以提供一些幫助。

  3. CMAKE_INCLUDE_PATH和CMAKE_LIBRARY_PATH

系統資訊

  • CMAKE_MAJOR_VERSION,CMAKE主版本號,比如2.4.6中的2
  • CMAKE_MINOR_VERSION,CMAKE次版本號,比如2.4.6中的4
  • CMAKE_PATCH_VERSION,CMAKE補丁等級,比如2.4.6中的6
  • CMAKE_SYSTEM,系統名稱,比如Linux-2.6.22
  • CMAKE_SYSTEM_NAME,不包含版本的系統名,比如Linux
  • CMAKE_SYSTEM_VERSION,系統版本,比如2.6.22
  • CMAKE_SYSTEM_PROCESSOR,處理器名稱,比如i686
  • UNIX,在所有的類Unix平臺為TRUE,包括OSX和cygwin
  • WIN32,在所有的Win32平臺為TRUE,包括cygwin

主要的開關選項

  1. CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS 
    用來控制IF ELSE語句的書寫方式。

  2. BUILD_SHARED_LIBS 
    這個開關用來控制預設的庫編譯方式。如果不進行設定,使用ADD_LIBRARY並沒有指定庫型別的情況下,預設編譯生成的庫都是靜態庫;如果SET(BUILD_SHARED_LIBSON)後,預設生成的為動態庫。

  3. CMAKE_C_FLAGS 
    設定C編譯選項,也可以通過指令ADD_DEFINITIONS()新增。

  4. MAKE_CXX_FLAGS 
    設定C++編譯選項,也可以通過指令ADD_DEFINITIONS()新增。

cMake常用指令

這裡引入更多的cmake指令,為了編寫的方便,將按照cmakeman page 的順序介紹各種指令,不再推薦使用的指令將不再介紹。

基本指令

PROJECT(HELLO) 
指定專案名稱,生成的VC專案的名稱,使用${HELLO_SOURCE_DIR}表示專案根目錄。

INCLUDE_DIRECTORIES 
指定標頭檔案的搜尋路徑,相當於指定gcc的-I引數 
INCLUDE_DIRECTORIES(${HELLO_SOURCE_DIR}/Hello) #增加Hello為include目錄

TARGET_LINK_LIBRARIES 
新增連結庫,相同於指定-l引數 
TARGET_LINK_LIBRARIES(demoHello) #將可執行檔案與Hello連線成最終檔案demo

LINK_DIRECTORIES 
動態連結庫或靜態連結庫的搜尋路徑,相當於gcc的-L引數 
LINK_DIRECTORIES(${HELLO_BINARY_DIR}/Hello)#增加Hello為link目錄

ADD_DEFINITIONS 
向C/C++編譯器新增-D定義,比如: 
ADD_DEFINITIONS(-DENABLE_DEBUG-DABC) 
引數之間用空格分割。如果程式碼中定義了:

#ifdef ENABLE_DEBUG

#endif
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

這個程式碼塊就會生效。如果要新增其他的編譯器開關,可以通過CMAKE_C_FLAGS變數和CMAKE_CXX_FLAGS變數設定。

ADD_DEPENDENCIES* 
定義target依賴的其它target,確保在編譯本target之前,其它的target已經被構建。ADD_DEPENDENCIES(target-name depend-target1 depend-target2 ...)

ADD_EXECUTABLE 
ADD_EXECUTABLE(helloDemo demo.cxx demo_b.cxx) 
指定編譯,好像也可以新增.o檔案,將cxx編譯成可執行檔案

ADD_LIBRARY 
ADD_LIBRARY(Hellohello.cxx) #將hello.cxx編譯成靜態庫如libHello.a

ADD_SUBDIRECTORY 
ADD_SUBDIRECTORY(Hello) #包含子目錄

ADD_TEST 
ENABLE_TESTING 
ENABLE_TESTING指令用來控制Makefile是否構建test目標,涉及工程所有目錄。語法很簡單,沒有任何引數,ENABLE_TESTING()一般放在工程的主CMakeLists.txt中。 
ADD_TEST指令的語法是:ADD_TEST(testnameExename arg1 arg2 …) 
testname是自定義的test名稱,Exename可以是構建的目標檔案也可以是外部指令碼等等,後面連線傳遞給可執行檔案的引數。

如果沒有在同一個CMakeLists.txt中開啟ENABLE_TESTING()指令,任何ADD_TEST都是無效的。比如前面的Helloworld例子,可以在工程主CMakeLists.txt中新增

ADD_TEST(mytest ${PROJECT_BINARY_DIR}/bin/main)
ENABLE_TESTING
  • 1
  • 2
  • 1
  • 2

生成Makefile後,就可以執行make test來執行測試了。

AUX_SOURCE_DIRECTORY 
基本語法是:AUX_SOURCE_DIRECTORY(dir VARIABLE),作用是發現一個目錄下所有的原始碼檔案並將列表儲存在一個變數中,這個指令臨時被用來自動構建原始檔列表,因為目前cmake還不能自動發現新新增的原始檔。比如:

AUX_SOURCE_DIRECTORY(. SRC_LIST)
ADD_EXECUTABLE(main ${SRC_LIST})
  • 1
  • 2
  • 1
  • 2

可以通過後面提到的FOR EACH指令來處理這個LIST。

CMAKE_MINIMUM_REQUIRED 
語法為CMAKE_MINIMUM_REQUIRED(VERSION versionNumber [FATAL_ERROR]), 
比如:CMAKE_MINIMUM_REQUIRED(VERSION 2.5 FATAL_ERROR) 
如果cmake版本小與2.5,則出現嚴重錯誤,整個過程中止。

EXEC_PROGRAM 
在CMakeLists.txt處理過程中執行命令,並不會在生成的Makefile中執行。具體語法為:

EXEC_PROGRAM(Executable [directory in which to run][ARGS <arguments to executable>][OUTPUT_VARIABLE <var>][RETURN_VALUE <var>])
  • 1
  • 1

用於在指定的目錄執行某個程式,通過ARGS新增引數,如果要獲取輸出和返回值,可通過OUTPUT_VARIABLERETURN_VALUE分別定義兩個變數。 
這個指令可以幫助在CMakeLists.txt處理過程中支援任何命令,比如根據系統情況去修改程式碼檔案等等。舉個簡單的例子,我們要在src目錄執行ls命令,並把結果和返回值存下來,可以直接在src/CMakeLists.txt中新增:

EXEC_PROGRAM(ls ARGS "*.c" OUTPUT_VARIABLE LS_OUTPUT RETURN_VALUE LS_RVALUE)
IF(not LS_RVALUE)
    MESSAGE(STATUS "ls result: " ${LS_OUTPUT})
ENDIF(not LS_RVALUE)
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

在cmake生成Makefile過程中,就會執行ls命令,如果返回0,則說明成功執行,那麼就輸出ls *.c的結果。關於IF語句,後面的控制指令會提到。

FILE指令 
檔案操作指令,基本語法為:

FILE(WRITEfilename "message to write"... )
FILE(APPENDfilename "message to write"... )
FILE(READfilename variable)
FILE(GLOBvariable [RELATIVE path] [globbing expression_r_rs]...)
FILE(GLOB_RECURSEvariable [RELATIVE path] [globbing expression_r_rs]...)
FILE(REMOVE[directory]...)
FILE(REMOVE_RECURSE[directory]...)
FILE(MAKE_DIRECTORY[directory]...)
FILE(RELATIVE_PATHvariable directory file)
FILE(TO_CMAKE_PATHpath result)
FILE(TO_NATIVE_PATHpath result)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

INCLUDE指令 
用來載入CMakeLists.txt檔案,也用於載入預定義的cmake模組。

INCLUDE(file1[OPTIONAL])
INCLUDE(module[OPTIONAL])
  • 1
  • 2
  • 1
  • 2

OPTIONAL引數的作用是檔案不存在也不會產生錯誤,可以指定載入一個檔案,如果定義的是一個模組,那麼將在CMAKE_MODULE_PATH中搜索這個模組並載入,載入的內容將在處理到INCLUDE語句是直接執行。

INSTALL指令

FIND_指令 
FIND_系列指令主要包含一下指令:

FIND_FILE(<VAR>name1 path1 path2 …)    VAR變數代表找到的檔案全路徑,包含檔名
FIND_LIBRARY(<VAR>name1 path1 path2 …)    VAR變量表示找到的庫全路徑,包含庫檔名
FIND_PATH(<VAR>name1 path1 path2 …)   VAR變數代表包含這個檔案的路徑
FIND_PROGRAM(<VAR>name1 path1 path2 …)   VAR變數代表包含這個程式的全路徑
FIND_PACKAGE(<name>[major.minor] [QUIET] [NO_MODULE] [[REQUIRED|COMPONENTS][componets...]])   用來呼叫預定義在CMAKE_MODULE_PATH下的Find<name>.cmake模組,也可以自己定義Find<name>模組,通過SET(CMAKE_MODULE_PATH dir)將其放入工程的某個目錄中供工程使用,後面會詳細介紹FIND_PACKAGE的使用方法和Find模組的編寫。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

FIND_LIBRARY示例:

FIND_LIBRARY(libXX11 /usr/lib)
IF(NOT libX)
    MESSAGE(FATAL_ERROR "libX not found")
ENDIF(NOT libX)
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

控制指令

IF指令,基本語法為:

IF(expression_r_r)
    #THEN section.
    COMMAND1(ARGS…)
    COMMAND2(ARGS…)ELSE(expression_r_r)
    #ELSE section.
    COMMAND1(ARGS…)
    COMMAND2(ARGS…)ENDIF(expression_r_r)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

另外一個指令是ELSEIF,總體把握一個原則,凡是出現IF的地方一定要有對應的ENDIF,出現ELSEIF的地方,ENDIF是可選的。表示式的使用方法如下:

IF(var)  如果變數不是:空, 0, N, NO, OFF, FALSE, NOTFOUND 或 <var>_NOTFOUND時,表示式為真。
IF(NOT var), 與上述條件相反。
IF(var1AND var2), 當兩個變數都為真是為真。
IF(var1OR var2), 當兩個變數其中一個為真時為真。
IF(COMMANDcmd), 當給定的cmd確實是命令並可以呼叫是為真。
IF(EXISTS dir) or IF(EXISTS file), 當目錄名或者檔名存在時為真。
IF(file1IS_NEWER_THAN file2), 當file1比file2新,或者file1/file2其中有一個不存在時為真檔名請使用完整路徑。
IF(IS_DIRECTORY dirname),  當dirname是目錄時為真。
IF(variableMATCHES regex)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

IF(string MATCHES regex) 當給定的變數或者字串能夠匹配正則表示式regex時為真。比如:

IF("hello" MATCHES "hello")
    MESSAGE("true")
ENDIF("hello" MATCHES "hello")
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3
IF(variable LESS number)
IF(string LESS number)
IF(variable GREATER number)
IF(string GREATER number)
IF(variable EQUAL number)
IF(string EQUAL number)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

數字比較表示式

android studio 快捷鍵整理

Alt+回車 匯入包,自動修正 Ctrl+N   查詢類 Ctrl+Shift+N 查詢檔案 Ctrl+Alt+L  格式化程式碼 Ctrl+Alt+O 優化匯入的類和包 Alt+Insert 生成程

Android百度地圖開發:地圖下載與配置

轉載請標明出處 弄了不久,也算是入門百度地圖的開發了,基本的實現並不難,接下來說下基本步驟: 1:註冊百度賬號並進入官網:http://lbsyun.baidu.com/index.php?title=androidsdk,按提示完成基本驗證就可進入如下頁

Android百度地圖開發之初體驗

    做關於位置或者定位的app的時候免不了使用地圖功能,本人最近由於專案的需求需要使用百度地圖的一些功能,所以這幾天研究了一下,現寫一下blog記錄一下,歡迎大家評論指正!一、申請AK(API Key)    要想使用百度地圖sdk,就必須申請一個百度地圖的api key

星雲鏈智能合約開發Mac下安裝的準備工作

星雲鏈開發環境安裝 nebulasio安裝 星雲鏈安裝 星雲鏈開發 智能合約開發 Homebrew安裝 包管理工具可以讓你安裝和更新程序變得更方便,目前在Mac系統中最受歡迎的包管理工具是 Homebrew. 我們安裝Homebrew是為了安裝星雲鏈開發環境時更方便快捷。 安裝方法 第一步

即時通訊音視訊開發視訊編解碼之理論概述

前言 即時通訊應用中的實時音視訊技術,幾乎是IM開發中的最後一道高牆。原因在於:實時音視訊技術 = 音視訊處理技術 + 網路傳輸技術 的橫向技術應用集合體,而公共網際網路不是為了實時通訊設計的。 系列文章 《即時通訊音視訊開發(二):視訊編解碼之數字視訊介紹》 《即時通訊音