gcc를 이용한 컴파일 옵션
다음의 gcc 컴파일 명령어를 통해 사용되는 옵션에 대해 간략히 알아보자.
gcc -v -I/usr/local/include -DDEBUG -Wall -W -O2 -L/usr/local/lib -o like like.c -lm
- v: gcc C컴파일러의 옵션으로 컴파일 과정을 출력한다. (verbose)
- I/usr/local/include -DDEBUG: 전처리기(cc1 -E)의 옵션
- Wall -W -O2: cc1의 옵션
- L/usr/local/lib -o like like.c -lm: collect2의 옵션. 이는 ld를 호출 시 전달한다.
man gcc 명령을 통해 기능별 옵션 리스트를 볼 수 있다.
gcc 옵션 규칙
-
각각의 옵션에는 그에 상응하는 gcc 내부 변수가 존재한다.
-
gcc/options.c, gcc/options.h에는 gcc 옵션에 상응하는 변수들을 볼 수 있다.
extern int warn_unused_variable; extern int flag_branch_target_load_optimize; ...
-
예를 들어,
int warn_unused_variable
변수는Wunused_variable
옵션을 주면 값이 설정되는 변수이다. 아무런 옵션도 주지 않으면 기본 값이 0으로 설정된다.
-
-
[f|W|m][옵션]은 설정이고, -[f|W|m]no-[옵션]은 해제이다.
- Wno-unused_function을 이용해 0으로 해제한다.
-
동일 종류의 옵션은 최종 옵션만 옵션 변수에 설정된다.
- gcc ... -W-unused_function -Wno-unused_function 은 마지막 설정인 -Wno-unused_function이 적용된다.
-
그룹 옵션이 존재한다.
- fdump-tree-all 은 -fdump-tree-original, -fdump-tree-optimize ... 의 옵션을 동시에 준 것과 동일하다.
- O1, -Wall이 그러하다.
-
f는 플래그, -W는 경고, -m은 아키텍처 종속, 기타 나머지들이다.
gcc 필수 옵션 및 중요 옵션
- gcc C 컴파일러 드라이버 옵션
-E
: 전처리 과정의 결과를 화면에 보인다.-S
: 어셈블리 파일(*.s
)만 생성하고 컴파일을 멈춘다.-c
: 오브젝트 파일(*.o
)만 생성하고 컴파일을 멈춘다.-v
: 컴파일 과정을 화면에 자세히 출력한다.-save-temps
: 컴파일 과정의 중간파일인 전처리 파일(*.i
), 어셈블리 파일(*.s
), 오브젝트 파일(*.o
)를 지우지 않고 디렉토리에 저장한다.
cc1 -E
또는cpp0
전처리기 옵션-I
: 전처리 과정 중 헤더파일을 탐색하는 기본 디렉토리를 추가한다. 기본적으로#include <file>
형식은 시스템 헤더 디렉토리로 설정된/usr/local/include
,/usr/lib/gcc/i386-redhat-linux/4.1.2/inclue
,/usr/include
순으로 찾고,#include "file"
형식은 현재 디렉토리에서 먼저 찾고 위 순서로 찾는다. 따라서-I
옵션으로 디렉토리를 지정하면 시스템 헤더 디렉토리보다 우선해서 찾는다.-include {file}
: 헤더파일을 소스 내에 추가할 때 사용한다. 이는#include "file"
한 것과 동일한 결과를 나타낸다.-D{macro_name}
: 매크로를 외부에서 define할 때 사용한다. 이는 디버깅에서 많이 쓰인다.-D{macro_name}={value}
: 이는#define macro value
한 것과 동일한 결과를 나타낸다.-U{macro_name}
: 이는-D
와 반대의 결과를 나타내고,#undef macro
와 동일한 결과를 나타낸다.-M
,-MM
: (Makefile작성 시 유용한 )종속 항목(컴파일되기 위해 필요한 항목) 리스트를 출력한다.-M
은 make를 위한 소스 파일의 모든 종속 항목을 출력하고,-MM
은 기본 include 디렉토리에 있는 헤더 파일은 빼고 종속 항목을 출력한다.-nostdinc
: 디폴트 include 디렉토리(/usr/include 등
)에서 헤더 파일을 탐색하지 않고,-I
옵션으로 추가한 디렉토리에서만 헤더 파일을 탐색한다.-C
: 전처리 과정에서 주석을 제거하지 않는다.-Wp,{options}
: 전처리기의 옵션으로 전달하고자 할 때 사용한다. 이는 전처리기(cc1 -E
)와 C 컴파일러 드라이버(gcc
)의 옵션이 서로 동일하다면 해당 옵션은 C 컴파일러 드라이버의 옵션으로 처리되므로 gcc의 해석을 거치지 않고 전처리기로 옵션을 전달하고자 할 때 사용된다.
cc1
C 컴파일러 옵션-ansi
: ANSI C 표준에 부합하는 소스를 작성하려 할 때 사용된다.std={C std}
: C 표준 버전을 지정하고자 할 때 사용된다. 여기에는 c89, c99 등이 있다.-traditional
: Traditional C 문법으로 문법을 검사한다.-W
,-Wall
:-Wall
은 모든 모호한 문법에 대한 경고 메시지를 출력한다.-W
은 합법적이지만 모호한 코딩에 대해 부가적인 정보를 제공한다. 따라서 두 옵션을 모두 사용하는 것이 좋다.gcc -W -Wall -o main main.c
-w
: 모든 경고 메시지를 제거한다. 이는-Wall
,-W{options}
보다 우선시된다.-O0
: 어떤 최적화도 수행하지 않는다. 아무런 최적화 옵션을 주지 않으면-O0
를 준 것과 동일하다.-O1
,-O2
,-O3
: 해당 옵션 적용시 세부적인 사항은 다음의 링크를 통해 확인할 수 있다.-Os
: 사이즈 최적화를 수행한다. 이는 임베디드 시스템 같이 메모리 공간이 협소한 곳에서 자주 사용된다.-g
: 디버거에 제공하는 디버깅 정보(변수 타입, 전역 심볼명, 주소, 소스 라인정보 등)를 바이너리에 삽입한다. 이는readelf -a file
명령으로 읽을 수 있으며,.debug_*
로 시작되는 섹션들이 이에 해당한다. 이 또한-O
옵션처럼 레벨이 있는데-g0
는 아무런 디버깅 정보를 삽입하지 않고,-g
는-g2
와 동일하다.
as
의 옵션-Wa,{as options}
: 여기서 {as options}에 들어가는 옵션들은 다음과 같다.-al
: 어셈블 된 인스트럭션을 보여준다.-as
: 정의된 심볼을 보여준다.-I{path}
: include 디렉토리를 지정한다.-W
,--no-warn
: 경고 메시지를 출력하지 않는다.-march={architectur}
: 해당 어셈블리로 번역한다.
collect2
,ld
의 옵션-L{library_path}
: 라이브러리를 찾을 디렉토리를 지정한다. 기본적으로는/usr/i386-redhat-linux/lib
,/usr/local/lib
,/lib
,/usr/lib
순으로 찾는다.-l{name_library}
: 같이 링크할 라이브러리를 지정한다. 이 옵션은 main()함수가 있는 소스 파일의 뒤에 와야한다. 만약 그렇지 않다면undefined
참조 오류가 발생할 수 있다. 이는 링커가 아카이브를 찾는 데 있어 항상 main()함수 뒤에서 탐색하기 때문이다.-shared
: 공유 라이브러리와 정적 라이브러리가 같이 있을 경우 공유 라이브러리를 우선해서 링크한다. 이는 디폴트 옵션이기도 하다.-static
: 정적 라이브러리를 우선하여 링크한다. 이 경우, 파일의 사이즈가 커짐에 유의하자.-nostdlib
: 링크 시 표준 C 라이브러리를 사용하지 않는다.nostartfiles
: crt1.o, crti.o, ctrbegin.o, crtend.o, crtn.o와 같은 crt 오브젝트 파일들을 링크하지 않는다. 이는 OS, bootloader 같은 프로그램을 컴파일 시 사용된다.-Wl{liker_options}
,-Xliner f{liker_option}
:gcc -o main main.c -Wl,-M,-s
: collect2를 거쳐 ld에 -M -s 옵션이 전달된다.gcc -o main main.c -Xlinker -M -Xlinker -s
: 이 또한 위와 같다.- 다음은 사용 가능한 유용한 링커 옵션들이다.
-s
: 실행 파일에서 심볼 테이블 제거-x
: 출력 파일에서 로컬 심볼 제거-e{name}
: 시작 심볼을 name 심볼로 사용한다. 기본적으로 시작 심볼은_start
심볼이다.-M
: 링커 스크립트와 메모리 맵을 자세히 출력한다.
gcc를 이용한 최적화 컴파일
- machine dependent 옵션을 이용한 최적화
:-march={cpu_type} -mutne={cpu-type} -mcpu={cpu-type}
:
-march
옵션은 cpu-type으로 지정하는 프로세서의 instructio set으로 코드를 생성한다. 이는 아래에서 설명할-mtune
을 내부적으로 포함하므로-mtune
을 굳이 주지 않아도 무방하다.-mtune
옵션은 인스트럭션을 스케쥴링하거나 정렬할 때 해당 CPU에 최적화되게 스케쥴링 및 정렬한다. 이 때에는 CPU 파이프라인 단계, 각 인스트럭션을 수행하는 데 걸리는 사이클, 버스, 캐시 크기 등을 고려한다.-mcpu
옵션은-mtune
옵션과 거의 동일하다.- cpu-type으로
generic
을 사용할 수 있는데, 이때-march
에서는 사용할 수 없다. 이는 CPU 종류마다 인스트럭션 셋이 다르기 때문이다.
- 프로파일 결과를 이용한 최적화
: 컴파일한 프로그램을 한 번 더 수행해 프로그램의 동작 특성을 파악하여, 이 정보를 바탕으로 다시 컴파일하며 최적화하는 방법이다.gcc -O2 -o main main.c -fprofile-generate
를 통해 main 바이너리에 프로파일 정보를 출력하는 코드가 추가하여 컴파일한다.$ ./main
을 통해 프로그램을 수행한다.gcc -O2 -o main main.c -fprofile-use
를 통해 프로그램을 수행하며 수집한 정보를 바탕으로 좀 더 최적화하여 바이너리를 생성한다.
- 레지스터 활용을 통한 최적화
-fforce-mem
: 메모리에 있는 값을 레지스터에 로드해 연산을 수행한다. (GCC 4.2 below)-fforce-addr
: 메모리 주소 값을 레지스터에 로드 후 연산을 수행한다.
- gcc 컴파일 속도 최적화
-pipe
: 컴파일 과정에서 임시파일을 생성해 전달하지 않고 파이프로 전달해 컴파일 속도를 더 빠르게 한다.
기타
- 환경변수를 사용한 gcc 설정
- COMPILER_PATH: gcc는 COMPILER_PATH에 등록된 전처리기(cc1 -E), 컴파일러(cc1), 어셈블러(as), 링커(collect2, ld)를 찾는다. 따라서
export COMPILER_PATH={directory}
를 통해 원하는 전처리기, 컴파일러, 어셈블러, 링커를 선택케 할 수 있다. - C_INCLUDE_PATH, CPLUS_INCLUDE_PATH, OBJC_INCLUDE_PATH: 소스 파일을 전처리 할 때 헤더파일을 찾을 디렉토리를 지정하는 환경변수이다.
- LIBRARY_PATH: 라이브러리를 찾을 디렉토리를 지정하는 환경 변수이다.
- COMPILER_PATH: gcc는 COMPILER_PATH에 등록된 전처리기(cc1 -E), 컴파일러(cc1), 어셈블러(as), 링커(collect2, ld)를 찾는다. 따라서
- specs 파일을 이용한 gcc 설정
'빌드&테스트도구 > GCC&Make&CMake' 카테고리의 다른 글
CMake - (1) CMake의 전반적인 사항들 (0) | 2020.11.08 |
---|---|
make - make에 대한 개요 (0) | 2020.10.06 |
GCC - (4) 링커(ld)에 관하여 (0) | 2020.09.13 |
GCC - (2) gcc의 세부 과정 (0) | 2020.09.07 |
GCC - (1) C 컴파일 과정 개요 (0) | 2020.09.02 |