Adding flags to static lib compilation - c++

Good day!lets say I have a makefile that compils a static library.
CC = g++
SOURCES = $(wildcard way_to_src/src/*.cpp)
INCLUDES = -Iway_to Incl
OBJECTS = $(SOURCES:.cpp=.o)
CFLAGS += $(INCLUDES)
TARGET_STATIC = libmy_.a
clean:
rm -f $(OBJECTS) $(TARGET_SO) $(TARGET_STATIC)
static : $(OBJECTS)
ar rcs $(TARGET_STATIC) $(OBJECTS)
How can I add '-fpermissive' flag to compilation ?

Set CXXFLAGS:
CXXFLAGS=-fpermissive
Also CFLAGS += $(INCLUDES) should also target CXXFLAGS:
CXXFLAGS += -fpermissive $(INCLUDES)

Related

How to create Makefile with includes and libraries?

I am trying to create Makefile for my C++ project.
My main.cpp contains this custom includes:
#include <mysql_connection.h>
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>
For compilation I use:
g++ -stdlib=libc++ -o app.cgi -I/usr/local/include -I/usr/local/mysql-connector-c++-8.0.21/include/jdbc -L/usr/local/mysql-connector-c++/lib64 main.cpp -lmysqlcppconn
Now I need to add
#include "tinyxml2/tinyxml2.hpp"
The most simple way is to create Makefile. I wrote:
CC = g++
CFLAGS = -Wall -g -std=c++11
INCLUDES = -I/usr/local/include -I/usr/local/mysql-connector-c++-8.0.21/include/jdbc
LDLIBS = -L/usr/local/mysql-connector-c++/lib64 -lmysqlcppconn
SRCS = main.cpp ./tinyxml2/tinyxml2.cpp
OBJS = $(SRCS:.cpp=.o)
MAIN = main.cgi
#
# The following part of the makefile is generic
#
.PHONY: depend clean
all: $(MAIN)
$(MAIN): $(OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS)
.PRECIOUS: %.o
.c.o:
$(CC) $(CFLAGS) $(INCLUDES) -cpp $< -o $#
clean:
$(RM) *.o *~ $(MAIN)
depend: $(SRCS)
makedepend $(INCLUDES) $^
I got error:
main.cpp:21:10: fatal error: 'mysql_connection.h' file not found
#include <mysql_connection.h>
How to add includes to every .o? tinyxml2 doesn't use MySQL connector so I shouldn't add -lmysqlcppconn. How to do it?
You could build the makefile step by step. Start with the build command and make it a makefile target (I removed -stdlib=libc++):
app.cgi: main.cpp
g++ -o app.cgi -I/usr/local/include -I/usr/local/mysql-connector-c++-8.0.21/include/jdbc -L/usr/local/mysql-connector-c++/lib64 main.cpp -lmysqlcppconn
Next you can extract most elements into variables and add compiler flags:
CXX = g++
CXXFLAGS = -Wall -g -std=c++11
MAIN = app.cgi
CPPFLAGS = -I/usr/local/include -I/usr/local/mysql-connector-c++-8.0.21/include/jdbc
SRCS = main.cpp
LDFLAGS = -L/usr/local/mysql-connector-c++/lib64
LDLIBS = -lmysqlcppconn
$(MAIN): $(SRCS)
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $(MAIN) $(SRCS) $(LDFLAGS) $(LDLIBS)
Add a clean and an all target:
CXX = g++
CXXFLAGS = -Wall -g -std=c++11
MAIN = app.cgi
CPPFLAGS = -I/usr/local/include -I/usr/local/mysql-connector-c++-8.0.21/include/jdbc
SRCS = main.cpp
LDFLAGS = -L/usr/local/mysql-connector-c++/lib64
LDLIBS = -lmysqlcppconn
.PHONY: all clean
all: $(MAIN)
$(MAIN): $(SRCS)
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $(MAIN) $(SRCS) $(LDFLAGS) $(LDLIBS)
clean:
$(RM) *.o *~ $(MAIN)
Split into compiler step (implicit makefile rule) and linker step:
CXX = g++
CXXFLAGS = -Wall -g -std=c++11
MAIN = app.cgi
CPPFLAGS = -I/usr/local/include -I/usr/local/mysql-connector-c++-8.0.21/include/jdbc
SRCS = main.cpp
OBJS = $(SRCS:.cpp=.o)
LDFLAGS = -L/usr/local/mysql-connector-c++/lib64
LDLIBS = -lmysqlcppconn
.PHONY: all clean
all: $(MAIN)
$(MAIN): $(OBJS)
$(CXX) -o $(MAIN) $(OBJS) $(LDFLAGS) $(LDLIBS)
clean:
$(RM) *.o *~ $(MAIN)
Finally add ./tinyxml2/tinyxml2.cpp:
CXX = g++
CXXFLAGS = -Wall -g -std=c++11
MAIN = app.cgi
CPPFLAGS = -I/usr/local/include -I/usr/local/mysql-connector-c++-8.0.21/include/jdbc
SRCS = main.cpp ./tinyxml2/tinyxml2.cpp
OBJS = $(SRCS:.cpp=.o)
LDFLAGS = -L/usr/local/mysql-connector-c++/lib64
LDLIBS = -lmysqlcppconn
.PHONY: all clean
all: $(MAIN)
$(MAIN): $(OBJS)
$(CXX) -o $(MAIN) $(OBJS) $(LDFLAGS) $(LDLIBS)
clean:
$(RM) *.o *~ $(MAIN)

Recursive Makefile to build .o files

I am writing a simple kernel and all is going well so far.
I am using a Makefile to build the system through the shell.
However, I wish to move and reorganise the file structure but, my the makefile uses absolute linking.
How can I refactor this to compile all .cpp/.c files and .s files to an out folder and link them, without needing to define each folder path?
CC = ~/opt/cross/bin/i386-elf-g++
AS = ~/opt/cross/bin/i386-elf-as
LNFLAGS = -T linker.ld -melf_i386
CCFLAGS = -c -ffreestanding -nostdlib -fno-builtin -fno-rtti -fno-exceptions
ASFLAGS = -c
CTMP = $(wildcard src/kernel/*.cpp)
ATMP = $(wildcard src/kernel/arch/i386/*.s)
CFILE = $(subst src/kernel/, ,$(CTMP))
AFILE = $(subst src/kernel/arch/i386/, ,$(ATMP))
CSRC = $(CFILE:.c=)
ASRC = $(AFILE:.s=)
OUT = $(wildcard out/*.o)
all: ccompile acompile link
ccompile:
for file in $(CSRC) ; do \
$(CC) $(CCFLAGS) src/kernel/$$file -o out/$$file.o ; \
done
acompile:
for file in $(ASRC) ; do \
$(AS) $(ASFLAGS) src/kernel/arch/i386/$$file.s -o out/$$file.o ; \
done
link:
ld $(LNFLAGS) -o latest.bin $(OUT)
Use the vpath directive to specifiy the source directories.
TARGETS := latest.bin
LD := ld
LDFLAGS := -T linker.ld -melf_i386
CC := ~/opt/cross/bin/i386-elf-g++
CCFLAGS := -c -ffreestanding -nostdlib -fno-builtin -fno-rtti -fno-exceptions
AS := ~/opt/cross/bin/i386-elf-as
ASFLAGS := -c
vpath %.cpp src/kernel
vpath %.s src/kernel/arch/i386
SOURCES := $(wildcard *.cpp) $(wildcard *.s)
OBJECTS := $(addsuffix .o, $(basename $(notdir $(SOURCES))))
all: $(TARGETS)
out/%.o: %.cpp
$(CC) $(CCFLAGS) -o $# $<
out/%.o: %.s
$(AS) $(ASFLAGS) -o $# $<
latest.bin: $(OBJECTS)
$(LD) $(LDFLAGS) -o $# $^

Compiling multiple test files efficiently with Makefile

I have a C++ project with the following structure:
/Project
Makefile
/src (.cpp source files)
...
/include (.h header files)
...
/libs
...
/build (.o object files)
...
/tests (target .cpp files I want to compile)
test1.cpp
test2.cpp
test3.cpp
...
/bin (output directory for compiled files)
...
For the tests inside my test file, I would like to be able to
Compile them individually, e.g. "make test1", "make test2"
Compile them all at once
But I would like to be able to do this without needing to define new variables (e.g. TARGET1, TARGET2,...) for each new test file, nor add a bunch of new lines to my makefile for each new test file.
For example, right now I have something like:
CXX = g++
SRC_DIR = ./src
BUILD_DIR = ./build
LIB = -I libs
INC = -I include
SRCS = $(shell find $(SRC_DIR) -type f -name *.cpp)
OBJS = $(patsubst $(SRC_DIR)/%, $(BUILD_DIR)/%, $(SRCS:.cpp=.o))
TARGET1 ?= test1.cpp
TARGET2 ?= test2.cpp
TARGET3 ?= test3.cpp
all: $(OBJS)
$(CXX) ./tests/$(TARGET1).cpp $(LIB) $(INC) $^ -o ./bin/$(TARGET1)
$(CXX) ./tests/$(TARGET2).cpp $(LIB) $(INC) $^ -o ./bin/$(TARGET2)
$(CXX) ./tests/$(TARGET3).cpp $(LIB) $(INC) $^ -o ./bin/$(TARGET3)
$(TARGET1): $(OBJS)
$(CXX) ./tests/$(TARGET1).cpp $(LIB) $(INC) $^ -o ./bin/$(TARGET1)
$(TARGET2): $(OBJS)
$(CXX) ./tests/$(TARGET2).cpp $(LIB) $(INC) $^ -o ./bin/$(TARGET2)
$(TARGET3): $(OBJS)
$(CXX) ./tests/$(TARGET3).cpp $(LIB) $(INC) $^ -o ./bin/$(TARGET3)
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CXX) $(INC) -c -o $# $<
which does the job, but isn't very scalable. How could I do this scalably?
Make has some more tricks that you can use (not tested):
CXX = g++
SRC_DIR = src
BUILD_DIR = build
TEST_DIR = tests
BIN_DIR = bin
LIB = -I libs
INC = -I include
SRCS = $(wildcard $(SRC_DIR)/*.cpp)
OBJS = $(patsubst $(SRC_DIR)/%.cpp,$(BUILD_DIR)/%.o,$(SRCS))
TESTS = $(wildcard $(TEST_DIR)/*.cpp)
TARGETS = $(patsubst $(TEST_DIR)/%.cpp,$(BIN_DIR)/%,$(TESTS))
all: $(TARGETS)
$(TARGETS): $(BIN_DIR)/%: $(OBJS)
$(CXX) $(TEST_DIR)/$*.cpp $(LIB) $(INC) $^ -o $#
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CXX) $(INC) -c -o $# $<
The main trick here is the static pattern rule for $(TARGETS): in the recipe $* expands as the stem of the pattern. The other tricks are a simpler use of patsubst and the use of wildcard instead of the less efficient shell find. Note that this last one works only if your source files are flat in src, not if they are organized in a hierarchy of sub-directories.
But this does not answer your most tricky request: a way to invoke make testX instead of make bin/testX. So, here is the most tricky part:
SHORTERTARGETS = $(patsubst $(TEST_DIR)/%.cpp,%,$(TESTS))
.PHONY: $(SHORTERTARGETS)
# $(1): short target
define TARGETS_rule
$(1): $(BIN_DIR)/$(1)
endef
$(foreach t,$(SHORTERTARGETS),$(eval $(call TARGETS_rule,$(t))))
You can even use this foreach-eval-call to factorize other parts of your Makefile:
CXX = g++
SRC_DIR = src
BUILD_DIR = build
TEST_DIR = tests
BIN_DIR = bin
LIB = -I libs
INC = -I include
SRCS = $(wildcard $(SRC_DIR)/*.cpp)
OBJS = $(patsubst $(SRC_DIR)/%.cpp,$(BUILD_DIR)/%.o,$(SRCS))
TESTS = $(wildcard $(TEST_DIR)/*.cpp)
TARGETS = $(patsubst $(TEST_DIR)/%.cpp,$(BIN_DIR)/%,$(TESTS))
SHORTERTARGETS = $(patsubst $(TEST_DIR)/%.cpp,%,$(TESTS))
.PHONY: all $(SHORTERTARGETS)
all: $(TARGETS)
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CXX) $(INC) -c -o $# $<
# $(1): short target
define TARGETS_rule
$(1): $(BIN_DIR)/$(1)
$(BIN_DIR)/$(1): $(OBJS)
$(CXX) $(TEST_DIR)/$(1).cpp $(LIB) $(INC) $$^ -o $$#
endef
$(foreach t,$(SHORTERTARGETS),$(eval $(call TARGETS_rule,$(t))))
The most difficult to understand in this last version is the need of $$in the recipe (double expansion). But here the GNU make manual is your friend.

Makefile source in multiple directories

I have seen some examples of using makefile with multiple source directories but still could not implement it to my makefile.
Currently I have all source files at /src/ folder and I would like to be able compile subfolders in /src/ such as /src/modules.
I am using:
NAME = 'AI'
SRC = src
TGT = obj
PRG = application
INCLUDES = -Iinclude ...
LIBRARIES = -L ...
CXXFLAGS = -O2 -std=c++0x $(INCLUDES) $(LIBRARIES)
SOURCES = $(wildcard $(SRC)/*.cpp)
ENDFLAGS = -ljvm -lcurl
NOWARNINGS = -Wno-unused-variable -Wno-unused-result
OBJS = $(addprefix $(TGT)/, $(notdir $(SOURCES:.cpp=.o)))
$(TGT)/%.o: $(SRC)/%.cpp
$(CXX) $(CXXFLAGS) -c $< -o $# $(NOWARNINGS)
$(PRG)/$(NAME): $(OBJS)
$(CXX) $(LIBRARIES) $(OBJS) -o $# $(ENDFLAGS) $(NOWARNINGS)

My makefile isn't finding my include paths

Simply put: It's not finding the include paths:
CC = g++
OBJS = *.o #*/*.o
DEBUG = -g
PNAME = game
INCLUDES = -Iheaders
CFLAGS = -Wall $(DEBUG)
LFLAGS = -Wall -lsfml-graphics -lsfml-window -lsfml-system $(DEBUG)
all: build
build: $(OBJS)
$(CC) $(LFLAGS) $(OBJS) -o $(PNAME)
clean:
\rm *.o *~ $(PNAME)
.cpp:
$(CC) $(CFLAGS) $(INCLUDES) -c $(.SOURCE)
Your makefile looks pretty broken to me. Firstly, you probably want:
OBJS = $(patsubst %.cpp,%.o,$(wildcard *.cpp))
Secondly, your final rule needs to be something more like:
%.o: %.cpp
$(CC) $(CFLAGS) $(INCLUDES) -c $^ -o $#