いけむランド

はてダからやってきました

vlang を cygwin で動かす

ちょっと前にそのうちソース公開するよと言われていた The V Programming Language が GitHub から取得できるようになりました。

github.com

というわけでいつもどおり cygwin で動かしてみます。

あくまでも記事執筆時 2019/06/27 時点での情報です。vlang は事前告知もあった影響か commit がガンガンされているため、最新の環境では役に立たないかもしれないことに注意してください。


手元に持ってきたり、mac や linux で動かすまでは他の紹介記事がググったら出てくるので、それらを参考にしてください。

www.pavlog.tokyo

cygwin で動かすには最初に v.c に手を入れる必要があります。

$ pwd
/path/to/v/compiler
$ make v.c
curl -Os https://raw.githubusercontent.com/vlang/vc/master/v.c

そのままコンパイルはできるのですが、このコンパイラを使って v 言語で書かれたソースをコンパイルしようとするとできないです。

$ gcc v.c -o vc.exe
# 死ぬほど警告が出る
$ file vc.exe
vc.exe: PE32+ executable (console) x86-64, for MS Windows
$ ./vc.exe version
V 0.1.4
$ ./vc.exe -o v.exe .
cc: warning: '-x objective-c' after last input file has no effect
cc: error: unrecognized command line option '-mmacosx-version-min=10.7'
V panic: clang error

原因は v.c がデフォルトで mac での挙動を想定しているためで、mac でしか認識しないコンパイラオプションを付与するためです。
v.c には -os というターゲットを切り替えるオプションがあるのですが、現在は mac, linux, windows しか受け付けない & 結局どれを指定しても何かしらのエラーとなります。

というわけで諦めて v.c を触ります。
触るポイントは new_v という関数で、ここで os をセットしてるため、その値を -1 のような定義済みの OS を表現する値以外をセットします。

  if (string_eq(dir, tos2(".")) && string_eq(out_name, tos2("a.out"))) {
    /*if*/

    string base = string_all_after(os__getwd(), tos2("/"));

    out_name = string_trim_space(base);
  };

  Os _os = MAC; // ← ココを -1 とかに変える

  if (string_eq(target_os, tos2(""))) {
    /*if*/

#ifdef __linux__

    _os = LINUX;

#endif

ここをいじると vc.exe が (とりあえずは) 動くようになります。これで v 言語で書かれた方のコンパイラをビルドします。

$ ./vc.exe -o v.exe .
$ file ./v.exe
./v.exe: PE32+ executable (console) x86-64, for MS Windows
$ ./v.exe version
V 0.1.4
$  ./v.exe
V 0.1.4
Use Ctrl-D to exit
For now you have to use println() to print values, this will be fixed soon

>>> println('Hello!')
cc: warning: '-x objective-c' after last input file has no effect
cc: error: unrecognized command line option '-mmacosx-version-min=10.7'
V panic: clang error

同じ修正を今度は main.v に加えなければなりません。
今度はきちんと cygwin を os のリストに加える修正にします。

diff --git a/compiler/main.v b/compiler/main.v
index b09e2e8..d80c7be 100644
--- a/compiler/main.v
+++ b/compiler/main.v
@@ -29,7 +29,7 @@ fn vtmp_path() string {
 }
 
 const (
-	SupportedPlatforms = ['windows', 'mac', 'linux']
+	SupportedPlatforms = ['windows', 'mac', 'linux', 'cygwin']
 	TmpPath            = vtmp_path()
 )
 
@@ -37,6 +37,7 @@ enum Os {
 	MAC
 	LINUX
 	WINDOWS
+	CYGWIN
 }
 
 enum Pass {
@@ -735,7 +736,7 @@ fn new_v(args[]string) *V {
 		base := os.getwd().all_after('/')
 		out_name = base.trim_space()
 	}
-	mut _os := MAC
+	mut _os := CYGWIN
 	// No OS specifed? Use current system
 	if target_os == '' {
 		$if linux {
@@ -753,6 +754,7 @@ fn new_v(args[]string) *V {
 		case 'linux': _os = LINUX
 		case 'windows': _os = WINDOWS
 		case 'mac': _os = MAC
+		case 'cygwin': _os = CYGWIN
 		}
 	}
 	builtins := [
$ ./v.exe
V 0.1.4
Use Ctrl-D to exit
For now you have to use println() to print values, this will be fixed soon

>>> println('Hello!')
Hello!

これで簡単な v 言語のコードならコンパイルできると思います。

ちなみに上記の旨の PR を出してみたのですが、複雑になるからこれ以上プラットフォームを増やすのはあんまり気乗りしないという回答でした。

github.com

たしかに今の works for me 感あるコードだと対応を入れる箇所が増えて微妙というのはわかる気がします。

今後、コードが整理されていったら、対応が容易になるかもしれないので、ちょっとそこまで待つことにしてみます。