티스토리 뷰

공부

ABI stability

Zedd0202 2019. 1. 7. 18:44
반응형


안녕하세요 :) Zedd입니다.

저번글에서..Swift 5.0이 가장!! 가장 중심적으로 보고 있다는게 바로 ABI stability라고 계~속 강조를 하는데요,

이 ABI stability가 뭔지 저는 잘 모르겠어요. 딱 뭔가 개념이 안잡힘 그래서 공부해보려고 합니다.


아 이 글을 다 썼는데요..참고로 정말 ABI에 대한 모든 자료를 짬뽕한 글이라고 보셔도 됩니다.

웬만한 블로그에는 다 가본 것 같아요. 근데도 제가 이걸 잘 이해한건지 이해가 안갑니다.

그래서 그런지..제가 정확한 정보를 전달한건지 의심스럽습니다...

혹시 내가 ABI를 좀 잘아는데, 틀린내용이 있는 것 같으면 제ㅔㅔ발 댓글 남겨주시기 바랍니다.

댓글 남길때는 어떤 부분이 틀렸고 왜 틀렸는지 이런걸 같이 적어주시면 감사 할 것 같습니다. 


아 그럼 제 궁금증을 여기에다 적겠습니다...

왜 아래에 안적냐면 아래에 적으면 안볼거 같아서. 

그만큼 궁금함. 글을 다 읽고 제 질문을 봐주세요.


1. Source compatibility와 Binary framework & runtime compatibility를 달성(?)하기 위한 조건이 ABI stability인가? 

이 부분이 궁금한 이유 Binary framework & runtime compatibility의 목표로 ABI stability가 나왔는데, 

그럼 Source compatibility를 달성하기 위해서는 ABI stability가 필요없다..고 해야하나 이건 너무 극단적인가 암튼 ABI stability랑 Source compatibility랑은 상관없는건가요? 

제 생각은 Source compatibility와 Binary framework & runtime compatibility를 달성하기 위한 조건이 ABI stability다. < 라고 생각하는데 이게 확실한지 제발 누가 yes or no로 대답해주세요.


2. ABI stability => pre-complied framework가능. < 이 되는거잖아요? 그럼에도 불구하고 pod은 계속 존재(?)해지는 것인가? 

아 뭔가 질문이 애매한데,

제가 알기론 pod가 지금 컴파일 때 "같이" 컴파일이 되잖아요. 그래서 빌드속도에 영향을 주는데...ABI stability가  안정되면 미리 컴파일 되었다 > 다시 컴파일 안해도 된다 > 빌드시간이 줄어든다. 이거같은데 지금 Carthage가 그런식으로 동작한다고 알고있는데..(미리 컴파일 되는), 그럼 pod는 어케되는건지? 궁금해요. 


네 근데 뭐 어케되긴 되겠죠 없어지기야 하겠어요. 그냥 생각이 궁금한거임


저 이런 궁금증(?)에 대해서 토론하는걸 굉장히 좋아하는데, 꼭 정답이 아니어도 괜찮습니다. 같이 이런 저런 문제에 대해 토론해보고싶어요. 그냥 저는 다른 iOS개발자들의 생각이 너무 궁금합니다. 

앞으로 블로그에 이런 궁금증을 많이많이..올려 볼 예정이에요. 

머 댓글 안달리면...머 어쩌겠음 걍 살아야하는 것을






ABI stability



자..제가 Swift 4.1 released! 글에서 

라고 했는데 솔직히 이해 안가죠. 저는 이해가 안갑니ㅏㄷ. 

저때 이해 완전히 안갔는데 그냥 쓴 거 같음. 

그래서 Swift ABI Stability Manifesto를 포함한 여러 ABI 관련 설명글들을 제 나름대로 풀어서 써볼려고 합니다. 


일단 갓-애플께서는 지금 빅픽쳐를 하나 생각하고 계시는데요,

현재 Swift의 최우선!!!!!! 최우선 과제 중 하나는 향후 Swift버전간의 호환성이라고 합니다. 

이 호환성은 두가지 goal을 달성하는 것을 목표로 합니다.


1. Source compatibility(소스 호환성)은 최신 컴파일러가 이전 버전의 Swift로 작성 된 코드를 컴파일 할 수 있음을 의미합니다.

이는 Swift개발자가 새로운 Swift버전이 나왔을 때 새 버전으로 마이그레이션 해야 할 때의 번거로움을 줄이는데 그 목적이 있습니다. 


자, 이까지 이해 가셨나요? 

자자 Swift 4.2나와서 님들 머했음.

저는 NSAttributedStringKey를 NSAttributedString.Key로 바꾸느라 엄청 번거로웠는데요.

자 암튼 다들 마이그레이션 한번씩 해보셨죠???? 안해봤어도 상관없는데, 암튼 내가 Xcode에서 Swift버전을 4.2로 띡 맞추는 순간, 내 소스코드의 Swift버전과 컴파일러의 Swift버전이 맞지 않으면 컴파일이 되지 않습니다.


이 소스호환성이라는게 없으면, 내 프로젝트가!! 내 모든 소스들과 패키지를 동일한 버전의 Swift로 작성해야하는 버전 잠금(version-lock)에 직면하게 됩니다.

그쵸? 

근데 소스호환성이 있자나? 그럼 여러 Swift버전에서 단일 코드 기반을 유지하면서 그냥 새로운 버전의 Swift를 사용 할 수 있다는 말임 ㅇㅇ

그냥 쉽게 생각하면 자 Swift4.2가 나왔어도 이 소스호환성만 있었다면 우리가 욕하면서 마이그레이션 해야 할 필요가 없었다는 말임 ㅇㅇ


자 이게 첫번째 goal이었고.

두번째 goal은 Binary framework & runtime compatibility.


2. Binary framework & runtime compatibility를 통해서 여러 Swift버전에서 작동하는 binary form(이진 형식)의 프레임워크를 배포 할 수 있게됩니다.

이것도 1번이랑 똑같이 생각하시면 됩니다.

우리가 앱에 third party framework를 추가합니다. 만약 이 third party framework가 Swift4.0으로 작성됐었다고 생각해볼게요.

근데 내가 잘~~쓰다가 오늘 Swift 4.2로 뾱 업데이트를 했어.

그러며는~~~ 이제 에러가 나기 시작한다. 그쵸.

근데 Binary framework & runtime compatibility가 있으면, 괜찮다는것입니다. 


Binary framework에는 프레임워크 API의 소스레벨 정보를 전달하는 Swift모듈파일과 런타임에 로드되는, 

컴파일 된 구현을 제공하는 공유 라이브러리가 모두 포함됩니다. 

즉, Binary framework = Swift모듈파일 + 공유 라이브러리 인 것.

자, Binary framework에는 위 두가지가 모두 포함된다고 그랬죠? 

그래서 Binary framework compatibility에도 역시나 2가지 goal이 있습니다.


1. Module format stability(모듈 형식 안정성)은 / 프레임워크의 공용 인터페이스에 대한 컴파일러의 표현인 모듈 파일을 / 안정화 시킵니다.

여기에는 API선언 및 inlineable코드가 포함됩니다. 모듈 파일은 프레임워크를 사용하여 클라이언트 코드를 컴파일 할 때, 타입 검사 및 코드 생성과 같은 필요한 작업을 위해 컴파일러에서 사용 된다고 합니다.


2. ABI stability은 다른 Swift버전으로 컴파일 된 앱과 라이브러리 간의 Binary compatibility를 가능하게 합니다.



What Is ABI?

자, 방금 위에서 

"ABI stability은 다른 Swift버전으로 컴파일 된 앱과 라이브러리 간의 Binary compatibility를 가능하게 합니다."라고 했죠?

그럼 ABI라는게 뭘까요. API는 들어봤는데 그쵸


Swift 프로그램 바이너리는 ABI를 통해 다른 라이브러리 및 구성요소와 상호작용 합니다.

ABI는 Application Binary Interface 또는 독립적으로 컴파일 된 바이너리 엔티티가 함께 연결되고 실행되어야 하는 규격입니다.


하이고 말 어렵다;;;

자자 여러분 일단 같이 봅시다.

ABI는 "Application Binary Interface"의 약자에요.

어랏 뭔가랑 비슷하네요. 네 API와 한 단어 빼고 똑같네요!

API는 Application Programming Interface의 약자였는데요.

ABI는 Application Binary Interface라네요. 


자, 이 ABI보다..지금은 우리가 API라는 걸 더 잘 아는 것 같아요.

API의 정의를 보면,  

응용 프로그램에서 사용할 수 있도록, 운영 체제나 프로그래밍 언어가 제공하는 기능을 제어할 수 있게 만든 인터페이스를 뜻한다.

라고..하는데요.

이 API가 소스코드상에서 다양한 구성 요소같의 통신 규칙을 정의하는 것과 마찬가지로!! 

ABI는 기계코드(machine code)에 대한 통신 규칙을 정의합니다.

규칙이에요 규칙!!!

프레임워크 또는 라이브러리들의 구성요소는 "binary language"를 사용하여 서로 통신을 할 수 있어요. 

그러니까 이 규칙을 서로서로 알고있어야 말이 통한다는 말임 ㅇㅋ?


예를 들어..객체에 메모리를 배치하는 방법, 함수를 호출하는 방법 등에 대한 인터페이스에요. 

그러니까 일련의 규칙이라고 생각하시면 됩니다. 


ABI는 일반적으로 다음과 같은 것들을 다루는데요,


  • CPU instructions (registers, stack organization, memory access type) CPU명령어

  • calling convention(함수 호출, argument전달, 값 리턴)

  • OS에 대한 시스템 호출 

  • Data Layout

  • Type Metadata

  • Mangling

  • Runtime

  • Standard Library


등등..


자..근데 있잖아요

잠깐 API이야기로 가봅시다.

API에 v1과 v2가 있다고 생각해볼게요. v2에는 인터페이스에 대한 몇가지 중요한 변경사항이 있어요.

예를들어, 뭐 v1때와 다르게 A라는 걸 만들 때 인수를 하나 더 넘겨야 한다는 식으로요.

여기서 중요한 점은, API v2는 v1과 호환되지 않으므로, v2를 호출 할 때 v1에 대해 작성된 클라이언트가 고장(break down)나게 됩니다.

여기까진 이해가 가시죠? 지금 든 예랑 똑같이!!

우리가 Swift2.0으로 binary를 만들고, Swift3.0에 연결하려고 하면 실패하게 됩니다. 왜냐? 그 사이에 많은 변경사항이 있었으니까요. 

우리가 v1클라이언트에서 v2를 호출하려는 격입니다. 

이게 바로 ABI가 호환이 안되어서 나는 문제입니다.


서로 다른 컴파일러 버전으로 컴파일 된 바이너리 코드간의 통신을 가능하게 하려면, ABI가 잘 정의되고 안정적(stable)이어야 합니다. 

그것을 ABI stability이라고 합니다. 


ABI stability은 향후 컴파일러 버전이 안정적인 ABI를 준수하는 바이너리를 생성 할 수 있도록, ABI를 잠그는 것(locking)을 의미합니다.


자..아직 이해가 안가실거라는 것을 압니다.

설명을 더 해볼게요.


현재 Swift는 ABI stability을 지원하는 언어가 아닙니다.

그래서 모든 바이너리(App이라고 생각하시면 됩니다.)는 자체적인 Swift Dynamic Library 버전을 번들로 제공합니다.

예를들어 App1이 Swift 3.0을 사용하고 있다면, Swift 3.0 Dynamic Library (3.0 ABI 포함)를 번들로 묶습니다.

App2가 Swift 3.2를 사용하고 있다면, 역시나 Swift 3.2 Dynamic Library (3.2 ABI 포함)를 번들로 묶습니다.

중요한 사실은 Swift는 iOS 운영체제에 살고있지(?) 않으며 앱내에 각각!!! 존재한다는 것입니다.

왜냐하면 Swift가 ABI stability를 지원하고 있지 않기 때문에, 다른 버전의 OS에서 실행되려면 모든 바이너리(앱)이 Swift Dynamic Library를 제공해야만 하는 것이죠.

약 5MB의 크기로, 그렇게 많은 부분을 차지하고 있진 않습니다. (IPA를 열면 swift standard libraries (.dylib)를 찾을 수 있을거에요)



만약 Swift가 ABI stability를 지원하게 된다면, 

Swift Dynamic Library가 각 앱마다 번들되는게 아니라, (i/mac 등) OS의 일부로 들어가게 됩니다. 

즉!!!! ABI는 모든 Swift 버전과 호환됩니다. 

App1이 Swift 5.0을 사용하고, App2가 Swift 5.2를 사용한다고 해도, 

각 앱마다 Swift가 번들되는것이 아니라 OS에 포함 된 Swift ABI를 사용하게됩니다.

즉, dylib를 앱에 패키징 할 필요가 없어집니다!!! 

따라서, 우리는 OS에서 제공되는 혜택을 누릴 수가 있는 것이죠.


Swift가 ABI stability를 지원함으로써 얻는 가장 큰 이점은 버전 호환성입니다.

Swift N이 있었다면 Swift N+1로 업그레이드 하는 건...정말.......아니 아닙니다.

Swift 2 > 3으로 마이그레이션 했던 분들,...존경,,,,

아무튼 ABI stability을 지원함으로써 앞으로 ABI 및 API가 모두 안정화되면, 이런 마이그레이션 과정이 전혀 필요없게 됩니다.


또한 개발자는 Swift로 작성된 closed source 3rd-party libraries를 만들고, 이를 미리 컴파일 된 프레임워크로 배포 할 수 있습니다.

이것은 현재(ABI가 안정화 되기 전), Objective-C에만 가능하기 때문에 이것도 큰변화라고 하네요.

프레임워크 제작자는 소스파일 대신, 미리 컴파일 된(Pre-compiled) 바이너리를 제공 할 수 있으므로 외부 dependencies를 프로젝트에 통합(integrate)해야 하는 경우, 빌드시간이 훨씬 빨라질 수 있습니다. 

(미리 컴파일된 바이너리를 만들 수 있는 이유는 Swift표준 라이브러리를 프레임워크에 묶을 필요가 없기 때문입니다.) 이 부분이 Binary framework & runtime compatibility부분이에요. (아니면 말좀)


또 한가지 장점을 들자면.. 번들 size가 줄어듭니다. Frameworks폴더에 Swift표준 라이브러리를 더 이상 포함 할 필요가 없기 때문에, 앱의 크기가 줄어듭니다.




조금 이해가 가셨나요?

그럼 계속 Swift ABI Stability Manifesto를 읽어보려고 합니다.


 ABI Stability는 외부에서 볼 수 있는 공용 인터페이스 및 symbol의 상수값에만 영향을 줍니다. 

internal symbol, convention, layout은 ABI를 위반하지 않고 계속 변경될 수 있습니다.

예를들어, 미래 컴파일러는 공용 인터페이스가 유지되는 한, 내부 함수 호출에 대한 호출 규칙을 자유롭게 변경 할 수 있습니다.


ABI에 관한 결정은 장기적인 파급 효과를 가져오며, 향후 언어가 성장하고 발전 할 수 있는 방법을 제한 할 수 있습니다. 미래 Swift버전에 안정성이 선언될 때 나타나는 비효율성이나 유연성 부족은 해당 플랫폼에서 영원히 지속될 것입니다.

(왜 ABI Stability를 지원하면 비효율적이고 유연성이 부족해지는지는 밑에서 추가적으로 설명하도록 할게요)


ABI Stability을 통해 OS공급업체는 Swift의 이전 버전 또는 최신버전으로 빌드 된 앱과 호환되는 Swift 표준 라이브러리 및 런타임을 포함 할 수 있습니다. 이렇게 하면 해당 플랫폼에서 이 Swift라이브러리 및 런타임의 자체 복사본을 배포 할 필요가 없습니다. 

이 말은 아까 했던 말이죠?  Swift가 OS레벨로 들어간단느 말,,,,


아무튼 이렇게 ABI stability를 알아보았는데요, 이제 다 읽었으면 맨 위로!!! 가주세요 XD


Module Stability

ABI 안정성은 런타임에 Swift버전을 섞는(mixing)것이에요.

그럼 컴파일타임은 어떨까요?

현재 Swift는 수동으로 작성된 헤더파일이 아니라 “MagicKit”라는 프레임워크와 같은 라이브러리 인터페이스를 표현하기 위해 “swiftmodule”이라는 불투명한(opaque) 아카이브 포맷을 사용합니다.(말이 무슨 왜이렇게 어려운지) 

그러나 “swiftmodule” 포맷 역시 현재 컴파일러 버전과 맞물려 있어, 다른 버전의 Swift로 “MagicKit”을 구축하면, 개발자는 MagicKit을 import할 수 없게 됩니다. 즉, 앱 개발자과 라이브러리 작성자는 같은 버전의 컴파일러를 사용해야 합니다.


이러한 제한을 제거하기 위해, 라이브러리 작성자는 "module stability”불리는 기능을 구현해야합니다.


예를들어 Swift 6을 사용하여 프레임워크를 만들 수 있습니다. 이 프레임워크 인터페이스는 Swift 6과 향후 (만약에 나올) Swift 7컴파일러에서 모두 읽을 수 있습니다.


Library Evolution

현재 Swift라이브러리가 변경되면, 해당 라이브러리를 사용하는 모든 앱을 다시 컴파일 해야해요. 여기엔 몇가지 장점도 있는데요, 컴파일러가 앱에서 사용하는 라이브러리의 정확한 버전을 알고있기 때문에 코드크기를 줄이고 앱을 더 빨리 실행 할 수 있는 추가 가정(assumptions)을 할 수 있습니다. 그러나 이러한 가정은 다음버전의 라이브러리에서는 사실이 아닐 수 있어요.


이 기능(module stability)은 라이브러리의 진화를 지원합니다. 클라이언트를 다시 컴파일 할 필요없이 라이브러리의 “새 버전”을 제공 할 수 있게 되는 것이죠. 





참고 : 

https://github.com/apple/swift/blob/master/docs/ABIStabilityManifesto.md

https://pspdfkit.com/blog/2018/binary-frameworks-swift/

https://developerinsider.co/what-will-be-new-in-swift-5/

https://www.bensnider.com/abi-compatibility-whoopdty-do-what-does-it-all-mean.html

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

https://www.reddit.com/r/swift/comments/67z7dy/what_is_abi_stability_and_why_does_it_matter/

https://medium.com/swift-india/swift-5-abi-stability-769ccb986d79

https://swift.org/blog/abi-stability-and-more/


반응형

'공부' 카테고리의 다른 글

Why use Rx?  (4) 2019.03.06
Premiere Pro 기초 ) 자막넣기  (3) 2019.02.22
App Thinning. 그리고 Bitcode  (11) 2019.01.06
Swift로 Slackbot 만들기  (1) 2019.01.05
Boot Camp로 Windows 10 설치시 WIFI문제 해결 + Boot Camp삭제 방법  (13) 2018.11.11