Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 3개 있습니다.)
(시리즈 글이 4개 있습니다.)
Linux: 5. Linux 응용 프로그램의 (C++) so 의존성 줄이기(ReleaseMinDependency)
; https://www.sysnet.pe.kr/2/0/11845

개발 환경 구성: 698. Golang - GLIBC 의존을 없애는 정적 빌드 방법
; https://www.sysnet.pe.kr/2/0/13490

Linux: 64. Linux 응용 프로그램의 (C++) so 의존성 줄이기(ReleaseMinDependency) - 두 번째 이야기
; https://www.sysnet.pe.kr/2/0/13494

Linux: 76. Linux - C++ (getaddrinfo 등을 담고 있는) libnss 정적 링크
; https://www.sysnet.pe.kr/2/0/13679




Linux 응용 프로그램의 (C++) so 의존성 줄이기(ReleaseMinDependency)

Visual C++의 경우 msvcr[version].dll에 대한 정적 링크를 다음과 같이 하면,

수동으로 구성해 본 VC++프로젝트 설정: ReleaseMinDependency
; https://www.sysnet.pe.kr/2/0/800

(* Visual Studio 버전에 따라 설정 옵션이 차이가 있습니다.)

순수하게 윈도우 시스템 dll에 대한 의존성만 갖게 됩니다. 마찬가지로 Linux 응용 프로그램도 그렇게 만들고 싶었는데요. 기본적으로는 다음과 같이 libstdc++, libgcc_s.so.1, libc.so.6에 대한 C/C++ 관련 런타임이 동적으로 바인딩되어 있습니다.

$ ldd ./projects/testapp/bin/x64/Debug/testapp.so
        linux-vdso.so.1 (0x00007ffdc17d4000)
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f71662ce000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f71660b6000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7165cc5000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f7165927000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f716686a000)

회사의 리눅스 개발자에 의하면, 다음의 옵션을 통해 libgcc_s와 libstdc++에 대한 의존성을 제거할 수 있다고 합니다.

[Linker / "Command Line"의 "Additional Options"]

-static-libgcc -static-libstdc++

빌드하면 이렇게 홀쭉해진 것을 볼 수 있습니다. ^^

~$ ldd ./projects/testapp/bin/x64/Debug/testapp.so
        linux-vdso.so.1 (0x00007ffd587e4000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2f521c9000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f2f527e7000)

그런데, CRT(C Runtime) 라이브러리인 libc.so.6에 대한 의존성을 제거할 수가 없습니다. 그래서 Visual C++와는 달리 libc 만큼은 빌드 환경과 실행 환경을 고려해야 합니다. (혹시 libc 의존성 없애는 방법을 아시는 분은 덧글 부탁드립니다. ^^)




검색해 보면, libc 의존성을 없애기 위해 "-static" 옵션을 주면 된다는 글들이 있습니다. 하지만 이 옵션을 [Linker / "Command Line"의 "Additional Options"]에 함께 주면 빌드 시 다음과 같은 식의 오류가 발생합니다.

1>  Linking objects
1>  Invoking 'ld'
1>  g++ -o "/home/usr23/projects/testapp/../testapp/bin/x64/Release/libtestapp.so" -Wl,--no-undefined -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -shared -static /home/usr23/projects/testapp/../testapp/obj/x64/Release/ClassFactory.o /home/usr23/projects/testapp/../testapp/obj/x64/Release/testapp.o /home/usr23/projects/testapp/../testapp/obj/x64/Release/dllmain.o /home/usr23/projects/testapp/../testapp/obj/x64/Release/ILRewriter.o
1>  /usr/bin/ld : error : /usr/lib/gcc/x86_64-linux-gnu/7/crtbeginT.o: relocation R_X86_64_32 against hidden symbol `__TMC_END__' can not be used when making a shared object
1>  /usr/bin/ld : error : final link failed: Nonrepresentable section on output
1>  collect2 : error : ld returned 1 exit status
1>  /usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/7/crtbeginT.o: relocation R_X86_64_32 against hidden symbol `__TMC_END__' can not be used when making a shared object
1>  /usr/bin/ld: final link failed: Nonrepresentable section on output
1>  collect2: error: ld returned 1 exit status

__TMC_END__ 오류에 관한 것을 다시 검색해 보면,

how to make a static binary of coreutils?
; https://askubuntu.com/questions/530617/how-to-make-a-static-binary-of-coreutils

다음과 같이 기존 crtbeginT.o를 crtbeginS.o로 덮어씌우면 됩니다.

$ g++ --version
g++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ cd /usr/lib/gcc/x86_64-linux-gnu/7.3.0
$ sudo cp crtbeginT.o crtbeginT.orig.o
$ sudo crtbeginS.o crtbeginT.o

실제로 이렇게까지 처리하면 컴파일/링킹 오류는 발생하지 않습니다. 문제는 바이너리 의존성이 오히려 원래대로 돌아가 버립니다.

$ ldd ~/projects/testapp/bin/x64/Release/libtestapp.so
        linux-vdso.so.1 (0x00007fff71fe9000)
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fa2814f0000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa2810ff000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa280d61000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fa281a8a000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fa280b49000)




참고로 우분투의 경우 g++ 8 버전을 다음과 같이 설치할 수 있습니다.

$ sudo add-apt-repository ppa:ubuntu-toolchain-r/test
$ sudo apt-get update
$ sudo apt-get install gcc-8 g++-8
$ gcc-8 --version

그럼 /usr/lib/gcc/x86_64-linux-gnu/8 디렉터리에 g++ 8 버전 관련 파일들이 설치됩니다. 이렇게 설치해도 기본적으로 gcc, g++ 명령시에는 g++-8 컴파일러가 동작하지 않습니다. (이를 위해서는 별도의 처리를 해야 하는데 이건 나중에. ^^)




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 12/20/2023]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2019-05-20 10시26분
$ sudo apt install pax-utils
$ lddtree /bin/ps
정성태
2019-05-20 10시33분
The 101 of ELF files on Linux: Understanding and Analysis
; https://linux-audit.com/elf-binaries-on-linux-understanding-and-analysis/
정성태
2019-05-20 10시34분
정성태

... 61  62  63  64  65  66  67  68  [69]  70  71  72  73  74  75  ...
NoWriterDateCnt.TitleFile(s)
12211정성태4/27/202019264개발 환경 구성: 486. WSL에서 Makefile로 공개된 리눅스 환경의 C/C++ 소스 코드 빌드
12210정성태4/20/202020707.NET Framework: 903. .NET Framework의 Strong-named 어셈블리 바인딩 (1) - app.config을 이용한 바인딩 리디렉션 [1]파일 다운로드1
12209정성태4/13/202017414오류 유형: 614. 리눅스 환경에서 C/C++ 프로그램이 Segmentation fault 에러가 발생한 경우 (2)
12208정성태4/12/202015977Linux: 29. 리눅스 환경에서 C/C++ 프로그램이 Segmentation fault 에러가 발생한 경우
12207정성태4/2/202015827스크립트: 19. Windows PowerShell의 NonInteractive 모드
12206정성태4/2/202018443오류 유형: 613. 파일 잠금이 바로 안 풀린다면? - The process cannot access the file '...' because it is being used by another process.
12205정성태4/2/202015105스크립트: 18. Powershell에서는 cmd.exe의 명령어를 지원하진 않습니다.
12204정성태4/1/202015104스크립트: 17. Powershell 명령어에 ';' (semi-colon) 문자가 포함된 경우
12203정성태3/18/202017949오류 유형: 612. warning: 'C:\ProgramData/Git/config' has a dubious owner: '...'.
12202정성태3/18/202021208개발 환경 구성: 486. .NET Framework 프로젝트를 위한 GitLab CI/CD Runner 구성
12201정성태3/18/202018438오류 유형: 611. git-credential-manager.exe: Using credentials for username "Personal Access Token". [1]
12200정성태3/18/202018529VS.NET IDE: 145. NuGet + Github 라이브러리 디버깅 관련 옵션 3가지 - "Enable Just My Code" / "Enable Source Link support" / "Suppress JIT optimization on module load (Managed only)"
12199정성태3/17/202016172오류 유형: 610. C# - CodeDomProvider 사용 시 Unhandled Exception: System.IO.DirectoryNotFoundException: Could not find a part of the path '...\f2_6uod0.tmp'.
12198정성태3/17/202019532오류 유형: 609. SQL 서버 접속 시 "Cannot open user default database. Login failed."
12197정성태3/17/202018829VS.NET IDE: 144. .NET Core 콘솔 응용 프로그램을 배포(publish) 시 docker image 자동 생성 - 두 번째 이야기 [1]
12196정성태3/17/202015948오류 유형: 608. The ServicedComponent being invoked is not correctly configured (Use regsvcs to re-register).
12195정성태3/16/202018268.NET Framework: 902. C# - 프로세스의 모든 핸들을 열람 - 세 번째 이야기
12194정성태3/16/202020999오류 유형: 607. PostgreSQL - Npgsql.NpgsqlException: sorry, too many clients already
12193정성태3/16/202017915개발 환경 구성: 485. docker - SAP Adaptive Server Enterprise 컨테이너 실행 [1]
12192정성태3/14/202019939개발 환경 구성: 484. docker - Sybase Anywhere 16 컨테이너 실행
12191정성태3/14/202021047개발 환경 구성: 483. docker - OracleXE 컨테이너 실행 [1]
12190정성태3/14/202015628오류 유형: 606. Docker Desktop 업그레이드 시 "The process cannot access the file 'C:\Program Files\Docker\Docker\resources\dockerd.exe' because it is being used by another process."
12189정성태3/13/202021231개발 환경 구성: 482. Facebook OAuth 처리 시 상태 정보 전달 방법과 "유효한 OAuth 리디렉션 URI" 설정 규칙
12188정성태3/13/202026020Windows: 169. 부팅 시점에 실행되는 chkdsk 결과를 확인하는 방법
12187정성태3/12/202015597오류 유형: 605. NtpClient was unable to set a manual peer to use as a time source because of duplicate error on '...'.
12186정성태3/12/202017402오류 유형: 604. The SysVol Permissions for one or more GPOs on this domain controller and not in sync with the permissions for the GPOs on the Baseline domain controller.
... 61  62  63  64  65  66  67  68  [69]  70  71  72  73  74  75  ...