애플 실리콘(ARM) 맥에서 Intel 전용 터미널 앱 구동하기

업데이트:

애플 실리콘(ARM)을 탑재한 맥에서, 터미널 앱을 사용하다 보면 여러 가지 사정에 의해 가끔 호환성 문제가 발생하는 경우가 있다.

필자의 경우 42의 libasm과제1를 수행하기 위해 인텔 맥에서 작성된 (무려)어셈블리 라이브러리를 함께 이용해서 C 파일을 컴파일하다가, symbol(s) not found for architecture arm64 라는 오류를 뱉는 것을 경험하게 되어 친구로부터 배운 아래 명령어들을 요긴하게 써먹었다. nasm2이 arm맥에서도 구동이 잘 되긴 하지만 어쨌든 인텔맥용 어셈블러라 인텔맥용 라이브러리만 만들어져서 사용한 방법으로, 이 상황을 비롯해 여러 귀찮은 상황에서 어쨌든 터미널에서 구동되는 앱을 인텔 맥에서처럼 작동시킬 수 있는 방법이다.

여러모로 애플 실리콘 맥은 컴퓨터 구조(?)나 컴파일러 등에 대해 학습하는데도 많은 도움을 줄 것 같다. 흥미로운 점이 많아 사용하면서 이런저런 재미를 주는 건 덤…

아직 애플 실리콘 M1 맥에 대한 정보가 부족하고, 제 지식이 짧아 잘못된 예시나 설명이 있을 수 있습니다. 혹시 설명에 틀린 부분이 있다면 댓글로 지적 부탁드립니다.

무조건 로제타로 돌려야할 때, x86_64용(인텔맥용) 터미널 앱 구동하기

해결책은 간단하다. 이걸 친구한테 배워서 이게 애플이 마련한 대책인지, 아니면 원래 유닉스 계열에서 이런 식으로 아키텍처를 선택(?)할 수 있는 건지는 잘 모르지만 애플 기술 문서에서 얼핏 본 것 같다.

$ arch -x86_64 실행할 명령어

이런 식으로 쓰면 된다. 예를 들자면 이런 식이다.

$ arch -x86_64 gcc -L. -lasm libasm_tester.c

물론 gcc 자체는 애플이 arm64e로 다 만들어둬서 원래는 문제가 없지만, libasm.a 파일이 인텔맥용으로 이미 만들어진 라이브러리이기 때문에 문제가 생긴다. arch -x86-64 를 붙이지 않고 실행하면 gcc가 기본값으로 arm64용 바이너리를 만들려고 시도하는데, 이 과정에서 libasm.a 파일을 사용할 수 없으므로 warning: ignoring file ./libasm.a, building for macOS-arm64 but attempting to link with file built for unknown-x86_64 라는 경고를 하며 libasm.a 라이브러리 파일을 무시하게 된다.

사실 gcc에 분명히 x86_64로 컴파일하는 옵션이 있을 테니 적절한 예시가 아닐 수 있지만, arch -x86_64 설명을 위해 단순히 예시로 사용한 점 참고 부탁드립니다.

아무튼 이 때 arch -x86-64를 앞에 붙여주면 gcc가 x86_64 모드로 구동되어 x86_64용 프로그램으로 컴파일하게 되는데, 이 때는 libasm.a 라이브러리를 잘 이용해서 컴파일하는 것으로 보인다. 전혀 문제없이 잘 컴파일되며, 이렇게 만들어진 a.out 파일은 x86_64용 바이너리가 됨을 확인할 수 있다. (내가 컴파일한 프로그램을 로제타로 돌리게 된다니) 어떻게 확인하냐면…

이 프로그램은 인텔용일까? 애플 실리콘용일까?

lipo를 사용해 확인할 수 있다. 이건 애플에서 만든 것 같다.

$ lipo -archs 실행파일명

아래와 같은 식으로 확인해볼 수 있다.

$ lipo -archs ./a.out
x86_64
$ lipo -archs $(which nasm)
x86_64
$ lipo -archs $(which python3)
x86_64 arm64e
$ lipo -archs ./testprogram
arm64

각각의 상황은 다음과 같다.

  • x86_64 한 개만 뜬다 : 당연히 x86_64용 프로그램이고, 이 프로그램을 실행할 때는 별도로 신경쓰지 않아도 알아서 로제타가 x86_64용으로 구동시킨다.
  • x86_64arm64(e)두 개가 뜬다 : 두 개 다 들어있는 유니버설 앱이다. 실행 시 기본적으로 arm64로 구동되며 위에서 다룬 arch -x86_64를 붙이고 실항하면 인텔맥용 바이너리를 실행하는 식. 참고로 arm64뒤에 e가 붙는 건 애플이 자체적으로 최적화한 그런(?) 바이너리라는 듯…
  • arm64만 뜬다 : 아직 직접 컴파일하는 경우 외에 이런 경우를 보진 못했다. arm64 바이너리만 존재하는 경우에도 궁금해서 arch -x86_64를 붙여 실행해봤는데, 당연히 arch: posix_spawnp: ./a.out: Bad CPU type in executable 오류를 뱉으며 실행이 안 된다.

마무리

솔직히 어셈블리 과제 같은 걸 ARM 맥에서 잘 할 수 있을까 궁금했는데, 문제 없이 수행 가능한 것 같아서 신기하다는 생각이 든다. 여러모로 ARM 맥과 로제타 2는 상식을 깨는 대단한 물건인 것 같다. 덕분에 공부도 되고, 장난감으로서의 가치도 훌륭한 것 같고… 여러분도 사세요.

  1. 어셈블리로 string.h 내장 함수 몇 가지를 구현하는 과제 

  2. 넷와이드 어셈블러. 인텔 x86 아키텍처용 어셈블러이자 역어셈블러라고 한다. 42에서 어셈블리 공부에 사용한다. NASM은 가장 대중적인 리눅스용 어셈블러들 가운데 하나라고 한다. 

댓글을 남겨주세요