💾 Archived View for misterio.me › 2021 › 09 › 14 › c-nix-boilerplate.gmi captured on 2022-06-04 at 00:03:24. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2022-03-01)
-=-=-=-=-=-=-
Gabriel Fontes
14 Sep 2021 - Gabriel Fontes
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.
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.
https://spin.atomicobject.com/2016/08/26/makefile-c-projects/
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!