How to make */* for many folders of self-contained cpp files? - c++

I'm playing around some tutorial code from this OpenCV 2 Cookbook. The code doesn't come with any Makefiles, and I'd like to create a Makefile that can Make all of the files in the codebase. My plan is to compile all the files with profiling, and then make a script that runs all the executables and collects the gprof results. Then, I can get some intuition for the computation time of various OpenCV functions.
The codebase is arranged like this: tutorial_code/Chapter[1-10]/*.cpp
Each .cpp file is self-sufficient and can be compiled without linking against other modules in this codebase. (There are a few small header-only libraries, though.)
Here are a couple things that I'm stuck up on:
Typically, the $(EXEC) in a Makefile represents a file that is the culmination of much of the building effort. However, in my case, I want to create a separate $(EXEC) for each .cpp file. I think I'm close to getting this right, but so far my Makefile just generates *.o but not *.out
I understand that SOURCES = $(wildcard *.cpp) is a way to "collect" the set of cpp files in the current directory. It would make sense that SOURCES = $(wildcard */*.cpp) would drill down and grab all .cpp files in the subdirectories. It doesn't seem to work, though.
Starting from this tutorial, I set up a Makefile that implements the proposed functionality. It doesn't quite work... $(wildcard */*.cpp) doesn't seem to drill down into directories, and I'm not sure how to do something like $< and $# to refer to basefilename.o and to create basefilename.out.
CC = g++
CC_FLAGS = -w `pkg-config opencv --cflags`
LINK = g++
LINKOPTS = -pg `pkg-config opencv --libs`
SOURCES = $(wildcard */*.cpp)
OBJECTS = $(SOURCES:.cpp=.o)
EXEC = $(SOURCES:.cpp=.out)
%.out: %.o
$(LINK) $< $(LINKOPTS) -o $#
%.o: %.cpp
$(CC) -c $(CC_FLAGS) $< -o $#
clean:
rm -f $(EXEC) $(OBJECTS)
I'm fairly familiar with Makefiles and OpenCV, and I haven't had a problem compiling my own projects by hand-coding the lists of dependencies, objects, etc in Makefiles. However, for the matter at hand, it'd be fantastic to just automatically make everything without much user intervention.
Feel free to comment, email, or message me for a copy of the codebase that I'm trying to compile.
I've also thought of making a script that iterates through the tutorial_code/Chapter[1-10] directories and creates one Makefile for each directory. Then, I'd make an other function in the script to call Make once in each directory. The idea of doing one grand Makefile sounds like more fun, though.
EDIT: This does work if I use SOURCES = $(wildcard *.cpp) and place the Makefile in the same directory where cpp files are located. However, I'm still trying to figure out how to have $(wildcard */*.cpp) drill down into subdirectories.
EDIT 2: The Makefile shown above now works properly. To see the earlier version, feel free to scroll through the edit history.

You can write a version of wildcard that works recursively to any depth using only make functions:
find-recursive = \
$(wildcard $1/$2) \
$(foreach f,$(wildcard $1/*/.),\
$(call find-recursive,$(patsubst %/.,%,$f),$2))
SOURCES = $(call find-recursive,.,*.cpp)

Related

Compiling larger C++ projects in VSCode

Im trying to compile a C++ project using MinGW and can compile a simple main.cpp file with hello world without problems using g++ main.cpp -o main and also with external libraries using main.cpp extlib.cpp -o main.
But say im working on a rather large project with 10s of .cpp files organised inside of different files, how can I get the compiler to find all the cpp files that are needed? I know i can use main.cpp libs/*.cpp -o main but this will only compile all the source files inside of libs but not inside folders in libs.
Ive looked into make and cmake but dont understand how those automate the process if you still have to manually enter the directories. Is there no way to simply hit compile or at least a command line command to compile all the needed files inside a directory? This seems to work with #include without issues?
If you want to stick with MinGW and GNU Make I would probably use a Makefile that looks something like this to start with. You basically only need to maintain the srcs-variable by adding your source-files there. Usually you can use the wildcard-function for this if you have sub dirs. The rest of the Makefile (which can be left alone) sets up a build of an executable main.exe that depends on all the object-files. I also included dependency-handling via the deps-variable and the compiler flag -MMD which comes in handy when the project grows.
srcs := $(wildcard *.cpp) $(wildcard dir1/*.cpp) $(wildcard dir2/*.cpp)
objs := $(srcs:.cpp=.o)
deps := $(objs:.o=.d)
app := main.exe
CXXFLAGS := -MMD -Og -g -Wall -Werror -Wpedantic -std=c++2a
$(app): $(objs)
$(CXX) $(LDFLAGS) -o $# $^ $(LDLIBS)
-include $(deps)
.PHONY: clean
clean:
rm -f $(objs) $(deps)
I use CMake for simple projects.
Here's the simplest example I came with (CMakeLists.txt to put along your main.cpp in the root of your project):
cmake_minimum_required(VERSION 3.1)
SET(CMAKE_APP_NAME "Project")
project (${CMAKE_APP_NAME})
# list here your directories
INCLUDE_DIRECTORIES(dir1)
INCLUDE_DIRECTORIES(dir2)
# add an executable and list all files to compile
add_executable(${CMAKE_APP_NAME} main.cpp
dir1/file1.cpp
dir1/file1.h
dir2/file2.h
dir2/file2.cpp
)
Once your project becomes more complex, you could use file(GLOB*) to avoid writing all the files.
Overall, the most "automated" way to build a larger project is to use CMake. Keep learning it. You can use file(GLOB) to avoid listing every file in CMakeLists.txt. This is not recommended (see discussion here), but I do it anyway and never had any issues.

Makefile doesn't check for updates in header file [duplicate]

This question already has answers here:
How to make Makefile recompile when a header file is changed?
(3 answers)
Closed 3 months ago.
I thought my makefile is pretty good but then I tried to update only a header file and recompile my library, but it doesn't change anything.
How can I make it work and recompile also the code in the h file.
My makefile:
SHELL = /bin/sh
SOURCE_FILES_DIRS = -I./../frmwrk/ -I./../Utils/
CXX = g++
CXXFLAGS = $(SOURCE_FILES_DIRS) -std=c++17 -rdynamic -fPIC -g -Wall
LDFLAGS = -shared
LIBS_DIR = ../../libs/
LIB_NAME = libIni.so
TARGET = $(LIBS_DIR)$(LIB_NAME)
SOURCES = $(shell echo *.cpp)
HEADERS = $(shell echo *.h)
OBJECTS = $(SOURCES:.cpp=.o)
LINK_LIBS = -lFrmwrk -lUtils
PREFIX = $(DESTDIR)/usr/local
BINDIR = $(PREFIX)/bin
all: $(TARGET)
$(TARGET): $(OBJECTS) $(HEADERS)
$(CXX) $(CXXFLAGS) -L$(LIBS_DIR) $(LDFLAGS) -o $(TARGET) $(OBJECTS) $(HEADERS) $(LINK_LIBS)
clean:
rm -f *.o $(TARGET)/*.so
rm -rf $(TARGET)
$(TARGET): $(OBJECTS) $(HEADERS)
[relink command]
This forces only a relink when the header file is changed. make has no idea, whatsoever, which C++ source file includes which header file. make knows only about dependencies explicitly declared in the header file. The only dependency stated here is that $(TARGET), the executable, has a dependency on the header file.
In order to force, for example, main.o to be recompiled when declarations.h are included, because main.cpp #includes declarations.h, you have to be explicit:
main.o: declarations.h
This directs make to rebuild main.o, from main.cpp, whenever declarations.h changes, which is what you want.
Manually tracking which object modules need to be rebuilt due to changes to which header files does not scale. make, of course, has no knowledge about anything C++ related, so you'll have to manually keep track of all the dependencies, manually, but that again doesn't scale.
The solution here is to migrate to some higher level build tools, like GNU autoconf and automake which will write the Makefile for you, complete with a bunch of rules that use compiler flags to dump the dependencies, and update the rules automatically, for you. You can always use the same compiler flags (there are flags that, and build all the scaffolding yourself, without autoconf and automake. But why bother, when autoconf automake will do it for you?
I know that this might be totally late but a quick solution to this would simply be to run a make clean such that you rm (remove command) remove the executables. By doing this I found a quick solution to this sort of problem.

C++ makefile building multiple dll and project structuring

I have tried searching for an answer but to no avail, so given that my project has got the following structure
makefile
./src
strings.cpp
networking.cpp
./bin
strings.dll
networking.dll
./build
strings.o
networking.o
./include
strings.h
networking.h
./lib
boost
I am very new to Makefiles and from the research I have done so far I have managed to get this together (not very complicated, I know)
CC = g++
SRC = src/strings.cpp
OUT = bin/strings.dll
OBJ = build/strings.o
INC= -I include
all: strings.dll
strings.dll: strings.o
$(CC) -shared -o $(OUT) $(OBJ)
strings.o: $(SRC)
$(CC) $(INC) -DBDLL -c $(SRC) -o $(OBJ)
The issues/questions I have are
1- It always goes through the whole compilation process, even when I have not changed the source code ?
2- How could I make things more 'effective' ? I saw examples of people using wildcards and such, but I had difficulty following along. Could I use wildcards to begin with since I want separate dlls for each target ?
3 - Lets say I introduced algorithms.h and algorithms.cpp what would be the recommended way of including that in the build ?
Thanks for any help, really appreciate it
First. Whole compilation process goes because make search for target "strings.dll" but build bin/strings.dll. So if you replace it to
bin/strings.dll: strings.o
$(CC) -shared -o $(OUT) $(OBJ)
bin/strings.o: $(SRC)
$(CC) $(INC) -DBDLL -c $(SRC) -o $(OBJ)
build of targets (bin/strings.o and bin/strings.dll) will be performed only if prerequisite is changed.
Second - basically wildcards are used for search all files inside the directory something like this: $(whildcard *.cpp) evaluates to all cpp file inside the current directory. So you can write something like this:
all_sources = $(wildcard *.cpp)
all_objects = $(addprefix bin/,$(all_sources:.cpp=.o))
all: bin/strings.dll
bin/strings.dll: $(all_objects)
<how to build strings.dll from objects>
bin/%.o: %.cpp
<how to build objects inside bin dir from cpp of current dir>
Third - makefile is not build system itself it is just a tool that has domain specific language. You can write your own build system using make. If you want ready build you better to study automake/cmake/... many of them.
Also it is good beginning to start using make tool. Don't stop and you will surprise how much power inside it.

Makefile using a library

I have made a project in Xcode who implements an algorithm in just 1 c++ file. To compile it needs an library who is in a directory called libgambit in an other directory. The directory structure looks like this:
lib/
libgambit/libgambit.cc
libgambit.h
game.cc
game.h
...
src/Game\ Theoretic\ Analysis/convertion.cc
convertion.h
Makefile
So what I need is a makefile who first builds everything whats in libgambit and uses the object files who result from that to build and link convertion.cc. The executable should then be in the same folder as the makefile.
It seems a pretty easy question but I'm suffering on it for 2 days now.
There's more than one way to do it. Here is a crude but effective way:
LIBSRCS := $(wildcard $(PATHTOLIB)/lib/libgambit/*.cc)
LIBOBJS := $(LIBSRCS:.cc=.o)
convertion: convertion.o $(LIBOBJS)
#g++ -Wall $^ -o $#
%.o: %.cc
#g++ -Wall -Ilib/libgambit -c $< -o $#
This does not track dependencies very well (if you alter a header file, Make won't notice that some objects must be rebuilt), but it is good enough for now. Let us know if you want to try advanced dependency handling.
You can use the Makefile developed here. It allows you to add new files and directories to the build without changing the Makefile.

Simple makefile generation utility?

Does anyone know of a tool that generates a makefile by scanning a directory for source files?
It may be naive:
no need to detect external dependencies
use default compiler/linker settings
You can write a Makefile that does this for you:
SOURCES=$(shell find . -name "*.cpp")
OBJECTS=$(SOURCES:%.cpp=%.o)
TARGET=foo
.PHONY: all
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $#
.PHONY: clean
clean:
rm -f $(TARGET) $(OBJECTS)
Just place this in root directory of your source hierarchy and run make (you'll need GNU Make for this to work).
(Note that I'm not fluent in Makefileish so maybe this can be done easier.)
CMake does it and it even creates makefiles and Visual Studio projects. http://www.cmake.org/
All you need to do is creating a CMakeLists.txt file containing the follwing lines:
file(GLOB sources *.h *.c *.cxx *.cpp *.hxx)
add_executable(Foo ${sources})
Then go into a clean directory and type:
cmake /path/to/project/
That will create makefiles on that clean build directory.
This is what I would use for a simple project:
CC = $(CXX)
CXXFLAGS += -ansi -pedantic -W -Wall -Werror
CPPFLAGS += -I<Dir Where Boost Lives>
SOURCES = $(wildcard *.cpp)
OBJECTS = $(patsubst %.cpp,%.o,$(SOURCES))
all: myApp
myApp: $(OBJECTS)
The only restriction is that if you are building an executable called myApp. Then one of the source files should be named myApp.cpp (which is where I put main).
There's a very old script called 'makedepend' that used to make very simple makefiles. I've since switched over to cmake for almost everything.
Here's the wiki article http://en.wikipedia.org/wiki/Makedepend, note the list of Alternatives at the bottom including depcomp in automake, and the -M flag in gcc.
EDIT: As someone pointed out to me in another question, gcc -MM *.cpp > Makefile produces a rather nice simple makefile. You only have to prepend your CPPFLAGS and a rule for constructing the entire binary... which will take the form:
CPPFLAGS=-Wall
LDFLAGS=-lm
all: binary_name
binary_name: foo.o bar.o baz.o biff.o
no need to detect external dependencies
use default compiler/linker settings
Why script then? Provided that all your project source files are *.cpp and in current directory:
all: $(notdir $(CURDIR))
$(notdir $(CURDIR)): $(subst .cpp,.o,$(wildcard *.cpp))
$(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $#
The Makefile would build the all the source files with default compiler/linker settings into an executable named after the name of the current directory.
Otherwise, I generally recommend people to try SCons instead of make where it is much simpler and intuitive. Added bonus that there is no need to code manually clean targets, source/header dependency checking is built-in, it is natively recursive and supports properly libraries.
As described in the linked discussion, HWUT is a tool that
can generate pretty Makefiles, searching for dependencies and include files in directories that you tell it. On windows you need to install MinGW and Ctags. Under Linux gcc and ctags are most likely present. It is OpenSource and free to use.
Especially, when generating Unit Tests for some already existing modules of some larger project with bad cohesion, this feautures easily spares you hours or even days.