GCC compilation

  • 学习GCC compilation

1.-Wall:turns on all the most commonly-used compiler warnings—it is recommended that you always use this option!

gcc -Wall hello.c -o hello

2.Linking with external libraries

gcc -Wall calc.c /usr/lib/libm.a -o calc

  To avoid the need to specify long paths on the command line, the compiler provides a short-cut option ‘-l’ for linking against libraries. For example, the following command:

$ gcc -Wall calc.c -lm -o calc

  Note: It is equivalent to the original command above using the full library name
‘/usr/lib/libm.a’.In general, the compiler option ‘-lNAME’ will attempt to link object
files with a library file ‘libNAME.a’ in the standard library directories.

3.Setting search paths

  A common problem when compiling a program using library header
files is the error:

FILE.h: No such file or directory

  This occurs if a header file is not present in the standard include file
directories used by gcc. A similar problem can occur for libraries:

/usr/bin/ld: cannot find library

  This happens if a library used for linking is not present in the standard library directories used by gcc.

  By default, gcc searches the following directories for header files:

  • /usr/local/include/
  • /usr/include/

the following directories for libraries:

  • /usr/local/lib/
  • /usr/lib/

  The list of directories for header files is often referred to as the include path, and the list of directories for libraries as the library search path or link path.

  When additional libraries are installed in other directories it is necessary to extend the search paths, in order for the libraries to be found. The compiler options ‘-I’ and ‘-L’ add new directories to the beginning of the include path and library search path respectively.

For example:

#include <stdio.h>
#include <gdbm.h>
int main (void)
{
	GDBM_FILE dbf;
	datum key = { "testkey", 7 }; /* key, length */
	datum value = { "testvalue", 9 }; /* value, length */
	printf ("Storing key-value pair... ");
	dbf = gdbm_open ("test", 0, GDBM_NEWDB, 0644, 0);
	gdbm_store (dbf, key, value, GDBM_INSERT);
	gdbm_close (dbf);
	printf ("done.\n");
	return 0;
}

The program uses the header file ‘gdbm.h’ and the library ‘libgdbm.a’.The library has not been installed in the default location of ‘/usr/local/lib’, with the header file in ‘/usr/local/include’, then the program must be compiled with the following simple command:

gcc -Wall -I/opt/gdbm-1.8.3/include -L/opt/gdbm-1.8.3/lib dbmain.c -lgdbm

4.Environment variables

  The search paths for header files and libraries can also be controlled through environment variables in the shell. These may be set automatically for each session using the appropriate login file, such as ‘.bash_profile’.

  Additional directories can be added to the include path using the environment variable C_INCLUDE_PATH (for C header files).Similarly, additional directories can be added to the link path using the environment variable LIBRARY_PATH.

For example:

$ C_INCLUDE_PATH=/opt/gdbm-1.8.3/include
$ export C_INCLUDE_PATH
$ LIBRARY_PATH=/opt/gdbm-1.8.3/lib
$ export LIBRARY_PATH

4.1.Extended search paths
  Following the standard Unix convention for search paths, several directories can be specified together in an environment variable as a colon separated list: DIR1:DIR2:DIR3:…

$ C_INCLUDE_PATH=.:/opt/gdbm-1.8.3/include:/net/include
$ LIBRARY_PATH=.:/opt/gdbm-1.8.3/lib:/net/lib

  To specify multiple search path directories on the command line, the options ‘-I’ and ‘-L’ can be repeated. For example, the following command,is equivalent to the environment variable settings given above.

$ gcc -I. -I/opt/gdbm-1.8.3/include -I/net/include
-L. -L/opt/gdbm-1.8.3/lib -L/net/lib …

5.Shared libraries and static libraries

  The simplest way to set the load path is through the environment variable LD_LIBRARY_PATH. For example, the following commands set the load path to ‘/opt/gdbm-1.8.3/lib’ so that ‘libgdbm.so’ can be found:

$ LD_LIBRARY_PATH=/opt/gdbm-1.8.3/lib
$ export LD_LIBRARY_PATH

  Several shared library directories can be placed in the load path, as a colon separated list DIR1:DIR2:DIR3:…:DIRN. For example, the following command sets the load path to use the ‘lib’ directories under ‘/opt/gdbm-1.8.3’ and ‘/opt/gtk-1.4’:

$ LD_LIBRARY_PATH=/opt/gdbm-1.8.3/lib:/opt/gtk-1.4/lib
$ export LD_LIBRARY_PATH

  If the load path contains existing entries, it can be extended using the syntax LD_LIBRARY_PATH=NEWDIRS:$LD_LIBRARY_PATH. For example, the following command adds the directory ‘/opt/gsl-1.5/lib’ to the load path shown above:

$ LD_LIBRARY_PATH=/opt/gsl-1.5/lib:$LD_LIBRARY_PATH
$ echo $LD_LIBRARY_PATH
/opt/gsl-1.5/lib:/opt/gdbm-1.8.3/lib:/opt/gtk-1.4/lib

6.Selecting specific standards

  The specific language standard used by GCC can be controlled with the ‘-std’ option. The following C language standards are supported:

  • ‘-std=c89’ or ‘-std=iso9899:1990’
    • The original ANSI/ISO C language standard (ANSI X3.159-1989,ISO/IEC 9899:1990).
  • ‘-std=iso9899:199409’
    • The ISO C language standard with ISO Amendment 1, published in 1994. This amendment was mainly concerned with internationalization, such as adding support for multibyte characters to the C library.
  • ‘-std=c99’ or ‘-std=iso9899:1999’
    • The revised ISO C language standard, published in 1999 (ISO/IEC
      9899:1999).
  • ‘-std=gnu89’ and ‘-std=gnu99’
    • The C language standards with GNU extensions can be selected with the options ‘-std=gnu89’ and ‘-std=gnu99’.

7.The Preprocessor

  If you use the ‘-E’ option, nothing is done except preprocessing. Some of these options make sense only together with ‘-E’ because they cause the preprocessor output to be unsuitable for actual compilation.

gcc -E a.c -o a.i

or

gcc -c -save-temps a.c

7.1.-DNAME

  It uses the preprocessor conditional #ifdef to check whether a macro is defined.When the macro is defined, the preprocessor includes the corresponding code up to the closing #endif command. In this example, the macro which is tested is called TEST, and the conditional part of the source code is a printf statement which prints the message “Test mode”:

#include <stdio.h>
int main (void)
{
	#ifdef TEST
	printf ("Test mode\n");
	#endif
	printf ("Running...\n");
	return 0;
}

  The gcc option ‘-DNAME’ defines a preprocessor macro NAME from the command line. If the program above is compiled with the commandline option ‘-DTEST’, the macro TEST will be defined and the resulting executable will print both messages:

$ gcc -Wall -DTEST dtest.c
$ ./a.out
Test mode
Running...

Note:
  Macros are generally undefined, unless specified on the command line with the option ‘-D’, or in a source file (or library header file) with #define.
  Some macros are automatically defined by the compiler—these typically use a reserved namespace beginning with a double-underscore prefix ‘__’.

  The complete set of predefined macros can be listed by running the GNU preprocessor cpp with the option ‘-dM’ on an empty file:

$ cpp -dM /dev/null

  -dM Instead of the normal output, generate a list of ‘#define’ directives for all the macros defned during the execution of the preprocessor, including predefned macros. This gives you a way of fnding out what is predefned in your version of the preprocessor. Assuming you have no fle ‘foo.h’, the command:

touch foo.h; cpp -dM foo.h

shows all the predefned macros.

7.2.Macros with values

#include <stdio.h>
int main (void)
{
	printf("Value of NUM is %d\n", NUM);
	return 0;
}

  To define a macro with a value, the ‘-D’ command-line option can be
used in the form ‘-DNAME=VALUE’. For example, the following command line defines NUM to be 100 when compiling the program above:

$ gcc -Wall -DNUM=100 dtestval.c
$ ./a.out
Value of NUM is 100

8.Compiling with optimization

8.1.Source-level optimization
8.1.1.Common subexpression elimination
  In compiler theory, common subexpression elimination (CSE) is a compiler optimization that searches for instances of identical expressions (i.e., they all evaluate to the same value), and analyzes whether it is worthwhile replacing them with a single variable holding the computed value. Detail see (CSE) by the GCC Compiler.

8.1.2.Function inlining
  Whenever a function is used, a certain amount of extra time is required for the CPU to carry out the call: it must store the function arguments in the appropriate registers and memory locations, jump to the start of the function (bringing the appropriate virtual memory pages into physical memory or the CPU cache if necessary), begin executing the code, and then return to the original point of execution when the function call is complete. This additional work is referred to as function-call overhead. Function inlining eliminates this overhead by replacing calls to a function by the code of the function itself (known as placing the code in-line). Detail see Function inlining.

8.2.Optimization levels
  Without any optimization option, the compiler’s goal is to reduce the cost of compilation and to make debugging produce the expected results. Statements are independent: if you stop the program with a breakpoint between statements, you can then assign a new value to any variable or change the program counter to any other statement in the function and get exactly the results you would expect from the source code.

  Turning on optimization flags makes the compiler attempt to improve the performance and/or code size at the expense of compilation time and possibly the ability to debug the program.

  The compiler performs optimization based on the knowledge it has of the program. Optimization levels -O and above, in particular, enable unit-at-a-time mode, which allows the compiler to consider information gained from later functions in the file when compiling a function. Compiling multiple files at once to a single output file in unit-at-a-time mode allows the compiler to use information gained from all of the files when compiling each of them.

  Not all optimizations are controlled directly by a flag. Only optimizations that have a flag are listed.

  • ‘-O0’ or no ‘-O’ option (default)
    At this optimization level GCC does not perform any optimization and compiles the source code in the most straightforward way possible. Each command in the source code is converted directly to the corresponding instructions in the executable file, without rearrangement. This is the best option to use when debugging a program. The option ‘-O0’ is equivalent to not specifying a ‘-O’ option.
  • ‘-O1’ or ‘-O’
    This level turns on the most common forms of optimization that do not require any speed-space tradeoffs. With this option the resulting executables should be smaller and faster than with ‘-O0’.The more expensive optimizations, such as instruction scheduling, are not used at this level. Compiling with the option ‘-O1’ can often take less time than compiling with ‘-O0’, due to the reduced amounts of data that need to be processed after simple optimizations.
  • ‘-O2’ This option turns on further optimizations, in addition to those used by ‘-O1’. These additional optimizations include instruction scheduling. Only optimizations that do not require any speed-space tradeoffs are used, so the executable should not increase in size. The compiler will take longer to compile programs and require more memory than with ‘-O1’. This option is generally the best choice for deployment of a program, because it provides maximum optimization without increasing the executable size. It is the default
    optimization level for releases of GNU packages.
  • ‘-O3’ This option turns on more expensive optimizations, such as function inlining, in addition to all the optimizations of the lower levels ‘-O2’ and ‘-O1’. The ‘-O3’ optimization level may increase the speed of the resulting executable, but can also increase its size. Under some circumstances where these optimizations are not favorable, this option might actually make a program slower.
  • ‘-funroll-loops’ This option turns on loop-unrolling, and is independent of the other optimization options. It will increase the size of an executable. Whether or not this option produces a beneficial result has to be examined on a case-by-case basis.
  • ‘-Os’ This option selects optimizations which reduce the size of an executable. The aim of this option is to produce the smallest possible executable, for systems constrained by memory or disk space. In some cases a smaller executable will also run faster, due to better cache usage.

  It is important to remember that the benefit of optimization at the highest levels must be weighed against the cost. The cost of optimization includes greater complexity in debugging, and increased time and memory requirements during compilation. For most purposes it is satisfactory to use ‘-O0’ for debugging, and ‘-O2’ for development and deployment.

refer to
An_Introduction_to_GCC-Brian_Gough.pdf
https://gcc.gnu.org/onlinedocs/gcc/Inline.html
https://opensourceforu.com/2017/04/different-c-standards-story-c/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值