GCC and Make Compiling, Linking and Building C/C++ Applications - 1
https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html
1. GCC (GNU Compiler Collection)
1.1 A Brief History and Introduction to GCC
The original GNU C Compiler (GCC) is developed by Richard Stallman, the founder of the GNU Project. Richard Stallman founded the GNU project in 1984 to create a complete Unix-like operating system as free software, to promote freedom and cooperation among computer users and programmers.
最初的 GNU C 编译器 (GCC) 由 GNU 项目的创始人 Richard Stallman 开发。Richard Stallman 于 1984 年创建了 GNU 项目,以创建一个完整的类 Unix 操作系统作为自由软件,以促进计算机用户和程序员之间的自由和合作。
GCC, formerly for GNU C Compiler
, has grown over times to support many languages such as C (gcc), C++ (g++), Objective-C, Objective-C++, Java (gcj), Fortran (gfortran), Ada (gnat), Go (gccgo), OpenMP, Cilk Plus, and OpenAcc. It is now referred to as GNU Compiler Collection
. The mother site for GCC is http://gcc.gnu.org/. The current version is GCC 7.3, released on 2018-01-25.
GCC, formerly for GNU C Compiler
,已经不断发展,支持许多语言,such as C (gcc), C++ (g++), Objective-C, Objective-C++, Java (gcj), Fortran (gfortran), Ada (gnat), Go (gccgo), OpenMP, Cilk Plus, and OpenAcc。它现在被称为 GNU Compiler Collection
。The mother site for GCC is http://gcc.gnu.org/. The current version is GCC 7.3, released on 2018-01-25.
GCC is a key component of so-called GNU Toolchain
, for developing applications and writing operating systems. The GNU Toolchain includes (GCC 是所谓的 GNU 工具链的关键组件,用于开发应用程序和编写操作系统。GNU 工具链包括):
- GNU Compiler Collection (GCC): a compiler suite that supports many languages, such as C/C++ and Objective-C/C++.
- GNU Make: an automation tool for compiling and building applications.
- GNU Binutils: a suite of binary utility tools, including linker and assembler.
- GNU Debugger (GDB).
- GNU Autotools: A build system including Autoconf, Autoheader, Automake and Libtool.
- GNU Bison: a parser generator (similar to lex and yacc).
GCC is portable and run in many operating platforms. GCC (and GNU Toolchain) is currently available on all Unixes. They are also ported to Windows (by Cygwin, MinGW and MinGW-W64). GCC is also a cross-compiler, for producing executables on different platform.
GCC 是可移植的,可在许多操作平台上运行。GCC (和 GNU 工具链) 目前在所有 Unix 上都可用。它们也被移植到 Windows (by Cygwin, MinGW and MinGW-W64)。GCC 也是一个交叉编译器,用于在不同平台上生成可执行文件。
GCC Versions
The various GCC versions are:
- GCC version 1 (1987): Initial version that support C.
- GCC version 2 (1992): supports C++.
- GCC version 3 (2001): incorporating ECGS (Experimental GNU Compiler System), with improve optimization.
- GCC version 4 (2005):
- GCC version 5 (2015):
- GCC Version 6 (2016):
- GCC Version 7 (2017):
C++ Standard Support
There are various C++ standards:
- C++98
- C++11 (aka C++0x)
- C++14 (aka C++1y)
- C++17 (aka C++1z)
- C++2a (next planned standard in 2020)
The default mode is C++98 for GCC versions prior to 6.1, and C++14 for GCC 6.1 and above. You can use command-line flag -std
to explicitly specify the C++ standard. For example,
- -std=c++98, or -std=gnu++98 (C++98 with GNU extensions)
- -std=c++11, or -std=gnu++11 (C++11 with GNU extensions)
- -std=c++14, or -std=gnu++14 (C++14 with GNU extensions), default mode for GCC 6.1 and above.
- -std=c++17, or -std=gnu++17 (C++17 with GNU extensions), experimental.
- -std=c++2a, or -std=gnu++2a (C++2a with GNU extensions), experimental.
incorporate [ɪn'kɔːpəreɪt]:vt. 包含,吸收,体现,把...合并 vi. 合并,混合,组成公司 adj. 合并的,一体化的,组成公司的
also known as,aka [eɪkeɪ'eɪ]:又名,亦称
explicitly [ɪk'splɪsɪtli]:adv. 明确地,明白地
1.2 Installing GCC on Unixes
GNU Toolchain, including GCC, is included in all Unixes. It is the standard compiler for most Unix-like operating systems.
GNU 工具链,包括 GCC,包含在所有 Unix 中。它是大多数类 Unix 操作系统的标准编译器。
1.3 Installing GCC on Mac OS X
Open a Terminal, and enter gcc --version
. If gcc is not installed, the system will prompt you to install gcc.
$ gcc --version
......
Target: x86_64-apple-darwin14.5.0 // 64-bit target codes
Thread model: posix
1.4 Installing GCC on Windows
For Windows, you could either install Cygwin GCC, MinGW GCC or MinGW-W64 GCC. https://www3.ntu.edu.sg/home/ehchua/programming/howto/Cygwin_HowTo.html
- Cygwin GCC: Cygwin is a Unix-like environment and command-line interface for Microsoft Windows. Cygwin is huge and includes most of the Unix tools and utilities. It also included the commonly-used Bash shell.
- MinGW: MinGW (Minimalist GNU for Windows) is a port of the GNU Compiler Collection (GCC) and GNU Binutils for use in Windows. It also included MSYS (Minimal System), which is basically a Bourne shell (bash).
- MinGW-W64: a fork of MinGW that supports both 32-bit and 64-bit windows.
huge [hjuːdʒ]:adj. 巨大的,庞大的,无限的
fork [fɔːk]:n. 叉,餐叉,耙 vt. 叉起,使成叉状 vi. 分叉,分歧
Various GCCs under Cygwin
There are many GCCs under Cygain/MinGW. To differentiate these variations, you need to understand the followings:
- Windows/Intel uses these instruction sets: x86 is a 32-bit instruction set; i868 is a 32-bit enhanced version of x86; x86_64 (or amd64) is a 64-bit instruction set.
- 32-bit compilers/programs can run on 32-bit or 64-bit (backward compatible) Windows, but 64-bit compiler can only run on 64-bit Windows.
- 64-bit compilers may produce target of 32-bit or 64-bit.
- If you use Cygwin’s GCC, the target could be native Windows or Cygwin. If the target is native Windows, the code can be distributed and run under Windows. However, if the target is Cygwin, to distribute, you need to distribute Cygwin runtime environment (cygwin1.dll). This is because Cygwin is a Unix emulator under Windows.
如果您使用 Cygwin 的 GCC,目标可能是本机 Windows 或 Cygwin。如果目标是本机 Windows,则可以在 Windows 下分发和运行代码。但是,如果目标是 Cygwin,要分发,则需要分发 Cygwin 运行时环境 (cygwin1.dll)。这是因为 Cygwin 是 Windows 下的 Unix 模拟器。
MinGW-W64 Target 32/64-bit Native Windows
The MinGW-W64 (a fork of MinGW, available at http://mingw-w64.org/doku.php) supports target of both 32-bit and 64-bit native Windows. You can install MinGW-W64
under Cygwin
by selecting these packages (under devel
category):
- mingw64-x86_64-gcc-core: 64-bit C compiler for target of native 64-bit Windows. The executable is
x86_64-w64-mingw32-gcc
. - mingw64-x86_64-gcc-g++: 64-bit C++ compiler for target of native 64-bit Windows. The executable is
x86_64-w64-mingw32-g++
. - mingw64-i686-gcc-core: 64-bit C compiler for target of native 32-bit Windows. The executable is
i686-w64-mingw32-gcc
. - mingw64-i686-gcc-g++: 64-bit C++ compiler for target of native 32-bit Windows. The executable is
i686-w64-mingw32-g++
.
Notes:
- I suggest you install
mingw64-x86_64-gcc-core
andmingw64-x86_64-gcc-g++
to provide native 64-bit Windows codes, but skipmingw64-i686-gcc-core
andmingw64-i686-gcc-g++
, unless you need to produce 32-bit Windows applications. - For JNI (Java Native Interface) in 64-bit Java, you need to use
x86_64-w64-mingw32-gcc
orx86_64-w64-mingw32-g++
to produce 64-bit native Windows code.
Run the executables and check the versions:
// Target 64-bit native Windows
$ x86_64-w64-mingw32-gcc --version
x86_64-w64-mingw32-gcc (GCC) 6.4.0
$ x86_64-w64-mingw32-gcc -v
Using built-in specs.
COLLECT_GCC=x86_64-w64-mingw32-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-w64-mingw32/6.4.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: .....
Thread model: posix
gcc version 6.4.0 (GCC)
$ x86_64-w64-mingw32-g++ --version
x86_64-w64-mingw32-g++ (GCC) 6.4.0
// Target 32-bit native Windows
$ i686-w64-mingw32-gcc --version
i686-w64-mingw32-gcc (GCC) 6.4.0
$ i686-w64-mingw32-g++ --version
i686-w64-mingw32-g++ (GCC) 6.4.0
Other GCCs in Cygwin
Other GCC packages in Cygwin are:
- gcc-core, gcc-g++: Basic 64-bit C/C++ compiler target 64-bit Cygwin. You probably should install these two packages too. However, to distribute the code produced, you need to distribute Cygwin Runtime Environment (cygwin1.dll). This is because Cygwin is a Unix emulator under Windows.
- cygwin32-gcc-core, cygwin32-gcc-g++: Older 32-bit C/C++ compiler for target 32-bit Cygwin (Obsoleted by gcc-code and gcc-g++?).
- mingw-gcc-core, mingw-gcc-g++: Older MinGW 32-bit C/C++ compiler for 32-bit Windows (Obsoleted by MinGW-W64 packages?).
1.5 Post Installation
Versions
You could display the version of GCC via --version
option:
strong@foreverstrong:~$ gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609
Copyright (C) 2015 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.
strong@foreverstrong:~$
strong@foreverstrong:~$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609
Copyright (C) 2015 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.
strong@foreverstrong:~$
More details can be obtained via -v
option, for example,
strong@foreverstrong:~$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.4.0-6ubuntu1~16.04.9' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --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 --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --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 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.9)
strong@foreverstrong:~$
strong@foreverstrong:~$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.4.0-6ubuntu1~16.04.9' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --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 --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --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 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.9)
strong@foreverstrong:~$
Help
You can get the help manual via the --help
option. For example,
$ gcc --help
Man Pages
You can read the GCC manual pages (or man pages) via the man utility:
$ man gcc
// or
$ man g++
// Press space key for next page, or 'q' to quit.
Reading man pages under CMD or Bash shell can be difficult. You could generate a text file via:
$ man gcc | col -b > gcc.txt
The col utility is needed to strip the backspace. (For Cygwin, it is available in Utils
, util-linux
package.)
需要 col 实用程序来剥离退格。
Alternatively, you could look for an online man pages, e.g., https://linux.die.net/man/1/gcc.
The GCC man pages are kept under usr/share/man/man1
.
strong@foreverstrong:~$ whereis gcc
gcc: /usr/bin/gcc /usr/lib/gcc /usr/share/man/man1/gcc.1.gz
strong@foreverstrong:~$
strong@foreverstrong:~$ whereis g++
g++: /usr/bin/g++ /usr/share/man/man1/g++.1.gz
strong@foreverstrong:~$
1.6 Getting Started
The GNU C and C++ compiler are called gcc and g++, respectively.
GNU C 和 C++ 编译器分别称为 gcc 和 g++。
Compile/Link a Simple C Program - hello.c
Below is the Hello-world C program hello.c:
// hello.c
#include <stdio.h>
int main() {
printf("Hello, world!\n");
return 0;
}
To compile the hello.c:
> gcc hello.c
// Compile and link source file hello.c into executable a.exe (Windows) or a (Unixes)
strong@foreverstrong:~/Desktop/hello-world$ ll
total 12
drwxrwxr-x 2 strong strong 4096 Sep 19 11:09 ./
drwxr-xr-x 9 strong strong 4096 Sep 19 11:16 ../
-rw-rw-r-- 1 strong strong 93 Sep 19 11:09 hello.c
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ cat hello.c
// hello.c
#include <stdio.h>
int main() {
printf("Hello, world!\n");
return 0;
}
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ gcc hello.c
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ ll
total 24
drwxrwxr-x 2 strong strong 4096 Sep 19 11:17 ./
drwxr-xr-x 9 strong strong 4096 Sep 19 11:16 ../
-rwxrwxr-x 1 strong strong 8600 Sep 19 11:17 a.out*
-rw-rw-r-- 1 strong strong 93 Sep 19 11:09 hello.c
strong@foreverstrong:~/Desktop/hello-world$
The default output executable is called a.exe
(Windows) or a.out
(Unixes and Mac OS X).
To run the program:
// (Windows) In CMD shell
> a
// (Unixes / Mac OS X) In Bash Shell - include the current path (./)
$ chmod a+x a.out
$ ./a.out
strong@foreverstrong:~/Desktop/hello-world$ ll
total 24
drwxrwxr-x 2 strong strong 4096 Sep 19 11:17 ./
drwxr-xr-x 9 strong strong 4096 Sep 19 11:16 ../
-rwxrwxr-x 1 strong strong 8600 Sep 19 11:17 a.out*
-rw-rw-r-- 1 strong strong 93 Sep 19 11:09 hello.c
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ ./a.out
Hello, world!
strong@foreverstrong:~/Desktop/hello-world$
Notes for Unixes and Bash Shell:
- In Bash shell, the default PATH does not include the current working directory. Hence, you need to include the current path (./) in the command. (Windows include the current directory in the PATH automatically; whereas Unixes do not - you need to include the current directory explicitly in the PATH.)
在 Bash shell 中,默认 PATH 不包含当前工作目录。因此,您需要在命令中包含当前路径 (./)。(Windows 自动包含 PATH 中的当前目录,而 Unix 则不包括 - 您需要在 PATH 中明确包含当前目录。) - You also need to include the file extension, if any, i.e.,
./a.out
.
您还需要包含文件扩展名。 - In Unixes, the output file could be
a.out
or simplya
. Furthermore, you need to assign executable file-mode (x) to the executable filea.out
, via commandchmod a+x filename
(add executable file-mode+x
to all usersa+x
).
在 Unix 中,输出文件可以是a.out
或简称为a
。 此外,您需要通过命令chmod a+x filename
将可执行文件模式 (x) 分配给可执行文件a.out
(将可执行文件模式+x
添加到所有用户a+x
)。
To specify the output filename, use -o
option (要指定输出文件名,请使用 -o
选项):
// (Windows) In CMD shell
> gcc -o hello.exe hello.c
// Compile and link source file hello.c into executable hello.exe
> hello
// Execute hello.exe under CMD shell
// (Unixes / Mac OS X) In Bash shell
$ gcc -o hello hello.c
$ chmod a+x hello
$ ./hello
strong@foreverstrong:~/Desktop/hello-world$ ll
total 12
drwxrwxr-x 2 strong strong 4096 Sep 19 11:23 ./
drwxr-xr-x 9 strong strong 4096 Sep 19 11:16 ../
-rw-rw-r-- 1 strong strong 93 Sep 19 11:09 hello.c
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ gcc -o hello hello.c
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ ll
total 24
drwxrwxr-x 2 strong strong 4096 Sep 19 11:24 ./
drwxr-xr-x 9 strong strong 4096 Sep 19 11:16 ../
-rwxrwxr-x 1 strong strong 8600 Sep 19 11:24 hello*
-rw-rw-r-- 1 strong strong 93 Sep 19 11:09 hello.c
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ ./hello
Hello, world!
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ ll
total 24
drwxrwxr-x 2 strong strong 4096 Sep 19 11:24 ./
drwxr-xr-x 9 strong strong 4096 Sep 19 11:16 ../
-rwxrwxr-x 1 strong strong 8600 Sep 19 11:24 hello*
-rw-rw-r-- 1 strong strong 93 Sep 19 11:09 hello.c
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ ./hello
Hello, world!
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ hello
The program 'hello' can be found in the following packages:
* hello
* hello-traditional
Try: sudo apt install <selected package>
strong@foreverstrong:~/Desktop/hello-world$
NOTE for Unixes:
- In Unixes, we typically omit the .exe file extension (meant for Windows only), and simply name the output executable as hello (via command
gcc -o hello hello.c
).
在 Unix 中,我们通常省略 .exe 文件扩展名 (仅适用于 Windows),只需将输出可执行文件命名为 hello (通过命令gcc -o hello hello.c
)。 - You need to assign executable file mode via command
chmod a+x hello
.
您需要通过命令chmod a + x hello
分配可执行文件模式。
Compile/Link a Simple C++ Program - hello.cpp
// hello.cpp
#include <iostream>
using namespace std;
int main() {
cout << "Hello, world!" << endl;
return 0;
}
You need to use g++ to compile C++ program, as follows. We use the -o
option to specify the output file name.
您需要使用 g++ 来编译 C++ 程序,如下所示。我们使用 -o
选项指定输出文件名。
// (Windows) In CMD shell
> g++ -o hello.exe hello.cpp
// Compile and link source hello.cpp into executable hello.exe
> hello
// Execute under CMD shell
// (Unixes / Mac OS X) In Bash shell
$ g++ -o hello hello.cpp
$ chmod a+x hello
$ ./hello
strong@foreverstrong:~/Desktop/hello-world$ ll
total 16
drwxrwxr-x 2 strong strong 4096 Sep 19 11:39 ./
drwxr-xr-x 9 strong strong 4096 Sep 19 11:16 ../
-rw-rw-r-- 1 strong strong 93 Sep 19 11:09 hello.c
-rw-rw-r-- 1 strong strong 121 Sep 19 11:39 hello.cpp
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ cat hello.cpp
// hello.cpp
#include <iostream>
using namespace std;
int main() {
cout << "Hello, world!" << endl;
return 0;
}
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ g++ -o hello hello.cpp
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ ll
total 28
drwxrwxr-x 2 strong strong 4096 Sep 19 11:42 ./
drwxr-xr-x 9 strong strong 4096 Sep 19 11:16 ../
-rwxrwxr-x 1 strong strong 9216 Sep 19 11:42 hello*
-rw-rw-r-- 1 strong strong 93 Sep 19 11:09 hello.c
-rw-rw-r-- 1 strong strong 121 Sep 19 11:39 hello.cpp
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ ./hello
Hello, world!
strong@foreverstrong:~/Desktop/hello-world$
More GCC Compiler Options
A few commonly-used GCC compiler options are:
$ g++ -Wall -g -o Hello.exe Hello.cpp
- -o: specifies the output executable filename. (指定输出可执行文件名。)
- -Wall: prints
all
Warning messages. - -g: generates additional symbolic debuggging information for use with gdb debugger. (生成其他符号调试信息以与 gdb 调试器一起使用。)
Compile and Link Separately
The above command compile the source file into object file and link with other object files and system libraries into executable in one step. You may separate compile and link in two steps as follows:
上面的命令将源文件编译成目标文件,并在一步中将其他目标文件和系统库链接成可执行文件。您可以通过以下两个步骤分离编译和链接:
// Compile-only with -c option
> g++ -c -Wall -g Hello.cpp
// Link object file(s) into an executable
> g++ -g -o Hello.exe Hello.o
strong@foreverstrong:~/Desktop/hello-world$ ll
total 16
drwxrwxr-x 2 strong strong 4096 Sep 19 11:51 ./
drwxr-xr-x 9 strong strong 4096 Sep 19 11:16 ../
-rw-rw-r-- 1 strong strong 93 Sep 19 11:09 hello.c
-rw-rw-r-- 1 strong strong 121 Sep 19 11:39 hello.cpp
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ g++ -c -Wall -g hello.cpp
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ ll
total 40
drwxrwxr-x 2 strong strong 4096 Sep 19 11:51 ./
drwxr-xr-x 9 strong strong 4096 Sep 19 11:16 ../
-rw-rw-r-- 1 strong strong 93 Sep 19 11:09 hello.c
-rw-rw-r-- 1 strong strong 121 Sep 19 11:39 hello.cpp
-rw-rw-r-- 1 strong strong 22072 Sep 19 11:51 hello.o
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ g++ -g -o hello hello.o
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ ll
total 60
drwxrwxr-x 2 strong strong 4096 Sep 19 11:52 ./
drwxr-xr-x 9 strong strong 4096 Sep 19 11:16 ../
-rwxrwxr-x 1 strong strong 20232 Sep 19 11:52 hello*
-rw-rw-r-- 1 strong strong 93 Sep 19 11:09 hello.c
-rw-rw-r-- 1 strong strong 121 Sep 19 11:39 hello.cpp
-rw-rw-r-- 1 strong strong 22072 Sep 19 11:51 hello.o
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ ./hello
Hello, world!
strong@foreverstrong:~/Desktop/hello-world$
The options are:
- -c: Compile into object file
Hello.o
. By default, the object file has the same name as the source file with extension of.o
(there is no need to specify -o option). No linking with other object files or libraries.
编译成目标文件Hello.o
。默认情况下,目标文件的名称与源文件的名称相同,扩展名为.o
(不需要指定 -o 选项)。没有链接到其他目标文件或库。 - Linking is performed when the input file are object files
.o
(instead of source file.cpp
or.c
). GCC uses a separate linker program (called ld.exe) to perform the linking.
当输入文件是目标文件.o
(而不是源文件.cpp
或.c
) 时,执行链接。GCC 使用单独的链接器程序 (称为 ld.exe) 来执行链接。
Compile and Link Multiple Source Files
Suppose that your program has two source files: file1.cpp, file2.cpp. You could compile all of them in a single command:
> g++ -o myprog.exe file1.cpp file2.cpp
However, we usually compile each of the source files separately into object file, and link them together in the later stage. In this case, changes in one file does not require re-compilation of the other files.
但是,我们通常将每个源文件分别编译到目标文件中,并在后面的阶段将它们链接在一起。在这种情况下,一个文件中的更改不需要重新编译其他文件。
> g++ -c file1.cpp
> g++ -c file2.cpp
> g++ -o myprog.exe file1.o file2.o
Compile into a Shared Library
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.
1.7 GCC Compilation Process
GCC compiles a C/C++ program into executable in 4 steps as shown in the above diagram. For example, a gcc -o hello.exe hello.c
is carried out as follows:
1. Pre-processing: via the GNU C Preprocessor (cpp.exe), which includes the headers (#include) and expands the macros (#define).
> cpp hello.c > hello.i
The resultant intermediate file hello.i
contains the expanded source code. (生成的中间文件 hello.i
包含扩展的源代码。)
2. Compilation: The compiler compiles the pre-processed source code into assembly code for a specific processor.
> gcc -S hello.i
The -S
option specifies to produce assembly code, instead of object code. The resultant assembly file is hello.s
. (-S
选项指定生成汇编代码,而不是目标代码。生成的程序文件是 hello.s
。)
3. Assembly: The assembler (as.exe) converts the assembly code into machine code in the object file hello.o
.
> as -o hello.o hello.s
4. Linker: Finally, the linker (ld.exe) links the object code with the library code to produce an executable file hello.exe
.
> ld -o hello.exe hello.o ...libraries...
Verbose Mode (-v)
You can see the detailed compilation process by enabling -v
(verbose) option. For example,
您可以通过启用 -v
(详细) 选项来查看详细的编译过程。
> gcc -v -o hello.exe hello.c
Defining Macro (-D)
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.
您可以使用 -Dname
选项定义宏,或使用 -Dname=value
来定义带值的宏。如果值包含空格,则应将其括在双引号中。
expand [ɪk'spænd; ek-]:vt. 扩张,使膨胀,详述 vi. 发展,张开,展开
1.8 Headers (.h), Static Libraries (.lib, .a) and Shared Library (.dll, .so)
Static Library vs. Shared Library
A library is a collection of pre-compiled object files that can be linked into your programs via the linker. Examples are the system functions such as printf() and sqrt().
库是预编译目标文件的集合,可以通过链接器链接到程序中。例如 printf() and sqrt() 等系统函数。
There are two types of external libraries: static library and shared library. (外部库有两种类型:静态库和共享库。)
- A static library has file extension of
.a
(archive file) in Unixes or.lib
(library) in Windows. When your program is linked against a static library, the machine code of external functions used in your program is copied into the executable. A static library can be created via the archive programar.exe
.
静态库的文件扩展名为 Unix 中的.a
(存档文件) 或 Windows 中的.lib
(库)。当程序链接到静态库时,程序中使用的外部函数的机器代码将复制到可执行文件中。 可以通过归档程序ar.exe
创建静态库。 - A shared library has file extension of
.so
(shared objects) in Unixes or.dll
(dynamic link library) in Windows. When your program is linked against a shared library, only a small table is created in the executable. Before the executable starts running, the operating system loads the machine code needed for the external functions - a process known as dynamic linking. Dynamic linking makes executable files smaller and saves disk space, because one copy of a library can be shared between multiple programs. Furthermore, most operating systems allows one copy of a shared library in memory to be used by all running programs, thus, saving memory. The shared library codes can be upgraded without the need to recompile your program.
共享库的文件扩展名为 Unix 中的.so
(共享对象) 或 Windows 中的.dll
(动态链接库)。当您的程序链接到共享库时,只在可执行文件中创建一个小表。在可执行文件开始运行之前,操作系统会加载外部函数所需的机器代码 - 称为动态链接的过程。动态链接使可执行文件更小并节省磁盘空间,因为可以在多个程序之间共享库的一个副本。此外,大多数操作系统允许所有正在运行的程序使用内存中共享库的一个副本,从而节省内存。无需重新编译程序即可升级共享库代码。
Because of the advantage of dynamic linking, GCC, by default, links to the shared library if it is available.
由于动态链接的优点,默认情况下,GCC 链接到共享库 (如果可用)。
You can list the contents of a library via nm filename
.
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.
对于源中使用的每个头文件 (通过 #include 指令),编译器会搜索这些头文件的所谓 include-paths。include-paths 通过 -Idir
选项 (或环境变量 CPATH) 指定。由于头文件名是已知的 (e.g., iostream.h, stdio.h),编译器只需要这些目录。
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.
链接器在所谓的库路径中搜索将程序链接到可执行文件所需的库。库路径通过 -Ldir
选项指定 (大写 L
后跟目录路径) (或环境变量 LIBRARY_PATH)。此外,还必须指定库名称。在 Unixes 中,库 libxxx.a 是通过 -lxxx 选项指定的 (小写字母 l
,没有前缀 lib
和 .a
扩展名)。在 Windows 中,提供全名,例如 -lxxx.lib。链接器需要知道目录以及库名称。因此,需要指定两个选项。
Default Include-paths, Library-paths and Libraries
Try list the default include-paths in your system used by the GNU C Preprocessor
via cpp -v
(尝试通过 cpp -v
列出 GNU C Preprocessor
使用的系统中的默认包含路径):
> cpp -v
......
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/x86_64-pc-cygwin/6.4.0/include
/usr/include
/usr/lib/gcc/x86_64-pc-cygwin/6.4.0/../../../../lib/../include/w32api
Try running the compilation in verbose mode (-v) to study the library-paths (-L) and libraries (-l) used in your system (尝试以详细模式 (-v) 运行编译,以研究系统中使用的库路径 (-L) 和库 (-l)):
> gcc -v -o hello.exe hello.c
......
-L/usr/lib/gcc/x86_64-pc-cygwin/6.4.0
-L/usr/x86_64-pc-cygwin/lib
-L/usr/lib
-L/lib
-lgcc_s // libgcc_s.a
-lgcc // libgcc.a
-lcygwin // libcygwin.a
-ladvapi32 // libadvapi32.a
-lshell32 // libshell32.a
-luser32 // libuser32.a
-lkernel32 // libkernel32.a
Eclipse CDT: In Eclipse CDT, you can set the include paths, library paths and libraries by right-click on the project ⇒ Properties ⇒ C/C++ General ⇒ Paths and Symbols ⇒ Under tabs Includes
, Library Paths
and Libraries
. The settings are applicable to the selected project only.
这些设置仅适用于所选项目。
1.9 GCC Environment Variables
GCC uses the following environment variables:
- PATH: For searching the executables and run-time shared libraries (.dll, .so).
- CPATH: For searching the include-paths for headers. It is searched after paths specified in
-I<dir>
options. C_INCLUDE_PATH and CPLUS_INCLUDE_PATH can be used to specify C and C++ headers if the particular language was indicated in pre-processing. (用于搜索头文件的包含路径。在-I <dir>
选项中指定的路径之后搜索它。如果在预处理中指示了特定语言,则可以使用 C_INCLUDE_PATH 和 CPLUS_INCLUDE_PATH 指定 C 和 C++ 头文件。) - LIBRARY_PATH: For searching library-paths for link libraries. It is searched after paths specified in
-L<dir>
options.
1.10 Utilities for Examining the Compiled Files
For all the GNU utilities, you can use command --help
to list the help menu; or man command
to display the man pages.
file
Utility - Determine File Type
The utility file
can be used to display the type of object files and executable files. For example,
实用程序 file
可用于显示目标文件和可执行文件的类型。
$ gcc -c hello.c
$ gcc -o hello.exe hello.o
$ file hello.c
hello.c: C source, ASCII text, with CRLF line terminators
$ file hello.o
hello.o: data
> file hello.exe
hello.exe: PE32 executable (console) x86-64, for MS Windows
strong@foreverstrong:~/Desktop/hello-world$ ll
total 60
drwxrwxr-x 2 strong strong 4096 Sep 19 11:52 ./
drwxr-xr-x 9 strong strong 4096 Sep 19 11:16 ../
-rwxrwxr-x 1 strong strong 20232 Sep 19 11:52 hello*
-rw-rw-r-- 1 strong strong 93 Sep 19 11:09 hello.c
-rw-rw-r-- 1 strong strong 121 Sep 19 11:39 hello.cpp
-rw-rw-r-- 1 strong strong 22072 Sep 19 11:51 hello.o
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ file hello.c
hello.c: C source, ASCII text
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ file hello.cpp
hello.cpp: C source, ASCII text
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ file hello.o
hello.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ file hello
hello: 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]=d56dc47e99b808fc6b5010414914bd3132f47d81, not stripped
strong@foreverstrong:~/Desktop/hello-world$
nm
Utility - List Symbol Table of Object Files
The utility nm
lists symbol table of object files. For example,
$ nm hello.o
0000000000000000 b .bss
0000000000000000 d .data
0000000000000000 p .pdata
0000000000000000 r .rdata
0000000000000000 r .rdata$zzz
0000000000000000 t .text
0000000000000000 r .xdata
U __main
0000000000000000 T main
U puts
$ nm hello.exe | grep main
00000001004080cc I __imp___main
0000000100401120 T __main
00000001004010e0 T main
......
nm
is commonly-used to check if a particular function is defined in an object file. A ‘T’ in the second column indicates a function that is defined, while a ‘U’ indicates a function which is undefined and should be resolved by the linker.
nm
通常用于检查目标文件中是否定义了特定函数。第二列中的 T
表示定义的函数,而 U
表示未定义的函数,应由链接器解析。
ldd
Utility - List Dynamic-Link Libraries
The utility ldd
examines an executable and displays a list of the shared libraries that it needs. For example,
实用程序 ldd
检查可执行文件并显示它需要的共享库列表。
> ldd hello.exe
ntdll.dll => /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll (0x7ff9ba3c0000)
KERNEL32.DLL => /cygdrive/c/WINDOWS/System32/KERNEL32.DLL (0x7ff9b9880000)
KERNELBASE.dll => /cygdrive/c/WINDOWS/System32/KERNELBASE.dll (0x7ff9b6a60000)
SYSFER.DLL => /cygdrive/c/WINDOWS/System32/SYSFER.DLL (0x6ec90000)
ADVAPI32.dll => /cygdrive/c/WINDOWS/System32/ADVAPI32.dll (0x7ff9b79a0000)
msvcrt.dll => /cygdrive/c/WINDOWS/System32/msvcrt.dll (0x7ff9b9100000)
sechost.dll => /cygdrive/c/WINDOWS/System32/sechost.dll (0x7ff9b9000000)
RPCRT4.dll => /cygdrive/c/WINDOWS/System32/RPCRT4.dll (0x7ff9b9700000)
cygwin1.dll => /usr/bin/cygwin1.dll (0x180040000)
strong@foreverstrong:~/Desktop/hello-world$ ll
total 60
drwxrwxr-x 2 strong strong 4096 Sep 19 11:52 ./
drwxr-xr-x 9 strong strong 4096 Sep 19 11:16 ../
-rwxrwxr-x 1 strong strong 20232 Sep 19 11:52 hello*
-rw-rw-r-- 1 strong strong 93 Sep 19 11:09 hello.c
-rw-rw-r-- 1 strong strong 121 Sep 19 11:39 hello.cpp
-rw-rw-r-- 1 strong strong 22072 Sep 19 11:51 hello.o
strong@foreverstrong:~/Desktop/hello-world$
strong@foreverstrong:~/Desktop/hello-world$ ldd hello
linux-vdso.so.1 => (0x00007ffc45b78000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f52791fb000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5278e31000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f5278b28000)
/lib64/ld-linux-x86-64.so.2 (0x00007f527957d000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f5278912000)
strong@foreverstrong:~/Desktop/hello-world$
转载:https://blog.csdn.net/chengyq116/article/details/101032602