我有一组构建交叉编译项目的步骤(https://github.com/n64decomp/sm64)。这些步骤需要例如
binutils
针对 MIPS 平台,例如mips-linux-gnu
。 (据称该项目也支持其他类似 mips64-elf
或 mips64-linux-gnu
的项目。)
-> 我想制作一个
shell.nix
文件,在 nix-shell
(或 nix shell
)下生成具有跨目标 binutils
可执行文件的环境。
还有一个说明:我正在 M1 mac 上编译。但是该项目不支持从
aarm64-darwin
进行构建,因此我使用 x86_64-darwin
作为 Rosetta2 兼容层下的构建平台。
我写了一个
shell.nix
,如下所示:
{ pkgs ? import <nixpkgs> {
# https://nixos.org/manual/nixpkgs/stable/#sec-cross-usage
localSystem = (import <nixpkgs/lib>).systems.examples.x86_64-darwin;
crossSystem = (import <nixpkgs/lib>).systems.examples.mips-linux-gnu;
}
}:
pkgs.mkShell {
# stuff I want at build-time
# -> package host = project build
# -> package target = project host
# pulled from https://github.com/n64decomp/sm64#step-1-install-dependencies-1
nativeBuildInputs = [
# doesn't compile code -> no target
pkgs.gnumake42
pkgs.coreutils
pkgs.pkg-config
# compiles -> target = mips-linux-gnu
pkgs.binutils
];
shellHook = ''
# some other setup commands...
'';
}
运行
nix-shell
并尝试使用任何依赖项(例如 make
)会生成类似 cannot execute binary file: Exec format error
的错误。似乎所有二进制文件都是为了在 mips 上运行而构建的,而不是为 mips 构建。
我还尝试将这些依赖项放入 buildInputs
中。运行项目构建然后生成错误
ld: archive has no table of contents file 'audiofile/libaudiofile.a' for architecture x86_64
mips-unknown-linux-gnu-ld
的target
是 x86_64
,而不是
mips
。问题如何重写此 shell.nix
x86_64-darwin
上运行的包,并为目标
mips-linux-gnu
构建?编辑:更多信息我打开了 nix repl
nix-repl> pkgs = import <nixpkgs> { localSystem = (import <nixpkgs/lib>).systems.examples.x86_64-darwin; crossSystem = (import <nixpkgs/lib>).systems.examples.mips-linux-gnu; }
nix-repl> pkgs.stdenv.buildPlatform.config
"x86_64-apple-darwin"
nix-repl> pkgs.stdenv.hostPlatform.config
"mips-unknown-linux-gnu"
nix-repl> pkgs.stdenv.targetPlatform.config
"mips-unknown-linux-gnu"
平台是
x86_64-darwin
,我的 host 和 target 平台都是
mips-linux
。这听起来是对的;我正在使用 x86_64-darwin
来 build这个项目,生成的 ROM
在
mips
上运行。 (它不会生成其他代码,因此目标无关紧要。)
但是nix-shell
是用来开发的;当您运行 nix-shell derivation.nix
时,它会将您带入
构建序列进行推导。因此环境位于
构建平台上,对吗?但这里似乎
nix-shell shell.nix
正在生成一个主机平台环境。这是为什么?解决了!据我现在的理解,这里发生了一些事情:
audiofile/libaudiofile.a
所有(减去一个)都是默认提供的。我真正需要的唯一依赖项是
gnumake42
make
与该项目不兼容通过指定 pkgs {crossSystem = ...}
进行交叉编译时,据称存在 callPackage
,尽管我不太确定为什么这可以解决问题🤔我以为我需要将本地系统设置为 x86_64-darwin
以实现项目兼容性,但事实证明,删除它以使用默认的 aarm64-darwin
这是生成的
shell.nix
{ pkgs ? import <nixpkgs> {
# https://nixos.org/manual/nixpkgs/stable/#sec-cross-usage
crossSystem = (import <nixpkgs/lib>).systems.examples.mips-linux-gnu;
}
}:
pkgs.callPackage
({ mkShell
, gnumake42
}: mkShell {
# pulled from https://github.com/n64decomp/sm64#step-1-install-dependencies-1
depsBuildBuild = [
gnumake42 # v4.4 breaks the build!
];
strictDeps = true;
shellHook = ''
# same setup code as before
# ...
'';
})
{ }