起因
当使用仓颉 1.0.3 在 macOS 26 Tahoe 上构建二进制时,运行构建的二进制会提示错误
bash-3.2$ ./target/release/bin/main
dyld[29505]: __DATA_CONST segment missing SG_READ_ONLY flag in /Users/runner/work/action/action/cjtest/target/release/bin/main
dyld[29505]: __DATA_CONST segment missing SG_READ_ONLY flag
Abort trap: 6
原因
查看 macho dyld 源码 可知
if ( !isDylibStub() && policy.enforceDataSegmentPermissions() ) {
if ( (strcmp(seg->segname, "__DATA") == 0) && (seg->initprot != (VM_PROT_READ | VM_PROT_WRITE)) )
return Error("__DATA segment permissions is not 'rw-'");
if ( strcmp(seg->segname, "__DATA_CONST") == 0 ) {
if ( seg->initprot != (VM_PROT_READ | VM_PROT_WRITE) )
return Error("__DATA_CONST segment permissions is not 'rw-'");
if ( (seg->flags & SG_READ_ONLY) == 0 ) {
bool isSplitSegMarker = false;
if ( this->isDylibOrStub() && this->hasSplitSegInfo(isSplitSegMarker) && !isSplitSegMarker ) {
// dylibs intended for dyld cache are allowed to not have SG_READ_ONLY set
}
else if ( this->inDyldCache() ) {
// dylibs in dyld cache are allowed to not have SG_READ_ONLY set
}
else if ( this->isStaticExecutable() ) {
// static excutables don't use dyld so have no way to make DATA_CONST read-only
}
else if ( policy.enforceDataConstSegmentPermissions() ) {
return Error("__DATA_CONST segment missing SG_READ_ONLY flag");
}
}
}
}
当 policy.enforceDataConstSegmentPermissions() 返回 true 时,__DATA_CONST 应该被正确的设置 bit 位 SG_READ_ONLY,否则则无法链接。 据 LLVM 社区报告,苹果应该在 macOS 13 已经启用了该功能,但是更加广泛的限制直到 macOS 26 才被启用。
查看 policy.enforceDataConstSegmentPermissions() 的逻辑可知
bool Policy::enforceDataConstSegmentPermissions() const
{
// dylibs in shared region don't set SG_READ_ONLY because of __objc_const
if ( _pathMayBeInSharedCache )
return false;
return (_enforcementEpoch >= Platform::Epoch::spring2025);
}
macOS 26.0 对应的是 fall2025,因此触发了这个错误。
Workaround
修复此错误需要对编译器本体进行改动,由于仓颉的后端使用 LLVM 15,可能需要从新版本 backport 特性。当前可用的 workaroud 是在 link-option 中指定 -no_data_const,彻底禁用 __DATA_CONST 段。ld.lld64 无法单独设置 segment flags,这一变更应该等待仓颉团队实现。
[package]
cjc-version = "1.0.3"
name = "test"
description = "nothing here"
version = "1.0.0"
target-dir = ""
src-dir = ""
output-type = "executable"
compile-option = ""
override-compile-option = ""
link-option = "-no_data_const"
package-configuration = {}
[dependencies]
现有行为
添加了 -no_data_const 后,应该可以在 macOS 26 上正确编译运行仓颉二进制了。
bash-3.2$ cat cjpm.toml
[package]
cjc-version = "1.0.3"
name = "test"
description = "nothing here"
version = "1.0.0"
target-dir = ""
src-dir = ""
output-type = "executable"
compile-option = ""
override-compile-option = ""
link-option = "-no_data_const"
package-configuration = {}
[dependencies]
bash-3.2$ cjpm build -V
Compiling package `test`: DYLD_LIBRARY_PATH=/Users/runner/hostedtoolcache/cangjie/1.0.3/aarch64/cangjie/runtime/lib/darwin_aarch64_llvm:$DYLD_LIBRARY_PATH cjc -j3 --import-path=/Users/runner/work/action/action/test/target/release --no-sub-pkg --output-dir=/Users/runner/work/action/action/test/target/release/bin --link-options -no_data_const -p /Users/runner/work/action/action/test/src --output-type=exe -o=main
Finished `build` profile compilation
Executable files at `/Users/runner/work/action/action/test/target/release/bin`
cjpm build success
bash-3.2$ ./target/release/bin/main
hello world
bash-3.2$ uname -a
Darwin Mac-1761991781781.local 25.0.0 Darwin Kernel Version 25.0.0: Wed Sep 17 21:41:26 PDT 2025; root:xnu-12377.1.9~141/RELEASE_ARM64_VMAPPLE arm64
发表回复