I did not succeed to fix the issue while executing the following code:
%.o: %.c
if [ $(notdir $<) = file1.c ]; then \
echo " >> $(notdir $<) is excluded"; \
else\
ifneq ($(FLAG1),)
$(run_function1)
endif
ifneq ($(FLAG2),)
$(run_function2)
endif
fi
The issue is the following:
if [ file2.c = file1.c ]; then \
echo " >> file2.c is excluded"; \
else\
ifneq (,)
/bin/sh: -c: line 4: syntax error near unexpected token `,'
/bin/sh: -c: line 4: ` ifeq (,)'
Any idea?
You are mixing Shell and Makefile syntax in the recipe. Keep in mind the recipe is passed to the shell pretty much un-modified except for $() variable expansions (i.e.: the ifneq and similar Make conditionals are not expanded if they are indented). See especially the first paragraph and 4th bullet of the documentation here: https://www.gnu.org/software/make/manual/html_node/Recipe-Syntax.html
What you meant to say is something like this, but this does not work due to the \ line continuation subsuming the subsequent ifndef/endif (ideas anyone?):
%.o: %.c
if [ $(notdir $<) = file1.c ]; then \
echo " >> $(notdir $<) is excluded"; \
else \
ifneq ($(FLAG1),)
$(run_function1); \
endif
ifneq ($(FLAG2),)
$(run_function2); \
endif
fi
The conditional Make function should still work:
%.o: %.c
if [ $(notdir $<) = file1.c ]; then \
echo " >> $(notdir $<) is excluded"; \
else \
$(if $(FLAG1),,$(run_function1);) \
$(if $(FLAG2),,$(run_function2);) \
fi
Or possibly using shell conditionals is clearer:
%.o: %.c
if [ $(notdir $<) = file1.c ]; then \
echo " >> $(notdir $<) is excluded"; \
else \
if [ -n $(FLAG1) ] \
$(run_function1); \
fi \
if [ -n $(FLAG2) ] \
$(run_function2); \
fi \
fi
Related
The error:
make: *** No rule to make target 'build-x86_64'. Stop.
My makefile:
x86_64_asm_source_files := $(shell find src/impl/x86_64 -name *.asm)
x86_64_asm_object_files := $(patsubst src/impl/x86_64/%.asm, build/x86_64/%.o, $(x86_64_asm_source_files))
$(x86_64_asm_object_files): build/x86_64/%.o : src/impl/x86_64/%.asm
mkdir -p $(dir $#) && \
nasm -f elf64 $(patsubst build/x86_64/%.o, src/impl/x86_64/%.asm, $#) -o $#
.PHONY: build-x86_64
build-x86_64: $(x86_64_asm_object_files)
mkdir -p dist/x86_64 && .
x86_64-elf-ld -n -o dist/x86_64/kernel.bin -T targets/x86_64/linker.ld $(x86_64_asm_object_files) && \
cp dist/x86_64/kernel.bin targets/x86_64/iso/boot/kernel.bin && \
grub-mkrescue /usr/lib/grub/i386-pc -o dist/x86_64/target.iso targets/x86_64/iso
I'm trying to increment a Makefile variable with eval function inside a rule (to do a fancy loading bar), by doing
$(eval COUNTER=$(shell echo $$(($(COUNTER) + 1))))
I found on internet that this is working for some people but this line causes me a Syntax Error: unexpected end of file, what should I do to increment my counter? Are there some non-horrific alternatives to this function, or a way to avoid this unexpected end of file? thanks for your help
Here is the entire Makefile I'm working on
SHELL = /bin/sh
.SUFFIXES = .c .h .o
NAME = Necklace
SRCD = src
INCD = inc
OBJD = .obj
SRC = $(addsuffix $(word 1, $(.SUFFIXES)),\
main\
necklace\
utils)
INC = $(addsuffix $(word 2, $(.SUFFIXES)),\
necklace)
OBJ = $(SRC:$(word 1, $(.SUFFIXES))=$(word 3, $(.SUFFIXES)))
CC = gcc
CFLAGS = -Wall\
-Werror\
-Wextra\
-I $(INCD)
COUNT = $(shell cat file.count 2>/dev/null)
COMPILED = $(shell echo $$(($(shell ls src/*$(word 1, $(.SUFFIXES)) | wc -l | tr -d ' ') - $(COUNT))))
define set
set = $(eval $1 := $2)
ifeq ($(COUNT),)
all:
echo $(words $(SRC)) > file.count && $(MAKE) -n | grep $(CC) | wc -l | tr -d ' ' > tmp.txt && rm -f file.count && echo $$(($$(cat tmp.txt) - 1)) > file.count && make
else
all: $(NAME)
endif
$(NAME): $(addprefix $(OBJD)/, $(OBJ)) | $(addprefix $(INCD)/, $(INC))
$(CC) $(CFLAGS) $^ -o $#
$(OBJD):
mkdir $#
$(OBJD)/%.o: $(SRCD)/%.c | $(OBJD)
#printf '\r\033[2KCompiling [' && sh prc.sh $(COMPILED) $(COUNT) && printf ']' && $(CC) $(CFLAGS) -c $< -o $# && $(eval COMPILED:=$(shell echo $$(($(COMPILED) + 1)))) #Syntax Error is here
clean:
rm -rf $(OBJD)
fclean: clean
rm -rf $(NAME)
re: fclean all
I managed to do it by writing and reading the variable into a file instead of using Make variables
I have the following Makefile:
.PHONY: all clean run
INC_DIR = include
SRC_DIR = src
KERNEL_NAME = mykernel
AS = as
ASPARAMS = --32
CXX = g++
CXXPARAMS = -m32 -ffreestanding -fno-exceptions -fno-rtti -I$(INC_DIR)
#CXXPARAMS = -m32 -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore -I$(INC_DIR)
LDPARAMS = -melf_i386
BUILD_DIR = build
ISO_DIR = $(BUILD_DIR)/iso
ISO_BOOT = $(ISO_DIR)/boot
GRUB_CONFIG = $(ISO_BOOT)/grub/grub.cfg
SRC = $(wildcard $(SRC_DIR)/*.cpp)
SRC += $(wildcard $(SRC_DIR)/**/*.cpp)
SRC += $(wildcard $(SRC_DIR)/*.s)
OBJS = $(SRC:=.o)
OBJS := $(addprefix $(BUILD_DIR)/, $(OBJS))
.SECONDARY: $(OBJS)
all: $(KERNEL_NAME).iso
run: $(KERNEL_NAME).iso
qemu-system-i386 -cdrom $<
$(KERNEL_NAME).iso: $(GRUB_CONFIG) $(ISO_BOOT)/$(KERNEL_NAME).bin
grub-mkrescue -o $# $(ISO_DIR)
$(ISO_BOOT)/$(KERNEL_NAME).bin: $(SRC_DIR)/linker.ld $(OBJS)
ld $(LDPARAMS) -T $^ -o $# -nostdlib
$(GRUB_CONFIG):
mkdir -p $(dir $#)
echo 'set timeout=0' > $(GRUB_CONFIG)
echo 'set default=0' >> $(GRUB_CONFIG)
echo '' >> $(GRUB_CONFIG)
echo 'menuentry "$(KERNEL_NAME) OS" {' >> $(GRUB_CONFIG)
echo ' multiboot2 /boot/$(KERNEL_NAME).bin' >> $(GRUB_CONFIG)
echo ' boot' >> $(GRUB_CONFIG)
echo '}' >> $(GRUB_CONFIG)
$(BUILD_DIR)/%.cpp.o: %.cpp
echo $(dir $#)
echo $(wildcard (dir $#))
#ifeq ($(wildcard (dir $#)),)
# echo "mkdir -p $(dir $#)" ;
# $(CXX) $(CXXPARAMS) $< -c -o $#
#endif
$(BUILD_DIR)/%.s.o: %.s
#if [ ! -d $(dir $#) ]; then \
echo "mkdir -p $(dir $#)" ; \
mkdir -p $(dir $#) ; \
fi
$(AS) $(ASPARAMS) $< -o $#
clean:
rm -rf $(KERNEL_NAME).iso $(BUILD_DIR)
Why do I get the output with empty echo by running make? The directory build/src exists.
echo build/src/
build/src/
echo
echo build/src/
build/src/
echo
echo build/src/
build/src/
echo
echo build/src/
build/src/
echo
echo build/src/
build/src/
echo
echo build/src/
build/src/
echo
echo build/src/gui/
build/src/gui/
echo
echo build/src/gui/
build/src/gui/
echo
ld -melf_i386 -T src/linker.ld build/src/Keyboard.cpp.o build/src/VGArray.cpp.o build/src/mykernel.cpp.o build/src/TextCursor.cpp.o build/src/VideoContext.cpp.o build/src/GDTable.cpp.o build/src/gui/DrawContext.cpp.o build/src/gui/Window.cpp.o build/src/loader.s.o -o build/iso/boot/mykernel.bin -nostdlib
ld: cannot find build/src/Keyboard.cpp.o: No such file or directory
ld: cannot find build/src/VGArray.cpp.o: No such file or directory
ld: cannot find build/src/mykernel.cpp.o: No such file or directory
ld: cannot find build/src/TextCursor.cpp.o: No such file or directory
ld: cannot find build/src/VideoContext.cpp.o: No such file or directory
ld: cannot find build/src/GDTable.cpp.o: No such file or directory
ld: cannot find build/src/gui/DrawContext.cpp.o: No such file or directory
ld: cannot find build/src/gui/Window.cpp.o: No such file or directory
Makefile:33: recipe for target 'build/iso/boot/mykernel.bin' failed
make: *** [build/iso/boot/mykernel.bin] Error 1
I tried to make a minimal example, but it works right when build directory exists.
.PHONY: all clean
CXX = g++
OPTS = -Wall -Wextra
BUILD_DIR = build
APP = $(BUILD_DIR)/main
SRC_DIR = src
SRC = $(wildcard $(SRC_DIR)/*.cpp)
all: $(APP)
$(APP): $(APP).o
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp
echo $(dir $#)
echo $(wildcard $(dir $#))
clean:
rm -rf $(BUILD_DIR) main *.o
Replace echo $(wildcard (dir $#)) by echo $(wildcard $(dir $#)) and things should work as you expect.
Note: SRC += $(wildcard $(SRC_DIR)/**/*.cpp) will not recurse in subdirectories. If you believed it would, try:
SRC = $(shell find $(SRC_DIR) -type f -name '*.cpp')
SRC += $(wildcard $(SRC_DIR)/*.s)
This is the makefile for MacOS The source directory contains the source files plus the makefile and srclist.make file
# makefile for molex on macOS
OBJDIR = ../Objects
SRCDIR = ./Source
include srclist.make
FC = gfortran
FFLAGS = -x f77-cpp-input -ffixed-line-length-132 -fno-align-commons -I$(SRCDIR) -O3
OBJECTS = $(addprefix $(OBJDIR)/, $(addsuffix .o, $(basename $(SRCLIST)) ))
SOURCES = $(addprefix $(SRCDIR)/, $(SRCLIST) )
vpath %.f $(SRCDIR)
vpath %.inc $(SRCDIR)
$(OBJDIR)/%.o : %.f
$(FC) -c $(FFLAGS) $< -o $#
molex : $(OBJECTS)
$(FC) -o molex $^
.PHONY : clean
clean:
rm $(OBJDIR)/*.o
srclist.make contains a list of fortran and include files to converted to object code which are placed in a separate Objects folder
SRCLIST = \
molex.f \
background.f \
bnu.f \
charfns.f \
checkparam.f \
escape.f \
extrap.f \
fcn.f \
fdjac.f \
fmin.f \
funcv.f \
getfs.f \
idtrans.f \
initcoll.f \
initx.f \
intensity.f \
levpop.f \
lnsrch2.f \
loadmol.f \
lubksb.f \
ludcmp2.f \
newt3.f \
nextline.f \
output.f \
tau.f \
taudust.f \
Tex.f \
bug.inc \
collisions.inc \
constants.inc \
control.inc \
moldata.inc \
nlevmax.inc \
nmax.inc \
parameters.inc \
radiative.inc \
I've tried placing escape backslashes in the macOS makefile and ran in cmd prmpt with mingw32-make
the environmental Path is set as C:\msys2\mingw-w64\bin
the partly edited makefile follows
# makefile for molex on macOS
OBJDIR = ..\\Objects
SRCDIR = .\\Source
include srclist.make
FC = gfortran
FFLAGS = -x f77-cpp-input -ffixed-line-length-132 -fno-align-commons -I$(SRCDIR) -O3
#OBJECTS = $(addprefix $(OBJDIR)/, $(addsuffix .o, $(basename $(SRCLIST)) ))
OBJECTS = $(addprefix $(OBJDIR)\\, $(addsuffix .o, $(basename $(SRCLIST)) ))
SOURCES = $(addprefix $(SRCDIR)/, $(SRCLIST) )
vpath %.f $(SRCDIR)
vpath %.inc $(SRCDIR)
$(OBJDIR)\%.o : %.f
$(FC) -c $(FFLAGS) $< -o $#
molex : $(OBJECTS)
$(FC) -o molex $^
.PHONY : clean
clean:
del $(OBJDIR)/*.o
The cmd prompt output follows
D:\test_molex_ian\Source>mingw32-make -f makefile molex
mingw32-make: *** No rule to make target '..\\Objects\\molex.o', needed by 'molex'. Stop.
I would appreciate some guidance please
I am trying to get the basename of filenames in Makefile; but it always fails: basename command does not work.
Here is my code:
list = a.xlib b.lib
all:
for each_lib in $(notdir $(list)); \
do \
if [[ $$each_lib == *.xlib ]]; then \
*** Here I need to get the basename of $$each_lib to some variable, say base_lib *** \
cp -p $$base_lib-un.xlib ../../dist/lib/$$each_lib \
else \
cp -p $$each_lib ../../dist/lib/$$each_lib \
fi; \
done;
If we can create a variable with the value of basename of each file in list, that would be perfect.
Thanks.
$(basename ...) is a make function. It cannot operate on shell variables, because they are expanded later than make commands. You can use the shells $(...) substitution, but you have to double the dollar sign, so makefile does not interpret it as a function.
See if one of the following options does what you want:
list = a.xlib b.lib
libs = $(filter-out %.xlib,$(list))
xlibs = $(filter %.xlib,$(list))
V ?= #
allsh:
$(V)for each_lib in $(notdir $(libs)); do \
echo cp -p $$each_lib ../../dist/lib/$$each_lib; \
done;
$(V)for each_lib in $(notdir $(xlibs)); do \
base_lib="$$(basename $$each_lib .xlib)"; \
echo cp -p $$base_lib-un.xlib ../../dist/lib/$$each_lib; \
done;
xlibsstripped = $(patsubst %.xlib,%,$(xlibs))
allmake:
$(V)for each_lib in $(notdir $(libs)); do \
echo cp -p $$each_lib ../../dist/lib/$$each_lib; \
done;
$(V)for each_lib in $(notdir $(xlibsstripped)); do \
echo cp -p $$each_lib-un.xlib ../../dist/lib/$$each_lib.xlib; \
done;
Run with make allsh/allmake V= to see the commands being run.
If what you want to do is get the basenames, I'm surprised that basename doesn't work. (What version of Make are you using?) Note that it is a Make function, so it goes outside the rules:
list = a.xlib b.lib
BASES = $(basename $(list))
You can do it with other Make functions (note the colons):
list := a.xlib b.lib
list := $(patsubst %.lib,%,$(list))
list := $(patsubst %.xlib,%,$(list))
If what you really want to do is move the files and modify the names of the xlib files (a-un.xlib => .../a.xlib), there's an easier way:
targets := $(addprefix ../../dist/lib/,$(list))
all: $(targets)
../../dist/lib/%.lib: %.lib
mv $< $#
../../dist/lib/%.xlib: %-un.xlib
mv $< $#