I want to replace the string libswscale.so.2 by libswscale.so (variables called $(SLIBNAME_WITH_MAJOR) and $(SLIBNAME), respectively). This is what I tried in the Makefile:
$(SUBDIR)$(SLIBNAME_WITH_MAJOR): $(OBJS) $(SUBDIR)lib$(NAME).ver
[...]
#echo SHFLAGS=$(SHFLAGS)
#echo SLIBNAME_WITH_MAJOR=$(SLIBNAME_WITH_MAJOR)
#echo SLIBNAME=$(SLIBNAME)
#echo A $(patsubst $(SLIBNAME_WITH_MAJOR),$(SLIBNAME),$(SHFLAGS))
#echo B $(SHFLAGS:$(SLIBNAME_WITH_MAJOR)=$(SLIBNAME))
#echo C $($(SHFLAGS):$(SLIBNAME_WITH_MAJOR)=$(SLIBNAME))
#echo D $(SHFLAGS:$(SLIBNAME_WITH_MAJOR)=$(SLIBNAME))
#echo E $(subst $(SLIBNAME_WITH_MAJOR),$(SLIBNAME),$(SHFLAGS))
#echo F $(subst l,L,$(SHFLAGS))
The output is
SHFLAGS=-shared -Wl,-soname,libswscale.so.2 -Wl,-Bsymbolic -Wl,--version-script,libswscale/libswscale.ver
SLIBNAME_WITH_MAJOR=libswscale.so.2
SLIBNAME=libswscale.so
A -shared -Wl,-soname,libswscale.so.2 -Wl,-Bsymbolic -Wl,--version-script,libswscale/libswscale.ver
B -shared -Wl,-soname,libswscale.so.2 -Wl,-Bsymbolic -Wl,--version-script,libswscale/libswscale.ver
C
D -shared -Wl,-soname,libswscale.so.2 -Wl,-Bsymbolic -Wl,--version-script,libswscale/libswscale.ver
E -shared -Wl,-soname,libswscale.so.2 -Wl,-Bsymbolic -Wl,--version-script,libswscale/libswscale.ver
F -shared -WL,-soname,libswscale.so.2 -WL,-BsymboLic -WL,--version-script,LibswscaLe/LibswscaLe.ver
The last one (F) is especially ridiculous. What is wrong here? Is it because $(SHFLAGS) is made up of variables as well?
Found it: $(SHFLAGS) was defined as
SHFLAGS=-shared -Wl,-soname,$$(#F) blablafoo
and using any substitution on it would not work until $$(#F) is actually evaluated (in my case to libswscale.so.2).
I solved it by replacing the variable reference:
#echo $(subst $$(#F),$(SLIBNAME),$(SHFLAGS))
Small hint on assignments: VAR = $(OTHERVAR) is evaluated when used, VAR := $(OTHERVAR) is evaluated immediately.
Related
I'm trying to optimize this makefile for adding PGM.
I created makefile needs to be optimized:
SOURCES = main.cpp logic.cpp
OBJECTS = $(SOURCES:.cpp=.o)
CC = CC
MODEL001 = FLAGA FLAGB
MODEL002 = FLAGC
CFLAGS001 = -c $(MODEL001:%=-D%)
CFLAGS002 = -c $(MODEL002:%=-D%)
PGMNUM = 001 002
all: PGM001 PGM002
PGM001:$(SOURCES)
$(CC) $(CFLAGS001) $(SOURCES)
$(CC) -o $PGM001 $(OBJECTS)
PGM002:$(SOURCES)
$(CC) $(CFLAGS002) $(SOURCES)
$(CC) -o $PGM002 $(OBJECTS)
Currently, I change the following variables when adding a PGM003.
ADD : MODEL003, CFLAGS003, PGM003:$(SOURCES)...
MODIFY : PGMNUM, all
Just by adding MODEL003 and PGMNUM, this makefile seems to work. How can I do it?
(pseudo code like this but does not work):
SOURCES = main.cpp logic.cpp
OBJECTS = $(SOURCES:.cpp=.o)
CC = CC
MODEL001 = FLAGA FLAGB
MODEL002 = FLAGC
MODEL003 = FLAGD FLAGE
PGMNUM = 001 002 003
CFLAGS$(PGMNUM) = -c $(MODEL$(PGMNUM):%=-D%)
all: $(PGMNUM:%=PGM%)
PGM$(PGMNUM):$(SOURCES)
$(CC) $(CFLAGS$(PGMNUM)) $(SOURCES)
$(CC) -o $PGM$(PGMNUM) $(OBJECTS)
By 'optimize', I take it you want to make it use less lines of code, rather than make it run faster. If so, you can use a function and eval as so:
SOURCES := main.cpp logic.cpp
PGMNUMS := 001 002 003
CC := CC
MODEL001 := FLAGA FLAGB
MODEL002 := FLAGC
MODEL003 := FLAGD
define func
CFLAGS$1 := -c $(MODEL$(p):%=-D%)
OBJECTS$1 := $$(SOURCES:.cpp=.$1.o)
$$(OBJECTS$1) : %.$1.o : %.cpp
$(CC) $$(CFLAGS$1) -o $$# $$^
PGM$1 : $$(OBJECTS$1)
$(CC) -o $$# $$^
endef
$(info --vv-- show generated code --vv--)
$(foreach p,$(PGMNUMS),$(info $(call func,$p)))
$(info --^^-- end of generated code --^^--)
#actually generate the calls:
$(foreach p,$(PGMNUMS),$(eval $(call func,$p)))
all: $(PGMNUM:%=PGM%)
Basically, you define a function func, and then run it for all values of $(PGMNUMS). Notice the use of $$ in the function definition -- in the function, $1 will expand to the first parameter. Items with $$var in front of them will expand to $var, rather than expanding at the time. I added a $(info..) which is useful to debug what you generate.
My Makefile looks like this:
OBJ = $(SRC:.c=.c.o) #yes it it should be renamed to .c.o, not .o
LIBS = -lchecl -lchecs -lchengine-dev -lglfw -lm -lGL -lGLEW -lcheio -lopenal -lfreetype
EXE = test
VER = -std=c99
MODE = -g
OPT = -O0
ERR = -Wall -Wuninitialized -Werror=implicit-function-declaration -Wextra -Wno-unused-parameter -Wno-incompatible-pointer-types -Werror=int-conversion -Wduplicated-cond -Wlogical-op -Wrestrict -Wnull-dereference -Wjump-misses-init -Wdouble-promotion -Wshadow -Wformat=2
LFLAGS = -o
CFLAGS = $(ERR) $(VER) $(OPT) -c $(MODE) `pkg-config --cflags freetype2`
run: $(EXE)
./$(EXE)
$(EXE): $(OBJ)
gcc $(LFLAGS) $(EXE) $(OBJ) $(LIBS)
%.o: %.c
gcc -c $(CFLAGS) $*.c
mv "$$(basename $*.o)" "$$(dirname $*)"
cleanall:
rm $(OBJ)
rm $(SRC)
And I am passing the SRC variable like this:
files=$(find . -type f -name '*.c.c')
make run SRC="$files"
But this gives the the following error:
make: *** No rule to make target 'src/setup.c
./states/mainMenuState.c
...
(a list of all source files)'
However if I manually copy the value of $files into the Makefile, writing SRC = and then the source files, it compiles just fine. If I write instead of OBJ = $(SRC:.c.c=.c.o) OBJ = $($(SRC):.c.c=.c.o) it seems to compile but not link correctly, because then I get this error:
//usr/local/lib/libchengine-dev.so: undefined reference to `vector_find'
//usr/local/lib/libchengine-dev.so: undefined reference to `che_init'
//usr/local/lib/libchengine-dev.so: undefined reference to `vector_destruct'
SRC is used in the definition of OBJ. But this can't be your real makefile, because it won't work. So something must be different about your real makefile versus what you've shown us, and that difference is critical to the problem you're having. As Renaud says, please provide a MCVE.
I created a simple makefile:
OBJS := $(SRC:.c=.c.o)
all: $(OBJS)
%.c.o : %.c
: $< $#
then ran it:
files=$(find -name \*.c)
make SRC="$files"
and it worked just fine:
: foo.c foo.c.o
: bar.c bar.c.o
: biz.c biz.c.o
: baz.c baz.c.o
You can work around the problem in GNU make 4.1 by not including newlines in the $files variable. For example you can change how you set it to this:
files=$(find . -type f -name '*.c.c' -printf '%p ')
so it uses space separators instead of newlines.
I'm trying to deal with Makefiles and wrote a simple "program":
DELETE_COMMAND := del
COMPILER := gcc
SOME_TEXT := lalalalalalalalalalalal!!!
all: sum.o even.o main.o pi.o
#$(COMPILER) -o output.exe sum.o even.o main.o pi.o
SOME_TEXT_2 := $(subst la,La,$(SOME_TEXT))
#echo $(SOME_TEXT_2)
clean:
#$(DELETE_COMMAND) *.o
#$(DELETE_COMMAND) output.exe
sum.o: sum.c sum.h
#$(COMPILER) -c sum.c
main.o: main.c sum.h pi.h
#$(COMPILER) -c main.c
pi.o: pi.c pi.h even.h
#$(COMPILER) -c pi.c
even.o: even.c even.h
#$(COMPILER) -c even.c
But I get the following error:
SOME_TEXT_2 := LaLaLaLaLaLaLaLaLaLaLal!!!
process_begin: CreateProcess(NULL, SOME_TEXT_2 := LaLaLaLaLaLaLaLaLaLaLal!!!, ...) failed.
make (e=2): The system cannot find the file specified.
make: *** [Makefile:7: all] Error 2
The problem is caused by this line:
SOME_TEXT_2 := $(subst la,La,$(SOME_TEXT))
but I have no idea what the problem is.
I'm using make from mingw-w64 on Windows.
Consider the rule...
all: sum.o even.o main.o pi.o
#$(COMPILER) -o output.exe sum.o even.o main.o pi.o
SOME_TEXT_2 := $(subst la,La,$(SOME_TEXT))
#echo $(SOME_TEXT_2)
Assuming all lines except the first begin with a tab character then each command will be run in a separate shell. But...
SOME_TEXT_2 := $(subst la,La,$(SOME_TEXT))
is not valid shell syntax -- it looks like it's supposed to be interpreted by make.
If the intent is simply to modify the variable SOME_TEXT and print the result then you can have either...
all: sum.o even.o main.o pi.o
#$(COMPILER) -o output.exe sum.o even.o main.o pi.o
#echo $(subst la,La,$(SOME_TEXT))
or, let make assign to SOME_TEXT_2...
SOME_TEXT_2 := $(subst la,La,$(SOME_TEXT))
all: sum.o even.o main.o pi.o
#$(COMPILER) -o output.exe sum.o even.o main.o pi.o
#echo $(SOME_TEXT_2)
How do I make this work? It errors out with "make: somevariable: Command not found"
sometarget:
somevariable = somevalue
Full example:
CXXFLAGS = -I/usr/include/test -shared -fPIC
OBJ = main.o Server.o
blabla : $(OBJ)
ifeq ($(argsexec),true)
# Creates an executable
CXXFLAGS = -I/usr/include/test
$(CXX) -o blabla $(OBJ) $(CXXFLAGS)
else
# Creates a library
DESTDIR = /home/pc
$(CXX) -o blabla $(OBJ) $(CXXFLAGS)
./bn.sh
endif
I found a solution using the eval function:
$(eval variablename=whatever)
This works :)
(although I may now try to find an easier build system ;))
Thanks everyone for reading and also of course #eriktous for writing!
If you write it like you did, the assignment will be executed as a shell command, which gives the error you got.
I would try organising it something like this:
CXXFLAGS = -I/usr/include/test
ifneq ($(argsexec),true)
CXXFLAGS += -shared -fPIC
DESTDIR = /home/pc
endif
OBJ = main.o Server.o
blabla : $(OBJ)
$(CXX) -o blabla $(OBJ) $(CXXFLAGS)
ifneq ($(argsexec),true)
./bn.sh
endif
This should do what you want, although I'm not quite happy with using the ifneq construct twice. I'd have to think harder to come up with something that avoids that.
I have to create different *.o files from a same set of *.c using various CFLAGS. I wanted to use patsubst to generate different *.o files from same *.c. I am doing something wrong the following statement, please help (I want to generate one set of object files having ($<)_O0.o and the other ($<)_O2.o from the same set of c source files):
$(CC) $(CFLAGS_02) -c $< -o $(patsubst %.c,%_O2.o,$<)
Thanks
Use patsubst to make lists of the objects that you want to build, and then use separate rules for each type of build.
Something like this:
SRC_FILES = source1.c source2.c
OBJ_FILES_O0 = $(patsubst %.c,%_O0.o,$(SRC_FILES))
OBJ_FILES_O2 = $(patsubst %.c,%_O2.o,$(SRC_FILES))
CFLAGS_O0 := -O0
CFLAGS_O2 := -O2
all: $(OBJ_FILES_O0) $(OBJ_FILES_O2)
$(OBJ_FILES_O0): %_O0.o: %.c
$(CC) $(CFLAGS_O0) -c $< -o $#
$(OBJ_FILES_O2): %_O2.o: %.c
$(CC) $(CFLAGS_O2) -c $< -o $#
You can also use wild cards to specify all files in the directory.
eg:
#Generic Makefile.
CC := g++
LD := g++
CFLAGS := -c
LDFLAGS := -L<path to lib> -l<libname> \
-L<path to lib> -l>libname> \
......................
ifeq (${TARGETARCH}, debug)
CFLAGS += -g -O0
elif
CFLAGS += -O4 -DNDEBUG
SRCFILES := $(wildcard *.cpp)
OBJFILES := $(patsubst %.cpp, %.o, ${SRCFILES})
all: main
main: ${OBJFILES}
#echo "[Linking]"$#
${LD} ${LDFLAGS} ${OBJFILES}
%.o: %.cpp
#echo "[Compiling]"$#
${CC} ${CFLAGS} $^ -o $#