---
# System prepended metadata

title: CMake筆記

---

# CMake筆記

## Configure CMake

CMakeLists.txt是CMake用來build C/C++ libraries所使用的build script
NDK底下有兩種方式可以build C/C++ libraries，ndk-build和CMake
ndk-build是for Android特化的方式，CMake則是跨平台使用

Android Developers對CMake build的說明(https://developer.android.com/studio/projects/configure-cmake)

CMake Documentation and Community
(https://cmake.org/documentation/)


## 基本內容
從Android Developer - Configure-cmake的範例來看，基本如下
會build出libnative-lib為名的so檔

```
# Sets the minimum version of CMake required to build your native library.
# This ensures that a certain set of CMake features is available to
# your build.
cmake_minimum_required(VERSION 3.4.1)

# Specifies a library name, specifies whether the library is STATIC or
# SHARED, and provides relative paths to the source code. You can
# define multiple libraries by adding multiple add_library() commands,
# and CMake builds them for you. When you build your app, Gradle
# automatically packages shared libraries with your APK.
add_library( # Specifies the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/cpp/native-lib.cpp )
             
# Specifies a path to native header files.
include_directories(src/main/cpp/include/)

```
若是需要加入NDK library之類的，可用find_library
```
find_library( # Defines the name of the path variable that stores the
              # location of the NDK library.
              log-lib

              # Specifies the name of the NDK library that
              # CMake needs to locate.
              log )
```
上面找到log這個library後，便可以用target_link_libraries來連結其它library
```
# Links your native library against one or more other native libraries.
target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the log library to the target library.
                       ${log-lib} )
```
如果是加入在別的地方已build好的非NDK library，會改為使用add_library並以IMPORTED的方式註明
import進來的library如果只是要打包在一起而非有build-time dependency的話，就不需要加進target_link_libraries
```
add_library( imported-lib
             SHARED
             IMPORTED )
```

## 以正在使用的libbitxxx.so為例
```
cmake_minimum_required(VERSION 3.4.1)

project(bitxxxxxxxxx)

add_library( # Sets the name of the library.
        bitxxx

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        JniBitxxxxxxxxx.cpp
        verxxxx.c)

set(include-headers-bitxxxxxxxxx inc)
include_directories( ${include-headers-bitxxxxxxxxx} )

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)


target_link_libraries( # Specifies the target library.
        bitxxx
        jnigraphics # Bitmap library, link to libjnigraphics, #include <android/bitmap.h>

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})
```












## 遇到的問題

### linker類型
其實不確定問題的原因，原makefile中有設定
```
LOCAL_LDFLAGS += -fuse-ld=gold
```
下下面兩段error的部份是一起出現的，__bss_start等等的都是跟linker有關的部份
[How can I add linker flag for libraries with CMake? - Stack Overflow](https://stackoverflow.com/questions/24532853/how-can-i-add-linker-flag-for-libraries-with-cmake)

目前已知下面這個方式是能build過的方式
有看過-fuse-ld=gold，這是google設計的linker，但會build error
應該就是import的so不是用gold所以出錯
```
set (CMAKE_SHARED_LINKER_FLAGS "-fuse-ld=lld")
```
主要是shared linker的設定格式
之前試好久都失敗是因為看到錯誤的寫法
```
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=lld")
```


```
> Task :app:buildCMakeRelWithDebInfo[arm64-v8a]
C/C++: ninja: Entering directory `C:\Users\vincent3_chen\AndroidStudioProjects\AsusCamera2\app\.cxx\RelWithDebInfo\1z6h4n4e\arm64-v8a'
C/C++: ld: error: found local symbol '__bss_start' in global part of symbol table in file C:/Users/vincent3_chen/AndroidStudioProjects/AsusCamera2/app/src/main/jniSrcs/feature_dit_light_art/jni/lib/arm64-v8a/libxditk_LightArt.so
C/C++: ld: error: found local symbol '_end' in global part of symbol table in file C:/Users/vincent3_chen/AndroidStudioProjects/AsusCamera2/app/src/main/jniSrcs/feature_dit_light_art/jni/lib/arm64-v8a/libxditk_LightArt.so
C/C++: ld: error: found local symbol '_edata' in global part of symbol table in file C:/Users/vincent3_chen/AndroidStudioProjects/AsusCamera2/app/src/main/jniSrcs/feature_dit_light_art/jni/lib/arm64-v8a/libxditk_LightArt.so
C/C++: clang++: error: linker command failed with exit code 1 (use -v to see invocation)
ld: error: found local symbol '__bss_start' in global part of symbol table in file C:/Users/vincent3_chen/AndroidStudioProjects/AsusCamera2/app/src/main/jniSrcs/feature_dit_light_art/jni/lib/arm64-v8a/libxditk_LightArt.so
ld: error: found local symbol '_end' in global part of symbol table in file C:/Users/vincent3_chen/AndroidStudioProjects/AsusCamera2/app/src/main/jniSrcs/feature_dit_light_art/jni/lib/arm64-v8a/libxditk_LightArt.so
ld: error: found local symbol '_edata' in global part of symbol table in file C:/Users/vincent3_chen/AndroidStudioProjects/AsusCamera2/app/src/main/jniSrcs/feature_dit_light_art/jni/lib/arm64-v8a/libxditk_LightArt.so
> Task :app:buildCMakeRelWithDebInfo[arm64-v8a] FAILED
```

```
Execution failed for task ':app:buildCMakeRelWithDebInfo[arm64-v8a]'.
> com.android.ide.common.process.ProcessException: ninja: Entering directory C:\Users\vincent3_chen\AndroidStudioProjects\AsusCamera2\app\.cxx\RelWithDebInfo\1z6h4n4e\arm64-v8a'
  [1/2] Building CXX object feature_dit_light_art/jni/CMakeFiles/ditlightart.dir/JniDITLightArt.cpp.o
  [2/2] Linking CXX shared library C:\Users\vincent3_chen\AndroidStudioProjects\AsusCamera2\app\build\intermediates\cxx\RelWithDebInfo\1z6h4n4e\obj\arm64-v8a\libditlightart.so
  FAILED: C:/Users/vincent3_chen/AndroidStudioProjects/AsusCamera2/app/build/intermediates/cxx/RelWithDebInfo/1z6h4n4e/obj/arm64-v8a/libditlightart.so 
  cmd.exe /C "cd . && C:\Users\vincent3_chen\AppData\Local\Android\Sdk\ndk\23.1.7779620\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=aarch64-none-linux-android28 --sysroot=C:/Users/vincent3_chen/AppData/Local/Android/Sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/windows-x86_64/sysroot -fPIC -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fexceptions -frtti -stdlib=libc++ -O2 -g -DNDEBUG  -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--fatal-warnings -Qunused-arguments -Wl,--no-undefined -shared -Wl,-soname,libditlightart.so -o C:\Users\vincent3_chen\AndroidStudioProjects\AsusCamera2\app\build\intermediates\cxx\RelWithDebInfo\1z6h4n4e\obj\arm64-v8a\libditlightart.so feature_dit_light_art/jni/CMakeFiles/ditlightart.dir/JniDITLightArt.cpp.o  C:/Users/vincent3_chen/AndroidStudioProjects/AsusCamera2/app/src/main/jniSrcs/feature_dit_light_art/jni/lib/arm64-v8a/libxditk_LightArt.so  C:/Users/vincent3_chen/AppData/Local/Android/Sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/aarch64-linux-android/28/liblog.so   -static-libstdc++ -latomic -lm && cd ."
  ld: error: found local symbol '__bss_start' in global part of symbol table in file C:/Users/vincent3_chen/AndroidStudioProjects/AsusCamera2/app/src/main/jniSrcs/feature_dit_light_art/jni/lib/arm64-v8a/libxditk_LightArt.so
  ld: error: found local symbol '_end' in global part of symbol table in file C:/Users/vincent3_chen/AndroidStudioProjects/AsusCamera2/app/src/main/jniSrcs/feature_dit_light_art/jni/lib/arm64-v8a/libxditk_LightArt.so
  ld: error: found local symbol '_edata' in global part of symbol table in file C:/Users/vincent3_chen/AndroidStudioProjects/AsusCamera2/app/src/main/jniSrcs/feature_dit_light_art/jni/lib/arm64-v8a/libxditk_LightArt.so
  clang++: error: linker command failed with exit code 1 (use -v to see invocation)
  ninja: build stopped: subcommand failed.

```

### C flags
android makefile會有像LOCAL_C_FLAGS/LOCAL_CPP_FLAGS之類的
雖然有google到在CMake可以使用add_compile_options來添加
```
add_compile_options(-ffast-math -O3)
```
後來有看到另一種方式
```
set(CMAKE_C_FLAGS "-ffast-math -O3")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffast-math -O3")
```
跟AI詢問過後，上面是override，下面會append到現有的flags上
${CMAKE_C_FLAGS}代表當前的flags

最後用message的方式印出${CMAKE_C_FLAGS}
在Build window中有看到add_compile_option沒效，可能沒有正確使用
set的方式有正確設定flags

看起來是適用的對象和使用方式不一樣，也不是檢查CMAKE_C_FLAGS
[add_compile_options加入某些编译选项(-pg)无效](https://www.cnblogs.com/bluettt/p/12952543.html)

AI建議這樣檢查，但我還沒試
```
# Define your target
add_executable(MyApp main.cpp) # replace with your source files

# Set any desired compile options
add_compile_options(-ffast-math -O3)

# Diagnostic command to print out the compile options
get_target_property(TARGET_COMPILE_OPTIONS MyApp COMPILE_OPTIONS)
message(STATUS "Compile options for MyApp: ${TARGET_COMPILE_OPTIONS}")

```


## reference from other note
參考自
[Android NDK 開發](https://hackmd.io/NOzQJQo4R0i5iVAD9tVyxw?view)

CMake 常用命令

* CMake **常用命令**

    | 命令 | 功能  |
    | ---------------------- | ---- |
    | set(<代號> <來源>) | 可為後方來源建立一個代號，之後使用 ${代號} 及可 `set(DIR "C:/File/main.c")`|
    | set(<功能> <on/off/other>) | 開啟 or 關閉某些功能，或指定參數 set(CMAKE_CXX_STANDARD 14)|
    | project(<項目名稱> LANGUAGES C) | Android 中可以不用指定  |
    | cmake_minimum_required | CMake 最低版本 **(衝突時以 gradle 中 externalNativeBuild 設定為準)** |
    | include_directories(路徑) | **指定 ==++原生代碼++ or ++so 庫++的路徑==** |
    | add_library(<庫名稱> <形式> <庫路徑(可多個)>) | **添加原 (Source) 文件、自己寫的程式** |
    | find_library | 添加 NDK API，也就是 Android NDK 提供的庫 |
    | set_target_properties | **指定特定庫的路徑 or ++指定生成的目標庫導出路徑++** |
    | target_link_library | 將 預編譯庫 **連接** 到自己的庫 |
    | aux_source_directory | 找在特定路徑下的文件，**可統整多個文件在一起**  |
    | file(<區域> <代號> <路徑>) | 編譯原文件 |
    
    
    
    
    
    
    
# Reference
Android Developes各種說明
[Configure CMake  |  Android Studio  |  Android Developers](https://developer.android.com/studio/projects/configure-cmake)
[CMake  |  Android NDK  |  Android Developers](https://developer.android.com/ndk/guides/cmake)
[Install and configure the NDK and CMake  |  Android Studio  |  Android Developers](https://developer.android.com/studio/projects/install-ndk)
[CmakeFlags  |  Android Developers](https://developer.android.com/reference/tools/gradle-api/8.1/com/android/build/api/dsl/CmakeFlags)

[CMake Documentation and Community](https://cmake.org/documentation/)

[How can I add linker flag for libraries with CMake?](https://stackoverflow.com/questions/24532853/how-can-i-add-linker-flag-for-libraries-with-cmake)

[Android NDK 開發](https://hackmd.io/NOzQJQo4R0i5iVAD9tVyxw?view)