C/C++筆記 #035# Makefile

相關資料:

 

實踐記錄:

一、查看 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>.
View Code

三、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 "allwarning 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
View Code

十、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.
View Code

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
相關文章
相關標籤/搜索