How do I expend this Makefile to use wildcards? - c++

I would like to adopt the following Makefile from this tutorial to more generic targets. For example, if I type make foo, then I expect an executable foo to be built from foo.v and foo.cpp in a process similar to that of making maskbus.
.PHONY: all
all: maskbus
obj_dir/Vmaskbus.cpp: maskbus.v
verilator -Wall -cc maskbus.v
obj_dir/Vmaskbus__ALL.a: obj_dir/Vmaskbus.cpp
make -C obj_dir -f Vmaskbus.mk
maskbus: maskbus.cpp obj_dir/Vmaskbus__ALL.a
g++ -I/usr/share/verilator/include -I obj_dir \
/usr/share/verilator/include/verilated.cpp \
maskbus.cpp obj_dir/Vmaskbus__ALL.a \
-o maskbus
.PHONY: clean
clean:
rm -rf obj_dir/ maskbus
Here is what I have tried
.PHONY: all
stuff: $(basename $(wildcard *.v))
all: stuff
obj_dir/%.cpp: %.v
verilator -Wall -cc $<
obj_dir/V%__ALL.a: obj_dir/V%.cpp
make -C obj_dir -f Vmaskbus.mk
stuff: $#.cpp obj_dir/V$#__ALL.a
g++ -I/usr/share/verilator/include -I obj_dir \
/usr/share/verilator/include/verilated.cpp \
$#.cpp obj_dir/V$#__ALL.a \
-o $#
.PHONY: clean
clean:
rm -rf obj_dir/ $(stuff)
Nota that I left the name Vmaskbus unchanged in the second rule as I have no idea how to extract the correct "basename" from a rule containing %. However, when I run make foo, that rule isn't even executed, and thus subsequent commands fail due to the absence of obj_dir/Vfoo__ALL.a. Some investigation suggests that the variable stuff is empty, but I'm sure I have both foo.v and foo.cpp in the current directory.

Figured it out myself:
.PHONY: all clean
stuff := $(basename $(wildcard *.v))
all: $(stuff)
obj_dir/V%.cpp: %.v
verilator -Wall -cc $<
obj_dir/V%__ALL.a: obj_dir/V%.cpp
make -C obj_dir -f V$*.mk
$(stuff): %: %.cpp obj_dir/V%__ALL.a
g++ -I /opt/local/share/verilator/include \
-I obj_dir \
-o $# \
/opt/local/share/verilator/include/verilated.cpp \
obj_dir/V$*__ALL.a \
$*.cpp
clean:
rm -rf obj_dir/ $(stuff)

Related

How to use C++ modules with a Makefile?

I have a Makefile which is minimal, yet complete. It is the following:
OUT = example
INSTALL_DIR = /usr/local/bin
OBJECT = ./obj
SOURCE = ./src
SRC := $(shell find $(SOURCE) -name *.cc)
OBJ := $(SRC:%=$(OBJECT)/%.o)
DEPS := $(OBJ:.o=.d)
INC_DIRS := $(shell find $(SOURCE) -type d)
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
CC = gcc
CFLAGS = -pipe -fmodules-ts -std=c++2a
DEBUG_FLAGS := $(CFLAGS) -g -Wall -Wextra
RELEASE_FLAGS := $(CFLAGS) -O3 -flto
debug: $(OBJ)
#echo "Building the DEBUG binary..."
#$(CC) $(OBJ) -o $(OUT) $(DEBUG_FLAGS)
#echo "The binary was built successfully!"
release: $(OBJ)
#echo "Building the RELEASE binary..."
#$(CC) $(OBJ) -o $(OUT) $(RELEASE_FLAGS)
#echo "The binary was built successfully!"
install: $(OUT)
#cp $(OUT) $(INSTALL_DIR)
uninstall:
#rm $(INSTALL_DIR)/$(OUT)
$(OBJECT)/%.cc.o: %.cc
#mkdir -p $(dir $#)
#echo "Building $#..."
#$(CC) $(CFLAGS) -c $< -o $#
.PHONY: clean
clean:
rm -rf $(OBJECT) $(OUT)
-include $(DEPS)
There is a directory called "src" which includes the source files. When I'm running make, I will get a compilation error about having to first create modules before using them. If I do create them manually, then I will be able to use "Make" and it will work then it will work. Is there a way to automatically create them?
I recommend using g++-11 instead of just gcc, since versions <=10 do not really include module support asides from the deprecated TS. Then also, use flag -std=c++20.
Also, I have (painful) experience using dependency files with gcc, since that particular feature is not really fully implemented. Last I checked (beginning of nov '21) the dependency files don't actually do anything as pertains to modules.
That being said, what you write should work. And it would, if the compiler-support for modules was finished.

Makefile compiling the good files without the dependencies

I have a problem with the dependencies in my Makefile.
There is no problem with the compilation, it compiles perfectly the good *.cc and *.hh but unfortunately, it does not re-compile the dependencies, thus there is no update in the executable.
Here is my makefile:
EXEC ?= program
SRCS = $(shell find -name *.cc)
DEP = $(SRCS:.cc=.d)
OBJDIR = objs
OBJS = $(SRCS:./%.cc=$(OBJDIR)/%.o)
CXX = g++
CFLAGS = -std=c++14 $(addprefix "-I", $(shell find -type d))
## Clean rule
.PHONY: clean
clean:
rm -rf $(OBJDIR)
rm -f $(EXEC)
$(EXEC) : $(OBJS)
#echo "Linking: $#"
$(CXX) $(OBJS) -o $#
-include $(DEP)
$(OBJDIR)/%.o : ./%.cc ./%.hh
#mkdir -p $(#D)
#echo "Compiling: $<"
#$(CXX) -c $(CFLAGS) -MT $# -MMD -MP -o $# $<
It is probably something related to the flag used by g++ but I do not manage to find the solution;
Thanks in advance for the help that you can provide on this issue,
If you do not specify the filename for the generated dependency files, it is going to be ${#:%.o=%.d} (compiler logic). I.e. your dependency files are in $(OBJDIR) and not in ./ where your makefile expects them to be.
Two alternative solutions:
DEP := $(OBJS:%.o=%.d).
#$(CXX) -c $(CFLAGS) -MT $# -MMD -MP -MF $(<:%.cc=%.d) -o $# $<

Recursive makefile for c++ source

I've been struggling with makefiles for a while now, since I don't really get how they work...
My directory structure is as followed:
--bin/
--build/
--includes/
--src/
----classes/
------somefiles.hpp
------somefiles.cpp
----states/
------somestates.hpp
----main.cpp
----few-other-files.cpp
--Makefile
--.gitignore
Which worked fine with my makefile, until I started adding those subdirs, classes and states
I can't seem to find how to include those subdirs in my makefile which is:
CC := g++
SRCDIR := src
BUILDDIR := build
TARGET := bin/game
SRCEXT := cpp
SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o))
CFLAGS := -g -Wall
LIB := -lsfml-audio -lsfml-graphics -lsfml-network -lsfml-system -lsfml-window
INC := -I includes -I /usr/local/include -L /usr/local/lib
$(TARGET): $(OBJECTS)
#echo "Linking..."
#echo "$(CC) $^ -o $(TARGET) $(LIB)"; $(CC) $^ -o $(TARGET) $(LIB)
$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
#mkdir -p $(BUILDDIR)
#echo "$(CC) $(CFLAGS) $(INC) -c -o $# $<"; $(CC) $(CFLAGS) $(INC) -c -o $# $<
clean:
#echo "Cleaning..."
#echo "$(RM) -r $(BUILDDIR) $(TARGET)"; $(RM) -r $(BUILDDIR) $(TARGET)
.PHONY: clean
Problem: Fatal error: can't create build/classes/stateManager.o: No such file or directory
Normally, the problem is that it can't build the directory. But I thought the mkdir -p would solve that.
Any help is greatly appreciated.
Replace:
mkdir -p $(BUILDDIR)
with
mkdir -p $(#:D)
Another way is to let make treat directories as targets and have them automatically created for you, so that you do not have to clutter your recipes with mkdir -p invocations:
.SECONDEXPANSION:
# Make the object file depend on its directory using order-only dependency.
$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT) | $$(dir $$#)
$(CC) $(CFLAGS) $(INC) -c -o $# $<
# Let make create the directories for your targets.
%/:
mkdir -p $#
# Do not remove the directories because they are "intermediate" targets.
.PRECIOUS : %/

how to write makefile that adds libraries after source

I have been supplied with the following makefile:
CXX=g++
CXXFLAGS=-std=c++11 -g -O2
LDFLAGS=-ltbb
EXE=$(basename $(wildcard *.cc))
all: $(EXE)
clean:
rm -fr $(EXE) *.dSYM
I am new to makefiles and In order to get it working in Ubuntu, I need to modify it such that the LDFLAGS comes after the source file in the compile command. How can I do this? My attempt is as follows:
CXX=g++
CXXFLAGS=-std=c++11 -g -O2
LDFLAGS=-ltbb
SRCS=$(wildcard *.cc)
EXES=$(subst .cc,,$(SRCS))
all: $(EXES)
$(CXX) $(CXXFLAGS) $(SRCS) $(LDFLAGS) -o $(EXES)
clean:
rm -fr $(EXE) *.dSYM
Libraries should be added to LDLIBS instead of LDFLAGS. Try this in your original makefile:
LDLIBS=-ltbb
See here for reference.

Makefile C++11 - Compiling to static library

I am trying to compile my source files to a static library, however, it doesn't seem to want to work. Here is the code:
#-----------------------------------------------------------------------------
# Usage of make file
#-----------------------------------------------------------------------------
# Clean operation:
# make -f MakeClient clean
#
# Make operation:
# make -f MakeClient
#
#
#OBJ = $(SRC:.cpp=.o)
OBJ_DIR = ./obj
OUT_DIR= ../lib
OUT_FILE_NAME = libclient.a
# include directories
INCLUDES=-I. -I../common -I../../depends -I../../depends/zlib
# C++ compiler flags (-g -O2 -Wall)
CXXFLAGS := -Wall -Wextra -pedantic-errors -std+c++0x
# compiler
CCC = g++
# Enumerating of every *.cpp as *.o and using that as dependency
$(OUT_FILE_NAME): $(patsubst %.cpp,$(OBJ_DIR)/%.o,$(wildcard *.cpp))
$(CCC) -o $(OUT_DIR)/$# $^ -static $(LIB_DIR) $(LIBS) -std=c++11
#Compiling every *.cpp to *.o
$(OBJ_DIR)/%.o: %.cpp dircreation
$(CCC) -c $(INCLUDES) $(CCFLAGS) -o $# $<
dircreation:
#mkdir -p $(OUT_DIR)
#mkdir -p $(OBJ_DIR)
.PHONY : clean
clean:
rm -f $(OBJ_DIR)/*.o $(OUT_DIR)/$(OUT_FILE_NAME) Makefile.bak
The problem seems to be recognising that I'm using C++11 since the actual code does not compile.
Any ideas?
Replace CCFLAGS with CXXFLAGS, or vice versa.
And the flag is spelled -std=c++0x (thanks, #Pixelchemist).