Skip to content

GCC

The GNU Compiler Collection (GCC) is a compiler system produced by the GNU Project supporting various programming languages.

Categories

How to install

GCC4.8.2를 CentOS6에서 설치하는 방법은 아래와 같다.

## Install pre-requirements:
$ yum install gmp-devel mpfr-devel libmpc-devel

## Download and extract gcc 4.8.2 source tar ball:
$ curl -O ftp://ftp.gnu.org/gnu/gcc/gcc-4.8.2/gcc-4.8.2.tar.gz; tar zxf gcc-4.8.2.tar.gz
$ cd gcc-4.8.2; ./configure --enable-languages=c,c++ --disable-multilib

## Build and install:
$ make; make install

Debian:

$ sudo apt-get install gcc
$ sudo apt-get install g++

RedHat:

$ sudo yum install gcc
$ sudo yum install gcc-c++

in Ubuntu

Ubuntu에서 GCC 4.9버전을 설치하고 싶다면 아래와 같이 설치하면 된다.

$ sudo add-apt-repository ppa:ubuntu-toolchain-r/test 
$ sudo apt-get update
$ sudo apt-get install gcc-4.9

만약, 기본 gcc명령을 gcc-4.9로 대체하고 싶다면 alternatives명령을 사용하면 된다.

간단한 사용 방법

GCC 사용방법에 대한 예제.

컴파일 방법. (오브젝트파일이 출력된다.)

gcc -c [SOURCE_PATH]

실행파일 작성 방법. (오브젝트 파일을 입력해야 한다.)

gcc -o [OUTPUT_PATH] [SOURCE_PATH] [SOURCE_PATH] [SOURCE_PATH] ...

Objective-C 소스코드 컴파일 방법.

gcc -lobjc -o source.m

MinGW Static and Dynamic Libraries

Compiling the Static Library

Building the Library.

gcc -c add.c -o add.o
ar rcs libadd.a add.o

Referencing the Library.

gcc -c main.c -o main.o
gcc -c main.exe main.o -L. -ladd
main.exe

Compiling the Dynamic Library

Referencing the Library.

gcc -c add.c -o add.o
gcc -shared -o libadd.so add.o
gcc -o main.exe main.c libadd.so

Environment Variables

참고로 LD_DEBUG는 GNU C 항목에서 확인할 수 있다.

LD_LIBRARY_PATH
ld에서 사용할 링커 라이브러리가 모여진 디렉토리 경로 모음.

Library dependency

라이브러리는 종속성 문제가 존재한다. 이는 gcc 컴파일 할 경우 명령행 인자 순서에 영향을 미친다.

## main.cpp 파일에서 liba.a의 함수를 사용할 경우 아래와 같은 순서로 적용해야 한다.
g++ -c main.cpp
g++ main.o -la

만약 링크 순서가 꼬일 경우 아래와 같이 적용하면 된다.

## -Wl 대신 -Xlinker를 사용해도 된다
g++ main.o -Wl,--start-group {라이브러리 목록} -Wl,--end-group

## 또는 편법적인 방법이지만 두 번 작성해도 된다.
g++ main.o -lcommon -lutil -lmisc -lcommon -lutil -lmisc

Precompiled Headers

미리 컴파일 된 헤더를 사용하면 컴파일 시간을 단축할 수 있다. PCH파일을 만드는 방법은 아래와 같이 헤더파일을 컴파일 하면 된다.

$ g++ -c stdafx.h

주의할 점은 -g플래그를 사용하면 다른 소스파일을 컴파일 할 경우 동일하게 -g플래그를 사용해야 하며, 사용하지 않을 경우도 동일하게 사용하면 안된다.

이 후, 파일명.h.gch파일이 생성되는데, PCH를 적용할 소스파일 상단에 헤더파일을 추가하면 된다. 자세한 내용은 https://gcc.gnu.org/onlinedocs/gcc/Precompiled-Headers.html 에서 확인할 수 있다.

Command-line options

GCC에서 사용할 수 있는 중요한 명령줄(Command line) 옵션 정리.

Common options

-c
링크과정을 진행하지않고 컴파일까지만 진행한다.
오브젝트파일을 출력한다.
-o<OUTPUT_PATH>
출력파일을 지정한다.
-I<INCLUDE_DIR>
대문자 i이며 #include 헤더의 경로를 나타낸다. -I와 <INCLUDE_DIR>사이에 공백은 없으며 여러번 사용할 수 있다.
-l<LIBRARY_NAME>
소문자 L이며 링크(Link)할 라이브러리를 명시한다.
접두사 lib과 접미사 .a(또는 *.so)를 제거한 라이브러리 이름을 적는다.
-l와 <INCLUDE_DIR>사이에 공백은 없으며 여러번 사용할 수 있다. (e.g. libmylib.a를 링크하고싶을 경우 -lmylib 라고 적으면 된다.)
만약 라이브러리의 전체 경로를 입력하고 싶다면 Object(*.o)파일과 같이 -l빼고 입력하면 된다.
-L<LIBRARY_DIR>
라이브러리를 모아놓은 경로를 명시한다.
-L과 <LIBRARY_DIR>사이에 공백은 없으며 여러번 사용할 수 있다. (e.g. -L.은 현재 디렉터리를 나타낸다.)
-p
프로그램을 prof로 프로파일링 할 수 있도록 링크한다.
-w
모든 경고 메시지 제거.
-W
합법적이지만 다소 모호한 코딩에 대하여 부가적인 경고 메시지 출력.
-Wall
모호한 코딩에 대하여 훨씬 더 자세한 경고 메시지 출력.
-Werror
모든 경고(Warning)를 오류(Error)로 취급한다. 즉, 한 개의 경고만 나와도 컴파일이 중단된다.
-Wtraditional
소스코드에 ANSI C와 K&R C 사이에 서로 다른 결과를 가져올 수 있다면 경고를 출력.
-Wno-psabi
note: the mangling of 'va_list' has changed in GCC 4.4와 같은 메시지를 제거하고 싶을 경우 사용된다.
NOTE: 정확한 옵션정보는 알아봐야 한다.
-Wno-wchar-size-warning
ld.exe: warning: ~.o uses 2-byte wchar_t yet the output is to use 4-byte wchar_t; use of wchar_t values across objects may fail와 같은 메시지를 제거하고 싶을 경우 사용된다.
NOTE: 정확한 옵션정보는 알아봐야 한다.
-static
정적 라이브러리로 컴파일한다.
-shared
가능한 공유라이브러리와 링크하고 공유라이브러리가 없을 경우 정적라이브러리와 링크한다.
-Wl,--subsystem,windows
MINGW 커맨드라인 창과 윈도우창이 동시에 나타나지 않는다.
-mwindows
MINGW의 WinMain을 진입점으로 설정한다. Linker 플래그로 설정하면 된다.
See also: http://blog.jidolstar.com/677|http://blog.jidolstar.com/677
-M
makefile을 위한 종속성(defendency) 리스트를 stdout으로 출력한다.
보통 리다이렉트를 이용한 *.d파일을 만들어 makefile에 사용된다. 자세한 내용은 종속물들을 자동으로 생성하기(Generating Dependencies Automatically)를 참조.
-MM
-M과 동일하지만 시스템 헤더 파일들에 대해서는 종속물들을 생략하도록 한다.
-H
사용하고 있는 전체 헤더파일 목록을 스택(Stack)형식으로 출력한다.
-std=c++11
https://gcc.gnu.org/onlinedocs/gcc/Standards.html
https://gcc.gnu.org/projects/cxx0x.html
개정된 C++ 11 표준 (ISO/IEC 14882:2011)을 적용한다.
--diag_suppress
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0348bk/CHDHFIAG.html
이 옵션은 지정된 태그가 있는 진단 메시지를 비활성화합니다.
--diag_suppress 옵션은 컴파일러에서 지정된 태그가 있는 진단 메시지를 오류 심각도로 설정하는 것이 아닌 해당 메시지를 표시하도록 하는 것을 제외하고 --diag_errors와 유사하게 동작합니다.
-save-temps
Store the normally temporary intermediate files(.s, .i, *.o) permanently.

Code Generation Conventions

These machine-independent options control the interface conventions used in code generation.

Most of them have both positive and negative forms; the negative form of -ffoo is -fno-foo. In the table below, only one of the forms is listed—the one that is not the default. You can figure out the other form by either removing no- or adding it.

-fstack-reuse=reuse-level
This option controls stack space reuse for user declared local/auto variables and compiler generated temporaries.
-fdiagnostics-color=auto
How to get color output from GCC
터미널 출력시 색상을 적용한다.
-fpermissive
Downgrade some diagnostics about nonconformant code from errors to warnings. Thus, using -fpermissive will allow some nonconforming code to compile. 3
gcc 4.1 버전부터 표준을 더 엄격하게 지키려고 하다보니 발생하는 문제로서 일종의 버그라고 봐도 무방하다. :문제가 되는 변수에 this->와 같이 명시적으로 변수를 사용하거나, 표준 헤더파일을 먼저 찾을 수 있도록 적절한 헤더파일을 include해준다. (템플릿을 컴파일할 때는 로컬에서 먼저 찾는다고 한다.) 만약 컴파일러 옵션으로 해결하고 싶을 경우 사용하면 된다.
See also: http://wanochoi.com/?tag=fpermissive
-fPIC
크고 느린코드 생성. 플렛폼에 독립적. CPU에 관계없이 사용할 수 있다. 크기에 상관이 없는 대신 Global Offset Table(GOT)의 심볼 맥세스 속도저하가 크다. (그런데 i386에서는 -fPIC-fpic나 비슷하다)
See also: Shared Library
See also: shared library관련 기초적인 질문
See also: http://lists.freebsd.org/pipermail/cvs-ports/2004-March/030214.html
-fpic
작고 빠른 코드 생성. CPU에 따라 -fpic로 생성할 수 있는 GOT(Glocal Offset Table)의 크기에 제한이 있다. Global Offset Table(GOT)을 통해 심볼들을 액세스하는데 기계에 따라서 정해진 한계가 있어서 경우에 따라서는 실패할 수도 있다. 하지만 성공하면 -fPIC에 비해 더 적은 속도 저하를 얻을 수 있다.
See also: Shared Library
See also: GCC 동적 라이브러리(.so) 만들기 및 -fPIC와 -fpic 차이점
-fvisibility=hidden
glibc - ELF symbol visibility
#Symbol Visibility 항목 참조.
ELF의 symbol visibility 속성을 변경한다.
-finput-charset=
Character sets - The C Preprocessor
Stackoverflow - How should I use g++'s -finput-charset compiler option correctly in order to compile a non-UTF-8 source file?
INPUT 소스코드의 문자열셋을 지정한다. utf8지정시 -finput-charset=UTF-8로 적용하면 된다.
-fmessage-length=n
메시지를 출력할 경우 한 라인에 들어갈 문자의 길이를 n의 값으로 설정한다. 0으로 설정할 경우 전체 메시지를 출력한다. (Try to format error messages so that they fit on lines of about n characters. default is 72)
-fwhole-program
Stackoverflow - gcc:how to remove undefined symbol that is not used?
-fdata-sections, -ffunction-sections
Stackoverflow - How to remove unused C/C++ symbols with GCC and ld?

GCC Optimization

어떤 CPU를 쓰는지 모르겠거나 어떤 설정을 선택해야 할지 모르겠다면, 아마 그냥 -march=native 설정을 사용할 수 있습니다. 이 플래그를 사용하면 GCC는 프로세서를 감지하고 자동으로 적당한 플래그를 설정합니다.

WARNING

다른 CPU에서 사용할 패키지를 컴파일하려 한다면 -march=native 플래그를 사용해선 안된다.

CPU 특수화 플래그

CPU별 --extra-cflags추가 플래그.

ARM v6
-marm -march=armv6
ARM v7vfpv3
-mfloat-abi=softfp -mfpu=vfpv3-d16 -marm -march=armv7-a
ARM v7vfp
-mfloat-abi=softfp -mfpu=vfp -marm -march=armv7-a
ARM v7n
-mfloat-abi=softfp -mfpu=neon -marm -march=armv7-a -mtune=cortex-a8
ARM v6+vfp
-DCMP_HAVE_VFP -mfloat-abi=softfp -mfpu=vfp -marm -march=armv6

Position Independent Code

Include directory list

INCLUDE 디렉토리 목록은 아래와 같이 확인할 수 있다.

# C
$ echo | gcc -Wp,-v -x c - -fsyntax-only 2>&1

# C++
$ echo | gcc -Wp,-v -x c++ - -fsyntax-only 2>&1

# more information
$ echo | gcc -E -v -x c++ -
# /dev/null use version:
$ g++ -E -x c++ - -v < /dev/null
# Or in Windows Command Prompt:
$ g++ -E -x c++ - -v < nul
# Clang version:
$ clang++ -E -x c++ - -v < /dev/null

참고로 기본 디렉터리 목록은 아래와 같다.

  • /usr/local/include
  • libdir/gcc/target/version/include
  • /usr/target/include
  • /usr/include

Include file list

-M옵션 등을 사용하여 dependency 목록을 확인할 경우 아래와 같은 명령으로 리스트를 출력할 수 있다.

cat ffserver.d | sed 's/[ ]/\n/g' | grep '\.h' | sed 's/ *//g' | sort | uniq

Include order

우선 헤더 폴더를 지정하는 방법은 아래와 같다.

  • -I dir
  • -iquote dir
  • -isystem dir
  • -idirafter dir

You can specify any number or combination of these options on the command line to search for header files in several directories. The lookup order is as follows:

  1. For the quote form of the include directive, the directory of the current file is searched first.
  2. For the quote form of the include directive, the directories specified by -iquote options are searched in left-to-right order, as they appear on the command line.
  3. Directories specified with -I options are scanned in left-to-right order.
  4. Directories specified with -isystem options are scanned in left-to-right order.
  5. Standard system directories are scanned.
  6. Directories specified with -idirafter options are scanned in left-to-right order.

Dump preprocessor defines

Yes, use -E -dM options instead of -c. Example (outputs them to stdout):

gcc -dM -E - < /dev/null

For C++

g++ -dM -E -x c++ - < /dev/null

From the gcc manual:

Instead of the normal output, generate a list of `#define' directives for all the macros defined during the execution of the preprocessor, including predefined macros. This gives you a way of finding out what is predefined in your version of the preprocessor. Assuming you have no file foo.h, the command

touch foo.h; cpp -dM foo.h

will show all the predefined macros.

If you use -dM without the -E option, -dM is interpreted as a synonym for -fdump-rtl-mach.

sysroot isysroot isystem

-sysroot는 표준 C 라이브러리의 헤더 파일과 라이브러리의 위치를 변경할 때 사용한다. 크로스 컴파일을 할 때 보통 사용한다.

-sysroot=/mips-root라면 /mips-root/usr/include, /mips-root/usr/lib에서 헤더 파일과 라이브러리를 찾게 된다.

-isysroot는 라이브러리와 별도로 헤더 파일만 따로 지정하고자 할 때 사용한다. 이 옵션이 없는 경우에는 -sysroot를 따르게 된다.

표준 C 라이브러리 헤더 파일 이외에도 /usr/include에는 많은 다른 라이브러리의 헤더 파일이 존재한다. 크로스 컴파일을 하는 경우에는 관련 라이브러리 헤더 파일을 한 곳에 모아 두면 편하게 되는데 위의 mips-root/usr/include에 추가해도 되지만 섞이는 것을 원치 않는 경우라면 -isystem옵션을 이용해서 추가로 다른 디렉토리를 지정하면 된다.

헤더 파일을 찾는 우선 순위는 다음과 같다.

  1. -I
  2. -isystem
  3. -sysroot or -isysroot

Disable GCC warnings for a few lines of code

코드상에서 GCC의 Warning을 제거하는 방법은 아래와 같다.

#if defined(__GNUC__) && defined(__cplusplus)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Winline"
#endif

#include <boost/log/trivial.hpp>

#if defined(__GNUC__) && defined(__cplusplus)
# pragma GCC diagnostic pop
#endif

Symbol Visibility

GCC 4.0부터 포함되어 있는 GCC Symbol Visibility Patch는 GCC 컴파일러를 조금 더 유용하게 만들어 준다. 홈페이지에서 언급한 이 기능의 장점은 다음과 같다.

  • 공유 라이브러리와 같은 DSO(Dynamic Shared Object, 동적 공유 객체)를 로드하는데 걸리는 시간을 획기적으로 향상시켜준다.
  • 컴파일러 최적화기(optimiser)가 더 좋은 코드를 만들수 있다.
  • DSO 크기를 5~20% 정도 줄여준다.
  • 심볼(symbol)이 충돌할 기회를 낮춰준다.

visibility 속성은 다음과 같은 4가지 중의 하나로 설정할 수 있다.

  • default: 기본값이다. visibility는 고려하지 않고 해당 심볼(의 바인딩)이 global인지 static(local)인지 만을 이용한다.
  • hidden: 주로 사용되는 속성이다. 해당 심볼을 외부로 공개하지 않게 만든다.
  • protected: 잘 사용되지 않는다. 해당 심볼은 공개하지만 다른 모듈에 의해 대체되지 않는다.
  • internal: 잘 사용되지 않는다. 해당 심볼을 공개하지 않으며 각 아키텍처 별로 약간씩 다른 효과를 가질 수 있다.

Exclude unused symbols

For GCC, this is accomplished in two stages:

First compile the data but tell the compiler to separate the code into separate sections within the translation unit. This will be done for functions, classes, and external variables by using the following two compiler flags:

-fdata-sections -ffunction-sections

Link the translation units together using the linker optimization flag (this causes the linker to discard unreferenced sections):

-Wl,--gc-sections

So if you had one file called test.cpp that had two functions declared in it, but one of them was unused, you could omit the unused one with the following command to gcc(g++):

gcc -Os -fdata-sections -ffunction-sections test.cpp -o test -Wl,--gc-sections

(Note that -Os is an additional compiler flag that tells GCC to optimize for size)

Tip

With mingw this does not work when linking statically statically libstdc++ and libgcc with the flag -static. The linker option -strip-all helps quite a bit, but still the generated executable (or dll) is about 4 way bigger than what Visual Studio would generate. Point is, I have no control on how libstdc++ was compiled. There should be a ld only option.

Exclude Functions

-finstrument-functions-exclude-file-list=file,file,... 옵션 또는 -finstrument-functions-exclude-function-list=sym,sym,... 옵션 참조.

... 결국 strip을 사용했다:

strip --strip-symbol=main -o libdwm.a libdwm-nomain.a

Whole archive

  • MSVC: link.exe/WHOLEARCHIVE:libA와 같이 사용하면 된다.
  • Clang: -Wl,-force_load,libfoobar.a를 사용하거나 -Wl,-all_load를 사용하면 된다.
  • GCC: -Wl,--whole-archive-Wl,--no-whole-archive플래그 사이에 추가하면 된다.

컴파일 과정

GCC 는 사실 컴파일러 자체를 말하는 것은 아니고, 컴파일 과정에 필요한 여러가지 기능들을 호출하는 역할을 합니다. 따라서 gcc 는 c 언어 뿐만 아니라 다른 언어들도 컴파일이 가능 합니다. 일련의 과정에 다른 언어를 컴파일하는 녀석들을 호출만 해주면 되기 때문입니다.

컴파일 과정 요약

  1. 전처리 과정
  2. 어셈블리 소스파일로 컴파일과정
  3. 인스트럭션 코드 생성 과정
  4. 링크 과정

전처리 ( ccp0 )

소스파일에 포함된 (#include) 파일들을 불러와 현재컴파일할 파일에 복사해서 붙여 넣는다. (결과물: test.i)

어셈블리 코드로 컴파일 (cc1)

실제 컴파일러라 할 수 있다. 어휘분석 -> 구문분석 -> 의미분석 -> 중간언어생성 -> 코드최적화 -> 목적코드생성 의 과정을 거친다.

  • 어휘 분석: 전처리 과정에서 생성된 test.i 파일을 문법적 의미가 있는 최소 단위 (토큰) 로 나눈다.
  • 구문 분석: 문법석 오류가 있는지 검사 한 후 파서트리를 만든다.
  • 의미 분석: 문법상 문제가 아닌 의미상 문제, 즉 선언되지 않은 변수의 사용이나 자료형 불일치, 함수 인자개수 등의 문제를 검사 한다.
  • 중간언어 생성: 어셈블리 코드로 만들기 전에 최적화를 위해 RTL(Register Transfer Language) 라는 lips 언어와 유사한 코드로 생성한다. (결과물 : test.rtl)
  • 코드 최적화: 코드의 사이즈를 줄이고, 속도를 높이기 위해 최적화를 진행 한다. gcc 컴파일의 대부분의 시간이 소요되며 아래 두단계를 거친다.
    • 중간코드 최적화
      • 지역 최적화 : 연산강도 경감, 상수계산등의 최적화
      • 전역 최적화 : 사용되지 않는 코드제거
      • 루프 최적화 : 사용하지 않는 루프제거, 루프결합
    • 목적코드 최적화
      • 최대한 메모리보다 레지스트를 사용하게 하고, 효율적인 인스트럭션을 선택하여 메모리 접근을 최적화 한다.
  • 목적코드 생성: 최적화된 rtl 코드를 어셈블리 코드로 변환 한다. 어셈블리코드는 cpu 마다 정해진 인스트럭션(기계어)과 1:1 로 매칭된 코드 이다. (결과물 : test.s)

기계어 코드 생성 (as)

.s 인 어셈블리 코드를 .o 인 오브젝트 파일로 바꾼다. 생성된 오브젝트 파일은 ELF(Executable and Linking) 바이너리 파일 구조 규약을 따르며, 이유는 여러 오브젝트 파일을 링크 할 때 파일의 구조가 다르다면 불가능 하기 때문임. 바이너리 포멧은 a.out / ELF / COFF 등이 유닉스 시스템 에서 쓰였으며, 현재는 ELF 가 대부분 사용된다. 윈도우 시스템 에서는 COFF , PE 가 쓰인다.

  • ELF 파일 구조는 맨위에 ELF 파일헤더, 프로그램 헤더 Table, 섹선1 ~ n , 섹션 헤더 테이블로 구된다.
  • ELF 파일 헤더를 제외하고 나머지는 컴파일된 파일 마다 다를 수 있으며, 인스트럭션과 데이터, GCC컴파일러 버전 등이 기록 된다.

링크 (collect2)

여러개의 오브젝트 파일을 하나로 링크하는 과정이며, 주로 라이브러리의 링크가 이루어 진다.

  • 정적 라이브러리 : 링크시에 라이브러리를 포함해서 실행 파일을 만든다. 따라서 다른 프로그램에서도 같은 라이브러리를 사용 한다면, 중복되기 때문에 용량을 많이 차지 하게 되지만, 링크가 완료된 상태이므로 속도는 빠르다.
  • 동적 라이브러리(공유 라이브러리) : 링크시 라이브러리의 포함 여부만 기록하고, 실제 동작할 때 메모리에 라이브러리를 로드하여 사용한다. 다른 프로그램에서 같은 라이브러리를 사용 할 경우 메모리에 이미 로드된 것을 사용 하므로, 공유 한다는 의미에서 공유 라이브러리 라고도 한다. 따라서 단 한개의 프로그램이라도 이 라이브러리를 사용 하고 있으면, 메모리에 상주 하며, 아무 프로그램도 사용 하지 않는다면, 메모리에서 제거 된다. 실행시 로드되므로 속도는 다소 느릴 수 있으나 중복로드 되지 않아 메모리 사용이 효율 적이다. (결과물 : 실행 파일).

흔한 컴파일러 오해들

Compiler#흔한 컴파일러 오해들 항목 참조.

디버깅 심볼

-g를 명령행에 사용하면 디버깅 심볼을 추가한다. objdump로 해당 섹션을 확인할 수 있다.

다음과 같이 확인한 수 있다.

$ objdump -x main-g.o | grep debug

다음과 같은 내용이 포함된다.

 25 .debug_aranges 00000030  0000000000000000  0000000000000000  00003042  2**0
 26 .debug_info   000000c4  0000000000000000  0000000000000000  00003072  2**0
 27 .debug_abbrev 00000071  0000000000000000  0000000000000000  00003136  2**0
 28 .debug_line   0000004c  0000000000000000  0000000000000000  000031a7  2**0
 29 .debug_str    0000009f  0000000000000000  0000000000000000  000031f3  2**0
0000000000000000 l    d  .debug_aranges 0000000000000000              .debug_aranges
0000000000000000 l    d  .debug_info    0000000000000000              .debug_info
0000000000000000 l    d  .debug_abbrev  0000000000000000              .debug_abbrev
0000000000000000 l    d  .debug_line    0000000000000000              .debug_line
0000000000000000 l    d  .debug_str 0000000000000000              .debug_str
  • -g0를 사용하면 디버깅 심볼을 넣지 않는다. -g를 명령행에 추가하지 않는 것과 동일하다.
  • 만약 -g0 옵션과 -g 옵션을 함께 사용하면 명령행 기준, 가장 마지막에 입력한 옵션이 적용된다.

디버그 심볼과 타겟 분리

You need to use objcopy to separate the debug information:

objcopy --only-keep-debug "${tostripfile}" "${debugdir}/${debugfile}"
strip --strip-debug --strip-unneeded "${tostripfile}"
objcopy --add-gnu-debuglink="${debugdir}/${debugfile}" "${tostripfile}"

I use the bash script below to separate the debug information into files with a .debug extension in a .debug directory. This way I can tar the libraries and executables in one tar file and the .debug directories in another. If I want to add the debug info later on I simply extract the debug tar file and voila I have symbolic debug information.

This is the bash script:

#!/bin/bash

scriptdir=`dirname ${0}`
scriptdir=`(cd ${scriptdir}; pwd)`
scriptname=`basename ${0}`

set -e

function errorexit()
{
  errorcode=${1}
  shift
  echo $@
  exit ${errorcode}
}

function usage()
{
  echo "USAGE ${scriptname} <tostrip>"
}

tostripdir=`dirname "$1"`
tostripfile=`basename "$1"`


if [ -z ${tostripfile} ] ; then
  usage
  errorexit 0 "tostrip must be specified"
fi

cd "${tostripdir}"

debugdir=.debug
debugfile="${tostripfile}.debug"

if [ ! -d "${debugdir}" ] ; then
  echo "creating dir ${tostripdir}/${debugdir}"
  mkdir -p "${debugdir}"
fi
echo "stripping ${tostripfile}, putting debug info into ${debugfile}"
objcopy --only-keep-debug "${tostripfile}" "${debugdir}/${debugfile}"
strip --strip-debug --strip-unneeded "${tostripfile}"
objcopy --add-gnu-debuglink="${debugdir}/${debugfile}" "${tostripfile}"
chmod -x "${debugdir}/${debugfile}"

License

GCC Runtime Library Exception

What libraries does the GCC Runtime Library Exception cover?
The GCC Runtime Library Exception covers any file that has a notice in its license headers stating that the exception applies. This includes libgcc, libstdc++, libfortran, libgomp, libdecnumber, libgcov, and other libraries distributed with GCC.

Troubleshooting

GCC사용과 관련된 문제점에 대하여 정리한다.

ISO C90 forbids mixed declarations and code

위와 같은 경고 메시지가 출력된다면 변수 선언을 함수 시작 부분으로 옮겨보자.

STD C++11 error

thread 등을 사용할 경우 아래와 같은 에러를 뱉으며 컴파일 조차 안되는 현상이 있을 수 있다.

In file included from test.cpp:1:0:
C:/root/msys/tdmgcc/lib/gcc/mingw32/4.9.2/include/c++/thread: In function 'bool std::operator<(std::thread::id, std::thread::id)':
C:/root/msys/tdmgcc/lib/gcc/mingw32/4.9.2/include/c++/thread:88:30: error: no match for 'operator<' (operand types are 'std::thread::native_handle_type {aka ptw32_handle_t}' and 'std::thread::native_handle_type {aka ptw32_handle_t}')
       { return __x._M_thread < __y._M_thread; }

이 경우 CPLUS_INCLUDE_PATH환경변수를 확인하고 만약 설정되어 있다면 제거하자. 910

결국 이 INCLUDE PATH관련 문제가 아니라 pthread win32의 pthread.h와 c++11의 thread가 내부적으로 사용하는 mingw/include/pathread.h가 충돌나는 문제였다.

_stricmp c++11 not existent

c++11에서 _stricmp, _strdup, _fileno 등의 심볼을 찾을 수 없다. 그 답변은 아래와 같다.

The -std=c++0x option causes g++ to go into 'strict ANSI' mode so it doesn't declare non-standard functions (and _stricmp() is non-standard - it's just a version of strcmp() that's case-insensitive).
Use -std=gnu++0x instead.

LIBRARY_PATH variable error

GCC 소스코드를 사용하여 직접 설치할 경우 make단계에서 아래와 같은 에러가 발생될 수 있다.

checking LIBRARY_PATH variable... contains current directory
configure: error: 
*** LIBRARY_PATH shouldn't contain the current directory when
*** building gcc. Please change the environment variable
*** and run configure again.

Apparently, your LIBRARY_PATH ends in a colon:

/usr/lib/x86_64-linux-gnu/:
#  -----------------------^

Get rid of that:

export LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/

cannot open shared object file

GLIBCXX not found

컴파일 완료 후, 실행파일을 실행할 경우 아래와 같은 에러 메시지가 출력될 수 있다.

/usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.15' not found

이 경우 Linker 옵션에 -static-libstdc++를 사용하면 해결될 수 있다.

만약 위와 같이 수정해도 해결되지 않는다면 LD_LIBRARY_PATH환경변수를 확인해보자. 64bit의 경우 /usr/local/lib64와 같은 경로가 추가돼있지 않는 경우가 있다.

Undefined reference to ~

라이브러리 링크시 undefined reference to ~와 같은 메시지가 발생하며 정상적으로 링크되지 않는 현상이 발생할 경우 -l옵션으로 시작하는 라이브러리의 command-line 위치를 바꿔보면 해결될 수 있다. 예를 들면 g++ -L. -ltest main.o과 같이 컴파일 할 경우 g++ -L. main.o -ltest와 같이 변경해보면 정상적으로 컴파일될 가능성이 있다.

DSO missing from command line

DSO here means Dynamic Shared Object; since the error message says it's missing from the command line, I guess you have to add it to the command line.

virtual-move-assign

C++:Inheritance#virtual-move-assign문서를 참조.

warning: direct access in function

아래와 같은 경고가 발생될 수 있다.

ld: warning: direct access in function 'std::__1::basic_filebuf<char, std::__1::char_traits<char> >::open(char const*, unsigned int)' from file '/Path/To/Derived/Data/Xcode/DerivedData/myapp/Build/Intermediates/myapp.build/Debug-iphoneos/myapp.build/Objects-normal/arm64/myapp_lto.o' to global weak symbol 'std::__1::basic_filebuf<char, std::__1::char_traits<char> >::open(char const*, unsigned int)' from file '/Path/To/Derived/Data/Xcode/DerivedData/myapp/Build/Intermediates/myapp.build/Debug-iphoneos/myapp.build/Objects-normal/arm64/myapp_lto.o' means the weak symbol cannot be overridden at runtime. This was likely caused by different translation units being compiled with different visibility settings.

컴파일 시 -fvisibility=hidden을 사용하면 된다.

See also

Favorite site

GCC Online documentation

References


  1. MinGW_Static_and_Dynamic_Libraries_-_CodeProject.pdf 

  2. GCC_-Multiple_precompiled_headers_and_specific_paths-_Stack_Overflow.pdf 

  3. http://stackoverflow.com/questions/8843818/what-does-the-fpermissive-flag-do 

  4. GCC_optimization_-_Gentoo_Wiki.pdf 

  5. Gcc-march_options.pdf 

  6. Position_Independent_Code_-PIC-in_shared_libraries-_Eli_Benderskys_website.pdf 

  7. Pic_option_for_shared_library.pdf 

  8. GCC_Warning_Error_List-kor.pdf 

  9. Q1: https://kldp.org/node/151389 

  10. Q2: http://sourceforge.net/p/tdm-gcc/bugs/256/ 

  11. Linux_-_No_such_so_file.pdf 

  12. Cannot_open_shared_object_file_-_Litcoder.pdf 

  13. Naver_blog_GCC_Compile_process_and_commandline_options.pdf 

  14. GCC_Options_and_how_to_create_library.pdf 

  15. GCC 컴파일 과정과 생성되는 파일을 볼 수 있다. 

  16. GCC_and_Make_-_A_Tutorial_on_how_to_compile,_link_and_build_C_C++_applications.pdf 

  17. Create_so_file.pdf 

  18. Gcc_options.pdf 

  19. Gcc.4.7.2.zip