在 Ubuntu 9.04 上安装 Kscope

Kscope 是我很喜欢的 Linux 平台上的代码查看工具,因为我不会用 Emacs,vim + ctags 又用得不熟,看看小程序还可以,看大项目就傻眼了。以前也尝试过 Source-Navigator(这个项目N年没更新,06年时候我装都装不上,08年底居然又复活了,有空了再去试试)、Eclipse、Kdevelop、CodeBlocks,总之都没有 Kscope 用着最舒服。Kscope 让我欣赏的特点主要有:

1. 它号称是代码编辑环境(source-editing environment),而不是IDE。我不用在建立 Kscope 项目时烦心地去选择项目类型、编译器、编译选项等等。编译我有 Makefile,我就是找个工具看看代码,用得着那么麻烦吗。 建立 Kscope 项目时只需要干两件事:选择项目名、项目保存地址和添加源文件。

2. 它不会在源文件目录下建立一堆乱七八糟的文件,影响市容。我记得 Eclipse、CodeBlocks 等都会把项目信息保存在源文件目录下,而 Kscope 的项目保存位置可以自己选,比如我一般都保存在 workspace/kscope 目录下面,这样对要查看的源文件目录没有任何影响。因此 Kscope 的项目和源文件基本没关系,我可以添加任何位置的源文件到某个项目中去。

3. 它不会去读非指定类型的文件。这是针对 Eclipse 来说的,每次在 Eclipse 项目中搜索时,一堆 .svn 目录中文件的结果让我感觉非常闹心,两年没用不知道现在的 Eclipse 是不是更智能点儿了,但是 Eclipse 改不了的毛病就是慢和吃内存。

4. 它支持代码查看的基本功能。其实我最常用的也就那么几个功能:语法高亮、同时打开多文件、整个项目中搜索字符串、查找函数定义位置和引用、项目文件列表+搜索。在这些条上据说 Windows 下的 SourceInsight 做得更好,但我没用过没有发言权。

简而言之,Kscope 与其它工具比就是快、简单、省心。但是时代在变革呀,转眼到了 KDE4 的时代,而 Kscope 仍然停留在 KDE3.5 上。现在的 Ubuntu 9.04 的依赖关系里,居然已经撤掉了 Kscope,在 9.04 上 sudo apt-get install kscope,会得到这样的消息:E: Couldn't find package kscope,真是让人丧气。

其实 Kscope 之所以不能安装,主要原因是它依赖于 Kate 的两个库:libkateinterfaces.so.0 和 libkateinterfaces.so.0,只需要从 KDE3.5 的 Kate 中提取出来这两个库安装到系统中后,Kscope 就可以正常运行了。Ubuntu 9.04 的依赖关系中虽然找不到 Kscope,但是 Ubuntu 的软件仓库中还有 Kscope 的包,我们可以手动下载安装。下面这个脚本的功能就是自动安装 kscope 到 Ubuntu 9.04,稍微修改一下也可以用于在其它 KDE4 桌面系统中安装 Kscope,或者解决 Kscope 无法运行的问题。您也可以从这里下载到该脚本:

#!/bin/bash
# This script helps you install Kscope on Ubuntu 9.04.
# You can also use it to fix "Kscope doesn't run in KDE4" bug.

echo "Determining machine hardware name... "
MACHINE=`uname -m`
case "$MACHINE" in
  i386 | i586 | i686)
    ARCH="i386"
    ;;
  x86_64)
    ARCH="amd64"
    ;;
  *)
    ARCH="i386"
    ;;
esac

# If Kscope is not installed, install it.
which kscope &> /dev/null
if [ $? -ne 0 ]; then
  echo "Installing kscope..."
  sudo apt-get install kscope || \
  wget http://archive.ubuntu.com/ubuntu/pool/universe/k/kscope/kscope_1.6.0-1_${ARCH}.deb && \
  sudo dpkg -i kscope_*.deb || \
  sudo apt-get -fy install || \
  echo "Oops, some error happens..."
fi

kscope -v &> /dev/null
if [ $? -eq 0 ]; then
  echo "Kscope works fine."
  exit
fi

echo "Downloading KDE3 libraries needed by kscope..."
wget http://ftp.debian.org/debian/pool/main/k/kdebase/kate_3.5.9.dfsg.1-6_${ARCH}.deb
dpkg -x kate_3*.deb kate

echo "Installing KDE3 libraries..."
sudo cp kate/usr/lib/libkateinterfaces.so.0.0.0 /usr/local/lib/
sudo cp kate/usr/lib/libkateutils.so.0.0.0 /usr/local/lib
sudo ln -s /usr/local/lib/libkateinterfaces.so.0.0.0 /usr/local/lib/libkateinterfaces.so.0
sudo ln -s /usr/local/lib/libkateutils.so.0.0.0 /usr/local/lib/libkateutils.so.0
sudo ldconfig

echo "Finished."

编译一个软件要花多长时间?

不知道现在世界上有多少人正坐在电脑前,等待着编译结束。如果把所有的软件按照规模来排名的话,编译器至少应该在最大那一批的角落里,想想自己动手编译 GNU 工具链需要的时间吧!难怪有人抗议说 gcc 应该附带音乐以便编译时候打发时间 ^_^

但是还有比 gcc 更变态的,就比如 Open64(原为 SGIPro64,开源后叫 Open64,Intel 和中科院改的叫 ORC,Pathscale 改的叫 EkoPath,特拉华大学改的叫 KylinC),Open64 前端使用的是修改后的 gcc,然后对生成的 WHIRL 文件进行处理,生成 .s 文件再让 as 去汇编。在编译 Open64 时什么稀奇古怪的问题都可能出来,最主要的原因可能是 gcc, binutils 源代码版本不对应,或者只能使用某个版本的 gcc 去编译,某个版本的 ld 去连接。看看 Open64 中的源代码就可以发现,什么风格的代码都有,gcc 的代码可能是 K&R 的,也可能是 ANSI 的,有 C 风格的 C++,还有数不清的 csh,代码的混乱程度比 gcc 有过之而无不及,warning 一大堆,我每次都奇怪它是如何编译过去的。

我没有具体计算过 Open64 的编译时间,但是从感觉上来看,如果全部编译的话,Open64 至少需要一个小时(双核3.4G,2G内存)。平常我改编译器的源代码,最多的就是改 Dwarf 相关的调试信息输出。GNU make 会增量构建,改个 c/cxx 问题还不大,顶多重编一下模块,我最怕的就是改动哪个头文件。因为如果动了头文件,尤其是那种比较关键的头文件,就意味这下面一个小时就等编译结果吧。

一般情况下 make 的逻辑是:如果源文件被更新,只需要重编这个文件生成目标文件,然后用其重新构建可执行文件;如果头文件被更新,那么所有依赖此头文件的源文件都要被重新编译。这个依赖关系是写在 Makefile 中的,为了避免无谓的重编译,一定要在 Makefile 中确定正确的依赖关系。而这个依赖关系的依据是程序中头文件的包含关系和模块之间的联系,所以在写程序时一定要谨慎地选择包含头文件。多 include 一个头文件,错误地声明一个全局变量,都会造成程序的臃肿。

其实在这一点上 GNU 的东西做得就比较不错,头文件的包含,文件的依赖关系都很清楚,而且本身做为 Linux 下的程序员来说,了解依赖关系就是理解 Makefile 的第一步。相比而言 Windows 程序员就差很多,Win 程序员太依赖 IDE(集成开发环境) 了,没有 IDE 什么都干不了。经常有人问 Linux 下没有 VC,那怎么写程序?天那,比 VC 优秀的编译器有很多,而且没有图形界面不意味着写不出图形界面的程序,VC 编译程序也是调用命令行的。VC 的编译器叫做 CL, 连接器叫做 LINK,VC 也有 make,叫做 NMAKE。不相信的人可以尝试一下:如果你安装了 VC 并且选择了将 VC 可执行文件路径加入到环境变量里,那么就可以用 CL hello.cpp 来编译你的 hello world 程序,根本没有必要为了一个单文件的命令行程序创建一个工程。

Linux 并不拒绝 IDE,从 Eclipse 的流行可以看到这一点,但是不要让 IDE 把程序员变傻。如果不了解程序编译的整个过程和逻辑,那么写程序就成了一件盲目的事情。很多 VC 的程序员都不能区分什么是 assembly file, object file, executable file,什么是 preprocess,一个程序的源文件是怎么组织起来的,最终的二进制文件是怎样生成的。他们所知道的就是把一个文件往工程里一拉,乱七八糟的头文件一包含,就希望程序能编译过去。一旦遇到问题,马上抱怨怎么报那么多错误,就算很明显的错误也要到论坛上叽叽歪歪一番,怎么能期望得到一个可靠又高效的程序呢?

从 VC 自动生成的源程序来看,本身就有很多问题,就拿 VC 自动生成的类来说,鲜有 private 类型的成员变量和方法,大多数都是 public 或者 protect 了事,因为这样它不容易出错。但是这样一来 C++ 面向对象的特性又去哪儿了?MFC 里一堆一堆的宏,又如何了解真正的 API?

IDE 仅仅是一个加强版的文本编辑器,它提供的功能是高效写代码,但需要程序员自己保证写高效的代码!

细节很重要!