본문 바로가기

awesome-c Beginner 번역/Building C Projects

<비공식 번역>awesome-c Beginner 번역 : 4. Header file location

현재위치


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'의 공식적인 번역이 아니며 수를 받은 것 역시 아닙니다!!




4: Header file location(헤더파일 위치)


헤더파일을 포함하기 위해서 여러분은 파일시스템에서 그것들을 찾을 수 있어야 합니다. 전처리기의 대부분에 의해서 사용하는 알고리즘은 매우 단순합니다: 전처리기는 사용자가 추가할 수 있는 하드코드된 디렉토리 목록을 가지고 있습니다. 그리고 전처리기는 그것들을 시퀀스안에서 그 파일들을 찾을때까지 스캔할 것입니다. file.h를 포함(include)하는 경우 또한 소스 파일이 포함되어있는 디렉토리를 스캔할 것입니다.


작은 프로젝트에서는 충분하지만 큰 프로젝트에서는 이 방법은 매우 부적절합니다. 작은 프로젝트와는 달리 큰 프로젝트는 보통 대부분이 연관이 없는 여러가지 부분으로 형성될 것입니다. 그리고 분리된 소스에서 함께 이름의 충돌이 있습니다. 지금까지 NetHack 4는 우리가 제공한 헤더파일간의 이름 충돌을 피하기 위해 관리하고 있습니다. (현재 여러 소스파일에서 여섯개의 이름을 쓰고 있지만:dump.c, log.c, messages.c, options.c, topten.c windows.c) 그러나 프로젝트가 커질수록 점점 어려워집니다.


또다른 문제는 해결책은 간단하지만 어떤 사람들을 포착하기 때문에 언급할 가치가 있습니다: 모든 C 컴파일러는 그들이 동작하는 시스템에서 올바르게 구성되어 있지는 않아, 그 결과 시스템의 헤더파일을 놓칠 수 있습니다. 대체적으로 이러한 현상을 리눅스 시스템의 /usr/local/include 에서 봐왔습니다. 이는 운영체제의 패키지 매니저에 의했다기 보다는 수동적인 설치 한 시스템 전체의 헤더파일이 대상입니다. 해결방법은 그저 명령 옵션(command-line option)을 사용하여 컴파일 할때마다 디렉토리를 포함하는대로 추가하는 것입니다.


어찌됐든, 이름 충돌에 관한 가능성의 결과로서, 헤더파일 세트가 각각의 소스파일에 포함하도록 해당 파일에 개별적으로 결정이 필요합니다. 빌드 시스템에서 일반적인 해결방법은 수동으로 작업하는 것입니다; 사용자는 헤더파일을 스캔하기위해 디렉토리 목록을 지정할 것입니다. 일반적으로 옵션으로 있는 프로젝트 전체 목록의 옵션은 특정 소스 파일을 오버라이드(override)합니다. 이러한 사양을 루프의 일종으로 지정하는 것은 매우 간단한 경향이 있고 쓰기 어려운 것은 아닙니다. 그러나 인간이 실수하는 에러의 기회가 증가하면서 모든 것은 기록될 필요가 있습니다. (그리고 에러의 종류는 실제 환경에서 확실히 문제가 될 수 있습니다.) 또한 이 존재는 큰 프로젝트에서 빈번하게 보이는 서로 다른 구성의 다중첩 빌드 시스템 사용을 권장하고 그건 거의 항상 나쁜 생각입니다. (이것은 상대적으로 [Recursive Make Considered Harmful]이라는 유명한 논문입니다.)

 

aimake에서 저는 적절한 이름을 가진 헤더파일에 대한 모든 소스트리를 스캔하는 접근을 사용합니다. 그 다음 헤더는 경로 비교를 통해 작동합니다. (디렉토리 구조적 측면에서 가장 일치하는 헤더파일을 찾습니다.) 프로젝트의 다른 파트, 어쨋든 계층적 빌드를 사용하는 경우나 합리적인 어떤 방법을 사용하는 경우에는 다른 디렉토리에 위치해야만 합니다. 그래서 이것은 특별히 불쾌한 요구는 아닙니다.

또한 헤더파일 디렉토리를 포함하는 시스템을 스캔하는 것은 필수적입니다. 모든 시스템에서 같은 위치에 존재하지 않기 때문입니다. 예를 들어 제 Ubuntu 노트북에서 NetHack 4의 서버 데몬의 Postgresql 헤더는 /usr/include/postgresql/libpq-fe.h에 있습니다. 다른 사람들의 시스템에서는 /usr/inlcude/libpq-fe.h에 있지만요. 이 문제의 일반적인 해결책은 구성 변수로 위치를 특정하도록 사용자에게 요구하는 작업을 자주 봐왔습니다. 그리고 각기 #include <postgresql/libpq-fe.h> 그리고 #include <libpq-fe.h> 중 선택하여 조건부 컴파일을 사용합니다. 파일 시스템에서 문제가 되는 헤더파일을 검색시 빌드시스템을 얻는 일은 간단하며 인간의 개입이 덜 필요합니다. 따라서 이는 바람직합니다. aimake도 이 작업을 수행할 뿐만 아니라 소스트리를 스캔합니다.

 

여기 미묘하게 다른하나가 있습니다: 전처리기 작업은 파일 보다는 디렉토리 단계에서 작동하기 때문인데. 만약 서로 다른 파일이 동일한 디렉토리에 있을 경우헤더 파일 검색에서 파일을 제외하는 것은 불가능합니다. 실제 빌드하는 동안 헤더파일을 정렬할 이유가 없기 때문에 작은 문제처럼 보일 수 있습니다. 그러나 무엇을 하던 종속 루프(loop)를 발견하기가 확실히 어려워질 것입니다; 빌드 시스템은 아직 내장되지 않은 파일 사용을 꺼려합니다(그리고 이전 컴파일에서 남은 것들 입니다.) 그러나 전처리기의 헤더파일 검색의 디렉토리 수준의 세분화는 각각 생성된 헤더파일의 분리된 디렉토리를 사용하지 않음으로 회피를 불가능하게 만듭니다.(이 경우 일부는 빌드시점에서 생성된 것을 의미하지만 아닌 것도 있습니다.) 이 문제의 해결방법으로 여러 이유 때문에 현재 aimake는 빌드하기 전에 빌드 트리 소속의 디렉토리에 있는 소스 트리의 헤더파일을 복사합니다. (#line 지시와 함께 원래 소프 파일에 대한 오류는 여전히 보고됩니다.) 저는 시스템 헤더에 대한 의지가 없습니다. 충돌을 피하기위해 다른 구문과 시스템 툴체인 메인테이너의 작업으로 유저헤더와 혼동할 수 없기 때문입니다. 그러나 필요하다면 가능합니다.

 

원래의 이유를 주의해야 합니다. aimake는 2012년 3월 늦은 시기에 나의 "NitroHack과 AceHack을 병합하려는 시도"의 베타에서 종속 루프를 실수로 도입했습니다. NetHack 4의 이름을 얻기전 며칠동안, 빌드에 무슨 잘못이 있었는지 알지 못했습니다.(그때, 나는 NitroHack에서 상속한 빌드 시스템인 cmake를 사용했습니다.그때 어떠한 어긋남도 깨닫지 못했고 실수에 대한 적절한 피드백이 주어질 희망은 없었습니다.) 당시의 전 시간의 압박을 받고 있었기 때문에(4월 1일 전에 프로그림이 준비되길 원했기 때문에) 저는 빠르게 빌드 작업물을 얻기 위해 대체할 수 있는 빌드 시스템으로서 스크립트를 작성했고 다수의 자그마한 수정 이후에 그 스크립트는 aimake가 되었습니다.

 


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

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