An unexpected rm occur after make - c

This is the main part of my makefile:
#openmp
ifeq($(BLITTZ_CC), icc)
OPENMP_OPTIONS := -fopenmp
else
OPENMP_OPTIONS := -fopenmp
endif
#compiler options
CXXFLAGS := -WALL -Wno-unused-parameter $(OPTIMIZE_OPTIONS) $(OPENMP_OPTIONS) $(MODE)
SRC_LIST := $(wildcard $(SRC_DIR)/*.cpp)
OBJ_LIST := $(patsubst %.cpp, $(BUILD_DIR)/%.o, $(notdir $(SRC_LIST)))
TARGET := main
BIN_TARGET := $(BIN_DIR)/$(TARGET)
$(BIN_TARGET): $(OBJ_LIST)
$(BLITZ_CC) -o $# $(OBJ_LIST) $(CXXFLAGS)
$(BUILD_DIR)/%.o: $(BUILD_DIR)/%.s
$(BLITZ_CC) -o $# -c $< $(CXXFLAGS)
$(BUILD_DIR)/%.s: $(SRC_DIR)/%.cpp
$(BLITZ_CC) -o $# -S $(CXXFLAGS) $<
#inc test
test:
echo $(SRC_LIST)
echo $(OBJ_LIST)
echo $(BIN_TARGET)
#clean
clean:
find $(BUILD_DIR) -name *.o -exec rm rf {} \;
find $(BUILD_DIR) -name *.s -exec rm rf {} \;
rm $(BIN_DIR)/*
This is what happens after make:
Why does rm *.s occur here? I need the assemble files and I do not want to delete them.

Because you've chained rules to create your .o files from your .cpp files, make marked your .s files as intermediate files and deleted them after building your target:
[...] an intermediate file which did not exist before make also does not exist after make.
You need to either mark your files as secondary files:
.SECONDARY: $(OBJ_LIST:.o=.s)
When a file is secondary, make will not create the file merely because it does not already exist, but make does not automatically delete the file.
Or you can flag your file pattern as precious:
.PRECIOUS: %.s
You can list the target pattern of an implicit rule (such as ‘%.o’) as a prerequisite of the special target .PRECIOUS to preserve intermediate files made by implicit rules whose target patterns match that file’s name; [...]

find $(BUILD_DIR) -name *.s -exec rm rf {} \; will get all .s files and execute rm rf so delete that line if you want to keep .s files

Related

Makefile can I execute a configuration only once?

Im trying to create a Makefile which compiles some files and creates some outputs but first I want it to execute the configuration only one time and the next time I type make it wont re-execute the configuration unless I change the parameters for example the prefix.
I tried using touch , FORCE and if, after searching a bit in other posts but Im newbie in gcc and Makefiles so I cant make it work.
My code now is (did not include the other rules because they dont affect the configuration):
XLEN := 32
RISCV_PREFIX := riscv$(XLEN)-unknown-elf-
RISCV_GCC := $(RISCV_PREFIX)gcc
CFLAGS := -O2
WORKING_DIR:= $(shell pwd)
LIBRARY_DIR:= $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/..)
B := $(shell echo $(LIBRARY_DIR))
$(info $(B))
--->(execute this only once)---> CONFIGURATION := configure --prefix=$(LIBRARY_DIR) --with-arch=rv32if --with-abi=ilp32d
RISCV_TEST_DIR:=$(shell pwd)
SCRIPTDIR:=$(RISCV_TEST_DIR)/../../tools
RISCV_OPTIONS = -o
RISCV_LINK = $(RISCV_GCC) $(PROGRAMS) $(RISCV_OPTIONS) $# $(CFLAGS) #produces .elf file!
RISCV_OBJDUMP = $(RISCV_PREFIX)objdump -D #produces a dump file to see the assembly code!
RISCV_OBJCOPY = $(RISCV_PREFIX)objcopy -O binary #produces a bin file!
%.elf: %.c
$(info Generating .elf file from files: $(PROGRAMS_NO_EX))
$(RISCV_LINK)
$(info Success!)
$(info ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)
%.dump: %.elf
$(info Copying assembly to dump file $(PROGRAMS_NO_EX).dump)
#$(RISCV_OBJDUMP) $< > $#
$(info Success!)
$(info ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)
%.bin: %.elf
$(info Generating bin file)
#$(RISCV_OBJCOPY) $< $#
$(info Success!)
$(info ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)
%.hex: %.bin
$(info Generating hex file)
echo cd $(SCRIPTDIR)
$(info Running binary to hex >>>)
python $(SCRIPTDIR)/bin2hex.py $< -a 0x0 > $# || exit -1
$(info Hex Generation Successful!)
$(info ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)
all: $(PROGRAMS_TO_CREATE); if [ -a $(LIBRARY_DIR)/config.status ]; then cd $(LIBRARY_DIR) && $(CONFIGURATION); fi;
configure: config.status
touch configure
config.status:
cd $(LIBRARY_DIR) && $(CONFIGURATION);
.PHONY: all clean
clean:
$(info Cleaning files...)
#rm -rf *.elf *.hex *.map *.objdump *.i *.s *.bin *.dump
$(info Done cleaning!)
Thank you in advance!
I believe the only problem with your configuration statements are incorrect paths in rules for config.status and configure, since they really will be located within $(LIBRARY_DIR). When the paths are correct, it will correctly run configuration only once:
$ cat Makefile
LIBRARY_DIR := library
all: $(LIBRARY_DIR)/config.status
$(info Making $#)
$(LIBRARY_DIR)/config.status: $(LIBRARY_DIR)/configure
cd $(<D) && ./$(<F)
Output:
$ make
cd library && ./configure
Making all
$ make # <--- Invoking second time, no configure step
Making all
make: 'all' is up to date.
With #raspy's help managed to solve the problem like this:
all: $(PROGRAMS_TO_CREATE)
$(PROGRAMS_TO_CREATE):$(LIBRARY_DIR)/config.status
$(LIBRARY_DIR)/config.status:
cd $(LIBRARY_DIR) && $(CONFIGURATION)

Compiling and linking subfolders using different Makefiles

I have a client/server application in C. The server has its own folder dserver, the same for the client dclient. Using both of them some files containing utility functions, I created another directory at the same level of the previously ones, named common.
My idea is to create each Makefile in each subfolder (one in dserver, one in dclient and another in common) and then one Makefile in the main directory which will run the other Makefiles which looks like:
all:
+$(MAKE) -C common
+$(MAKE) -C dserver
+$(MAKE) -C dclient
The first problem is that the common/Makefile should not create an executable but only create the object files that will be needed to create the executable for the client and for the server. In my case it is:
CXX = gcc
SOURCEDIR := ./
SOURCES := $(wildcard $(SOURCEDIR)/*.c)
OBJDIR=$(SOURCEDIR)/obj
OBJECTS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.o, $(SOURCES))
DEPENDS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.d, $(SOURCES))
# ADD MORE WARNINGS!
WARNING := -Wall -Wextra
$(OBJDIR)/%.o: $(SOURCEDIR)/%.c Makefile | $(OBJDIR)
$(CXX) $(WARNING) -MMD -MP -c $< -o $#
$(OBJDIR):
mkdir -p $(OBJDIR)
My problem is that it is creating the object directory specified by OBJDIR but not the object files *.o: how should it be?
Secondly in the client and server Makefiles I should both include path to the files in common and then referencing the object files in the resulting from the compilation of common to build the executables. So taking for example the dserver/Makefile I added the line INC_PATH = -I../common/ and referencing it in the compilation as $(CXX) $(WARNING) -MMD -MP -c $(INC_PATH) $< -o $#. However in the code I had to do #include "../common/utilities.h".
Is there a way to include the path in the Makefile so that in the code it allows to do just: #include "utilities.h"?
And also, supposing that common has its own object directory containing the object files needed both by the client and server, how build, for example the server executable referencing the object files both in the common directory and the ones specific and contained in the server directory?
The dserver/Makefile is something like (and the dclient/Makefile has the same structure):
CXX = gcc
INC_PATH = -I../common/
SOURCEDIR := ./
SOURCES := $(wildcard $(SOURCEDIR)/*.c)
OBJDIR=./obj
OBJECTS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.o, $(SOURCES))
DEPENDS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.d, $(SOURCES))
# ADD MORE WARNINGS!
WARNING := -Wall -Wextra
# .PHONY means these rules get executed even if
# files of those names exist.
.PHONY: all clean
# The first rule is the default, ie. "make",
# "make all" and "make parking" mean the same
all: server
clean:
$(RM) $(OBJECTS) $(DEPENDS) server
# Linking the executable from the object files
# $^ # "src.c src.h" (all prerequisites)
../server: $(OBJECTS)
$(CXX) $(WARNING) $(INC_PATH) $^ -o $#
#$(CXX) $(WARNING) $(CXXFLAGS) $(INC_PATH) $^ -o $# $(LIBS)
-include $(DEPENDS)
$(OBJDIR):
mkdir -p $(OBJDIR)
$(OBJDIR)/%.o: $(SOURCEDIR)/%.c Makefile | $(OBJDIR)
$(CXX) $(WARNING) -MMD -MP -c $(INC_PATH) $< -o $#
You don't specify any rules for building the objects in your "common" Makefile - this is the only rule you have.
$(OBJDIR):
mkdir -p $(OBJDIR)
You want to put a rule before that to all get it to build the objects, maybe something along the lines of:
all: $(OBJDIR) $(OBJECTS)
It has to go before the original rule as if you don't specify what is being built, make will do the first rule it finds.
Including header files from "common" in your other directories should be working just fine by using -I../common/.
Using the objects from "common" should just be a case of adding them to the list of objects ie:
COMMON_OBJECTS=../common/obj/utilities.o
../server: $(OBJECTS) $(COMMON_OBJECTS)
Or having them built into a library so you don't need to know what object files there are.
Also it's worth noting that $(CXX) is the variable used to store the C++ compiler - for building with the C compiler you want to be using $(CC) and $(CFLAGS).

Make implicit rules with GCC: Redirecting *.o

I am trying to get make to do the following with an implicit rule:
obj/lsabase.o : inc/lsabase.h lsabase.c
cc -c lsabase.c && mv lsabase.o obj
I searched for ways to redirect the output of "cc -c .." with compiler options, but didn't find any here.
Also the implicit rule defined for compiling from source to object only lets you use $(CPPFLAGS) and $(CFLAGS).
Does anybody know how to trick make into using this (mv lsabase.o obj) in an implicit rule, so I can put all *.o files in a seperate directory?
obj/lsabase.o : inc/lsabase.h lsabase.c
cc -I"inc" -c lsabase.c -o obj/lsabase.o
I would
avoid doing the mv manually but rather telling gcc to put in the obj dir
let gcc handle the dependencies (by creating .d files)
and here is what I usually do when all my .c files are in a subdir and I want to compile all of them in a parallel dir obj (that I can easily remove):
default: my_code
#add subdirs
DIRS := $(shell find src -type d)
#add include directives for subdirs
CFLAGS += $(DIRS:%=-I%)
#collect all c files
SRCS := $(shell find src/* -name \*.c)
OBJS := $(addprefix obj/, $(SRCS:.c=.o))
DEPS := $(addprefix obj/, $(SRCS:.c=.d))
# this generates a dependency file for every .c
obj/%.d: %.c
# mkdir -p "$(#D)"
# echo "Checking dependencies for $<"
# create and modify dependecy file .d to take into account the location obj (sed magical)
# gcc $(CFLAGS) -MM $< 2>/dev/null | sed -e "s#\(^.*\)\.o:#obj/$(shell dirname $<)/\1.d obj/$(shell dirname $<)/\1.o:#" > $#
#this compiles
obj/%.o : %.c
gcc $(CFLAGS) -c $< -o $#
#this creates the executable
my_code: $(OBJS)
gcc $(OBJS) -o $# $(LDFLAGS)
# this does the magic
-include $(DEPS)
clean:
rm -rf obj
If you're new to Make, this might seem difficult, but it's really powerful once you get through.
you can write the makefile rule this way:
obj/lsabase.o : lsabase.c inc/lsabase.h
<tab>cc $(CFLAGS) -c $< -o $# -Iinc/.
where, in the actual makefile, the <tab> would be replaced with an actual tab character
Notice the *.c file is first in the list of dependencies, so can use the $< shortcut
You mentioned wanting to do this for all the object files..
obj/$.o : %.c inc/%.h
<tab>cc $(CFLAGS) -c $< -o $# -Iinc/.
However, that may not be the most flexible. For maximum flexibility, suggest adding a rule to generate and include dependency files named *.d. Then using:
obj/$.o : %.c %.d
<tab>cc $(CFLAGS) -c $< -o $# -Iinc/.

using loop in GNU makefile

Can anyone help me figure out why am I not be bale to pass different versions of .ll files to LLVM_OPT here? Is there a way in makefile to extract each basename of those $(SRC) to pass to opt?
So the scenario is compiling *.c with clang and then applying opt with $(CCC_OPT) to each individual *.ll to transform them to $file_Opt.ll. At last, clang generate the backend a.out by linking all $file_Opt.ll.
BENCHMARK = $(shell basename `pwd`)
SRC := $(wildcard *.c)
HEADERS := $(wildcard *.h)
# Actions
.PHONY: all clean vclean
all:
$(ZCC) $(HEADERS) $(INCPATHS) $(SRC)
$(foreach var,$(SRC), $(CC_OPTS) $(CCC_OPTS) -S -o $(var)_llvmOpt.ll $(var).ll;)
$(LCC) -v *_llvmOpt.ll -lm
clean:
rm -f a.out *.o *.a *.s *.i *.I
vclean:
rm -f a.out *.o *.a *.s *.i *.I *.ll
output:
opt: loop-wrap.c.ll: error: Could not open input file: No such file or directory
make: *** [all] Error 1
Two choices for removing the .c suffix from the filename.
You can use the Text Function patsubst directly:
$(foreach var,$(patsubst %.c,%,$(SRC)),$(CC_OPTS) $(CCC_OPTS) -S -o $(var)_llvmOpt.ll $(var).ll;)
Or through a Substitution Reference.
$(foreach var,$(SRC:.c=),$(CC_OPTS) $(CCC_OPTS) -S -o $(var)_llvmOpt.ll $(var).ll;)
Or, and this is arguably more correct, you could also use the Functions for File Names function basename for this:
$(foreach var,$(basename $(SRC)),$(CC_OPTS) $(CCC_OPTS) -S -o $(var)_llvmOpt.ll $(var).ll;)

Make error when trying to create *.o

I'm at my wits end here because of this extremely stupid error I'm getting from my makefile.
I finally gave up stripped the makefile down to just two lines:
%.o: %.c
gcc -c -o $# $< -I../inc
Command: make . The output:
make: *** No targets. Stop.
The spaces at the beginning are real tabs instead of spaces. The c files are in the same directory. If instead of %.o I give, say, file1.o and file1.c instead of %.c, all is well (file1.o gets created). I see plenty of examples on the 'net that use the % operator, though. If I include a clean: target, it is promptly found, like so:
%.o: %.c
gcc -c -o $# $< -I../inc
clean:
echo "this is clean!"
Command: make . The output:
echo "this is clean!"
this is clean!
Please help me out here as I'm totally clueless about what's wrong with my targets. In the second sample (the one with clean target), I guess the clean target is found and acted upon as the first one is 'invalid' somehow.
Looks like you forgot to write a target. You have just written rules of how to compile, but not what to do with those objects. I mean, I miss something like:
my_executable_file: *.o
gcc -o my_executable_file *.o
EDIT:
What is set before is true, you need a target. But as you want only to compile, your target should be something like:
OBJECTS = file.o #and whatever objects you need, as a list separated by commas
And then your target:
my_objects: $(OBJECTS)
So putting it all together:
OBJECTS = file.o #and whatever objects you need, as a list separated by commas
my_objects: $(OBJECTS)
%.o: %.c
gcc -c -o $# $< -I../inc
Below is the Makefile that will enable to any number of targets to compile
OBJ := file.o
all: $(OBJ)
%.o: %.c
gcc -c -o $# $< -I../inc
clean:
echo "this is clean!"
Here, OBJ will be the list of the files that you want to compile , like here it is file.c
Add the file name you want to compile to OBJ, when make is called it will build the target all first which depends on the OBJ.
To build OBJ the gcc command is used.
When an explicit target is not given to make, then the first (non-pattern?) target in the Makefile is used. In the case above, it is the clean target.
I see your intention to make only .o files (can be needed for creation of libraries).
You can modify your Makefile to build only .o files or build only executable by using the same Makefile
For the below directory structure (using tree command)
# tree .
.
|-- include
| `-- head.h
|-- Makefile
|-- obj
`-- src
`-- main.c
Makefile
# GNU Makefile #
# Some Variables #
CC := gcc
RM := rm
MV := mv
# Phony Targets #
.PHONY: clean
.PHONY: move
# Path for Source, Object and Include #
SRC_PATH := ./src/
OBJ_PATH := ./obj/
INCLUDE_PATH := ./include/
# Source and Object File Names #
SRC := $(SRC_PATH)main.c
OBJ := $(SRC:c=o) # Substitutes all SRC but with .c as .o (main.c becomes main.o) #
# Executable Name #
TARGET := exe
# Building Binary - use 'make' #
binary: $(TARGET) move
$(TARGET): $(OBJ)
$(CC) -o $(TARGET) $^
# Building only Object Files - use 'make object_only' #
object_only : $(OBJ) move
$(OBJ): $(SRC)
$(CC) -c -o $# $< -I $(INCLUDE_PATH)
# This rule is for moving .o files to ./obj directory (More Organised) #
move:
$(MV) $(SRC_PATH)*.o $(OBJ_PATH)
# For Cleaning - use 'make clean' #
clean:
echo "Cleaning Up!"
$(RM) -rfv $(TARGET) $(OBJ_PATH)*.o $(SRC_PATH)*.o # Delete .o and executable #
Execution:
To build only object files use
$ make object_only
To build object files and executable, use
$ make

Resources