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.
Related
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.
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
I want to share my project which was written in C/C++ (Linux environment gcc/g++ compiler) as shared library/static library without actually sharing the source code. So that other users can use my project without actually knowing my source code. Can anyone tell how do I share it as .so/.a format?
Suppose, my project looks like:
main.cpp,
source1.cpp,
source2.cpp,
source3.cpp,
head1.h,
Makefile
How can I share this project by hiding the source code of the files source1.cpp, source2.cpp and source3.cpp and making these as shared library/static library. main.cpp file contains the main() function. What is the detailed procedure?
PS: I am a novice in shared library/static library.
Suppose you have the following source file:
mylib.c:
#include <stdio.h>
void my_print(int i)
{
printf("i=%d\n", i);
}
The public header for this would be:
mylib.h:
#ifndef MYLIB_H
#define MYLIB_H
void my_print(int i);
#endif
You could then build the library like this:
gcc -g -Wall -Wextra -c mylib.c
gcc -g -Wall -Wextra -shared -fPIC -o libmylib.so mylib.o
Then you can distribute libmylib.so and mylib.h to users. Then can then use it in their code like this:
user_prog.c:
#include "mylib.h"
int main()
{
my_print(5);
return 0;
}
They would then put libmylib.so into someplace like /usr/lib or /usr/local/lib, and compile like this:
gcc -g -Wall -Wextra -o user_prog user_prog.c -l mylib
For your particular case, assuming head1.h contains the public interface and source1.cpp source2.cpp source3.cpp the library, you would compile like this:
g++ -g -Wall -Wextra -c source1.cpp
g++ -g -Wall -Wextra -c source2.cpp
g++ -g -Wall -Wextra -c source3.cpp
g++ -g -Wall -Wextra -shared -fPIC -o libmylib.so source1.o source2.o source3.o
You need to create object files from your source files. Then create static and/or shared libraries. You will need to provide a header file for use with your library. And note that your library must NOT contain main().
See detailed instructions for gcc
Ofcourse you can. Simply supply the people with the library file and the header files corresponding to the source files used to build the library.
I have the following code:
namespace rm {
namespace lib {
class Object {
public:
Object() {printf("Hi\n");}
};
}
}
Now I wanted to compile the class into an shared library using g++ -Wall -Wno-unused -Werror -fPIC -g -Iinclude/ -c -O0 -o object.o object.cpp and g++ --shared -o librm.so object.o. Compilation works with no problems, however after checking the resulting library with nm librm.so | c++filt, rm::lib::Object::Object() is nowhere to be found. GCC gives out no warning, even with -Wextra enabled.
G++ version is (Raspbian 4.9.2-10) 4.9.2
Code defined in class are implicitly marked as inline (and it is not used), and so not saved in file.
I'm using GCC version 4.7.2. I create a static library having two files "ctest1.cpp" and "ctest2.cpp".
ctest1.cpp
#include <stdio.h>
#include "ctest2.h"
void ctest1()
{
printf("In ctest1");
ctest2();
}
ctest2.cpp
#include <stdio.h>
void ctest2()
{
printf("In ctest2");
}
The header file "ctest2.h" is,
void ctest2();
And similarly the file "ctest1.h",
void ctest1();
This static library is linked to the following main file "in_test.cpp",
in_test.cpp
#include <stdio.h>
#include "ctest1.h"
using namespace std;
int main()
{
ctest1();
printf("InMain\n");
return 0;
}
I was expecting that after providing proper feedback and enabling -flto, the compiler should have inlined the function call ctest2() in file "ctest1.cpp"(and even call ctest1() in "in_test.cpp"), but it doesn't. Following are the compilation steps that I follow:
g++ -Wall -c -g -O3 -fprofile-generate -ftest-coverage ctest2.cpp ctest1.cpp
ar -rcsv libtest.a ctest2.o ctest1.o
g++ -Wall -g -O3 -fprofile-generate -ftest-coverage in_test.cpp -o checking libtest.a
For training I run the executable n times, then
g++ -Wall -c -g -O3 -flto -fwhole-program -fprofile-use ctest2.cpp ctest1.cpp
ar -rcsv libtest.a ctest2.o ctest1.o
g++ -Wall -g -O3 -flto -fwhole-program -fprofile-use in_test.cpp -o checking libtest.a
I have also tried -fuse-linker-plugin where I gave the path to the gold linker in the compilation command, but the functions were not inlined. I would also like to bring to your notice that when I try this experiment without creation of a static library (with flto and feedback), the compiler inlines the function calls. In that case, I just create one executable out of all the files. This is the reason I was expecting it to work in case of static libraries.
Can someone please tell me what's going wrong here ?