2010-05-05 3 views
0

정적 라이브러리를 참조하는 응용 프로그램을 컴파일 할 때 gcc 컴파일러가 특정 최적화를 수행 할 수 있다는 것을 읽었습니다. 예를 들어 정적 코드에서 "pull" 응용 프로그램이 의존하는 라이브러리 이렇게하면 정적 라이브러리의 일부가 앱에서 사용되지 않는 경우 응용 프로그램의 실행 파일 크기를 최소로 유지할 수 있습니다.GCC가 정적 라이브러리를 참조하는 응용 프로그램을 컴파일하는 방법

1) 사실입니까?

2) GCC는 응용 프로그램이 실제로 사용하는 정적 라이브러리의 코드를 어떻게 알 수 있습니까? 그것은 응용 프로그램에 포함 된 (직접 및 간접적으로) 헤더 파일을 찾은 다음 이에 따라 코드를 가져 옵니까? 아니면 정적 라이브러리에서 어떤 메소드가 호출되는지 실제로 확인합니까?

답변

2

정적 라이브러리는 개체 파일의 모음입니다. 링커 (ld)는 어떤 객체 파일이 사용되었는지 (즉, 어딘가에서 참조 된 함수를 포함하고 있음) 추적하고 최종 실행 가능 이미지에 참조되지 않은 코드를 포함하지 않습니다.

1

gcc 아무 것도하지 않습니다. 모두 당신이 설명하는 , ld에 의해 처리됩니다 연결입니다.

ld는 개체 파일의 기호 테이블을 검사하여 어떤 기호를 연결해야하는지 결정한 다음 관련 개체 파일을 라이브러리에서 가져 와서 실행 파일에 연결합니다.

1

답변
1) 예, 참조 된 코드 만 가져옵니다. 정적 라이브러리에는 라이브러리에서 내 보낸 모든 심볼의 인덱스 테이블이 포함되어 있기 때문에 작은 크기 외에도 링크 속도가 향상됩니다. 객체 파일을 하나 하나 찾아 보는 것과는 대조적으로이 테이블에서 조회가 더 빠릅니다.
또는 참조에 관계없이 정적 라이브러리의 모든 심볼을 가져 오려는 경우 --whole-archive 스위치를 ld에 전달할 수 있습니다.

2) ld (gnu 링커)의 문맥에서이 질문을하는 것이 더 정확할 것입니다. 왜냐하면 이것이 실제로 참조를 끌어 들이기 때문입니다. GCC는 컴파일이 끝나면 링커를 호출한다 (gcc -c를하지 않으면 컴파일이 중단된다). 따라서 컴파일이 완료되면 ld는 객체 (.o) 파일 및 라이브러리의 정렬 된 목록으로 호출됩니다. ld는 .o 파일을 하나씩 처리하고 각 링커에 대해 a) 아직 해결할 수없는이 파일에 필요한 외부 기호를 적어 두십시오. 이것들을 미해결의 테이블에 추가합니다. b)이 파일에서 내 보낸 기호 (함수, 전역 변수)를보고 이전에 수행 한 모든 참조를 해결합니다. 이것은 연결 프로세스에 대한 매우 간단한 개요입니다. 이제 링커가 정적 라이브러리에 오면 기본적으로 정적 라이브러리를 사용하여 심볼을 해석하는 것과 동일한 작업을 수행합니다. 그러나 한 가지 차이점이 있습니다. 링커는 확인되지 않은 기호와 종속 항목 만 가져옵니다. 따라서 우리는 a.o와 libstatic.a를 가지고 있고, 차례로 b.o와 c.o가 있다고 가정합니다.
b.o는 bar() 및 moreBar()를 정의합니다.
c.o는 baz() 및 moreBaz()를 정의합니다.
a.o는 foo()를 정의합니다.
여기서 foo는 baz를 호출하는 bar를 호출합니다. 이제 당신이 할 때 gcc -o app a.o libstatic.a 링커는 a.o를 처리 한 후에 바를 해결해야한다는 것을 알고 있지만 바를 해결하는 동안 링커는 바가 baz가 필요하다는 것을 알게됩니다. 이것은 libstatic.a에서 다시 해결됩니다. moreBar() 및 moreBaz()는 참조가 없으므로 무시됩니다.

관련 문제