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;)
Related
I'm building a linux kernel module written in ASM and C.
individually, the code can compile, but I can't figure out how to compile it together (Both C and ASM files).
I have 2 c files (entry.c, cpu_checks.c), 1 header file (cpu_checks.h) and 1 assembly file (cpu.asm).
I'm trying to compile all to .o object files and then link them together. My problem is that for some resaon the makefile doesn't recognize the rule for building .asm files.
This is how my makefile looks as of now:
CONFIG_MODULE_SIG=n
KDIR ?= /lib/modules/`uname -r`/build
DRIVER_DIR=path/to/driver/dir
CC = gcc
CFLAGS += -g -DDEBUG
LD = ld
LDFLAGS = -melf_i386
NASM = nasm
NASMFLAGS = -f elf64 -F stabs
obj-m := hyper.o
hyper-objs := $(patsubst $(DRIVER_DIR)/%.asm, $(DRIVER_DIR)/%.o, $(wildcard $(DRIVER_DIR)/*.asm))
hyper-objs += $(patsubst $(DRIVER_DIR)/%.c, $(DRIVER_DIR)/%.o, $(wildcard $(DRIVER_DIR)/*.c))
default:
make -C $(KDIR) M=$(PWD) modules
$(LD) $(LDFLAGS) $(hyper-objs)
# Makefile recognizes this rule.
$(DRIVER_DIR)/%.o: $(DRIVER_DIR)/%.c
$(CC) $(CFLAGS) $# $<
# Makefile doesn't recognize this rule.
$(DRIVER_DIR)/%.o: $(DRIVER_DIR)/%.asm
$(NASM) $(NASMFLAGS) $#
clean:
rm -rf *.o *~
real_clean:
rm -f *.o *.ko *~
I'm not very good at writing makefiles, so I might (even probably) have written something wrong. If not, what can I do to et the makefile to recognize that rule?
The problem is that your default: rule doesn't have any dependencies to check. So it will just run the commands under it without building any of the .o files that you need. Adding $(hyper-objs) as a dependency will ensure all the .o files are built first
default: $(hyper-objs)
I'm trying to create a generic Makefile to use with most of my projects. It should work as follows: only rebuild and link those .o files whose .c or .h dependency has changed. The .o and .d files are stored in a separate directory called 'build'.
With the help of the official GNU Make manual and some googling I've managed to achieve the desired behavior except for one thing: when I run make re I get the error:
Assembler messages: Fatal error: can't create build/ft_build_buffer.o: No such file or directory — the reason for this is that the 'build' directory only gets created whenever the .d files are generated, but for some reason the re rule simply skips this step and goes on to compile .o files straight away! Note: if I run make clean && make fclean && make all (which should be the exact same thing) everything works fine.
A few other things: I've tried using the -MMD option to generate dependencies on the fly but on my machine that causes the .d files to only contain .c dependencies. Of course I could just make all .c files depend on all .h files but that seems like a very sloppy solution.
Feel free to share any other advice/improvements that will make this file more clean and readable, thanks! :)
# Define the C compiler to use.
CC := gcc
# Define any compile-time flags.
CFLAGS := -I./include -Wall -Wextra -Werror -g
#CFLAGS := -I./include -march=native -O2 -pipe
# Define the executable file.
BIN := ft_hexdump
# Define build directory.
BUILD_DIR := build
# Define source files directory.
SRC_DIR := src
# Define the C source files.
SRCS := $(wildcard $(SRC_DIR)/*.c)
# Define the C object files.
OBJS := $(SRCS:$(SRC_DIR)/%.c=$(BUILD_DIR)/%.o)
# Define the prerequisite files.
DEPS := $(OBJS:%.o=%.d)
.PHONY: all clean fclean re
.DELETE_ON_ERROR:
all: $(BIN)
-include $(DEPS)
$(BIN): $(OBJS)
$(CC) $(CFLAGS) $^ -o $#
$(BUILD_DIR)/%.o: $(BUILD_DIR)/%.d
$(CC) $(CFLAGS) -c $(SRC_DIR)/$*.c -o $#
$(BUILD_DIR)/%.d: $(SRC_DIR)/%.c
#mkdir -p $(#D)
#set -e; rm -f $#; \
$(CC) $(CFLAGS) $(INCLUDE) -MM $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
clean:
-rm -rf $(BUILD_DIR)
fclean: clean
-rm -f $(BIN)
re: fclean all
Here is the modified working version as suggested by #M.M
# Define the C compiler to use.
CC := gcc
# Define any compile-time flags.
CFLAGS := -I./include -Wall -Wextra -Werror -g
#CFLAGS := -I./include -march=native -O2 -pipe
# Define the executable file.
BIN := ft_hexdump
# Define build directory.
BUILD_DIR := build
# Define source files directory.
SRC_DIR := src
# Define the C source files.
SRCS := $(wildcard $(SRC_DIR)/*.c)
# Define the C object files.
OBJS := $(SRCS:$(SRC_DIR)/%.c=$(BUILD_DIR)/%.o)
# Define the prerequisite files.
DEPS := $(OBJS:%.o=%.d)
.PHONY: all clean fclean re
.DELETE_ON_ERROR:
all: $(BIN)
-include $(DEPS)
$(BIN): $(OBJS)
$(CC) $(CFLAGS) $^ -o $#
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
#mkdir -p $(#D)
$(CC) $(CFLAGS) -MMD -c $(SRC_DIR)/$*.c -o $#
clean:
-rm -rf $(BUILD_DIR)
fclean: clean
-rm -f $(BIN)
re:
$(MAKE) fclean
$(MAKE) all
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
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/.
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