2022/02/28(月)MSYS2のセットアップメモ
投稿日:
確認環境
msys2-x86_64-20260322
セットアップ
MSYS2から落としてインストールする。
pacman -Syuu
入れとくと便利なものたち
pacman
2023以前の古いMSYS2ではpacman -sS パッケージ名を毎回入れないとインストールできないケースがあるかもしれない。
pacman -S --noconfirm unzip
pacman -S --noconfirm diffutils
pacman -S --noconfirm openssh
pacman -S --noconfirm patch
pacman -S --noconfirm perl
pacman -S --noconfirm zsh
pacman -S --noconfirm git
pacman -Sy --noconfirm openbsd-netcat
# prompt用に退避させる
mv /usr/bin/git /usr/bin/msys2_git
バイナリ追加
- jq
- MSYS2のパッケージとして入れず、chocoから入れる
- dig v9.16.50
\usr\local\binに.exeと.dllを全部入れる- Windowsサポートは9.16系までしかない
dotfileの設定
呼び出しを簡略化する
毎回こんな感じで呼ぶのは面倒なので簡略化する。
C:/env/msys64/msys2_shell.cmd -defterm -here -use-full-path -no-start -msys -shell zsh
C:/env/msys64/run_zsh.cmdのようなファイルを作り、以下の内容を書くことでC:/env/msys64/run_zsh.cmd '/c/path/to/hoge.sh'のようにしてシェルスクリプトを実行できるようになる。
@echo off
set MSYSTEM=MSYS
set MSYS2_PATH_TYPE=inherit
set CHERE_INVOKING=1
C:\env\msys64\usr\bin\zsh.exe -l %*
外部連携
呼び出しを簡略化している前提
VSCode連携
{
"terminal.integrated.defaultProfile.windows": "MSYS2",
"terminal.integrated.profiles.windows": {
"MSYS2": {
"overrideName": true,
"path": ["C:\\env\\msys64\\run_zsh.cmd"]
}
}
}
Windows Terminal連携
{
"defaultProfile": "{17da3cac-b318-431e-8a3e-7fcdefe6d114}",
"profiles": {
"defaults": {},
"list": [
{
"commandline": "C:/env/msys64/run_zsh.cmd",
"font": {
"face": "Consolas",
"size": 11
},
"guid": "{17da3cac-b318-431e-8a3e-7fcdefe6d114}",
"icon": "C:/env/msys64/mingw64.ico",
"name": "MINGW64 / MSYS2",
"colorScheme": "VSCode"
}
]
},
"schemes": [
{
"name": "VSCode",
"background": "#1e1e1e",
"foreground": "#d4d4d4",
"black": "#000000",
"blue": "#2472c8",
"brightBlack": "#666666",
"brightBlue": "#3b8eea",
"brightCyan": "#29b8db",
"brightGreen": "#23d18b",
"brightPurple": "#d670d6",
"brightRed": "#f14c4c",
"brightWhite": "#e5e5e5",
"brightYellow": "#f5f543",
"cyan": "#11a8cd",
"green": "#0dbc79",
"purple": "#bc3fbc",
"red": "#cd3131",
"white": "#e5e5e5",
"yellow": "#e5e510"
}
]
}
msys2_shell.cmdのCLI Optionsの意味合い
msys2_shell.cmdの中身を読んで机上で書いているだけなので実際そう動くのかの検証はしていない。
起動パラメーターについては、:checkparamsラベルの中のループして合致するものがあれば環境変数を立て、既知の環境変数であればmsys2_shiftCounterという変数をインクリメントして、MSYS2用のパラメーターと、ユーザーパラーメーターの教会の切り分けをする実装となっている。これはつまり後続処理でmsys2_shiftCounter個分のパラメーターを読み飛ばし、それ以降のパラメーターを処理するためにある。
-mingw32 | -mingw64 | -ucrt64 | -clang64 | -msys[2]
それぞれで実行環境が変わるが、MSYS2用アプリケーションの開発環境用設定のため、-msysで基本的に問題ない。
内部的には環境変数MSYSTEMに対して、対応する値を設定している。-msysと-msys2は等価。
-defterm | -mintty | -conemu
開くターミナルの指定。
-defterm- 標準ターミナルで開く
- Windows TerminalやVSCodeで開く場合はこれを指定する
-mintty- Minttyが起動する
-conemu- Conemuが起動する
内部的にはシェルを直に蹴るか、minttyやconemuにシェルの起動パラメーターを渡しているかの違いがある。
-here
現在の作業フォルダをカレントディレクトリとして開く。
内部的には環境変数CHERE_INVOKINGに対しenabled_from_argumentsを設定している。
MSYS2公式ではCHERE_INVOKINGには1を設定するそうだが、手元で見た限りenabled_from_argumentsを設定しても動作は変わらなかった。恐らく単純に変数値が設定されているか、そうでないかで処理が分かれていると思われる。
参考までにCHERE_INVOKINGを未設定にするとMSYS2のホーム(~)で起動した。
-where DIRECTORY
指定ディレクトリをカレントディレクトリとして開く。
内部的にはcmdでシェルを起動する前にcdしてるだけ。
-[use-]full-path
Windowsのパスを継承する。
内部的には環境変数MSYS2_PATH_TYPEにinheritを設定している。
-no-start
新窓で開かない。
内部的には指定した場合はシェルが直に起動し、指定しない場合startコマンドでシェルが起動するようになっている。
-shell SHELL
ログインシェルを指定する。
例えば-shell zshならzshがログインシェルになる。未指定の場合、bashがログインシェルになる。これはmsys2_shell.cmdでデフォルト値がbashになっているため。
参考までにmsys2_shell.cmdのset "LOGINSHELL=bash"を書き換えるとアップデート時に上書きされて消えるので、しないほうがいい。
-help | --help | -? | /?
ヘルプの表示。
内部的にはprinthelpラベルに飛んでいる。
トラブルシューティング
zsh-newuser-install: startup files exist, aborting. Use the argument -f if you want to force the function to be run again.と出る
zsh-newuser-install: startup files exist, aborting.
Use the argument -f if you want to force the function to be run again.>
と出る場合の対処方法。
msys64/usr/share/zsh/scripts/newuserというファイルを消せば出なくなる。
2022/02/13(日)TypeScriptの型推論の穴についてのメモ
投稿日:
TypeScriptをぼちぼちやってきた中で、型推論が素直に決まらないみたいな所が出てきたので書き置きとして残しておきます
具体的には何かしらの関数を通して処理を隠蔽すると上手くいかなくなるケースがあります
型が推論されないケース
検査関数的なものを通した場合に、後続処理で期待通り型が推論されなくなるケースです
その1
type HogePiyo = 'hoge' | 'piyo';
type InputProps<ValueT> = {
value: ValueT;
error: string;
};
const required = (val: string) => {
return val === '';
};
const registerHogePiyo = (value: HogePiyo) => {
console.log('register', value);
};
const input: InputProps<HogePiyo | ''> = {
value: '',
error: '',
};
if (required(input.value)) {
input.error = 'ERR';
console.error(input.error);
} else {
// ここでは input.value は 'hoge' | 'piyo' となるはずだが
// TSC は 'hoge' | 'piyo' | '' と解釈する
registerHogePiyo(input.value);
}
その 2
type HogePiyo = 'hoge' | 'piyo';
type InputProps<ValueT> = {
value: ValueT;
error: string;
hasError: boolean;
};
const required = <ValueT>(obj: InputProps<ValueT | ''>) => {
if (obj.value === '') {
return { value: '', error: '必須入力です', hasError: true };
} else {
return { value: obj.value, error: '', hasError: false };
}
};
const registerHogePiyo = (value: HogePiyo) => {
console.log('register', value);
};
const input: InputProps<HogePiyo | ''> = {
value: '',
error: '',
hasError: false,
};
const result = required(input);
if (result.hasError) {
console.error(result.error);
} else {
// ここでは input.value は 'hoge' | 'piyo' となるはずだが
// TSC は 'hoge' | 'piyo' | '' と解釈する
registerHogePiyo(result.value);
}
export {};
型を推論されるようにしたケース
オブジェクトに型判定用のプロパティを生やしasで型を明示することでクリアしています
type HogePiyo = 'hoge' | 'piyo';
type InputProps<ValueT> = {
value: ValueT;
error: string;
hasError: boolean;
};
const required = <ValueT>(obj: InputProps<ValueT | ''>) => {
if (obj.value === '') {
return { value: '', error: '必須入力です', hasError: true } as {
value: '';
error: string;
hasError: true;
};
} else {
return { value: obj.value, error: '', hasError: false } as {
value: ValueT;
error: string;
hasError: false;
};
}
};
const registerHogePiyo = (value: HogePiyo) => {
console.log('register', value);
};
const input: InputProps<HogePiyo | ''> = {
value: '',
error: '',
hasError: false,
};
const result = required(input);
if (result.hasError) {
console.error(input.error);
} else {
registerHogePiyo(result.value);
}
export {};
あとがき
- Assertion Functionsを使う方法もあると思いますが、何も考えずAssertion Functionsを書くと次のような弊害があり、積極的に採用しづらいと考えています
- 何もしていなければ基本的にバンドル後のソースコードに出てくる
- 要するにバンドルサイズが大きくなります
throwを書く必要性があり、バンドル後に残っている以上、このthrowをcatchする必要性がある- 無意味な実装工数が生まれる
- そもそも論としてAssertion Functionsを書く工数が生まれる
- Assertion Functionsの振る舞いを見ている限り、
asに限りなく近く、ぶっちゃけasで書いたほうが楽
- 何もしていなければ基本的にバンドル後のソースコードに出てくる
- 絶対に
asを使わず現実的な工数で開発するというのは、割と非現実ではないかという感触があります- 個人的に型推論はIDEが勝手にやってくれるおかげで楽ができるシステムだと考えているので、型推論の補佐をする仕組みに工数をかけるというのは本末転倒な気がしています
- 品質は大切なことですが、反面で少なくないビジネスには期限もあります
- 品質に寄せすぎた過剰に冗長なコードも、納期に寄せすぎた脆弱性不具合山盛りスパゲティコードもどちらも考えものであり、その辺のバランスが上手くとれるやり方がなんかないかなーと考えることはしばしばあります