News for hackers. Stuff that matters.
Re:Benefits of Not Using an IDE by adrian_b on Saturday August 21, 2021 @03:04PM (#28259597)
The good editors for programmers, since ancient times, for example already in the BRIEF editor for MS-DOS, before 1990, provide means to attach arbitrary CLI commands or scripts to menus or keyboard shortcuts.

Therefore, if you want you can invoke from inside the editor any commands needed for project management or for compiling/linking/running/debugging.

So in the end you are right that a powerful editor can do what an IDE does, after some customization.

The main difference with IDE's is that the project management provided by the IDE is normally non-optional, you are forced to always use it.

In 30 years of experiencing a very large number of IDE's I have not seen even a single one where using its project management functions would not waste a lot of time comparing to non-integrated alternatives.

I think that it is sad that only a very small number of developers know how to use correctly the ancient program "make". I do not know why this happened. To use correctly "make" I have never needed anything else besides reading the GNU make manual provided with gmake, but it seems that very few people read the manual.

The only time when I had to write makefiles was more than 20 years ago, when I have written a set of universal makefiles, which I have been using unchanged for every software project ever since. For any new project I need to just (optionally) add a file with some extra definitions, e.g. a list of directories where the source files are located or the names of the executables or libraries that must be built. If no definitions are provided, suitable defaults are used, e.g. the directory with the Makefile also contains the source files and the target is an executable with the same name as the directory. The Makefile per target directory may contain just a single line, with an include directive for the universal makefile. The universal makefile searches all the source directories for all the possible types of source files, selects automatically the appropriate compilers based on the language indicated by the file name extensions and on the cross-compilation target if one is specified, generates automatically all the dependencies and so on.

Instead of using "make" like this, almost all the open-source projects that I have seen have huge and immensely complicated makefiles that are much more difficult to read, understand and modify than the source files of the programs. When the makefiles are generated from templates, those are typically even more difficult to understand and modify.

I have no idea who loves those extremely complex methods of compiling and building software projects.

During the years, a lot of replacements for "make" have been introduced, which are better than "make" used wrongly, but I have not seen any which is better than "make" used rightly, without pointless complications.

Re:Benefits of Not Using an IDE by cweagans on Saturday August 21, 2021 @06:16PM (#28261045)
Have you published this makefile somewhere? I’d love to take a look at it.
Re:Benefits of Not Using an IDE by adrian_b on Sunday August 22, 2021 @01:16AM (#28263075)
It is not published, but there is not really much about it, except exploiting most features provided by gmake.

For easy maintenance, the universal makefile is split into 4 files that are completely universal + 1 makefile with extra definitions per each combination of operating system and CPU type that might be a target for compilation.

The extra files for specific compilation targets, e.g. skylake-linux-gnu, armv7e-m4-none-eabi, i686-cygwin and so on, contain definitions for the names of all the tools that might be used, e.g. compilers for various programming languages, linking commands, librarian commands, binary file modification commands (e.g. objcopy), default locations for library files, default locations for include files, default values for compilation flags.

The 4 completely universal files do not contain directly any command name or command flags or any file name or any directory name. They contain only variable names whose values are either defined in the operating system/CPU specific makefile or whose values are determined by the make command by scanning the project and by transforming the found files, e.g. by replacing the file name extensions.

The 4 completely universal files are:

1. A file for the top directory of a complex project, which descends recursively in all subdirectories and runs there the given make command, if a Makefile exists in the subdirectory

2. A file with make targets. Examples of make targets:

clean:

$(RM) $(RMFLAGS) $(MAP) $(BIN) $(IMPLIB) $(EXE) $(LIB) $(WEXE) $(DLIB)

$(RM) $(RMFLAGS) $(OBJS) $(OBJS:.o=.d) $(OBJS:.o=.lst)

and

all : $(EXE) $(LIB) $(WEXE) $(DLIB)

The 4 variables above are the files to be built, respectively CLI executables, static libraries, GUI executables and dynamic libraries.

As I have said everything must be expressed using variables that will be defined elsewhere.

3. A file with make rules, for how to build any kind of file that might be encountered. Examples of rules:

%.o: %.c

$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ -c $<

%.s: %.cpp

$(CXX) $(CXXFLAGS) $(DEFINES) $(INCLUDES) -o $@ -S $<

%.d: %.cpp

$(CXX) $(CXXFLAGS) $(DEFINES) $(INCLUDES) -MD -o $(@:.d=.o) -c $<

4. A file with definitions, which is the most important in simplifying the makefiles needed for any new project, which are typically almost empty, because they do not need any other line besides including the universal makefile, even if I usually add a definition with a list of source directories, in order to separate the place where the project is built from the place where the source files are stored and possibly some options, e.g. building a debug version instead of a release version, or building for a cross-compilation target.

Example how to determine the directories with source files:

ifeq "$(strip $(SOURCE_DIRS))" ""

SOURCE_DIRS := .

endif

ifeq "$(strip $(PREFIX_DIR))" ""

VPATH := $(SOURCE_DIRS)

else

VPATH := $(addprefix $(PREFIX_DIR)/, $(SOURCE_DIRS))

endif

Example of how to scan the source directories for source files written in a certain programming language:

CPP_FILES := $(notdir $(wildcard $(addsuffix /*.cpp, $(VPATH))))

The list for every kind of source files is stored in a corresponding variable like above.

For the source files that are compiled to object files, the list of object files that must be made is computed so:

OBJS := $(CPP_FILES:.cpp=.o) $(C_FILES:.c=.o) $(SS_FILES:.S=.o) $(S_FILES:.s=.o) $(O_FILES)

I use many more kinds of source files, so the OBJS above is just a shortened example.

The operating system/CPU type specific makefile includes the 3 universal files with targets, rules and definitions and it also includes the automatically generated dependencies:

include $(OBJS:.o=.d)

so later only the specific makefile needs to be included, depending on the compilation target.

There are many more details, but these are the general principles. They are intended to make me write as little as possible in the Makefile for a new project.

If I do not define in the Makefile from the project directory what shall be built with "make all", then either an executable is built, having the same name as the Makefile directory, or another kind of file is built, if the directory has a special suffix, e.g. a static library for a directory ending in "_lib".

When I add, delete, move or rename source files, I do not have to do anything for project management, except doing a "make clean" before that, because the next "make" will update the lists of source files.