I have a simple Makefile. When i'm NOT using a variable in dependencies list it works fine. Otherwise it gives fallowing error:
make: *** No rule to make target 'ext/configXML.o', needed by 'libledrgb-jni.so'. Stop.
Furthermore when i do
make print-LED-CFG-SRC
LED-CFG-SRC = ../led-cfg/src
So the value is set properly, altough if I explicitly add rule for this file:
ext/configXML.o: $(LED-CFG-SRC)/%.cc
#echo 'Building file: $<'
#${CXX} $(CXXFLAGS) -c -o "$#" "$<"
It looks like the problem is with the LED-CFG-SRC to source file:
make ext/configXML.o
make: *** No rule to make target '/configXML.cc', needed by 'ext/configXML.o'. Stop.
But the file exists:
make list
ls -la ../led-cfg/src
total 340
drwxrwxr-x 2 gigi gigi 4096 lip 27 13:10 .
drwxrwxr-x 12 gigi gigi 4096 lip 28 10:08 ..
-rw-rw-r-- 1 gigi gigi 11918 lip 28 09:54 configXML.cc
-rw-rw-r-- 1 gigi gigi 2891 lip 27 13:17 configXML.h
Here's the source Makefile:
EXTOBJS = ext/configXML.o ext/packet.o ext/tinyxml2.o ext/crypt.o ext/rozkaz.o
LED-CFG-SRC := ../led-cfg/src/
INCLUDES := -I$(LED-CFG-SRC)
CXXFLAGS := $(INCLUDES)
LIBRARY := libledrgb-jni.so
CXXFLAGS := $(INCLUDES) -fPIC -std=c++14
all: dirs $(LIBRARY)
$(LIBRARY): $(OBJFILES) $(EXTOBJS)
$(CXX) -shared -o $# $^
ext/%.o: $(LED-CFG-SRC)/%.cc
#echo 'Building file: $<'
#${CXX} $(CXXFLAGS) -c -o "$#" "$<"
clean:
rm -rf $(EXTOBJS)
list:
ls -la $(LED-CFG-SRC)
print-% : ; #echo $* = $($*)
.PHONY: clean dirs
I'm using GNU Make 4.1
Shot in the dark. At least in the Makefile listing you have posted, there is a redundant undesired whitespace in the definition of the LED-CFG-SRC variable:
LED-CFG-SRC := ../led-cfg/src/<there-is-reduntant-whitespace-here>
That means, when the variable is expanded in the rule definition later, the make would see ../led-cfg/src/ %.cc (two words, $< = ../led-cfg/src/, and %.cc being only as a additional dependency) instead of the expected ../led-cfg/src/%.cc.
You should activate display of non-printable characters in your editor, since make in places is extremely picky about the whitespaces: some it chooses to strip automatically, but some it keeps. Like here: make had stipped the whitespace in the front of the ../led-cfg/src/, but it kept the one at the end.
Related
I have some kind of make dependency problem. all_2 does not rebuild after a1.src has been touched, but all_1 does. Why? Can't I use absolute paths?
$ cat Makefile
DIR = ${HOME}/tmp
outputs = $(DIR)/dir1/a1.out $(DIR)/dir2/a2.out
all_1 : dir1/a1.out dir2/a2.out
all_2 : $(outputs)
ls -l $(outputs) # debug print
*/%.out : $(notdir %.src)
#touch $#
#echo 'Build $# from $(notdir $*.src)'
This is my directory structure:
$ ls -R
Makefile a1.src a2.src dir1 dir2
./dir1:
a1.out
./dir2:
a2.out
all_1 works fine:
$ touch a1.src
$ make all_1
Build dir1/a1.out from a1.src
$ make all_1
make: Nothing to be done for `all_1'.
but all_2 does not rebuild a1.out (although the out files exist, so I guess that the targets are ok):
$ touch a1.src
$ make all_2
ls -l /Users/eternity/tmp/dir1/a1.out /Users/eternity/tmp/dir2/a2.out # debug print
-rw-r--r-- 1 eternity staff 0 Jan 20 15:25 /Users/eternity/tmp/dir1/a1.out
-rw-r--r-- 1 eternity staff 0 Jan 20 14:46 /Users/eternity/tmp/dir2/a2.out
$
First, the * is not a "wildcard" in the target side. You need a pattern rule with %.out as target:
%.out: ...
That will match against target names with a trailing .out.
The stem (i.e.: the % part in the target) with which the pattern rule was matched against will be stored in the automatic variable $*:
%.out: $(notdir $*.src)
However, that alone won't do: you also need to enable secondary expansion to use the variable $* as part of the rule definition, because its value is empty during the first expansion. In order to enable secondary expansion, simply define the target .SECONDEXPANSION, i.e.:
.SECONDEXPANSION:
Once enabled, for delaying the expansion of a variable or function at the rule definition, you need to replace $ by $$:
%.out: $$(notdir $$*.src)
So, with all that in mind, your last rule should look like:
.SECONDEXPANSION:
%.out: $$(notdir $$*.src)
#touch $#
#echo 'Build $# from $(notdir $*.src)'
This is how my directory looks like:
/project
makefile
/ceda_lib
makefile
files....
/general
makefile
files....
/CLI
makefile
files....
/objects
files.o
Makefile(main):
1 #start other makefiles
2
3
4 o= ./objects
5 DEPS= Affine.hpp CEDA.hpp generalParameters.hpp generalFunctions.hpp
6 OBJ= $o/main.o $o/Affine.o $o/generalFunctions.o
7 CC=g++
8 CFLAGS= -Wall -g -I.
9 export CC
10 export CFLAGS
11 export DEPS
12
13 all:
14 ▸---+$(MAKE) -C general
15 ▸---+$(MAKE) -C ceda_lib
16 ▸---+$(MAKE) -C CLI
17
18 run: $(OBJ) $(DEPS)
19 ▸---$(CC) -o $# $^
The other makefiles look like this:(update2)
1 include ../makefile.variables
2
3 OBJ = main.o
4 all: $(OBJ)
5
6 $(OBJ): %.o: %.cpp $(DEPS)
7 ▸---$(CC) -o ../objects/$# -c $< $(CFLAGS)
What I want to do is for all code in the 3 directories to be compiled and all objects to be stored in the /object directory. Then an executable will be created from the $DEPS and the contents of /object directory.
This makefile doesn't work sadly. Could you please find what I've done wrong and also could you suggest me ways to improve the code. (I'm quite new to makefiles).
Also this is the output whenever I try making the project:(Update2)
make: Entering directory '/home/george/Documents/CEDA'
make -C general
make[1]: Entering directory '/home/george/Documents/CEDA/general'
g++ -o ../objects/generalFunctions.o -c generalFunctions.cpp -Wall -g -I.
make[1]: Leaving directory '/home/george/Documents/CEDA/general'
make -C ceda_lib
make[1]: Entering directory '/home/george/Documents/CEDA/ceda_lib'
g++ -o ../objects/Affine.o -c Affine.cpp -Wall -g -I.
Affine.cpp:4:33: fatal error: generalParameters.hpp: No such file or directory
#include "generalParameters.hpp"
^
compilation terminated.
makefile:7: recipe for target 'Affine.o' failed
make[1]: *** [Affine.o] Error 1
make[1]: Leaving directory '/home/george/Documents/CEDA/ceda_lib'
makefile:8: recipe for target 'All' failed
make: *** [All] Error 2
make: Leaving directory '/home/george/Documents/CEDA'
This is the makefile.variables
1 #variables used by all makefiles in project directory
2
3 PATH_TO_DIR = ~/Documents/CEDA
4 c = $(PATH_TO_DIR)/ceda_lib
5 g = $(PATH_TO_DIR)/general
6 e = $(PATH_TO_DIR)/CLI #e for executable
7
8 DEPS= $c/Affine.hpp $c/CEDA.hpp $g/generalParameters.hpp $g/generalFunctions.hpp
9 CC=g++
10 CFLAGS= -Wall -g -I.
Here:
OBJ= main.o
../objects/%.o: %.cpp $(DEPS)
$(CC) -c $< $(CFLAGS)
This makefile contains one rule, which is a pattern rule, a way to build any file with a name like ../objects/foo.o. But it doesn't tell Make which object file it is to build. To be precise, a pattern rule cannot be the default rule.
The simplest way to fix this is with the addition of an ordinary rule:
../objects/$(OBJ):
Once you have this working you will have the object files, but there are still problems in the main makefile. The run rule will not build an executable, and if you want to execute that rule you will have to invoke it on the command line, it won't follow automatically.
You are attempting recursive use of Make -- which is tricky -- before you've mastered the basics. I suggest you try using the makefile to build the object files, then try to build the executable using the command line, then look carefully at the command you used and rewrite the run rule.
Once you get that far, other improvements are possible. (Make is a powerful tool, but it has a long learning curve.)
EDIT: If it isn't working at all, try something simpler first.
Pick a source file in ceda_lib, like, I don't know main.cpp. Verify that the source file exists and that the corresponding object file (main.o) does not. Edit the makefile (in ceda_lib/) to this:
main.o: main.cpp
$(CC) -c $< $(CFLAGS)
Then within ceda_lib/, try make and see what happens.
If it builds main.o, then delete main.o, and then from project/ try make -C ceda_lib, and see what happens. If that builds ceda_lib/main.o, then we can move on to more advanced makefiles.
I'm trying to get started with CuTest to do unit testing in C.
When make-ing, I get the following error:
dev:~/bistro# make
cutest/CuTest.c:10: *** missing separator. Stop.
The file cutest/CuTest.c comes directly from the library. I have done no mods to it. Here are the concerned lines:
08 - #include "CuTest.h"
09 -
10 - /*-------------------------------------------------------------------------*
11 - * CuStr
12 - *-------------------------------------------------------------------------*/
13 -
14 - char* CuStrAlloc(int size)
Here's the Makefile I'm using, for complete reference:
NAME = bistro
SOURCES_DIR = src
OBJECTS_DIR = obj
SOURCES = $(shell find $(SOURCES_DIR) -type f -name *.c) cutest/CuTest.c
OBJECTS = $(patsubst $(SOURCES_DIR)/%.c, $(OBJECTS_DIR)/%.o, $(SOURCES))
DEPS = $(OBJECTS:.o=.d)
CFLAGS = -Wall -Werror -Wextra
COMPILER = gcc -I cutest -I $(SOURCES_DIR) $(CFLAGS)
BISTRO_MAIN = $(OBJECTS_DIR)/bistro/bistro_main.o
.PHONY: test all clean fclean re
all: $(NAME)
# header dependencies
-include $(DEPS)
$(NAME): $(OBJECTS)
$(COMPILER) -o $(NAME) $(OBJECTS)
test: $(filter-out $(BISTRO_MAIN), $(OBJECTS))
$(COMPILER) -c all_tests.c -o all_tests.o
$(COMPILER) -o test $(filter-out $(BISTRO_MAIN), $(OBJECTS)) all_tests.o
rm -f all_tests.o
$(OBJECTS_DIR)/%.o: $(SOURCES_DIR)/%.c
#if [ ! -d "$(#D)" ]; then mkdir -p $(#D); fi
$(COMPILER) -MMD -c $< -o $#
clean:
rm -Rf $(OBJECTS_DIR)/*
fclean: clean
rm -f $(NAME)
re: fclean all
What could be the cause of this error message?
EDIT 1: The makefile is indented with 4-space tabs only. Could the call to the "find" command be the cause of that? Also, how come the error says the missing separator is in the .c file?
EDIT 2: The accepted answer shows the error. In addition, the call did not work because it was searching for *.c, which should be "*.c".
It means you are using (four) spaces instead of tab symbol.
Make target's command must be indented with a tab.
See http://www.gnu.org/software/make/manual/make.html#Rule-Introduction:
Please note: you need to put a tab character at the beginning of every recipe line! This is an obscurity that catches the unwary. If you prefer to prefix your recipes with a character other than tab, you can set the .RECIPEPREFIX variable to an alternate character
Your error comes because you include a C source file into Makefile.
SOURCES = $(shell find $(SOURCES_DIR) -type f -name *.c) cutest/CuTest.c
OBJECTS = $(patsubst $(SOURCES_DIR)/%.c, $(OBJECTS_DIR)/%.o, $(SOURCES)) # cutest/CuTest.c stays cutest/CuTest.c
DEPS = $(OBJECTS:.o=.d)
-include $(DEPS) # oops, includes cutest/CuTest.c
My makefile contains the following lines
11 SRC := $(shell echo src/*.cpp)
12 SRC += $(shell echo $(TEST_ROOT)/*.cpp)
13
14 OBJECTS = $(SRC:.cpp=.o)
22 # [debug] target
23 $(TARGET): $(OBJECTS)
24 $(CC) $(OBJECTS) -o $(TARGET)
25
26 # [debug] .o
27 $(OBJECTS): $(SRC)
28 $(CC) $(CFLAGS) $(DEBUG_FLAGS) -c $(SRC) $(OBJECTS)
Which fails because ... well the following evidently is not a way to do it
g++ -pedantic -Wall -Werror -O0 -g -Wno-format -DUSE_MEASURE -c src/Timer.cpp test/TimerTest.cpp src/Timer.o test/TimerTest.o
How should i modify line #28 to produce .o from all my sources please?
This should do the trick:
$(OBJECTS): %.o : %.cpp
$(CC) $(CFLAGS) $(DEBUG_FLAGS) -c $< $#
This rule will build one object file, and Make will call it once for each object that the other rule needs. You can write a rule that will build all object files in one pass, but there's no advantage to that.
EDIT:
Suppose SRC is src/foo.cpp src/bar.cpp testroot/baz.cpp,
so OBJECTS is src/foo.o src/bar.o testroot/baz.o
We could have a separate rule for each:
src/foo.o : src/foo.cpp
...
src/bar.o : src/bar.cpp
...
testroot/baz.o : testroot/baz.cpp
...
But that's redundant (since the commands are very similar) and inconvenient (since we don't want to add/remove rules whenever we add/remove targets). So we use a pattern rule:
%.o : %.cpp
...
Now when Make wants to build src/foo.o, it sees that the target matches the pattern %.o, the stem (corresponding to %) is src/foo, and the corresponding prereq, src/foo.cpp exists, so it uses this rule.
But we have a variable OBJECTS that lists the targets we want to build with this rule, so we can restrict it to a static pattern rule, which looks about the same but has some advantages we need not get into here:
$(OBJECTS) : %.o : %.cpp
...
Now for the ... part. The command tells the compiler to scan the prereq (src/foo.cpp) and build the target (src/foo.o), so we must refer to those things in the command. Automatic variables help with that; $# is the name of the target, and $< is the name of the first (and in this case the only) prerequisite:
$(OBJECTS): %.o : %.cpp
$(CC) $(CFLAGS) $(DEBUG_FLAGS) -c $< $#
I tried the following code tree. If I put the header file hello.h into the "inc" archive, and use the MM option my system reported that hello.h cannot be found even I add a vpath command in my makefile. If I move the hello.h back to the same directory of hello.c, gcc -MM works fine and listed the dependence file successfully.
How can I make the gcc know where to find the header file automatically? The following is the code tree, and "hello.h" is placed in archive "inc"
total 12
-rw-r--r-- 1 root root 101 Jun 22 14:13 hello.c
drwxr-xr-x 2 root root 4096 Jun 22 14:14 inc
-rw-r--r-- 1 root root 139 Jun 22 14:18 makefile
The following is my makefile content:
vpath %.h /home/tempcode/inc
hello: hello.o
gcc -o hello hello.o
hello.o: hello.c hello.h
gcc -c hello.c
debug:
gcc -MM hello.c
It makes me puzzled that if I run gcc directly like this, it works. does this mean VPATH or vpath do not help gcc finding the include path ? If so, I guess vpath variable only helps 'make' with finding the header file but not helping gcc, am I right?
[root#localhost tempcode]# gcc -MM -I/home/tempcode/inc hello.c
hello.o: hello.c /home/tempcode/inc/hello.h
does this mean VPATH or vpath do not help gcc finding the include path ? If so, I guess vpath variable only helps 'make' with finding the header file but not helping gcc, am I right?
That is correct. You should set the CFLAGS variable to do what you want. Make automatically includes CFLAGS when compiling C files. (CXXFLAGS for C++.) In your case, you'll need to add it to make .d files. I usually do something like this:
INCLUDES = -I/home/tempcode/inc
CFLAGS += $(INCLUDES)
CXXFLAGS += $(INCLUDES)
debug:
gcc -MM $(CFLAGS) hello.c