문제

컴파일이 어떻게 작동하는지 설명할 수 있는 사람이 있나요?

컴파일이 어떻게 작동하는지 알 수 없는 것 같습니다.

좀 더 구체적으로 예를 들자면..Lua 상태를 로드하기 위해 MSVC++ 6에서 일부 코드를 작성하려고 합니다.

나는 벌써:

  • 라이브러리에 대한 추가 디렉터리를 설정하고 올바른 디렉터리에 파일을 포함합니다.
  • extern "C"를 사용함(Lua는 C 전용이기 때문이라고 들었습니다)
  • 올바른 헤더 파일을 포함시켰습니다

하지만 MSVC++6에서는 해결되지 않은 외부 기호(내가 사용한 Lua 함수의 경우)에 대한 일부 오류가 계속 발생합니다.

이 문제를 해결하고 다음 단계로 넘어가는 방법을 알고 싶은 만큼, 관련된 기본 프로세스를 이해하게 된다면 훨씬 더 나을 것이라고 생각합니다. 이에 대해 좋은 설명을 쓸 수 있는 사람이 있을까요?제가 알고 싶은 것은 과정입니다..다음과 같이 보일 수 있습니다:

1 단계:

  • 입력:소스 코드
  • 프로세스:구문 분석(여기에 더 자세한 내용을 추가할 수도 있음)
  • 산출:여기서 출력되는 것은 무엇이든 ..

2 단계:

  • 입력:1단계에서 출력된 내용과 기타 필요한 내용(라이브러리?DLL?.그래서?.lib?)
  • 프로세스:입력으로 무엇을 하든
  • 산출:무엇이든지 출력된다

등등..

감사해요..

아마도 이것은 기호가 무엇인지, 정확히 "연결"이 무엇인지, "객체" 코드가 무엇인지 등을 설명할 것입니다.

감사해요..너무 멍청해서 죄송해요..

추신언어별로 다를 필요는 없습니다.하지만 가장 편한 언어로 표현해 보세요.:)

편집하다:어쨌든 오류를 해결할 수 있었는데, 프로젝트에 .lib 파일을 수동으로 추가해야 한다는 사실이 밝혀졌습니다.단순히 IDE 설정이나 프로젝트 설정에서 라이브러리 디렉터리(.lib가 있는 위치)를 지정하는 것은 작동하지 않습니다.

하지만 아래 답변은 제가 그 과정을 더 잘 이해하는 데 어느 정도 도움이 되었습니다.정말 감사합니다!..아직도 철저한 가이드를 작성하고 싶은 사람이 있다면 그렇게 하세요..:)

편집하다:추가 참고를 위해 한 저자(Mike Diehl)가 이 내용을 아주 잘 설명하는 두 개의 기사를 찾았습니다.:)컴파일 프로세스 검토:1 부 컴파일 프로세스 검토:2 부

도움이 되었습니까?

해결책

소스에서 실행 파일까지는 일반적으로 C 및 관련 언어에 대한 2 단계 프로세스이지만 IDE는 아마도 이것을 단일 프로세스로 제시 할 수 있습니다.

1/ 소스를 코딩하고 컴파일러를 통해 실행하십시오. 이 단계의 컴파일러에는 소스와 연결할 다른 제품의 헤더 파일이 필요합니다 (아래 참조).

컴파일은 소스 파일을 객체 파일로 전환하는 것으로 구성됩니다. 객체 파일에는 컴파일 된 코드와 다른 제품이 무엇인지 알 수있는 충분한 정보가 있지만 ~ 아니다 그 다른 것들을 찾을 수있는 곳 (예 : LUA 라이브러리).

2/ 다음 단계 인 Linking은 모든 객체 파일을 라이브러리와 결합하여 실행 파일을 작성합니다. 나는 여기서 동적 링크를 다루지 않을 것입니다. 그 이유는 거의 이점이 거의없이 설명을 복잡하게 만들 것입니다.

링커가 다른 코드를 찾을 수있는 디렉토리를 지정해야 할뿐만 아니라 해당 코드가 포함 된 실제 라이브러리를 지정해야합니다. 해결되지 않은 외부가 있다는 사실 은이 작업을 수행하지 않았다는 것을 나타냅니다.

예를 들어, 다음 단순화 된 C 코드를 고려하십시오 (xx.c) 및 명령.

#include <bob.h>
int x = bob_fn(7);

cc -c -o xx.obj xx.c

이것은 컴파일됩니다 xx.c 파일로 xx.obj. 그만큼 bob.h 프로토 타입을 포함합니다 bob_fn() 편집이 성공할 것입니다. 그만큼 -c 컴파일러에 실행 파일이 아닌 객체 파일을 생성하도록 지시합니다. -o xx.obj 출력 파일 이름을 설정합니다.

그러나 실제 암호 ~을 위한 bob_fn() 헤더 파일이 아니라 /bob/libs/libbob.so, 링크하려면 다음과 같은 것이 필요합니다.

cc -o xx.exe xx.obj -L/bob/libs;/usr/lib -lbob

이것은 생성됩니다 xx.exe ~에서 xx.obj, 양식의 라이브러리 (주어진 경로에서 검색) 사용 libbob.so (lib와.는 일반적으로 링커에 의해 추가됩니다). 이 예에서 -L 라이브러리의 검색 경로를 설정합니다. 그만큼 -l 필요한 경우 실행 파일에 포함시킬 라이브러리를 지정합니다. 링커는 일반적으로 "bob"을 가져 와서 다음으로 지정된 검색 경로에서 첫 번째 관련 라이브러리 파일을 찾습니다. -L.

라이브러리 파일은 실제로 객체 파일 모음입니다 (zip 파일에 다른 여러 파일이 포함되어 있지만 반드시 압축 할 필요는 없습니다) - 정의되지 않은 외부의 첫 번째 관련 발생이 발견되면 객체 파일이 라이브러리에서 복사되어 추가됩니다. 당신처럼 실행 파일에 xx.obj 파일. 이것은 일반적으로 해결되지 않은 외부가 없을 때까지 계속됩니다. '관련'라이브러리는 "밥"텍스트를 수정 한 것입니다. libbob.a, libbob.dll, libbob.so, bob.a, bob.dll, bob.so 등등. 관련성은 링커 자체에 의해 결정되며 문서화되어야합니다.

작동 방식은 링커에 따라 다르지만 이것은 기본적으로 IT입니다.

1/ 모든 객체 파일에는 해결해야 할 미해결 외부 목록이 포함되어 있습니다. 링커는 이러한 모든 객체를 구성하고 그 객체 사이의 링크를 수정합니다 (가능한 한 많은 외부를 해결).

2/ 그런 다음 모든 외부에 대해 아직 해결되지 않은 링커는 링크를 만족시킬 수있는 객체 파일을 찾는 라이브러리 파일을 빗질합니다. 그것을 찾으면 그것을 끌어 당깁니다. - 당겨진 물체에 만족 해야하는 외부 목록이있을 수 있으므로 더 해결되지 않은 외부가 발생할 수 있습니다.

3/ 반복 2 단계 2를 반복하여 해결되지 않은 외부가 더 이상 없거나 라이브러리 목록에서이를 해결할 가능성이 없을 때까지 반복하십시오 (LUA 라이브러리 파일을 포함하지 않았기 때문에 개발 중이 었음).

앞에서 언급 한 합병증은 역동적 인 연결입니다. 그곳에서 실제 루틴이 아닌 루틴 (마커의 일종)과 연결되는 곳은 나중에로드 시간 (실행 파일을 실행할 때)에 해결됩니다. Windows Common Control과 같은 것들이 이러한 DLL에 있으므로 객체를 새로운 실행 파일로 다시 링크하지 않고도 변경할 수 있습니다.

다른 팁

1 단계 - 컴파일러 :

  • 입력 : 소스 코드 파일 [S
  • 프로세스 : 소스 코드를 구문 분석하고 기계 코드로 변환
  • 출력 : 객체 파일 [s],
    • 이 객체에서 정의 된 기호의 이름 과이 개체 파일 "내보내기"
    • 이 개체 파일에 정의 된 각 기호와 관련된 기계 코드
    • 이 객체 파일에서 정의되지 않았지만이 객체 파일의 소프트웨어가 의존하고 그 후에 연결되어야하는 기호의 이름, 즉이 개체 파일 "import"라는 이름.

2 단계 - 연결 :

  • 입력:
    • 1 단계에서 객체 파일 [s
    • 다른 객체의 라이브러리 (예 : O/S 및 기타 소프트웨어)
  • 프로세스:
    • 연결하려는 각 객체에 대해
    • 이 객체가 가져 오는 기호 목록을 가져옵니다
    • 다른 라이브러리 에서이 기호를 찾으십시오
    • 해당 라이브러리를 객체 파일에 연결하십시오
  • 출력 : 모든 객체의 기계 코드와 객체로 가져온 (링크 된) 라이브러리의 객체를 포함하는 단일 실행 파일.

두 가지 주요 단계는 컴파일과 링크입니다.

컴파일은 단일 컴파일 장치 (단순히 소스 파일, 포함 된 모든 헤더와 함께)를 사용하고 객체 파일을 만듭니다. 이제 해당 객체 파일에는 특정 위치 (주소)에 정의 된 많은 기능 (및 정적 데이터와 같은 다른 것)이 있습니다. 다음 단계에서 링크하면 이러한 기능에 대한 약간의 추가 정보도 필요합니다. 그래서 이것들도 저장됩니다. 단일 객체 파일은 실제로 다른 객체 파일에있는 함수를 참조하기 때문에 (코드가 실행될 때 호출하려고하기 때문에)를 참조 할 수 있지만 여기서 단일 객체 파일을 처리하고 있기 때문에 상징적 참조 ( '이름') 만 다른 기능은 객체 파일에 저장됩니다.

다음으로 연결됩니다 (여기서 정적 링크로 제한합시다). 링크는 첫 번째 단계에서 생성 된 객체 파일 (직접 또는 .lib 파일로 함께 버린 후)이 함께 가져 와서 실행 파일이 생성되는 곳입니다. 링크 단계에서 한 객체 파일 또는 lib에서 다른 객체 파일에서 다른 상징적 참조는 올바른 객체에서 이름을 찾아 함수의 주소를 찾고 오른쪽에 주소를 놓아서 해결됩니다 (가능하다면). 장소.

이제 필요한 'extern "c"'에 대해 설명하려면 다음과 같습니다.

C에는 기능 과부하가 없습니다. 함수는 항상 그 이름으로 인식 할 수 있습니다. 따라서 코드를 C 코드로 컴파일하면 함수의 실제 이름 만 객체 파일에 저장됩니다.

그러나 C ++에는 '기능 / 메소드 과부하'라는 것이 있습니다. 이것은 함수의 이름이 더 이상 그것을 식별하기에 충분하지 않음을 의미합니다. 따라서 C ++ 컴파일러는 기능의 프로토 타입을 포함하는 함수의 '이름'을 만듭니다 (이름과 프로토 타입은 함수를 고유하게 식별하므로). 이것을 '이름 Mangling'이라고합니다.

C ++ 프로젝트에서 'C'코드 (예 : 사전 컴파일 된 Lua Binaries)로 컴파일 된 라이브러리를 사용하려는 경우 'extern "c"'사양이 필요합니다.

정확한 문제의 경우 : 여전히 작동하지 않으면이 힌트가 도움이 될 수 있습니다. * Lua Binaries가 동일한 버전의 VC ++로 컴파일 되었습니까? * VC 솔루션 내에서 또는 C ++ 코드로 별도의 프로젝트로 LUA를 직접 컴파일 할 수 있습니까? * 모든 'extern "c"'가 올바른 것이 있습니까?

프로젝트 설정으로 이동하여 "링커" 탭 어딘가에 해당 LUA 라이브러리 *.lib 파일이 있는 디렉터리를 추가해야 합니다."라이브러리 포함"이라는 설정이 있는데, 찾아볼 수 없어서 죄송합니다.

"확인되지 않은 외부 기호"가 나타나는 이유는 C++의 컴파일이 두 단계로 작동하기 때문입니다.먼저 코드가 컴파일되고 각 .cpp 파일이 자체 .obj 파일에 포함된 다음 "링커"가 시작되어 모든 .obj 파일을 .exe 파일에 결합합니다..lib 파일은 라이브러리 배포를 좀 더 간단하게 만들기 위해 함께 병합된 .obj 파일 묶음입니다.따라서 "#include" 및 extern 선언을 모두 추가하면 해당 서명이 있는 코드를 어딘가에서 찾을 수 있지만 링커는 실제 코드가 있는 .lib 파일이 어디에 있는지 모르기 때문에 해당 코드를 찾을 수 없다고 컴파일러에 알렸습니다. 배치되다.

라이브러리의 REDME를 읽었는지 확인하세요. 일반적으로 코드에 라이브러리를 포함하기 위해 수행해야 할 작업에 대한 자세한 설명이 있습니다.

당신은 또한 이것을 확인할 수도 있습니다. 컴파일러, 어셈블러, 링커 및 로더 : 간단한 이야기.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top