elixir

elixir

开源源代码索引和交叉引用系统

Elixir是一个开源的源代码交叉引用系统,专为C/C++项目设计。它使用Git和Berkeley DB存储代码及索引数据,可高效索引大型项目的所有版本。Elixir采用简洁的数据结构,提供快速查询,支持CGI和REST API接口。该系统特别适合Linux内核等大型开源项目的代码浏览和搜索。

Elixir源代码索引Git数据库Github开源项目

= Elixir 交叉引用工具 :doctype: book :pp: {plus}{plus} :toc: :toc-placement!:

image::https://travis-ci.com/bootlin/elixir.svg?branch=master[构建状态,link=https://travis-ci.com/bootlin/elixir]

Elixir 是一个受 https://en.wikipedia.org/wiki/LXR_Cross_Referencer[LXR] 启发的源代码交叉引用工具。它用 Python 编写,主要目的是为了以最小的占用空间索引 C 或 C{pp} 项目(如 Linux 内核)的每个发布版本。

它使用 Git 作为源代码文件存储,使用 Berkeley DB 存储交叉引用数据。在内部,它索引 Git blobs 而不是文件树,以避免重复工作和数据。它具有简单直观的数据结构(类似于早期的 LXR 版本),以保持查询简单快速。

您可以在 https://elixir.bootlin.com/ 上看到它的运行效果

注意:本文档适用于 Elixir 2.0 版本。

toc::[]

= 要求

  • Python >= 3.6
  • Git >= 1.9
  • Jinja2 和 Pygments (>= 2.7) Python 库
  • Berkeley DB (及其 Python 绑定)
  • Universal Ctags
  • Perl (用于非贪婪正则表达式和自动化测试)
  • Falcon 和 mod_wsgi (用于 REST API)

= 架构

Elixir 具有以下架构:

.---------------.----------------. | CGI 接口 | REST 接口 | |---------------|----------------.

查询命令更新命令
Shell 脚本
'--------------------------------'

Shell 脚本 (script.sh) 是底层,提供与 Git 和其他 Unix 工具交互的命令。Python 命令使用 shell 脚本的服务来提供对带注释的源代码和标识符列表的访问 (query.py),或创建和更新数据库 (update.py)。最后,CGI 接口 (web.py) 和 REST 接口 (api.py) 使用查询接口来生成 HTML 页面和响应 REST 查询。

在安装系统时,您应该手动测试每一层,确保它正常工作后再继续下一层。

== 数据库设计

./update.py 存储 git 对象哈希("blobs")和顺序键之间的双向映射。 索引这些哈希的目的是减少它们的存储占用(SHA-1 哈希为 20 字节,而 32 位整数为 4 字节)。

将提供详细的数据库图表。在此之前,请直接查看源代码。

= 手动安装

== 安装依赖


对于 RedHat/Fedora/AlmaLinux



sudo dnf install python36-pip python36-pytest python36-jinja2 python36-bsddb3 python36-falcon python3-pygments git httpd perl perl-autodie jansson libyaml rh-python36-mod_wsgi


对于 Debian



sudo apt install python3-jinja2 python3-bsddb3 python3-falcon python3-pytest python3-pygments universal-ctags perl git apache2 libapache2-mod-wsgi-py3 libjansson4

要启用 REST API,请按照 https://github.com/GrahamDumpleton/mod_wsgi[`mod_wsgi`] 的安装说明进行操作,并按照 https://github.com/GrahamDumpleton/mod_wsgi#connecting-into-apache-installation 中的详细说明将其连接到 apache 安装。

要了解需要安装哪些软件包,您还可以阅读 docker/ 目录中的 Docker 文件,以了解 Elixir 在您喜欢的发行版中需要哪些软件包。

== 下载 Elixir 项目


git clone https://github.com/bootlin/elixir.git /usr/local/elixir/

== 创建目录


mkdir -p /path/elixir-data/linux/repo mkdir -p /path/elixir-data/linux/data

== 设置环境变量

使用两个环境变量来告诉 Elixir 在哪里找到项目的本地 git 仓库和数据库:

  • LXR_REPO_DIR (项目的 git 仓库目录)
  • LXR_DATA_DIR (项目的数据库目录)

现在打开 /etc/profile 并追加以下内容。


export LXR_REPO_DIR=/path/elixir-data/linux/repo export LXR_DATA_DIR=/path/elixir-data/linux/data

然后运行 source /etc/profile

== 克隆内核源代码

首先克隆 Linus Torvalds 发布的主分支:


cd /path/elixir-data/linux git clone --bare https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git repo

然后,您还应该声明一个对应于 stable 树的 stable 远程分支,以获取所有发布更新:


cd repo git remote add stable git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git git fetch stable

然后,您还可以声明一个对应于其他仓库中不存在的旧 Linux 版本的 history 远程分支,以获取所有仍然可用的旧版本:


cd repo git remote add history https://github.com/bootlin/linux-history.git git fetch history --tags

请随意以这种方式添加更多远程分支,因为 Elixir 将考虑所有远程分支的标签。

== 第一次测试


cd /usr/local/elixir/ ./script.sh list-tags

== 创建数据库


./update.py <线程数>


生成完整数据库可能需要很长时间:在 Xeon E3-1245 v5 上索引 Linux 内核的 1800 个标签大约需要 15 小时。因此,您可能想要调整脚本(例如,通过使用 "head" 限制标签数量)以测试更新和查询命令。您甚至可以创建一个新的 Git 仓库,只创建一个标签,而不使用非常大的官方内核仓库。


== 第二次测试

验证查询是否有效:

$ ./query.py v4.10 ident raw_spin_unlock_irq C $ ./query.py v4.10 file /kernel/sched/clock.c

注意: v4.10 可以替换为任何其他标签。

== 配置 httpd

CGI 接口 (web.py) 旨在由您的 Web 服务器调用。由于它包含对多个项目进行索引的支持,它需要一个不同的变量 (LXR_PROJ_DIR),该变量指向具有特定结构的目录:

  • <LXR_PROJ_DIR> ** <项目 1> *** data *** repo ** <项目 2> *** data *** repo ** <项目 3> *** data *** repo

然后它将在调用查询命令时生成其他两个变量。

现在打开 /etc/httpd/conf.d/elixir.conf 并写入以下内容。 注意:如果使用 apache2 (Ubuntu/Debian) 而不是 httpd (RedHat/Centos), 默认配置文件为: /etc/apache2/sites-enabled/000-default.conf


HTTP 所需

<Directory /usr/local/elixir/http/> Options +ExecCGI AllowOverride None Require all granted SetEnv PYTHONIOENCODING utf-8 SetEnv LXR_PROJ_DIR /path/elixir-data </Directory>

REST API 所需

<Directory /usr/local/elixir/api/> SetHandler wsgi-script Require all granted SetEnv PYTHONIOENCODING utf-8 SetEnv LXR_PROJ_DIR /path/elixir-data </Directory>

AddHandler cgi-script .py #Listen 80 <VirtualHost *:80> ServerName xxx DocumentRoot /usr/local/elixir/http

# 要在安装 mod_wsgi 后启用 REST api:填写路径并取消注释:
#WSGIScriptAlias /api /usr/local/elixir/api/api.py

AllowEncodedSlashes On

RewriteEngine on RewriteRule "^/$" "/linux/latest/source" [R] RewriteRule "^/(?!api|acp).*/(source|ident|search)" "/web.py" [PT] RewriteRule "^/acp" "/autocomplete.py" [PT] </VirtualHost>

RHEL/CentOS 默认已启用 cgi 和 rewrite 支持,但如果你使用的是 Debian/Ubuntu 发行版,则需要手动启用。


a2enmod cgi rewrite

最后,启动 httpd 服务器。


systemctl start httpd

== 配置 SELinux 策略

当使用启用了 SELinux 的 systemd 时,httpd 服务器只能访问有限的目录。 如果你的 /path/elixir-data/ 不在这些允许的目录中,你将收到 500 状态码的响应。

要允许 httpd 服务器访问 /path/elixir-data/,请运行以下命令:

chcon -R -t httpd_sys_rw_content_t /path/elixir-data/

要检查是否生效,请运行以下命令:

ls -Z /path/elixir-data/

如果你想查看与 httpd 相关的 SELinux 日志,请运行以下命令:

audit2why -a | grep httpd | less

== 配置 systemd 日志目录

默认情况下,elixir 的错误日志会放在 /tmp/elixir-errors。 然而,systemd 默认启用 PrivateTmp。 因此,最终的错误目录将类似于 /tmp/systemd-private-xxxxx-httpd.service-xxxx/tmp/elixir-errors。 如果你想禁用它,请使用以下属性配置 httpd.service:

PrivateTmp=false

== 配置 lighttpd

以下是 lighttpd 的示例配置:


server.document-root = server_root + "/elixir/http" url.redirect = ( "^/$" => "/linux/latest/source" ) url.rewrite = ( "^/(?!api|acp).*/(source|ident|search)" => "/web.py/$1") url.rewrite = ( "^/acp" => "/autocomplete.py") setenv.add-environment = ( "PYTHONIOENCODING" => "utf-8", "LXR_PROJ_DIR" => "/path/to/elixir-data" )

= REST API 使用

配置 httpd 后,你可以测试 API 的使用:

== ident 查询

/api/ident/<Project>/<Ident>?version=<version>&family=<family> 发送 GET 请求。 例如:

curl http://127.0.0.1/api/ident/barebox/cdev?version=latest&family=C

响应体的结构如下:


{ "definitions": [{"path": "commands/loadb.c", "line": 71, "type": "variable"}, ...], "references": [{"path": "arch/arm/boards/cm-fx6/board.c", "line": "64,64,71,72,75", "type": null}, ...] }

= 维护和增强

== 使用缓存提高性能

在 Bootlin,我们使用 https://varnish-cache.org/[Varnish http 缓存] 作为前端,以减少运行 Elixir 代码的服务器负载。

.-------------. .---------------. .-----------------------. | Http 客户端 | --------> | Varnish 缓存 | --------> | 运行 Elixir 的 Apache | '-------------' '---------------' '-----------------------'

== 保持 Elixir 数据库更新

为了保持 Elixir 数据库的更新并索引新发布的版本, 我们建议使用类似 utils/update-elixir-data 的脚本,通过每日 cron 任务调用。

你可以设置 $ELIXIR_THREADS 来更改 update.py 用于索引的线程数(默认为系统的 CPU 数量)。

== 控制 git 仓库的磁盘使用

随着不断更新 git 仓库,你可能会注意到某些仓库比原来大得多。这似乎发生在大型仓库中出现 gc.log 文件时, 导致 git 的垃圾收集器(git gc)失败,因此每次获取新对象时都会快速消耗磁盘空间。

当这种情况发生时,你可以通过打包 git 目录来节省磁盘空间,方法如下:


cd <bare-repo> git prune rm gc.log git gc --aggressive

实际上,再次运行上述命令可以节省更多空间。

要在循环中处理多个 git 仓库,你可以使用我们提供的 utils/pack-repositories 脚本, 在所有仓库所在的目录中运行。

= 构建 Docker 镜像

Dockerfile 文件位于 docker/ 目录中。要构建镜像,请运行以下命令:

git clone https://github.com/bootlin/elixir.git ./elixir

docker build -t elixir -f ./elixir/docker/Dockerfile ./elixir

然后你可以使用 docker run 运行镜像。 建议将卷或主机目录挂载到 Elixir 数据目录。 这样可以轻松替换容器为新版本,而不会丢失索引数据。

mkdir ./elixir-data

docker run -v ./elixir-data/:/srv/elixir-data -d --name elixir-container elixir

Docker 镜像不包含任何仓库。要索引仓库,你可以使用实用脚本 index-repository。 例如,要添加 musl 仓库,请运行:

docker exec -it -e PYTHONUNBUFFERED=1 elixir-container /usr/local/elixir/utils/index-repository musl https://git.musl-libc.org/git/musl

没有 PYTHONUNBUFFERED 环境变量,更新日志可能会延迟显示。

或者,在单独的容器中运行索引:

docker run -e PYTHONUNBUFFERED=1 -v ./elixir-data/:/srv/elixir-data --entrypoint /usr/local/elixir/utils/index-repository elixir musl https://git.musl-libc.org/git/musl

你也可以使用 utils/index-all-repositories 开始索引所有官方支持的仓库。

索引完成后,Elixir 应该可以在主机上通过以下 URL 访问: http://172.17.0.2/musl/latest/source

如果 172.17.0.2 无响应,你可以通过运行以下命令检查容器的 IP 地址:

docker inspect elixir-container | grep IPAddress

== 自动仓库更新

Docker 镜像本身不会自动更新仓库。 你可以,例如,在容器中启动 utils/update-elixir-data(或在单独的容器中,挂载 Elixir 数据卷/目录) 通过主机上的 cron 定期更新仓库。

== 将 Docker 镜像用作开发服务器

你可以通过按照上述步骤轻松将 Docker 镜像用作开发服务器,但在运行 docker run elixir 时, 将主机上的 Elixir 源目录挂载到容器中的 /usr/local/elixir/

在主机上对代码所做的更改应该自动反映在容器中。 你可以使用 apache2ctl 重启 Apache。 错误日志可在容器内的 /var/log/apache2/error.log/tmp/elixir-errors 中找到。

= 硬件要求

性能要求主要取决于 Elixir 服务的流量。但是,快速的服务器对于项目的初始索引也有帮助。

强烈推荐使用 SSD 存储,因为需要频繁访问 git 仓库。

在 Bootlin,以下是我们使用的服务器的一些详细信息:

  • 截至 2019 年 7 月,我们的 Elixir 服务消耗 17 GB 数据(支持所有项目), 仅对于 Linux 内核(最新版本为 5.2),索引数据占用 12 GB, git 仓库占用 2 GB。
  • 我们在一个云服务器上使用 8 GB RAM 的 LXD 实例,该服务器有 8 个 CPU 核心, 运行频率为 3.1 GHz。

= 为 Elixir 做贡献

== 支持新项目 Elixir具有非常简单的模块化架构,只需在Elixir源码中添加一个新文件即可支持新的源代码项目。

Elixir的假设:

  • 项目源码必须存在于git仓库中
  • 所有项目发布都与特定的git标签关联。Elixir只考虑这些标签。

首先按照上述说明安装Elixir。查看projects子目录了解已支持的项目。

当Elixir至少能运行一个项目后,就可以克隆你想支持的项目的git仓库:

cd /srv/git git clone --bare https://github.com/zephyrproject-rtos/zephyr

完成后,你也可以引用和获取该项目的远程分支,例如对应Linux内核的stable树(参见本文档前面关于Linux的说明)。

现在,在你的LXR_PROJ_DIR目录中,为新项目创建一个新目录:

cd $LXR_PROJ_DIR mkdir -p zephyr/data ln -s /srv/git/zephyr.git repo export LXR_DATA_DIR=$LXR_PROJ_DIR/data export LXR_REPO_DIR=$LXR_PROJ_DIR/repo

然后,返回Elixir源码并测试标签是否正确提取:

./script.sh list-tags

根据你想在Elixir页面上展示可用版本的方式,你可能需要对每个标签字符串进行替换,例如添加缺失的v前缀,以与其他项目版本的显示方式保持一致。你也可以决定忽略特定标签。这些都可以通过在新的projects/<projectname>.sh文件中重新定义默认的list_tags()函数来实现。下面是一个例子(projects/zephyr.sh文件):

list_tags() { echo "$tags" | grep -v '^zephyr-v' }

注意<project_name>必须与你在LXR_PROJ_DIR下创建的目录名称匹配。

下一步是确保版本在版本菜单中按照你的意愿分类。这个分类工作是通过list_tags_h()函数完成的,该函数生成./scripts.sh list-tags -h命令的输出。以下是Linux项目的输出示例:

v4 v4.16 v4.16 v4 v4.16 v4.16-rc7 v4 v4.16 v4.16-rc6 v4 v4.16 v4.16-rc5 v4 v4.16 v4.16-rc4 v4 v4.16 v4.16-rc3 v4 v4.16 v4.16-rc2 v4 v4.16 v4.16-rc1 ...

第一列是版本的顶级菜单项。 第二列是下一级菜单项, 第三列是可以在菜单中选择的实际版本。 注意,这第三项必须与git中标签的确切名称相对应。

如果默认行为不符合你的需求,你需要自定义list_tags_h函数。

你还应确保Elixir正确识别最新版本:

./script.sh get-latest

如有必要,自定义get_latest()函数。

如果你想在设备树文件中启用对compatible属性的支持,在projects/<projectname>.sh的开头添加dts_comp_support=1

现在你可以为新项目生成Elixir的数据库:

./update.py <线程数>

然后你可以通过HTTP服务器检查Elixir是否正常工作。

== 编码风格

如果你希望为Elixir的Python代码做出贡献,请遵循Python的官方编码风格。

== 如何发送补丁

与我们分享贡献的最佳方式是在GitHub上提交拉取请求。

= 自动化测试

Elixir在t/目录中包含一个简单的测试套件。要运行它, 在Elixir的顶级目录中执行:

prove

测试套件使用t/tree中提取的Linux v5.4代码。

== t/tree中代码的许可

复制的代码按照Linux附带的COPYING文件中描述的方式许可。所有复制的文件都带有GPL-2.0+GPL-2.0-or-later的SPDX许可标识符。根据GNU的兼容性表,GPL 2.0+代码可以在GPLv3下使用,前提是组合在GPLv3下。此外,GNU对AGPLv3的概述表明,其条款"实际上包含GPLv3的条款"加上网络使用段落。因此,开发者有理由相信将这些文件在AGPLv3下许可是授权的。(另见此问题评论,其中有类似情况的另一个例子。)

= 许可

Elixir版权所有 (c) 2017--2020 其贡献者。它基于AGPLv3许可。 详情请参阅Elixir附带的COPYING文件。

编辑推荐精选

讯飞智文

讯飞智文

一键生成PPT和Word,让学习生活更轻松

讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。

AI办公办公工具AI工具讯飞智文AI在线生成PPTAI撰写助手多语种文档生成AI自动配图热门
讯飞星火

讯飞星火

深度推理能力全新升级,全面对标OpenAI o1

科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。

热门AI开发模型训练AI工具讯飞星火大模型智能问答内容创作多语种支持智慧生活
Spark-TTS

Spark-TTS

一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型

Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。

Trae

Trae

字节跳动发布的AI编程神器IDE

Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。

AI工具TraeAI IDE协作生产力转型热门
咔片PPT

咔片PPT

AI助力,做PPT更简单!

咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支持多种文档格式导入生成 PPT,提供海量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。

讯飞绘文

讯飞绘文

选题、配图、成文,一站式创作,让内容运营更高效

讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。

热门AI辅助写作AI工具讯飞绘文内容运营AI创作个性化文章多平台分发AI助手
材料星

材料星

专业的AI公文写作平台,公文写作神器

AI 材料星,专业的 AI 公文写作辅助平台,为体制内工作人员提供高效的公文写作解决方案。拥有海量公文文库、9 大核心 AI 功能,支持 30 + 文稿类型生成,助力快速完成领导讲话、工作总结、述职报告等材料,提升办公效率,是体制打工人的得力写作神器。

openai-agents-python

openai-agents-python

OpenAI Agents SDK,助力开发者便捷使用 OpenAI 相关功能。

openai-agents-python 是 OpenAI 推出的一款强大 Python SDK,它为开发者提供了与 OpenAI 模型交互的高效工具,支持工具调用、结果处理、追踪等功能,涵盖多种应用场景,如研究助手、财务研究等,能显著提升开发效率,让开发者更轻松地利用 OpenAI 的技术优势。

Hunyuan3D-2

Hunyuan3D-2

高分辨率纹理 3D 资产生成

Hunyuan3D-2 是腾讯开发的用于 3D 资产生成的强大工具,支持从文本描述、单张图片或多视角图片生成 3D 模型,具备快速形状生成能力,可生成带纹理的高质量 3D 模型,适用于多个领域,为 3D 创作提供了高效解决方案。

3FS

3FS

一个具备存储、管理和客户端操作等多种功能的分布式文件系统相关项目。

3FS 是一个功能强大的分布式文件系统项目,涵盖了存储引擎、元数据管理、客户端工具等多个模块。它支持多种文件操作,如创建文件和目录、设置布局等,同时具备高效的事件循环、节点选择和协程池管理等特性。适用于需要大规模数据存储和管理的场景,能够提高系统的性能和可靠性,是分布式存储领域的优质解决方案。

下拉加载更多