Nix和GCC - `无法找到crt1.o`

5

我在WSL上运行着Ubuntu 18.x的Nix操作系统。

我使用$ nix-env -i gcc命令安装了GCC,安装的版本为gcc-7.3.0

我试图使用GCC编译一个由Ferret生成的简单CPP文件。但是GCC出现了以下错误:

$ g++ -std=c++11 -x c++ test_1.cpp -o test_1
/usr/bin/ld: cannot find crt1.o: No such file or directory
/usr/bin/ld: cannot find crti.o: No such file or directory
collect2: error: ld returned 1 exit status

看起来我以为Nix会包含与GCC(“build-essential”相当的)常见依赖项,但我认为这并不正确。
使用Nix搜索(“nix-env -qaP 'gcc'”,“nix-env -qaP --description | grep -i gcc”)没有提供太多帮助。
其他帖子提到安装gcc-multilib(apt软件包)。 Nix中唯一提到它的是测试软件包。
$ nix-env -qaP --description | grep -i multilib
nixpkgs.tests.cc-multilib-gcc                                            cc-multilib-test                               
nixpkgs.tests.cc-multilib-clang                                          cc-multilib-test

我不知道如何搭建构建环境。我找不到任何相关的文档来告诉我需要哪些软件包才能开始工作。这应该是挺简单的事情。


路径/usr/bin/ld是一种提示,表明某些配置不正确;Nix不使用/usr。您是否考虑创建一个Nix表达式,以便可以使用nix build来编译您的程序? - Emmanuel Rosa
@EmmanuelRosa 我没有,不知道nix的深度。关于ld,有趣的观点,但我没有安装nix版本,我肯定不需要吧?$ which ld; /usr/bin/ld; $ which gcc; /home/<user>/.nix-profile/bin/gcc. - Rebs
不需要创建nix表达式,使用nix-shell就可以完成这个操作吗?例如:nix-shell -p gcc_multi,然后执行gcc <file>./a.out - Eugene Triguba
2个回答

2
简而言之,Nix 的操作方式与其他大多数发行版不同。使用 Nix 时,您不是像大多数发行版那样安装工具和库,而是创建一个“Nix 表达式”,声明您的构建依赖项并提供编译程序的指令。例如,假设您有一个名为 hello.cc 的源代码文件:
#include <iostream>
using namespace std;

int main() 
{
    cout << "Hello, World!";
    return 0;
}

要使用Nix编译它,您可以使用一个名为default.nix的文件(位于同一目录中),如下所示:

let
    pkgs = (import <nixpkgs>) {};
    gcc = pkgs.gcc;
    stdenv = pkgs.stdenv;
in
    stdenv.mkDerivation {
        name = "hello";
        version = "1.0.0";
        src = ./.;
        phases = [ "unpackPhase" "buildPhase" "installPhase" ];

        buildPhase = ''
            ${gcc}/bin/g++ -std=c++11 -x c++ hello.cc -o hello
        '';

        installPhase = ''
            mkdir -p $out/bin
            cp hello $out/bin
        '';
    }

你可以像这样构建:nix build

最后你会得到一个符号链接 ./result,它指向上述使用的 $out 目录。上文中的 installPhase 将二进制文件复制到 $out/bin,因此可以通过运行 ./result/bin/hello 来执行程序。

Nix 语言在其文档中有描述,并且你可以在 Nixpkgs 文档中获得如何使用它构建的概述。


4
这似乎不对劲。我只是使用Nix软件包管理器,我不需要完整的操作系统/构建系统抽象。我已经有足够多的工具需要学习了。我正在寻找一些能够减轻我的工作负担的东西,而不是增加它。我肯定只是缺少了一些需要与GCC一起安装的软件包。 - Rebs
@Rebs,需要记住的是Nix不是普通的软件包管理器。因此,其他软件包管理器中的一些概念,例如如果您安装了两个软件包,它们应该能够“看到”彼此的想法,不适用于Nix。例如,如果您有需要libgtk的代码,并尝试通过先安装gcc和gtk来编译它,那么它将无法工作。gcc将无法“看到”libgtk。相反,您需要创建一个提供gtk依赖项的Nix表达式。然后,Nix将创建一个“用户环境”,在其中gtk对gcc可见。然后编译将继续进行。 - Emmanuel Rosa
好的,这完全不是我预期的。听起来很有趣,但也很繁琐。我想我要转向一些更简单的东西了。感谢你的帮助。 - Rebs
4
@EmmanuelRosa,有没有办法让这个工具正常运作呢?我以为 nix-env -i packagename 的目的是将这些依赖项放入 ~/.nix-profile/bin~/.nix-profile/lib 等位置,以便可以看到并使用它们。即使我完全接受了 Nix 的抽象思想,我还是需要能够像传统方式那样使用这些工具,比如下载和编译一个没有 default.nix 的 C++ 项目。 - tom

0

只需使用gcc获取Nix shell即可。

nix shell nixpkgs#gcc # with flakes
nix-shell -p gcc # without flakes

然后执行 gcc <任何内容> 似乎可以工作。

如果你想要其他依赖项,也可以添加它们:

nix-shell -p pkgconfig gcc openssl
g++ $(pkg-config --libs --cflags openssl) solution.cpp

或者最终构建一个.nix文件,这是这个非临时版本的文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接