Skip to content

Wine

와인(영어: Wine)은 마이크로소프트 윈도우 전용 프로그램을 유닉스 계열 운영체제에 실행하기 위한 호환성 계층이다.

About

Wine (originally an acronym for "Wine Is Not an Emulator") is a compatibility layer capable of running Windows applications on several POSIX-compliant operating systems, such as Linux, Mac OSX, & BSD. Instead of simulating internal Windows logic like a virtual machine or emulator, Wine translates Windows API calls into POSIX calls on-the-fly, eliminating the performance and memory penalties of other methods and allowing you to cleanly integrate Windows applications into your desktop.

How to install

ArchLinux

ArchLinux 에서는 multilib 저장소를 활성화 해야 한다.

$ sudo pacman -S wine

Internet Explorer를 사용한다면:

$ sudo pacman -S wine-gecko

.NET을 사용한다면:

$ sudo pacman -S wine-mono

Ubuntu

설치 가능한 패키지를 검색해보자:

sudo apt search wine

다음과 같은 목록이 나온다:

  • wine/jammy,jammy,now 6.0.3~repack-1 all [installed,automatic] - Windows API implementation - standard suite
  • wine-binfmt/jammy,jammy 6.0.3~repack-1 all - Register Wine as the interpreter for Windows executables
  • wine-development/jammy,jammy 6.0+repack-1ubuntu1 all - Windows API implementation - standard suite
  • wine-stable/jammy,jammy,now 3.0.1ubuntu1 all [installed] - Windows API implementation (transitional package)
  • wine32/jammy,now 6.0.3~repack-1 i386 [installed,automatic] - Windows API implementation - 32-bit binary loader
  • wine32-development/jammy 6.0+repack-1ubuntu1 i386 - Windows API implementation - 32-bit binary loader
  • wine32-development-preloader/jammy 6.0+repack-1ubuntu1 i386 - Windows API implementation - prelinked 32-bit binary loader
  • wine32-development-tools/jammy 6.0+repack-1ubuntu1 i386 - Windows API implementation - 32-bit developer tools
  • wine32-preloader/jammy 6.0.3~repack-1 i386 - Windows API implementation - prelinked 32-bit binary loader
  • wine32-tools/jammy 6.0.3~repack-1 i386 - Windows API implementation - 32-bit developer tools
  • wine64/jammy,now 6.0.3~repack-1 amd64 [installed,automatic] - Windows API implementation - 64-bit binary loader
  • wine64-development/jammy 6.0+repack-1ubuntu1 amd64 - Windows API implementation - 64-bit binary loader
  • wine64-development-preloader/jammy 6.0+repack-1ubuntu1 amd64 - Windows API implementation - prelinked 64-bit binary loader
  • wine64-development-tools/jammy 6.0+repack-1ubuntu1 amd64 - Windows API implementation - 64-bit developer tools
  • wine64-preloader/jammy 6.0.3~repack-1 amd64 - Windows API implementation - prelinked 64-bit binary loader
  • wine64-tools/jammy 6.0.3~repack-1 amd64 - Windows API implementation - 64-bit developer tools
  • winetricks/jammy,jammy 0.0+20210206-2 all - simple tool to work around common problems in Wine

일단 안정화 버전과 winetricks를 설치:

sudo apt install wine-stable winetricks

winecfg

Wine 용 GUI 구성 도구이며 winecfg를 실행하여 시작할 수 있습니다.

최초 설치시 .NET을 위한 mono, Embedding HTML을 위하 geko 패키지 등을 설치한다.

regedit

Wine의 레지스트리 편집 도구로 regedit를 실행하여 시작할 수 있습니다. 유용한 레지스트리 키에 대한 WineHQ의 기사를 참조하십시오.

control

Wine 컨트롤을 실행하여 시작할 수있는 Wine의 Windows 제어판 구현입니다.

전체 목록은 WineHQ의 명령 목록을 참조하십시오.

모든 wine 프로세스를 죽이는 방법

wineserver -k

다음을 통해 강제 종료 할 수 있습니다.

wineserver -k9

wine 재부팅

wineboot

Fonts

Wine 응용 프로그램에 쉽게 읽을 수있는 글꼴이 표시되지 않으면 글꼴이 설치되어 있지 않을 수 있습니다. wine에서 액세스 할 수 있도록 모든 시스템 글꼴을 쉽게 연결하려면:

cd ${WINEPREFIX:-~/.wine}/drive_c/windows/Fonts
find /usr/share/fonts/ -iname '*.otf' -o -iname '*.ttf' -exec ln -s {} \;

나눔고딕 설치 및 설정

sudo apt install fonts-nanum

cd ${WINEPREFIX:-~/.wine}/drive_c/windows/Fonts

dpkg -L fonts-nanum | grep --color=never -i '\.ttf$' | xargs -i ln -s {}

sed -i 's/"MS Shell Dlg"="Tahoma"/"MS Shell Dlg"="NanumGothic"/' ~/.wine/system.reg
sed -i 's/"MS Shell Dlg 2"="Tahoma"/"MS Shell Dlg 2"="NanumGothic"/' ~/.wine/system.reg

한글 폰트 출력

winetricks로 폰트를 다운로드 받는다. (~/.wine/drive_c/windows/Fonts 폴더를 확인하면 된다)

winetricks corefonts
winetricks allfonts

~/.wine/system.reg파일의, "MS Shell Dlg" 항목이 Tahoma으로 되어있을 것이다. 이 것을 Gulim으로 변경한다.

wine을 재시작한다:

wineboot

환경변수 LANG=ko_KR.utf8로 변경한다.

위 방법 또는

레지스트리의 FontSubstituteNanumGothic으로 하는 설정, 여전히 유효하다. 경로는 다음과 같다:

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\FontSubstitutes

Winetricks

Winetricks는 Windows 프로그램을 실행하는 데 필요한 기본 요구 사항을 설치할 수있는 스크립트입니다. 설치 가능한 구성 요소에는 DirectX 9.x, MSXML (Microsoft Office 2007Internet Explorer에 필요), Visual Runtime 라이브러리 등이 포함됩니다.

sudo pacman -S winetricks

Optional dependencies for wine

  • giflib
  • lib32-giflib
  • libpng
  • lib32-libpng
  • libldap
  • lib32-libldap
  • gnutls
  • lib32-gnutls
  • mpg123
  • lib32-mpg123
  • openal
  • lib32-openal
  • v4l-utils
  • lib32-v4l-utils
  • libpulse
  • lib32-libpulse
  • alsa-plugins
  • lib32-alsa-plugins
  • alsa-lib
  • lib32-alsa-lib
  • libjpeg-turbo
  • lib32-libjpeg-turbo
  • libxcomposite
  • lib32-libxcomposite
  • libxinerama
  • lib32-libxinerama
  • ncurses
  • lib32-ncurses
  • opencl-icd-loader
  • lib32-opencl-icd-loader
  • libxslt
  • lib32-libxslt
  • gst-plugins-base-libs
  • lib32-gst-plugins-base-libs
  • vkd3d
  • lib32-vkd3d
  • sdl2
  • lib32-sdl2
  • libgphoto2
  • sane
  • gsm
  • cups
  • samba
  • dosbox

Wine Application Database (AppDB)

minit (Game)

설치 목록:

  • d3dcompiler_42
  • d3dcompiler_43
  • d3dcompiler_46
  • d3dcompiler_47
  • d3dx10
  • d3dx11
  • d3dx9

작동 원리

Wine은 POSIX 호환 OS(리눅스,macOS,BSD)에서 Windows 프로그램을 실행가능하게 해주는 호환레이어

밸브의 Steam Deck도 Wine기반 솔루션을 사용

=== WINE = Wine Is Not an Emulator ===

  • 에뮬레이터 방식은 느리고, 실제로 Linux/macOS는 네이티브하게 윈도우 바이너리를 실행가능함 (조금만 도와준다면)
  • 디버거를 통해서 리눅스/윈도우 바이너리가 어떻게 동작하는지 상세 설명

Hello, Wine!

  • 기본적으로 Wine은 윈도우 실행파일에 대한 "Dynamic Loader"임
  • 네이티브 리눅스 바이너리이고, EXE나 DLL을 어떻게 처리해야 하는지 알고 있음
  • Wine은 윈도우 실행파일을 메모리에 읽어들인 후, 파싱해서 의존성을 파악하고, 실행해야할 코드로 점프
  • 이것만으로도 일단 윈도우 바이너리를 실행가능하지만, 예외가 있음

System Calls

  • syscalls 라고 부르는 시스템호출이 Wine을 복잡하게 함
  • syscalls 는 OS에 구현되는 것이며, 실행파일 또는 라이브러리에 들어있는게 아님
  • OS에서 제공하는 syscalls는 OS API
    • 리눅스 : read, write, open, brk, getpid,..
    • 윈도우 : NtReadFile, NtCreateProcess, NtCreateMutant,..
  • 시스템 호출은 코드의 일반 함수호출과 다름. 예를 들어, 파일 오픈 같은 것은 File Descriptor를 추적하기 때문에 커널에서 처리되어야 함
  • 따라서 응용 프로그램 코드는 자체적으로 "인터럽트"하고 커널에 제어를 제공하는 방법이 필요("Context Switch")
  • OS가 제공하는 함수 집합과 호출 방식은 OS별로 다름
    • 리눅스에서는 read() 함수를 호출하면 파일 디스크립터를 레지스터 %rdi, 버퍼 포인터를 %rsi, 읽을 바이트수를 %rdx 에 넣어야 함
    • 하지만 윈도우는 read() 함수가 커널에 없음
  • 같은 "Hello World!" 를 인쇄하는 코드를 리눅스/윈도우에서 실행해보면
    • 리눅스는 libc.so 의 puts를, 윈도우는 ucrtbase.dll 의 printf 를 호출
    • 요즘 리눅스에선 정적으로 링크해버려서 puts 구현체를 바이너리안에 포함시켜서 libc.so가 실행중에 안쓰이는게 일반적
  • 윈도우에서는 적어도 최근까지만 해도 "Malware만 시스템 호출을 직접 사용했음"
    • 일반적인 응용프로그램은 항상 kernel32.dll/kernelbase.dll/ntdll.dll 에 의존하여 커널과 직접 통신하지 않게 함

Runtime translation of Syscalls

  • syscall 을 인터셉트하면 어떨까?
  • 어플리케이션이 NtWriteFile()을 호출할 때 끼어들어서 write()를 호출한 후 바이너리가 원하는 결과 포맷으로 리턴해 준다면?
  • 커스텀 버전의 ucrtbase.dll 을 제공한다면 가능하겠지만, 복잡한 문제가 발생
  • 대신에 바이너리와 커널사이에 끼어있는 ntdll.dll을 수정
  • 최근 버전의 Wine은 ntdll.dll(PE 바이너리) 과 ntdll.so(ELF 바이너리) 로 구성
    • dll은 얇은 레이어로 단순히 콜을 ELF쪽으로 리디렉션함
    • ELF는 __wine_syscall_dispatcher 라는 특별한 함수를 가지고 있어서, 현재 스택을 윈도우에서 리눅스, 또는 그 반대로 변환하는 마법을 부림
  • 이 syscall dispatcher 가 윈도우 세계와 리눅스 세계를 연결하는 다리임
    • 콜링 컨벤션을 처리하고, 스택 공간을 할당하고, 레지스터를 옮기고 하는 등의 처리를 함
    • 실행이 ntdll.so로 와서 리눅스 바이너리로 넘어오면, 우리는 모든 Linux API를 사용할 수 있게 됨

이게 다라고?

  • 매우 쉬운 것처럼 들리지만..
    • 윈도우 API는 엄청 많고, 문서화가 잘 되어있지 않으며, 알려진/안알려진 버그들이 있고, 그것들은 있는 그대로 보존해야함. 대부분의 Wine 코드는 다양한 윈도우 DLL의 구현체임
    • syscall 호출엔 다양한 방법이 있고, 기술적으로 어플리케이션들이 syscall을 직접 호출하는 것을 막을 방법이 없음
    • (윈도우 게임들은 모든 미친 짓을 한다는 것을 기억할 것)
    • 리눅스 커널은 이걸 처리하는 특별한 메커니즘이 있고, 물론 이게 복잡도를 가중 시킴
    • 32bit vs 64bit 문제도 넌센스임. 수많은 32비트 게임들이 있고, 그들은 다시 64비트로 재릴리즈 되지 않을 것. Wine은 둘 다를 지원하기 때문에 이 역시 복잡도를 가중 시킴
    • 여기서 wine-server는 거론도 하지 않았음. 이것은 Wine이 생성하는 별도의 프로세스로, 커널의 "상태"(파일 디스크립터, 뮤텍스 등)을 유지함
    • 게임을 실행하고 싶다면? DirectX 와 PulseAudio, 입력 디바이스 등을 처리해야해서 일이 엄청 많음
  • 와인은 오래 개발되어 먼 길을 왔음. 오늘날엔 최신 게임인 Cyberpunk 2077 이나 Elden Ring을 아무 문제없이 실행 가능
  • 심지어 가끔은 Wine이 Windows보다 더 나은 성능을 보일 때도 있음

Troubleshooting

FATAL ERROR in Vertex Shader compilation

################################################################################
FATAL ERROR in Vertex Shader compilation
ShaderName: shdSwap

memory:67:22: error: syntax error, unexpected NEW_IDENTIFIER

at gml_Object_UberCont_Draw_77
################################################################################

또는:

################################################################################
FATAL ERROR in Vertex Shader compilation
ShaderName: shaderTemplate

D3DXCompile failed - result

at gml_Object_objControlerN_Draw_64
################################################################################

다음을 설치했다:

  • d3dcompiler_42
  • d3dcompiler_43
  • d3dcompiler_46
  • d3dcompiler_47
  • d3dx10
  • d3dx11
  • d3dx9

Call from 7B010BE6 to unimplemented function mfplat.dll.MFCreateTempFile, aborting

KakaoTalk에서 프로필 클릭하면 에러 뜨더라...

wine: Call from 7B010BE6 to unimplemented function mfplat.dll.MFCreateTempFile, aborting

Wine Mono is not installed

03b4:err:mscoree:CLRRuntimeInfo_GetRuntimeHost Wine Mono is not installed

Mono 를 설치하자.

See also

Favorite site

References


  1. How_Wine_works_101_-_Reboot_and_Shine.pdf 

  2. How_to_install_DirectX_in_Linux_using_Wine.pdf