C/C++笔记 #035# Makefile
相关资料:
- Understanding roles of CMake, make and GCC
GCC and Make ( A simple tutorial, teaches u how to use gcc and make.)
实践记录:
1、查看 g++ / gcc 的版本:
root@xkfx:~# gcc --version
gcc (Debian 4.9.-) 4.9.
Copyright (C) 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>.
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 "all
" warning 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:: multiple definition of `main'
/tmp/ccsm0AxM.o:/root/labs/hello.cpp:: first defined here
collect2: error: ld returned 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 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 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. (Debian 4.9.-)
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- -auxbase hello -version -o /tmp/ccqPyWpO.s
GNU C++ (Debian 4.9.-) version 4.9. (x86_64-linux-gnu)
compiled by GNU C version 4.9., GMP version 6.0., MPFR version 3.1.-p3, MPC version 1.0.
GGC heuristics: --param ggc-min-expand= --param ggc-min-heapsize=
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.-) version 4.9. (x86_64-linux-gnu)
compiled by GNU C version 4.9., GMP version 6.0., MPFR version 3.1.-p3, MPC version 1.0.
GGC heuristics: --param ggc-min-expand= --param ggc-min-heapsize=
Compiler executable checksum: ff85870e740eb08c48a56c2c170390f8
COLLECT_GCC_OPTIONS='-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
as -v -- -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-.so. /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
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 ;
}
root@xkfx:~/labs# g++ hello.cpp -DHELLO= -g
root@xkfx:~/labs# ./a.out
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.
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 -bit LSB relocatable, x86-, version (SYSV), not stripped
root@xkfx:~/labs# file a.out
a.out: ELF -bit LSB executable, x86-, version (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-.so., for GNU/Linux 2.6., 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- pre-req- ...
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
C/C++笔记 #035# Makefile的更多相关文章
- Linux 编程学习笔记----动笔makefile档
Befroe Beginning. 在设置暑假的plan ,关于Linux的书籍如今在看的是ALP和Linux高级程序设计(杨宗德)第三版.在计划中的是Linux高级环境编程. 如今開始关于Linux ...
- 《笨办法学C》笔记之Makefile
使用gcc编译C语言源码 在Linux系统中,C语言源码需要用gcc编译为二进制可执行文件,才能够运行. $ gcc test.c -o test 这句命令就将test.c文件编译为test二进制可执 ...
- [国嵌笔记][017][Makefile工程管理]
Makefile的用途 1.make能够使整个程序的编译.链接只需一个命令就可以完成 2.make的工作主要依赖于Makefile的文件.Makefile文件描述了整个程序的编译.链接等规则,使之自动 ...
- makefile笔记9 - makefile隐含规则
在我们使用 Makefile 时,有一些我们会经常使用,而且使用频率非常高的东西,比如,我们编译C/C++的源程序为中间目标文件(Unix 下是[.o]文件,Windows 下是[.obj]文件). ...
- makefile笔记10 - makefile 函数库文件
函数库文件也就是对 Object 文件(程序编译的中间文件)的打包文件.在 Unix 下,一般是由命令"ar"来完成打包工作. 一.函数库文件的成员 一个函数库文件由多个文件组成. ...
- makefile笔记7 - makefile函数
在 Makefile 中可以使用函数来处理变量,从而让我们的命令或是规则更为的灵活和具有智能. make 所支持的函数也不算很多,不过已经足够我们的操作了.函数调用后,函数的返回值可以当做变量来使用. ...
- makefile笔记6 - makefile条件判断
使用条件判断,可以让 make 根据运行时的不同情况选择不同的执行分支.条件表达式可以是比较变量的值,或是变量和常量的值. 一.示例 下面的例子,判断\(\$\)(CC)变量是否"gcc&q ...
- makefile笔记5 - makefile变量
在 Makefile 中的定义的变量,就像是 C/C++语言中的宏一样,他代表了一个文本字串,在 Makefile 中执行的时候其会自动原模原样地展开在所使用的地方.其与 C/C++所不同的是,你可以 ...
- makefile笔记4 - makefile命令
每条规则中的命令和操作系统 Shell 的命令行是一致的. make 会一按顺序一条一条的执行命令,每条命令的开头必须以[Tab]键开头,除非,命令是紧跟在依赖规则后面的分号后的. 在命令行之间中的空 ...
随机推荐
- vue中打包生成可配置文件以便修改接口地址
vue打包上传到服务器之后,如果数据接口域名发生变化,需要手动修改接口地址,在发布的时候也麻烦,于是.. 在打包之后如果有一个json配置文件以便修改那不是方便很多 在网上找了一些方法貌似都是异步请求 ...
- OSS命令行工具ossutil
ossutil工具旨在为您提供一个以命令行方式管理OSS数据的途径.当前版本未提供完整的Bucket和Multipart管理功能,相关功能会在后续版本中开发.如果您需要使用上述功能,建议先使用ossc ...
- iOS ViewControllers 瘦身
https://objccn.io/issue-1-1/ https://juejin.im/user/57ddfba4128fe10064cbb93a 把 Data Source 和其他 Proto ...
- Socket通信的Python实现
Python中实现socket通信,socket通信的服务端比较复杂,而客户端非常简单,所以客户端基本上都是用sockct模块实现,而服务 端用有很多模块可以使用.下面就说一下服务端可使用的模块. 模 ...
- Tomcat的overview界面浅析
Server Locations配置有三个选项(加载位置): 1. Use workspace metadata (does not modify Tomcat installation); 2. U ...
- mysql 数据库的操作
1.数据库的查看 1)查看mysql中所有的数据库 "show databases;" mysql> show databases; +---------------- ...
- What is Druid?
Druid is a data store designed for high-performance slice-and-dice analytics ("OLAP"-style ...
- [py]python自省工具
参考 在日常生活中,自省(introspection)是一种自我检查行为.自省是指对某人自身思想.情绪.动机和行为的检查.伟大的哲学家苏格拉底将生命中的大部分时间用于自我检查,并鼓励他的雅典朋友们也这 ...
- HDU Today(自己的代码不知道哪里错了一直没A抄袭大神的)
http://acm.hdu.edu.cn/showproblem.php?pid=2112 本题题目意思非常简单,麻烦的就是处理一下字符串,这是我能力欠缺的地方 ;} 先把我有乱有麻烦的错误代码贴上 ...
- 字母统计-map
题目描述 输入一行字符串,计算其中A-Z大写字母出现的次数 输入描述: 案例可能有多组,每个案例输入为一行字符串. 输出描述: 对每个案例按A-Z的顺序输出其中大写字母出现的次数. 示例1 输入 复制 ...