Include a .cpp file using Make - c++

I want to include GeometricRecognizer.cpp into run.cpp , I have the solution(below mentioned) for CMake which works, i want to include it in another project which uses make the format of makefile is also given below .How to add the dependency of GeometricRecognizer.cpp using makefile ?
CMake:
ADD_EXECUTABLE(run run.cpp lib/GeometricRecognizer.cpp)
TARGET_LINK_LIBRARIES(run)
Make :
INCS_GTK=-I/usr/include/gtk-2.0 -I/usr/include/glib-2.0 -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0
INCS=-I/usr/include/freetype2 -I/usr/include/mysql -Iframeworks ${INCS_GTK}
LDLIBS=-lconfig++ -lcxcore -lcv -lGL -lGLU -lglut

This line in a CMake file does not include a cpp file in another cpp file:
ADD_EXECUTABLE(run a.cpp b.cpp)
It creates an executable target called run which is the result of compiling a.cpp and b.cpp and linking those files.
In your Makefile the following lines:
MAINCXX=${shell find -name '*.cxx'}
TARGETS=${MAINCXX:%.cxx=%}
Are the two important lines which actually setup the executable targets to compile and which source files they are created from. As can be seen in those two lines MAINCXX is just a list of all files *.cxx in the source tree and TARGETS will be the same list just without the .cxx part (so if MAINCXX=run.cxx then it will be TARGETS=run.cxx)
Your makefile seems to be heavily designed to support that specific usecase, also the real Make magic happens in the last line of Makefile where it includes another Makefile.
You need to look at the file named generic.mk and understand how it is designed. If you just want to add another target you can add the following:
run: run.cpp lib/GeometricRecognizer.cpp
g++ -o run $(DEFINES) $(INCS) $(WARNINGS) run.cpp lib/GeometricRecognizer.cpp
The listing of source files can be replaced by a builtin variable in GNU Make.

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.

Changed .h file in C++ does not need to be compiled again?

I have the following question. After a successful compilation, if I compile it again after I only change some content in one of the .h files, the computer says:
make: Nothing to be done for `all'.
Can I force the compiler to compile again even if I have only modified the .h files?
If you want your output to be updated when header files change, then you have to add it to your dependency statement:
myprogram: myprogram.cpp myprogam.h
c++ -o myprogram myprogram.cpp
Typically we don't do it this way because the code that does things stays in the cpp file. If you are on unix and want to force a rebuild, just touch a cpp file to update its timestamp (forcing a rebuild) with "touch myprogram.cpp", for example, or delete your existing executable.
If you are using make without a Makefile, letting it infer dependencies, it will probably not infer the header dependencies. In this case, either blow away your executable or touch your source file.
Sounds like your Makefile does not have dependencies configured correctly. That is what you should look into fixing.
If you really want to just force a rebuild rather than fix the underlying problem. Then you can do a make clean before your make all or, if the Makefile does not have a "clean" target, delete all the generated object files and libs/executables and then run make all again.
You can force make to rebuild everything using the --always-make command line option.
However, it sounds like you don't have your dependencies setup properly in your Makefile. If your code (.cpp files) actually include headers, then generally your target for compiling them should have a prerequisite on the header files that it includes.
There is a simpler way than the accepted answer. Simply add -MD to your compiler flags in your Makefile, and -include myfile.d at the end of the Makefile (listing all source files with a *.d extension instead). This will, respectively, generate and reference additional *.d dependency files in your build folder (wherever your *.o files go) when you make, so you do not need to explicitly add every single header file to your makefile dependencies.
This is useful for projects with a long list of header files. Furthermore, this way, you know that you can't forget to include a header file in your Makefile dependencies, preventing troubleshooting time lost later when you think your binary updated when you changed a header file, but it actually didn't because you forgot to put it in the Makefile.
For example, use gcc -MD -I. -c myfile.cpp -o obj/myfile.o, and you can keep your Makefile dependencies as just foo: myfile.cpp without myfile.h.
A shortcut way to do this so you only need to list all files once is something like the following:
# Beginning of Makefile etc. etc.
# Only need to list all files once, right here.
SRCS = myfile.cpp myfile2.cpp
OBJS = $(SRCS:%.cpp=%.o)
# put .o and .d files in ./obj/
# (Assumes 'obj' directory exists)
FULLOBJS = $(addprefix obj/,$(OBJS))
# rule to make object (*.o) files
$(FULLOBJS): obj/%.o:%.cpp
gcc -MD -I. -c %< -o $#
# rule to make binary
foo: $(FULLOBJS)
g++ -o $# $(FULLOBJS)
# rule to clean (Note that it also deletes *.d files)
.PHONY: clean
clean:
rm -rf obj/*.o obj/*.d foo
# include dependency files (*.d) if available
-include $(FULLOBJS:%.o=%.d)
Can I force the compiler to compile again even if I have only modified
the .h files?
Yes ... but you probably want to improve your make (tool).
What I do is to force the most recent compile of the file in question, where the command generated by make shows.
Example:
# ... noise
g++ -O3 -ggdb -std=c++14 -Wall -Wextra -Wshadow -Wnon-virtual-dtor -pedantic -Wcast-align -Wcast-qual -Wconversion -Wpointer-arith -Wunused -Woverloaded-virtual -O0 lmbm101_11.cc -o lmbm101_11 -L../../bag -lbag_i686 -lnet_i686 -lposix_i686 -lzlib_i686 -lrt -pthread
# ... more noise.
To force a build, I highlight the "command" make created (starts with "g++", and resides between noise and more noise), and invoke it instead of make.
This is trivial using emacs on Linux. Might not be so easy on other systems.
You might consider copying this command into the file, for future use.
( i.e. I bypass make until I choose to fix my make file. )

Unexpected behavior of g++ -MG flag

I have main.cpp file for which I want to generate dependency file main.d (to be included in Makefile).
I'm calling g++ -MM -MF src/main.d -MP -MT src/main.o src/main.cpp. It works fine unless I have some source generator. I found -MG flag for this, but it doesn't work as I expected it to work.
For example: main.cpp includes module/mod.h (#include "module/mod.h") and mod.h includes generator/gen.h (#include "generator/gen.h"), gen.h is generated. There is following structure:
-Makefile
-src
--main.cpp
--module
---mod.h
---generator
----gen.h
In Makefile I have a rule to generate src/module/generator/gen.h.
Generated by g++ dependencies for existing files are correct:
src/main.o: src/module/mod.h
But for non-existing file gen.h dependency is just generator/gen.h.
If I generate this file before generating dependencies it is correct src/module/generator/gen.h.
Is there any other option for g++ to correctly generate dependencies for non-existing files?
main.d generated when gen.h doesn't exist:
src/main.o: src/module/mod.h generator/gen.h
Correct main.d generated when gen.h exist:
src/main.o: src/module/mod.h src/module/generator/gen.h
As stated in man gcc
The dependency filename is taken directly from the "#include" directive without prepending path
actually there's no way for gcc to know the real path.
I'd recommend you to fix the include statement to keep include path in sync with make path, i.e. white in mod.h
#include <module/generator/gen.h>
put Makefile to src and add proper -I flag to gcc, e.g.
SRCDIR := $(shell pwd)
CXXFLAGS += -I$(SRCDIR)
it is a good practice to always start all non-local includes from some 'source root'

Adding dependency on a non-compiled file in a Makefile

I have the following code generation scheme:
The original file is *.c.macro
It is processed by a special program that generates the *.c file. The program uses external XML files mentioned in the original .c.macro file. Somthing along this line:
macroprocess foo.c.macro -o foo.c
Then the *.c file is compiled to *.o normally
What I want to do is to make the .c file dependant on the XML files. So that if the XML changes, macroprocessing is automatically redone when 'make' command is invoked.
I can modify the code of the macroprocessor so that it would generate a list of all XMLs and write it somewhere, but I have no idea how to incorporate it into a makefile. Apparently I would need to play with 'include' command in the makefile, but usually it's employed to add dependencies on actual code like .h files.
If you can get your macroprocess to write a dependency file (e.g. *.xmldep) for each *.c.macro file you can do:
-include $(C_MACRO:.c.macro=.xmldep)
where $(C_MACRO) is a variable that contains your *.c.macro files.
The - in front will ensure that the first time, the make will not fail when it cannot locate the dependency files.
You can add foo.xml as a dependency of foo.c and use a filter command to get only the %.c.macro file as arguments for macroprocess.
Something like this:
# Basic targets
all: foo
foo: foo.o
gcc -o $# $^
foo.o: foo.c
gcc -o $# -c $<
# Special target with filter
foo.c: foo.c.macro
macroprocess -o $# $(filter %.c.macro,#^)
# Adding foo.xml as a dependency of foo.c
foo.c: foo.xml
.PHONY: all foo

I can't link my opengl program to math3d.h

I was writing an OpenGL program and it happens that I have a problem with linking with math3d.h.
I am using Ubuntu and g++.
The thing is that I didn't install the package for the math3d because I got the header file and a cpp file from the net with OpenGL superbible. So I just copied the header file and .cpp file to the local directory and did
#include "math3d.h"
But the thing is that I used to use switches to link the other header files like gl.h, glu.h ,glut.h by giving.
g++ test.cpp -lGL -lGLU -lglut.
But I don't know what to give for math3d. I get an error saying undefined reference to the functions. This error I used to get when I don't give -lGL etc. for the functions in those respective libraries.
I am totally stuck here and I don't know what to do and without this I cannot go forward.
You don't link header files. You include them, and then link the object files produced by the *.cpp files together.
Short answer
g++ test.cpp math3d.cpp -lGL -lGLU -lglut
... and it works.
Long Answer
What you are lacking is any kind of build system (read up on Makefile). You need to first build the math3d.cpp, then your test program.
Sample Makefile:
CC=g++
CFLAGS=-c -Wall
LDFLAGS=-lGL -lGLU -lglut
SOURCES=test.cpp math3d.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=test
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
Well, y'know, this one might even work :>
Need to compile math3d.cpp as well:
g++ test.cpp math3d.cpp -lGL -lGLU -lglut
There are a couple of problems with your question:
You don't link to header files - you include header files, you link object files or libraries
Besides including the appropriate header files you need to link in the library - you said you copied the .cpp file from the 'local directory' does this mean you added one of the .cpp files from the OpenGL project into your project? This can work if you make sure you get all the .cpp files you need (the functions you use that are declared in 'math3d.h' may be implemented across a number of .cpp files). However, it is MUCH better to build openGL as a library and link against that. You may want to consult the OpenGL documentation to see how to build it.