APR not found报错详解:Apache源码编译依赖配置与解决方案
2026/9/13 14:20:44 网站建设 项目流程

1. 一次源码编译的“下马威”:APR not found 是什么情况

兄弟们,装个 Apache(也就是 httpd)本来不是什么大事,但你要是走源码编译这条老路,十有八九会被一个报错卡得头皮发麻:

configure: error: APR not found. Please read the documentation.

我第一次遇到这个报错的时候,心里是一万个问号:我把 httpd 的压缩包解压了,进了目录,执行./configure --prefix=/usr/local/httpd,结果它给我来一句“找不到 APR”,还让我去读文档。问题是,我用find / -name "apr*"也搜索过啊,明明系统里可能压根没这东西,或者装了我不知道。

这个报错说白了就是:httpd 源码包里其实不包含完整的 APR(Apache Portable Runtime)库,它默认假设你的系统里已经装好了 APR、APR-util 和 PCRE 这三个依赖。如果 configure 脚本在默认路径下找不到它们,就会直接摆烂退出,而不是帮你自动下载或者说“我帮你装一个”。跟鸡蛋里挑骨头似的,本质上是一个依赖缺失问题,但这背后牵扯到你对 Linux 软件安装机制、库文件搜索路径、版本兼容性的理解。

那这篇文章我就把从零开始解决这条报错的路子完整走一遍。不是只告诉你“yum install apr apr-devel”这么简单,而是把背后的排查逻辑、动静两派解决方式、还会踩到什么坑,都讲清楚。适合哪些人看?刚接触 Linux 源码编译的新手、公司内网环境没法随便联网装包的同学,以及想把 Apache 调教得明明白白的运维入门选手。

2. 先搞懂 httpd、APR、APR-util 各自是谁,才好对症下药

2.1 APR 是什么,为什么 httpd 非要它不可

APR 的全称是 Apache Portable Runtime,说白了就是 Apache 自己维护的一套跨平台底层运行时库,它把文件操作、网络 socket、进程管理、共享内存、线程锁这些杂七杂八的系统调用封装成一套统一的接口。

我们不需要每个 Linux 发行版上的网络 API 写一遍,只要针对这套接口适配了某个平台,上层应用就能顺利跑起来。没有 APR 的话,httpd 自身的一大堆功能就直接没法编译通过。

这里有个很容易被忽略的细节:APR 不是 Apache 服务器的功能模块,它是一个基础依赖库。就像你做饭需要先有锅和灶,APR 就是那口锅。报错“APR not found”并不是说你 Apache 装坏了,而是说它赖以生存的锅还没准备。

2.2 光有 APR 还不够,APR-util 和 PCRE 也是刚需

很多时候,你解决完“APR not found ”,马上又会遇到下一个报错:

configure: error: APR-util not found. Please read the documentation.

或者:

configure: error: pcre-config for libpcre not found.

这说明 configure 是按顺序检查依赖的:先检查 APR,再检查 APR-util,再检查 PCRE。你缺哪个它就先报哪个。所以铺路要一次铺齐,别挤牙膏似的查一个装一个。

  • APR-util:在 APR 基础之上提供更上层的功能,比如数据库连接池、LDAP 客户端、XML 解析等等。httpd 的很多模块需要用到它。
  • PCRE:Perl Compatible Regular Expressions 库,负责正则表达式解析。Apache 的配置指令里大量用到正则匹配(比如<IfModule>RewriteRule),没有 PCRE 很多规则没法用。

2.3 报错信息里没告诉你的那些隐含条件

看报错日志的时候,光看最后一行“APR not found”其实信息非常有限。更好的习惯是把 configure 的输出从头到尾扫一遍,你会看到它其实还打印了:

checking for APR... no

也就是它检查过了,结果是否定的。再往上翻,可能还有警告信息,比如:

configure: WARNING: APR version 1.5.0 or later is required

这种情况是系统里有 APR,但版本太老,压根不达标。你敢信,有些老系统自带的 APR 版本停留在 1.4 左右,而新版本 httpd 对 APR 版本有下限要求。所以“找不到”往往不只是不存在,也可能是版本不够。

3. 两条解决路线:包管理器省心法 vs 源码编译折腾法

3.1 路线一:用发行版自带的包管理器装依赖(推荐新手上路)

这是最省心的一种方式。不同发行版对应命令不一样:

CentOS / RHEL / Rocky Linux 系:

yum install -y apr apr-devel apr-util apr-util-devel pcre pcre-devel

Debian / Ubuntu 系:

apt-get update apt-get install -y libapr1 libapr1-dev libaprutil1 libaprutil1-dev libpcre3 libpcre3-dev

装完之后,再回来执行:

./configure --prefix=/usr/local/httpd

一般情况下,configure 就能顺利通过。为什么这里要强调-devel-dev结尾的包?因为 httpd 编译时不光需要 APR 运行库,它还需要头文件(header files),比如apr.hapr_pools.h这些。普通的apr包只提供运行时需要的动态库(.so),不提供开发用的头文件;apr-devel才提供头文件和链接时的元数据。

提示:如果你在最小化安装的 CentOS 环境里,yum install可能会提示你“No package apr-devel available”。这种情况十有八九是你没装 EPEL 源或者没启用 BaseOS 源,先处理仓库源问题再继续。

3.2 路线二:源码方式自己编译安装 APR(适合离线内网或自定义版本)

包管理器虽然方便,但在某些场景下并不好使:

  1. 服务器在内网,没法直接连外网仓库;
  2. 默认仓库里的 APR 版本太老,不满足 httpd 要求;
  3. 公司安全规范要求所有软件必须走内部编译发布流程。

那就得自己找 APR 源码包来编。官方下载渠道一般是 Apache 软件基金会提供的镜像站,比如:

  • APR 源码包:apr-1.7.x.tar.gz
  • APR-util 源码包:apr-util-1.6.x.tar.gz
  • PCRE 源码包:pcre2-10.x.tar.gz(新版 httpd 对 pcre2 的支持更好,建议直接用 pcre2)

下载完成之后,按顺序编译安装。先说 APR:

tar -zxvf apr-1.7.4.tar.gz cd apr-1.7.4 ./configure --prefix=/usr/local/apr make && make install

这里--prefix=/usr/local/apr是建议的路径,把 APR 独立放在一个目录,方便后续管理和卸载。不指定也行,默认会装到/usr/local/apr的变异路径下,但那样找起来费劲,我建议还是显式指定。

接下来编译 APR-util。注意,它编译时需要知道 APR 的安装位置,所以要用--with-apr参数:

tar -zxvf apr-util-1.6.3.tar.gz cd apr-util-1.6.3 ./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr make && make install

然后编译 PCRE2:

tar -zxvf pcre2-10.42.tar.gz cd pcre2-10.42 ./configure --prefix=/usr/local/pcre2 make && make install

编译完这三个之后,再回到 httpd 源码目录,配置的时候把它们的路径都指过去:

./configure --prefix=/usr/local/httpd \ --with-apr=/usr/local/apr \ --with-apr-util=/usr/local/apr-util \ --with-pcre=/usr/local/pcre2

这一路参数就是明确告诉 configure:别瞎找了,APR 在这、APR-util 在那、PCRE 在这,直接拿去用吧。

3.3 两种路线的利弊分析

方案优点缺点适合场景
包管理器安装快、简单、自动处理依赖关系仓库版本可能偏旧;自定义安装路径困难能联网、对版本要求不高的场景
源码编译 APR版本可控、路径可控、适合离线环境步骤多、容易踩版本兼容性问题内网服务器、需要自定义参数、追求新版本

诚心建议是,能走包管理器就别折腾源码,除非你有强制性要求。MySQL、PHP 都可以编译安装玩,但 APR 这种底层库,自己编一次就会发现,它居然还有交叉编译、静态链接、共享库路径配置一堆破事,投入产出比很低。

4. 实操现场:源码编译 APR 全流程记录与避坑细节

4.1 步骤一:准备编译工具链

先别急着下载源码,你得确保系统里有编译器。用官方点的说法就是 gcc、make、libtool 这些基础组件。

CentOS/RHEL:

yum groupinstall "Development Tools"

Ubuntu/Debian:

apt-get install build-essential libtool-bin

值得注意的一点是,APR 的 configure 脚本生成过程可能依赖libtool的特定版本。如果你在 Ubuntu 上用的是libtool-bin这个包,还得确认一下版本。我遇到过在较新系统上编译老版本 APR 时,libtoolize因为版本不匹配导致生成出来的 makefile 有问题的坑。

4.2 步骤二:编译 APR 时的常见报错与对应处理

先看一个高频报错:

/usr/bin/ld: cannot find -luuid collect2: error: ld returned 1 exit status

这是链接器找不到 uuid 库。解决办法:

  • CentOS:yum install -y libuuid-devel
  • Ubuntu:apt-get install -y uuid-dev

其实源码方式编译 APR,最烦的就是这种“配置通过了,结果 make 时炸了”的情况,缺乏经验的容易在这里懵。

还有一个高频报错:

error: libtool: link: cannot find the library `-lrt` or `-lpthread`

这个通常不是缺库,而是工具链没装全。把 gcc、g++、make、libtool、autoconf 这些全装上,一般能解决。另外有些老教程会让你加LDFLAGS=-lrt来硬编,但那是治标不治本。

操作心得:在编译 APR 之前,先跑一句ldconfig -p | grep -E "libuuid|libcrypto|libexpat",大概扫一眼系统里有没有这些常用依赖库。缺啥提前补上,比等 configure 报错再回来查效率高得多。

4.3 步骤三:配置 httpd 并处理后续连环报错

当你顺利把 APR、APR-util、PCRE 都编译安装好,进入 httpd 的./configure时,可能还会遇到一个新的经典报错:

configure: error: Could not find a version of the library libpcre

明明刚才不是编译了 pcre2 吗,怎么还找不到?

原因很简单:httpd 某些老版本用的是 PCRE1,不是 PCRE2。如果你编译的是 PCRE2,但 configure 脚本还停留在找 PCRE1 的阶段,它自然搜不到。

解决办法有两条:

  1. 下载 PCRE1 的最终版本pcre-8.45.tar.gz,传进系统里编译安装,再通过--with-pcre=/usr/local/pcre指定路径;
  2. 或者用比较新、支持 PCRE2 的 httpd 版本源码(httpd 2.4.58 之后对 PCRE2 友好很多)。

我当时在老版本 httpd 上被这个问题卡了一个多小时,后来干脆换了新版本源码,同时换 pcre2 编译,一路畅通。所以给大家的建议是:源码编译时,版本组合是重中之重,别老想着用老掉牙的 httpd 配新依赖库。

4.4 自定义路径场景下的环境变量配置

如果你把 APR 装在/usr/local/apr,配置完 httpd 是没问题了,但运行 httpd 的时候可能出幺蛾子,因为它运行时需要找到libapr-1.so.0这个动态库。而系统默认的库搜索路径里往往没有/usr/local/apr/lib,于是你会看到:

error while loading shared libraries: libapr-1.so.0: cannot open shared object file: No such file or directory

这个问题的本质是动态链接器找不到共享库。解决办法:

echo "/usr/local/apr/lib" > /etc/ld.so.conf.d/apr.conf ldconfig

ldconfig会重新生成/etc/ld.so.cache,让系统以新路径查找共享库。这一步非常容易忘,一旦忘了,前面所有编译的喜悦都会在启动 httpd 时被兜头浇灭。

5. 从“装好依赖”到“真正编译成功”的关键细节

5.1 configure 到底在检查什么

很多人对 configure 的印象就是“一条命令,运行完就完事”,其实它在背后做了大量探测工作。当你执行./configure --prefix=/usr/local/httpd时,它执行了以下几个与 APR 相关的核心检查:

  • 查找指定路径下的apr-config脚本;
  • 执行apr-config --version来验证版本号;
  • 执行apr-config --cppflags --ldflags --libs来获取编译参数;
  • 尝试编译一个小的可执行文件,链接 APR 库,验证编译链路的可行性。

如果上面任何一步失败,configure 就会给出那个经典的“APR not found”。

理解了这个流程后,你就知道:它说 not found,很可能不是文件不存在,而是你在源码编译时没有把自定义路径传给它。因为默认搜索路径里根本没有/usr/local/apr/bin

所以,如果你用--with-apr传参之后还是报错,可以手动跑一下:

/usr/local/apr/bin/apr-config --version

看看这个命令能不能正常输出版本号。如果没有输出或者提示找不到命令,那说明你的 APR 编译安装过程本身就有问题。

5.2 从源码包还是从开发包安装,二者差异很大

不少新手会把apache2-devhttpd-develapr-devel这几个包搞混。它们有的是 Apache 本体,有的是 Apache 的配套开发包,有的是 APR 的开发头文件包。

在 Debian/Ubuntu 系统上,如果你执行:

apt-get install -y apache2

那只是安装了 Apache 运行环境,并不一定会把libapr1-dev装进来,所以当你再去用源码编译另一个 httpd 时,还是可能遇到“APR not found”。

正确的做法是用apt-cache search apr看看有哪些包可用,然后安装对应的 dev 版本:

apt-cache search apr | grep -i dev

这相当于在“阅兵”一样,先看看仓库里有哪些兵种,再决定派哪支部队上。

5.3 版本匹配问题:新 httpd 配老 APR 的隐性风险

假设你系统自带的 APR 是 1.6.5 版本,而 httpd 是 2.4.62 最新版。理论上没问题,因为 httpd 2.4.x 本来就要求 APR 1.6+。但如果你用的是 APR 1.4.x,那么很多新特性就不支持,configure 阶段也可能直接报错。

这里给一张对照表,方便大家参考:

httpd 版本最低 APR 版本最低 APR-util 版本最低 PCRE 版本
httpd 2.2.xAPR 1.2APR-util 1.2PCRE 6.0
httpd 2.4.xAPR 1.5APR-util 1.5PCRE 8.0(推荐 8.40+)
httpd 2.4.58+APR 1.6APR-util 1.6PCRE2(支持但有时需配置)

不要小看这个表,很多生产环境里“明明按教程做却失败”的怪现象,最终排查下来都是版本之间差了一截。

6. 所有踩过的坑:常见问题排查速查表

收集我及身边同事在 Apache 编译安装过程中经常遇到的典型问题,整理成一个速查表。

问题一:执行 configure 直接报 APR not found

  • 原因 1:系统里压根没装 APR。解决:用包管理器安装,或源码编译。
  • 原因 2:装了 APR 但未安装开发包(-devel / -dev)。解决:补装对应 dev 包。
  • 原因 3:APR 装在了非默认路径。解决:给 configure 传--with-apr参数。
  • 原因 4:APR 版本过低。解决:升级到 httpd 要求的版本。

问题二:configure 提示 APR-util not found

  • 原因:APR-util 缺失或路径不对。解决:参考上文路线一或路线二,在安装 APR 之后安装 APR-util。注意 APR-util 编译时需要--with-apr指定 APR 路径。

问题三:configure 提示 pcre-config for libpcre not found

  • 原因:PCRE 开发库缺失。解决:安装pcre-devel/libpcre3-dev,或手动编译 PCRE 后通过--with-pcre指定路径。
  • 注意事项:如果你安装的是 PCRE2,但 configure 还在找pcre-config(PCRE1 的命令),可以先建一个软链接:
ln -s /usr/local/pcre2/bin/pcre2-config /usr/local/bin/pcre-config

但这不是长久之计,最好还是让 httpd 版本匹配 PCRE 版本。

问题四:make 时报错找不到头文件

  • 原因:比如apr.h找不到。这一般是在编译 httpd 时,APR 的头文件路径没有传递进去。
  • 解决:确认--with-apr参数指向的目录里存在include/apr-1/apr.h,然后用下面的方式把 CPPFLAGS 传给 configure:
CPPFLAGS="-I/usr/local/apr/include/apr-1" ./configure --with-apr=/usr/local/apr ...

问题五:make install 成功但启动时报错缺少动态库

  • 原因:动态库路径不在系统搜索范围内。
  • 解决:参考 4.4 节,修改/etc/ld.so.conf.d/下配置文件并执行ldconfig

问题六:编译过程中报libtool相关错误

  • 原因:系统的 libtool 版本太老或没装。
  • 解决:CentOS 下yum install -y libtool;Ubuntu 下apt-get install -y libtool-bin。如果还不行,建议源码编译安装新版 libtool。

这张表建议收藏,遇到问题不要慌,从上到下排查一遍基本能搞定。

7. 这套报错里藏着的 Linux 底层逻辑,值得你多读两遍

7.1 动态链接、头文件、开发包,三者是老三样

这个 APR not found 的报错,看起来只是一个小问题,但它内部把 Linux 开发环境里几个最基础的概念串联了起来:

  • 头文件(headers):编译 C 代码时,编译器需要看函数的声明。APR 提供了比如apr_file_open这种函数的声明,就放在apr_file_io.h里。没有头文件,编译器直接报“隐式声明”或找不到定义。
  • 动态链接库(shared libraries):程序运行时,需要通过dlopen或动态链接器加载.so文件。Linux 系统里运行时代码会从/usr/lib/usr/lib64/usr/local/lib等路径去搜索。
  • 开发包(-devel / -dev):把上面两样打包发布的一个规范。普通运行包只放.so,开发包会额外放头文件和.so的符号链接文件(比如libapr-1.so -> libapr-1.so.0.7.0)。

理解这老三样之后,很多 Linux 下的编译报错你都能一眼看穿:是找不到头文件、找不到库文件,还是找不到符号。而不是每次都去复制粘贴报错到搜索引擎里。

7.2 预处理、编译、链接:编译期和运行期为什么要分开看

一个 C 程序从源码到可执行文件,要经过预处理、编译、汇编、链接几个阶段。configure阶段的检查大多发生在编译早期和链接阶段

  • 如果报错是fatal error: apr.h: No such file or directory,那是编译器没找到头文件;
  • 如果报错是cannot find -lapr-1,那是链接器没找到库文件;
  • 如果报错是编译都通过但运行时提示找不到.so,那是动态加载器没找到共享库。

这三个报错看起来很像,但解决思路完全不同。能不能分清楚,基本就界定了“会写代码的人”和“只会抄命令的人”。

回到 APR not found 这个报错,它就是链接 / 配置阶段出了问题,比编译阶段报错要更厚重一点,因为它往往是因为缺少依赖项而不是因为你的代码写错了。

7.3 为什么源码编译的软件难以卸载干净

最后再聊一个源码编译的痛点:卸载难。如果你是用yum install apr-devel装的依赖,卸载时你只要:

yum remove apr-devel

但如果你是自己编译安装到/usr/local/apr的,卸载时通常只能:

rm -rf /usr/local/apr

外加清理一下/etc/ld.so.conf.d/里的配置。更麻烦的是,如果当时有别的软件链到了这份 APR 上,那它也会跟着出问题。所以生产环境里,我还是推荐:

  1. 优先用发行版包管理器装依赖;
  2. 如果必须自己编,就把它单独放到独立目录,并在文档里记录清楚;
  3. 千万别图省事把所有东西装到/usr/local/lib大杂烩目录里,管理会非常混乱。

8. 最后再分享两个小实操建议

关于这个 APR not found 报错,最后再补充两个我个人比较受用的习惯。

第一个是,在 configure 之前先加载环境变量。如果你已经把 APR 装到了自定义目录,与其每次命令里长长地传一堆--with-apr--with-pcre,不如把这些路径统一整理成一个环境变量脚本httpd_env.sh

export APR_HOME=/usr/local/apr export APR_UTIL_HOME=/usr/local/apr-util export PCRE_HOME=/usr/local/pcre2 export LD_LIBRARY_PATH=$APR_HOME/lib:$APR_UTIL_HOME/lib:$PCRE_HOME/lib:$LD_LIBRARY_PATH export CFLAGS="-I$APR_HOME/include/apr-1 -I$PCRE_HOME/include" export LDFLAGS="-L$APR_HOME/lib -L$PCRE_HOME/lib"

然后每次编译之前:

source httpd_env.sh

这样能避免你每敲一遍 configure 都要数一下到底漏了哪个参数。特别是后期还要给 httpd 添加模块,重新执行 configure 时,这个环境变量脚本能帮你避开很多参数拼写错误。

第二个是,测试阶段优先用默认安装路径跑通整个流程。很多初学者一上来就自定义--prefix=/usr/local/httpd-custom,导致后续日志路径、配置路径全都跟默认的不一样,排查问题时经常分不清到底用的是哪套配置。先让整个源码编译流程用默认路径完整走一遍,确认没问题之后,再按业务需求做自定义调整,这样排错时至少能确定问题一定在你自定义的那部分里,而不会怀疑到底是不是编译流程本身有问题。

Apache httpd 编译安装虽然只是一个入门级的技能点,但围绕它展开的动态库、头文件、编译链路、版本兼容性这些知识,在很多其他软件安装场景里都能复用,算是花一份时间,武装一套底层思维吧。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询