macos 上怎么编译出 portable nginx? 就像 windows 上的绿色软件一样

2023-03-11 00:56:08 +08:00
 laravel

就是不依赖编译时候的系统,放到任何 macos 上都可以运行

我现在用

./configure --prefix=./nginx --with-pcre=../pcre2-10.42 --with-http_ssl_module --with-openssl=../openssl-1.1.1t

编译出来的 nginx

通过命令 otool -L sbin/nginx

可以看到还是依赖我电脑上的文件

./sbin/nginx:
	/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.0.0)

怎么编译才能完全不依赖我的系统

1864 次点击
所在节点    程序员
13 条回复
Love4Taylor
2023-03-11 00:58:18 +08:00
静态编译?应该和 linux 上参数大概一致吧?
laravel
2023-03-11 00:59:29 +08:00
@Love4Taylor 就是编译时候不让他找系统里的环境,就在执行目录寻找依赖
bakaft
2023-03-11 01:02:25 +08:00
laravel
2023-03-11 01:06:57 +08:00
@bakaft 想做 mac 上的绿色软件,现在要做 nginx php mysql 环境的话,还要用 brew 一个一个安装,或者用集成开发环境,这会污染系统,我就想把所有软件和依赖放到一个目录,就跟 windows 上的 zip 解压出来直接可以运行的那种软件一样
laravel
2023-03-11 01:07:33 +08:00
@bakaft 现在我发现我编译出来的,放到别人系统无法运行
laravel
2023-03-11 01:26:25 +08:00
刚才指定了一下 zlib 目录,又减少了一个依赖,看来是有希望

执行 otool -L ./nginx

现在是
```
./nginx:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.0.0)
```

这是什么依赖?
hguandl
2023-03-11 02:45:12 +08:00
libSystem.B.dylib 应该是 macOS 上的 libc ,属于系统的一部分,正常来说所有程序都会动态链接这个库,不能再去掉了。只剩这一个动态库的话,可以说这个程序是静态的,其他人系统无法运行应该不是链接库的问题。我想了几种可能的原因:

1. 系统版本:如果不指定的话,默认情况下编译出来的程序所需的系统版本是和当前系统一致的。可以通过 otool -l nginx | grep minos 查看。可以加编译参数把目标版本设置得低一些,比如 -mmacosx-version-min=11.0 ,就是兼容 Big Sur 版本。

2. 架构:可能你用的是 Apple Silicon ,编译出来的是 arm64 的二进制文件,别人电脑是 x86 的,就无法运行。这就需要交叉编译,可以看官方文档 https://developer.apple.com/documentation/apple-silicon/building-a-universal-macos-binary

3. 签名:macOS 的安全规则比较苛刻,对于下载的文件,如果没有合适的签名可能会阻止运行。试试 xattr -d com.apple.quarantine nginx 把隔离去掉。
laravel
2023-03-11 03:24:15 +08:00
@hguandl 没有 c/c++基础,感觉太复杂了,还不如只研究 windows 软件,mac 的用户也不是很多
xiadong1994
2023-03-11 04:36:35 +08:00
Docker 就是用来解决这种问题的
qfdk
2023-03-11 06:56:33 +08:00
docker 不香么? 再不齐用 caddy 吧 这个就一个可执行文件就好了
yzwduck
2023-03-11 08:50:18 +08:00
macOS 上程序对系统依赖的判定与 Linux 不一样。

Linux 只保证了系统调用的 ABI 是稳定的,但它不提供任何用户态环境的保障,所以程序需要静态链接 C runtime 等依赖项。

但 macOS 只保证了 C runtime 和一大堆系统库的 API 是稳定的,它不保障系统调用是稳定的 (
https://developer.apple.com/forums/thread/706419 ),程序必须链接到 macOS 提供的 C runtime (以及 libSystem 之类) 的动态库上。

即使在 OS X 10.10 上,系统中也存在 /usr/lib/libz.1.dylib 和 /usr/lib/libSystem.B.dylib 。如果编译选项正确的话,Xcode 14 编译出来的程序能在 macOS 10.13 (甚至更早的系统) 上运行。

TL;DR:
如果只需要支持 Xcode 兼容的 deployment target (Xcode 14: macOS 10.13 或更新),在满足 (1) 不链接到系统路径以外的动态库,(2) export MACOSX_DEPLOYMENT_TARGET=10.13 环境变量,或者提供了 -mmacosx-version-min=10.13 编译参数,(3) 编译 x86_64 和 ARM64 两份架构的代码,就应该能保证程序能在 macOS 10.13 以后的系统上运行。

如果要支持 OS X 10.9 或更老的系统,或者 i386/PPC 架构的话,就超出我的实践范围了。
guanzhangzhang
2023-03-11 09:55:33 +08:00
```
--with-cc-opt='-static -s' \
--with-ld-opt=-static
```
加这俩试试,不知道 mac 上能有用不
laravel
2023-03-11 11:44:06 +08:00
@guanzhangzhang 不行,我估计别人是修改了 nginx 的代码,让他编译时候去自己的目录找依赖

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/923048

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX