# for more informationusingCMake with Android Studio, read the# Documentation:https://d.android.com/studio/projects/add-native-code.html# Sets the minimum version of CMake required to build the native library.cmake_minimum_required (version3.4.1) # Creates and names a library, sets it aseither static# or SHARED, and provides the relative paths to it source code.# you can define multiple libraries, and CMake builds them foryou.# Gradle automatically packages GKFX libraries with your apk.add_library (# Sets the name of the library. Native-Lib # sets the library asa shared library. SHARED # provides a relative path to your source file (s). SRC/main/cpp/native-lib.cpp) # searches forA specified prebuilt library and stores the path asa# variable. Because CMake includes system librariesinchThe search path by#defaultNeed to specify the name of the PublicNDK library# you want to add. CMake verifies that the library exists before# completing its build.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) # Specifies libraries CMake should link to your target library. you# can link multiple libraries, such asLibraries you defineinch This# Build script, prebuilt third-Party libraries, or System libraries.target_link_libraries (# Specifies the target library. Native-Lib # Links the target library to the Log Library # includedinchThe NDK. ${log-lib})
Above the completion of the annotated content, but the core of which is also a few sentences, the following are introduced:
cmake_minimum_required(VERSION 3.4.1)Used to set the minimum CMake version we need when compiling the local library, Androidstudio automatically generated, we hardly need our own tube.
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 )
add_libraryThe name of the local library used to set the build of the compilation, which indicates that the native-lib SHARED compilation was generated 动态链接库 (as mentioned earlier), src/main/cpp/native-lib.cpp represents the path to the file that participates in the compilation, which can be written in multiple files.
find_libraryis used to add some of the libraries we need to rely on when compiling our local libraries, because CMake already know the path of the system library, so we just specify to use the log library, and then give the log library alias for log-lib Easy reference later, here the log The library is the repository we need to use to log logs when we debug, and the NDK provides it for us.
target_link_librariesis to correlate our own libraries and some third-party libraries or system libraries, where we associate our libraries native-lib and log libraries.
NDK Custom Configuration
1. To add multiple C + + files that participate in compilation
First, we found that the above examples are related to a C + + file, then our actual project can not only have a C + + file, so we first want to change CMakeLists.txt the file, as follows:
add_library( HelloNDK SHARED src/main/cpp/HelloNDK.c src/main/cpp/HelloJNI.c)
Simple, straightforward, but it is important to note that when you write a path, you must pay attention to the current CMakeLists.txt position in the project, the path above is relative to the CMakeLists.txt write.
2. We want to compile multiple so libraries
We will find that, as we wrote above, because there is only one CMakeLists.txt file, so we will compile all the C + + files into a so library, which is very inappropriate, here we try to learn how to compile multiple so libraries.
Let's put my project folder structure on the map:
Then see how each CMakeLists.txt of our files is written:
The contents of the files within the one folder CMakeLists.txt :
ADD_LIBRARY(one-lib SHARED one-lib.c)target_link_libraries(one-lib log)
The contents of the files within the folder CMakeLists.txt :
ADD_LIBRARY(two-lib SHARED two-lib.c)target_link_libraries(two-lib log)
The contents of the file under the app directory CMakeLists.txt
# Sets The minimum version of CMake required to build the native library. cmake_minimum_required (VERSION 3.4. 1) add_library (hellondk SHARED src/main/cpp/hellondk.c src/main/cpp/hellojni.c) 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 (hellondk log)
add_subdirectory (src/main/ Cpp/one) add_subdirectory (src/main/cpp/two)
With the above configuration we can see that the configuration of the CMakeLists.txt file is to support inheritance, so we just write the configuration of different special configuration items in the sub-configuration file, and finally configure the path of the child configuration file in the top-level file, we will compile the project now, we'll >\ in the < project directory. App\build\intermediates\cmake\debug\obj\armeabi You can see the generated dynamic link library below. And it's a three dynamic link library.
3. Change the directory generated by the dynamic link library
We are not found above the so library path is too deep, not easy to find, nothing, can be configured, we just need to add the following sentence in the top-level CMakeLists.txt file can be
#设置生成的so动态库最后输出的路径set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI})
Then we can see the directory under App/src/main jniLibs , in which we see the folders and files of our dynamic link library (this is directly configured to the default path of the system, if the configuration to other paths needs to be specified in the Gradle file jinLibs.srcDirs = [‘newDir‘] ).
NDK Error Debugging
In the process of development, will inevitably encounter bugs, then how to do, hit log ah, below we talk about playing log and look at the position of log.
1. Log in a C + + file
(1) Adding a header file to a C + + file
#include <android/log.h>
Above is the header file for the print log and must be added
(2) Add the macro definition and tag of the print log
Log definition#defineLOG"Jnilog"This is a custom log tag.#define LOGD (...) __android_log_print (Android_log_debug,log,__va_args__) //definition logd type #define Logi (log,__va_args__) // Define Logi type #define LOGW (log,__va_args__) //define LOGW Type #define LOGE (log,__va_args__) //define Loge Type # Define LOGF ( log,__va_args__) //define LOGF type
The log level above is the corresponding one in Android.
(3) After two steps above, we can print the log.
int len = 5;LOGE("我是log %d", len);
Now we can see our printed logs in the Logcat.
2. View error messages
First we write an error manually, we find a function in the C file above, which writes the following code:
int * p = NULL;*p = 100;
Above is a null pointer exception, we run the program, we find a crash, and then look at the console, only the following line of information:
libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 17481
Completely do not understand the above information OK, this is not obvious, let's learn how to make the above information clear
We need to use the ndk-stack tool, which is in our NDK root directory, it can help us to translate the above information into more understandable and more detailed error message, the following to see how to do:
(1) Open the command line in Androidstudio and enteradb logcat > log.txt
In the above sentence we use the ADB command to capture the log log and write to the Log.txt file, and then we can see the Log.txt file in the project root directory
(2) Open the Log.txt to see the error message, as follows:
F/LIBC (17481): Fatal signalOne (SIGSEGV), code1, fault addr0x0 in Tid17481 (DEKONG.NDKDEMO1)I/debug (67): * * * * * * * * * * * * * * * * * * * * * * * * * * * *I/debug (): Build fingerprint:' Generic/vbox86p/vbox86p:5.0/lrx21m/genymotion08251046:userdebug/test-keys 'I/debug (): Revision:' 0 'I/debug ((+): ABI:' x86 'I/debug ((): PID:17481, Tid:17481, Name:dekong.ndkdemo1 >>> com.codekong.ndkdemo1 <<<I/debug (): SignalOne (SIGSEGV), code1 (segv_maperr), fault addr0x0I/debug (): EAX00000000 ebx f3494fcc ecx ffa881a0 edx00000000I/debug (): ESI f434e2b0 EDI00000000I/debug (): Xcs00000023 XDS0000002b xes0000002b XFS00000007 XSS0000002bI/debug (: EIP f3492a06 EBP ffa88318 ESP ffa88280 flags00210246I/debug (67):I/debug (): BackTrace:I/debug (67): #XX pc00000a06/data/app/com.codekong.ndkdemo1-2/lib/x86/libhellondk.so (Java_com_codekong_ndkdemo1_mainactivity_updatefile+150) i/debug (67): # 01 pc 0026e27b/data/dalvik-cache/x86/[email protected]@ Com.codekong.ndkdemo1-[email protected] @classes. DexI /debug (67): #02 pc 9770ee7d < Unknown>i/debug (67): #03 pc a4016838 <unknown>i/debug (67): i/debug (67): Tombstone written to:/data/tombstones/tombstone _05
Now the error message still can not understand, so we need to use ndk-stack conversion:
(3) Continue to enter the following command on the command line in Androidstudio (before that, we have to add the Ndk-stack path to the environment variable so that we can use it directly on the command line)
ndk-stack -sym app/build/intermediates/cmake/debug/obj/x86 -dump ./log.txt
The above -sym parameters for your corresponding platform (I am the Genymotion Simulator, x86 platform) path, if you follow the above steps to change the path, it will need to write the path, the -dump following parameters are our previous step to obtain the Log.txt file, the execution results are as follows:
Crash Dump:Build fingerprint:' Generic/vbox86p/vbox86p:5.0/lrx21m/genymotion08251046:userdebug/test-keys ' PID:17481, Tid:17481, Name:dekong. ndkdemo1>>> com. Codekong. ndkdemo1<<<signalOne (SIGSEGV), code1 (segv_maperr), fault addr0x0Stack Frame I/debug (67):#00 pc00000A06/Data/app/com. Codekong. ndkdemo1-2/lib/x86/libhellondk. SO (java_com_codekong_ndkdemo1_mainactivity_updatefile+): Routine java_com_codekong_ndkdemo1_mainactivity_updatefile at F:\androidfirstcode\ndkdemo1\app\src\main\cpp/hellojniC32Stack Frame I/debug (67):#01 pc0026e27b/Data/dalvik-cache/x86/[Email protected] @com. Codekong. ndkdemo1-[Email protected][Email protected]. DexStack Frame I/debug (67):#02 pc9770ee7d<unknown>: unable to open symbol file app/build/intermediates/cmake/ Debug/obj/x86/<unknown>22): Invalid argumentstack frame i/debug (67): #03 pc a4016838 <unknown>: unable to open symbol file App/build/intermediates/cmake/debug/obj/x86/<unknown >22): Invalid Argumentcrash dump is completed
In particular, the above sentence:
g_ndkdemo1_MainActivity_updateFile+150): Routine Java_com_codekong_ndkdemo1_MainActivity_updateFile at F:\AndroidFirstCode\NDKDemo1\app\src\main\cpp/HelloJNI.c:32
Accurately indicates the number of rows where the error occurred
Androidstudio Project Cmakelists Analysis