파일 A 를 컴파일한다고 합시다.
A 에 인클루드한 헤더 파일에 func 라는 함수의 선언이 있고 A 에는 이 함수를 호출하는 코드가 있습니다.
A 를 컴파일만(링크 안하고)하면 아무 이상 없이 컴파일 잘 됩니다. 이 결과물을 목적 파일(Object file)이라고 부릅니다.
컴파일은 잘 됐지만, A를 컴파일한 목적 파일은 실행 가능한 코드가 아닙니다. 왜나하면 func 를 호출했을때 실제 어떤 코드를 실행해야할지 모르기 때문입니다.
인클루드된 파일에는 func 의 타입에 관한 정보가 있어서 A 파일을 컴파일하는데에는 아무 문제가 없지만, 실제 func 의 구현 코드(실행할 명령들)는 모르는거지요.
실행가능한 코드를 만들어내려면 어딘가에서 func 의 실행 코드를 찾아서 A 를 컴파일한 결과물과 연결시켜야만 합니다.
그 어딘가는 실제 func 의 구현 코드가 있는 파일을 컴파일한 목적 파일이거나, 그런 목적 파일들을 모아놓은 라이브러리가 되겠지요.
이 연결 과정을 '링크'라고 부릅니다.
요약하면 링크는 여러 분리된 파일들을 컴파일한 각각의 결과물에서 최종적인 실행 파일을 만드는데 필요한 부분들을 찾아 연결하는 작업입니다.
그런데 경우에 따라서는 필요한 모든 목적 코드를 연결해서 완전히 완성된 실행 파일을 만들어내지 않고, 프로그램이 실행되는 중간에 프로그램 외부에 존재하는 필요한 목적 코드를 찾아서 연결하는 경우도 있습니다. 전자를 정적(static) 링크, 후자를 동적(dynamic)링크라고 부릅니다.
자바의 경우도 여러 분리된 파일들을 따로 따로 컴파일한 후 실행시키므로 링크 과정이 필요합니다. 다만 자바는 동적 링크인 거지요. 프로그램 실행 중에 필요한 클래스를 클래스패스에서 찾아서 로드하는 겁니다. JVM 이 알아서 다 처리해주고 프로그래머가 특별히 링크 과정을 신경 쓸 필요가 없으므로 링크가 없는 것처럼 보이는 겁니다.
C/C++도 동적 링크를 할 수 있습니다. 리눅스에서는 확장자가 so 인 파일들, 윈도에서는 확장자가 dll 인 파일들이 그런 동적 링크를 위한 라이브러리들입니다. 하지만 자바처럼 투명하게 처리되지는 않고 프로그래머가 컴파일러에게 약간 힌트를 주어야 합니다.
링키지는 링크를 위한 규칙입니다. 예를 들어 어떤 함수는 전적으로 그 파일 안에서만 사용가능하고 외부 파일에서는 호출하지 못하도록 하고 싶으면 internal linkage 를 줘서 외부 파일에서 그 함수를 링크하려고 하면 에러가 나도록 할 수 있습니다. 또 C++이 아닌 다른 언어를 사용해서 컴파일된 목적 파일과 링크하기 위해 링키지를 정해줄 수도 있습니다. 언어가 다르면 목적 파일에 들어 있는 실행 코드를 찾기 위한 방법이 달라지기 때문에 주의를 기울여야 합니다. C 와 C++을 링크하는 경우에도 이런 주의를 기울여야 합니다. C++에서 extern "C" 선언을 사용하면 컴파일러에게 이 코드는 C 언어에서도 호출될 수 있도록 처리하라고, 또는 반대로 C 에서 컴파일된 목적코드와 링크해야 한다고 알려주는 겁니다. extern "Java" 같은 것도 형식적으로는 가능하지만 실제로 지원되는 경우는 없습니다. 링키지와 name mangling 등에 대해서는 처음부터 신경쓸 필요는 없습니다. 나중에 C++을 좀 안 다음에 공부하는게 낫습니다. 처음부터 머리 싸매봐야 이해도 안되고 필요하지도 않습니다.
구체적인 코드를 예로 들어 설명을 드리고 싶지만, 시간이 넉넉치 않아서^^; 간단한 코드를 직접 작성해서 이리 저리 실험을 해보시면서 에러 메시지들을 살펴보면 이해가 좀 더 쉬울 수도 있습니다.
사실 자바가 링크 개념과 링키지 개념이 표면적으로 나와있지는 않지만 내부적으로는 이런 일을 수행할겁니다.
왜냐하면 자바코드를 바이트코드로 컴파일 후 이를 JVM이 로딩할 때 해당 자바 바이트코드에서 참조하는 다른
패키지나 다른 클래스파일들 직접 메모리로 불러와야지만 프로그램이 정상적으로 동작 할 수 있을 테니까요.
이는 정적링크보다는 동적링크 개념에 더 가까울듯 하군요..
간단히 비교를 해보자면..
c의 컴파일 ◁ - ▷ 자바 바이트코드 생성
c의 동적링크 ◁ - ▷ JVM이 바이트코드를 native로 컴파일을 하면서 필요한 각종 클래스 파일을 동시에 포함하여 하나로 합함
c의 링키지 ◁ - ▷ 자바클래스에서 참조하는 다른 클래스들의 참조 목록
정도로 비교가 가능할듯 합니다.
-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.
-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.
파일 A 를
파일 A 를 컴파일한다고 합시다.
A 에 인클루드한 헤더 파일에 func 라는 함수의 선언이 있고 A 에는 이 함수를 호출하는 코드가 있습니다.
A 를 컴파일만(링크 안하고)하면 아무 이상 없이 컴파일 잘 됩니다. 이 결과물을 목적 파일(Object file)이라고 부릅니다.
컴파일은 잘 됐지만, A를 컴파일한 목적 파일은 실행 가능한 코드가 아닙니다. 왜나하면 func 를 호출했을때 실제 어떤 코드를 실행해야할지 모르기 때문입니다.
인클루드된 파일에는 func 의 타입에 관한 정보가 있어서 A 파일을 컴파일하는데에는 아무 문제가 없지만, 실제 func 의 구현 코드(실행할 명령들)는 모르는거지요.
실행가능한 코드를 만들어내려면 어딘가에서 func 의 실행 코드를 찾아서 A 를 컴파일한 결과물과 연결시켜야만 합니다.
그 어딘가는 실제 func 의 구현 코드가 있는 파일을 컴파일한 목적 파일이거나, 그런 목적 파일들을 모아놓은 라이브러리가 되겠지요.
이 연결 과정을 '링크'라고 부릅니다.
요약하면 링크는 여러 분리된 파일들을 컴파일한 각각의 결과물에서 최종적인 실행 파일을 만드는데 필요한 부분들을 찾아 연결하는 작업입니다.
그런데 경우에 따라서는 필요한 모든 목적 코드를 연결해서 완전히 완성된 실행 파일을 만들어내지 않고, 프로그램이 실행되는 중간에 프로그램 외부에 존재하는 필요한 목적 코드를 찾아서 연결하는 경우도 있습니다. 전자를 정적(static) 링크, 후자를 동적(dynamic)링크라고 부릅니다.
자바의 경우도 여러 분리된 파일들을 따로 따로 컴파일한 후 실행시키므로 링크 과정이 필요합니다. 다만 자바는 동적 링크인 거지요. 프로그램 실행 중에 필요한 클래스를 클래스패스에서 찾아서 로드하는 겁니다. JVM 이 알아서 다 처리해주고 프로그래머가 특별히 링크 과정을 신경 쓸 필요가 없으므로 링크가 없는 것처럼 보이는 겁니다.
C/C++도 동적 링크를 할 수 있습니다. 리눅스에서는 확장자가 so 인 파일들, 윈도에서는 확장자가 dll 인 파일들이 그런 동적 링크를 위한 라이브러리들입니다. 하지만 자바처럼 투명하게 처리되지는 않고 프로그래머가 컴파일러에게 약간 힌트를 주어야 합니다.
링키지는 링크를 위한 규칙입니다. 예를 들어 어떤 함수는 전적으로 그 파일 안에서만 사용가능하고 외부 파일에서는 호출하지 못하도록 하고 싶으면 internal linkage 를 줘서 외부 파일에서 그 함수를 링크하려고 하면 에러가 나도록 할 수 있습니다. 또 C++이 아닌 다른 언어를 사용해서 컴파일된 목적 파일과 링크하기 위해 링키지를 정해줄 수도 있습니다. 언어가 다르면 목적 파일에 들어 있는 실행 코드를 찾기 위한 방법이 달라지기 때문에 주의를 기울여야 합니다. C 와 C++을 링크하는 경우에도 이런 주의를 기울여야 합니다. C++에서 extern "C" 선언을 사용하면 컴파일러에게 이 코드는 C 언어에서도 호출될 수 있도록 처리하라고, 또는 반대로 C 에서 컴파일된 목적코드와 링크해야 한다고 알려주는 겁니다. extern "Java" 같은 것도 형식적으로는 가능하지만 실제로 지원되는 경우는 없습니다. 링키지와 name mangling 등에 대해서는 처음부터 신경쓸 필요는 없습니다. 나중에 C++을 좀 안 다음에 공부하는게 낫습니다. 처음부터 머리 싸매봐야 이해도 안되고 필요하지도 않습니다.
구체적인 코드를 예로 들어 설명을 드리고 싶지만, 시간이 넉넉치 않아서^^; 간단한 코드를 직접 작성해서 이리 저리 실험을 해보시면서 에러 메시지들을 살펴보면 이해가 좀 더 쉬울 수도 있습니다.
혹시나해서 찾아보니
혹시나해서 찾아보니 gcc 에서 extern "Java" 가 되는군요. g++ 과 gcj 사이의 링크가 가능한 모양입니다. 질문과는 관계 없지만, 앞 글에 잘못 써놔서 정정합니다.
이렇게 설명드리면
이렇게 설명드리면 더 간편할까요?
우선 c언어에서의 링크와 컴파일, 링키지 개념은 위에분께서 잘 설명해주셨으니 넘어가고..
자바와 c와 비교를 해보겠습니다.
사실 자바가 링크 개념과 링키지 개념이 표면적으로 나와있지는 않지만 내부적으로는 이런 일을 수행할겁니다.
왜냐하면 자바코드를 바이트코드로 컴파일 후 이를 JVM이 로딩할 때 해당 자바 바이트코드에서 참조하는 다른
패키지나 다른 클래스파일들 직접 메모리로 불러와야지만 프로그램이 정상적으로 동작 할 수 있을 테니까요.
이는 정적링크보다는 동적링크 개념에 더 가까울듯 하군요..
간단히 비교를 해보자면..
c의 컴파일 ◁ - ▷ 자바 바이트코드 생성
c의 동적링크 ◁ - ▷ JVM이 바이트코드를 native로 컴파일을 하면서 필요한 각종 클래스 파일을 동시에 포함하여 하나로 합함
c의 링키지 ◁ - ▷ 자바클래스에서 참조하는 다른 클래스들의 참조 목록
정도로 비교가 가능할듯 합니다.
-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.
-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.
댓글 달기