programing

먼저 개체 파일에 컴파일해야 하는 이유는 무엇입니까?

stoneblock 2023. 9. 11. 21:25

먼저 개체 파일에 컴파일해야 하는 이유는 무엇입니까?

작년에 저는 포트란에서 프로그래밍을 시작했습니다. 연구 대학에서 일하고 있습니다.저의 대부분의 이전 경험은 PHP나 오래된 ASP와 같은 웹 언어에 있어서 진술문을 작성하는 것은 처음입니다.

수정하려는 코드가 두 개 있습니다.

실행 파일을 만들기 전에 모듈(예: gfortran -cfilea.f90)에서 .o 파일을 생성하는 명시적 문있습니다.

다른 것은 실행 파일을 직접 생성하는 것입니다(때로는 .mod 파일을 생성하지만 gfortran -o 실행 파일 a.f90 fileb.f90 mainfile.f90과 같이 .o 파일은 생성하지 않습니다).

  • 한 가지 방법이 다른 방법보다 선호되는 이유가 있습니까?

먼저 개체 파일에 컴파일하는 것을 별도 컴파일이라고 합니다.많은 장점과 몇 가지 단점이 있습니다.

장점:

  • 개체 파일(.o)을 라이브러리로 변환하고 나중에 링크하기 쉬운 기능
  • 많은 사람들이 동시에 다른 소스 파일을 작업할 수 있습니다.
  • 컴파일 속도 향상(소스가 변경되지 않은 경우 동일한 파일을 몇 번이고 컴파일하지 않음)
  • 오브젝트 파일들은 다른 언어 소스들로부터 만들어질 수 있고 나중에 함께 연결될 수 있습니다.그러려면 개체 파일이 동일한 형식과 호환되는 호출 규칙만 사용하면 됩니다.
  • 별도의 컴파일은 정적 또는 공유된 시스템 전체 라이브러리(OS 라이브러리, 언어 표준 라이브러리 또는 타사 라이브러리)의 배포를 가능하게 합니다.

단점:

  • 컴파일러가 수행할 수 없는 (함수 최적화와 같은) 최적화가 있으며, 링커는 신경 쓰지 않습니다. 그러나 이제 많은 컴파일러가 "링크 시간 최적화"를 수행하는 옵션을 포함하고 있으므로 이러한 단점은 상당 부분 해소됩니다.그러나 시스템 라이브러리 및 타사 라이브러리의 경우에는 여전히 문제이며, 특히 공유 라이브러리의 경우에는 문제가 됩니다(실행할 때마다 변경될 수 있는 구성 요소의 일부를 최적화하는 것은 불가능하지만, JIT 컴파일과 같은 다른 기술은 이 문제를 완화할 수 있습니다).
  • 일부 언어에서 프로그래머는 이 객체와 연결되는 다른 것들의 사용을 위해 일종의 헤더를 제공해야 합니다.를 들어 를어에야다서다를o을 제공해야 합니다..h개체 파일과 함께 사용할 파일입니다.하지만 어쨌든 좋은 연습입니다.
  • C 또는 C++와 같은 텍스트 기반 언어에서 함수 프로토타입을 변경하면 두 곳에서 변경해야 합니다.헤더 파일에 한 번, 구현 파일에 한 번.

100개의 소스 파일이 몇 개 있는 프로젝트가 있을 때는 변경할 때마다 모든 파일을 다시 컴파일하고 싶지 않습니다.각 소스 파일을 별도의 개체 파일로 컴파일하고 변경에 영향을 받는 소스 파일만 다시 컴파일하면 소스 코드 변경부터 새 실행 파일까지 최소 시간이 소요됩니다.

make는 그러한 종속성을 추적하고 무언가가 바뀌었을 때 이진법을 다시 만드는 데 사용되는 일반적인 도구입니다.으로 각 될 수 -로각는을다한해에될다수로은이스한될다수yre에t(로ea로seueh은 ).make), 바이너리를 를 을 을 를

.o 파일은 Object File입니다.최종 프로그램의 중간 표현입니다.

구체적으로, 일반적으로 .o 파일은 컴파일된 코드를 가지고 있지만, 그것이 가지고 있지 않은 것은 모든 다른 루틴이나 데이터에 대한 최종 주소입니다.

프로그램이 실행되기 전에 필요한 것 중 하나는 메모리 이미지와 유사한 것입니다.

예를들면.

메인 프로그램이 있고 루틴 A라고 부른다면 (이건 가짜 포트란입니다. 저는 수십 년 동안 손을 대지 않았으니 여기서 저와 함께 일하세요.)

PROGRAM MAIN
INTEGER X,Y
X = 10
Y = SQUARE(X)
WRITE(*,*) Y
END

그러면 SQUARE 기능이 있습니다.

FUNCTION SQUARE(N)
SQUARE = N * N
END

는 개별적으로 컴파일된 단위입니다.메인이 컴파일될 때 "SQUARE"가 어디에 있는지, 어떤 주소에 있는지 알 수 없습니다.마이크로프로세서 JUMP SUBROUTIN(JSR) 명령어를 호출할 때 해당 명령어가 수행해야 할 부분이 있다는 것을 알아야 합니다.

.o 파일에는 이미 JSR 명령어가 있지만 실제 값은 없습니다.이는 애플리케이션에 따라 링크 또는 로드 단계에서 나중에 제공됩니다.

따라서 MAINES .o 파일에는 메인에 대한 모든 코드와 해결하려는 참조 목록(특히 SQUARE)이 있습니다.SQUARE는 기본적으로 독립적이고, 어떤 참조도 없지만, 동시에 기억 속에 어디에 존재하는지에 대한 주소도 아직 없었습니다.

링커는 .o 파일을 모두 제거하고 그것들을 하나의 exe로 결합할 것입니다.옛날에는 컴파일된 코드가 말 그대로 기억 이미지일 것입니다.프로그램은 어떤 주소에서 시작하여 단순히 RAM에 도매로 로드된 후 실행됩니다.따라서 시나리오에서는 링커가 두 개의 .o 파일을 가져와 서로 연결한 후(실제 주소를 얻기 위해 SQUARE) Main에서 SQUARE 참조를 찾아서 주소를 입력하는 것을 볼 수 있습니다.

현대의 링커들은 그렇게 멀리 가지 않고, 최종 처리의 대부분을 프로그램이 실제로 로딩될 때로 미루고 있습니다.하지만 컨셉은 비슷합니다.

.o 파일로 컴파일하면 나중에 실행 전에 링크 및 로드 프로세스에 의해 결합되는 재사용 가능한 논리 단위가 생성됩니다.

또 다른 좋은 점은 .o 파일이 다른 언어에서 나올 수 있다는 것입니다.호출 메커니즘이 호환되는 한(즉, 인수가 함수 및 프로시저에 전달되고 전달되는 방법) 소스 언어는 .o로 컴파일되면 관련성이 떨어집니다.예를 들어 포트란 코드로 링크, 결합, C 코드를 연결할 수 있습니다.

PHP 등에서는 런타임 시 모든 코드가 하나의 이미지에 로드되기 때문에 프로세스가 다릅니다.PHP를 사용하는 방법과 유사한 FORTRANs .o 파일에는 파일을 크고 응집력 있는 전체로 결합하는 메커니즘이 포함되어 있습니다.

컴파일 시간과 별개로 컴파일 과정이 다단계 과정이라는 점도 이유입니다.

The multi-part process.

개체 파일은 해당 프로세스에서 나오는 중간 출력 중 하나일 뿐입니다.이 파일들은 결국 실행 파일을 생성하기 위해 링커에 의해 사용될 것입니다.

더 큰 실행 파일을 구성하기 위해 연결할 수 있도록 개체 파일로 컴파일합니다.그것만이 할 수 있는 유일한 방법은 아닙니다.

그런 식으로 하지 않고 메모리에 컴파일하고 결과를 즉시 실행하는 컴파일러도 있습니다.이전에, 학생들이 메인프레임을 사용해야만 했을 때, 이것은 표준이었습니다.터보 파스칼도 이런 식으로 했습니다.

언급URL : https://stackoverflow.com/questions/5283841/why-compile-to-an-object-file-first