IOS/Swift

[Swift] Entry Point란?

민몬+ 2021. 10. 5. 02:25

Entry Point란?


Entry Point는 말 그대로 '진입점'이라는 의미로 프로그램이 시작하는 지점이다.

모든 프로그램에는 Entry Point가 존재한다.

CPU가 Entry Point를 통해 해당 프로그램을 시작하기 때문이다.

 

OS 환경에서 응용프로그램을 실행하면 Dispatcher는 해당 프로그램을 CPU에 적재한다.

그러면 CPU의 PC(Program Counter)는 응용프로그램을 실행하기 위한 특정 주소로 Branch 해야 한다.

 

이때 PC(Program Counter)는 어떤 값을 가져야 할까?

바로, 응용프로그램의 시작 주소를 가리켜야 한다.

즉, 응용프로그램이 시작될 때 PC(Program Counter)는 Entry Point의 주소로 Branch 한다.

 

Script언어나 간단한 Binary File 등의 Entry Point는 파일의 첫 번째 줄이다.

C, C++ 등의 언어에서는 흔히 main() 함수를 Entry Point로 사용한다.

 

이 포스팅에서는 Swfit에서 사용되는 Entry Point에 대해 설명한다. 

 

Swift의 Entry Point


Swift 파일에서 Entry Point는 어디일까?

결론부터 말하자면 Swift의 Entry Point 또한 main 함수이다.

흔히 Swift의 Entry Point를 검색하면 @main, @UIApplicationMain 등에 대한 설명을 찾을 수 있다.

이는 모두 Main함수를 작성하기 위해 Swift 컴파일러가 제공하는 편의사항이다.

Swift언어에서 Main 함수가 어떻게 존재하는지 확인해보자.

 

test.swift라는 파일을 생성한 뒤 아래와 같이 코드를 작성한다.

print("First Line")
print("Second Line")

작성한 파일은 터미널 창에서 swiftc를 통해 컴파일할 수 있다. ('-emit-sil' 옵션을 통해 어셈블리어 직전 단계의 Code 형태 출력)

$ swiftc test.swift -emit-sil

어셈블리어로 컴파일되기 이전 test.swift 파일의 형태는 아래와 같다.

sil @main : 
$@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>)->Int32 {

.... 생략 ....

  return %53 : $Int32
} // end sil function 'main'

컴파일러가 test.swift에 main함수를 추가해줬음을 알 수 있다.

정리하자면 Swift파일을 컴파일할 때 컴파일러는 파일의 Top-Level Code를 main 함수로 감싸준다.

 

만약 여러 개의 Swift파일이 컴파일된다면 그 프로그램의 main 함수는 여러 개가 되는 걸까?

test.swift파일을 1, 2 두 개로 작성한 뒤 아래와 같이 컴파일을 진행한다.

$ swiftc test1.swift test2.swift

멀쩡히 컴파일되던 Swift파일은 아래와 같은 문구로 컴파일이 실패하게 된다.

error: expressions are not allowed at the top level
print("First Line")

해석하면 Top-Level에서 print("First Line") 표현은 허용되지 않는다는 의미이다.

이유는 Apple 공식 문서의 아래 문구를 통해 이해할 수 있다.

Executable top-level code contains statements and expressions, not just declarations, and is allowed only as the top-level entry point for the program.

종합해보면 아래와 같은 사실을 알 수 있다.

  1. print("First Line") 같은 Executable Top-Level Code는 Top-Level Entry Point에만 허용된다.
  2. Error가 발생한 것으로 보아 test 1.swift, test2.swift 파일에는 Top-Level Entry Point가 존재하지 않는다.
  3. 두 개 이상의 파일에서 컴파일러는 각 파일에 main 함수를 삽입해주지 않는다. (Entry Point가 두 개가 되기 때문)

그렇다면 두 개 이상의 파일을 포함하는 프로그램은 Entry Point가 어디에 존재할까?

Apple 공식 문서에 따르면 Entry Point를 표기하는 방법은 아래와 같이 다섯 가지가 있다.

 

  1. Attribute @main
  2. Attribute @NSApplicationMain
  3. Attribute @UIApplicationMain
  4. a main.swift file
  5. a file that contains top-level executable code.

 

위 다섯가지 방식의 목적은 Code의 Entry Point를 생성해주는 데 있다.

이들 모두 Entry Point(main 함수)를 생성하며 OS는 이를 호출하여 프로그램을 실행한다.

 

Main 함수 호출


그렇다면 Entry Point인 Main 함수는 누가 호출할까?

이를 이해하기 위해선 간단히 컴파일 과정을 살펴볼 필요가 있다.

 

위의 예시는 C언어의 컴파일 과정이지만 모든 컴파일 과정은 위의 틀에서 크게 벗어나지 않는다.

컴파일러는 각 파일들을 컴파일하여 Object파일을 만들고 이 파일들을 링커가 하나로 모아 ELF 파일을 만든다.

 

여기서 주목할 점은 링커의 역할이다.

링커는 각 Object 파일의 Symbol 테이블을 참조하여 각 프로그램의 Symbol들을 연결한다.

링커의 또 한 가지의 역할은 해당 프로그램의 시작점을 지정하는 것이다.

일반적으로 Linker.ld 파일에서 Entry(Symbol) 등의 문법을 통해 시작점을 지정한다.

 

즉, 링커가 만들어준. exe,. elf,. bin 파일들의 시작점을 알기 위해서는 Symbol이 필요하다.

이것이 Swift 컴파일러가 그토록 강조하는 Entry Point의 존재 이유이며 main이 이 Symbol로 사용된다.

 

간단한 실험을 통해 링킹 과정에서 main Symbol이 참조됨을 확인할 수 있다.

아래와 같이 test 1.swift, test2.swift 두 개의 파일을 작성한다. (Top-Level Code를 포함할 시 에러가 발생하므로 func으로 정의)

test1.swift

func firstTest() -> Void {
	print("test")
}

test2.swift

func secondTest() -> Void {
	print("test")
}

위 두 개의 파일을 컴파일하면 아래와 같은 에러를 확인할 수 있다.

Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
<unknown>:0: error: link command failed with exit code 1 (use -v to see invocation)

자세히는 알 수 없지만 확실한 점은

'_main' Symbol이 어디선가 참조되었고 ld(링커)가 이 Symbol을 찾을 수 없다는 것이다.

이유는 간단하다. 우리는 test 1.swift와 test2.swift 파일 어디에도 Entry Point를 지정하지 않았고, main함수는 생성되지 않았다.

 

참고 사항
위 설명에서는 이해를 돕기 위해 Entry Point와 main 함수를 동일시했지만
Entry Point는 꼭 main함수가 아닐 수 있다.
프로그램의 Entry Point는 링크 스크립트에서 Entry( )를 통해 지정되며 이는 main 함수일 수도 혹은 다른 코드일 수 있다.
(Startup.s 등의 어셈블리 코드가 기본적인 초기화를 수행하고 main을 호출해주는 경우도 많다.)

 

Reference


https://developer.apple.com/swift/blog/?id=7 

 

Files and Initialization - Swift Blog

Get the latest news and helpful tips on the Swift programming language from the engineers who created it.

developer.apple.com

https://docs.swift.org/swift-book/ReferenceManual/Declarations.html

 

Declarations — The Swift Programming Language (Swift 5.5)

Declarations A declaration introduces a new name or construct into your program. For example, you use declarations to introduce functions and methods, to introduce variables and constants, and to define enumeration, structure, class, and protocol types. Yo

docs.swift.org

http://recipes.egloos.com/5317479

 

스타트업(Startup.S) 파일이 뭐죠?

뭘 알아야 이해를 하지 호스트 피시에 전원을 넣으면 한참 동안 뭔가를 하다가 윈도우가 나타나죠. 이런 과정을 부팅이라고 말합니다. 이처럼 임베디드 시스템도 부팅을 하는데, 부팅 과정 중에

recipes.egloos.com

https://swiftrocks.com/entry-points-swift-uiapplicationmain-main

 

Entry Points in Swift: How @main and @UIApplicationMain work internally

In this article, we'll see how Swift determines the entry point of an app, the different attributes used to alter this behavior in iOS, how they work internally, and what Swift 5.3's new @main attribute brings to the table.

swiftrocks.com

 

'IOS > Swift' 카테고리의 다른 글

[Swift] Main Attribute  (0) 2021.10.08
[Swift] Top-Level Code란?  (0) 2021.10.07