💾 Archived View for misterio.me › notes › c-nix-boilerplate › index.gmi captured on 2022-07-16 at 14:31:57. Gemini links have been rewritten to link to archived content

View Raw

More Information

-=-=-=-=-=-=-

Gabriel Fontes

About

Blog

Notes

Portfolio

C Nix boilerplate

Last modified on 13 Jul 2022 by Gabriel Fontes

Tags: #nix

Looking to start out a C (or C++) project and wanna some cool and nifty commands to manage it through both make and nix? As a plus, you'll also get nice out of tree builds.

Then look no further, here's all the boilerplate you need.

If you just want it fast without an explanation, it's all available on my repository.

repository

You can just run nix flake init -t github:misterio77/nix-config#templates.c, to quickly init a flake with this template.

We're gonna start by building a flexible (yet simple) Makefile:

# Set default prefix and bin dirs, for non-nixos
PREFIX ?= /usr/local
BIN_DIR ?= $(PREFIX)/bin

# Executable name
TARGET_EXEC ?= foo-bar
# Build directory
BUILD_DIR ?= ./build
# Source directory(ies)
SRC_DIRS ?= ./src

# Use find to get all .c and .cpp files
SRCS := $(shell find $(SRC_DIRS) -name *.cpp -or -name *.c)
# Map those to their respective .o files
OBJS := $(SRCS:%=$(BUILD_DIR)/%.o)
# Dependency files generated by gcc
DEPS := $(OBJS:.o=.d)

# Directories with includes
INC_DIRS := $(shell find $(SRC_DIRS) -type d)
# Flags for including those
INC_FLAGS := $(addprefix -I,$(INC_DIRS))

# Flags for both C and C++
CPPFLAGS ?= $(INC_FLAGS) -MMD -MP

# Link executable
$(BUILD_DIR)/$(TARGET_EXEC): $(OBJS)
    $(CXX) $(OBJS) -o $@ $(LDFLAGS)

# C source files
$(BUILD_DIR)/%.c.o: %.c
    $(MKDIR_P) $(dir $@)
    $(CC) $(CPPFLAGS) $(CFLAGS) -c {body}lt; -o $@

# C++ source files
$(BUILD_DIR)/%.cpp.o: %.cpp
    $(MKDIR_P) $(dir $@)
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c {body}lt; -o $@

# Clean built artifacts
clean:
    $(RM) -r $(BUILD_DIR)

# Install to prefix/bin path
install: $(BUILD_DIR)/$(TARGET_EXEC)
    install -d $(BIN_DIR)
    install -t $(BIN_DIR) {body}lt;

# Include generated dependencies
-include $(DEPS)

MKDIR_P ?= mkdir -p

This is heavily based on this post, with the main change being the install directive.

this post

Okay, now we just need a flake for building with nix:

{
  description = "Foo Bar C/C++ Project";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, flake-utils }:
    # For each system
    flake-utils.lib.eachDefaultSystem (system:
      let
        # Derivation and executable name
        name = "foo-bar";
        pkgs = (import nixpkgs { inherit system; });
      in
      rec {
        # nix build
        packages.${name} = pkgs.stdenv.mkDerivation rec {
          inherit name;
          src = ./.;
          # Set prefix, so stuff is installed to $out
          makeFlags = [ "PREFIX=$(out)" ];
        };
        defaultPackage = packages.${name};

        # nix run
        apps.${name} = {
          type = "app";
          program = "${packages.${name}}/bin/${name}";
        };
        defaultApp = apps.${name};

        # nix develop
        devShell = pkgs.mkShell {
          # Add clang and clang-tools for LSP support while editing
          buildInputs = with pkgs; [ gnumake clang clang-tools ];
        };
      });
}

And there you go!

Wanna talk? Hit me up on email. Feel free to encrypt, and use plaintext if possible.

eu@misterio.me

g.fontes@usp.br

PGP: 7088 C742 1873 E0DB 97FF 17C2 245C AB70 B4C2 25E9

This site's code is available under MIT, while its content is CC BY-SA 4.0

Repository