試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

Wine環境にWindows版のPyGTKをインストールする作業を自動化

Windows版PyGTKをWine環境にインストール」の作業は色々と面倒なので、自動でこれを行うスクリプトを作成した。ダウンロードする各パッケージのバージョンは今後変化していくため、最新バージョンを使用するためにはコード内の上のほうにある各パッケージのバージョン番号部分を書き換えていくことになる。
Wineインストーラが正常に通らない可能性があるものは使用せず、Pythonをインストールするのにmsiexecは使用しているが残りは全てunzipコマンドで展開してインストールしている(同コマンドがインストールされている必要がある)。
GTK+を使用するためのレジストリ設定も最後に自動で行っている。
[任意]ファイル名: wine-pygtk-setup.sh

#! /bin/bash

# wine-pygtk-setup.sh
# Wine環境(WINEPREFIX)へWindows版GTK+/Python/PyGTKをインストールする
# (C) 2009 kakurasan
# Licensed under LGPL2+

PYTHON_VER=2.6.1
GTK_VER=2.14.7-20090119
PYGOBJECT_VER=2.14.2-2
PYCAIRO_VER=1.4.12-2
PYGTK_VER=2.12.1-3

ARCH=win32

PYTHON_VER_SHORT=$(echo ${PYTHON_VER} | sed 's:\([0-9]*\.[0-9]*\)\..*:\1:')
GTK_VER_SHORT=$(echo ${GTK_VER} | sed 's:\([0-9]*\.[0-9]*\)[\.\-].*:\1:')
PYGOBJECT_VER_SHORT=$(echo ${PYGOBJECT_VER} | sed 's:\([0-9]*\.[0-9]*\)[\.\-].*:\1:')
PYCAIRO_VER_SHORT=$(echo ${PYCAIRO_VER} | sed 's:\([0-9]*\.[0-9]*\)[\.\-].*:\1:')
PYGTK_VER_SHORT=$(echo ${PYGTK_VER} | sed 's:\([0-9]*\.[0-9]*\)[\.\-].*:\1:')

PYTHONDIR=Python${PYTHON_VER_SHORT:0:1}${PYTHON_VER_SHORT:2:1}

URL_PYTHON_BASE=http://python.org/ftp/python
URL_GTK_BASE=http://ftp.gnome.org/pub/gnome/binaries/${ARCH}/gtk+
URL_PYGOBJECT_BASE=http://ftp.gnome.org/pub/GNOME/binaries/${ARCH}/pygobject
URL_PYCAIRO_BASE=http://ftp.gnome.org/pub/GNOME/binaries/${ARCH}/pycairo
URL_PYGTK_BASE=http://ftp.gnome.org/pub/GNOME/binaries/${ARCH}/pygtk

URL_PYTHON=${URL_PYTHON_BASE}/${PYTHON_VER}/python-${PYTHON_VER}.msi
URL_GTK=${URL_GTK_BASE}/${GTK_VER_SHORT}/gtk+-bundle_${GTK_VER}_${ARCH}.zip
URL_PYGOBJECT=${URL_PYGOBJECT_BASE}/${PYGOBJECT_VER_SHORT}/pygobject-${PYGOBJECT_VER}.${ARCH}-py${PYTHON_VER_SHORT}.exe
URL_PYCAIRO=${URL_PYCAIRO_BASE}/${PYCAIRO_VER_SHORT}/pycairo-${PYCAIRO_VER}.${ARCH}-py${PYTHON_VER_SHORT}.exe
URL_PYGTK=${URL_PYGTK_BASE}/${PYGTK_VER_SHORT}/pygtk-${PYGTK_VER}.${ARCH}-py${PYTHON_VER_SHORT}.exe

PATH=/bin:/usr/bin
WINEPREFIX=${WINEPREFIX:-~/.wine}
CACHEDIR=${CACHEDIR:-~/.cache/wine-pygtk-setup}


download()
{
  local outfile="${CACHEDIR}/$(basename ${1})"
  if [ ! -f "${outfile}" ]; then
    if wget -V | grep Wget >/dev/null 2>&1; then
      wget -O "${outfile}.part" -c "${1}"
    else
      curl -L -o "${outfile}.part" -C - "${1}"
    fi
    [ ${?} -ne 0 ] && return 1
    mv "${outfile}"{.part,}
    return 0
  fi
}

# キャッシュディレクトリにファイルが無ければダウンロード
mkdir -p "${CACHEDIR}"
for URL in ${URL_PYTHON} ${URL_GTK} ${URL_PYGOBJECT} ${URL_PYCAIRO} ${URL_PYGTK}; do
  if ! download ${URL}; then
    echo "Download failed: "${URL} >&2
    exit 1
  fi
done

# Pythonを非対話でインストール
if ! msiexec /i "${CACHEDIR}"/$(basename ${URL_PYTHON}) /qn; then
  echo "Failed to install Python" >&2
  exit 1
fi

# GTK+をインストール
cd "$(winepath -u "C:\\")"
mkdir GTK
cd GTK
if ! unzip "${CACHEDIR}"/$(basename ${URL_GTK}) > /dev/null; then
  echo "Failed to extract GTK+" >&2
  exit 1
fi

# 一時ディレクトリ
# Wine環境の一時ディレクトリを利用
cd "$(winepath -u "C:\\WINDOWS\\TEMP")"
TMPDIR=$(mktemp -d wine-pygtk-setup.XXXXXXXXXX)
pushd ${TMPDIR} > /dev/null

# PyGTKの各パッケージをインストール
for F in $(basename ${URL_PYGOBJECT}) $(basename ${URL_PYCAIRO}) $(basename ${URL_PYGTK}); do
  # 被るファイルは上書き
  yes | unzip -u "${CACHEDIR}"/${F} > /dev/null
  # 警告が出て展開が行われると戻り値1で終了する
  if [ ${?} -ne 1 ]; then
    echo "Failed to extract ${CACHEDIR}/${F}" >&2
    popd > /dev/null
    rm ${TMPDIR} -fr
    exit 1
  fi
done
pushd DATA/ > /dev/null
mv {l,L}ib
for F in $(find -type f | sed 's:/[^/]*$::' | sort -u); do
  install -d "../../../../${PYTHONDIR}/${F}"
  mv $(find ${F}/* -maxdepth 0 -type f) "../../../../${PYTHONDIR}/${F}/"
done
popd > /dev/null
pushd PLATLIB/ > /dev/null
for F in $(find -type f | sed 's:/[^/]*$::' | sort -u); do
  install -d "../../../../${PYTHONDIR}/Lib/site-packages/${F}"
  mv $(find ${F}/* -maxdepth 0 -type f) "../../../../${PYTHONDIR}/Lib/site-packages/${F}/"
done
popd

# インストール後の自動実行スクリプト
pushd SCRIPTS/ > /dev/null
for F in *_postinstall.py; do
  wine "C:\\${PYTHONDIR}\\python.exe" ${F} -install
done
popd > /dev/null

# GTK+のレジストリ項目
cat <<EOF > gtk.reg
REGEDIT4

[HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\Environment]
"GTK_BASEPATH"="C:\\\\GTK"
"PATH"=hex(2):25,47,54,4b,5f,42,41,53,45,50,41,54,48,25,5c,62,69,6e,3b,43,3a,\\
  5c,77,69,6e,64,6f,77,73,5c,73,79,73,74,65,6d,33,32,3b,43,3a,5c,77,69,6e,64,\\
  6f,77,73,00

[HKEY_LOCAL_MACHINE\\Software\\GTK\\2.0]
"DllPath"="C:\\\\GTK\\\\bin"
"Path"="C:\\\\GTK"
EOF
printf "\"VendorVersion\"=\"%s\"\n" ${GTK_VER} >> gtk.reg
printf "\"Version\"=\"%s\"\n" $(echo ${GTK_VER} | sed 's:\-.*::') >> gtk.reg
regedit gtk.reg
popd > /dev/null
rm ${TMPDIR} -fr

echo "Done."

インストール先のWine環境(既定は[ホームディレクトリ]/.wine/環境変数WINEPREFIXで変更可)には200MiB、ファイルをダウンロードして保存(再利用可)する領域(既定は[ホームディレクトリ]/.cache/wine-pygtk-setup/環境変数CACHEDIRで変更可とした)には40MiB以上の空きを推奨。
下は[ホームディレクトリ]/.wine-pygtkというWine環境にインストールした後テストを行う例。

(インストール)
$ WINEPREFIX=~/.wine-pygtk [wine-pygtk-setup.shの場所]
(テスト)
$ WINEPREFIX=~/.wine-pygtk wine "C:\Python26\python.exe" [PyGTKを使用したコード]