5

I'm running Nix on WSL with Ubuntu 18.x.

I installed GCC with $ nix-env -i gcc which installed gcc-7.3.0.

I'm trying to use GCC to compile a simple CPP file (generated by Ferret). But GCC is coming up with the following error:

$ 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

It seems that I expected Nix to include common dependencies along with GCC (build-essential equivalents), which I assume is not true.

Searching using Nix (nix-env -qaP 'gcc', nix-env -qaP --description | grep -i gcc) doesn't provide much help.

Other posts mention installing gcc-multilib (apt package). The only mention of that in Nix are testing packages:

$ nix-env -qaP --description | grep -i multilib
nixpkgs.tests.cc-multilib-gcc                                            cc-multilib-test                               
nixpkgs.tests.cc-multilib-clang                                          cc-multilib-test

I'm at a loss as to how to get a build environment working. I cannot find any documentation as to what packages I need to get going. This is pretty simple stuff.

Rebs
  • 4,169
  • 2
  • 30
  • 34
  • The path `/usr/bin/ld` is a clue that something is misconfigured; Nix doesn't use `/usr`. Have you considered creating a Nix expression so that you can use `nix build` to compile your program? – Emmanuel Rosa Aug 20 '18 at 13:13
  • @EmmanuelRosa I haven't, no. I don't know much about nix's depths. Re: ld, Interesting point, but I haven't installed a nix version, surely I shouldn't have to? `$ which ld; /usr/bin/ld; $ which gcc; /home//.nix-profile/bin/gcc`. – Rebs Aug 21 '18 at 06:21
  • Isn't it possible to do this with `nix-shell` and not needing to create a nix expression? i.e. `nix-shell -p gcc_multi` and then `gcc ` and `./a.out`? – Eugene Triguba Jan 14 '23 at 15:26

2 Answers2

2

In short, things are done differently with Nix. Instead of installing tools and libraries like you'd do with most distros, when using Nix you create a "Nix expression" which declares your build dependencies and instructions for compiling your program. For example, say you have a hello.cc with this source code:

#include <iostream>
using namespace std;

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

To compile it with Nix you can use a default.nix file (in the same directory) like this:

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
        '';
    }

...which you can build like this: nix build

You'll end up with a ./result symbolic link which points to the $out directory used above. The installPhase above copies the binary to $out/bin, so the program can be executed by running ./result/bin/hello

The Nix language is described in its documentation and you can get an overview of how to use it to build things from the Nixpkgs documentation.

Emmanuel Rosa
  • 9,697
  • 2
  • 14
  • 20
  • 4
    This doesn't seem right. I'm just using the nix package manager. I'm not after a full OS/Build system abstraction. I have enough to learn with the tools I have. I'm looking for something to reduce my workload, not add to it. Surely there is just some missing package that I need to install alongside GCC? – Rebs Aug 28 '18 at 09:41
  • @Rebs, the thing to keep in mind is that Nix is no ordinary package manager. Thus some concepts from other package managers, such as the idea that if you install two packages they should be able to "see" each other, do not apply. For example, if you have code which requires libgtk and you try to compile it by first installing gcc and gtk, it will not work. gcc would not be able to "see" libgtk. Instead you'd need to create a Nix expression which provides gtk as a dependency. Nix will then create a "user environment" in which gtk is visible to gcc. Compilation would then proceed as normal. – Emmanuel Rosa Aug 28 '18 at 11:26
  • Ok, that's totally different to what I expected. It sounds interesting, but a burden. I think I'm going to jump ship to something simpler. I appreciate the help. – Rebs Aug 28 '18 at 11:53
  • 4
    @EmmanuelRosa is there really no way to make this work? I thought the purpose of `nix-env -i packagename` was to put such dependencies into `~/.nix-profile/bin`, `~/.nix-profile/lib`, etc. so that they can be seen and used. Even if I've fully bought into Nix's abstractions, I still need to be able to use these tools in a traditional manner, like to download and compile a C++ project that doesn't come with a `default.nix`. – tom Nov 07 '19 at 00:57
0

Simply getting a Nix shell with gcc works.

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

and then going gcc <anything> seems to work.

If you want other dependencies you can add them as well:

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

or eventually build up a .nix file which is the non ad-hoc version of this

Michal_Atlas
  • 1
  • 1
  • 1