when I use a completely generic rule to create executable files without specifying the rule name (I put it below) GNU Make 4.2.1 (running on wsl) creates relocatable files under the folders I specify, and after creating the executable, it removes them.
I also put whole makefile code at the end. Here is the generic code that I mentioned above:
# executable rule 1
%: $(PREQS_for_EXECUTABLES) $(MAIN_OBJ_DIR)%.o
@echo executable rule 1
$(CC) -o $@ $(wordlist 2, $(words $^), $^) $(CFLAGS) $(LIBS)
when I call this rule, from the shell, following lines are executed:
creating ./mains/obj/ ./sources/obj/
gcc -c -o sources/obj/testUtil.o sources/testUtil.c -I./headers/
gcc -c -o sources/obj/timeUtil.o sources/timeUtil.c -I./headers/
gcc -c -o sources/obj/quickSortVersions.o sources/quickSortVersions.c -I./headers/
gcc -c -o sources/obj/quickSortSubFns.o sources/quickSortSubFns.c -I./headers/
gcc -c -o sources/obj/experimentSetUp.o sources/experimentSetUp.c -I./headers/
gcc -c -o sources/obj/stringUtil.o sources/stringUtil.c -I./headers/
gcc -c -o mains/obj/main.o mains/main.c -I./headers/ -lm
executable rule 1
gcc -o main sources/obj/testUtil.o sources/obj/timeUtil.o sources/obj/quickSortVersions.o sources/obj/quickSortSubFns.o sources/obj/experimentSetUp.o sources/obj/stringUtil.o mains/obj/main.o -I./headers/ -lm
rm sources/obj/testUtil.o sources/obj/stringUtil.o sources/obj/quickSortSubFns.o sources/obj/quickSortVersions.o mains/obj/main.o sources/obj/timeUtil.o sources/obj/experimentSetUp.o
I didn't understand why it puts rm command at the end.
instead when I do this, It worked as I expected:
(here main, testMain, and rangen are some executable file names that I wanted for shell to advice me when I type make and hit tab)
# executable rule 2
main testMain rangen: %: $(PREQS_for_EXECUTABLES) $(MAIN_OBJ_DIR)%.o
@echo executable rule 2
$(CC) -o $@ $(wordlist 2, $(words $^), $^) $(CFLAGS) $(LIBS)
and also when I add those rules below, even if I still use executable rule 1 and and even those below rules are not refered anywhere and not used anywhere, It works as I expected:
# I even dont use those rules! They are refered nowhere
objects: $(OBJECTS)
@echo not refered rule
mainObjects: $(MAIN_OBJECTS)
# @echo not refered rule
Here is the whole makefile:
# https://www.gnu.org/software/make/manual/make.html
# https://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/
# make file is designed for the following file tree:
# ./
# | headers/ # a folder containing some headers designed by me.
# | mains/ # a folder containing .c files with int main(int,char**){} definitions.
# | sources/ # a folder containing .c files that are commonly used by main files.
# | makefile # this file.
# this makefile has rules
# to create the folders
# ./sources/obj/
# ./mains/obj/
# to compile relocatables
# from ./sources/*.c to ./sources/obj/*.o
# from ./mains/*.c to ./mains/obj/*.o
# and link relocatables in ./sources/obj/*.o with each one of ./mains/obj/*.o
# into an executable with same name with the associated main file.
# common source folder
SRC_DIR=./sources/
# header folder
HDR_DIR=./headers/
# common relocatable folder
OBJ_DIR=$(SRC_DIR)obj/
# folder with main files
MAIN_SRC_DIR=./mains/
# folder with main files' relocatables
MAIN_OBJ_DIR=$(MAIN_SRC_DIR)obj/
# ./mains/obj/ ./sources/obj/
ADDITIONAL_FOLDERS=$(MAIN_OBJ_DIR) $(OBJ_DIR)
# paths to c files with int main(int,char**){} definitions.
MAIN_SOURCES=$(wildcard $(MAIN_SRC_DIR)*.c)
# paths to common c files
SOURCES=$(wildcard $(SRC_DIR)*.c)
# paths to headers
HEADERS=$(wildcard $(HDR_DIR)*.h)
# paths to common relocatable files
OBJECTS=$(patsubst $(SRC_DIR)%.c, $(OBJ_DIR)%.o, $(SOURCES))
# paths to relocatables with int main(int,char**){} definitions.
MAIN_OBJECTS=$(patsubst $(MAIN_SRC_DIR)%.c, $(MAIN_OBJ_DIR)%.o, $(MAIN_SOURCES))
# prerequisites to create executable files.
PREQS_for_EXECUTABLES=folders $(OBJECTS)
IDIR =$(HDR_DIR)
CC=gcc
CFLAGS=$(patsubst %,-I%,$(IDIR))
DEPS=$(HEADERS)
LIBS=-lm
# create necessary folders
folders:
@(mkdir $(ADDITIONAL_FOLDERS) 1>/dev/null 2>/dev/null && echo creating $(ADDITIONAL_FOLDERS) \
|| echo folders $(ADDITIONAL_FOLDERS) already created)
# compiles relocatable requested as ./soruces/obj/*.o
$(OBJ_DIR)%.o: $(SRC_DIR)%.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
# compiles relocatable requested as ./mains/obj/*.o
$(MAIN_OBJ_DIR)%.o: $(MAIN_SRC_DIR)%.c
$(CC) -c -o $@ $< $(CFLAGS) $(LIBS)
EXECUTABLES=$(patsubst $(MAIN_SRC_DIR)%.c, %, $(MAIN_SOURCES))
.PHONY: clean
clean:
rm -rf $(EXECUTABLES) $(ADDITIONAL_FOLDERS)
# link one of main files from $(MAIN_OBJ_DIR) with ./sources/obj/*.o files
# into an executable with same name with the main file
# executable rule 1
%: $(PREQS_for_EXECUTABLES) $(MAIN_OBJ_DIR)%.o
@echo executable rule 1
$(CC) -o $@ $(wordlist 2, $(words $^), $^) $(CFLAGS) $(LIBS)
# # # main, testMain, and rangen were my main file names.
# # I added them here because I want for shell to advice them when I type make and hit tab.
# executable rule 2
main testMain rangen: %: $(PREQS_for_EXECUTABLES) $(MAIN_OBJ_DIR)%.o
@echo executable rule 2
$(CC) -o $@ $(wordlist 2, $(words $^), $^) $(CFLAGS) $(LIBS)
# executable rule 3
# test: $(PREQS_for_EXECUTABLES) $(MAIN_OBJ_DIR)test.o
# @echo executable rule 3
# $(CC) -o $@ $(wordlist 2, $(words $^), $^) $(CFLAGS) $(LIBS)
# main: $(PREQS_for_EXECUTABLES) $(MAIN_OBJ_DIR)main.o
# @echo executable rule 3
# $(CC) -o $@ $(wordlist 2, $(words $^), $^) $(CFLAGS) $(LIBS)
# rangen: $(PREQS_for_EXECUTABLES) $(MAIN_OBJ_DIR)rangen.o
# @echo executable rule 3
# $(CC) -o $@ $(wordlist 2, $(words $^), $^) $(CFLAGS) $(LIBS)
# it behaves different when I use executable rule 2 or 3 instead of executable rule 1
# or when I add those lines to file
# # I even dont use those rules! They are refered nowhere
# objects: $(OBJECTS)
# @echo not refered rule
# mainObjects: $(MAIN_OBJECTS)
# # @echo not refered rule
# in short, if I use executable rule 1, it removes relocatable files after using them.
# if I use executable rule 2 or 3, or if I turn above rules (objects, mainObjects) on,
# even if they are not refered anywhere, it works as I expected.
I see that this is a similar post, But I still don't understand why the following rule doesn't interprete the object files as intermediate.
main testMain rangen: %: $(PREQS_for_EXECUTABLES) $(MAIN_OBJ_DIR)%.o
@echo executable rule 2
$(CC) -o $@ $(wordlist 2, $(words $^), $^) $(CFLAGS) $(LIBS)