<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Farseerfc的小窩 - pacman</title><link href="//farseerfc.me/" rel="alternate"></link><link href="//farseerfc.me/feeds/tag-pacman.atom.xml" rel="self"></link><id>//farseerfc.me/</id><updated>2016-07-31T03:52:00+09:00</updated><entry><title>PacVis: 可視化 pacman 本地數據庫</title><link href="//farseerfc.me/pacvis.html" rel="alternate"></link><published>2016-07-31T03:52:00+09:00</published><updated>2016-07-31T03:52:00+09:00</updated><author><name>farseerfc</name></author><id>tag:farseerfc.me,2016-07-31:/pacvis.html</id><summary type="html">
&lt;div class="panel panel-default"&gt;
&lt;div class="panel-heading"&gt;
PacVis&lt;/div&gt;
&lt;div class="panel-body"&gt;
&lt;img alt="Demo of PacVis" class="img-responsive" src="//farseerfc.me/images/pacvis-first.png"/&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="pacvis"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id11"&gt;我爲什麼要做 PacVis&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;我喜歡 Arch Linux ，大概是因爲唯有 Arch Linux 能給我對整個系統「瞭如指掌」的感覺。
在 Arch Linux 裏我能清楚地知道我安裝的每一個包，能知道系統裏任何一個文件是來自哪個包，
以及我爲什麼要裝它。或許對 Debian/Fedora/openSUSE 足夠熟悉了之後也能做到這兩點，
不過他們的細緻打包的結果通常是包的數量比 Arch 要多個 3 到 10 倍，並且打包的細節也比 Arch
Linux 簡單的 PKGBUILD 要複雜一個數量級。&lt;/p&gt;
&lt;p&gt;每一個裝過 Arch Linux 的人大概都知道，裝了 Arch Linux 之後得到的系統非常樸素，按照
ArchWiki 上的流程一路走下來的話，最關鍵的一條命令就是 &lt;code class="code"&gt;
pacstrap /​mnt …&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;</summary><content type="html">
&lt;div class="panel panel-default"&gt;
&lt;div class="panel-heading"&gt;
PacVis&lt;/div&gt;
&lt;div class="panel-body"&gt;
&lt;img alt="Demo of PacVis" class="img-responsive" src="//farseerfc.me/images/pacvis-first.png"/&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="pacvis"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id11"&gt;我爲什麼要做 PacVis&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;我喜歡 Arch Linux ，大概是因爲唯有 Arch Linux 能給我對整個系統「瞭如指掌」的感覺。
在 Arch Linux 裏我能清楚地知道我安裝的每一個包，能知道系統裏任何一個文件是來自哪個包，
以及我爲什麼要裝它。或許對 Debian/Fedora/openSUSE 足夠熟悉了之後也能做到這兩點，
不過他們的細緻打包的結果通常是包的數量比 Arch 要多個 3 到 10 倍，並且打包的細節也比 Arch
Linux 簡單的 PKGBUILD 要複雜一個數量級。&lt;/p&gt;
&lt;p&gt;每一個裝過 Arch Linux 的人大概都知道，裝了 Arch Linux 之後得到的系統非常樸素，按照
ArchWiki 上的流程一路走下來的話，最關鍵的一條命令就是 &lt;code class="code"&gt;
pacstrap /​mnt base&lt;/code&gt;
 ，
它在 &lt;code class="code"&gt;
/​mnt&lt;/code&gt;
 裏作爲根調用 &lt;code class="code"&gt;
pacman -S base&lt;/code&gt;
 裝上了整個 base 組，
然後就沒有然後了。這個系統一開始空無一物，你需要的任何東西都是後來一點點用
&lt;code class="code"&gt;
pacman&lt;/code&gt;
 手動裝出來的，沒有累贅，按你所需。&lt;/p&gt;
&lt;p&gt;然而時間長了，系統中難免會有一些包，是你裝過用過然後忘記了，
然後這些包就堆在系統的角落裏，就像家裏陳年的老傢俱，佔着地，落着灰。雖然
&lt;code class="code"&gt;
pacman -Qtd&lt;/code&gt;
 能方便地幫你找出所有
&lt;strong&gt;曾經作爲依賴被裝進來，而現在不被任何包依賴&lt;/strong&gt; 的包，但是對於那些你手動指定的包，
它就無能爲力了。&lt;/p&gt;
&lt;p&gt;於是我就一直在找一個工具能幫我梳理系統中包的關係，方便我：&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;找出那些曾經用過而現在不需要的包&lt;/li&gt;
&lt;li&gt;找出那些體積大而且佔地方的包&lt;/li&gt;
&lt;li&gt;釐清系統中安裝了的包之間的關係&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="figure"&gt;
&lt;img alt="Android System Architecture" class="img-responsive" src="//farseerfc.me/images/Android-System-Architecture.jpg"/&gt;
&lt;p class="caption"&gt;&lt;a class="reference external" href="https://en.wikipedia.org/wiki/Android_(operating_system)"&gt;Android 系統架構&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;關於最後一點「釐清包的關係」，我曾經看到過
&lt;a class="reference external" href="https://en.wikipedia.org/wiki/Architecture_of_OS_X"&gt;macOS 系統架構圖&lt;/a&gt;
和 Android 的系統架構圖，對其中的層次化架構印象深刻，之後就一直在想，是否能畫出現代
Linux 桌面系統上類似的架構圖呢？又或者 Linux 桌面系統是否會展現完全不同的樣貌？
從維基百科或者別的渠道能找到 Linux 內核、或者 Linux 圖形棧，
或者某個桌面環境的架構，但是沒有找到覆蓋一整個發行版的樣貌的。
於是我便想，能不能從包的依賴關係中自動生成這樣一張圖呢。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="id1"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id12"&gt;PacVis的老前輩們&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;在開始寫 PacVis 之前，我試過一些類似的工具，他們都或多或少能解決一部分我的需要，
又在某些方面有所不足。這些工具成爲了 PacVis 的雛形，啓發了 PacVis
應該做成什麼樣子。&lt;/p&gt;
&lt;div class="section" id="pactree"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id13"&gt;pactree&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;pactree 曾經是一個
&lt;a class="reference external" href="https://bbs.archlinux.org/viewtopic.php?id=51795"&gt;獨立的項目&lt;/a&gt; ，現在則是
&lt;a class="reference external" href="https://www.archlinux.org/pacman/pactree.8.html"&gt;pacman 的一部分&lt;/a&gt; 了。
從手冊頁可以看出， pactree 的輸出是由某個包開始的依賴樹。
加上 &lt;code class="code"&gt;
--graph&lt;/code&gt;
 參數之後 pactree 還能輸出
&lt;a class="reference external" href="http://www.graphviz.org/"&gt;dot&lt;/a&gt; 格式的矢量圖描述，然後可以用 dot 畫出依賴圖：&lt;/p&gt;
&lt;div class="panel panel-default"&gt;
&lt;div class="panel-heading"&gt;
&lt;code class="code"&gt;
pactree pacvis-git -d3 --graph | dot -Tpng &amp;gt;pacvis-pactree.png&lt;/code&gt;
&lt;/div&gt;
&lt;div class="panel-body"&gt;
&lt;img alt="pactree --graph" class="img-responsive" src="//farseerfc.me/images/pacvis-pactree.png"/&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="code-line"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt; pactree pacvis-git -d3&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;pacvis-git&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;├─python-tornado&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;│ └─python&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;│   ├─expat&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;│   ├─bzip2&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;│   ├─gdbm&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;│   ├─openssl&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;│   ├─libffi&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;│   └─zlib&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;├─pyalpm&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;│ ├─python&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;│ └─pacman&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;│   ├─bash&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;│   ├─glibc&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;│   ├─libarchive&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;│   ├─curl&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;│   ├─gpgme&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;│   ├─pacman-mirrorlist&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;│   └─archlinux-keyring&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;└─python-setuptools&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;  └─python-packaging&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;    ├─python-pyparsing&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;    └─python-six&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="gp"&gt; $&lt;/span&gt; pactree pacvis-git -d3 --graph &lt;span class="p"&gt;|&lt;/span&gt; dot -Tpng &amp;gt;pacvis-pactree.png&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;從畫出的圖可以看出，因爲有共用的依賴，所以從一個包開始的依賴關係已經不再是一棵
&lt;a class="reference external" href="https://zh.wikipedia.org/wiki/%E6%A8%B9%E7%8B%80%E7%B5%90%E6%A7%8B"&gt;圖論意義上的樹(Tree)&lt;/a&gt;
了。最初嘗試做 PacVis 的早期實現的時候，就是試圖用 bash/python 腳本解析 pactree 和
pacman 的輸出，在 pactree 的基礎上把整個系統中所有安裝的包全都包含到一張圖裏。
當然後來畫出的結果並不那麼理想，首先由於圖非常巨大，導致 dot
的自動佈局要耗費數小時，最後畫出的圖也過於巨大基本上沒法看。&lt;/p&gt;
&lt;p&gt;然而不得不說沒有 pactree 就不會有 PacVis ，甚至 pacman 被分離出 alpm
庫也和 pactree 用 C 重寫的過程有很大關係，而 PacVis 用來查詢 pacman 數據庫的庫
pyalpm 正是 alpm 的 Python 綁定。因爲 pactree 的需要而增加出的 alpm 庫奠定了 PacVis
實現的基石。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="pacgraph"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id14"&gt;pacgraph&lt;/a&gt;&lt;/h3&gt;
&lt;div class="panel panel-default"&gt;
&lt;div class="panel-heading"&gt;
pacgraph 的輸出&lt;/div&gt;
&lt;div class="panel-body"&gt;
&lt;img alt="pacgraph" class="img-responsive" src="//farseerfc.me/images/pacvis-pacgraph.png"/&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a class="reference external" href="http://kmkeen.com/pacgraph/index.html"&gt;pacgraph&lt;/a&gt; 是一位 Arch Linux 的
Trusted User &lt;a class="reference external" href="http://kmkeen.com/"&gt;keenerd&lt;/a&gt; 寫的程序，和
PacVis 一樣也是用 Python 實現的。
比起 pactree ， pacgraph 明顯更接近我的需求，它默認繪製整個系統的所有安裝包，
並且用聰明的佈局算法解決了 dot 佈局的性能問題。&lt;/p&gt;
&lt;p&gt;pacgraph 的輸出是一個富有藝術感的依賴圖，圖中用不同的字體大小表示出了每個包佔用
的磁盤空間。通過觀察 pacgraph 的輸出，我們可以清楚地把握系統全局的樣貌，
比如一眼看出這是個桌面系統還是個服務器系統，並且可以很容易地發現那些佔用磁盤空間
巨大的包，考慮清理這些包以節約空間。&lt;/p&gt;
&lt;p&gt;更棒的是 pacgraph 還提供了一個交互性的 GUI 叫做 pacgraph-tk ，顯然通過 tk 實現。
用這個 GUI 可以縮放觀察整幅圖的細節，或者選中某個包觀察它和別的包的依賴關係。&lt;/p&gt;
&lt;p&gt;pacgraph 還支持通過參數指定只繪製個別包的依賴關係，就像 pactree 那樣。&lt;/p&gt;
&lt;p&gt;不過 pacgraph 也不是完全滿足我的需要。如我前面說過，我希望繪製出的圖能反應
&lt;strong&gt;這個發行版的架構面貌&lt;/strong&gt; ，而 pacgraph 似乎並不區別「該包依賴的包」和「依賴該包的包」
這兩種截然相反的依賴關係。換句話說 pacgraph 畫出的是一張無向圖，
而我更想要一張有向圖，或者說是 &lt;strong&gt;有層次結構的依賴關係圖&lt;/strong&gt; 。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="id4"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id15"&gt;於是就有了 PacVis&lt;/a&gt;&lt;/h2&gt;
&lt;div class="panel panel-default"&gt;
&lt;div class="panel-heading"&gt;
PacVis 剛打開的樣子&lt;/div&gt;
&lt;div class="panel-body"&gt;
&lt;img alt="PacVis on startup" class="img-responsive" src="//farseerfc.me/images/pacvis-second.png"/&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;總結了老前輩們的優勢與不足，我便開始利用空餘時間做我心目中的 PacVis 。
前後斷斷續續寫了兩個月，又分爲兩個階段，第一階段做了基本的功能和雛形，
第二階段套用上 &lt;a class="reference external" href="https://getmdl.io/"&gt;https://getmdl.io/&lt;/a&gt; 的模板，總算有了能拿得出手給別人看的樣子。&lt;/p&gt;
&lt;p&gt;於是乎前兩天在 AUR 上給 pacvis 打了個
&lt;a class="reference external" href="https://aur.archlinux.org/packages/pacvis-git/"&gt;pacvis-git&lt;/a&gt;
包，現在想在本地跑 pacvis 應該很方便了，用任何你熟悉的 aurhelper
就可以安裝，也可以直接從 aur 下載 PKGBUILD 打包：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="code-line"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="go"&gt;~$ git clone aur@aur.archlinux.org:pacvis-git.git&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;~$ cd pacvis-git&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;~/pacvis-git$ makepkg -si&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;~/pacvis-git$ pacvis&lt;/span&gt;&lt;/span&gt;
&lt;span class="code-line"&gt;&lt;span class="go"&gt;Start PacVis at http://localhost:8888/&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;按照提示說的，接下來打開瀏覽器訪問 &lt;a class="reference external" href="http://localhost:8888/"&gt;http://localhost:8888/&lt;/a&gt; 就能看到 PacVis
的樣子了。僅僅作爲嘗試也可以直接打開跑在我的服務器上的 demo:
&lt;a class="reference external" href="https://pacvis.farseerfc.me/"&gt;https://pacvis.farseerfc.me/&lt;/a&gt; ，這個作爲最小安裝的服務器載入速度大概比普通的桌面系統快一點。&lt;/p&gt;
&lt;div class="panel panel-default"&gt;
&lt;div class="panel-heading"&gt;
在 Windows msys2 跑 PacVis&lt;/div&gt;
&lt;div class="panel-body"&gt;
&lt;img alt="PacVis on Windows msys2" class="img-responsive" src="//farseerfc.me/images/pacvis-msys2.png"/&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;另外補充一下，因爲 PacVis 只依賴 pyalpm 和 tornado ，所以在別的基於 pacman
的系統上跑它應該也沒有任何問題，包括
&lt;a class="reference external" href="https://msys2.github.io/"&gt;Windows 上的 msys2&lt;/a&gt; 裏（儘管在 msys2 上編譯
tornado 的包可能要花些功夫）。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="id5"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id16"&gt;PacVis 的圖例和用法&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;操作上 PacVis 仿照地圖程序比如 Google Maps 的用法，可以用滾輪或者觸摸屏的手勢
縮放、拖拽，右上角有個側邊欄，不需要的話可以點叉隱藏掉，右下角有縮放的按鈕和
回到全局視圖的按鈕，用起來應該還算直觀。&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="PacVis showing pacvis-git" class="img-responsive" src="//farseerfc.me/images/pacvis-pacvis-git.png"/&gt;
&lt;p class="caption"&gt;pacvis-git 包的依賴&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;先解釋圖形本身，整張圖由很多小圓圈的節點，以及節點之間的箭頭組成。
一個圓圈就代表一個軟件包，而一條箭頭代表一個依賴關係。縮放到細節的話，
能看到每個小圓圈的下方標註了這個軟件包的名字，鼠標懸浮在圓圈上也會顯示相應信息。
還可以點開軟件包，在右側的邊欄裏會有更詳細的信息。&lt;/p&gt;
&lt;p&gt;比如圖例中顯示了 pacvis-git 自己的依賴，它依賴 pyalpm, python-tornado 和
python-setuptools ，其中 pyalpm 又依賴 pacman 。圖中用
&lt;span class="label label-primary"&gt;紫色&lt;/span&gt; 表示手動安裝的包，
&lt;span class="label label-warning"&gt;橙色&lt;/span&gt; 表示被作爲依賴安裝的包，
箭頭的顏色也隨着包的顏色改變。&lt;/p&gt;
&lt;p&gt;值得注意的是圖中大多數箭頭都是由下往上指的，這是因爲 PacVis 按照包的依賴關係做
了拓撲排序，並且給每個包賦予了一個拓撲層級。比如 pacvis-git 位於 39
層，那麼它依賴的 pyalpm 就位於 38 層，而 pyalpm 依賴的 pacman 就位於 37
層。根據層級關係排列包是 PacVis 於 pacgraph 之間最大的不同之處。&lt;/p&gt;
&lt;p&gt;除了手動縮放， PacVis 還提供了搜索框，根據包名快速定位你感興趣的包。
以及在右側邊欄中的 Dep 和 Req-By 等頁中，包的依賴關係也是做成了按鈕的形式，
可以由此探索包和包之間的關聯。&lt;/p&gt;
&lt;p&gt;最後稍微解釋一下兩個和實現相關的參數：&lt;/p&gt;
&lt;div class="label label-info"&gt;
Max Level&lt;/div&gt;
&lt;p&gt;這是限制 PacVis 載入的最大拓撲層。系統包非常多的時候 PacVis
的佈局算法會顯得很慢，限制層數有助於加快載入，特別是在調試 PacVis 的時候比較有用。&lt;/p&gt;
&lt;div class="label label-info"&gt;
Max Required-By&lt;/div&gt;
&lt;p&gt;這是限制 PacVis 繪製的最大被依賴關係。稍微把玩一下 PacVis 就會發現系統內絕大多數
的包都直接依賴了 glibc 或者 gcc-libs 等個別的幾個包，而要繪製這些依賴的話會導致
渲染出的圖中有大量長直的依賴線，不便觀察。於是可以通過限制這個值，使得 PacVis
不繪製被依賴太多的包的依賴關係，有助於讓渲染出的圖更易觀察。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="id6"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id17"&gt;從 PacVis 能瞭解到的一些事實&lt;/a&gt;&lt;/h2&gt;
&lt;div class="panel panel-default"&gt;
&lt;div class="panel-heading"&gt;
一個 KDE 桌面的 PacVis 結果全圖， &lt;a class="reference external" href="//farseerfc.me/images/pacvis-16384.png"&gt;放大（17M）&lt;/a&gt;&lt;/div&gt;
&lt;div class="panel-body"&gt;
&lt;img alt="A normal KDE desktop in PacVis" class="img-responsive" src="//farseerfc.me/images/pacvis-4096-anno.png"/&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;稍微玩一下 PacVis 就能發現不少有趣現象，上述「絕大多數包依賴 glibc 」就是一例。
除此之外還有不少值得玩味的地方。&lt;/p&gt;
&lt;div class="section" id="id7"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id18"&gt;依賴層次&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;系統中安裝的包被明顯地分成了這樣幾個層次：&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;glibc 等 C 庫&lt;/li&gt;
&lt;li&gt;Bash/Perl/Python 等腳本語言&lt;/li&gt;
&lt;li&gt;coreutils/gcc/binutils 等核心工具&lt;/li&gt;
&lt;li&gt;pacman / systemd 等較大的系統工具&lt;/li&gt;
&lt;li&gt;gtk{2,3}/qt{4,5} 等 GUI toolkit&lt;/li&gt;
&lt;li&gt;chromium 等 GUI 應用&lt;/li&gt;
&lt;li&gt;Plasma/Gnome 等桌面環境&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;大體上符合直觀的感受，不過細節上有很多有意思的地方，比如 zsh 因爲 gdbm
間接依賴了 bash，這也說明我們不可能在系統中用 zsh 完全替代掉 bash。
再比如 python （在 Arch Linux 中是 python3）和 python2 和 pypy
幾乎在同一個拓撲層級。&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="zsh depends on bash because of gdbm" class="img-responsive" src="//farseerfc.me/images/pacvis-zsh-bash.png" style="width: 45%;"/&gt;
&lt;p class="caption"&gt;zsh 因爲 gdbm 間接依賴了 bash&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;不過偶爾顯示的依賴層級不太符合直觀，比如 qt5-base &amp;lt; qt4 &amp;lt; gtk2 &amp;lt; gtk3 。
qt5 因爲被拆成了數個包所以比 qt4 更低級這可以理解，而 gtk 系比 qt
系更高級這一點是很多人（包括我）沒有預料到的吧。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="id8"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id19"&gt;循環依賴&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;有些包的依賴關係形成了循環依賴，一個例子是 freetype2 和 harfbuzz，freetype2
是繪製字體的庫，harfbuzz 是解析 OpenType 字形的庫，兩者對對方互相依賴。
另一個例子是 KDE 的 kio 和 kinit，前者提供類似 FUSE 的資源訪問抽象層，
後者初始化 KDE 桌面環境。&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="freetype2 harfbuzz" class="img-responsive" src="//farseerfc.me/images/pacvis-freetype2-harfbuzz.png" style="width: 45%;"/&gt;
&lt;p class="caption"&gt;freetype2 和 harfbuzz 之間的循環依賴&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;因爲這些循環依賴的存在，使得 PacVis 在實現時不能直接拓撲排序，我採用環探測
算法找出有向圖中所有的環，並且打破這些環，然後再使用拓撲排序。
因此我在圖中用紅色的箭頭表示這些會導致環的依賴關係。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="id9"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id20"&gt;有些包沒有依賴關係&lt;/a&gt;&lt;/h3&gt;
&lt;div class="figure"&gt;
&lt;img alt="PacVis Level 0" class="img-responsive" src="//farseerfc.me/images/pacvis-level0.png" style="width: 45%;"/&gt;
&lt;p class="caption"&gt;man-pages 和 licenses 沒有依賴關係&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;有些包既不被別的包依賴，也不依賴別的包，而是孤立在整張圖中，比如
man-pages 和 licenses 。這些包在圖中位於最頂端，拓撲層級是 0 ，我用
&lt;span class="label label-info"&gt;藍色&lt;/span&gt; 正方形特別繪製它們。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="linux"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id21"&gt;只看依賴關係的話 Linux 內核完全不重要&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;所有用戶空間的程序都依賴着 glibc ，而 glibc 則從定義良好的 syscall 調用內核。
因此理所當然地，如果只看用戶空間的話， glibc 和別的 GNU 組件是整個 GNU/Linux
發行版的中心，而 Linux 則是位於依賴層次中很深的位置，甚至在我的 demo 服務器上
Linux 位於整個圖中的最底端，因爲它的安裝腳本依賴 mkinitcpio
而後者依賴了系統中的衆多組件。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="pacman-qtd"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id22"&gt;pacman -Qtd 不能找到帶有循環依賴的孤兒包&lt;/a&gt;&lt;/h3&gt;
&lt;div class="figure"&gt;
&lt;img alt="pacman -Qtd cannot find packages with circle dependency" class="img-responsive" src="//farseerfc.me/images/pacvis-circledeps-Qtd.png" style="width: 45%;"/&gt;
&lt;p class="caption"&gt;msys2 中帶有循環依賴的孤兒包&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;這是我在 msys2 上測試 PacVis 的時候發現的，我看到在渲染的圖中有一片羣島，
沒有連上任何手動安裝的包。這種情況很不正常，因爲我一直在我的所有系統中跑
&lt;code class="code"&gt;
pacman -Qtd&lt;/code&gt;
 找出孤兒包並刪掉他們。放大之後我發現這些包中有一條循環依賴，
這說明 &lt;code class="code"&gt;
pacman -Qtd&lt;/code&gt;
 不能像語言的垃圾回收機制那樣找出有循環依賴的孤兒包。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="id10"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id23"&gt;PacVis 的未來&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;目前的 PacVis 基本上是我最初開始做的時候設想的樣子，隨着開發逐漸又增加了不少功能。
一些是迫於佈局算法的性能而增加的（比如限制層數）。&lt;/p&gt;
&lt;p&gt;今後準備再加入以下這些特性：&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;更合理的 optdeps 處理。目前只是把 optdeps 關係在圖上畫出來了。&lt;/li&gt;
&lt;li&gt;更合理的 &lt;strong&gt;依賴關係抉擇&lt;/strong&gt; 。有時候包的依賴關係並不是直接根據包名，而是
&lt;code class="code"&gt;
provides&lt;/code&gt;
 由一個包提供另一個包的依賴。目前 PacVis 用 alpm
提供的方式抉擇這種依賴，於是這種關係並沒有記錄在圖上。&lt;/li&gt;
&lt;li&gt;目前的層級關係沒有考慮包所在的倉庫 (core/extra/community/...) 或者包所屬的組。
加入這些關係能更清晰地表達依賴層次。&lt;/li&gt;
&lt;li&gt;目前沒有辦法只顯示一部分包的關係。以後準備加入像 pactree/pacgraph 一樣顯示部分包。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果你希望 PacVis 出現某些有趣的用法和功能，也
&lt;a class="reference external" href="https://github.com/farseerfc/pacvis/issues"&gt;請給我提 issue&lt;/a&gt; 。&lt;/p&gt;
&lt;/div&gt;
</content><category term="tech"></category><category term="python"></category><category term="pacvis"></category><category term="pacman"></category><category term="arch"></category><category term="linux"></category><category term="pacgraph"></category></entry></feed>