zoukankan      html  css  js  c++  java
  • 【C/C++笔记】Makefile

    相关资料:

    实践记录:

    1、查看 g++ / gcc 的版本:

    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 # 详细版本

     2、You can get the help manual via the --help option. 

    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

    3、You can read the GCC manual pages (or man pages) via the man utility:

    root@xkfx:~# man gcc
    No manual entry for gcc
    See 'man 7 undocumented' for help when manual pages are not available.

    4、More GCC Compiler Options

    root@xkfx:~/labs# g++ hello.cpp -Wall -g

    -Wall: prints "allwarning messages. 

    -g: generates additional symbolic debuggging information for use with gdb debugger.

    5、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,

     6、对于多个源文件编译成一个可执行文件,比较好的实践是,分开编译再链接,这样修改一个源文件就不必再编译所有别的源文件:

    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 然后重新链接就可以了。

    7、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

    8、GCC Compilation Process 图片来自相关资料之二:

    assembly code  汇编代码

    9、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

    10、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

    11、Static Libraries (.lib, .a) vs. Shared Library (.dll, .so)

    前者是直接把外部代码拷贝进你的代码,然后形成可执行文件。

    后者则是在你的可执行程序跑起来之前,操作系统加载外部代码给你的程序调用。

    因为后者节省空间,内存(好几个程序可以共用一个 share library),GCC 总是会在可能的情况下优先采用动态链接。

    12、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

    13、尝试通过“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.

    14、Try running the compilation in verbose mode (-v) to study the library-paths (-L) and libraries (-l) used in your system:

    15、通过 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命令就简单介绍到这里了, 虽然简单, 但很实用, 故不可不知。

    16、

    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
  • 相关阅读:
    学习笔记Jmail收发邮件
    ModalPopup
    学习笔记:UpdatePanel控件
    转AjaxControlToolkit的安装与使用详解
    转linq中的Single()、First()、Take(1) LINQ 标准的查询操作符 排序 orderby、thenby、Take
    转Global.asax文件
    转<%%>、<%=%>、<%$%>、<%@%>的区别
    C++文件包含处理—#include
    GISer学习之道(转载)
    OSG中的示例程序简介
  • 原文地址:https://www.cnblogs.com/xkxf/p/8594251.html
Copyright © 2011-2022 走看看