__TOC__
Chromebrewは、ChromeOSで動作するソースビルド指向のパッケージ管理システムです。
ChromeOSは、Linuxカーネルの上にChromeウェブブラウザーを中心としてネットワーククライアント機能を提供します。
ですが、所謂GNU/Linuxのディストリビューションに観られるパッケージマネージャーを含まず、GNU/Linuxの環境を手に入れるには…
 LXCコンテナー上で、GNU/Linuxディストリビューションを実行します（設定 >  “Linux (Beta)” として知られます）
 chroot 環境で、GNU/Linuxディストリビューションを実行します（サポート終了しました）
 デベローパーモードのシェル環境に独自バイナリーをインストールします（GNU/Linuxディストリビューションとのパッケージ互換性はないです）
の３つなどがあります。
Chromebrewは、その名の通りHomebrewの影響を受けていますが、完全にRubyで記述され（Homebrewは一部 bash スクリプト）、ChoromeOS固有の事情（ユーザーが書込みも実行もできるファイルシステムは /usr/local に限られるなど）に適応しています。
Chromebrewは、仮想環境やchrootのオーバーヘッドはなく、ユーティリティーや共有ライブラリーなどChromeOSのものを使えるのでフットプリントは、この中で一番小さくなります。
Chromebrewは、BSD Unixの package source や ports collection の様にソースコードからのビルドをユーザーが気軽に行え、たとえばCコンパイラーに -march=native オプションを与えホスト環境のプロセッサーで実行可能な命令セットからコード生成をすることができるなど、資源の少ない環境にも好適です。
インストールする前に、Chromebook をデベロッパーモードにする必要があります。
Chromebook をデベロッパーモードにすると、工場出荷時の設定に戻されます。
Chromebook をデベロッパーモードにすると、工場出荷時の設定に戻されます。
大切なので二回言いました。
Chromebookを「デベロッパーモード''Developer mode'' を「開発者モード」とする資料もありますが、定訳がないので「デベロッパーモード」とカタカナ表記にしました。」にすると、Chromebookのシステムファイルを変更できるなど、完全なルートアクセスを取得できます。
デベロッパーモードには、一部のファイルを変更したり、外部USBデバイスからChromebookを起動したりするなど他の使い道もあります。
デベローパーモードへ切替える方法
ESC + 更新（F3）ボタンを押しながら、電源ボタンを押します。その後、電源ボタンを離します。
リカバリー画面が表示されます。ここで、Ctrl + Dキーを押して開発者モードをオンにします。その後、数分待ちます。
 まず、 https://chromebrew.github.io/ にアクセスして、インストール方法が変わっていないか確認してください。
 crosh を開きます。
Chrome で、ctrl+alt+T で crosh を開きます。
Welcome to crosh, the Chrome OS developer shell.
If you got here by mistake, don't panic!  Just close this tab and carry on.
Type 'help' for a list of commands.
If you want to customize the look/behavior, you can use the options page.
Load it by using the Ctrl-Shift-P keyboard shortcut.
crosh>
Chrome に新しいタブが開き、上のような表示が現れます。
crosh>  shell
[ERROR:src/main.rs:184] ERROR: unknown command: shell
と表示された場合は、デベローパーモードになっていません。デベローパーモードへの切替え手順を確認しましょうChromeOS Flex の場合、grubの設定ファイルに cros_debug を追加します。。
shellの起動。
crosh> shell
chronos@localhost / $
shell が、開きました。初期状態では bash です。
 インストールスクリプトのオンザフライ実行。
chromebrew のインストールスクリプトをファイルに落とさず、そのまま bash の標準入力に流します。
chronos@localhost / $ curl -Ls git.io/vddgY | bash
Welcome to Chromebrew!
Please enter the developer mode password
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.
Password: 
Doing initial setup for install in /usr/local.
This may take a while if there are preexisting files in /usr/local...
Downloading information for Bootstrap packages...
[1/15]: https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/musl_zstd.rb --> musl_zstd.rb
--_curl_--https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/musl_zstd.rb
[2/15]: https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/pixz.rb --> pixz.rb
--_curl_--https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/pixz.rb
                       :
                       :
                       :
                       . .
                   ..,:;;;::'..
                 .':lllllllool,.
                ...cl;..... ,::;'.
               .'oc...;::::..0KKo.
               .'od: .:::::, lolc.
             .'lNMMMO ;ooc.,XMMWx;:;.
            .dMMMMMMXkMMMMxoMMMMMMMMO.
            .:O0NMMMMMMMMMM0MMMMMN0Oc.
              .:xdloddddddoXMMMk:x:....
              .xMNOKX0OOOOxcodlcXMN0O0XKc.
              .OMXOKXOOOOOk;ol:OXMK...;N0.
              'XMKOXXOOOOOk:docOKMW,  .kW;
             .cMMKOXXOOOOOOOOOOO0MM;  .lMc.
             .cMM00XKOOOOkkkkkkOOWMl. .cMo.
             .lMWO0XKOOOkkkkkkkkONMo.  ;Wk.
             .oMNO0X0OOkkkkkkkkkOXMd..,oW0'
             .xMNO0X0OOkkkkkkkkkkXMWKXKOx;.
             .0MXOOOOOOkkkkkkkkkOKM0..
             'NMWNXXKK000000KKXNNMMX.
             .;okk0XNWWMMMMWWNKOkdc'.
                .....'cc:cc:''...
  ___ _                               _
 / (_)|\                              |\\
|     ||__    ,_    __  _  _  _    __ |/_  ,_    __  _   _   _
|     |/  |  /  |  /  \/ |/ |/ |  |_/ |  \/  |  |_/ /|   |   |\_
 \___/|   |_/   |_/\__/  |  |  |_/|__/\__/   |_/|__/  \_/ \_/
Edit /usr/local/etc/env.d/02-pager to change the default PAGER.
more is used by default
You may wish to edit the /usr/local/etc/env.d/01-editor file for an editor default.
Chromebrew provides nano, vim and emacs as default TUI editor options. 
Chromebrew installed successfully and package lists updated.
chronos@localhost / $
のようなアスキーアートとメッセージが表示されたら chromebrew のインストールは完了です。
chromebrew のインストールが終わったら、基本的な動作を確認します。
chronos@localhost / $ crew
Usage:
  crew autoremove [options]
  crew build [options] [-k|--keep]  ...
  crew const [options] [ ...]
  crew deps [options] [-t|--tree] [-b|--include-build-deps] [--exclude-buildessential]  ...
  crew download [options]  ...
  crew files [options]  ...
  crew help []
  crew install [options] [-k|--keep] [-s|--build-from-source] [-S|--recursive-build]  ...
  crew list [options] (available|installed|compatible|incompatible)
  crew postinstall [options]  ...
  crew reinstall [options] [-k|--keep] [-s|--build-from-source] [-S|--recursive-build]  ...
  crew remove [options]  ...
  crew search [options] [ ...]
  crew sysinfo [options]
  crew update [options] []
  crew upgrade [options] [-k|--keep] [-s|--build-from-source] [ ...]
  crew whatprovides [options]  ...
chronos@localhost / $ crew sysinfo
- Architecture: `x86_64` (`x86_64`)
- Kernel version: `4.14.282-19192-g19e8c55302db`
- Chromebrew version: `1.24.0`
- Chromebrew prefix: `/usr/local`
- Chromebrew libdir: `/usr/local/lib64`
- Last update in local repository: `e01f130: Edge 103.0.1264.77-1 => 104.0.1293.47-1 (#7254)`
- OS variant: `Chrome OS`
- OS version: `octopus-release/R104-14909.100.0`
- OS channel: `stable-channel`
サブコマンドとオプションの一覧が表示されます。
sysinfo サブコマンドは、OSとchromebrew自身の情報を表示します。
内容はバージョンによって異なります。
tree コマンドをインストールしてみます。
$ crew install tree
tree: Tree is a recursive directory listing command that produces a depth indented listing of files, which is colorized ala dircolors if the LS_COLORS environment variable is set and output is to tty.
http://mama.indstate.edu/users/ice/tree/
Version: 2.0.2
License: GPL-2
Performing pre-flight checks...
Precompiled binary available, downloading...
Cannot find cached archive. 😔 Will download.
[####################################################################################################################################]  51.52 KB 100%
Tree archive downloaded.
Unpacking archive using 'tar', this may take a while...
Performing pre-install...
Performing install...
Using rdfind to convert duplicate files to hard links.
Now scanning ".", found 2 files.
Now have 2 files in total.
Removed 0 files due to nonunique device and inode.
Total size is 177860 bytes or 174 KiB
Removed 2 files due to unique sizes from list. 0 files left.
Now eliminating candidates based on first bytes: removed 0 files from list. 0 files left.
Now eliminating candidates based on last bytes: removed 0 files from list. 0 files left.
Now eliminating candidates based on sha1 checksum: removed 0 files from list. 0 files left.
It seems like you have 0 files that are not unique
Totally, 0 B can be reduced.
Now making hard links.
Making 0 links.
Tree installed!
 
chronos@localhost ~ $ tree -d /usr/local/lib/crew/
/usr/local/lib/crew/
├── bin
├── lib
├── packages
└── tools
 
4 directories
chronos@localhost ~ $ 
treeはディレクトリー構造をツリー表示するコマンドで、階層構造の把握の役に立ちます。
crew install パッケージ名
の形式では、バイナリーパッケージがインストールされますが、chromebrew では同程度の手間でソースからインストールすることができます。
chronos@localhost ~ $ crew reinstall -s tree
tree: Tree is a recursive directory listing command that produces a depth indented listing of files, which is colorized ala dircolors if the LS_COLORS environment variable is set and output is to tty.
Performing pre-flight checks...
Downloading source...
Archive found in cache
Unpacking archive using 'tar', this may take a while...
Building from source, this may take a while...
gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o tree.o tree.c
gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o unix.o unix.c
gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o html.o html.c
gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o xml.o xml.c
gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o json.o json.c
gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o hash.o hash.c
gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o color.o color.c
gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o file.o file.c
gcc  -o tree tree.o unix.o html.o xml.o json.o hash.o color.o file.o
Preconfiguring package...
install -d /usr/local/tmp/crew/dest/usr/local/bin
install -d /usr/local/tmp/crew/dest/usr/local/share/man/man1
if [ -e tree ]; then \
         install tree /usr/local/tmp/crew/dest/usr/local/bin/tree; \
fi
install doc/tree.1 /usr/local/tmp/crew/dest/usr/local/share/man/man1/tree.1
Rename all *.la_tmp files back to *.la
Checking for FHS3 compliance...
Checking for conflicts with files from installed packages...
Stripping libraries...
Stripping binaries...
Running patchelf
Running patchelf to patch binaries for library paths
Using rdfind to convert duplicate files to hard links.
Now scanning ".", found 4 files.
Now have 4 files in total.
Removed 0 files due to nonunique device and inode.
Total size is 95387 bytes or 93 KiB
Removed 4 files due to unique sizes from list. 0 files left.
Now eliminating candidates based on first bytes: removed 0 files from list. 0 files left.
Now eliminating candidates based on last bytes: removed 0 files from list. 0 files left.
Now eliminating candidates based on sha1 checksum: removed 0 files from list. 0 files left.
It seems like you have 0 files that are not unique
Totally, 0 B can be reduced.
Now making hard links.
Making 0 links.
Removing since upgrade or reinstall...
Tree removed!
Performing pre-install...
Performing install...
Using rdfind to convert duplicate files to hard links.
Now scanning ".", found 2 files.
Now have 2 files in total.
Removed 0 files due to nonunique device and inode.
Total size is 95236 bytes or 93 KiB
Removed 2 files due to unique sizes from list. 0 files left.
Now eliminating candidates based on first bytes: removed 0 files from list. 0 files left.
Now eliminating candidates based on last bytes: removed 0 files from list. 0 files left.
Now eliminating candidates based on sha1 checksum: removed 0 files from list. 0 files left.
It seems like you have 0 files that are not unique
Totally, 0 B can be reduced.
Now making hard links.
Making 0 links.
Tree installed!
chronos@localhost ~ $ 
また、 -s オプションがついていることが違います。これが「ソースからビルドしてインストールする」指示で、依存パッケージのインストールやソースコードの取得を（必要であれば）確認を求めつつ実行します。
短所:ネットワークから取得し展開するだけのバイナリーパッケージより、コンパイルなどが必要な分、メモリー・ストレージ・時間などの資源の使用が多い。
長所
バイナリーパッケージが作られた時より新しいコンパイラでコンパイルされるので、生成されるコードの質が高い。
コンパイル条件を変えることで、LTOやPGOを使ったり、ターゲットCPUの命令セットに最適化することなどができます。
crewを更新すると自分で行った /usr/local/lib/crew 以下の変更が書き戻されるので、変更を行っている場合は、事前にバックアップを取りv git diff の差分を保存するようにしてください。
crew 自身のアップデート:
chronos@localhost ~ $ crew update
crewを更新します。
これはcrew本体のみをアップデートします。
パッケージのアップデート:
chronos@localhost ~ $ crew upgrade
パッケージのアップデートを行います。
パッケージが省略された場合、全てのパッケージが更新されます。 そうでなければ、特定のパッケージが更新されます。
-s または --build-from-source を指定すると、パッケージはバイナリでアップグレードされるのではなく、コンパイルされます。
-v または --verbose を指定すると、より多くの情報が表示されます。
crew のパッケージのレシピは、/usr/local/lib/crew/packages/ にある1つのrubyスクリプトです。
Crystal言語のパッケージが crew になかったので作ってみました。
/usr/local/lib/crew/packages/crystal.rb:
require 'package'
class Crystal < Package
  description 'Programming language Crystal official binary'
  homepage 'https://crystal-lang.org/'
  version '1.6.0-dev-cd3081f3b'
  license 'Apache License 2.0'
  compatibility 'x86_64'
  source_url 'https://github.com/crystal-lang/crystal/releases/download/1.5.0/crystal-1.5.0-1-linux-x86_64.tar.gz'
  source_sha256 '627360f0fc805202d80310007d503c7a2fc0745b1db2211537d7f54e9a994347'
  def self.build
    system 'git clone https://github.com/crystal-lang/crystal'
    Dir.chdir 'crystal' do
      system 'git checkout cd3081f3b87ef6c777255197d35e140b8249c534'
      system "sed -i 's@^@15.0 @' src/llvm/ext/llvm-versions.txt"
      system %(SHELL=sh PATH=../bin/:$PATH \
             FLAGS="--release --no-debug --progress --threads=1" \
             CRYSTAL_CACHE_DIR="#{Dir.getwd}/cache" \
             make interpreter=true verbose=true)
    end
  end
  def self.install
    Dir.chdir 'crystal' do
      system 'make', "DESTDIR=#{CREW_DEST_DIR}", 'install'
    end
  end
  def self.postinstall
    puts "\nType 'crystal' to get started.\n".lightblue
  end
end
class Package とユーティリティ関数を定義した 'package' を読み込みます。
class パッケージ名 < Packageの「パッケージ名」は、レシピファイルから拡張子を取り先頭を大文字にしたものになります。
逆に言うと、レシピファイル名にはRubyの識別子に使えない - を含めたり、数字で始めることが出ません。
このため - は _ に置換え、数字で始まる場合は pkg を前置します。
description、パッケージの説明。crew search などで参照されます。
homepage、ホームページのURL文字列。
version、バージョンを表す文字列。スクリプトの中で @version で参照できます。
license、ライセンスを表す文字列。
compatibility、対応しているアーキテクチャーを表す文字列。'aarch64' 'armv7l' 'i686' 'x86_64' または 'all'。複数の場合は , で区切ります。
Scala言語のパッケージも crew になかったので作ってみました。
/usr/local/lib/crew/packages/scala.rb:
require 'package'
class Scala < Package
  description 'The Scala 3 compiler, also known as Dotty.'
  homepage 'https://dotty.epfl.ch/'
  version '3.2.0'
  license 'Apache-2.0'
  compatibility 'all'
  source_url "https://github.com/lampepfl/dotty/releases/download/3.2.0/scala3-3.2.0.tar.gz"
  source_sha256 '194bd030808f6fc7de083bfd7c75230d719aedc20f3cb7562dc65d18b4a17278'
  depends_on 'jdk18'
  no_compile_needed
  no_patchelf
  def self.install
    system "mkdir -p #{CREW_DEST_DIR}/usr/local/share/scala/  #{CREW_DEST_DIR}/usr/local/bin/"
    system "mv bin lib #{CREW_DEST_DIR}/usr/local/share/scala/"
    %w(scala scalac scaladoc).each do | cmd |
      system "( cd #{CREW_DEST_DIR}/usr/local/bin/ && ln -s ../share/scala/bin/#{cmd} )"
    end
  end
end
自分の作ったレシピを有効にするには、/usr/local/lib/crew/packages/ にスクリプトを用意したあと
パッケージリストの更新:
$ crew update ''
を実行します。