There is a small C library consisting of three files:

  • lib.h - code
  • test.c - tests
  • debug.h - additional code for tests.

I want to write a Makefile to:

  • Compile all make files. They should appear in the out directory. It is not necessary to create it, it is always there, it contains a .gitkeep file and is itself added to .gitignore .
  • Run tests by make test.out/test -v .
  • Clean up the results of the last two actions on make cleangit clean -fdx out .

Here's what happened so far:

 .PHONY: all test out/lib: lib.h gcc -o out/lib lib.h out/test: test.c lib.h debug.h gcc -o out/test test.c all: out/lib out/test test: out/test ./out/test -v clean: git clean -fdx out 

Problem 1: the make command only creates out/lib . However, make test works for it: first compiles out/test , then runs it.

UPD: fixed by setting the target all: ... before out/lib and out/test . Now both are going. However, for test: ... this is not required, the goal described earlier is fully recognized. I still do not understand the logic.

Problem 2: the development environment (CLion with the Makefile plugin) underscores the red details for out/lib and out/test with the message "Unresolved prerequisite" and suggests making "Create Rule". I don’t understand why files from the disk should be declared as targets, but I won’t do make lib.c

What am I doing wrong? I met make a couple of hours ago, do not hesitate to explain the most basic things.

  • without parameters, make starts the very first target. But you can always write the name of the goal and he will fulfill it. And the fact that CLion emphasizes - and who knows. Not the fact that his developers know the syntax of the Makefile. By the way, make lib.c - you can write there. This is a valid target. It will default to gcc -o lib lib.c - KoVadim
  • @KoVadim aha, that makes it all clear. Developers of a plugin for working with a Makefile probably need to know the syntax of the Makefile, but they do not really explain the proposed replacements. - Nick Volynkin
  • The most important thing to remember about a makefile is a tab. that is, goals start from the first position, but the teams inside them get off strictly tabom. - KoVadim
  • @KoVadim yes, in the code I have tabs everywhere, although here the editor replaced them with spaces. - Nick Volynkin
  • simply to the word: the desire to add the results of processing in a separate directory - in my humble opinion, unconstructive and meaningless. the fact that some ide does this way does not justify their developers in any way. // clion, by the way, you are slightly hinting at this (unconstructiveness and meaninglessness). - aleksandr barakin

1 answer 1

The first thing you do wrong is trying to use a separate (from the current source) directory for “folding” the results of source processing. normal practice: create a directory, put the makefile in it, source, process it (with the make program), save the result in the same directory.


the second thing you are doing wrong, or rather, you understand wrong - this is the choice of the “silent” goal. that is, the goal that will be executed if the make program does not explicitly specify any goal.

this is how the first met in the first (or explicitly specified) makefile target will be executed (search order for makefiles if the name is not explicitly indicated using the -f option: GNUmakefile , makefile , Makefile ).

if you want the default to execute a target with a name, for example, первая_цель , then put it first . caveat: in principle, the implementation itself (and prerequisites) of the target can be left somewhere “in the depths” of the file, but then you still need to put a “stub” at the beginning of the file:

 # это строка-заглушка, необходимая просто для обозначения того, что # «первая_цель» — это «умолчальная» цель первая_цель: другая_цель: пререквизиты команды первая_цель: её_пререквизиты команды_для_выполнения_этой_цели 

It is also worth mentioning the special variable .DEFAULT_GOAL , with which you can override the "default" target.

  • I do not agree with trying to use a separate directory for "folding" the results of source code processing . when working with the project, creating separate directories for source code files, object files, libraries. A fairly common practice. - Yaroslav
  • To me, folding everything into one folder seems like a mess. Now I need to add the doxygen config and shell script for building and publishing documentation. If they also lie in the root, then the result will be 10 files lying next to each other, of which only three are code, the rest are official. - Nick Volynkin
  • Take at least github.com/torvalds/linux : Makefile in the root, code in the subdirectories. - Nick Volynkin
  • A fairly common practice. - probably in the area that you are more familiar. - aleksandr barakin
  • Take at least github.com/torvalds/linux: Makefile in the root, code in the subdirectories. - incorrect statement. do a search for files named [Mm]akefile and the like (often use the suffix .mk ) and see for yourself. - aleksandr barakin