problem with including fmt library in several cpp files - c++

Good day!
I installed the fmt library in Ubuntu. Added it in my project
#include "fmt/core.h"
#include "fmt/format.h"
#include "fmt/format-inl.h"
to use fmt::format_int и fmt::format. I added library headers in several cpp files of my project. During linkage I got the mistake "multiple definition":
obj/container.o: In function fmt::v7::format_error::~format_error()': container.cpp:(.text+0x40e): multiple definition of fmt::v7::format_error::~format_error()'
obj/line.o:line.cpp:(.text+0x40e): first defined here
I've read something about this mistake. It is recommended to divide declaration and implementation in h and cpp files, to set some status to objects that causes mistake and so on. But all this recommendations imply editing of library (not my!) code!
What is wrong?
I do the following
compilation of files - one by one
g++ -std=c++11 -Wall -o obj/line.o -c /home/...//line.cpp
g++ -std=c++11 -Wall -o obj/container.o -c /home/...//container.cpp
g++ -std=c++11 -Wall -o obj/geometryObject.o -c /...//geometryObject.cpp
g++ -std=c++11 -Wall -o obj/model.o -c /home/...//model.cpp
g++ -std=c++11 -Wall -o obj/point.o -c /home/...//point.cpp
g++ -std=c++11 -Wall -o obj/main.o -c /home/...//main.cpp
Linking - error here
g++ -std=c++11 -Wall -o myapp obj/line.o obj/container.o obj/geometryObject.o obj/model.o obj/point.o obj/main.o

You shouldn't be including fmt/format-inl.h because it's an internal header. Please see the documentation for the list of public headers and what they provide.

Related

Why can't Makefile find include directories

I can't seem to include a header in my test program using a Makefile.
I've attempted to try relative paths using -I with no luck. I'm new to Make and for some reason I am having a hard time understanding it's usage.
my code, test.cpp
#include <iostream>
#include <results/enumTest.h>
int main()
{
return 0;
}
and my Makefile:
CFLAGS = -Wall -g -Wextra -Wpedantic -std=gnu++11 -m64 -Iinclude
test: test.o
gcc $(CFLAGS) -I/.. -o test test.o
test.o: test.cpp
gcc $(CFLAGS) -I/.. -c test.cpp
my directory structure:
/testDir/
./results/enuMtest.h
./test/test.cpp
./test/Makefile
I would hope that I could compile and then run the test software using a Makefile. This is more or less a tutorial for me.
Your include path -I/.. is invalid. You're trying to access the parent directory of the root directory, which cannot exist. Change your Makefile to use relative paths instead with -I..
This will access the parent directory as intended:
CFLAGS = -Wall -g -Wextra -Wpedantic -std=gnu++11 -m64 -Iinclude
test: test.o
g++ $(CFLAGS) -I.. -o test test.o # Change here
test.o: test.cpp
g++ $(CFLAGS) -I.. -c test.cpp # ...and here
Note the removed slashes.
EDIT: As commented by #Lightness, you should include non-system headers with "header.h" rather than <header.h>. Additionally, since you are trying to compile a C++ program, it is recommended to use g++ instead of gcc (I've updated this in the snippet above).
There are several improvements possible.
You try to set the include path to the parent dir of / which is /.
You try to compile a c++ program using gcc but not g++
You don't need (it would still work) to set an include path, when linking. (test:
test.o)
Since there is no directory named include in the filetree you specified, you also don't need -Iinclude in the CFLAGS
Usually the C++ variant of CFLAGS is named CXXFLAGS, but I did not change it in the modified example below.
A corrected makefile would be:
CFLAGS = -Wall -g -Wextra -Wpedantic -std=gnu++11 -m64
test: test.o
g++ $(CFLAGS) -o test test.o
test.o: test.cpp
g++ $(CFLAGS) -I.. -c test.cpp
As an additional note:
#include "" instead of #include <> would also work. The difference is, that "" searches the included file relative from the location of the current source file, while <> uses the directories you specify using -I.
Find more details here

compiling c++ 11 program the simple way using makefile

Got an assignment to write a simple program in c++11 which contains the following files:
main.cpp
house.h
tree.h
The main function is obviously in the main.cpp file.
main.cpp includes the 2 header files and uses them.
when I tried to compile on Linux, I wrote:
g++ -std=c++11 -O2 -Wall -pedantic -pthread main.cpp -o prog
And I got a prog file which I could run.
Then I tried to compile it using a makefile, what I did was this:
all:
g++ -std=c++11 -O2 -Wall -pedantic -pthread main.cpp -o prog
and hit make all
Sadly it doesn't work.
Tried to search the web for how to do it properly, no luck.
Can you tell me how it needs to be done?
Also, how to make a smart compile? i.e. compile only when the above files are changed.
Thanks!
Create a Makefile with just the following lines and check this out:
CFLAGS += -g -O2 -Wall -W -pedantic
CXXFLAGS=$(CFLAGS) -std=c++11
CFLAGS += -pthread
LDFLAGS += -pthread
And type make main. Make will search its built-in rules and discover that there is a way to get from main.cpp to a compiled program named main. It will then execute a built-in rule that looks something like:
$(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $#
If you want to just type make then you can add:
all: main
And the built-in implicit rules will build main for you when you type make.
In Makefile
all:
<TAB>g++ -std=c++11 -O2 -Wall -pedantic -pthread main.cpp -o prog
This will work, Please pay attention here that <TAB> is the tab character that we need to insert.
Simply compiled it by issuing
make
Or for a simple cases, make provides a short cut with default rule. You can compile our code without using Makefile.
CXXFLAGS=-std=c+=11 -Wall -pedantic -pthread make main
But this approach will name the program name as name of the file, i.e. main here, instead of prog as you wanted

C++ - Makefile using g++

I have made a Makefile for my CMSC 202 course project, 'Blackjack'. It does everything I need it to and it works perfectly. You may be asking why I posted here then, this is because I have no idea how it works and I didn't use any other resources but myself to create it.
Here is my Makefile code.
# Object files to either reference or create
OBJECTS = Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
# The executable file that will be created at the end
EXEC = Proj2.out
# The flags to use for compilation
FLAGS = -Wall
# The code compiler to use for compilation
CC = g++
# Perform action on all object files (May or may not exist)
all: $(OBJECTS)
$(CC) $(FLAGS) -o $(EXEC) $(OBJECTS)
Here is the terminal output when I call make in the terminal.
g++ -c -o Proj2.o Proj2.cpp
g++ -c -o Blackjack.o Blackjack.cpp
g++ -c -o Deck.o Deck.cpp
g++ -c -o Card.o Card.cpp
g++ -c -o Hand.o Hand.cpp
g++ -c -o Player.o Player.cpp
g++ -Wall -o Proj2.out Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
Can anyone tell me how the .o files are being compiled? It does not look like they are being prompted to be compiled with that g++ -c -o $.o $.cpp command anywhere in the Makefile. Nor did I state to use any .cpp files.
Thank you in advance for your help.
Edit
Thanks to all your great help, this is now the terminal output I receive when using make.
g++ -Wall -c -o Proj2.o Proj2.cpp
g++ -Wall -c -o Blackjack.o Blackjack.cpp
g++ -Wall -c -o Deck.o Deck.cpp
g++ -Wall -c -o Card.o Card.cpp
g++ -Wall -c -o Hand.o Hand.cpp
g++ -Wall -c -o Player.o Player.cpp
g++ -Wall -o Proj2.out Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
Thank you so much to all of you who have contributed.
Make has a set of implicit rules (see here for a reference). For instance
Compiling C++ programs
`n.o' is made automatically from `n.cc' or `n.C' with a command of the form
`$(CXX) -c $(CPPFLAGS) $(CXXFLAGS)'.
Most make's will also use this rule for .cpp files.
When make sees there's a x.o requirement for one of your targets, it will try to see if it can generate x.o using implicit rules, and in your case find it can do it starting from a .cpp file.
This Makefile uses implicit rules which are a great way to reduce duplication.
By default the first target will be built, here all. It depends on a number
of object files listed in a variable $OBJECTS, e.g. Proj2.o who's
dependencies aren't listed in the Makefile. Now if make sees an input file in the current directory
with a matching name, e.g. Proj2.cpp it will try
to build Proj2.o from it (there are other implicit rules for sources in
other languages). Proj2.o would then be built by default with the command
$(CXX) $(CXXFLAGS) -c -o Proj2.o
where $(CXX) the name of the C++ compiler (g++ in your case).
The explicit build step for all assembles all the object files into the
target executable.
Looking at above build command you'll notice a small problem in your Makefile. Since the flags to the C++ compiler are given in a variable FLAGS and not the standard CXXFLAGS no warnings will be emitted when building the object files. Using the standard name would fix this (you do want warnings, maybe even more than -Wall gives you).

"Undefined reference" error when using custom destructor

I'm trying to write a class that needs to deallocate some memory, so I've defined a custom destructor. This is compiled as a shared library. However, when I try to compile a basic program to use that library, I'm getting the usual "undefined reference" error when a definition cannot be found. If I remove the destructor, this does not occur.
Here's a stripped-down example:
Header file:
#ifndef _SKYMAP_H_
#define _SKYMAP_H_
#include <vector>
#include "TCanvas.h"
class BL_Skymap {
public:
BL_Skymap();
~BL_Skymap();
protected:
TCanvas mCanvas;
};
#endif //_BENSLIBRARY_SKYMAP_H_
Source file:
\#include "BL_Skymap.h"
BL_Skymap::BL_Skymap()
{
}
BL_Skymap::~BL_Skymap()
{
}
Now the program I'm using is simply this:
\#include "BL_Skymap.h"
int main()
{
BL_Skymap map;
return(0);
}
Note that I'm using the ROOT analysis package (that's the TCanvas object). When I compile the small program above, I get the following errors (the Skymap class is compiled into libMyLibrary.so):
g++ test.cpp -o test -lMyLibrary `root-config --cflags --glibs`
/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../lib/libMyLibrary.so: undefined reference to 'TCanvas::~TCanvas()'
/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../lib/libMyLibrary.so: undefined reference to 'TCanvas::TCanvas(bool)'
Please note that the root package gives a utility to generate the required compiler flags, which is the purpose of root-config --cflags --glibs above.
What am I missing here?
UPDATE: I've written a Makefile to perform the compilation of my library, which executes the following:
g++ -Wall -Wextra -ansi -pedantic --std=c++11 -Isrc -Ihdr -MM -MT 'obj/BL_Skymap.o' src/BL_Skymap.cpp -MF BL_Skymap.d `root-config --cflags --glibs`
g++ -Wall -Wextra -ansi -pedantic --std=c++11 -Isrc -Ihdr -fPIC -o obj/BL_Skymap.o -c src/BL_Skymap.cpp `root-config --cflags --glibs`
g++ -Wall -Wextra -ansi -pedantic --std=c++11 -shared obj/*.o -o libMyLibrary.so
UPDATE2: I found the problem - in the final step in the compilation above, I was forgetting to add the call to root-config and therefore libMyLibrary.so wasn't linking to the ROOT libraries like it should have.
As stated in an update to the original question, my problem was that I was using the relevant flags for the ROOT libraries when I was compiling the BL_Skymap.o object file, but not when I was linking the object file together to make the libMyLibrary.so file.
Adding the ROOT flags to this final step fixed the problem.

GLEW based program does not compile

I am trying to use GLEW in a program I'm creating, but my compiler will not compile it, instead it throws a ton of errors at this line gcc -g -c glew.c -o glew.o. This is my Makefile:
MY_LIBS =
glewex: glew.o main.o glew.h
g++ main.o glew.o glew.h -o glewex $(MY_LIBS)
glew.o: glew.c
gcc -g -c glew.c -o glew.o
main.o: main.cpp
g++ -g -c main.cpp -o main.o
It simply outputs hundreds of errors that look like this:
__glewActiveTexture redeclared without dllimport attribute: previous import ignored [ -Wattributes ]
Try this:
gcc -g -DGLEW_STATIC -c glew.c -o glew.o
That should prevent DLL import/export decorations from getting added to the declarations.
You don't want to add the library source files to the compiler input of your project. You should add the library to the list of linker inputs; either statically (libglew.a) or dynamic (-lglew).
I.e. either
gcc -o … -lglew
or
gcc -o … libglew.a
When linking GLEW statically you must add -DGLEW_STATIC to the compiler options generating the compilation units (.o files)