[재재질문]gcc 최적화 실행파일 만들기? -고수님 도와주세요

neohwang의 이미지

안녕하세요.
지난번에 질문을 올렸는데, 답변이 없어서 다시 요청합니다.
꼭 누가 좀 알려주세요.

gcc -o test main.c lib.c <엔터>

위와 같이 컴파일 하여 test 라는 실행파일을 만드는 과정에서,
lib.c 에 10개의 함수가 있습니다.
그중 실제로 main.c에서 참고하는 것은 3개 밖에 없을때,

컴파일 옵션에서 나머지 7개의 전혀 참조하지 않는 함수를 제외하고,
최적화된 실행파일을 만들수 있는 옵션이 있는지요?

있다면 어떻게 하는지 알려주시면 고맙겠습니다.

제가 테스트 해보니 자동으로 최적화가 되지는 않더군요.
예를 들어,

위의 경우 lib.c 에 있는 10개의 함수를 전혀 main.c 에서 참조하지 않아도,
lib.c 전체가 포함되더군요.

물론 제가 최종적으로 하고 싶은것은 lib.c에서 참조하는 함수가 3개 밖에 없을때, 그 3개만 실행파일에 추가된 최적화된(사이즈가 작은) 실행파일을 만드는 것입니다.

제발 고수님들이 도와주세요.

winner의 이미지

제가 아는 것과는 다르네요.

비록 test 해보지는 않았습니다만 정말로 그렇다면 기본 compile 은 모두 엄청나게 커진다는 것인데...

이해가 가지 않습니다.

제가 알기로 compile 과정이 끝나고 link 작업에 들어갈 때 필요한 module 만 link 할 텐데요.

어떻게 test 하셔서 그런 결론에 도달했는지 궁금합니다.

PHP 같은 interpreter 언어도 아니고 compiler 언어가 그런 것을 감안해서 실행file 을 만들지 않는다면 compiler 언어의 장점은 거의 없을 것입니다.

lib.c 가 거대하다면 가능한 좀더 여러 file 로 쪼개서 object file 을 만드는 것이 좋을 겁니다..
아무리 C 가 compile 시간이 많이 걸리지 않아도 거대한 code compile 하는 것은 시간이 많이 걸리는 법이니까요.

아시리라 봅니다만 object file 을 만드는 option 은 -c 입니다.
c 란 Compile only not link 에서 나온 것일 겁니다.

neohwang의 이미지

main.c 소스

#include <stdio.h>

int main(int argc, char *argv[])
{
	printf("Hello, world\n");
	
	return 0;
}

lib.c 소스

#include <stdio.h>

void print1(void);
void print2(void);
void print3(void);
void print4(void);
void print5(void);
void print6(void);
void print7(void);
void print8(void);

void print1(void)
{
	printf("111111111111111111111111111111111111111111111111111111111111111111111");
}
void print2(void)
{
	printf("111111111111111111111111111111111111111111111111111111111111111111111");
}
void print3(void)
{
	printf("111111111111111111111111111111111111111111111111111111111111111111111");
}
void print4(void)
{
	printf("111111111111111111111111111111111111111111111111111111111111111111111");
}
void print5(void)
{
	printf("111111111111111111111111111111111111111111111111111111111111111111111");
}
void print6(void)
{
	printf("111111111111111111111111111111111111111111111111111111111111111111111");
}
void print7(void)
{
	printf("111111111111111111111111111111111111111111111111111111111111111111111");
}
void print8(void)
{
	printf("111111111111111111111111111111111111111111111111111111111111111111111");
}

위의 경우에서 다음과 같이 컴파일 하면

gcc -o test main.c

사이즈가

-rwxrwxr-x 1 view view 13507 Sep 2 09:10 test

이렇게 됩니다.

근데, 다음과 같이 컴파일 하면

gcc -o test main.c lib.c

사이즈가

-rwxrwxr-x 1 view view 14101 Sep 2 09:10 test

이렇게 커집니다.

main.c 에서 lib.c에 있는 함수를 전혀 참조하지 않는데요...
제가 테스트 해보니, 전혀 참조되는 함수가 없는 lib.c 의 사이즈가 커지면 커질수록 test의 실행파일 사이즈가 계속 커진다는 것입니다.

혹시 옵션에서 이러한 것을 제거할 방법이 있는지 그게 궁금합니다.

물론 lib.c를 쪼개는 방법도 있지만,
이런 저런 프로그램에서 많이 사용하다 보니..... 그럼 도움 부탁 드립니다.

참고로 시스템 정보는 다음과 같습니다.

[view:/home/view/neo/beta/tmp]$ gcc -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/2.96/specs
gcc version 2.96 20000731 (Red Hat Linux 7.3 2.96-110)
[view:/home/view/neo/beta/tmp]$ uname -a
Linux localhost 2.4.18-3 #1 Thu Apr 18 07:37:53 EDT 2002 i686 unknown
[view:/home/view/neo/beta/tmp]$
monpetit의 이미지

neohwang wrote:
main.c 에서 lib.c에 있는 함수를 전혀 참조하지 않는데요...
제가 테스트 해보니, 전혀 참조되는 함수가 없는 lib.c 의 사이즈가 커지면 커질수록 test의 실행파일 사이즈가 계속 커진다는 것입니다.

lib.c를 main.c와 함께 컴파일하지 않고 따로 라이브러리로 만들어놓고 컴파일하면 main.c에서 lib.c의 함수를 전혀 사용하지 않는 한 실행파일의 크기는 커지지 않을 겁니다. 라이브러리의 장점이죠. 하지만 lib.c의 함수 중에서 단 하나라도 main.c에서 사용하면 lib.c의 함수 모두가 함께 따라옵니다.

neohwang wrote:
혹시 옵션에서 이러한 것을 제거할 방법이 있는지 그게 궁금합니다.

물론 lib.c를 쪼개는 방법도 있지만,
이런 저런 프로그램에서 많이 사용하다 보니.....


제가 아는 한 제거할 방법은 없습니다. 잘 다듬어진 정적 라이브러리는 거의 함수 1개당 파일 1개로 쪼개 놓더군요. 그게 힘들 경우엔 공유 라이브러리를 만들죠.

실행파일의 크기에 민감한 프로젝트가 아니라면 그냥 사용하시고, 아무리 해도 파일 크키를 양보할 수 없는 경우엔 그만큼 더 노력을 하셔야 합니다.

winner의 이미지

답변이 아니라 죄송합니다.

솔직히 저도 당연시 되겠지 하는 문제였는데 문제가 된다고 하니 궁금해서요.

link 단위는 object file 단위이며, object file 은 source file 단위로 compile 된다.
정적 library 에 object file 을 추가하면 해당 object file 단위로 추출을 해서 link 된다.

결국 library 의 통합관리는 source level 에서는 불가능하고, binary 에서 가능하며, 그 단위는 source(object) file 이다.

neohwang의 이미지

아~~~~~~~~~~~~~~

C 컴파일러 및 링커가 그 정도는 해 줄 줄 알았는데....
무척 아쉽군요.....

jokerol의 이미지

gcc 명령후에 main.c 와 lib.c 를 같이 나열하시니 나열된 2개 파일다 바이너리가
되어 합쳐 지겠죠, 저건 라이브러리로 사용되는 방식이 아니고 그냥 둘다 컴파일 해서
합친겁니다. 그러니까 사용 되든 안되든 두 파일이 합쳐지니 크기가 커지지요.

그리고 라이브러리로 만들게 되면, 함수 단위로 필요한 함수를 불러 오는게 아니고,
gcc 옵션의 -l -L 을 이용해 라이브러리 의 위치와 이름을 명시하면 명시된 파일
단위로 불러오는 거로 전 생각하고 있습니다(정적 라이브러리일 경우) 그리고 불러온
파일의 내용(오브젝트 파일)이 붙여지게 되는거고, 사용된 함수가 그 붙여진 부분에 있으면 찾아서
쓰는 거고 없으면 못 찾는다고 컴파일러가 에러를 내겠죠. 그래서 정적 라이브러리를 쓰면
용량이 커지는 겁니다. 하지만 실행 속도는 필요한 함수를 곧바로 찾아 쓸수 있으니 빠르겠지요

반면에 동적링크(공유 라이브러리) 는 여러 프로그램이 자주 쓰는 라이브러리를 메모리 상에
같이 올려놓고 프로그램이 실행 될때, 필요한 함수(라이브러리)를 이미 다른 프로그램에서 올려
놓았으면 거기서 찾아 쓰고 없으면, 에러를 내고 실행을 멈추죠. 그런면 때문에 공유랑이브러리가 맞지 않으면 실행안되며 속도도 정적링크 보다 조금 떨어지지만,
라이브러리 내용 변경시의 유연성,크기의 효율등과 같은 면 때문에 많이 쓰죠.

제가 쓴 내용중에도 아마 세부적으로 틀린 점들이 있을 거라고 생각합니다. 하지만 전체
내용 면에서는 거의 들어 맞을 겁니다.

참고로 리눅스에서 정적 링크파일은 .o 파일이며, 이걸 모아 놓은게 .a 파일이죠.
리눅스에서는 .so .so.2 등의 파일들이 공유 링크 파일 들입니다.

윈도우에서는 공유 라이브러리 포맷으로 dll 을 쓴다고 대충 알고 있습니다.

it takes a day to make you yawn, brother

it takes a day to make you yawn, brother

grassman의 이미지

GCC에도 smart linking이 구현되어 있어서 object 단위가 아닌 함수 단위의 제거가 됩니다.

http://kldp.org/node/94079

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.