Skip to content

Instantly share code, notes, and snippets.

@jdonszelmann
Last active October 29, 2019 10:26
Show Gist options
  • Save jdonszelmann/26c71445b12593d2224d98a4ad09a9d2 to your computer and use it in GitHub Desktop.
Save jdonszelmann/26c71445b12593d2224d98a4ad09a9d2 to your computer and use it in GitHub Desktop.
General makefile for any c/asm project
executable_name = yeet
version = 0.0.1
arch ?= x86_64
LINKER = gcc
CC = gcc
CPP = g++
ASM = gcc
NASM = nasm
SOURCEDIR = src
BINDIR = bin
BUILDDIR = build
RESOURCESDIR = resources
TESTDIR = test
# any directory named this will be included
INCLUDEDIR = include
# Flags for the linker.
LFLAGS =
# string of -l<something> library names.
# Use "-lstdc++" for projects including c++ code
LIBRARIES =
# flags for the c compiler
CFLAGS =
# flags for the cpp compiler
CPPFLAGS =
# flags for the assembler (.s / gcc)
ASMFLAGS =
# flags for the assembler (.asm / nasm)
NASMFLAGS =
#gdb
GDBARGS =
# setup
#-----------------------
executable_fullname = $(executable_name)-$(version)-$(arch)
executable = $(BINDIR)/$(executable_fullname)
testexecutable = $(BINDIR)/test/$(executable_fullname)
dirs = $(shell find $(SOURCEDIR)/ -type d -print)
testdirs = $(shell find $(TESTDIR)/ -type d -print)
includedirs := $(sort $(foreach dir, $(foreach dir1, $(dirs), $(shell dirname $(dir1))), $(wildcard $(dir)/$(INCLUDEDIR))))
CFLAGS += $(foreach dir, $(includedirs), -I./$(dir))
CPPFLAGS += $(foreach dir, $(includedirs), -I./$(dir))
ASMFLAGS += $(foreach dir, $(includedirs), -I./$(dir))
# support for .S files
assembly_source_files := $(foreach dir,$(dirs),$(wildcard $(dir)/*.S))
assembly_object_files := $(patsubst $(SOURCEDIR)/%.S, \
$(BUILDDIR)/%.o, $(assembly_source_files))
# support for .s files
assembly_source_files += $(foreach dir,$(dirs),$(wildcard $(dir)/*.s))
assembly_object_files += $(patsubst $(SOURCEDIR)/%.s, \
$(BUILDDIR)/%.o, $(assembly_source_files))
# support for .asm files
nassembly_source_files := $(foreach dir,$(dirs),$(wildcard $(dir)/*.asm))
nassembly_object_files := $(patsubst $(SOURCEDIR)/%.asm, \
$(BUILDDIR)/%.o, $(nassembly_source_files))
# support for .c files
c_source_files := $(foreach dir,$(dirs),$(wildcard $(dir)/*.c))
c_object_files := $(patsubst $(SOURCEDIR)/%.c, \
$(BUILDDIR)/%.o, $(c_source_files))
# support for .cpp files
cpp_source_files := $(foreach dir,$(dirs),$(wildcard $(dir)/*.cpp))
cpp_object_files := $(patsubst $(SOURCEDIR)/%.cpp, \
$(BUILDDIR)/%.o, $(cpp_source_files))
# support for .S tests
assembly_test_source_files := $(foreach dir,$(testdirs),$(wildcard $(dir)/*.S))
assembly_test_object_files := $(patsubst $(TESTDIR)/%.S, \
$(BUILDDIR)/%.o, $(assembly_test_object_files))
# support for .s tests
assembly_test_source_files += $(foreach dir,$(testdirs),$(wildcard $(dir)/*.s))
assembly_test_object_files += $(patsubst $(TESTDIR)/%.s, \
$(BUILDDIR)/%.o, $(assembly_test_object_files))
# support for .asm tests
nassembly_test_source_files := $(foreach dir,$(testdirs),$(wildcard $(dir)/*.asm))
nassembly_test_object_files := $(patsubst $(TESTDIR)/%.asm, \
$(BUILDDIR)/%.o, $(nassembly_test_object_files))
# support for .c tests
c_test_source_files := $(foreach dir,$(testdirs),$(wildcard $(dir)/*.c))
c_test_object_files := $(patsubst $(TESTDIR)/%.c, \
$(BUILDDIR)/%.o, $(c_test_source_files))
# support for .c tests
cpp_test_source_files := $(foreach dir,$(testdirs),$(wildcard $(dir)/*.cpp))
cpp_test_object_files := $(patsubst $(TESTDIR)/%.cpp, \
$(BUILDDIR)/%.o, $(cpp_test_source_files))
cpp_test_functions := $(shell cat $(cpp_test_source_files) | sed -n "s/void \\(test_.*\\)().*/\\1/p")
# default rules
#-----------------------
.PHONY: clean run debug build test
# build the executable but don't run
build: $(executable) | resourcesdir
clean:
@rm -rf $(BUILDDIR)
@rm -rf $(BINDIR)
# run the executable
run: build | resourcesdir
@echo starting
@cd $(RESOURCESDIR) && ../$(executable)
# run the executable with gdb
debug: $(executable) | resourcesdir
@gdb --args $(executable) $(GDBARGS)
test: $(testexecutable) | testdir resourcesdir
@echo testing
@cd $(RESOURCESDIR) && ../$(testexecutable)
# intermediate rules
#-----------------------
resourcesdir:
@mkdir -p $(RESOURCESDIR)
testdir:
@mkdir -p $(TESTDIR)
@mkdir -p $(BINDIR)/test
builddir:
@mkdir -p $(BUILDDIR)
# linking
$(executable): $(assembly_object_files) $(c_object_files) $(nassembly_object_files) $(cpp_object_files) | builddir
@echo linking...
@mkdir -p $(BINDIR)
@$(LINKER) -L/usr/lib $(LFLAGS) -o $@ $(assembly_object_files) $(nassembly_object_files) $(c_object_files) $(cpp_object_files) $(LIBRARIES)
# test linking
$(testexecutable): testobject $(assembly_object_files) $(c_object_files) $(nassembly_object_files) $(cpp_object_files) $(assembly_test_object_files) $(c_test_object_files) $(nassembly_test_object_files) $(cpp_test_object_files) | builddir testdir
@echo linking tests...
@mkdir -p $(BINDIR)/test
@$(LINKER) -L/usr/lib $(LFLAGS) -Wl,--wrap,main -o $@ $(BUILDDIR)/__test.o $(assembly_object_files) $(nassembly_object_files) $(c_object_files) $(cpp_object_files) $(assembly_test_object_files) $(c_test_object_files) $(nassembly_test_object_files) $(cpp_test_object_files) $(LIBRARIES)
# compile assembly files (.S)
$(BUILDDIR)/%.o: $(SOURCEDIR)/%.S | builddir
@mkdir -p $(shell dirname $@)
@echo compiling $<
@$(ASM) -c $(ASMFLAGS) $< -o $@
# compile assembly files (.S)
$(BUILDDIR)/%.o: $(SOURCEDIR)/%.s | builddir
@mkdir -p $(shell dirname $@)
@echo compiling $<
@$(ASM) -c $(ASMFLAGS) $< -o $@
# compile assembly files
$(BUILDDIR)/%.o: $(SOURCEDIR)/%.asm | builddir
@mkdir -p $(shell dirname $@)
@echo compiling $<
@$(NASM) $(NASMFLAGS) $< -o $@
# compile c files
$(BUILDDIR)/%.o: $(SOURCEDIR)/%.c | builddir
@mkdir -p $(shell dirname $@)
@echo compiling $<
@$(CC) -c $(CFLAGS) $< -o $@
# compile cpp files
$(BUILDDIR)/%.o: $(SOURCEDIR)/%.cpp | builddir
@mkdir -p $(shell dirname $@)
@echo compiling $<
@$(CPP) -c $(CPPFLAGS) $< -o $@
# compile assembly files (.S)
$(BUILDDIR)/%.o: $(TESTDIR)/%.S | builddir
@mkdir -p $(shell dirname $@)
@echo compiling $<
@$(ASM) -c $(ASMFLAGS) $< -o $@
# compile assembly files (.S)
$(BUILDDIR)/%.o: $(TESTDIR)/%.s | builddir
@mkdir -p $(shell dirname $@)
@echo compiling $<
@$(ASM) -c $(ASMFLAGS) $< -o $@
# compile assembly files
$(BUILDDIR)/%.o: $(TESTDIR)/%.asm | builddir
@mkdir -p $(shell dirname $@)
@echo compiling $<
@$(NASM) $(NASMFLAGS) $< -o $@
# compile c files
$(BUILDDIR)/%.o: $(TESTDIR)/%.c | builddir
@mkdir -p $(shell dirname $@)
@echo compiling $<
@$(CC) -c $(CFLAGS) $< -o $@
# compile cpp files
$(BUILDDIR)/%.o: $(TESTDIR)/%.cpp | builddir
@mkdir -p $(shell dirname $@)
@echo compiling $<
@$(CPP) -c $(CPPFLAGS) $< -o $@
.PHONY: testobject
define testfile
#include <iostream>
$(foreach function, $(cpp_test_functions), void $(function)();)
extern "C" int __wrap_main(){
$(foreach function, $(cpp_test_functions), $(function)(); std::cout<<"$(function) successful"<<std::endl;)
return 0;
}
endef
export testfile
testobject: | builddir
@echo "$$testfile" | $(CPP) -c -o $(BUILDDIR)/__test.o -xc++ -
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment