レガシーPerlビルド ~現代に蘇るPerl[1-2].0とPerl6~

Ffd3f0ebea474176dfbe876216a793f9?s=47 AnaTofuZ
January 26, 2019

レガシーPerlビルド ~現代に蘇るPerl[1-2].0とPerl6~

YAPC::Tokyo 2019でのトークです

Ffd3f0ebea474176dfbe876216a793f9?s=128

AnaTofuZ

January 26, 2019
Tweet

Transcript

  1. レガシーPerlビルド
 ~現代に蘇る 
 Perl[1..5].0
 
 とPerl6~八雲アナグラ @AnaTofuZ
 
 YAPC::Tokyo 2019

  2. None
  3. None
  4. None
  5. None
  6. ͓Θͼ

  7. レガシーPerlビルド
 ~現代に蘇る 
 Perl[1-5].0
 
 とPerl6~八雲アナグラ @AnaTofuZ
 
 YAPC::Tokyo 2019

  8. レガシーPerlビルド
 ~現代に蘇る 
 Perl[1-2].0
 
 とPerl6~八雲アナグラ @AnaTofuZ
 
 YAPC::Tokyo 2019

  9. None
  10. •転生したらPerlだけPerl2.0しかない世界だった •上司からPerl3で動かすように圧を掛けられた •考古学が好き •役に立たない技術を追い求めたい

  11. 明日の役には立たない!!!!! いますぐ行こう 
 ホール か Room0

  12. my $self = shift; • 八雲アナグラ (id:AnaTofuZ) • 最近はCとCbC(軽量継続が入ったC言語)
 Perlなどを書いている

    • オリオンビールと泡盛を飲むのが目的の団体
 Okinawa.pmとPerl入学式in沖縄所属です
  13. • “Perlぐらいになるとinstallもおもしろい” by 入門Perl • Perl5.28ということは少なくとも30個以上のPerlのバージョン が存在する • 全部ビルド出来るかは解らないが,Perl[1-5]の代表的なPerlを 気合でインストールして遊んでみたいという魂胆です

  14. perl いわゆるperl ラリー・ウォールが書いたもの

  15. perl StrawberryPerl や Active PerlなどのMS用Perl

  16. perl Perl5+Perl6でPerl11や!!!!!!なcperl

  17. perl なつかしのjperl (正体はパッチ)

  18. perl • 今回みるperlはラリー・ウォールによって書かれたperl • Cで実装されている • なおCで書かれているPerlではあるが
 cperlと呼ぶと別物なのでそう呼んではいけない

  19. • Perlのビルド方法 • Perl1.0 • Perl2.0 • Perl3.0 • Perl4.0

    • Perl5.0の動かし方 • Perl6についてちょっと触れる
  20. Perl

  21. Perl

  22. $git tag if-0.0603 if-0.0604 if-0.0605 perl-1.0 perl-1.0.15 perl-1.0.16 perl-2.0 perl-2.001

    perl-3.000 perl-3.044 perl-4.0.00 perl-4.0.36 perl-5.000 perl-5.000o
  23. • GitHubから落とすのがやりやすく, やり方は主に二種類
 • git logが欲しい場合
 • git logはいらない場合
 git

    clone -b perl-1.0 —single-branch git@github.com:Perl/perl5.git wget https://github.com/Perl/perl5/archive/perl-1.0.tar.gz
  24. tar ~/w/p/o/p/t/perl5-perl-1.0 » ls -la total 816 drwxr-xr-x 44 anatofuz

    staff 1408 Dec 18 1987 ./ drwxr-xr-x 6 anatofuz staff 192 Jan 26 05:35 ../ -rwxr-xr-x 1 anatofuz staff 27329 Dec 18 1987 Configure* -rw-r--r-- 1 anatofuz staff 226 Dec 18 1987 EXTERN.h -rw-r--r-- 1 anatofuz staff 224 Dec 18 1987 INTERN.h -rw-r--r-- 1 anatofuz staff 5872 Dec 18 1987 MANIFEST -rw-r--r-- 1 anatofuz staff 3522 Dec 18 1987 Makefile.SH -rw-r--r-- 1 anatofuz staff 3386 Dec 18 1987 README -rw-r--r-- 1 anatofuz staff 84 Dec 18 1987 Wishlist -rw-r--r-- 1 anatofuz staff 47964 Dec 18 1987 arg.c -rw-r--r-- 1 anatofuz staff 5478 Dec 18 1987 arg.h -rw-r--r-- 1 anatofuz staff 3366 Dec 18 1987 array.c
  25. 1FSM 1FSM 1FSM 1FSM 1FSM

  26. 1FSM 1FSM 1FSM 1FSM 1FSM

  27. Perl • 最近はbrewやplenvやperlbrewなどであまり意識しない気がし ますが…

  28. Perl $POpHVSF

  29. Perl $POpHVSF த਎͸
 4IFMM4DSJQU ؀ڥ͝ͱʹ.BLFpMF
 Λੜ੒͢Δ

  30. Perl $POpHVSF NBLF

  31. Perl $POpHVSF NBLF .BLFpMFΛݩʹ
 NBLFίϚϯυͰ
 QFSMΛϏϧυ͢Δ

  32. Perl $POpHVSF NBLF NBLFJOTUBMM

  33. Perl $POpHVSF NBLF NBLFJOTUBMM ద੾ͳσΟϨΫτϦʹ Ϗϧυͨ݁͠ՌΛ഑ஔ͢Δ

  34. Perl $POpHVSF NBLFEFQFOE NBLFJOTUBMM NBLF

  35. Perl $POpHVSF NBLFEFQFOE NBLFJOTUBMM ΠϯΫϧʔυϑΝΠϧ͕
 Ͳ͜ʹ͋Δ͔Λௐࠪ͢Δ NBLF

  36. Perl • make dpenedは実はperl5でも実行されている(自動実行される) • 基本的には現代のperl5とほとんど変わりない!! • old perl(厳密には3くらいまで)は,手動でmake dependする

    • 現在のlinuxやbsdベースなmac osのビルドフローと変わらない のはラリー・ウォールがUNIXの延長でPerlを考えたからである 為な気がしている(個人の見解です)
  37. Con gure • 最初に実行されるスクリプトConfigure $POpHVSF த਎͸
 4IFMM4DSJQU ؀ڥ͝ͱʹ.BLFpMF
 Λੜ੒͢Δ

  38. Con gure $POpHVSF

  39. con g.sh $POpHVSF DPOpHTI

  40. con g.h Make le $POpHVSF DPOpHTI .BLFpMF4) DQI4) NBLFEFQFOE 4)

  41. con g.h Make le $POpHVSF DPOpHTI .BLFpMF4) DQI4) NBLFEFQFOE 4)

    DPOpH<I)> .BLFpMF
  42. Con gure • 手書き
 (OSの変更に追従して頑張っていく必要がある)
 • そもそもConfigureに頼らない
 (Cmakeを使う,ビルドツールを別に用意するなど)
 • 何かのツールからConfigureを自動的に生成する

  43. Con gure • autoconf,automakeなどのいわゆるGNU製のツールを
 使う事が多い気がする
 • autoconfコマンドでは, configure.inを設定ファイルとして記述し Configureを生成する
 •

    生成されたConfigureは, makefile.in を元にMakefileを生成する (makefile.inを自動的に生成するのがautomake)
  44. • RubyとPythonはconfigure.inがある
 (autoconfを使っている)
 • CコンパイラなLLVM/clangはcmakeを使っているので Configureに頼っていない

  45. Perl Con gure • Perlには1.0から現在までconfigure.inは存在しない
 • そもそもPerl1.0時代にはautoconfがリリースされてない
 (Autoconfは1991リリース, Perlは1987リリース)
 •

    ラリーはどうやってConfigureを生成していたのだろうか…
  46. A. dist • ラリーは自分でConfigureを設定ファイルから生成し
 作ったプログラムをパッケージ化しメールに流すまで
 一連の処理をする「dist」ツールキットを自作した • なお作ってすぐ人にメンテ権を委譲しており, ラリーは初期実装 以外あまり関わっていない

  47. metacon g • configureを生成するのはmetaconfigというPerlスクリプト
 • autoconfのお兄さん的存在(wikipediaにも書いてある) • 現在のGitHubのPerl5リポジトリにあるmetaconfigではない

  48. metacon g NFUBDPOpH ഑෍͢Δ
 ϓϩάϥϜͷ৘ใΛ ·ͱΊΔpackinitΛ
 ࣮ߦ QBDLBHF QBDLJOJU

  49. metacon g NFUBDPOpH ࢖༻͢ΔϓϩάϥϜ ͷҰཡMANIFESTͱ .packageΛಡΈࠐΉ QBDLBHF ."/*'&45 QBDLJOJU

  50. metacon g NFUBDPOpH Ϗϧυ࣌ʹඞཁͳcp ͳͲͷϓϩάϥϜΛฒ ΂ͨϑΝΠϧΛੜ੒ QBDLBHF ."/*'&45 QBDLJOJU 8BOUFE

  51. metacon g NFUBDPOpH ϑΝΠϧͷมߋ఺Λ දʹͨ͠ObsoleteΛ ੜ੒ QBDLBHF ."/*'&45 QBDLJOJU 8BOUFE

    0CTPMFUF
  52. metacon g NFUBDPOpH ೦ئͷConfigureΛ
 ੜ੒ QBDLBHF ."/*'&45 QBDLJOJU 8BOUFE 0CTPMFUF

    $POpHVSF
  53. dist/metacon g • distツールキットのmetaconfigは地味にメンテされている
 (ただしPerl特化から汎用型に変化している上に
 モダンなコードにするなどの積極性はなく
 Perl5で動く実質Perl4なソースコード)
 • 幾つかのdistツールキットはPerl5としてメンテされていない
 (getopts.plをrequireしているコードが残されているなど)

  54. metacon g ( ) sub main'profile { &auto_main'profile; } sub

    auto_main'profile { &main'dataload; } # Load the calling function from DATA segment and call it. This function is # called only once per routine to be loaded. sub main'dataload { local($__packname__) = (caller(1))[3]; $__packname__ =~ s/::/'/; local($__rpackname__) = $__packname__; local($__at__) = $@; $__rpackname__ =~ s/^auto_//; &perload'load_from_data($__rpackname__); local($__fun__) = "$__rpackname__"; $__fun__ =~ s/'/'load_/; eval "*$__packname__ = *$__fun__;"; # Change symbol table entry die $@ if $@; # Should not happen $@ = $__at__; # Restore value $@ had on entrance &$__fun__; # Call newly loaded function
  55. dist/metacon g • レガシーPerl的にはmetaconfigの実行に必要になるPerlの
 設定ファイル(*.SH)は当時のものを利用出来るので便利
 • Perl5のConfigureはdistのmetaconfigを使っている訳では無く
 勝手に書き換えているのが多くなってきている

  56. metacon g • Tux(H.Merjin Brand)さん以外
 殆ど詳しい人がおらず問題に一部でなった. • 2016年のQA Hackathonなどから海外のPerlMongerの間で metaconfigが話題にでる

    • GitHubにリポジトリを移したり
 READMEを書いたりなどの作業がその後進み
 PerlToolChainSummitでもmetaconfigの話がされていた模様
  57. Perl • 基本的な構成はPerl5と変わらずC, YACCで記述されている • perly.cがmain関数があるコード • perl.cはperl.y(YACC)が生成する構文解析するフェーズ • ラリー・ウォールは当初構文解析がPerlだと思っていた?

    • Perl5からはperl.cとperly.cの名前が入れ替わる
  58. Perl1.0

  59. Perl1.0 • 1987年リリース.現存する最古のPerl • 歴史的にはIRCより古い • comp.sources.miscのニュースグループに投稿された • 文法定義はyaccで行い,後はCで書く素朴な実装 •

    Intel8086 pdp11 iAPX286などの16bitアーキテクチャを想定 • OSとしてはsun, gcos, unix, ibm, mertなどに対応している
  60. • PerlMongerは定期的にPerl1.0のパッチを書く習性がある
 (テスト通過率100%のバージョンが存在している)
 • スカラ型のさきがけ
 Str型では文字列の実態をchar*で持つ素朴な実装 • char型に依存するので当然ながらマシン環境に依存する

  61. • K&R (C言語の最初の規格書)が出る前にCで書かれている • 規格が無いため,処理系によって使用するCライブラリ関数の
 返り値の型が異なるケースがあり, マクロで制御している • 構文木を評価するevalループは素朴にマクロを使わずに
 whileループで書かれている

  62. (main ) main(argc,argv,env) register int argc; register char **argv; register

    char **env; { register STR *str; register char *s; char *index(); linestr = str_new(80); str = str_make("-I/usr/lib/perl "); /* first
  63. (main ) main(argc,argv,env) register int argc; register char **argv; register

    char **env; { register STR *str; register char *s; char *index(); linestr = str_new(80); str = str_make("-I/usr/lib/perl "); /* first mainͷܕ͕ແ্͍ʹenvΛ Ҿ਺Ͱ࣋ͬͯ͘Δ Ϩδελʹࡌ͍ͤͨؾ࣋ͪΛ දͨ͠ register͕ଟ༻
  64. (main ) main(argc,argv,env) register int argc; register char **argv; register

    char **env; { register STR *str; register char *s; char *index(); linestr = str_new(80); str = str_make("-I/usr/lib/perl "); /* first ͦ΋ͦ΋Ҿ਺ͷએݴ͕͍ΘΏΔ
 K&RελΠϧ
  65. Perl K&R • Nick Ing-Simmons 氏によって1997年にminiperlの部分を中心 に書き換えられる. • gnuなprotoizeと手書きで直していった •

    PerlへのNick Ing-Simmons氏の貢献は多大
  66. Perl5 #ifdef NO_ENV_ARRAY_IN_MAIN extern char **environ; int main(int argc, char

    **argv) #else int main(int argc, char **argv, char **env) #endif { int exitstatus, i; #ifdef PERL_GLOBAL_STRUCT struct perl_vars *my_vars = init_global_struct(); # ifdef PERL_GLOBAL_STRUCT_PRIVATE int veto; mainؔ਺͚ͩͷperlmain.cͰ intܕͰهड़
  67. • さまざまなエンジニアが気合い入れてメンテナンスされている • 現在でテスト100%通るパッケージが存在する

  68. None
  69. None
  70. Perl1.0 • まずはオプションを解析し • 気合い入れて入力されたファイルを1行ずつ読み込み • 字句解析しつつYACCで構文解析 • あとはひたすら実行するぞ!!!

  71. Perl1 จࣈྻ 453 ΦϒδΣΫτ "3( ͱΓ͍͋͑ͣΖ͍ Ζ͍ΕΔϠπ 45"#

  72. Perl1 TUS@QUS จࣈྻ 453 TUS@MJOL จࣈྻ࡟আ IBTI TUS@MFO จࣈྻ௕ TUS@QPL

    ϙΠϯλʹ453Λม ׵͢Δϑϥά
  73. Perl2.0

  74. Perl2.0 • 付属のConfigureはそのまま使えるが
 make dependした時にmac osのヘッダーファイル関連で破滅 ./config.h:172:19: warning: '/*' within

    block comment [-Wcomment] #/*undef TMINSYS /**/ ^ /usr/include/AvailabilityInternal.h:38846:2: error: #else after #else #else ^ /usr/include/AvailabilityInternal.h:38203:10: error: unterminated conditional directive #if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_13 ^ /usr/include/AvailabilityInternal.h:38116:10: error: unterminated conditional directive #if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_12_4
  75. Con gure <1> • メンテされているmetaconfigを利用して
 Configureそのものを作り変える • 新たに生成したConfigureはよしなに依存しているファイルを書 き出してくれるので,これに乗っ取ることでMakeが通る

  76. Con gure <2> • mac osにgccをinstallする • mac osに標準では行っているgccはgccのフリをしたllvm/clang •

    gccでビルドする様にMakefileを書き換えるとよしなに動く • Mojaveではそもそもgccをinstallするのが難しいので
 最近はこの方法を取らない…
  77. Make le • 無事生成したMakefileであるが, 微妙にビルドできない状況に なっている • Makefileに謎の <built-in>と <command

    line>が出現 • ヘッダーファイルとして存在し無い為ビルドできない
 (昔はこの記法があった?) arg.o: /usr/include/time.h arg.o: <built-in> arg.o: <command line>
  78. Make le • 利用するヘッダーファイルをMakefileに書き出すのは
 makedpend終了後に行われる • なのでmakedpendの設定ファイルmakedepend.SHで
 command-lineなどを生成しない様にする

  79. makedepend.SH $egrep '^#include ' ` cat .clist` ` cat .hlist`

    >.deptmp $echo "Updating Makefile..." <.clist $sed -n \ -e '/\//{' \ -e 's|^\(.*\)/\(.*\)\.c|\2.o: \1/\2.c; '"$defrule \1/\2.c|p" \ -e d \ -e '}' \ -e 's|^\(.*\)\.c|\1.o: \1.c|p' >> Makefile.new <.hlist $sed -n 's|\(.*/\)\(.*\)|s= \2= \1\2=|p' >.hsed <.deptmp $sed -n 's|c:#include "\(.*\)".*$|o: \1|p' | \ $sed 's|^[^;]*/||' | \ $sed -f .hsed >> Makefile.new <.deptmp $sed -n 's|c:#include <\(.*\)>.*$|o: /usr/include/\1|p' \ >> Makefile.new <.deptmp $sed -n 's|h:#include "\(.*\)".*$|h: \1|p' | \ $sed -f .hsed >> Makefile.new
  80. • 我々にはperl5があるのでワンライナーで削除するぞ!!! $perl -ni -e 
 'print unless /(built-in)|(command line)/'

    Makefile
  81. YACC • YACCで何も記述されていないstabvalがエラーを起こす %type <ival> prog decl format %type <stabval>

    %type <cmdval> block lineseq line loop cond sideff nexpr else
  82. YACC • コメントアウトや!!!!!! %type <ival> prog decl format /*%type <stabval>*/

    %type <cmdval> block lineseq line loop cond sideff nexpr else
  83. YACC • sprintfはcharのポインタかintか分けている… • 現在はint型 • そもそもsprintfがある
 ヘッダーファイルをincludeしているのでいらない #ifdef CHARSPRINTF

    char *sprintf(); #else int sprintf(); #endif
  84. YACC • sprintfはcharのポインタかintか分けている… • 現在はint型 • そもそもsprintfがある
 ヘッダーファイルをincludeしているのでいらない undef;

  85. C • UIDTYPEが無い…? そんな…? ./perl.h:235:1: error: unknown type name 'UIDTYPE'

    UIDTYPE getuid(); ^ ./perl.h:236:1: error: unknown type name 'UIDTYPE' UIDTYPE geteuid(); ^ ./perl.h:237:1: error: unknown type name 'GIDTYPE' GIDTYPE getgid(); ^ ./perl.h:238:1: error: unknown type name 'GIDTYPE' GIDTYPE getegid();
  86. C • 型変わっとるやんけ!!!!!!! NAME geteuid, getuid -- get user identification

    SYNOPSIS #include <unistd.h> uid_t geteuid(void); uid_t getuid(void);
  87. C • uid_tにすべての型を修正する uid_t getuid(); uid_t geteuid(); uid_t getgid(); uid_t

    getegid();
  88. C • 型のコンフリクトなどが生じる In file included from arg.c:10: ./perl.h:275:14: error:

    conflicting types for 'times' long time(), times(); ^
  89. C • timesだけlong型にすることでfix long times();

  90. C • エラーが増えてつらい arg.c:934:43: error: incomplete definition of type 'struct

    tms' apush(ary,str_nmake(((double)timesbuf.tms_utime)/HZ)); ~~~~~~~~^ ./perl.h:226:12: note: forward declaration of 'struct tms' EXT struct tms timesbuf; ^ arg.c:935:43: error: incomplete definition of type 'struct tms' apush(ary,str_nmake(((double)timesbuf.tms_stime)/HZ)); ~~~~~~~~^ ./perl.h:226:12: note: forward declaration of 'struct tms' EXT struct tms timesbuf; ^ arg.c:936:43: error: incomplete definition of type 'struct tms' apush(ary,str_nmake(((double)timesbuf.tms_cutime)/HZ));
  91. C • morecoerがstaticで定義されてないなどとでる malloc.c:155:1: error: static declaration of 'morecore' follows

    non-static declaration malloc.c:126:5: note: previous implicit declaration is here morecore(bucket); ^ malloc.c:164:5: error: non-void function 'morecore' should return a value [- Wreturn-type] return; ^ malloc.c:181:5: error: non-void function 'morecore' should return a value [- Wreturn-type] return; ^
  92. C • 魔法のことばをいれてあげる!
 (Gccでよしなにやると自動で入るがclangだと入らない) static morecore(register); static findbucket(union overhead*, int);

  93. Mojave Perl殺す気に なってきたのでは…?

  94. •gccだと大体このあたり の修正でビルドできます
 (ためそう!!!)

  95. Perl4.0 • 関数名がincludeしているCのライブラリと衝突する問題が発生 • 我々にはPerl5があるのでワンライナーで置換する

  96. Perl5.0 • レガシーPerlビルド史上最強の難敵 •

  97. • 現在のPerl6はRakudoが主流 • RakudoはVM+NQP(NotQuitPerl)+Perl6(NQP製)の三段構成 • 主流のVMはCで書かれているMoarVM
 JVMなどでも動くが機能は先にMoarに追加される • レガシーPerl6は恐らくPugsとParrotなど

  98. • Perl6は幾つかの例題ではPerl5より早く動くようになってきた • Perl6を使ってみた系の論文も発表されてきている • 実装はドキュメントを,仕様はRoastを読む
 (仕様がドキュメントベースの時もあったがすでに古い)

  99. Perl6 $POpHVSFQM NBLF NBLFJOTUBMM MoarVM/
 NQP/
 Rakudo

  100. NQP $POpHVSFQM NPBS NQP +7. ͲͷVMΛར༻͢Δ͔ ΛΦϓγϣϯͱͯ͠ ઃఆ͢Δ

  101. Perl6 .PBS#ZUF$PEF /21 NQP NBLF NPBS ༧ΊόΠτίʔυԽ ͞ΕͨNQP ΠϯλϓϦλΛ MoarVMͷόΠφϦ

    ʹΘͨ͢
  102. Perl6 .PBS#ZUF$PEF /21 NQP NBLF NPBS  aORQ NQPΠϯλϓϦλΛ هड़͍ͯ͠ΔNQPͷ

    ιʔείʔυΛೖྗͱ ͯ͠༩͑Δ
  103. NQP .PBS#ZUF$PEF /21 NQP NBLF NPBS  aORQ ORQ
 TUBHF

  104. NQP NQP NBLF NPBS  aORQ ORQ
 TUBHF ORQ
 TUBHF

    ͜Ε͕͍ΘΏΔnqp
  105. Rakudo Rakudo $POpHVSFQM ORQ
 TUBHF NPBS

  106. Rakudo Rakudo ORQ
 TUBHF NPBS  aORQ  aQN

  107. Rakudo Rakudo ORQ
 TUBHF NPBS  aORQ  aQN QFSM

  108. • 生成されたnqp, perl6ともに正体はバイトコードをmoarに
 ライブラリパスなどを設定して,
 moarを実行するシェルスクリプト

  109. • 様々な環境でぜひビルドしてみましょう!!