惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Check Point Blog
aimingoo的专栏
aimingoo的专栏
Jina AI
Jina AI
Microsoft Security Blog
Microsoft Security Blog
IT之家
IT之家
V
Visual Studio Blog
量子位
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 聂微东
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
大猫的无限游戏
大猫的无限游戏
Y
Y Combinator Blog
Stack Overflow Blog
Stack Overflow Blog
D
Docker
MyScale Blog
MyScale Blog
小众软件
小众软件
云风的 BLOG
云风的 BLOG
美团技术团队
Microsoft Azure Blog
Microsoft Azure Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
Last Week in AI
Last Week in AI
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 【当耐特】

kkocdko's blog

Tasker 永久试用修改思路 - kkocdko's blog 极限压缩文档扫描件 - kkocdko's blog Bypass the Blank Chars Detection crknob - Chrome portable patch 我如何将博客首页体积降至 3 KB - kkocdko's blog 如何极限优化压缩文件体积 - kkocdko's blog EmEditor 精简版 - kkocdko's blog Backup Data from VSCode Web 优雅地游玩 Minecraft - kkocdko's blog 让程序以管理员权限运行的 PE 清单 - kkocdko's blog 注销 ZEIT 账号之后遇到的坑 - kkocdko's blog 本博客的协议已更改为 CC0 - kkocdko's blog mobp - 使 MSOffice 后台常驻 在安装 VS 生成工具时规避 .NET 安装错误 各种格式的占位空文件 - kkocdko's blog 优雅地游玩 Flash 游戏 - kkocdko's blog WPS 2016 极限精简版 - kkocdko's blog Convert Const to Let by Terser 规避 Visual Studio 许可证过期的 Bug 方便地使用 iPod - kkocdko's blog 用 UserJS 注入 UserCSS - kkocdko's blog 注册表修改文件关联(默认程序) - kkocdko's blog 周期精准的太阳系模型 - kkocdko's blog 关闭屏幕的 WinAPI - kkocdko's blog 重置 Windows 图标缓存 - kkocdko's blog AIDA64 极限精简单文件版 - kkocdko's blog 几何画板单文件精简版 - kkocdko's blog 世界之窗浏览器单文件版 - kkocdko's blog 在 MBR + Legacy 下用 Bootmgr 引导 Ubuntu 简洁的 Markdown 预览工具 - kkocdko's blog
Multi call binary for existing projects
2026-04-11 · via kkocdko's blog

What's that? Okey, BusyBox is a multi call binary, one binary as ls,cat and more.

Why? Please ask the LLM for an answer.

TLDR: modify each commands' entry function to export int cmd_xxx_main(...), write a wrapper as new entry to call different cmd_xxx_main depends on argv[0], finally link them together.

Some projects like libwebp were compiled into many executabe, here's how to modify as little as possible to build it into multi call binary.

First, download and extract the source tarballs:

mkdir webp
cd webp
curl -L https://github.com/webmproject/libwebp/archive/2e81017c7a345f687223086cbc177a8459a18b52.tar.gz | tar -zx --strip-components 1 # 20240901 > 1.4.0

Then modify the entry function name by sed commands:

sed -i.bak -e 's|int main(|int cmd_webpinfo_main(|' examples/webpinfo.c
sed -i.bak -e 's|int main(|int cmd_cwebp_main(|' examples/cwebp.c
sed -i.bak -e 's|int main(|int cmd_dwebp_main(|' examples/dwebp.c

For C++, needs extern "C" to keep a stable C-ABI:

sed -i.bak -e 's|int main(|extern "C" int cmd_djxl_main(|' tools/djxl_main.cc

Then you need a wrapper, multicall.cc:

#include <stddef.h>
#include <string.h>
#include <stdio.h>
#if defined(WIN32) || defined(_WIN32)
#define PATH_SEPARATOR '\\\\'
#else
#define PATH_SEPARATOR '/'
#endif
extern "C" {
  int cmd_webpinfo_main(int argc, const char* argv[]);
  int cmd_cwebp_main(int argc, const char* argv[]);
  int cmd_dwebp_main(int argc, const char* argv[]);
}
int main(int argc, const char *argv[]) {
  for (int i = 0; argc != 0 && i != 2; i++) {
    const char *argv0 = strrchr(argv[0], PATH_SEPARATOR);
    if (argv0 == NULL) argv0 = argv[0]; else argv0++;
    if (strcmp(argv0, "webpinfo") == 0) return cmd_webpinfo_main(argc, argv);
    if (strcmp(argv0, "cwebp") == 0) return cmd_cwebp_main(argc, argv);
    if (strcmp(argv0, "dwebp") == 0) return cmd_dwebp_main(argc, argv);
    argv++;
    argc--;
  }
  puts("applets: webpinfo cwebp dwebp");
  return 0;
}

Because libwebp uses cmake and ninja, so here's a util function to extract ninja targets. Then, compile all targets and link them with multicall.cc:

export CFLAGS="-O3 -fomit-frame-pointer -march=x86-64-v3 -flto"
export CXXFLAGS="$CFLAGS"

rm -rf build

# cmake will use CFLAGS/CXXFLAGS from environment
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DWEBP_USE_THREAD=OFF -DWEBP_UNICODE=OFF

# extract path of targets
ninja_targets(){
  cat build/build.ninja | grep $1 | sed -e 's|\$||g' -e 's/|/ /g' | cut -d " " -f 4- | tr " " "\n" | grep -E "\.[^\\/]+/*{content}*/quot; # get targets built by $1, fix msys2 paths like "D$:/a.o", remove target head and '|' char, exclude targets without extension name
}
webp_targets=""
webp_targets="$webp_targets $(ninja_targets C_EXECUTABLE_LINKER__webpinfo_Release)"
webp_targets="$webp_targets $(ninja_targets C_EXECUTABLE_LINKER__cwebp_Release)"
webp_targets="$webp_targets $(ninja_targets C_EXECUTABLE_LINKER__dwebp_Release)"
ninja -C build $webp_targets

g++ $CXXFLAGS multicall.cc \
  $(realpath $webp_targets) \
  -o zcodecs

Full runnable build script is here (ect + libjxl + libwebp).

As I described here, we can also use objcopy or modify the LLVM IR to rename symbols, however