/magefile

MaGEfile - a non-recursive, generic makefile for C++ projects

Primary LanguageMakefileMIT LicenseMIT

MaGEfile - the official MaGES build system

MaGEfile is a generic, non-recursive makefile designed for C++ projects. Its main goal is to provide a build system which requires a minimum amount of manual configuration, using automatic detection of dependencies and probing all necessary objects to link each executable specified by the user. A further goal is to create a well-defined structure to include new functionalities within the makefile, without directly editing its base file. The core ideas and source of inspiration come mostly from this insightful paper.

How to use

The functionalities of this makefile will be devided in Configuration, Building and Diagnosis. Currently, there is no support to diagnosis and configuration only addresses which variables you should consider to change manually. Support to diagnosis and more complex, automated configuration is expected to be added some time in the future.

Configuration

All variables of interest to the user are placed inside a section named PROJECT VARIABLES, quite visible. I may change this extravagant style later, but for now it is what it is. Most of the variables are straight-forward. The meaning of each one is listed bellow:

  • HEADER_SUFFIXES: the suffixes that are accepted in header filenames. It affects the automatic detection of necessary object files, so make sure you don't forget to add any unorthodox suffix you may come to use. SOURCE_SUFFIXES will be added in later development, for now it only supports .cpp files (unless you search for all occurrencies and change them);
  • Variables terminated in DIR specifies the directories of the project. At the moment, only one directory is supported for each variable, but with any depth of subdirectories;
    • SRCDIR: the sources directory (i.e., where you placed your implementation files);
    • INCDIR: the headers directory (i.e., where you placed your interface/definition files). If you prefer to organize your code in modules, each module correponding to a directory with both, headers and implementations, you can emulate this by setting SRCDIR and INCDIR to the same directory (project's root (.), for instance);
    • OBJDIR: the objects directory (i.e., where the building rules places all generated objects for the project). Usually, you will not need to change this;
    • TSTDIR: the tests directory (i.e., where you put your test files, if any - good practices, dude). Notice: you don't need to remove the default value if you're not going to actually use it;
    • DEPDIR: the dependencies directory (i.e., where the building rules places all aditional rules to track dependencies). You only need to change this in case you already use a directory with same name;
  • MAINFILES: the files that contains the main entry to a program (i.e., the main function of C++). Through each of this files the makefile will know which objects it should link to create a program. This variable is intrinsically related to BINARIES;
  • BINARIES: for each file with a main function specified in MAINFILES, the makefile expects a corresponding binary in this variable. The relation is constructed based on the order of files, where the first file in MAINFILES is related to the first binary in BINARIES, the second file with the second binary, and so on. Notice: you need to specify the relative path from the root of the project in both variables;
  • CXXFLAGS: flags to give to the C++ compiler;
  • LDFLAGS: "Extra flags to give to compilers when they are supposed to invoke the linker, ‘ld’, such as -L. Libraries (-lfoo) should be added to the LDLIBS variable instead" - GNU Make Manual;
  • LDLIBS: "Library flags or names given to compilers when they are supposed to invoke the linker, ‘ld’. LOADLIBES is a deprecated (but still supported) alternative to LDLIBS. Non-library linker flags, such as -L, should go in the LDFLAGS variable." - GNU Make Manual;
  • INCLUDE: the directories that should be added with -I flag. The INCDIR is added by default;
  • TMAINFILES: see MAINFILES, applied to tests;
  • TBINARIES: see BINARIES, applied to tests;
  • TCXXFLAGS: see CXXFLAGS, applied to tests;
  • TLDFLAGS: see LDFLAGS, applied to tests;
  • TLDLIBS: see LDLIBS, applied to tests;
  • TINCLUDE: see INCLUDE, applied to tests;
  • DEBUG: if different of 0, removes all supressing of commands echoing;

All the flags and libs specific to tests are appended to the flags and libs of the project.

Building

The basic goals supported so far by this makefile are listed bellow:

  • all: default goal. Compiles and links all binaries listed in BINARIES;
  • tests: compiles and links all binaries listed in TBINARIES;
  • clean: removes all generated objects and binaries;
  • distclean: executes clean and removes all generated dependencies as well;

Besides these goals, the makefile autogenerate goals with the name of each binary (from both, BINARIES and TBINARIES). It is also possible to give a specific name of a file, which will result in the execution of any rule to create or update it (if necessary).

Diagnosis

Not present in this Plane of Existence, yet.

Requirements

  • updated version of GNU Make (tested with 4.2.1, probably works with any version above 3.80);
  • compiler with support to dependency-related flags (used to generate dependency files); GCC/g++ is recommended;