gcc
gcc
:
- GNU C/C++ Compiler의 약자.
- Linux계열 system에서 가장 많이 사용되는 compiler.
- 주로 C program을 compile할 때 사용된다.
gcc는 C program 뿐만 아니라 ADA, Java와 같은 다양한 language를 compile할 수 있도록
architecture가 설계되어 있다.
- C++ Program을 compile하려면 g++라는 별도의 compiler를 사용.
- gcc는 소스파일부터 실행파일까지 여러 일을 수행한다.
- preprocessing : 매크로 처리
- compilation, assembly
- linking
cross-compile
:
예를 들어 x86에서 ARM용 object code를 생성하는 cross-compile도 gcc를 통해서 한다.
Building an executable file
ld
라고 하는 linker가 object file을 실행파일(a.out
)로 만들어줌
- gcc가 직접적으로 일을 할 때는 2.뿐이고,
Preprocessing, assembling, linking할 때는 gcc가 기타 명령어들을 내부적으로 호출하여 사용함.
gcc architecture
- gcc architecture는 왜 3단계로 나누어져 있는가?
Front End
:
어떠한 language가 오던지 Generic이라고 하는 중간 코드로 변환한다.
만약 우리가 새로운 언어를 만들었다면,
Front End에 Generic으로 변환할 수 있는 module을 넣어줘야 한다.
Middle End
:
Front End에서 생성된 Generic(중간코드)을 최적화하는 과정을 거친다.
opt(optimization pass 1 ~ N)
최적화를 통해 RTL(Register Transfer Language)이라는 언어로 변환한다.
Back End
:
RTL 형태의 중간코드를 실제 machine code로 변환한다.
x86이라면 x86용 assembly code로 만들고,
ARM이라면 ARM용 assembly code로 만듦.
➡️ language와 target architecture에 관계없이 항상 공통되었다.
그래서 새로운 언어를 개발했으면,
middle end와 back end는 그대로 사용하고,
front end에서 새로운 언어에 대한 generic format으로 만들어 줄 module만 넣어주면 된다.
➡️ 만약 새로운 architecture를 개발했다면,
새로운 architecture에 대해 assembly code로 변환시킬 back end를 만들면 된다.
gcc 간단한 사용법
- gcc -o hello hello.c -g -Wall
-o
: tells the compiler to name the executable
-g
: adds symbolic information to hello for debugging
-Wall
: tells it to print out all warnings
gcc major options
Compiler path options
- -Idir : 해당 dir에서 header file을 cumulative하게(반복해서) 찾아라.
- -Ldir : 해당 dir에서 library를 cumulative(반복해서) 찾아라.
- -l : Link to lib;
- lfoo : links to libfoo.so(shared library) if it exists, or to libfoo.a(static library) as a second choice
Compiler preprocessor options
- -E : Preprocessing only
(gcc가 preprocessor까지만 불러서 사용하고 그 다음인 compiling, assembling, linking을 하지 말고 멈춰라.)
- -Ddef : Define def
(외부 define을 사용할 수 있다.)
- -Udef : Undefin def
(외부 define을 사용할 수 없다.)
Compiler warning options
- -v : verbose mode.
(message를 많이 찍어줘라 + gcc version 정보)
- -w : Suppress warnings
(message를 적게 찍어줘라)
- -W : More verbose mode
(-v보다 더 많이 찍어줘라)
- -Wall : 모든 warning을 찍어줘라
Complier debugging options
- -g : gdb의 정보를 포함하라
- -pg : profiler의 정보를 포함하라
(profiler를 통해 어떤 함수의 어떤 부분에서 시간을 많이 소요하는지 정보를 얻을 수 있음)
-
-c : Stop after creating object files, don't link
(linking단계 직전인 assembling까지만 하라.)
= (실행파일을 만들지 말고 object file까지만 만들어라)
-
-o file명 : 지정한 file명으로 실행파일을 생성하라.
Compiler control options
- -ansi : c90이라는 문법 standard에 맞게 compile하라
- -pedantic : c standard에 있는 문법들만 사용하고, extension을 사용하지 마라
- -std=c99 : c99에 맞게 compile하라.
- -O[lev] : 최적화 level을 설정. (0, 1-default, 2, 3가 있는데, 2 level을 주로 사용한다)
- -Os : 속도를 위한 최적화가 아닌, size를 위한 최적화를 해라
Common set of options
-O2 -Wall -pedantic
:
- -O2 : Level 2까지 optimization 해라.
- -Wall : 모든 Warning message를 출력해라
- -pedantic : gcc extension 말고, 순수한 C언어 문법에만 맞도록 compile하라.
Linux kernel을 compile할 때는 gcc extension을 많이 사용하기 때문에 -pedantic 옵션을 사용하면 안된다.
gcc example
example 1
:
Object file 생성 (linking 전 assembling까지만 수행) :
실행 file 생성 (Linking) :
example 2
:
여러 파일에서 include하면 중복이 많아지기 때문에 "funcs_2.h"처럼 만들 수 있다.
Library
-
Library
: compile된 다양한 object file들을 모아놓은 file들.
예를 들어, pThread Library는 thread에 관련된 함수들을 종합적으로 모아놓은 file.
-
Library는 두가지 type으로 나눌 수 있다.
- Static Library (정적 라이브러리)
- Shared Library (공유 라이브러리 = 동적 라이브러리)
1. Static Library
Static Library
: Link at compile time
How to build/use an archive file(=static library)
-
ar
: creates, updates, lists and extracts files from the library
-
nm
: 생성한 정적 라이브러리에 만든 함수들이 있는지 확인할 수 있다.
Example
-
example 2
: nm(생성한 정적 라이브러리에 만든 함수들이 있는지 확인할 수 있다.)
-
example 3
: ldd (해당 프로그램이 돌기 위한 라이브러리)
-
example 4
: -static (필요한 라이브러리들을 해당 파일에 한꺼번에 저장. 버전정보가 달라져도 피해 없음)
2. Shared Library
Shared Library
: Linked to any program at run-time
Building a Shared Library
- Functions must be
reentrant
= No global variables
:
여러 program들이 공유 라이브러리를 공유할 때, 간섭효과를 없애야 한다
- Code must be
position-independent
:
공유 라이브러리가 memory 어디에 load될지 가정하고 program을 짜면 안된다.
항상 바뀌기 때문.
Shared library names
- libmyfuncs.so.1.0 : 실제로 생성한 library
- libmyfuncs.so.1 : library가 runtime에 사용될 때, 누구를 pointing하는지에 따라 어떤 version이 사용될지 결정된다.
(.so.1.0, .so.1.1, ...)
- libmyfuncs.so : .so는 실제 파일이 아니라, libmyfuncs.so.1.0의 symbolic link이다.
Finding shared libraries at runtime
- library를 link할 때, 모든 directory를 다 찾아볼 수 없으니까 어느 directory를 찾아볼지 지정해줄 수 있다.
- system library : /etc/ld.so.conf
- 자체 library : LD_LIBRARY_PATH라는 환경변수에 해당 공유라이브러리가 있는 경로를 적어준다.
ex: LD_LIBRARY_PATH=$HOME/foo/lib
Example
example 1
:
궁금한 점> symbolic link를 만드는 것을 lib directory에서 수행하면 되는데,
lib directory의 상위 directory에서 수행하면 안된다..
1. 실험 : /lib의 상위 directory에서 ln -s 수행, 상위에서 export, 오류 :
2. 실험 : /lib의 상위 directory에서 ln -s 수행, /lib에서 export, 오류 :
3. 실험 : /lib에서 ln -s 수행, /lib의 상위 directory에서 export, 정상동작 :
4. 실험 : /lib에서 ln -s 수행, /lib에서 export, 정상동작 :
/lib에서 symbolic link를 만들 때만 정상 동작.. 왜 그럴까?
symbolic link(libshared.so와 libshared.so.1)가 libshared.so.1.0을 pointing하는데,
libshared.so는 link할 때 사용되고,
libshared.so.1은 runtime할 때 사용된다.
만약 ln -s lib/libshared.so.1.0 lib/libshared.so 라고 했으면
libshared.so는 lib/libshared.so.1.0을 pointing하기 때문에 엉뚱한 곳을 pointing하는 것이라 linking이 안됐던 것임.
그래서 아래와 같이 해야 제대로 linking된다.