ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

mongoose-android-x86_64 编译报 PIE?TaoToken 这样让 Codex 改 examples.mk

mongoose-android-x86_64 编译报 PIE?TaoToken 这样让 Codex 改 examples.mk 在编译 mongoose-android-x86 时NDK 提示 only position independent executables (PIE) are supported。这个报错卡了我很久最后是靠着 TaoToken 把 Codex 的 Base URL 指到 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 创建的统一 API 通道上再让 Codex 按 x86_64-4.9 工具链补全 examples.mk 的 CFLAGS 和 LDFLAGS 才解决。整个过程你也能复现先到官网拿 Key配好 Codex把报错贴进去按补丁改完重新 make 就行。写这篇不是让你去翻 Android NDK 的古老文档而是记录一条能落地的排障路径遇到 NDK 参数报错与其自己逐行猜 Makefile不如让 Codex 直接看报错和文件同时把模型通道稳定下来。1. 先把现场摆出来examples.mk 里的 PIE 报错1.1 NDK 报了什么错在编译 mongoose-android-x86 的 example 程序时NDK 的 x86_64-4.9 工具链直接抛出一句 only position independent executables (PIE) are supportedmake 当场停住。这个错误在 Android 6.0 之后的 NDK 环境里几乎是必现的它不是一个普通警告而是平台对可执行文件格式的硬性要求从 Android 5.0 开始系统不再加载非 PIE 的可执行文件NDK 的链接器一旦发现目标文件不满足 PIE 条件就会直接拒绝生成产物。所以你会看到 make 在执行到编译或链接那一步时戛然而止后面的一堆规则全都不会继续跑。PIE 报错通常有两种形态。编译阶段如果 CFLAGS 里没有-fPIE会提示(-fPIE)链接阶段如果 LDFLAGS 里没有-pie会提示(-pie)。你看到的可能是其中一句也可能两句先后出现这取决于 Makefile 是先编译还是先链接。原文的 examples.mk 里恰好把这两句注释都留在了对应位置像是原作者给后来人留的线索。顺着那两行注释往下看就能定位到 CFLAGS 和 LDFLAGS 两个变量。1.2 examples.mk 里缺了哪两个参数mongoose-android-x86 的 example 程序共用一份 examples.mk。默认情况下CFLAGS 只有-g -W -Wall这类常规选项附带-I../..和-Wno-unused-function里面没有任何与 PIE 相关的参数。LDFLAGS 也只有一行-Wl,-rpath-link指向 sysroot 的库目录同样没有 PIE 相关参数。两个变量正好各缺一个开关CFLAGS 里少-fPIELDFLAGS 里少-fPIE -pie。这里容易犯迷糊的地方是很多人只给编译参数加了-fPIE以为链接参数不用管结果 make 在最后链接时报第二句错误白白浪费一轮等待。这个问题的麻烦之处在于工程本身是可以编出 x86_64 版本的模拟器上也跑过但 NDK 版本一换链接策略跟着收紧老参数就不够用了。所以修复思路不是升级 NDK也不是换编译器而是在 examples.mk 的编译和链接两条参数链上各补一个开关。如果你只是想临时绕过可以在 make 命令后面手动传CFLAGS-fPIE LDFLAGS-pie但每换一个 example 目录就得重来一次而且不同 example 的 Makefile 还不一定都接受外部传参。最干净的做法是把参数写进 examples.mk让make一次通过。1.3 为什么把这件事交给 CodexCodex 在处理「已知报错 已知 Makefile」的场景时最大的优势是能同时看到报错、工具链版本和文件内容然后对照平台文档生成最小补丁。你不需要花十分钟教它什么是 PIE它自己能从前面的报错文本里推断出缺的是-fPIE和-pie。但要让 Codex 跑起来得先解决模型 API 的连通问题。我的做法是用 TaoToken 把 Codex 的 Base URL 指到统一 API 通道上这样 Codex 就能稳定调用模型。下面这一节就是配置步骤。2. 用 TaoToken 把 Codex 接到你的环境2.1 官网拿 Key写进 ~/.codex/config.tomlCodex 读取的是用户目录下的~/.codex/config.toml它不认 Claude Code 那套ANTHROPIC_BASE_URL环境变量。所以第一步是打开 TaoToken注册后在控制台创建一个 API Key拿到YOUR_API_KEY。注意这个 Key 不是用来填官网的而是填进 Codex 的 provider 配置里让 Codex 的请求走 TaoToken 的 API 通道。我的~/.codex/config.toml最终长这样model 你的模型ID # 以 TaoToken 模型广场为准 model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key YOUR_API_KEY wire_api chat这里base_url是接口地址必须写成https://taotoken.net/api末尾不要加/v1。配置文件里的env_key指的是环境变量名你需要把真正的 Key 值导出到环境变量里在终端执行export YOUR_API_KEY粘贴你刚创建的Key官网页面 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 只负责注册、创建 Key、看模型广场和用量和工具里填的 Base URL 是两回事不要把带 UTM 的落地页地址填进任何工具的 base_url 字段。另外env_key这个名字容易让人误以为要在 config.toml 里直接写 Key 原文实际上 Codex 是启动时从这个环境变量读取所以只要 shell 会话里导出了这个变量Codex 就能正常工作。2.2 模型 ID 去模型广场选别自己造我一开始想当然填了一个自己听过的模型 IDCodex 启动后直接报 model not found。后来去 TaoToken 的模型广场就在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 上看了一眼才发现模型 ID 和我预想的不一样。所以model字段一定要以模型广场为准不要凭印象写。模型广场同时会标注上下文长度、是否支持工具调用这两个信息会影响 Codex 能否看懂完整的 examples.mk。上下文太短的模型可能只看到片段就给出不完整的补丁选一个上下文足够长的模型更稳妥。配置好之后Codex 就能通过 TaoToken 的兼容通道调用模型了。接下来把编译报错和 examples.mk 贴给它让它干活。3. 让 Codex 改 examples.mk补 -fPIE 和 -pie3.1 给 Codex 的提示词怎么写新开一个 Codex 会话把下面这段提示词贴进去剩下的交给 Codex我在编译 mongoose-android-x86 的 example 程序NDK 是 x86_64-4.9 工具链 SYSROOT 指向 android-23/arch-x86_64。 编译报错only position independent executables (PIE) are supported. (-fPIE / -pie) 这是 examples/examples.mk 里的相关片段 CFLAGS 里只有 -g -W -Wall 以及 -I../..、-Wno-unused-function LDFLAGS 里只有 -Wl,-rpath-link$(SYSROOT)/usr/lib 请只修改这两个变量补全 PIE 相关参数保持其他编译选项不变并输出 diff。这样写的好处是给 Codex 限定了边界只补-fPIE和-pie不要顺手动-O2或者加别的库。Codex 给出的结果基本就是原文注释里那两行参数的还原但它会把参数放进对应变量而不是让你自己猜位置。如果你不限定边界它有时会顺手做点“优化”比如把-Wall换成-Wextra虽然也能编过但会给后续对比带来噪音。3.2 CFLAGS 的改法Codex 给出的 CFLAGS 差异很小在原有选项里插入一个-fPIECFLAGS -fPIE实际操作时把它和原有 CFLAGS 合并成一行也可以比如把原来的-g -W -Wall改成-g -W -fPIE -Wall。注意这里用的是-fPIE不是-fPIC。两者都生成位置无关代码但-fPIC一般用于共享库编译可执行文件时用-fPIE更符合平台预期。如果误用-fPIC某些 NDK 版本虽然也能编过但链接时可能出现告警所以按 Codex 的改法最稳。补丁应用到 examples.mk 后可以先用grep -n fPIE examples.mk确认参数已经写进去了再执行 make。3.3 LDFLAGS 的改法LDFLAGS 需要同时补-ldl -fPIE -pieLDFLAGS -ldl -fPIE -pie或者和原来的 rpath-link 写在一起LDFLAGS -Wl,-rpath-link$(SYSROOT)/usr/lib -ldl -fPIE -pie-ldl在某些精简例子里不是必须的但加上不会出错而且能让 mongoose 的dlopen相关功能正常链接。-fPIE在链接阶段同样要出现它不是编译器的专利-pie则明确告诉链接器输出一个 PIE 可执行文件。这两个参数少一个之前的报错就会换着花样回来。Codex 给完 diff 后我不会让它直接去改本机的 examples.mk也不会让它执行 make。它只负责生成补丁真正保存文件、重新编译都在我的终端里操作。AI 工具可以给方案但环境的控制权要留在自己手里。4. 顺手改掉端口和 WebSocket 地址4.1 simplest_web_server.c 的监听端口PIE 参数修好之后原工程还有两个小坑要处理。examples/simplest_web_server/simplest_web_server.c里默认监听端口是 8000。如果希望 Android 浏览器直接访问http://localhost而不带端口可以把这行改成 80static const char *s_http_port 80;这里改不改不影响编译但如果你要部署到真机上通常都会顺手改成 80省得每次敲端口。要注意的是80 端口在 Android 上不一定能直接绑定部分系统的应用进程没有权限监听 1024 以下的端口需要 root 或者换回 8000。所以这个改动要结合你的实际运行环境决定不要因为看到原文改成 80 就盲目照搬。Codex 同样可以直接定位到这个文件里的对应行你只要把文件路径发给它它会告诉你这一行的上下文方便你决定是否改动。4.2 index.html 的 ws 地址examples/websocket_chat/index.html里的 WebSocket 地址默认连的是当前域名下的/ws。如果聊天服务跑在 8000 端口而页面不是从 8000 端口打开的握手会失败所以要把端口显式写出来var ws new WebSocket(ws:// location.host :8000);如果你把 HTTP 服务也改成 80那么这里可以保持/ws不变只要端口不一致就必须显式写清楚。客户端握手失败时通常不会在终端打印日志只会看到页面上的聊天消息发不出去排查起来比 PIE 报错更费劲。这两处改动和 PIE 报错没有直接关系但既然要重新编译一次最好一起改完省得下次又为这一行重新走一遍 make 和 adb push。5. 重新 make 并通过 adb 部署5.1 编译和产物复制改完 examples.mk 和两个源文件后回到终端重新编译。先编 websocket_chat再编 simplest_web_servercd examples/websocket_chat make clean make cd ../simplest_web_server make clean make这里务必执行make clean。如果之前的失败编译留下了目标文件新的-fPIE参数可能不会完整参与链接make 会误以为没有变更而跳过链接步骤。只有 clean 之后重新 make才能确认补丁真的生效了。编译过程中如果看到-fPIE出现在命令行里基本就可以放心了如果依然报错回到第 6 节排查。编译通过后把产物放到共享目录mkdir -p /opt/share-vm/fedora23server-share/webserver cp examples/simplest_web_server/simplest_web_server /opt/share-vm/fedora23server-share/webserver/ cp examples/websocket_chat/websocket_chat /opt/share-vm/fedora23server-share/webserver/ cp examples/websocket_chat/index.html /opt/share-vm/fedora23server-share/webserver/5.2 推到 Android 设备上运行用 adb 把整个 webserver 目录推到设备的/system/xbin/quagga/adb push /opt/share-vm/fedora23server-share/webserver /system/xbin/quagga/ adb shell进入设备后启动两个服务cd /system/xbin/quagga ./simplest_web_server ./websocket_chat 浏览器访问http://localhost能看到页面就说明编译和部署都通了。这一步是整个排障的验证环节如果 PIE 参数没补对这里根本走不进去如果端口和 ws 地址没改对页面能打开但聊天功能是坏的。所以建议把这一条当作最终验收用例跑通了再关终端。6. 排障万一还报 PIE 或者别的6.1 make 仍报 PIE 时先看 V1如果你把 Codex 给的补丁粘进 examples.mkmake还是报 only position independent executables (PIE) are supported先跑一次make V1看实际执行的编译命令里有没有-fPIE和-pie。很多时候不是没加而是 Makefile 里CFLAGS被赋值了两次后面的覆盖了前面的。把完整 examples.mk 重新发给 Codex让它检查是否有变量互相覆盖比你自己逐行找快得多。另一种情况是编译过了、链接时只报-pie说明 CFLAGS 生效了但 LDFLAGS 里的-pie没进入最终链接命令。检查 LDFLAGS 是否被 Makefile 后续规则重写或者确认目标规则里的编译命令确实引用了$(LDFLAGS)。Codex 给出的补丁一般会连这条规则一起检查所以如果你是从命令行直接拼参数而不是改文件很容易漏掉这一步。6.2 回官网看调用量和模型广场排障结束、服务也跑起来之后我通常回到 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 的控制台看一眼这次排障消耗了多少量以及到底用的是哪个模型。这里有两个实际意义一是确认 Key 没有异常消耗二是顺便看看模型广场里有没有上下文更长、更适合看 Makefile 的模型。如果下次再遇到类似的 NDK 报错我会优先选上下文更长的模型让 Codex 一次把整个 examples.mk 读完避免它只看到片段就给出不完整的补丁。如果你还没创建 Key现在去 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 注册并创建 API Key再按上面的步骤配好 Codex就能把同样的排障流程跑通。
返回列表