In my makefile I have an object variable. I need to prepend obj/ to every .o file. How would I do this?
CC=g++
CFLAGS=-C -Wall
LDFLAGS=-lsqlite3 -lpthread -ldl
SOURCES=main.cpp Database.cpp actionInit.cpp TileSet.cpp Player.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=mahjong-counter
all: bin $(OBJECTS) $(EXECUTABLE)
bin:
mkdir -p bin
%.o: %.cpp
$(CC) $(LDFLAGS) $< -c -o $#
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $(EXECUTABLE)
clean:
rm $(OBJECTS)
You want CXX, not CC. CC is for C compiler, not the C++ compiler
In any case, I believe the following should work:
CXX=g++
CXXFLAGS=-C -Wall
LDFLAGS=-lsqlite3 -lpthread -ldl
OBJ_DIR = obj
BIN_DIR = bin
EXECUTABLE=mahjong-counter
SOURCES= main.cpp Database.cpp actionInit.cpp TileSet.cpp Player.cpp
OBJECTS= $(SOURCES:%.cpp=$(OBJ_DIR)/%.o)
all: dirs $(OBJECTS) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $(EXECUTABLE)
$(OBJ_DIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) $< -o $#
dirs:
mkdir -p $(BIN_DIR)
mkdir -p $(OBJ_DIR)
.PHONY: dirs all
You could use more expressive version of substitution you employed when assigning OBJECTS
OBJECTS=$(SOURCES:%.cpp=obj/%.o)
or use a standard text transformation function
OBJECTS=$(addprefix obj/,$(SOURCES:.cpp=.o))
Related
In the old Makefile there is an include part:
SHELL=/bin/sh
CORE_SRC=\
./Core/allocator.cpp \
./Core/etc... \
CORE_OBJS=$(CORE_SRC:.cpp=.o)
INCLUDE=\
`pkg-config --cflags glib-2.0 libpng` \
`sdl-config --cflags` \
`freetype-config --cflags` \
`./python-config-linux.sh --cflags` \
-I./TopLayer -I./etc...
CC=g++-4.4
CFLAGS=-O3 -pipe -Wall -fPIC -D__STDC_CONSTANT_MACROS
CORE_LFLAGS=\
-fPIC \
-Wl,-rpath,./libs
CORE_LDLIBS=\
`pkg-config --libs glib-2.0 libpng` \
`sdl-config --libs` -lz -ljpeg \
`freetype-config --libs` \
`curl-config --libs` \
-L./$(LIBSDIR) \
-letc...
GAME_LFLAGS=\
-shared -pthread -fPIC \
-Wl,-rpath,../libs
GAME_LDLIBS=\
-lm \
`python-config-linux.sh --libs`
target_name: $(CORE_OBJS) $(CORE_NAME)
target_name: override CFLAGS += -DAV_OUTPUT
$(CORE_NAME): $(CORE_OBJS)
$(CC) $(CORE_LFLAGS) $(CORE_OBJS) $(CORE_LDLIBS) -o $#
.c.o:
$(CC) $(CFLAGS) $(INCLUDE) -c $< -o $*.o
.cpp.o:
$(CC) $(CFLAGS) $(INCLUDE) -c $< -o $#
The execution of those configs is:
$pkg-config --cflags glib-2.0 libpng
-> -I/usr/include/glib-2.0 -I/usr/lib/i386-linux-gnu/glib-2.0/include -I/usr/include/libpng12
$sdl-config --cflags
-> -I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT
$freetype-config --cflags
-> -I/usr/include/freetype2
$./python-config-linux.sh --cflags
-> -I/python-2.7.10/include/python2.7 -I/python-2.7.10/include/python2.7 -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes
I don't understand and a bit confused about Cmake - should I use target_include_dirictories() or find_packages()?
Should target_include_dirictories() be used also with --cflags and libs like glib-2.0 libpng for pkg-config?
*Updated makefile. Removed unnecessary targets etc.
You will need both find_package() and target_link_libraries().
target_include_directories() is almost always obsolete when using libraries found through find_package. Docs.
Example
Example tested on macOS HighSierra with CMake 3.12.
project(Example)
cmake_minimum_required(VERSION 3.10)
find_package(PNG REQUIRED)
add_executable(prog main.c) # main.c from: http://zarb.org/~gc/html/libpng.html
target_link_libraries(prog PNG)
# On Ubuntu 14.04 + CMake 3.2 use the older syntax (FindPNG.cmake is too old) from the next line:
# target_link_libraries(prog ${PNG_LIBRARIES})
I have a makefile, for a C project with 2 sub-C-files and I can create two exe, one static and one dynamic.
But the static is lighter in space than the dynamic!
The programs can be launched and seems to be the sames
Is it normal?
Thank you very much, I have an exam in 2 days and I hope I will fix that problem :)
Simon
CC = gcc
CFLAGS = -Wall
CFLAGS2 = -shared
CFLAGS3 = -fPIC
LIB_U_CAM_TTL = -l_projet_vision_u_cam_ttl
LIB_SERIAL_LINUX = -l_projet_vision_serial_linux
CHEMIN = -L/usr/local/lib
lib_projet_vision_serial_linux.so: serial_linux.o
$(CC) $(CFLAGS2) $^ -o $#
lib_projet_vision_u_cam_ttl.so: u_cam_ttl.o
$(CC) $(CFLAGS2) $^ -o $#
lib_projet_vision_serial_linux.a : serial_linux.o
ar -rv $# $^
lib_projet_vision_u_cam_ttl.a : u_cam_ttl.o
ar -rv $# $^
projet_vision_dynamic: main_vision.c install
$(CC) $(CFLAGS3) $^ $(CHEMIN) $(LIB_SERIAL_LINUX) $(LIB_U_CAM_TTL) -o $#
projet_vision_static: main_vision.c install
$(CC) $^ $(CHEMIN) $(LIB_SERIAL_LINUX) $(LIB_U_CAM_TTL) -o $#
%.o : %.c
$(CC) $(CFLAGS) -c $< -o $#
install: lib_projet_vision_serial_linux.so lib_projet_vision_serial_linux.a lib_projet_vision_u_cam_ttl.so lib_projet_vision_u_cam_ttl.a
sudo cp -f *.h /usr/local/include/
sudo cp -f *.so /usr/local/lib/
sudo cp -f *.a /usr/local/lib/
sudo cp projet_vision_dynamic /usr/bin/
sudo cp projet_vision_static /usr/bin/
sudo ldconfig
uninstall: clean
sudo rm -f /usr/local/include/serial_linux.h
sudo rm -f /usr/local/include/u_cam_ttl.h
sudo rm -f /usr/local/lib/lib_projet_vision_serial_linux.so
sudo rm -f /usr/local/lib/lib_projet_vision_u_cam_ttl.so
sudo rm -f /usr/local/lib/lib_projet_vision_u_cam_ttl.a
sudo rm -f /usr/local/lib/lib_projet_vison_serial_linux.a
sudo ldconfig
clean:
rm -f *.o *~ *.so *.a
rm -f projet_vision_static projet_vision_dynamic
Let's say I want to rewrite this:
main.o: main.cpp
g++ -c main.cpp
factorial.o: factorial.cpp
g++ -c factorial.cpp
hello.o: hello.cpp
g++ -c hello.cpp
in a more generic way as something like this:
SOURCES = main factorial hello
$(SOURCES).o: $(SOURCES).cpp
g++ -c $(SOURCES).cpp
How do I do that?
First we tell the compiler how to nme the output files, just to avoid misunderstanding:
main.o: main.cpp
g++ -c main.cpp -o main.o
factorial.o: factorial.cpp
g++ -c factorial.cpp -o factorial.o
hello.o: hello.cpp
g++ -c hello.cpp -o hello.o
Then we put in automatic variables, to reduce redundancy:
main.o: main.cpp
g++ -c $< -o $#
factorial.o: factorial.cpp
g++ -c $< -o $#
hello.o: hello.cpp
g++ -c $< -o $#
Then we realize that these rules all look the same, so we combine them as a static pattern rule:
main.o factorial.o hello.o: %.o : %.cpp
g++ -c $< -o $#
Then we use a variable to store the names of the objects:
OBJECTS := main.o factorial.o hello.o
$(OBJECTS): %.o : %.cpp
g++ -c $< -o $#
I learnt from the GNU Make manual that the sign $^ is an automatic variable which represents the names of all the prerequisites. However I fell upon a makefile like this one:
SVR_OBJECT_FILES = server.o\
server_func.o
CLT_OBJECT_FILES = client.o
CFLAGS = -Wall -Werror -W
CC = gcc
all: client/client server/serveur
client/client: $(CLT_OBJECT_FILES)
server/serveur: $(SVR_OBJECT_FILES)
client/client server/serveur:
#mkdir -p $(dir $#)
$(CC) $(CFLAGS) $^ -o $#
%.o: %.c
$(CC) -c $<
clean:
rm -f client/client server/serveur *.o
Which works fine so my question is :
How can the command below can link the right object files while the $^ variable is refering no preprerequisites at all. (the rule has no prerequisites)
$(CC) $(CFLAGS) $^ -o $#
$^ contains all the prerequisites of the target, not just the ones that are mentioned with the rule itself. The same file can appear as a target several times in rules with no commands:
sometarget: dependency1
…
sometarget: dependency2
assemble -o $# $^
…
sometarget: dependency3
The dependencies of sometarget are dependency1, dependency2 and dependency3, and when the assemble command is invoked by make sometarget, it will receive all three as arguments.
Here, $^ will contain all $(CLT_OBJECT_FILES) or $(SRV_OBJECT_FILES) depending on which target the command is executed for.
My make file has worked, up until I tried some variable substitution. %.o is not recognized.
I get make: * No rule to make target `%.o', needed by `parser'. Stop.
CC=gcc
CFLAGS=-ansi -pedantic -Wall -ggdb3
PROJECT=project.c project.h
PARSER=parser.c parser.h
OBJ=project.o parser.o
#CFILE=project.c parser.c
#1 no problem
#parser: project.o parser.o
# $(CC) $(CFLAGS) -o $# $^
#2 no problem
#parser: $(OBJ)
# $(CC) $(CFLAGS) -o $# $^
#3 this fails
parser: %.o
$(CC) $(CFLAGS) -o $# $^
#parser: project.o parser.o
# gcc -ansi -pedantic -Wall -ggdb -o parser project.o parser.o
project.o: $(PROJECT)
$(CC) $(CFLAGS) -c $^
parser.o: $(PARSER)
$(CC) $(CFLAGS) -c $^
clean:
rm -f $(OBJ) parser
You're not creating a pattern rule, since there is no % in the target name. As a result the % has no special meaning in the list of dependencies. It's seen as a literal part of a file name; you can't use it as a regular wildcard.