Rebs
Rebs

Reputation: 4239

Nix and GCC - `cannot find crt1.o`

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.

Upvotes: 5

Views: 4250

Answers (2)

Michal_Atlas
Michal_Atlas

Reputation: 11

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

Upvotes: 1

Emmanuel Rosa
Emmanuel Rosa

Reputation: 9885

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.

Upvotes: 2

Related Questions