preface
How does C/C + + code become a program that can run on hardware? Let's start with a simple "Hello World" program.
Hello World compilation
There is a popular joke:
A programmer was very interested in calligraphy and decided to make achievements in this field after retirement. So he spent a lot of money to buy the first-class four treasures of study. One day, after dinner, he suddenly had an elegant mood, polished ink and paper, and lit a good sandalwood, which was quite Wang Xizhi's style and Yan Zhenqing's momentum. He calmed down for a moment, splashed ink and wrote solemnly: Hello World
"Hello World" of C code, helloWorld.c As follows:
/*include head file*/ #include <stdio.h> /*the main function*/ int main(int argc,char *argv[]) { printf("Hello World!\n"); return 0 ; }
Let's compile using gcc first:
$ gcc helloWorld.c $ ./a.out Hello World!
You can see, "Hello World!" Has been printed directly to the screen. So what happened here?
For help, we can run gcc --help to view the help instructions, one of which is:
-v Display the programs invoked by the compiler.
In other words, adding the - v parameter can display the details of the program compiled and called. For more analysis of gcc -v, please refer to: Parsing gcc -v output
The output information is as follows:
$ gcc helloWorld.c -o helloWorld -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/8/lto-wrapper OFFLOAD_TARGET_NAMES=nvptx-none OFFLOAD_TARGET_DEFAULT=1 Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Uos 8.3.0.3-3+rebuild' --with-bugurl=file:///usr/share/doc/gcc-8/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-8 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 8.3.0 (Uos 8.3.0.3-3+rebuild) COLLECT_GCC_OPTIONS='-o' 'helloWorld' '-v' '-mtune=generic' '-march=x86-64' /usr/lib/gcc/x86_64-linux-gnu/8/cc1 -quiet -v -imultiarch x86_64-linux-gnu helloWorld.c -quiet -dumpbase helloWorld.c -mtune=generic -march=x86-64 -auxbase helloWorld -version -o /tmp/ccfIwQTj.s GNU C17 (Uos 8.3.0.3-3+rebuild) version 8.3.0 (x86_64-linux-gnu) compiled by GNU C version 8.3.0, GMP version 6.1.2, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.20-GMP GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/8/../../../../x86_64-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /usr/lib/gcc/x86_64-linux-gnu/8/include /usr/local/include /usr/lib/gcc/x86_64-linux-gnu/8/include-fixed /usr/include/x86_64-linux-gnu /usr/include End of search list. GNU C17 (Uos 8.3.0.3-3+rebuild) version 8.3.0 (x86_64-linux-gnu) compiled by GNU C version 8.3.0, GMP version 6.1.2, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.20-GMP GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: b0aa96b3fb90562a90ec754591a6a020 COLLECT_GCC_OPTIONS='-o' 'helloWorld' '-v' '-mtune=generic' '-march=x86-64' as -v --64 -o /tmp/ccUwhs9h.o /tmp/ccfIwQTj.s GNU assembler version 2.31.1 (x86_64-linux-gnu) using BFD version (GNU Binutils for Uos) 2.31.1 COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/8/:/usr/lib/gcc/x86_64-linux-gnu/8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/8/:/usr/lib/gcc/x86_64-linux-gnu/ LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/8/:/usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/8/../../../:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS='-o' 'helloWorld' '-v' '-mtune=generic' '-march=x86-64' /usr/lib/gcc/x86_64-linux-gnu/8/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/8/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/8/lto-wrapper -plugin-opt=-fresolution=/tmp/ccXGG9qg.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o helloWorld /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/8 -L/usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/8/../../.. /tmp/ccUwhs9h.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/crtn.o COLLECT_GCC_OPTIONS='-o' 'helloWorld' '-v' '-mtune=generic' '-march=x86-64'
There is too much information. Let's digest it and eliminate the additional information. We can see three steps cc1, as and collect2, as follows:
Preprocessing and compiling cc1
Search this message for HelloWorld c. You will see:
/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -quiet -v -imultiarch x86_64-linux-gnu helloWorld.c -quiet -dumpbase helloWorld.c -mtune=generic -march=x86-64 -auxbase helloWorld -version -o /tmp/ccfIwQTj.s
As you can see, cc1 is used to convert HelloWorld C compile and generate ccfiwqtj s.
Assembly as
Continue to find ccfiwqtj s. You will see:
as -v --64 -o /tmp/ccUwhs9h.o /tmp/ccfIwQTj.s
as can be seen from it, ccfiwqtj S assembly generates ccfiwqtj o.
Link collect2
Continue to find ccfiwqtj o. You will see:
/usr/lib/gcc/x86_64-linux-gnu/8/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/8/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/8/lto-wrapper -plugin-opt=-fresolution=/tmp/ccXGG9qg.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o helloWorld /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/8 -L/usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/8/../../.. /tmp/ccUwhs9h.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/crtn.o
As you can see, using collect2, ccuwhs9h O links with many other files to generate helloWorld.
Episode
The compilation process can be roughly divided into four steps: preprocessing, compilation, assembly and linking. But we have found that gcc -v only uses three steps. What's going on here?
stay Behind GCC compilation (preprocessing and compilation, assembly and linking) It is mentioned in:
In fact, gcc calls cpp here (although we only see CC1 through gcc's - v). cpp, The C Preprocessor, is mainly used to preprocess macro definitions, file inclusion, conditional compilation, etc.
Let's use cpp to test, and also add "- v" parameter:
$ cpp helloWorld.c -o helloWorld.i -v Using built-in specs. COLLECT_GCC=cpp OFFLOAD_TARGET_NAMES=nvptx-none OFFLOAD_TARGET_DEFAULT=1 Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Uos 8.3.0.3-3+rebuild' --with-bugurl=file:///usr/share/doc/gcc-8/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-8 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 8.3.0 (Uos 8.3.0.3-3+rebuild) COLLECT_GCC_OPTIONS='-E' '-o' 'helloWorld.i' '-v' '-mtune=generic' '-march=x86-64' /usr/lib/gcc/x86_64-linux-gnu/8/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu helloWorld.c -o helloWorld.i -mtune=generic -march=x86-64 ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/8/../../../../x86_64-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /usr/lib/gcc/x86_64-linux-gnu/8/include /usr/local/include /usr/lib/gcc/x86_64-linux-gnu/8/include-fixed /usr/include/x86_64-linux-gnu /usr/include End of search list. COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/8/:/usr/lib/gcc/x86_64-linux-gnu/8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/8/:/usr/lib/gcc/x86_64-linux-gnu/ LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/8/:/usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/8/../../../:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS='-E' '-o' 'helloWorld.i' '-v' '-mtune=generic' '-march=x86-64'
It is found that cc1:
/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu helloWorld.c -o helloWorld.i -mtune=generic -march=x86-64
And HelloWorld C to compile and generate cfiwqtj S comparison:
/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -quiet -v -imultiarch x86_64-linux-gnu helloWorld.c -quiet -dumpbase helloWorld.c -mtune=generic -march=x86-64 -auxbase helloWorld -version -o /tmp/ccfIwQTj.s
It can be seen that cc1 adds the - E parameter during preprocessing. It can be understood that when cc1 adds the - E parameter, only preprocessing is performed. When cc1 does not add the - E parameter, preprocessing and compilation are completed at the same time. Therefore, there are only three steps, but preprocessing and compilation are combined into one step by cc1.
Four steps
Next, let's break down these four steps again and control each process with simpler parameters. Reference article: How is the hello program compiled?.
Tip: if the "- v" parameter is added to the following commands, you can also view the specific called programs and parameters, which is the decomposition of the previous steps.
Pretreatment
Preprocessing is mainly used to process the instructions starting with # in the source code (#pragma exception), such as #include in the hello world program in this article. After preprocessing, stdio The contents of H are inserted into the position of the preprocessing instruction.
To generate only the preprocessed content, GCC - E - O HelloWorld i helloWorld. C is equivalent to CPP - O HelloWorld i helloWorld. c:
gcc -E -o helloWorld.i helloWorld.c # -The E parameter indicates that only preprocessing is performed
Generated HelloWorld I is the content after preprocessing. If you are interested, you can open the file to view the content, and you will find stdio The position of H is replaced by its actual content. After preprocessing, the comment content will also be deleted and the macro definition will be expanded.
After knowing this skill, we can preprocess some complex macro definitions and then view the preprocessed code to quickly troubleshoot and understand the code.
compile
After preprocessing, it is necessary to perform lexical analysis, syntax analysis and semantic analysis on the generated preprocessing files, and finally generate assembly code files. White dots can be simply understood as "translating" C code into assembly code. This process is not only the core, but also a more complex process. We can command:
gcc -S -o helloWorld.s helloWorld.c # -The S parameter indicates that only until the assembly is generated
The generated assembly code HelloWorld S as follows:
.file "helloWorld.c" .text .section .rodata .LC0: .string "Hello World!" .text .globl main .type main, @function main: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 subq $16, %rsp movl %edi, -4(%rbp) movq %rsi, -16(%rbp) movl $.LC0, %edi call puts movl $0, %eax leave .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE0: .size main, .-main .ident "GCC: (Uos 8.3.0.3-3+rebuild) 8.3.0" .section .note.GNU-stack,"",@progbits
assembly
Assembly is to translate assembly code into machine executable instructions and generate object files. The whole process is relatively simple, which is almost translated one by one according to assembly instructions and machine instructions. We can obtain the compiled content with the following command:
gcc -c -o helloWorld.o helloWorld.c # -The c parameter indicates that only the executable instruction files of the machine are generated and are not linked
link
Link is to put all the target files together in some way to generate the final executable file. The printf function is invoked in our hello program, but it does not exist in helloWorld.. O, but in libc So or libc A, so we need to integrate them through links.
gcc -o helloWorld.o helloWorld.c
In the actual project, we can check the link information to determine whether the specified path is correct for those external libraries.
summary
The compilation process is divided into four steps:
- Will c source program preprocessing is i file
- The compiler will i file compiled into s assembler
- The assembler will s assembler compiled into o relocatable target files
- The linker links the relocatable target file into an executable file
Use the "- v" parameter in the compilation process to view the compilation process in detail, which is very useful in practical development.
One more thing: compilation process in Android NDK
Sample code
jni In the project, the same "Hello World" sample code is added with ndk compilation script Application.mk,Android.mk , enter jni directory and compile with NDK build:
chenls@chenls-PC:jni$ ndk-build [arm64-v8a] Compile : helloWorld <= helloWorld.c [arm64-v8a] Executable : helloWorld [arm64-v8a] Install : helloWorld => libs/arm64-v8a/helloWorld
NDK build script The document mentions that the parameter V=1 starts the build and displays the build command.
In fact, this is similar to - v in gcc. Let's try:
chenls@chenls-PC:jni$ ndk-build V=1 rm -f /home/chenls/Desktop/Android-Native-Development/source/helloWorld/libs/arm64-v8a/* rm -f /home/chenls/Desktop/Android-Native-Development/source/helloWorld/libs/arm64-v8a/gdbserver rm -f /home/chenls/Desktop/Android-Native-Development/source/helloWorld/libs/arm64-v8a/gdb.setup [arm64-v8a] Compile : helloWorld <= helloWorld.c rm -f /home/chenls/Desktop/Android-Native-Development/source/helloWorld/obj/local/arm64-v8a/objs/helloWorld/helloWorld.o /home/chenls/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/bin/clang -MMD -MP -MF /home/chenls/Desktop/Android-Native-Development/source/helloWorld/obj/local/arm64-v8a/objs/helloWorld/helloWorld.o.d -target aarch64-none-linux-android26 -fdata-sections -ffunction-sections -fstack-protector-strong -funwind-tables -no-canonical-prefixes --sysroot /home/chenls/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/sysroot -g -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -D_FORTIFY_SOURCE=2 -fpic -O2 -DNDEBUG -I/home/chenls/Desktop/Android-Native-Development/source/helloWorld/jni -fstack-protector -DANDROID -nostdinc++ -Wformat -Werror=format-security -c /home/chenls/Desktop/Android-Native-Development/source/helloWorld/jni/helloWorld.c -o /home/chenls/Desktop/Android-Native-Development/source/helloWorld/obj/local/arm64-v8a/objs/helloWorld/helloWorld.o [arm64-v8a] Executable : helloWorld /home/chenls/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ -Wl,--gc-sections -Wl,-rpath-link=/home/chenls/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26 -Wl,-rpath-link=/home/chenls/Desktop/Android-Native-Development/source/helloWorld/obj/local/arm64-v8a /home/chenls/Desktop/Android-Native-Development/source/helloWorld/obj/local/arm64-v8a/objs/helloWorld/helloWorld.o -lgcc -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libgcc_real.a -latomic -Wl,--exclude-libs,libatomic.a -target aarch64-none-linux-android26 -no-canonical-prefixes -Wl,--build-id -nostdlib++ -Wl,--no-undefined -Wl,--fatal-warnings -lc -lm -o /home/chenls/Desktop/Android-Native-Development/source/helloWorld/obj/local/arm64-v8a/helloWorld [arm64-v8a] Install : helloWorld => libs/arm64-v8a/helloWorld install -p /home/chenls/Desktop/Android-Native-Development/source/helloWorld/obj/local/arm64-v8a/helloWorld /home/chenls/Desktop/Android-Native-Development/source/helloWorld/libs/arm64-v8a/helloWorld /home/chenls/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-strip --strip-unneeded /home/chenls/Desktop/Android-Native-Development/source/helloWorld/libs/arm64-v8a/helloWorld
Let's also digest it, which is divided into two steps:
Generated using clang o documentation
Search this message for HelloWorld c. You will see:
/home/chenls/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/bin/clang -MMD -MP -MF /home/chenls/Desktop/Android-Native-Development/source/helloWorld/obj/local/arm64-v8a/objs/helloWorld/helloWorld.o.d -target aarch64-none-linux-android26 -fdata-sections -ffunction-sections -fstack-protector-strong -funwind-tables -no-canonical-prefixes --sysroot /home/chenls/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/sysroot -g -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -D_FORTIFY_SOURCE=2 -fpic -O2 -DNDEBUG -I/home/chenls/Desktop/Android-Native-Development/source/helloWorld/jni -fstack-protector -DANDROID -nostdinc++ -Wformat -Werror=format-security -c /home/chenls/Desktop/Android-Native-Development/source/helloWorld/jni/helloWorld.c -o /home/chenls/Desktop/Android-Native-Development/source/helloWorld/obj/local/arm64-v8a/objs/helloWorld/helloWorld.o
As you can see, using clang, HelloWorld C preprocessing, compiling and assembling to generate HelloWorld O documentation.
Using clang + + links
Continue to find HelloWorld o. You will see:
/home/chenls/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ -Wl,--gc-sections -Wl,-rpath-link=/home/chenls/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26 -Wl,-rpath-link=/home/chenls/Desktop/Android-Native-Development/source/helloWorld/obj/local/arm64-v8a /home/chenls/Desktop/Android-Native-Development/source/helloWorld/obj/local/arm64-v8a/objs/helloWorld/helloWorld.o -lgcc -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libgcc_real.a -latomic -Wl,--exclude-libs,libatomic.a -target aarch64-none-linux-android26 -no-canonical-prefixes -Wl,--build-id -nostdlib++ -Wl,--no-undefined -Wl,--fatal-warnings -lc -lm -o /home/chenls/Desktop/Android-Native-Development/source/helloWorld/obj/local/arm64-v8a/helloWorld
You can see from it that the helloWorld. Net is created using clang + + O link to generate helloWorld.
Use of clang
It can be found that clang is used in ndk compilation, and clang is very similar to gcc. It can also use the parameters mentioned above. Let's take a look at the specific operations.
Tip: if the "- v" parameter is added to the following commands, you can also view the specific calling programs and parameters, which are very similar to gcc.
clang pretreatment
Just put the generated file HelloWorld O changed to HelloWorld i. Then add the - E parameter to get the preprocessed file:
/home/chenls/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/bin/clang -MMD -MP -MF /home/chenls/Desktop/Android-Native-Development/source/helloWorld/obj/local/arm64-v8a/objs/helloWorld/helloWorld.o.d -target aarch64-none-linux-android26 -fdata-sections -ffunction-sections -fstack-protector-strong -funwind-tables -no-canonical-prefixes --sysroot /home/chenls/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/sysroot -g -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -D_FORTIFY_SOURCE=2 -fpic -O2 -DNDEBUG -I/home/chenls/Desktop/Android-Native-Development/source/helloWorld/jni -fstack-protector -DANDROID -nostdinc++ -Wformat -Werror=format-security -c /home/chenls/Desktop/Android-Native-Development/source/helloWorld/jni/helloWorld.c -o /home/chenls/Desktop/Android-Native-Development/source/helloWorld/obj/local/arm64-v8a/objs/helloWorld/helloWorld.i -E
clang compilation
Just put the generated file HelloWorld O changed to HelloWorld s. Then add the - S parameter to get the assembly file:
/home/chenls/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/bin/clang -MMD -MP -MF /home/chenls/Desktop/Android-Native-Development/source/helloWorld/obj/local/arm64-v8a/objs/helloWorld/helloWorld.o.d -target aarch64-none-linux-android26 -fdata-sections -ffunction-sections -fstack-protector-strong -funwind-tables -no-canonical-prefixes --sysroot /home/chenls/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/sysroot -g -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -D_FORTIFY_SOURCE=2 -fpic -O2 -DNDEBUG -I/home/chenls/Desktop/Android-Native-Development/source/helloWorld/jni -fstack-protector -DANDROID -nostdinc++ -Wformat -Werror=format-security -c /home/chenls/Desktop/Android-Native-Development/source/helloWorld/jni/helloWorld.c -o /home/chenls/Desktop/Android-Native-Development/source/helloWorld/obj/local/arm64-v8a/objs/helloWorld/helloWorld.s -S
Summary of NDK build compilation process
During ndk compilation, clang is called internally. Clang is similar to gcc and can use the same parameters to track the compilation process.