I try to make one thing or another depending if a file has extension p.md or md:
$(DST)/%.md.html: $(SRC)/%.md $(TMPHTML5)
$(eval EXT := $(suffix $<))
ifeq('$(EXT)','.p.md')
$(PANDOC_MD_HTML) -o $# $< -V filename=$(<F) -V otherformatspresentations=true
else
$(PANDOC_MD_HTML) -o $# $< -V filename=$(<F)
endif
but I get:
make site/ESPA4.Dia-0-presentacio.p.md.html -B
ifeq('.md','.p.md')
/bin/sh: -c: line 0: syntax error near unexpected token `'.md','.p.md''
/bin/sh: -c: line 0: `ifeq('.md','.p.md')'
make: *** [Makefile:103: site/ESPA4.Dia-0-presentacio.p.md.html] Error 1
Why don't you just use one pattern per type of file you want to create, as make was intended to be used?
$(DST)/%.p.md : $(SRC)/%.md $(TMPHTML5)
$(PANDOC_MD_HTML) -o $# $< -V filename=$(<F) -V otherformatspresentations=true
$(DST)/%.md : $(SRC)/%.md $(TMPHTML5)
$(PANDOC_MD_HTML) -o $# $< -V filename=$(<F)
Note that depending on which version of GNU make you're using order may or may not be important but this will work with all versions.
If you want to do it in one rule you can't use ifeq etc. That is a make command, and everything in the recipe is passed to the shell. The shell doesn't know anything about ifeq hence your errors. You'll have to either use the $(if ...) function or else use shell syntax completely:
$(DST)/%.md.html: $(SRC)/%.md $(TMPHTML5)
$(PANDOC_MD_HTML) -o $# $< -V filename=$(<F) $(if $(filter %.p.md,$<),-V otherformatspresentations=true)
Or:
$(DST)/%.md.html: $(SRC)/%.md $(TMPHTML5)
other=; case $< in (*.p.md) other="-V otherformatspresentations=true" ;; esac; \
$(PANDOC_MD_HTML) -o $# $< -V filename=$(<F) $$other
Related
I am trying to compile a program using this makefile:
GCCPARAMS = -m32 -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore
ASPARAMS = --32
objects = src/loader.o src/kernel.o
%.o: src/%.cpp
gcc $(GCCPARAMS) -c -o $# $<
%.o: src/%.s
echo $(ASPARAMS)
as $(ASPARAMS) -o $# $<
kernel.bin: linker.ld $(objects)
ld $(LDPARAMS) -T $< -o $# $(objects)
install: kernel.bin
sudo cp $< boot/mykernel.bin
The problem comes when doing make which prints the following:
as -o src/loader.o src/loader.s
src/loader.s: Assembler messages:
src/loader.s: Warning: end of file not at end of a line; newline inserted
src/loader.s:18: Error: operand type mismatch for `push'
src/loader.s:19: Error: operand type mismatch for `push'
make: *** [<builtin>: src/loader.o] Error 1
As you can se the variable is not properly set, instead, make puts a space where the variable should be. That causes the assembler compiler to think it's a 64 bit architecture and giving some errors.
Any idea of what is going on? I am doing this using WSL2 by the way.
The reason you see this is because your recipe rules are wrong.
You have these object files:
objects = src/loader.o src/kernel.o
and you have this rule:
%.o: src/%.s
echo $(ASPARAMS)
as $(ASPARAMS) -o $# $<
When trying to build src/loader.o what does the stem of the pattern %.o match? It will match src/loader of course. So then what will the prerequisite be? It will be src/%.s with the stem expanded, so it will be src/src/loader.s. I presume that this doesn't exist.
As a result of this, this pattern rule doesn't match. So what does make do? It looks for a different pattern rule, and it turns out that GNU make provides a default pattern rule to build a .s file, which uses a pattern %.o : %.s and that pattern DOES match, so that's used.
But that built-in rule uses the standard make variables, which are AS and ASFLAGS. You haven't set ASFLAGS, so no flags are used.
You can tell that it's not using your rule because your rule has an echo ... in it and make does not print that command out. Therefore, it's not running your rule.
This question already has answers here:
What does this GCC error "... relocation truncated to fit..." mean?
(11 answers)
gfortran for dummies: What does mcmodel=medium do exactly?
(2 answers)
Closed 3 years ago.
The makefile I attach comes from the source directory of a smooth particle hydrodynamics code. When I fix the number of particles to 128**3 particles, my code compiles fine. Now that I need to use 256**3 I get a relocation truncated to fit: R_X86_64_PC32 against symbol ... defined in COMMON section in ....
I have tried several things I found online:
using the set stacksize unlimited command
adding the -mcmodel=large flag
adding the -fPIC flag
none of these seem to work. I am also aware of the https://www.technovelty.org/c/relocation-truncated-to-fit-wtf.html article, but I do not understand what I am supposed to do.
My makefile: (I attach part of it)
include ../makeflags
CPP=g++
CPPFLAGS = $(OPTIONS) -D$(SYS) -mcmodel=large -traceback
.SUFFIXES: .F
OBJ = hydra.o accel.o ahtime.o clist.o cool.o createcool.o dumpdata.o
.f.o:
$(F77) $(FLAGS) -c $<
.F.o:
# if test $(SYS) = ibm ; then \
echo "$(CPP) -P -C $(CPPFLAGS) $< > tmp/$*.f";\
$(CPP) -P -C $(CPPFLAGS) $< > tmp/$*.f;\
echo "$(F77) $(FLAGS) -c tmp/$*.f";\
$(F77) $(FLAGS) -c tmp/$*.f;\
elif test $(SYS) = f2c ; then \
echo "$(CPP) -P -C $(CPPFLAGS) $< > tmp/$*.f";\
$(CPP) -P -C $(CPPFLAGS) $< > tmp/$*.f;\
echo "$(F77) $(FLAGS) -c tmp/$*.f";\
$(F77) $(FLAGS) -c tmp/$*.f;\
else \
echo "$(F77) $(FLAGS) $(CPPFLAGS) -c $<";\
$(F77) $(FLAGS) $(CPPFLAGS) -c $<;\
fi
.c.o:
$(CC) -c $(CPPFLAGS) $(CFLAGS) $<
hydra: tmp $(OBJ)
echo $(FLAGS)
$(F77) -o hydra $(FLAGS) $(OBJ) $(LIBS)
mv hydra $(RUNDIR)
new_options:
touch *.F
make
clean:
/bin/rm -rf *.o tmp
system.o: system.$(SYS)
# if test $(SYS) = f2c ; then \
cp system.f2c system.c; \
$(CC) -c $(CPPFLAGS) $(CFLAGS) system.c; \
else \
cp system.$(SYS) system.f; \
$(F77) $(FLAGS) -c system.f; \
fi
tmp:
# test -d $# || mkdir $#
# for i in `ls *.inc` ; do \
(cd tmp ; ln -s ../$$i $$i ) ; \
done
My flags file: (I attach part of it)
SHELL = /bin/sh
# set SYS to one of: sun, dec, cray, sgi, ibm, hpux, f2c, g77
SYS = g77
# choose appropriate names for compilers
F77 = /usr/bin/f77
CC = cc
CPP = /lib/cpp
# compilation flags for linux box
FLAGS= -O2
FLAGS= -O2 -fomit-frame-pointer -m486
FLAGS= -Wall -g
FLAGS= -mcmodel=large
# For cosmic test use
UNITS_OPTIONS =
OTHER_OPTIONS =
OPTIONS = $(FORCE_OPTIONS) $(UNITS_OPTIONS) $(OTHER_OPTIONS)
I understand this is some memory problem, which, for some reason is not resolved with the options I have described above. Please bare in mind I cannot mess with the variable definitions in the code (e.g. change COMMON blocks etc.), because they are linked to many programs and this will cause an overall failure of compilation. The exact error I am receiving is:
/home/user/Downloads/Stage/hydra4.0/src/hydra.F:1:(.text+0x14): relocation truncated to fit: R_X86_64_PC32 against symbol `param_' defined in COMMON section in hydra.o
for many component programs, not only for hydra.o.
After 3 months of looking into this problem, I solved it by adding -mcmodel=medium.
I am doing a simple Interpreter using bison and lex. This is my make file content.
#
# makefile for ccalc
#
OBJS += mylang.o SM.o lex.o parse.o
# rules
%.c: %.y
bison -o $(#:%.o=%.d) $<
%.c: %.l
flex -o$(#:%.o=%.d) -i $<
# dependencies
mylang: mylang.yy.tab.c lex.c $(OBJS)
#echo g++ -Os -std=c++0x -omylang $(OBJS)
#g++ -Os -std=c++0x -omylang $(OBJS)
#echo ' '
# source
mylang.o: mylang.cpp
SM.o: SM.cpp SM.h
lex.o: lex.c
parse.o: mylang.yy.tab.c
mylang.yy.tab.c: mylang.yy
lex.c: mylang.ll
When run this make file, The command running as
g++ -c -o SM.o SM.cpp
But I want to run as,
g++ -Os -std=c++0x -c -o SM.o SM.cpp
What Should I change in my make file to run with c++0x Compiler Version.
Set CXXFLAGS flags accordingly:
CXXFLAGS="-Os -std=c++0"
make uses internal defaults rule to compile
c++ files to .o files. You can display them with make -p.
The rules in your case are
COMPILE.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
COMPILE.cpp = $(COMPILE.cc)
%.o: %.cpp
# recipe to execute (built-in):
$(COMPILE.cpp) $(OUTPUT_OPTION) $<
So i have a somewhat large C++ project that I want to compile.Previously I used Code::Blocks, but now I want more control about what's happening behind the scenes. However making makefiles was just too complex for me!!
What I want is this: Can i create a python script that acts as a makefile, if so how?!
In the makefile I want to search for all *.cpp files on certain directories and then invoke g++ to compile/link them.
EDIT: sorry i forgot to mention i also have headers and want custom g++ parameters
Try scons
It looks like what you need
Try that:
#default target
all: prog
#auto dependency
include $(OBJ_FILES:.o=.d)
%.o: %.cpp
$(CXX) -c $(CXXFLAGS) $*.cpp -o $*.o
$(CXX) -MM $(CXXFLAGS) $*.cpp > $*.d
#mv -f $*.d $*.d.tmp
#sed -e 's|.*:|$*.o:|' < $*.d.tmp > $*.d
#sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \
sed -e 's/^ *//' -e 's/$$/:/' >> $*.d
#rm -f $*.d.
#set ld flags eg for libs
LDFLAGS = -lsdl2 -lglew -lgl
#set cxxflags for all debug options and others
CXXFLAGS= -g -Wall
#collect all cpp files:
CPP_FILES := $(shell find . -type f -name '*.cpp')
#get the object file names for them
OBJ_FILES := $(CPP_FILES:.cpp=.o)
#and link all togeter
prog: $(OBJ_FILES)
g++ $(CXXFLAGS) $(LDFLAGS) -o $# $^
I found it obscure to use make utility to generate header dependencies makefile for the source file and using this build the library or create executable accordingly.
1)
As suggested in the manual:
http://www.gnu.org/software/make/manual/html_node/Automatic-Prerequisites.html#Automatic-Prerequisites
I tried with the approach mentioned over there (In my case dependency files are present under obj/):
obj/%.d:%.cpp
#set -e; rm -f $#; \
g++ -MM $(CPPFLAGS) ${INC_FLAGS} $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
But this throws a shell error:
/bin/sh: cannot create obj/xyz.d.23030: Directory nonexistent
However obj directory is present, I didn't understand the use of sed command. The manual explains that it replaces any ".obj : .cpp" rule to ".obj .dep : .cpp", But How ?
2)
I also tried the approach mentioned over here :
http://mad-scientist.net/make/autodep.html
obj/%.o : %.c
g++ -MMD ${CPPFLAGS} ${INC_FLAGS} -c $$< -o $$#
#cp obj/$*.d obj/$*.P; \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $*.d >> $*.P; \
rm -f $*.d
Using this dependency file is generated but following error message is asserted:
"/bin/sh: cannot open obj/%.P: No such file"
sed: -e expression #2, char 4: unterminated `s' command
Again use of sed is not clear.
This becomes more obfuscate ... Here In the second approach if I don't add separate rule to create dependency files and generate them at the time of object creation, As "g++ -MP -MMD -c" creates both .o and .d. But how .o will be compiled again using the dependency makefile which is generated in the same command ?
I appreciate any help in resolving the errors occurred, And helping me in understanding this.
Or Please suggest some elegant approach to do the same.
EDIT : (As suggested in the comment)
In the second approach using both -MMD and -MP it works as expected, But I can't understand how it's working. Here sed comamnd is not required, and source gets rebuild if related header is modified:
obj/%.o : %.c
g++ -MMD -MP ${CPPFLAGS} ${INC_FLAGS} -c $$< -o $$#
But As described in gcc manual page , If I didn't interpreted it wrong -MMD used to generate the dependency(excluding system header) file and -MP used to generate empty rule for each header, But it only modifies the object rule:
i.e.,
obj/%.o obj/%.d : %.cpp (This is what sed is doing as mentioned in GNU make manual)
or something like,
obj/%.o : %.cpp (list of dependent headers for particular .cpp file)
What is the use of following two commands and how it works ?
a)sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#;
b)
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $*.d >> $*.P;
However obj directory is present,
Apparently it isn't. That's the first thing you need to solve.
I didn't understand the use of sed command. The manual explains that it replaces any ".obj : .cpp" rule to ".obj .dep : .cpp", But How ?
The special make variable $* contains the stem that matched the pattern of the target, which will be the part of the target that matches the pattern %
The sed command replaces obj/%.o: with obj.o obj.d:, exactly as the Make manual says. To explain "how" you need to understand sed, but it's not a very complicated sed command.
Using this dependency file is generated but following error message is asserted:
That make recipe has a # character, which means everything after it is a comment, you need to escape it with \#
However, if you're using GCC it's easier to just add -MMD to the normal recipe for generating object files, which will produce the .d files as a side-effect of compilation, so you don't need a separate target for the .d files.
So this is a makefile I wrote for one of my modules at university, you can try using it, when you call make it generates all the files and links all the files without needing to define anything extra in the file. There is a lot of excess stuff here, but I did this quite a while ago, but you can take things out and play around with it to see what you can remove. Hope this helps =)
CC=g++
WARNING_FLAGS=-Wall -Wextra -Weffc++ -Winit-self -Wmissing-include-dirs \
-Wswitch-default -Wswitch-enum -Wunused-parameter -Wstrict-overflow=5 \
-Wfloat-equal -Wshadow -Wc++0x-compat -Wconversion -Wsign-conversion \
-Wmissing-declarations -Wstrict-null-sentinel -Woverloaded-virtual -Wsign-promo\
-Werror -pedantic
FORMATTING_FLAGS=-fno-pretty-templates -fmessage-length=80 -fdiagnostics-show-option
CFLAGS=${WARNING_FLAGS} ${FORMATTING_FLAGS} -g -std=c++0x -pipe -frepo
LDFLAGS=
LDLIBS=-lGL -lGLEW -lglut -lGLU -lX11 -lXi -lm -lpng
TARGET=main
OBJECTS=$(addsuffix .o, $(basename $(shell ls *.C | grep -v Test)))
HEADERS=$(addsuffix .h, $(basename $(shell ls *.h | grep -v Test)))
TEST_LDFLAGS=-lboost_unit_test_framework
TEST_LDLIBS=${LDLIBS}
TEST_TARGET=test
TEST_OBJECTS=$(addsuffix .o, $(basename $(shell ls *.C | grep -v main)))
CLEAN_TARGETS=$(addsuffix .o, $(basename $(shell ls *.C))) ${TARGET} ${TEST_TARGET} *.rpo *.gch makefile.dep
all: ${OBJECTS}
${CC} ${LDFLAGS} ${LDLIBS} $^ -o ${TARGET}
test: ${TEST_OBJECTS}
${CC} ${TEST_LDFLAGS} ${TEST_LDLIBS} $^ -o ${TEST_TARGET}
%.o:
${CC} ${CFLAGS} -c ${LDFLAGS} $< -o $#
Test.o: Test.C Makefile
${CC} -c $< -o $#
clean:
rm ${CLEAN_TARGETS}
makefile.dep: *.[Ch]
for i in *.C; do gcc -std=c++0x -MM "$${i}"; done > $#
include makefile.dep