Linux From Scratch

# Linux From Scratch

Linux From Scratch をやってみる

## 参考

- [本家](https://www.linuxfromscratch.org/)
- [LFSブック日本語版](http://lfsbookja.osdn.jp/)
    - [LFS systemd版](http://lfsbookja.osdn.jp/12.0-sysdja/)
- [Linux From Scratch で自作ディストリビューションづくり](https://www.miraclelinux.com/tech-blog/r2zvo8)

## 必要なもの

- 作成する Linux とは別の開発環境用の Linux。「ホスト」と呼ばれる。
    - CPU 4コア、メモリ 8GB程度。
    - インストール時に「開発(development)」オプションを選択し、開発ツールをインストールしておく。
        - Bash
        - Binutils
        - Bison
        - Coreutils
        - Diffutils
        - Findutils
        - Gawk
        - GCC
        - Grep
        - Gzip
        - Linux Kernel
        - M4
        - Make
        - Patch
        - Perl
        - Python
        - Sed
        - Tar
        - Texinfo
        - Xz

    - バージョンチェック

        ```bash
        cat > version-check.sh << "EOF"
        #!/bin/bash
        # Simple script to list version numbers of critical development tools
        export LC_ALL=C
        bash --version | head -n1 | cut -d" " -f2-4
        MYSH=$(readlink -f /bin/sh)
        echo "/bin/sh -> $MYSH"
        echo $MYSH | grep -q bash || echo "ERROR: /bin/sh does not point to bash"
        unset MYSH
        
        echo -n "Binutils: "; ld --version | head -n1 | cut -d" " -f3-
        bison --version | head -n1
        
        if [ -h /usr/bin/yacc ]; then
          echo "/usr/bin/yacc -> `readlink -f /usr/bin/yacc`";
        elif [ -x /usr/bin/yacc ]; then
          echo yacc is `/usr/bin/yacc --version | head -n1`
        else
          echo "yacc not found"
        fi
        
        echo -n "Coreutils: "; chown --version | head -n1 | cut -d")" -f2
        diff --version | head -n1
        find --version | head -n1
        gawk --version | head -n1
        
        if [ -h /usr/bin/awk ]; then
          echo "/usr/bin/awk -> `readlink -f /usr/bin/awk`";
        elif [ -x /usr/bin/awk ]; then
          echo awk is `/usr/bin/awk --version | head -n1`
        else
          echo "awk not found"
        fi
        
        gcc --version | head -n1
        g++ --version | head -n1
        grep --version | head -n1
        gzip --version | head -n1
        cat /proc/version
        m4 --version | head -n1
        make --version | head -n1
        patch --version | head -n1
        echo Perl `perl -V:version`
        python3 --version
        sed --version | head -n1
        tar --version | head -n1
        makeinfo --version | head -n1  # texinfo version
        xz --version | head -n1
        
        echo 'int main(){}' > dummy.c && g++ -o dummy dummy.c
        if [ -x dummy ]
          then echo "g++ compilation OK";
          else echo "g++ compilation failed"; fi
        rm -f dummy.c dummy
        EOF
        ```

- 構築するLinux用のディスク：30GB 程度
    - /    : 20GB
    - /boot: 200MB
    - /swap: 2GB

## 環境

- [VirtualBox(Windows)](https://www.virtualbox.org/)
    - [一般] > [高度]
        - クリップボードの共有: 双方向
        - ドラッグ＆ドロップ: 双方向
    - [システム]
        - [マザーボード]
            - メインメモリ: 8GB
            - 起動順序: フロッピーのチェック外す
            - チップセット: ICH9
        - [プロセッサー]
            - プロセッサ: 4
    - [ディスプレイ]
        - [スクリーン]
            - ビデオメモリ: 128M
            - ディスプレイ数: 1
            - 3Dアクセラレーション有効化: チェック
    - [ストレージ]
        - コントローラSATA
            - SATA0: 50GB(ホストOS用)
            - SATA1: 30G(開発用)

- [Parallels(mac)](https://www.parallels.com/jp/)

- [Ubuntu 22.04](https://www.ubuntulinux.jp/home)
    - [download](https://www.ubuntulinux.jp/download)

## Tips

```bash
# ディスク確認(開発用の追加ディスクの確認)
lsblk

# パーティション作成の自動化
sudo umount -l /deb/sdb1
sudo swapoff /dev/sdb2

sudo parted -a opt /dev/sdb -s mklabel gpt \
  -s mkpart primary ext4 0% 28G \
  -s mkpart primary linux-swap 28G 100%

mkswap /dev/sdb2
swapon /dev/sdb2

# 解凍
tar xvf xxx.tar.xz # .tar.xz
tar xvfz xxx.tar.gz # .tar.gz | .tgz
tar xvfy xxx.tar.bz2 # .bz2 
```
 
## 構築

### ubuntu インストール

```bash
# 最新に更新
sudo apt update
sudo apt upgrade

# 必要なものインストール
sudo apt install gcc make vim git apt-file

# ubuntu softwareから
code

# ファイルからパッケージを探す
sudo apt-file update
sudo apt-file search texinfo

# シェルを変更(dash => bash)
sudo dpkg-reconfigure dash

# 開発に対して足りないもの
sudo apt install bison yacc gawk g++ m4 texinfo
```

- 自動ログイン
    - [設定] - [ユーザー] で設定できる

### ホストでの準備

- パーティション
    - sda: ホスト（ubuntu）
    - sdb: 開発領域(30GB)
        - sdb1: 28G(/)
        - sdb2:  2G(swap)

```bash
# パーティション作成とファイルシステム作成
sudo parted -a opt /dev/sdb -s mklabel gpt \
  -s mkpart primary ext4 0% 28G \
  -s mkpart primary linux-swap 28G 100%

mkswap /dev/sdb2

# ファイルシステム作成(partedで一気にやるので不要？)
# mkfs -v -t ext4 /dev/sdb1
# mkswap /dev/sdb2

# 環境変数の設定
export LFS=/mnt/lfs

# 毎回実行するのは面倒なので、起動時に設定する。
if [ -z $LFS ]; then
    echo "export LFS=/mnt/lfs" >> ~/.bash_profile
    sudo echo "export LFS=/mnt/lfs" >> /root/.bash_profile
fi

# パーティションのマウント
sudo mkdir -pv $LFS
sudo mount -v -t ext4 /dev/sdb1 $LFS
sudo swapon /dev/sdb2
# 毎回実行するのは面倒なので、起動時にマウントするには "/etc/fstab" に以下を追記
# /dev/sdb1    /mnt/lfs    ext4    defaults    1    1

# パッケージのダウンロード
sudo mkdir -v $LFS/sources
sudo chmod -v a+wt $LFS/sources

## ダウンロードリスト作成
wget https://lfsbookja.osdn.jp/11.3-sysdja/wget-list-systemd
cat > wl.sed << "EOF"
s|ftp\.gnu\.org/gnu/|ftp.riken.jp/GNU/|g
s|www\.kernel\.org/pub/linux/|ftp.riken.jp/Linux/kernel.org/linux/|g
s|www\.cpan\.org|ftp.riken.jp/lang/CPAN|g
s|ftp\.vim\.org|ftp.jp.vim.org|g
EOF
sed -f wl.sed -i.orig wget-list-systemd
rm wl.sed

wget --input-file=wget-list-systemd --continue --directory-prefix=$LFS/sources
pushd $LFS/sources
  sudo wget https://lfsbookja.osdn.jp/11.3-sysdja/md5sums
  sudo md5sum -c md5sums
popd
# 所有者をrootに統一しておく。ホスト上のユーザは開発環境には存在しないため。
chown root:root $LFS/sources/*
```

- 残作業

```bash
# 限定的なディレクトリレイアウトの作成
sudo mkdir -pv $LFS/{etc,var} $LFS/usr/{bin,lib,sbin}

for i in bin lib sbin; do
  sudo ln -sv usr/$i $LFS/$i
done

case $(uname -m) in
  x86_64) sudo mkdir -pv $LFS/lib64 ;;
esac

sudo mkdir -pv $LFS/tools

# 開発ユーザの作成
sudo groupadd lfs
sudo useradd -s /bin/bash -g lfs -m -k /dev/null lfs
sudo passwd lfs

sudo chown -v lfs $LFS/{usr{,/*},lib,var,etc,bin,sbin,tools}
case $(uname -m) in
  x86_64) sudo chown -v lfs $LFS/lib64 ;;
esac
```

- lfsユーザの設定

```bash
# lfs ユーザにスイッチ
su - lfs

cat > ~/.bash_profile << "EOF"
exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash
EOF

cat > ~/.bashrc << "EOF"
set +h
umask 022
LFS=/mnt/lfs
LC_ALL=POSIX
LFS_TGT=$(uname -m)-lfs-linux-gnu
PATH=/usr/bin
if [ ! -L /bin ]; then PATH=/bin:$PATH; fi
PATH=$LFS/tools/bin:$PATH
CONFIG_SITE=$LFS/usr/share/config.site
export LFS LC_ALL LFS_TGT PATH CONFIG_SITE
EOF
```

## 一時的なツールの構築

### クロスコンパイラと関連ライブラリのビルド

- "開発するOS上で動作するプログラム" をホスト上でコンパイルするためのツールをビルド
- $LFS/tools ディレクトリにインストールされる
- ライブラリについては、実際使用する場所にインストールされる
- "lfs" ユーザで実行する

### クロスコンパイルによる一時的ツールのビルド

- 上記でビルドしたツールを使って、"開発するOS上で動作するプログラム" をクロスコンパイルする
- "lfs" ユーザで実行する

### chroot への移行と一時的ツールの追加ビルド

- rootユーザで実行する