资讯动态

源码编译完全指南:从环境准备到定制修改与避坑排查

发布时间:2026/10/15 16:06:56 来源:尧图企业网站定制
很多人觉得源码编译是件麻烦事环境配半天依赖缺这个缺那个编译又报错折腾一晚上连个可执行文件都没见着。但如果你有定制需求——比如想给某个开源项目加上自己需要的功能、裁剪掉用不到的模块、针对特定CPU做指令集优化或者单纯想把项目的源码彻底读一遍然后按自己的理解改造——那源码编译这门手艺绕不开。这篇文章把源码从拉取到定制落地的完整链路拆开讲包括为什么要自己编译、编译前怎么准备环境、configure和CMake阶段到底在干什么、源码定制从哪下手以及一整套踩坑排查方法。我尽量不写成教材而是按我实际动手的习惯来写。如果你手里正好有一个开源项目想改成自己的形状照着这篇文章走比漫无目的地搜一堆零散教程要省时间得多。1. 为什么非要自己编译源码先把底层逻辑理清楚1.1 预编译包和源码包差的不是几步命令现在大多数软件都提供了预编译好的安装包无论是Linux的apt、yum还是Windows下的安装程序基本都是解压即用。既然这么方便为什么还要自己搞源码编译关键就落在“定制”这两个字上。预编译包是在某台通用构建机上生成的它面对的是最大公约数的运行环境。CPU指令集只能取最保守的x86-64基线不会给你开AVX2库的依赖版本是编译时锁定的你系统里那个新版动态库可能ABI不兼容跑起来直接报错功能更是全量编译想砍掉用不上的模块在发行版包里基本没戏。源码包则完全不同。你拿到的是项目最原始的形态所有编译开关都在你手里攒着想开哪个功能编译哪个模块完全自己说了算。你可以用-marchnative让编译器针对你本机的CPU生成最激进的指令集也可以把不需要的特性通过配置项关掉把最终产物体积控制到极致。说白了预编译包是标准套餐源码编译是自己下厨味道和用料都归你管。1.2 需要源码编译的典型场景在实际项目里需要动源码编译的场景其实特别集中基本逃不出下面这几类第一类是性能敏感场景。同样的代码编译器知道目标CPU支持什么指令和不知道完全是两码事。比如做视频处理、科学计算、数据库内核这类项目用发行版自带的二进制包和你用-O2 -marchnative -flto编出来的二进制在矩阵运算、SIMD优化上的差距能达到百分之二三十这绝对不是玄学。第二类是平台适配。某些开源项目官方只发布x86_64的二进制但你的目标环境是ARM、RISC-V或者某个老旧的嵌入式平台这时候不自己编译就无解。交叉编译工具链一遍遍地调最终让代码在目标板上跑起来这个过程没有源码在手完全不可能。第三类是功能裁剪。很多开源项目功能全面但你只需要其中一小块。比如一个HTTP服务器库你只用它的静态文件服务WebSocket、TLS代理这些模块就可以直接关掉编译产物从几十MB缩减到几MB安全攻击面也小了。第四类是安全审计。这个容易被忽略——你手上跑的二进制是从源码编译出来的还是从某个渠道下载的来路不明的包这在安全性上是两种完全不同的信任级别。源码编译意味着你能审计每一行进入最终产物的代码自己掌控供应链。1.3 源码到可执行文件的完整链路预处理、编译、汇编、链接自己动手之前至少得知道编译器在背后做了哪几步。拿C/C来说从.c文件到可执行文件中间隔着四道工序。预处理阶段处理#include、#define、条件编译这些指令把头文件内容真正插入到源码里展开所有宏。编译阶段把预处理后的代码翻译成汇编代码这是最核心的一步优化基本都发生在这里。汇编阶段把汇编代码编译成机器码生成目标文件.o或.obj。链接阶段把多个目标文件以及静态库、动态库“缝合”在一起处理符号引用最终生成可执行文件。如果你不幸遇到过undefined reference to这种报错那九成是死在链接阶段。理解这四个阶段之后很多编译报错你一眼就能判断问题出在哪一步排查效率完全不一样。我用一个最简单的生活化类比预处理像是把菜谱里所有引用的配方卡片抽出来放到眼前编译像是按配方把食材切成丁、切成丝汇编是摆盘拼好链接则是把每一盘菜拼成一桌完整的宴席少一道菜或者端错了盘宴会就砸了。2. 编译前的准备工作环境不整干净后面全是坑2.1 工具链选型编译器与构建系统怎么搭工具链由两部分组成编译器负责把代码变成机器码构建系统负责调度编译过程。我见过很多新手上来就闷头敲make环境里连编译器都没有或者装了一堆乱七八糟的依赖最后编译失败都分不清是工具问题还是代码问题所以先把这两层理清楚。编译器这个层面开源世界主流就是GCC和Clang/LLVM。GCC历史长、兼容性好很多老项目对它的支持最成熟Clang报错信息更友好、编译速度普遍更快而且在静态分析上更有优势。Windows上还有MSVC但如果你是交叉平台项目建议优先跑通GCC或Clang随后再适配MSVC不要一上来就三线并进。构建系统这个层面常见的组合有两套。老牌组合是configure脚本加Makefile这类项目历史包袱重但你接触的开源老项目大概率长这样。现代组合是CMake加Ninja或MakeCMake负责生成构建规则Ninja负责真正执行编译Ninja在并行编译上比Make更聪明明显更快。还有极少数项目用Bazel、Meson这类新构建系统但遇到的概率相对低。我的建议很直接看项目官方用什么构建系统就用什么不要自己换。项目提供的CMakeLists.txt和你手动写的Makefile在选项处理、依赖检测上有千丝万缕的联系贸然替换等于给自己加难度。2.2 依赖处理读懂项目的依赖声明源码编译一大半的崩溃现场都发生在依赖阶段头文件找不到、库版本不对、系统里有多个库互相打架这类问题几乎人人都会遇到。想避开你得先会读项目的依赖声明。在configure为骨架的项目里有一个configure.ac或configure.in文件里面会写清楚需要哪些库、版本下限是多少、哪些功能是可选的。如果项目用了pkg-config你可以通过pkg-config --list-all | grep 关键字快速确认某个库有没有装、装在哪个路径。pkg-config --cflags --libs 库名可以直接看到编译这个库需要的头文件路径和链接参数这个工具真的能救大命。在CMake项目里信息主要看CMakeLists.txt开头的find_package指令。比如find_package(OpenSSL REQUIRED)表示必须要OpenSSL后面跟OPTIONAL表示有这个库就启用相关功能没有就跳过。你在配置阶段看到Could NOT find xxx的提示大概率就是这些依赖没装齐。依赖处理的核心窍门其实是记录和拆解。每拉一个项目先建一个文本文件记录它的依赖清单然后按清单装依赖每装完一个就重新跑一次配置阶段确认这个依赖被正确识别。别一次性装一堆库否则出问题了你根本不知道是哪一个引入了冲突。装依赖的时候优先用系统包管理器比如apt install libxxx-dev因为系统源的库版本和你操作系统的ABI是匹配的自定义编译第三方库容易把自己绕进去。提示很多发行版分成库名和库名-dev两个包编译时要装的是带-dev或-devel后缀的那个里面才有头文件和未strip的库。只装运行库编译时会告诉你头文件找不到。2.3 环境变量、安装前缀和目录规划讲环境之前先说一个概念安装前缀prefix。它决定最终的可执行文件、库文件、头文件、配置文件安装到什么目录。默认情况下很多项目会安装到/usr/local但你未必有写权限也未必想把一个自行编译的软件混进系统路径。我推荐的做法是统一规划一个源码构建目录比如~/opt或者/opt/projectx给不同项目建独立子目录安装前缀用--prefix$HOME/opt/projectx-a或-DCMAKE_INSTALL_PREFIX$HOME/opt/projectx-a。这样每个自定义编译的软件都独立、可卸载、不污染系统以后想清理直接删对应目录就行。环境变量方面最常用的是CC、CXX、CFLAGS、CXXFLAGS和LDFLAGS。CC和CXX指定用哪个编译器CFLAGS和CXXFLAGS指定编译选项LDFLAGS指定链接选项。跨平台交叉编译的时候还会用到--host和--build参数不过在文章后面我会专门讲交叉编译这里先说原生编译。我强烈建议在编译之前先把编译选项和环境变量记录下来写成一个shell脚本或环境配置文件。比如export CC/usr/bin/gcc export CXX/usr/bin/g export CFLAGS-O2 -marchnative export CXXFLAGS-O2 -marchnative -stdc17这样不仅可复现你还能在排查问题时知道“我这个二进制到底是怎么编出来的”。很多人编译一次成功后就忘了当时的配置等半年后想加个功能重新编完全忘了当初开过哪些选项这是非常让人崩溃的一件事。3. 完整编译实操从源码拉取到可执行文件落地3.1 获取源码、校验完整性、选择正确的版本源码获取一般是两种途径从版本控制仓库克隆或者下载官方发布的源码压缩包。开发阶段想跟进最新改动用git clone拉主分支生产或稳定环境强烈建议下载带版本号的Release源码包不要用git主干代码编生产环境主干随时可能处于半坏状态。拿到源码包后先做一步很多人忽视的校验。官方Release页面一般会提供SHA256或GPG签名用sha256sum比对一下哈希值防止下载过程中文件损坏或被人篡改。我见过有人在下载了一个坏包后折腾一下午最后发现是包本身不完整这种时间浪费完全没必要。版本选择上有个原则不要选太老的版本太老版本可能在新编译器上编译报错需要打一堆补丁也不要盲目追求最新最新版本可能有未暴露的兼容性问题。选择标准是项目维护者明确标注为稳定版的最近一个发布版同时留意它的依赖要求是否符合你当前的系统环境。3.2 configure阶段这一层到底在做什么很多初学者觉得configure就是一条固定命令跑就完了。其实configure的核心工作是探测环境、生成配置头文件和Makefile。它会检查你系统里有没有某个函数、某个头文件、某个库然后把检测结果写进生成的头文件比如config.h和Makefile里后续编译阶段才真正有据可依。configure类项目的标准三步是./configure --prefix/your/prefix --enable-opt --disable-feature make make installconfigure的选项可以用./configure --help查看里面会把所有功能和开关列出来包括--enable-xxx、--disable-xxx、--with-xxx、--without-xxx等。我的习惯是先把--help输出保存到文件里然后逐项扫一遍把需要开的开关先写进笔记最后再跑正式配置。因为configure脚本执行一次要一会儿反复改参数反复跑非常消耗耐性和时间。CMake项目在配置阶段用的是cmake命令不是configure脚本。一个典型的配置命令长这样cmake -S . -B build -DCMAKE_BUILD_TYPERelease \ -DCMAKE_INSTALL_PREFIX/your/prefix \ -DENABLE_EXTRA_PLUGINON \ -DBUILD_SHARED_LIBSOFF-S指定源码目录-B指定构建目录-D传入配置变量。特别注意-B build这个习惯它把构建产物和源码目录分开不会在源码目录里生出一堆.o文件这也是CMake推荐的方式。很多人图省事在源码目录内直接cmake会把项目目录搞得乱七八糟后续想清理也不知道删什么。配置阶段如果成功CMake会打印出完整的配置摘要比如哪些功能ON、哪些功能OFF、依赖库是哪个版本。这个摘要我建议截图或保存下来它是你排查后面编译问题的重要依据。3.3 编译阶段make和ninja的正确用法配置完成之后才是真正吃CPU的阶段。configure类项目用make -j$(nproc)-j参数指定并行编译的任务数$(nproc)自动获取CPU核心数。比如一个8核CPU-j8会把8个编译任务扔出去并行跑。很多人图快直接-j$(nproc)或者-j16但要注意内存每个编译任务可能要吃掉几百MB甚至几个GB内存如果CPU核心多但内存小并行任务一多系统直接卡死。我在本机8核16GB内存上编过一个大项目-j8没问题但有个同事在16核32GB上同样项目跑到链接阶段内存吃紧最后降到-j6才稳。编译阶段就是CPU和内存的平衡游戏。CMake项目如果生成的是Makefile同样用make -j如果生成的是Ninja用ninja。Ninja本身会合理利用并行性不需要额外指定-j也能跑满。你要观察编译进度可以在CMake项目里把默认构建系统改成-G NinjaNinja的输出更清爽进度条也更直观。编译过程如果遇到报错不要慌着清屏重来。先往上翻日志找到第一个error:开头的行。编译错误一般会带文件名和行号比如/path/to/src/main.cpp:42:10: fatal error: xxx.h: No such file or directory这个信息告诉你两件事哪个文件、缺什么东西。缺头文件一般是依赖没装或者-I路径没配好如果是语法错误看看是不是编译器版本和代码要求的C标准不匹配。解决一个错误后就重新跑编译因为很多后续错误是由第一个错误引发的解决第一性错误往往后面一排报错自己就消失了。3.4 安装、卸载与产物打包编译成功后安装阶段要做的事情是make install如果你是普通用户前缀指定到~/opt下没有任何问题如果指定到系统目录可能需要sudo。安装完以后可以用find /your/prefix -type f | head -50看看到底装了哪些文件确认一下有没有遗漏。卸载的方式很简单如果你还在源码目录里make uninstall通常能搞定。但如果你已经清理了源码目录或者项目不提供uninstall目标那只能手动删文件。这也是我喜欢指定独立prefix的原因直接rm -rf /your/prefix/projectx-a就全部清掉了系统一点残留没有。如果编译的产物要分发给多台机器我不建议直接拷贝文件夹。更稳的方式是用打包工具把安装产物打包成deb或rpm比如checkinstall它可以在make install的时候捕获所有安装到系统里的文件清单然后生成一个安装包。这样在其他机器上可以用统一的包管理器安装和卸载可维护性好得多。DESTDIR方式也常用就是make install DESTDIR/tmp/staging这样会把所有文件装到/tmp/staging/your/prefix下你再进入/tmp/staging把整个目录打包分发之后用户解包到根目录即可。这种手法在做交付部署时很实用。4. 定制化修改源码从功能开关到打补丁的完整路径4.1 先看懂项目结构再动手改码定制化修改源码最忌讳的就是一上来就找某个文件开改。我理解那种想快速看到效果的心情但你不了解项目整体的模块划分和编译组织方式改出来的东西多半要么编不过要么编译过了但运行时不生效甚至把整个项目搞崩溃。拿到一个项目后先花半小时看目录结构和构建脚本。重点看这几样源码目录的顶层布局比如src/、lib/、include/、tests/分别放什么入口函数在哪main函数或初始化函数在哪个文件里配置文件怎么读默认配置是硬编码在代码里还是从外部文件加载。这些信息在项目根目录的README、ARCHITECTURE、docs/目录里通常有描述如果没有就结合构建脚本和头文件去猜。看构建脚本这里configure项目要看Makefile.am或Makefile.inCMake项目要看CMakeLists.txt。这些文件里能看到每个源文件被编进哪个目标、哪些宏被定义、哪些是公共头文件的安装路径。你改了代码以后要能判断出“我改的这个源文件会被编进哪部分产物”这个对应关系非常重要。4.2 功能开关、编译宏和配置文件的定制点定制化改造一般从三个层面下手难度递增我强烈建议按下面这个顺序来。第一个层面是功能开关。多数成熟的CMake项目都暴露了大量配置变量你在cmake -D阶段就能克制地打开或关闭功能。这是侵入性最小的修改方式也是优先考虑的方式。你不需要改一行代码只需要在配置阶段把-DENABLE_XXXON或-DDISABLE_YYYON传进去。对应到configure类项目就是--enable-xxx或--disable-yyy。前提是你知道项目有哪些开关同样靠--help或CMakeCache。第二个层面是编译宏。项目代码里大量使用条件编译比如#ifdef PROJECTX_ENABLE_ADVANCED_MODE // 高级模式代码 #endif如果你想让这段默认被跳过的代码编译进来可以在配置阶段用-DCMAKE_CXX_FLAGS-DPROJECTX_ENABLE_ADVANCED_MODE加编译宏或者在CMake项目中直接target_compile_definitions加私有宏。这种方式比改源码温和得多因为你没有动现有代码逻辑只是影响了编译器视角。第三个层面才是真正修改源码比如改默认参数、修改启动逻辑、替换某个模块的实现。这个侵入性最大也最容易在项目升级时产生冲突。改源码前一定要想清楚这个改动能不能通过配置和宏解决如果必须改源码也要把改动点控制在最小范围不要顺手把排版也改了不然后面看diff你根本分不清哪些是逻辑修改哪些是无关变动。注意无论哪个层面定制之前先确认项目的许可证允许你做修改。开源许可证对源代码修改和分发有不同的要求比如有些是传染型License有些是宽松型提前确认能避免后续麻烦。4.3 补丁管理让定制在项目升级后还能活下去源码定制最棘手的问题不是怎么改而是改了之后怎么办。项目发布了新版本你改过的代码可能和新代码冲突怎么把定制在新版本上重新打上这是很多人的噩梦。我的做法是严格遵循“补丁化”管理。源码仓库保持和上游一致不直接在上面改代码。有效路径是这样的从上游拉一个干净分支新建一个专门放定制的分支在定制分支上做一些修改然后把修改生成一个或一系列补丁文件用git format-patch或git diff导出项目升级新版本后在新版本代码上重新应用补丁。用git format-patch的好处是它保留提交信息应用和回溯都比较方便。格式大致像是git checkout -b custom-branch upstream/main # 做修改并提交 git format-patch upstream/main -o /path/to/patches/在新版本上重放时理论上逐个应用git apply就能生效。如果新版代码有了变动某个补丁打不上git apply会提示冲突位置这时候你逐个解决冲突就好不会出现“不知道改了哪里”的窘境。如果不想用git管理补丁也可以用quilt这类传统补丁管理工具它把补丁栈管理得比较清晰适合没有git参与的古老项目。但我的经验是现代项目git的format-patch机制已经够用没有必要引入额外工具。关键是从一开始就养成“修改不等于直接改源码而是改完后导出补丁”的习惯。哪怕你只做一次性定制这个习惯也能让你在踩坑后回退到稳定状态。4.4 一个定制实例给某开源项目加一个默认配置项我举一个稍微具体的例子帮你把前面几个方法串起来。假设有一个开源项目X它的行为由一个配置文件控制默认配置是编译时生成的你希望把某个默认超时时间从30秒改成60秒。按我前面的顺序先看项目有没有暴露配置项。如果CMake配置里有-DPROJECTX_DEFAULT_TIMEOUT30那直接在配置阶段传值就行一行代码都不用改。如果没有就看超时时间的默认值定义在哪个头文件里可能是一个#define DEFAULT_TIMEOUT 30这时可以用编译宏覆盖cmake -S . -B build -DCMAKE_CXX_FLAGS-DPROJECTX_DEFAULT_TIMEOUT60 ...如果连宏覆盖都不支持因为代码可能把路径写死在了某个配置文件的生成逻辑里那只能改源码。改的方式是找到生成默认配置的代码把硬编码的30改成读环境变量或预定义宏。举个例子// 原代码 config.timeout 30; // 定制后 #ifndef PROJECTX_DEFAULT_TIMEOUT #define PROJECTX_DEFAULT_TIMEOUT 30 #endif config.timeout PROJECTX_DEFAULT_TIMEOUT;这样改完之后你不但实现了定制还为项目贡献了一个新的配置入口未来其他人通过编译宏就能改超时时间而不用再改代码。这就是定制和反哺的双赢做法。改完之后用git format-patch导出补丁放在你的补丁目录里后续项目升级你也能快速重放这个定制。5. 编译报错排查与避坑手册5.1 高频错误类型一眼定位问题源头源码编译报错翻来覆去就那么几类我见过的踩坑经验基本都能归进下面这个表格。错误类型典型报错特征核心原因优先排查方向头文件缺失fatal error: xxx.h: No such file or directory依赖库没装开发包用apt install libxxx-dev或检查CPLUS_INCLUDE_PATH库找不到cannot find -lxxx库文件路径未识别检查LDFLAGS和LIBRARY_PATH确认库是否编译为.a/.so未定义引用undefined reference to xxx链接时缺少目标文件或库顺序不对检查库链接顺序把静态库放在对象文件后面语法错误error: xxxx was not declared in this scope编译器标准太老或依赖冲突切换C标准检查宏定义冲突配置失败configure: error: *** is required某个依赖缺失或版本过低查看错误信息中的库名装对应开发包内存耗尽internal compiler error: Killed并行任务太多降低-j数量或加swap冲突的宏定义error: redefinition of ...不同库头文件宏冲突检查编译命令行里的-D精简多余宏头文件缺失是最常见的问题解决思路很直接根据报错里的头文件名反查它属于哪个库。用apt-file search xxx.h前提是你装了apt-file可以快速定位。库找不到的时候注意一个细节动态库的后缀是.so静态库是.a-lxxx去找的可能是libxxx.so或libxxx.a如果两者都不存在就会报错。有些时候库装在非标准路径比如/usr/local/libGCC默认不搜这里你需要用环境变量或在配置阶段通过--with-xxx/usr/local指定。未定义引用这个问题比较有意思很多新手一看到就慌。实际上它经常不是什么大问题而是链接顺序不对在GCC的链接命令里静态库要放在引用它的目标文件之后因为链接器是顺序扫描的。这个顺序错误在你用命令手动链接时特别常见CMake和Makefile一般会处理妥当但你手写编译命令时要注意。5.2 排查流程从日志到最小复现遇到编译问题我的排查流程固定死了按这个顺序走效率很高。第一步看完整报错日志不是只看屏幕最后几行。重定向到日志文件再搜make -j4 21 | tee build.log grep -n error: build.log | head -20tee会把输出同时打印到屏幕和日志文件后面随便查。很多编译报错是中段出现的回滚屏幕根本看不全日志给了你完整的排查依据。第二步定位第一个错误而不是最后一个错误。编译器在遇到错误后经常产生级联错误后面一串都是假的只有第一个错误是真正的病根。从日志中找最先出现的error:所在位置往前翻几行看上下文通常能看到具体的文件名和行号。第三步搜索报错信息。把错误信息中不含路径和文件名的那句摘出来比如undefined reference to std::thread::join()大部分情况下网上已有大量解决方案。但注意别只盯着搜索结果里给出的某个具体版本号你的环境和别人未必一致理解原因比抄命令更重要。第四步如果实在找不到原因做最小复现。写一个只包含出问题的那几行代码的小文件单独编译它看能否复现报错。如果最小文件编不过说明问题出在代码本身或编译器环境如果最小文件没问题那问题多半出在工程配置和依赖的交互上。这一步能快速聚焦出错的真正层级。5.3 提速与缓存ccache和增量编译源码编译还有一个很实际的问题耗时长。一个大项目全量编译动辄半小时到几个小时如果每次改几行就要全量重编效率太低。所以需要两个提速工具增量编译和编译缓存。增量编译的原理很简单如果源文件没变就没有必要重新编译它对应的.o文件。Make和Ninja天然支持增量编译只要你保持构建目录在改少量代码后重新运行make或ninja编译器只会编译受影响的那部分链接也只在需要时执行。所以千万不要每次编译前都删掉构建目录那是完全的开倒车。ccache则更进一步它是一个编译缓存工具。它会把每次编译的预处理结果和编译产物缓存下来当你清理了构建目录或者在不同分支间切换时只要编译命令和源文件哈希没变它就直接从缓存里提供结果完全不调用编译器。配置非常简单export CCccache gcc export CXXccache g或者CMake项目里cmake -S . -B build -DCMAKE_CXX_COMPILER_LAUNCHERccache用了ccache之后同样的代码在相同编译参数下第二次编译几乎瞬间完成。这种提速对“改几行代码—编一次—看效果”的开发循环来说体验提升是巨大的。在我的实践里ccache把大项目反复编译的耗时能减少七成以上。5.4 几个容易忽略的隐藏坑最后写几个经常让我和同事栽跟头的隐藏坑这些坑不在任何文档里完全靠实际动手踩出来。第一个坑是磁盘空间。编译过程产生的中间文件极其庞大一个大点的项目源码可能就几百MB但完整的构建目录动辄几GB甚至十几GB。编到一半磁盘满了编译直接失败而且这种失败往往没有明确的错误提示你只看到某个写文件的地方失败。建议编译前用df -h看一眼磁盘空间至少要留出源码体积五倍以上的余量。第二个坑是文件系统大小写和符号链接。在Linux上一切正常但如果源码在Windows的NTFS分区通过WSL访问或者构建目录在某种网络文件系统上一些依赖相对路径和符号链接解解析的项目会出现莫名其妙的编译失败。遇到这种问题优先把源码和构建目录放到原生Linux文件系统盘上而不是共享盘或挂载盘。第三个坑是硬编码路径。编译时如果用了-marchnative最终二进制就会绑定在你当前CPU指令集上把这台机器编译的二进制拷贝到别的机器运行可能会报Illegal instruction (core dumped)。这是源码编译最常见的交付陷阱。如果要分发要么不用-marchnative要么用-marchx86-64-v3这类相对通用的指令集级别要么每台目标机器各编一份。第四个坑是构建目录的持久化。很多人编译成功后就把构建目录删了结果过阵子想加个选项重新配置发现整个Makefile和缓存都没了只能从头再来。我建议至少保留CMakeCache.txt或config.status文件因为这两个文件记录了完整的配置参数下次配置时可以直接参考。CMake项目里你甚至可以复制旧的构建目录改名再配置cmake会在原有缓存基础上增量更新能省很多时间。写在最后的一个小技巧源码编译这件事说到底是耐心和细心的事。我见过太多人卡在依赖报错上就放弃了其实绝大多数问题早五分钟看日志就能解决。最后分享一个我个人的习惯每次编译一个陌生项目之前我会先花两分钟把它的构建系统类型、依赖要求、版本号和我的编译选项记在项目目录里的一个BUILD-NOTES.md文件里。三个月后项目升级你再回来想重新编译时翻这个文件比翻聊天记录和模糊的记忆可靠一百倍。编译命令行不必记在脑子里但编译思路和做出的决策值得记下来这条经验帮我省掉了很多重复排查的时间。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑