TeXLive on FreeBSD(ファイル名と格闘編)
portshakerで得られるtexliveのports collectionにprint/texlive-japanese-otf-uptexというものが出てきましたが、ファイル名に()と空白を含んでおり、print/texlive-core/bsd.texlive.mkではうまく処理できていません。また、pkg-plistも不完全な状態です。
今回はこれを解決してみよう、という話です。
FreeBSDのtexlive portsは、texlive の tlpobj を公式のperl scriptではなくて自前の print/texlive-core/bsd.texlive.mk で取り扱うようにできているようです。そして、そこではawkスクリプトが用いられています。ファイル名に空白を含んでいることは想定外のようですので、そこから直します。tlpobjのフォーマットはよくわかりませんが、公式のperl module(例えば、http://distrib-coffee.ipsl.jussieu.fr/pub/mirrors/ctan/systems/texlive/tlnet/tlpkg/TeXLive/ の TLPOBJ.pm, TLConfig.pmあたり)を参考にすると、デフォルト設定では、" ほげほげ"という行があったら(先頭空白に注意)、"$prefix/ほげほげ"、というパスを表す、さらに、もし" RELOC/ほげほげ"という文字列の場合は、設定ファイル(これはどこにあるのか…)で指定された文字列に置換してから"$prefix/"を先頭に付加する、というシンプルな仕組みのようです。一方で、bsd.texlive.mkの方では、空白入りファイル名は想定せずに、インストールするファイルのsrcとdstとオプション(pkg-plistに出てくる、%%NOPORTDOCS%%など)を空白区切りファイルに一旦格納します。ここが問題なので、とりあえず、ファイル名やパス名にコンマは出てこないだろう、と仮定し(この仮定はまずいかも知れないが、他の文字でもいい。何なら良いだろうか?)、コンマ区切りファイル(CSV)にいったん格納するように変更します。
--- portshaker/freebsd_texlive/print/texlive-core/bsd.texlive.mk 2012-01-20 00:31:50.290495850 +0900 +++ bsd.texlive.mk 2012-02-06 00:42:08.985429696 +0900 @@ -24,81 +24,82 @@ FETCH_ARGS= -ApR # Do NOT restart a previously interrupted transfer USE_XZ= yes NO_BUILD= yes +NO_WRKSUBDIR= yes MKTEXLSR= ${PREFIX}/bin/mktexlsr ${WRKDIR}/.install_files: build - @( cd ${WRKDIR} && cat tlpkg/tlpobj/${PORTNAME}.tlpobj | awk '\ - $$0 ~ /^ / { \ - source=$$1; \ - target="share/" $$1; \ - if (index($$1, "RELOC/")) { \ - sub("RELOC/", "", source); \ - sub("RELOC/", "texmf-dist/", target); \ + @( cd ${WRKDIR} && ${CAT} tlpkg/tlpobj/${PORTNAME}.tlpobj | ${GREP} ^\ | ${AWK} '\ + { \ + source=substr($$0, 2, length($$0)); \ + target="share/" source; \ + if (index(source, "RELOC/")) { \ + sub("RELOC/","",source); \ + sub("RELOC/", "texmf-dist/",target); \ } \ - if (system("[ -e ${PREFIX}/" target " ]") != 0) { \ - print source " " target; \ + if (system("[ -e \"${PREFIX}/" target "\" ]") != 0) { \ + print source "," target ","; \ } \ }' > ${WRKDIR}/.install_files; \ ) .if !defined(NOPORTDOCS) - @( cd ${WRKDIR} && cat tlpkg/tlpobj/${PORTNAME}.doc.tlpobj | awk '\ - $$0 ~ /^ / { \ - source=$$1; \ - target="share/" $$1; \ - if (index($$1, "RELOC/")) { \ - sub("RELOC/", "", source); \ - sub("RELOC/", "texmf-dist/", target); \ + @( cd ${WRKDIR} && ${CAT} tlpkg/tlpobj/${PORTNAME}.doc.tlpobj | ${GREP} ^\ | ${AWK} '\ + { \ + source=substr($$0, 2, length($$0)); \ + target="share/" source; \ + if (index(source, "RELOC/")) { \ + sub("RELOC/","",source); \ + sub("RELOC/", "texmf-dist/",target); \ } \ - if (system("[ -e ${PREFIX}/" target " ]") != 0) { \ - print source " " target " %%PORTDOCS%%"; \ + if (system("[ -e \"${PREFIX}/" target "\" ]") != 0) { \ + print source "," target ",%%PORTDOCS%%"; \ } \ }' >> ${WRKDIR}/.install_files; \ ) .endif .if !defined(NOPORTSRC) - @( cd ${WRKDIR} && cat tlpkg/tlpobj/${PORTNAME}.source.tlpobj | awk '\ - $$0 ~ /^ / { \ - source=$$1; \ - target="share/" $$1; \ - if (index($$1, "RELOC/")) { \ - sub("RELOC/", "", source); \ - sub("RELOC/", "texmf-dist/", target); \ + @( cd ${WRKDIR} && ${CAT} tlpkg/tlpobj/${PORTNAME}.source.tlpobj | ${GREP} ^\ | ${AWK} '\ + { \ + source=substr($$0, 2, length($$0)); \ + target="share/" source; \ + if (index(source, "RELOC/")) { \ + sub("RELOC/", "",source); \ + sub("RELOC/", "texmf-dist/",target); \ } \ - if (system("[ -e ${PREFIX}/" target " ]") != 0) { \ - print source " " target " %%PORTSRC%%"; \ + if (system("[ -e \"${PREFIX}/" target "\" ]") != 0) { \ + print source "," target ",%%PORTSRC%%"; \ } \ }' >> ${WRKDIR}/.install_files; \ ) .endif pkg-plist: ${WRKDIR}/.install_files - @sort -k 2 < ${WRKDIR}/.install_files | awk ' { print $$3 $$2 } ' > ${PLIST} - @for dir in `cut -f 2 < ${WRKDIR}/.install_files | xargs dirname | sort -r | uniq`; do \ + @${SORT} -t',' -k 2 < ${WRKDIR}/.install_files | ${AWK} -F',' ' { print $$3 $$2 } ' > ${PLIST} + @for dir in `${CUT} -d',' -f 2 < ${WRKDIR}/.install_files | ${XARGS} dirname | ${SORT} -r | uniq`; do \ if [ ! -d "${PREFIX}/$$dir" ]; then \ - echo @dirrmtry $$dir >> ${PLIST} ;\ + ${ECHO} @dirrmtry $$dir >> ${PLIST} ;\ fi; \ done - @echo "@exec %D/bin/mktexlsr" >> ${PLIST} - @echo "@unexec %D/bin/mktexlsr" >> ${PLIST} + @${ECHO} "@exec %D/bin/mktexlsr" >> ${PLIST} + @${ECHO} "@unexec %D/bin/mktexlsr" >> ${PLIST} do-install: ${WRKDIR}/.install_files - @for dir in `cut -f 2 < ${WRKDIR}/.install_files | xargs dirname | sort -r | uniq`; do \ + @for dir in `${CUT} -d',' -f 2 < ${WRKDIR}/.install_files | ${XARGS} dirname | ${SORT} -r | uniq`; do \ if [ ! -d "${PREFIX}/$$dir" ]; then \ ${MKDIR} "${PREFIX}/$$dir" ;\ fi; \ done - @( cd ${WRKDIR} && while read source target junk; do \ + @( cd ${WRKDIR} && IFS="," && while read source target junk; do \ ${INSTALL_DATA} $$source ${PREFIX}/$$target; \ done < ${WRKDIR}/.install_files \ ) post-install: .if defined(WITHOUT_TEXLIVE_MKTEXLSR) - @echo "WITHOUT_TEXLIVE_MKTEXLSR is set. Not running ${MKTEXLSR}." - @echo "You MUST run 'mktexlsr' to update TeXLive installed files database." + @${ECHO} "WITHOUT_TEXLIVE_MKTEXLSR is set. Not running ${MKTEXLSR}." + @${ECHO} "You MUST run 'mktexlsr' to update TeXLive installed files database." .else - @echo "Updating ls-R databases..." + @${ECHO} "Updating ls-R databases..." @${MKTEXLSR} .endif
awkで先頭一文字だけ除く美しい方法がよくわからないので結局、substrしました。初めてIFS使った。ついでに、echoを${ECHO}にするとか、コマンドの変数化もやりました(uniqだけ/usr/ports/Mk/bsd.commands.mkに見付からなかったので、置き換えてません。ないのか…)。さらについでに、以前も指摘したエラーメッセージの抑制のパッチも入っています。このパッチは、 http://www.gfd-dennou.org/member/murashin/distfiles/patches/bsd.texlive.mk.patch に、ファイルそのものは http://www.gfd-dennou.org/member/murashin/distfiles/patches/bsd.texlive.mk.escaped-shell-chars に置いてあります。
パッチは ~/bsd.texlive.mk.patch にあるとして、 パッチを print/texlive-core/bsd.texlive.mkに当てて、pkg-plistを作りなおして、make install します。
# cd /usr/ports/print/texlive-core/ # patch < ~/bsd.texlive.mk.patch # cd ../texlive-japanese-otf-uptex/ # make pkg-plist # make install
これは、print/texlive-japanese-otf-uptex, あるいはパッケージ名としては texlive-japanese-otf-uptex-20120203 をインストールした状態、もっと正確に言えば、texlive-japanese-otf-uptex-20120203 の内容物をインストールした状態で行ってはいけません。その場合、正常なpkg-plistが生成されません。これは、pkg-plist生成時およびインストール時に、存在しないファイルだけをインストールするようになっているからです。
というわけで、print/japanese-otf-uptexを正常にインストールできるようになりました。なお、上記のパッチはfreebsd-texliveの開発・メンテナのromainさんに送りました。下手な英語で通じるのかどうか不安ですが、とりあえず待ちです。
(2012/2/6 0:55ごろ訂正) tlpobjに" RELOC"がない場合、エンバグしてしまっていたので、直しました。汚いですが。それに伴って上記のdiffも入れ換えてあります。前後の文面も多少変えました。それ以前のものを持っていってしまった方はご注意下さい。
(2012/2/6 5:50ごろ訂正) PORTDOCSについてインストールされない不具合が混入していたので直しました。ご注意下さい。また、生成されるpkg-plistは、このパッチを適用するかしないかにかかわらず、不完全である疑いがあります。特に@dirrmtry回りが怪しいです。こちらもご注意を。
(2012/2/7 3:30ごろ訂正) RELOC を置換するあたりの文を、正しくしました。