因为网络不通,无法使用服务器上的lxr,严重影响我阅读代码的效率,所以索性自己找来了LXR的最新版lxr-0.9.1,在本地机上试着安装一份。
LXR是使用WEB方式下的源代码整理浏览工具,最大的用途在于清理出了代码中函数、变量的定义、说明、应用的关系,并用链接的形式表现在网页上。LXR整理出代码的结构和调用关系,存在数据库中,并在显示时与源代码树结合,从功能上说,包括代码浏览、标识符搜索、文本搜索和文件搜索,其中的文本搜索和文件搜索利用的是第三方工具(即glimpse或swish-e)。它的主要组成部分包括三个:Perl编写的网页/CGI部分,基于MySQL的索引数据管理(新版本才有)和通用的文本搜索工具。目前的版本,采用Glimpse或者Swish-e中的一种作为通用文本搜索工具。在安装上,基本上也按照这三个部分来配置。
1.download
现在LXR已经成为sourceforge的一个project,所以可以到lxr.sourceforge.net上找到最新的lxr代码(当然也就是源代码了)。glimpse和swish-e另找。
要使LXR工作,至少需要以下部件:
一个支持CGI的Web服务器,Apache就不错;
Apache的mod_perl插件,以支持perl脚本的cgi解释,或者直接用Perl也可以;
MySQL或者Postgres,本人用的是MySQL;
ctags包,一般都有。
2.configure
尽管lxr源码里有一个INSTALL文件,但语焉不详,这里写下的是本人的配置经验,不一定是唯一的,也不一定是最佳的。
1)位置规划
LXR除了数据库那一部分不需要考虑存放位置以外,还有CGI/HTML部分、索引生成工具部分和所需要索引的源代码部分需要考虑,我的实践中使用的与INSTALL缺省的不同,最大的一点不同在于我将WEB部分和工具部分分离开,只允许WEB部分暴露给浏览器——主要是基于也许会更安全一些的考虑。
另一个不同是用符号链接而不是真正的源代码目录作为源代码部分,因为LXR索引的Linux Kernel是最常用的,而Kernel本身还被用来重编内核和升级,所以不适合完全拷贝过来。
本例中使用的是/usr/local/lxr目录作为LXR的根目录。
#tar zxvf lxr-0.9.1.tar.gz -C /usr/local ;将lxr解压到/usr/local/lxr下
#cd /usr/local/lxr
#mkdir http ;建http目录,用于存放WEB部分
#mv Local.pm diff fixhashbang ident find search source templates/* http
;将web相关部分移到http下
#rm -rf templates ;这个模板目录已经没用了
#ln http/Local.pm . -s
#ln http/lxr.conf . -s ;为web部分和工具部分都需要用的文件建符号连接
#mkdir src ;源代码部分的根
#cd src
#mkdir kernel ;内核代码目录
#vi versions ;编辑/usr/local/lxr/src/versions文件,内容为kernel,表示让lxr索引kernel
#cd kernel
#ln ../../../../src/linux-2.4.18 2.4.18 -s ;2.4.18才是真正的kernel源码根,之所以这么安排,主要是为了避免glimpse建索引时弄脏了/usr/src/linux-2.4.18/
#cd ../../ ;回到/usr/local/lxr
#mv lib /usr/lib/perl5/site_perl/LXR ;将自定义的perl库文件拷贝到perl/mod_perl使用的缺省库文件目录中,这是相对于redhat系统的
2)改写lxr.conf
准备好了目录结构,下一步就是改写lxr.conf文件。缺省的lxr.conf已经从templates拷贝到/usr/local/lxr/http/下了,并在/usr/local/lxr/下有个连接。
'glimpsebin'变量,改为glimpse命令的位置,用which glimpse可以找到(如果装了的话),缺省为/usr/bin/glimpse;
注释掉所有与swish-e相关的变量定义,——因为我编译swish-e时,make test执行了两天一夜也没有结束,所以只好改用glimpse,据说swish-e更强大些;
'genericonf'设为'/usr/lib/perl5/site_perl/LXR/Lang/generic.conf';
'baseurl'设为'http://10.129.6.244/lxr',这个IP当然不是通用的;
'range'改为[ readfile('/usr/local/lxr/src/versions') ],用绝对路径,主要是为了方便;
'default'改为'kernel',我自己定义的缺省的代码树名;
'sourceroot'设为'/usr/local/lxr/src',也用绝对路径;
'sourcerootname'设为'Linux',自定义的,它将显示在缺省的最高级源码目录上;
'glimpsedir' => '/usr/local/lxr/src/$v/',$v表示使用version变量的值,也就要求把glimpse的索引结果文件保存在/usr/local/lxr/src/kernel上,与2.4.18并列;
其余都不用改。
3)apache的httpd.conf
保证装了mod_perl的时候,在httpd.conf中添加以下几行:
Alias /lxr /usr/local/lxr/http
<Directory /usr/local/lxr/http>
AllowOverride None
Options FollowSymLinks
<Files ~ (search|source|ident|diff|find)$>
SetHandler perl-script
PerlHandler Apache::Registry
Options +ExecCGI
</Files>
</Directory>
表示访问/lxr就相当于访问/usr/local/lxr/http,且用perl解释search、source、ident、diff和find几个脚本,而其他的仍然当成html来使用。
如果没有mod_perl,可以用SetHandler cgi-script代替perl-script,一样可以用,PerlHandler就不用了。
3.initialize
1)初始化MySQL数据库
运行mysql,在提示符下运行"\. initdb-mysql"。这样就建好了lxr用户,建好了lxr数据库可其中一系列表格,并让lxr能全权访问lxr数据库,但没有访问其他库的权限,而且,也不用密码。
2)建glimpse索引
在/usr/local/lxr/src/kernel/下运行'find . -name "*.[chS]" -follow | glimpseindex -H . -o -F',索引所有.c、.h、.S(汇编)文件。这个过程比较耗时,但比起下一个过程来,就小巫见大巫了。
3)建identity索引
这是LXR精髓所在,在/usr/local/lxr/下运行'./genxref --version=kernel --url=http://10.129.6.244/lxr',这个过程在我的机器上用了5个小时,其结果就是在MySQL中添东西。如果已经做过索引了,它就只关心那些修改过的或新的文件,速度就快多了。这个过程如果中断了,最好清空数据库重新来过,否则可能会有错误。
4)修改权限
最简单的办法就是把/usr/local/lxr/http下所有的文件都改成apache的属主。在/usr/local/lxr/下运行'chown apache.apache http -R'。
4.startup
重启mysql和httpd,然后访问http://10.129.6.244/lxr/source/就可以了。比较奇怪的是,因为这个cgi允许用类似目录一样的形式(source/)来访问,所以,如果服务器端有更新,浏览器端仍会使用老的页面,refresh也没用。这时只有清空本地cache了。
5.update
我还没有遇到更新的情况,但估计2.4.18升级到2.4.19时比较麻烦,因为目录名变了,而数据库里存的仍然是老名字,glimpse也用的老名字,所以更新可能需要重建一次数据索引,就是重新来一次3.initialize。
但如果仅仅是添加新的源代码树,则只需要修改src/versions文件,按照kernel/2.4.18的模子再在src下建一个目录树,并一样执行一次3.2、3.3、3.4就可以了。为了方便,我把3.x做成了两个脚本。
6.bugs
应该在源代码树的组织上。如果同时要索引kernel-2.4.18和kernel-2.2.19,逻辑上好像应该在kernel下建另一个连接指向2.2.19的代码,但实际上应该建一个kernel2与kernel并列在src目录下。
更新时看样子也会有问题,因为数据库里记录了2.4.18的目录信息,glimpse里也记录了2.4.18。重建实在耗时。
不知谁有更好的配置方案,尽管这做不了博士课题。
不知道有没有遗漏的地方。还多亏参考了别人已有的配置,尽管版本不同。
FIXIT:
1.在Config.pm中有一段处理baseurl的代码(_initialize()),屏蔽了所有config变量的生成。只能注释掉才能使其正常工作。
2.缺省情况下,glimpse采用case insensitive方式工作(search程序),需要去掉"-i"的开关。
---------------------------------------------------------------------------------------------------------------------------------------------
前段时间因为工作需要,从源码开始配置了apache2+modperl2+lxr-0.9.2,有些地方和本文所说不
同,所以把更新内容贴在这里,希望对后来者有用。
--------------
更新 040628:
1.从perl源码安装时没有DBI和DBD::mysql,需要自行安装。
DBI和DBD::mysql的源代码都可以直接从google中找到,下载后perl
Makefile.PL、make、make install即可。
2./usr/lib/perl5/site_perl下需要有一份Local.pm的链接,/usr/local/lxr下倒是不需要。
3.source脚本里使用的internal-gopher-*图片都不能正常显示,可能是mozilla或者是别的什么浏
览器的设置。需要恢复成注释掉的/icons/目录下的相应图片,这些图片apache的缺省安装都有。
4.不知道为什么,http目录下的那些template HTML文件在各个脚本里都打不开(doesn't
exist),除非将其拷贝到系统根目录(“/”)。没办法,只能在lxr.conf中使用绝对路径来说明
这些templates。
5.html-head.html和html-tail.html中都含有一些指向internet的图片链接,最简单的办法就是去
掉那个<img>。
6.swish-e的配置很简单,只要设置好lxr.conf中的变量就可以
了。但“file search”功能没有实现使用swish-e的版本,如果
要用,只能继续使用glimpse。glimpse的配置因为版本的变化
而和以前有所不同,而且在lxr.conf中已经没有glimpseindex的
变量定义了,需要手工添加。
7.swish-e的索引文件现在统一放在src/index目录下,因为
genxref会用'$version'作为索引文件的文件名前缀,因而可以放
在同一个目录下。
8.lxr可能原本用于同一软件的不同版本的源代码索引,例如
Linux的不同版本,因此它的version变量应该是代码的版本号,
但这里直接用这个版本号指向了不同的代码树。本来lxr索引的
不同版本的代码是可以diff markup的,现在这个功能也就同时
失去了意义。
9.使用mod_perl2的apache2的httpd.conf文件变化不大,只需要
将Apache::Registry改为ModPerl::Registry。
10.样例中的lxr.conf有两个swishdir和两个glimpsedir,后面那
一对实际上可以删除。
11.现在直接将代码拷贝到src目录下,而不是像以前那样在src
的子目录里再作目录链接,也就是说,少了一层目录。
12.html-ident.html最后那个table是冗余的,应该删除。
13.httpinit函数最后调用了printhttp来显示一些信息,但这些信
息会影响lxr输出的美观(位于题头),所以在
LXR::Common.pm中注释掉了。
14.0.9.2版的lxr把freetext索引和identity索引都集中在genxref脚
本中进行,且4.17版的glimpseindex不支持管道输入。
15.将glimpsedir设为"/usr/local/lxr/src/index",glimpseindex将
把索引文件建立在$glimpsedir/$release/目录下。这时应当修改
find和search,当它输出文件名时忽略掉$config->sourceroot/
$release/的前缀。和以前的配置相比,这一修改是当前仅有一
层源码目录引起的。
16.最终还是选用glimpse,因为它的freetext索引中有简短的上
下文。
更新040708:
因为发现lxr在Linux的几个浏览器下都只显示HTML代码,
所以怀疑是因为注释了printhttp()而缺少HTML Header,但加上
这个函数后仍然如此,HTML头信息直接显示在HTML代码最前
面。
参考linux-forum上tcpwl的配置,在httpd.conf中加上
“ForceType text/html”,就可以正确显示了。
如此设置后,printhttp()打印的几行Header信息仍然显示了
出来,仍然是参考tcpwl的配置,加上“PerlOptions ParseHeaders”,
但浏览时报错,说缺少http头。
注释掉printhttp()中“Content-Type”之前的两个打印语
句,总算正常了。
现在的httpd.conf中与lxr相关的部分如下:
----------
Alias /lxr /usr/local/lxr/http
<Directory /usr/local/lxr/http>
AllowOverride None
Options FollowSymLinks
<Files ~ (search|source|ident|diff|find)$>
SetHandler perl-script
PerlHandler ModPerl::Registry
PerlOptions ParseHeaders
Options +ExecCGI
</Files>
ForceType text/html
</Directory>
现在的lxr.conf如下:
-----------
# -*- mode: perl -*-
# Configuration file
#
(
{
# Global configuration
# Path to glimpse executable.
# Define this OR the swish-e variables depending which search engine you want to
use.
'glimpsebin' => '/usr/local/bin/glimpse',
'glimpseindex' => '/usr/local/bin/glimpseindex',
# Where to store the glimpse index files
'glimpsedir' => '/usr/local/lxr/src/index',
# Location of SWISH-E indexer binary
# 'swishindex' => '/usr/local/bin/swish-e',
# Location of SWISH-E search binary
# 'swishsearch' => '/usr/local/bin/swish-e',
# Where to store the swish index files
# 'swishdir' => '/usr/local/lxr/src/index/',
# Path to Exuberant Ctags executable
'ectagsbin' => '/usr/bin/ctags',
# Place where lxr can write temporary files
'tmpdir' => '/tmp',
# Location of the Generic.pm config file
'genericconf' => '/usr/lib/perl5/site_perl/LXR/Lang/generic.conf'
},
{
# Configuration for href=http://192.168.1.3/lxr.>http://192.168.1.3/lxr.
# baseurl is used to select configuration block.
'baseurl' => 'http://172.16.109.67/lxr', # Put your URL here
'virtroot' => '/lxr', # The bit after the / above
'variables' => {
# Define typed variable "v". This is the list of versions to index.
'v' => {'name' => 'Version',
# This can come from a file, a function or be explicitly
# ennumerated.
# From a file:
'range' => [ readfile('/usr/local/lxr/src/versions') ],
# Explicitly:
# 'range' => [qw(v1 v2 v3.1 v4 experimental)],
# If files within a tree can have different versions,
# e.g in a CVS tree, 'range' can be specified as a
# function to call for each file:
#'range' => sub { return
# ($files->allreleases($LXR::Common::pathname),
# $files->allrevisions($LXR::Common::pathname))
# }, # deferred function call.
# The default version to display
'default' => 'linux-2.6.6'},
# Define typed variable "a". First value is default.
'a' => {'name' => 'Architecture',
'range' => [qw(i386 alpha arm m68k mips ppc sparc sparc64)]},
},
# These do funky things to paths in the system - you probably don't need them.
'maps' => {
'/include/asm[^\/]*/' => '/include/asm-$a/',
'/arch/[^\/]+/' => '/arch/$a/',
},
# Templates used for headers and footers
'htmlhead' => '/usr/local/lxr/http/html-head.html',
'htmltail' => '/usr/local/lxr/http/html-tail.html',
'htmldir' => '/usr/local/lxr/http/html-dir.html',
'htmlident' => '/usr/local/lxr/http/html-ident.html',
'htmlident_refs' => '/usr/local/lxr/http/html-ident-refs.html',
'sourcehead' => '/usr/local/lxr/http/html-head.html',
'sourcedirhead' => '/usr/local/lxr/http/html-head.html',
'stylesheet' => 'lxr.css',
# sourceroot - where to get the source files from
# For ordinary directories, this specifies a directory which has each version as a
# subdirectory e.g.
# indexed-src/version1/...
# indexed-src/version2/...
# The names of the version directories must match the values for the Version
# variable above.
'sourceroot' => '/usr/local/lxr/src',
# Alternatively, this can specify a CVS repository by setting the value to "cvs:"
# followed by the path to the repository. Note this must be file accessible -
remote
# server access does NOT work.
# 'sourceroot' => 'cvs:/hom/karsk/a/CVSROOT/linux',
# The name to display for this source tree
'sourcerootname' => 'Codes',
# The DBI identifier for the database to use
# For mysql, the format is dbi:mysql:dbname=<name>
# for Postgres, it is dbi:Pg:dbname=<name>
# for Oracle, it is dbi:Oracle:host=localhost;sid=DEVMMS;port=1521
'dbname' => 'dbi:mysql:dbname=lxr',
# If you need to specify the username or password for the database connection,
# uncomment the following two lines
# 'dbpass' => 'foo',
# 'dbuser' => 'lxr',
# For using glimpse, the directory to store the .glimpse files in is required
# 'glimpsedir' => '/path/to/glimpse/databases',
# Location of swish-e index database files if using swish-e
# 'swishdir' => '/usr/local/lxr/src/$v',
# where to look for include files inside the sourcetree. This is used to hyperlink
# to included files.
'incprefix' => ['/include', '/include/linux'],
# Which extensions to treat as images when browsing. If a file is an image,
# it is displayed.
'graphicfile' => '(?i)\.(gif|jpg|jpeg|pjpg|pjpeg|xbm|png)$', #'
# How to map files to languages
# Note that the string for the key and the first entry in the
# array MUST match
'filetype' => {
# Format is
# Language name, filepatten regexp, module to invoke,
# (optional )tabwidth
# Note that to have another language supported by Generic.pm,
# you must ensure that:
# a) exuberant ctags supports it
# b) generic.conf is updated to specify information about the language
# c) the name of the language given here matches the entry in generic.conf
'C' => ['C', '\.c$' #'
, 'LXR::Lang::Generic', '8'],
'C++' => ['C++',
'\.C$|((?i)\.c\+\+$|\.cc$|\.cpp$|\.cxx$|\.h$|\.hh$|\.hpp$|\.hxx$|\.h\+\+$)' #'
, 'LXR::Lang::Generic', '8'],
# Some languages are commented out until the relevant entries in generic.conf are
made
# The list here is the set supported by ctags 5.0.1
# ['Beta', '(?i)\.bet$' #'
# , 'LXR::Lang::Generic'],
# ['Cobol', '(?i)\.cob$' #'
# , 'LXR::Lang::Generic'],
# ['Eiffel', '(?i)\.e$' #'
# , 'LXR::Lang::Generic'],
# ['Fortran', '(?i)\.f$|\.for$|\.ftn$|\.f77$|\.f90$|\.f95$' #'
# , 'LXR::Lang::Generic'],
'Java' => ['Java', '(?i)\.java$' #'
, 'LXR::Lang::Java', '4'],
# ['Lisp', '(?i)\.cl$|\.clisp$|\.el$|\.l$|\.lisp$|\.lsp$|\.ml$' #'
# , 'LXR::Lang::Generic'],
# No tabwidth specified here as an example
'Make' => ['Make', '(?i)\.mak$|makefile*' #'
, 'LXR::Lang::Generic'],
# ['Pascal', '(?i)\.p$|\.pas$' #'
# , 'LXR::Lang::Generic'],
'Perl' => ['Perl', '(?i)\.pl$|\.pm$|\.perl$' #'
, 'LXR::Lang::Generic', '4'],
'php' => ['php', '(?i)\.php$|\.php3$|\.phtml$' #'
, 'LXR::Lang::Generic', '2'],
'Python' => ['Python', '(?i)\.py$|\.python$' #'
, 'LXR::Lang::Generic', '4'],
# ['rexx', '(?i)\.cmd$|\.rexx$|\.rx$' #'
# , 'LXR::Lang::Generic'],
# ['ruby', '(?i)\.rb$' #'
# , 'LXR::Lang::Generic'],
# ['scheme', '(?i)\.sch$|\.scheme$|\.scm$|\.sm$' #'
# , 'LXR::Lang::Generic'],
# ['shell', '(?i)\.sh$|\.bsh$|\.bash$|\.ksh$|\.zsh$' #'
# , 'LXR::Lang::Generic'],
# ['s-Lang', '(?i)\.sl$' #'
# , 'LXR::Lang::Generic'],
# ['tcl', '(?i)\.tcl$|\.wish$' #'
# , 'LXR::Lang::Generic'],
},
# Maps interpreter names to languages. The format is:
# regexp => langname
# regexp is matched against the part after #! on the first line of a file
# langname must match one of the keys in filetype above.
#
# This mapping is only used if the filename doesn't match a pattern above, so
# a shell script called shell.c will be recognised as a C file, not a shell file.
'interpreters' => {
'perl' => 'Perl',
# 'bash' => 'shell',
# 'csh' => 'shell',
'python' => 'Python',
},
})
LXR 0.9.3 版本已经发布, 安装过程比较方便 , 生成网页的脚本修正了
不过安装前需要预先安装必须的工具(见附件MMagic)和glimpse最新版本
安装过程和0.9.2 基本相同,不需要手工运行glimpse, 由lxr 自己调用.
浙公网安备 33010602011771号