GCC and Make ( A simple tutorial, teaches u how to use gcc and make.)html
GNU make
c++
一、查看 g++ / gcc 的版本:vim
root@xkfx:~# gcc --version gcc (Debian 4.9.2-10) 4.9.2 Copyright (C) 2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. root@xkfx:~# gcc -v # 詳細版本
二、You can get the help manual via the --help
option. windows
root@xkfx:~# gcc --help Usage: gcc [options] file... Options: -pass-exit-codes Exit with highest error code from a phase --help Display this information --target-help Display target specific command line options --help={common|optimizers|params|target|warnings|[^]{joined|separate|undocumented}}[,...] Display specific types of command line options (Use '-v --help' to display command line options of sub-processes) --version Display compiler version information -dumpspecs Display all of the built in spec strings -dumpversion Display the version of the compiler -dumpmachine Display the compiler's target processor -print-search-dirs Display the directories in the compiler's search path -print-libgcc-file-name Display the name of the compiler's companion library -print-file-name=<lib> Display the full path to library <lib> -print-prog-name=<prog> Display the full path to compiler component <prog> -print-multiarch Display the target's normalized GNU triplet, used as a component in the library path -print-multi-directory Display the root directory for versions of libgcc -print-multi-lib Display the mapping between command line options and multiple library search directories -print-multi-os-directory Display the relative path to OS libraries -print-sysroot Display the target libraries directory -print-sysroot-headers-suffix Display the sysroot suffix used to find headers -Wa,<options> Pass comma-separated <options> on to the assembler -Wp,<options> Pass comma-separated <options> on to the preprocessor -Wl,<options> Pass comma-separated <options> on to the linker -Xassembler <arg> Pass <arg> on to the assembler -Xpreprocessor <arg> Pass <arg> on to the preprocessor -Xlinker <arg> Pass <arg> on to the linker -save-temps Do not delete intermediate files -save-temps=<arg> Do not delete intermediate files -no-canonical-prefixes Do not canonicalize paths when building relative prefixes to other gcc components -pipe Use pipes rather than intermediate files -time Time the execution of each subprocess -specs=<file> Override built-in specs with the contents of <file> -std=<standard> Assume that the input sources are for <standard> --sysroot=<directory> Use <directory> as the root directory for headers and libraries -B <directory> Add <directory> to the compiler's search paths -v Display the programs invoked by the compiler -### Like -v but options quoted and commands not executed -E Preprocess only; do not compile, assemble or link -S Compile only; do not assemble or link -c Compile and assemble, but do not link -o <file> Place the output into <file> -pie Create a position independent executable -shared Create a shared library -x <language> Specify the language of the following input files Permissible languages include: c c++ assembler none 'none' means revert to the default behavior of guessing the language based on the file's extension Options starting with -g, -f, -m, -O, -W, or --param are automatically passed on to the various sub-processes invoked by gcc. In order to pass other options on to these processes the -W<letter> options must be used. For bug reporting instructions, please see: <file:///usr/share/doc/gcc-4.9/README.Bugs>.
三、You can read the GCC manual pages (or man pages) via the man
utility:api
root@xkfx:~# man gcc No manual entry for gcc See 'man 7 undocumented' for help when manual pages are not available.
四、More GCC Compiler Optionsapp
root@xkfx:~/labs# g++ hello.cpp -Wall -g
-Wall
: prints "all
" warning messages. less
-g
: generates additional symbolic debuggging information for use with gdb
debugger.
五、Compile and Link Separately
The above command compile the source file into object file and link
with other object files (system library) into executable in one step. You may separate compile and link in two steps as follows:
root@xkfx:~/labs# ls hello.cpp root@xkfx:~/labs# g++ hello.cpp -c -Wall -g // Compile-only with -c option
root@xkfx:~/labs# ls
hello.cpp hello.o
root@xkfx:~/labs# g++ hello.o -o hello.exe -g // Link object file(s) into an executable root@xkfx:~/labs# ls hello.cpp hello.exe hello.o root@xkfx:~/labs# ./hello.exe hello,
六、對於多個源文件編譯成一個可執行文件,比較好的實踐是,分開編譯再連接,這樣修改一個源文件就沒必要再編譯全部別的源文件:
root@xkfx:~/labs# g++ hello.cpp hello2.cpp -o hello -g /tmp/ccGNmFaS.o: In function `main': /root/labs/hello2.cpp:5: multiple definition of `main' /tmp/ccsm0AxM.o:/root/labs/hello.cpp:5: first defined here collect2: error: ld returned 1 exit status root@xkfx:~/labs# g++ hello.cpp hello2.cpp -o hello /tmp/cc1ASkoC.o: In function `main': hello2.cpp:(.text+0x0): multiple definition of `main' /tmp/cc4ImNYi.o:hello.cpp:(.text+0x0): first defined here collect2: error: ld returned 1 exit status
上面是錯誤的示範,順即可以看到有 -g 和沒 -g 的區別,正確姿式:
root@xkfx:~/labs# g++ hello.cpp -c root@xkfx:~/labs# g++ hello2.cpp -c root@xkfx:~/labs# g++ hello.o hello2.o -o hello hello2.o: In function `main': hello2.cpp:(.text+0x0): multiple definition of `main' hello.o:hello.cpp:(.text+0x0): first defined here collect2: error: ld returned 1 exit status
這樣一旦修改了 hello.cpp 就只須要再次編譯 hello.cpp 而後從新連接就能夠了。
七、To compile and link C/C++ program into a shared library (".dll"
in Windows, ".so"
in Unixes), use -shared
option. Read "Java Native Interface" for example.
因而順手查了下 JNI 是怎麼回事:
jNi就是java調用本地方法的技術,最簡單的來講,java運行一個程序須要要和不一樣的系統平臺打交道,在windows裏就是和windows平臺底層打交道,mac就是要和mac打交道,jvm就是經過大量的jni技術使得java可以在不一樣平臺上運行。而使用了這技術的一個標誌就是native,若是一個類裏的一個方法被native修飾,那就說明這個方法是jni來實現的,他是經過本地系統api裏的方法來實現的。固然這個本地方法多是c或者C++,固然也多是別的語言。jni是java跨平臺的基礎,jvm經過在不一樣系統上調用不一樣的本地方法使得jvm能夠在不一樣平臺間移植。
當前你本身也能夠用jni來寫一些程序,這種基本上是你之前使用了其餘語言完成了一些功能,可是你有要用java來重複這些功能的時候,就可使用jni來完成了。不過帶來的問題就是,若是你的那個本地方法是依託於本地操做系統的話,那就意味着你的java程序也只能在這一個系統上運行了。因此jni就使得java很容易限定在了一個系統平臺上,而jdk的做用在於他提供一個規範,這個規範就是包含了不少native方法,這些方法都是要本地操做系統來實現的,而實現了這些本地方法的操做系統就能夠移植java平臺了。 ------ 來自 baidu daay1986
八、GCC Compilation Process 圖片來自相關資料之二:
assembly code 彙編代碼
九、You can see the detailed compilation process by enabling -v
(verbose) option. 詳細;囉嗦
root@xkfx:~/labs# g++ hello.cpp -v Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.9/lto-wrapper Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Debian 4.9.2-10' --with-bugurl=file:///usr/share/doc/gcc-4.9/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.9 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.9 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.9-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.9-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.9-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --with-arch-32=i586 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.9.2 (Debian 4.9.2-10) COLLECT_GCC_OPTIONS='-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64' /usr/lib/gcc/x86_64-linux-gnu/4.9/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE hello.cpp -quiet -dumpbase hello.cpp -mtune=generic -march=x86-64 -auxbase hello -version -o /tmp/ccqPyWpO.s GNU C++ (Debian 4.9.2-10) version 4.9.2 (x86_64-linux-gnu) compiled by GNU C version 4.9.2, GMP version 6.0.0, MPFR version 3.1.2-p3, MPC version 1.0.2 GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/4.9" ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../x86_64-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /usr/include/c++/4.9 /usr/include/x86_64-linux-gnu/c++/4.9 /usr/include/c++/4.9/backward /usr/lib/gcc/x86_64-linux-gnu/4.9/include /usr/local/include /usr/lib/gcc/x86_64-linux-gnu/4.9/include-fixed /usr/include/x86_64-linux-gnu /usr/include End of search list. GNU C++ (Debian 4.9.2-10) version 4.9.2 (x86_64-linux-gnu) compiled by GNU C version 4.9.2, GMP version 6.0.0, MPFR version 3.1.2-p3, MPC version 1.0.2 GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: ff85870e740eb08c48a56c2c170390f8 COLLECT_GCC_OPTIONS='-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64' as -v --64 -o /tmp/cc9l3HyT.o /tmp/ccqPyWpO.s GNU assembler version 2.25 (x86_64-linux-gnu) using BFD version (GNU Binutils for Debian) 2.25 COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.9/:/usr/lib/gcc/x86_64-linux-gnu/4.9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.9/:/usr/lib/gcc/x86_64-linux-gnu/ LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.9/:/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS='-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64' /usr/lib/gcc/x86_64-linux-gnu/4.9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/4.9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/4.9/lto-wrapper -plugin-opt=-fresolution=/tmp/ccVqDgIY.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.9/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.9 -L/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../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/4.9/../../.. /tmp/cc9l3HyT.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/4.9/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crtn.o
十、You can use the -Dname
option to define a macro, or -Dname=value
to define a macro with a value. The value
should be enclosed in double quotes if it contains spaces. 例如說:
#include <iostream> using namespace std; int main() { cout << HELLO << endl; return 0; }
root@xkfx:~/labs# g++ hello.cpp -DHELLO=123 -g root@xkfx:~/labs# ./a.out 123
十一、Static Libraries (.lib, .a) vs. Shared Library (.dll, .so)
前者是直接把外部代碼拷貝進你的代碼,而後造成可執行文件。
後者則是在你的可執行程序跑起來以前,操做系統加載外部代碼給你的程序調用。
由於後者節省空間,內存(好幾個程序能夠共用一個 share library),GCC 老是會在可能的狀況下優先採用動態連接。
十二、Searching for Header Files and Libraries (-I, -L and -l)
When compiling the program, the compiler needs the header files to compile the source codes; the linker needs the libraries to resolve external references from other object files or libraries. The compiler and linker will not find the headers/libraries unless you set the appropriate options, which is not obvious for first-time user. For each of the headers used in your source (via #include directives), the compiler searches the so-called include-paths for these headers. The include-paths are specified via -Idir option (or environment variable CPATH). Since the header's filename is known (e.g., iostream.h, stdio.h), the compiler only needs the directories. The linker searches the so-called library-paths for libraries needed to link the program into an executable. The library-path is specified via -Ldir option (uppercase 'L' followed by the directory path) (or environment variable LIBRARY_PATH). In addition, you also have to specify the library name. In Unixes, the library libxxx.a is specified via -lxxx option (lowercase letter 'l', without the prefix "lib" and ".a" extension). In Windows, provide the full name such as -lxxx.lib. The linker needs to know both the directories as well as the library names. Hence, two options need to be specified.
1三、嘗試經過「cpp -v」列出「GNU C預處理器」使用的系統中的默認 include路徑:
root@xkfx:~/labs# cpp -v // .......................... #include "..." search starts here: #include <...> search starts here: /usr/lib/gcc/x86_64-linux-gnu/4.9/include /usr/local/include /usr/lib/gcc/x86_64-linux-gnu/4.9/include-fixed /usr/include/x86_64-linux-gnu /usr/include End of search list.
1四、Try running the compilation in verbose mode (-v
) to study the library-paths (-L
) and libraries (-l
) used in your system:
1五、經過 file 查看文件類型:
root@xkfx:~/labs# file hello.o hello.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped root@xkfx:~/labs# file a.out a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=242ba76e8db35435fd054bf0d930f6ed2ca9375c, not stripped root@xkfx:~/labs# file hello.cpp hello.cpp: C source, ASCII text
經過 nm 列出特性文件中的符號信息(像是函數啥的), linux中的nm命令簡介 這篇文章很生動,。(附帶動態連接庫、靜態連接庫怎麼操做)
經過 ldd 列出動態連接庫,同一位做者 linux中的ldd命令簡介
在實際linux開發與調試中, 要常常查看動態庫依賴關係, ldd用得仍是比較多的, 特別是出現故障的時候。OK, ldd命令就簡單介紹到這裏了, 雖然簡單, 但很實用, 故不可不知。
1六、
root@xkfx:~/labs# vim hello.c root@xkfx:~/labs# vim makefile root@xkfx:~/labs# ls hello.c makefile
root@xkfx:~/labs# make gcc -c hello.c gcc -o hello.exe hello.o root@xkfx:~/labs# ls hello.c hello.exe hello.o makefile
makefile 內容:
all: hello.exe hello.exe: hello.o gcc -o hello.exe hello.o hello.o: hello.c gcc -c hello.c clean: rm hello.o hello.exe
make 指令在沒有目標的時候默認就是 make all .
A rule consists of 3 parts: a target, a list of pre-requisites and a command (目標,前提條件,命令), as follows:
target: pre-req-1 pre-req-2 ... command
command 前面必須是 Tab 而不能是 Space
makefile 的內容定義了 make 指令在該目錄下的行爲,
例如輸入 make clean , clean 是目標,沒有先決條件,那麼就執行命令 rm hello.o hello.exe
輸入 make all ,先決條件是 hello.exe 若是沒發現,那麼就搜索指令去製造它。
在製造 hello.exe 的時候,會檢查 hello.o 是否是「新鮮」,(大概是比較建立文檔的時間?),若是「新鮮」纔會製造,不然的話:
root@xkfx:~/labs# make make: Nothing to be done for 'all'.
如今想正常跑 make,一個方法是 make clean 一下:
root@xkfx:~/labs# make clean rm hello.o hello.exe root@xkfx:~/labs# ls hello.c makefile root@xkfx:~/labs# make gcc -c hello.c gcc -o hello.exe hello.o
另外一個方法就是讓 hello.c 變「新鮮」(不用修改,打開後從新 wq保存一下就能夠了。):
root@xkfx:~/labs# ls hello.c hello.exe hello.o makefile root@xkfx:~/labs# vim hello.c root@xkfx:~/labs# make gcc -c hello.c gcc -o hello.exe hello.o