很多時候,build 程式時最後會死在 link error,一堆 symbol 會找不到。最後追查下來,通常會發現是 project dependencies 沒有設好的緣故。由於是「找不到」而不是「用得不對」,因此我們通常得用 grep 之類的工具,從十幾萬行的程式裡,去尋找遺失的 symbol 在哪裡。當一個 dependency 忘記設時,可能遺失的 symbols 會達上百個[1],要一個一個手動尋找時,就很討厭了。

為了避免這樣的情形,也為了方便確認目前系統各 components 的關聯情形,如同原本預計的理想狀態,我寫了一個簡單的 script,叫 dsw2dot.pl,能夠 parse VC6 的 dsw 檔,然後依據內函的各 project 檔的相依情形,產生 GraphViz 的 dot 檔 script。這樣一來,我就可以用 dot 產生 png/svg/... 等各種圖形了。

這個程式的 usage 如下:

Usage: dsw2dot.pl [ <option> ... ] <dsw-file> [ <dot-file> ]

Generate graphviz digraph script <dot-file> according to project dependencies
that parsed from VC6 workspace file <dsw-file>.  If path of digraph script
<dot-file> is not given or is a single dash, will output to standard output.

Options:

  -h,--help       Show this help message.
  --rankdir <rd>  Set drawing rank direction <rd> to TB (top-to-bottom), LR
                  (left-to-right), RL (right-to-left), or BT (bottom-to-top).
                  (default: TB)
  -v,--verbose    Show verbose progress messages.

Revision: r373 (2007-05-15)

預設的方向是 top-to-bottom,但如果 components 數太多,相依性太淺的話,可以改成 left-to-right 會比較好看。

例如,分析 xmlrpc-c 目錄下的 Windows/xmlrpc.dsw 後得到的 dot 檔如下:

digraph xmlrpc {
    fontsize = 10
    bgcolor = "transparent"

    node [
        fontsize = 10
        shape = "record"
    ]

    edge [
        fontsize = 8
        arrowhead = "normal"
    ]

#   Project: abyss

#   Project: cpptest
    cpptest -> xmlrpc

#   Project: curllib

#   Project: gennmtab

#   Project: libutil_xmlrpc

#   Project: query_meerkat
    query_meerkat -> xmlrpc

#   Project: rpctest
    rpctest -> xmlrpc

#   Project: xmlparse
    xmlparse -> xmltok

#   Project: xmlrpc
    xmlrpc -> abyss
    xmlrpc -> curllib
    xmlrpc -> libutil_xmlrpc
    xmlrpc -> xmlparse

#   Project: xmlrpc_sample_add_asynch_client
    xmlrpc_sample_add_asynch_client -> xmlrpc

#   Project: xmlrpc_sample_add_server
    xmlrpc_sample_add_server -> xmlrpc

#   Project: xmlrpc_sample_add_server_w32httpsys
    xmlrpc_sample_add_server_w32httpsys -> xmlrpc

#   Project: xmlrpc_sample_add_sync_client
    xmlrpc_sample_add_sync_client -> xmlrpc

#   Project: xmlrpc_sample_auth_client
    xmlrpc_sample_auth_client -> xmlrpc

#   Project: xmltok
    xmltok -> gennmtab
}

產生的圖形如下:

理論上,perl 有 GraphViz 模組可以用,不過我還沒用上就是了。有空應該來研究一下。


  1. 一個 library 可能提供了上百個 functions,更遑論如果是用 C++ 寫,加上 function overloadding 與 template programming,量會更大。