실제 C/C++ 소스 파일에 전처리기 빌드 지시문을 포함하여 C/C++ 코드 컴파일

실제 C/C++ 소스 파일에 전처리기 빌드 지시문을 포함하여 C/C++ 코드 컴파일

특정 빌드 시스템에 의존하고 싶지 않은 이유가 있습니다. 나는 누군가가 좋아하는 것을 무시하려는 것이 아니라 컴파일러와 함께 제공되는 것을 고수하고 싶습니다. 이 경우에는 GCC입니다. Automake에는 특히 Windows와의 호환성 문제가 있습니다. <3 GNU make에는 큰 제한이 있으며 종종 쉘 스크립트로 보완해야 합니다. 쉘 스크립트는 다양한 형태를 취할 수 있으며, 간단히 말해서 많은 사람들을 화나게 할 가능성이 높기 때문에 제가 하려는 것은 다음과 같습니다.

주요 진입점은 하나님이다. C이든 C++ 소스 파일이든 애플리케이션의 중심입니다. 나는 메인 진입점이 가장 먼저 실행되기를 원할 뿐만 아니라, 그것이 가장 먼저 컴파일되기를 원합니다. 설명하겠습니다 -

독점 및 비공개 소스 라이브러리가 일반적이었던 때가 있었습니다. Apple이 Unix로 전환하고 Microsoft가 스스로를 공격함으로써 그 시대는 끝났습니다. 동적 연결이 필요한 모든 라이브러리는 애플리케이션의 지원 파일로 포함될 수 있습니다. 따라서 .SO(또는 .DLL ;])에 대한 별도의 빌드 지침은 별도의 실행 파일이므로 모두 괜찮습니다. 다른 라이브러리는 정적으로 링크되어야 합니다. 이제 정적 링크에 대해 이야기해 보겠습니다.

정적 연결은 정말 개자식입니다. 이것이 makefile의 목적입니다. 전체 프로젝트가 하나의 언어(예: C 또는 C++)로 작성된 경우 라이브러리를 헤더로 #include할 수 있습니다. 좋아요. 하지만 이제 또 다른 상황을 고려해 보겠습니다.

당신이 나와 같고 C에서 문자열을 사용하는 것이 왜 어려운지 알 수 없어서 C++를 사용하기로 결정했다고 가정해 보겠습니다. 하지만 MiniBasic과 같은 C 라이브러리를 사용하고 싶습니다. 신 이시여 도와 주시오. C 라이브러리의 디자인이 C++의 구문을 따르지 않으면 문제가 발생합니다. C 소스 파일을 컴파일하려면 C 컴파일러를 사용해야 하고, C++ 소스 파일을 컴파일하려면 C++ 컴파일러를 사용해야 하기 때문에 makefile이 유용한 곳입니다. makefile을 사용하고 싶지 않습니다.

GCC의 전처리기 매크로를 활용하여 다음과 같이 말할 수 있는 방법이 있었으면 좋겠습니다.

안녕하세요 GCC입니다. 괜찮으세요? 잊어버린 경우를 대비해 지금 보고 있는 소스 파일은 C++로 작성되었습니다. 물론 G++로 컴파일해야 합니다. 이 파일에도 다른 파일이 필요하지만 C로 작성되었습니다. "lolcats.c"라고 합니다. GCC를 사용하여 객체 파일로 컴파일하고, G++를 사용하여 기본 객체 파일로 컴파일한 다음, 이를 함께 연결하여 실행 파일을 형성하기를 바랍니다.

전처리기 용어로 이와 같은 내용을 어떻게 작성합니까? GCC도 이런 일을 합니까?

답변1

주요 진입점은 하나님이다. C이든 C++ 소스 파일이든 애플리케이션의 중심입니다.

단지 같은 방법으로질소는 소나무의 핵심이다. 여기가 모든 게 있는 곳이야시작하지만 C나 C++에는 애플리케이션의 "중심"을 배치할 수 있는 기능이 없습니다 main().

많은 C 및 C++ 프로그램이 구축되었습니다.이벤트 루프또는입출력 펌프. 이들은 그러한 프로그램의 "허브"입니다. 이 루프를 동일하게 넣을 필요조차 없습니다.기준 치수처럼 main().

나는 메인 진입점이 가장 먼저 실행되기를 원할 뿐만 아니라, 그것이 가장 먼저 컴파일되기를 원합니다.

사실 버리는 것이 가장 쉽다.main() 마지막C 또는 C++ 소스 파일에서.

C 및 C++는 일부 언어와 달리 선언 전에 기호를 사용할 수 있습니다. 첫 번째는 main()당신이해야한다는 것을 의미합니다사전선언그 밖의 모든 것.

독점 및 비공개 소스 라이브러리가 일반적이었던 때가 있었습니다. Apple이 Unix로 전환하고 Microsoft가 스스로를 공격하면서 그 시대는 끝났습니다.

"그에게 꿈을 꾸고 있다고 말해주세요!"

OS X 및 iOS 예가득한독점 코드인 Microsoft는 조만간 사라지지 않을 것입니다.

어쨌든, 현재 Microsoft의 어려움이 귀하의 질문과 어떤 관련이 있습니까? 당신은 DLL을 만들고 싶을 수도 있다고 말했고, Automake가 Windows를 효율적으로 처리하지 못한다고 언급했습니다. 이는 Microsoft가 귀하의 세계에서 여전히 관련성이 있음을 말해줍니다.

정적 연결은 정말 개자식입니다.

정말? 나는 항상 그것을 찾았습니다.더 쉽게동적 라이브러리에 연결하는 대신. 이는 오류 가능성이 적은 오래되고 간단한 기술입니다.

정적 링크는 외부 종속성을 실행 파일에 통합하여 실행 파일이 독립적이고 자체 포함되도록 합니다. 귀하의 질문의 나머지 부분으로 판단하면 이것이 귀하에게 호소력이 있을 것입니다.

헤더로 라이브러리를 #include할 수 있습니다.

아니...너#include 쿠토우, 도서관보다는.

이것은 단지 현학적인 것이 아닙니다. 용어문제. 말된다.

#include도서관을 이용할 수 있다면 #include </usr/lib/libfoo.a>괜찮습니다.

많은 프로그래밍 언어에서는외부 모듈/라이브러리 참조가 작동하는 방식. 즉, 외부 코드를 직접 참조합니다.

C와 C++는 이런 방식으로 작동하는 언어에 속하지 않습니다.

C 라이브러리의 디자인이 C++의 구문을 따르지 않으면 문제가 발생합니다.

아니요, C++ 사용법을 배우면 됩니다. 구체적으로 여기서는,extern "C".

전처리기 용어로 이와 같은 내용을 어떻게 작성합니까?

#include다른 C 또는 C++ 파일을 사용하는 것은 완전히 합법적입니다.

#include <some/library/main.cpp>

#include <some/other/library/main.c>
#include <some/other/library/secondary_module.c>

#include <iostream>

int main()
{
   call_the_library();
   do_other_stuff();
   return 0;
}

여기서는 이를 사용 하지 않습니다. extern "C"왜냐하면 다른 라이브러리의 C 및 C++ 코드를 직접 C++ 파일로 끌어오기 때문에 C 모듈도 적법한 C++여야 합니다. 많이있다C와 C++의 성가신 작은 차이점, 하지만 두 언어를 혼합하려면 이를 처리하는 방법을 알아야 합니다.

이 작업의 또 다른 까다로운 부분은 #includes링커 명령의 경우 명령 순서가 라이브러리 참조 순서보다 더 민감하다는 것입니다. 이 방법으로 링커를 우회하면 링커가 자동으로 수행하는 일부 작업을 수동으로 수행해야 합니다.

이것을 증명하기 위해 나는 가져갔습니다.미니 기본 버전(자신의 예) script.c드라이버를 #include <basic.c>대신 나타내는 독립 실행형 C++ 프로그램으로 변환합니다 #include <basic.h>(.수리하다) 이것이 실제로 C++ 프로그램이라는 것을 증명하기 위해 모든 printf()호출을 스트림 삽입으로 변경했습니다 cout.

C와 C++를 혼합하려는 사람들을 위해 일상적인 작업 내에서 몇 가지 다른 변경 작업을 수행해야 했습니다.

  1. void*MiniBasic 코드는 다른 포인터 유형의 자동 변환을 허용하려는 C의 의지를 활용합니다 . C++를 사용하면 명시적으로 표현할 수 있습니다.

  2. 최신 컴파일러는 더 이상 "Hello, world!\n"context 에서 C 문자열 상수(예:)의 사용을 허용하지 않습니다 char*. 표준에 따르면 컴파일러는 이를 읽기 전용 메모리에 넣을 수 있으므로 const char*.

그게 다야. GCC 불만 사항을 해결하는 데 몇 분 밖에 걸리지 않습니다.

basic.c나는 링크된 패치 파일의 내용에 비슷한 변경을 가해 야 했습니다 script.c. 나는 그것들이 더 비슷하기 때문에 차이점을 게시하지 않았습니다.

이 문제를 해결하는 다른 방법을 알아보려면SQLite 병합, 비교SQLite 소스 트리. SQLite는 #include다른 모든 파일을 하나의 기본 파일로 사용 하지 않습니다 .시리즈로함께 사용되지만 이는 #includeC 또는 C++의 모든 작업이기도 합니다.

답변2

gcc는 C, C 및 C++를 C++로 컴파일합니다. 파일 이름을 올바르게 지정했기 때문에 전처리기가 관련되지 않습니다. 그러나 extern "C"링커가 항목을 올바르게 연결할 수 있도록 C++ 파일의 C 선언 주위에 블록을 배치 해야 합니다 .

하지만 당신이 설명하는 내용은 거의 도움이 되지 않습니다. 사용 중인 라이브러리가 처음에 컴파일하기 위해 일부 구성이 필요한 경우 파일을 프로젝트에 직접 컴파일하려고 하면 여전히 구성이 필요합니다. 현실 세계에는 순수 ISO C이고 수정이나 일종의 구성 스크립트 없이 모든 플랫폼에서 컴파일되는 중요한 라이브러리가 많지 않습니다. 따라서 대부분의 경우 복잡성을 줄이는 것이 아니라 복잡성을 생성해야 합니다. 어떻게든 자신의 빌드에서 해당 구성을 처리하세요.

답변3

아니요, 그렇게 할 수는 없습니다. gcc pragma 없음다음과 같이 컴파일. 가장 유사한 것은 Microsoft Visual C++ #pragma comment(lib, …)또는 #pragma comment(linker, …)[1] [2] 일부 라이브러리는 연결 과정에 포함되어야 합니다.

안녕하세요 GCC입니다. 괜찮으세요? 잊어버린 경우를 대비해 지금 보고 있는 소스 파일은 C++로 작성되었습니다. 물론 G++로 컴파일해야 합니다. 이 파일에도 다른 파일이 필요하지만 C로 작성되었습니다. "lolcats.c"라고 합니다. GCC를 사용하여 객체 파일로 컴파일하고, G++를 사용하여 기본 객체 파일로 컴파일한 다음, 이를 함께 연결하여 실행 파일을 형성하기를 바랍니다.

귀하의 요청은 Makefile이 수행하는 작업과 정확히 같습니다.

쉘 스크립트를 생성하여 소스 파일을 추출하고 사용하려는 명령을 사용하여 컴파일할 수 있습니다. 하지만 그건 잘못된 해결책이에요™

파일이 여러 개인 경우 여러 파일로 저장하세요. 사람들이 make나 cmake를 사용하는 것을 원하지 않으면 Makefile/를 제공하지 마세요 CMakefile. 예를 들어 파일을 제공하십시오 compile-me.sh.

비슷한 상황에 처해 있다고 느끼는 유일한 경우는 단일 파일에 util을 작성했지만 주석 상단에 컴파일 명령을 제공한 경우입니다.

답변4

모든 내용이 플러그인이 되도록 결정할 수 있습니다. 그런 다음 이를 컴파일 gcc -shared -fPIC -O thing1.cc -o thing1.so 하고 기본 스텁 프로그램을 실행하게 합니다.드로펜(3)그게 전부입니다 . ./thing1.soLinux 에서는 가능합니다.dlsymGodbinfmt_misc더 투명하게 만드는 팁.

별도의 프로그램을 갖고 싶다면 GCC가-f독립형옵션. 그런 다음 런타임 환경을 제공하는 것은 사용자에게 달려 있습니다(적어도 일부 기본 I/O의 경우).시스템 호출어떤 인터페이스를 연결해야 합니까? 참조시스템 호출(2)). 관련 내용을 주의 깊게 공부하세요ABILinux/x86-64 사양은 다음과 같습니다.여기. 읽다호출 규칙.

컴파일러 플러그인을 사용하여 GCC를 사용자 정의할 수도 있습니다.녹다(그런 다음 임의의 작업을 수행하는 것을 추가할 수 있습니다. #pragma 어쩌면 하나를 포크할 수도 있습니다 gcc...)

그건 그렇고,진입 지점God귀하의 파일은 소스 파일이 아니지만 링커에 알려진 일부 태그 와 같습니다 .

자세히 알아보기번역가,커넥터(바라보다레빈의 책:링커 및 로더,대상 파일,매우 낮은 주파수,도서관및 공유 객체(참조드레이퍼스 페이퍼: 공유 라이브러리 작성 방법...),crt0.o도움이 될 것입니다.

또한보십시오C++ 모듈 제안 초안 N3347

관련 정보