APR not found报错详解:Apache源码编译依赖配置与解决方案
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 源码包里其实不包含完整的 APRApache 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 的很多模块需要用到它。PCREPerl 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-develDebian / 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.h、apr_pools.h这些。普通的apr包只提供运行时需要的动态库.so不提供开发用的头文件apr-devel才提供头文件和链接时的元数据。提示如果你在最小化安装的 CentOS 环境里yum install可能会提示你“No package apr-devel available”。这种情况十有八九是你没装 EPEL 源或者没启用 BaseOS 源先处理仓库源问题再继续。3.2 路线二源码方式自己编译安装 APR适合离线内网或自定义版本包管理器虽然方便但在某些场景下并不好使服务器在内网没法直接连外网仓库默认仓库里的 APR 版本太老不满足 httpd 要求公司安全规范要求所有软件必须走内部编译发布流程。那就得自己找 APR 源码包来编。官方下载渠道一般是 Apache 软件基金会提供的镜像站比如APR 源码包apr-1.7.x.tar.gzAPR-util 源码包apr-util-1.6.x.tar.gzPCRE 源码包pcre2-10.x.tar.gz新版 httpd 对 pcre2 的支持更好建议直接用 pcre2下载完成之后按顺序编译安装。先说 APRtar -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然后编译 PCRE2tar -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/RHELyum groupinstall Development ToolsUbuntu/Debianapt-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 库。解决办法CentOSyum install -y libuuid-develUbuntuapt-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 的阶段它自然搜不到。解决办法有两条下载 PCRE1 的最终版本pcre-8.45.tar.gz传进系统里编译安装再通过--with-pcre/usr/local/pcre指定路径或者用比较新、支持 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 ldconfigldconfig会重新生成/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-dev、httpd-devel、apr-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.0httpd 2.4.xAPR 1.5APR-util 1.5PCRE 8.0推荐 8.40httpd 2.4.58APR 1.6APR-util 1.6PCRE2支持但有时需配置不要小看这个表很多生产环境里“明明按教程做却失败”的怪现象最终排查下来都是版本之间差了一截。6. 所有踩过的坑常见问题排查速查表收集我及身边同事在 Apache 编译安装过程中经常遇到的典型问题整理成一个速查表。问题一执行 configure 直接报 APR not found原因 1系统里压根没装 APR。解决用包管理器安装或源码编译。原因 2装了 APR 但未安装开发包-devel / -dev。解决补装对应 dev 包。原因 3APR 装在了非默认路径。解决给 configure 传--with-apr参数。原因 4APR 版本过低。解决升级到 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-configPCRE1 的命令可以先建一个软链接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 传给 configureCPPFLAGS-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 libtoolUbuntu 下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 上那它也会跟着出问题。所以生产环境里我还是推荐优先用发行版包管理器装依赖如果必须自己编就把它单独放到独立目录并在文档里记录清楚千万别图省事把所有东西装到/usr/local/lib大杂烩目录里管理会非常混乱。8. 最后再分享两个小实操建议关于这个 APR not found 报错最后再补充两个我个人比较受用的习惯。第一个是在 configure 之前先加载环境变量。如果你已经把 APR 装到了自定义目录与其每次命令里长长地传一堆--with-apr、--with-pcre不如把这些路径统一整理成一个环境变量脚本httpd_env.shexport 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 编译安装虽然只是一个入门级的技能点但围绕它展开的动态库、头文件、编译链路、版本兼容性这些知识在很多其他软件安装场景里都能复用算是花一份时间武装一套底层思维吧。