본문 바로가기

awesome-c Beginner 번역/Building C Projects

<비공식 번역>awesome-c Beginner 번역 : 2. Standard directory detection

현재위치


1. Configuration

2. Standard directory dectection

3. Source file dependency calculation

4. Header file location

5. Header precompileation

6. Preprocessing

7. Compliation and assembly

8. Object file dependency calculation

9. Linking

10. Installation

11. Resource linking

12. Package generation

13. Dynamic linking

<주의!!>

nethack4.org의 'Building C Projects'의 공식적인 번역이 아니며 수를 받은 것 역시 아닙니다!!




2: Standard directory dectction(2: 표준 디렉토리 감지)


시스템 헤더 및 라이브러리의 처리의 어떤 종류를 처리할 수 있기 위해, 여러분은 먼저 그들이 어디에 있는지 아셔야합니다. 여러분은 앞서서 논의했던 libpq-fe.h같은 헤더 파일을 사용하기 위해 그 위치의 하위 디렉토리를 스캔할 수 있는 시스템 헤더의 위치를 알 필요가 있습니다. 공공목적으로 사용하려는 라이브러리는 거의 하위 디렉토리에 저장되지 않습니다; 그러나 aimake는 라이브러리가 특정 기호를 가졌는가를 결정하기 위해 내부를 볼 수 있어야 합니다. 그래서 표준 라이브러리의 집합도 찾을 필요가 있습니다.


시스템없이 하드 코딩된 지식과 함께 시스템의 헤더 및 라이브러리가 저장되는 위치를 결정하는 것은 실제로 매우 어려운 문제입니다. 그리고 대다수의 빌드 시스템에서 헤더파일의 위치와 오브젝트 파일 종속성 계산이 자동화되기보단 사람에게 남겨진 이유의 일부일 수 있습니다. 헤더와 라이브러리는 시스템의 어디에나 위치할 수 있습니다.(예를 들어 제 Windows시스템에서 컴파일러를 제 Document 디렉토리의 하위 디렉토리에 설치했습니다. 이는 완전히 임의의 이름을 가질 수 있음을 말합니다.); 우리가 실행가능한 C 툴체인의 위치를 안다고 가정하면 우리는 나머지를 찾을 수 있을까요?


저는 몇몇 기술적 시도를 했고 결국 합리적으로 보이는 휴대용 두 가지를 세팅했습니다. (이건 Linux의 gcc/clang과 GNU Id/gold, Windows의 mingw과 같이 동작하고 Mac OS X에서 비슷한 것과 같이 동작합니다. Mac은 다루는게 익숙하지 않기때문에 이 테스트는 다른 사람들에 의해 수행습니다.) :


  • 헤더 파일에서 전처리기는 그들을 포함할 수 있는 헤더파일의 위치를 알아야만 합니다. 그리고 질문에 대한 표준 옵션이 없더라도 종속성을 보고하기 위해 표준 옵션 (-M)이 있습니다. 따라서 우리가 필요한 모든 가능한 표준 헤더 파일 디렉토리 각각에 종속성 파일을 하나를 생성합니다.

    현재, aimake는 종속성으로 다섯 개의 헤더파일을 사용합니다. 소스에 있는 그것들은 완전히 설명해뒀습니만, 여기에는 제가 봤던 시스템에서 헤더파일을 정렬이 가능한 디렉토리의 짧은 개요를 다루었고 어떤 헤더파일은 aimake 테스트에 사용했습니다.

o 컴파일러와 함께 적재된 헤더파일(<iso646.h>, 실제로 컴파일러에 적재하지 않을 이유가 없기 때문입니다. 특히 많은 C 라이브러리는 이 헤더파일을 적재하지 않습니다.);


o 컴파일러에 의해 패치된 헤더파일(<limts.h>, gcc가 무조건 패치하는 파일);


o 아키텍쳐-기반 헤더파일 (<sys/typed.h>; 대부분의 시스템에서 표준 C 헤더의 어느것도 이것을 저장하지 않습니다, 그래서 저는 대부분의 아키텍처-기반 POSIX 헤더를 사용합니다.);


o C 라이브러리와 함께 적재된 헤더파일 (<setjmp.h> 는 제가 모든 시스템에서 테스트 카테고리에서 찾아낸 헤더입니다. 아마도 이 헤더는 컴파일러에게 너무도 이상하고 엉망이기 때문일 것입니다.);


o 라이브러와 함께 적재된 비표준(즉 non-C/POSIX) 헤더파일 (<zlib.h>, zlib는 세계에서 가장 폭넓게 사용되는 라이브러리 중 하나이기 때문입니다.).


  • 라이브러리의 경우, 링커(linker)가 다시 찾고있는 곳을 찾아낼 수 있는 표준적인 방법은 없습니다. 심지어 알고 있어야 하지만; 비록 gcc-에 특정적이라도 저는 gcc --print -search-dirs를 시도합니다, 그러나 이것은 시스템의 모든 라이브러리 디렉토리보다는 오직 gcc가 내부용도로 필요한 라이브러리 디렉토리를 찾아내는 듯합니다. 대부분 제가 찾아낸 휴대용 방법은 링커에게 우리가 다루는 작은 테스트 파일의 각 라이브러리에서 연결하도록 요청합니다. (한번에 하나씩(one at a time) 라이브러리 찾기는 수행하여 실패하더라도 다른 라이브러리 검색에 영향을 끼치지 않도록 합니다.), 그리고 디버그 추적(trace) 생성을 얻습니다.

    이 방법을 쓸때는 몇가지 문제가 있습니다.(비록 전 어떠한 경우에도 사용하지만) 첫 번째는 추적을 위해서 링커에게 요청하는 옵션이 표준 (-t)지만 결과 포맷이 없고, 라이브러리에 링크되고 있는 이유에 따라 하나의 링커에 엄청나게 다를 수 있습니다. 여기 정규식은 aimake가 결과물을 파싱하기 위해 사용합니다.(aimake의 일부분도 제거된 소스 파일의 매칭을 회피를 위해 사용합니다, 그리고 리눅스에 맞게 파일 확장자를 설정; 다른 시스템에서는 파일 확장자의 변경이 필요합니다.)

    /^(?:(?:-l|lib)[^ ]+ )?\(?(.*?\/.*?(?:\.a|\.o|\.so)(?:\.[0-9]+)?)(?:\)|\([^\/]*\)|\z)/

    다음 문제는, 이 일치하는 파일을 보고 때때로 그것들 중 일부는 텍스트 파일이 될 것입니다! 이 문제는 라이브러리 개발자가 가끔 이전 버전과의 호환성 때문에 이상한 일을 하기 때문입니다. 여기 제 우분투 시스템의 libncurses.so 의 전체 모습입니다.

    INPUT(libncurses.so.5 -ltinfo)

    저는 확실히 모르지만, 무슨 일이 일어난지에 대한 제 추측으론 libcurses는 과거의 언젠가 두개의 라이브러리로 쪼개졌고(libncurses와 libtinfo), 따라서 libncurses.so는 두 라이브러리를 끄는 링커 스크립트로 포장 되었습니다. 명백히 이 스크립트는 라이브러리에 존재하는 심볼의 존재 결정에는 쓸모없습니다. 그러나 링커 추적은 끌어들인 라이브러리 양쪽 모두를 포함합니다, 그래서 그러한 포장과 함께 필수적인 모든 것은 무시합니다. aimake는 첫 킬로바이트를 스캔하거나 비 ASCII문자를 라이브러리에서 찾습니다; 어떠한 것도 검색에 실패한다면 "라이브러리"는 실제로 링커 스크립트라고 간주합니다.

    그것의 또다른 이슈는, 만약 우리가 라이브러리로 부터 적어도 하나의 심볼조차 사용하지 않는다면, 링커를 최적화 할 수 있습니다; 그리고 어떤 상황에서(예를 들면 정적 라이브러리의 경우), 링커 추적 결과를 보여주지 않을 것입니다. 현재 aimake는 구성파일에서 사용자가 요구할지도 모르는 라이브러리를 검색합니다 (성능적 이유; 심볼에 대해 전체 시스템에서 모든 라이브러리 검색은 제 랩탑에선 시간단위로 걸리기 때문이죠), 그래서 저는 라이브러리에서 사용자가 기대하는 심볼의 이름을 요청에 의해 해결했습니다, 그리고 aimake는 표준 -u 옵션을 사용해서 강제로 링커와 연결합니다. 이러한 접근의 추가적인 잇점은 동일한 이름의 다른 라이브러리보다 우리가 예상하는 라이브러리를 찾는데에 안정적입니다.

    시스템의 표준 라이브러리에 대한 부작용은, 기본적으로 연결되어 있다는 것입니다. (올바르게 종속성 계산을 수행하기 위해 이들을 분석하는 일이 필요한데다 어떤 종속성도 명시적일 필요는 없으며, 우리는 또한 링커에게 전달할 필요가 없습니다, 만약 여러분이 명시적으로 표준 라이브러리를 연결한다면 Mac OS X의 링커는 불평하고 빌드를 혼란스러워 합니다.) 우리는 파일들 사이를 분할할 방법을 알 수 없습니다, 그래서 심볼을 지정하면 아무 소용이 없게 됩니다. 따라서 저는 결국 링커에게 표준 라이브러리의 모든 심볼에서 연결을 요청하는 직접적인 방법을 정착할 필요가 있었습니다 (--whole-archive, 에다가 --allow-multiple-definition을 추가해 여러분이 얻을 결과에서 스팸 에러의 양을 줄입니다.) 이것은 보통 이용 가능한 출력 파일을 생성하지 않습니다 (정말로 예상되지도 않습니다), 그러나 aimake는 출력 추적에 대해 이 부분을 신경쓰지 않습니다. 부가적으로 이것은 mingw 링커의 충돌 원인입니다, 그러나  이미 aimake가 필요한 출력 추적이 완료된 이후의 일이죠. (이것은 윈도우에서 NetHack 4를 빌드하면 Id.exe충돌에 대해 에러 다이얼로그가 뜨는 이유를 알 수 있습니다.)


이 모든것은 저를 귀찮게 합니다, 무언가로서 이 일은 어려울 필요가 없는 기본입니다. 저는 시스템 불가지론적 관점에서 이 문제에서 어느 누구도 본질적인 시스템 별 정보를 확인하려 노력하지 않을 것이라 추측합니다. (헤더와 라이브러리가 설치되는 위치)



출처1 : https://github.com/aleksandar-todorovic/awesome-c

출처2 : http://nethack4.org/blog/building-c.html