0

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)

  • I have no idea what a "solid instance of a relocatable file" is. – MadScientist Jan 15 '23 at 14:01
  • I mean, no file is created. But object files are used as they exist. – faruk yıldırım Jan 15 '23 at 14:33
  • It's not clear to me exactly what the problem is. I recommend you run `make` then cut and paste (with formatting) the make command you invoked and the output you got, and then point out explicitly what part of the results you don't like or aren't how you expect, and what you wanted to happen instead. – MadScientist Jan 15 '23 at 14:46
  • I corrected the problem report now – faruk yıldırım Jan 15 '23 at 14:50
  • I misinterpreted the problem before. now, I see This kind of question is answered before. – faruk yıldırım Jan 15 '23 at 15:01
  • Does this answer your question? [Why does make delete my temporary files?](https://stackoverflow.com/questions/14776258/why-does-make-delete-my-temporary-files) – John Bollinger Jan 15 '23 at 16:11
  • Executable rule 1 is a pattern rule. It cannot be used directly to build the ultimate target(s); they have to be specified on the command line or as prerequisites of another rule. In this case, the `.o` files are *intermediate files*, which `make` automatically deletes when they are no longer needed (for the build). "Executable rule 2" is a static pattern rule that is 100% equivalent to the collection of three target rules specified as "executable rule 3". The .o files are explicitly named as prerequisites here, and therefore are not "intermediate" in the relevant sense. – John Bollinger Jan 15 '23 at 16:17
  • Thanks to everyone, now I got the point – faruk yıldırım Jan 15 '23 at 17:18

0 Answers0