How to export a #defines from c++ shared library to application - c++

My library is built with some #define enabled (e.g -DUSE_FOO=1) and also USE_FOO is used in public header file.
The problem is an application using library includes the public header file and thus USE_FOO appears in the application context and would be undefined in application context.
How can I export USE_FOO define to application based on whether it's enabled in the library or not?
e.g
include/public/foo.h
lib/libfoo.so --> foo.cc
in foo.h contain code as
#if defined (USE_FOO)
#define SIZE 5
#else
#define SIZE 10
#endif
foo.cc
#include "foo.h"
int getSizeFromLib()
{
return SIZE;
}
libfoo.so source file includes foo.h and built by configuring USE_FOO at compile time.
Now, application uses libfoo library by including public/foo.h and uses his own build configuration to build the app. but the problem is application is unaware of USE_FOO which will be always undefined in application side. So SIZE will be 10 in application but 5 inside the library
I want USE_FOO to exported to application based on whether its defined for libfoo.so or not. I.e if libfoo.so is built with USE_FOO=1 application should also see USE_FOO=1 and vice-versa
If it's not possible to do it in pre-defined way, then any trick to solve this would be welcomed.

In Linux world this task is solved by pkgconfig tool. Basically in addition to binaries and headers your library also comes with a .pc file which looks like
prefix=/usr/local
exec_prefix=${prefix}
includedir=${prefix}/include
libdir=${exec_prefix}/lib
Name: foo
Description: The foo library
Version: 1.0.0
Cflags: -I${includedir}/foo USE_FOO=1
Libs: -L${libdir} -lfoo
This file is installed to /usr/lib/pkgconfig and clients should query proper CFLAGS from it by calling pkg-config from Makefile:
CFLAGS = -g -Wall -Wextra $(pkg-config --cflags)
For more details, check the guide.
The only portable solution would be to add an auto-generated foo-config.h header which will be included by all library public headers and would define all version-specific defines (like USE_FOO). This would of course only work in source files that actually include library headers.

There is no way to "export" a preprocessor define from a library to an application. Both must be compiled with compatible flags, for example:
CFLAGS=-DUSE_FOO=1
gcc $CFLAGS --shared -o lib/libfoo.so foo.cc
gcc $CFLAGS lib/libfoo.so app.c

Related

Including isolated Qt objects in .cpp file

I want to use a library that utilizes the QT-class QVector2D to calaculate B-splines (library: https://github.com/ejmahler/SplineLibrary). But I can't figure out how to get the includes / linking right using a simple .cpp file and compiling with g++.
This is my attempt
// test.cpp
// My attempt at including the QVector2D class
#include </home/user/Qt/5.8/gcc_64/include/QtCore/qconfig.h>
#include </home/user/Qt/5.8/gcc_64/include/QtCore/qglobal.h>
#include </home/user/Qt/5.8/gcc_64/include/QtGui/qtguiglobal.h>
#include </home/user/Qt/5.8/gcc_64/include/QtGui/qvector2d.h>
// For spline library
#include <SplineLibrary/spline_library/spline.h>
#include <SplineLibrary/spline_library/vector.h>
#include <SplineLibrary/spline_library/splines/uniform_cr_spline.h>
int main()
{
std::vector<QVector2D> splinePoints{
QVector2D( 0, 1),
...
};
UniformCRSpline<QVector2D> mySpline(splinePoints);
QVector2D interpolatedPosition = mySpline.getPosition(0.5f);
}
Compiling with g++ 5
$ g++ -std=c++17 test.cpp -o test
gives
/home/user/Qt/5.8/gcc_64/include/QtCore/qglobal.h:63:28: fatal error:
QtCore/qconfig.h: No such file or directory compilation terminated.
I have verified that the file qconfig.h exists and that it is in the path as included.
I'm guessing my error is either in how I try to include the QT-headers, that I need to link it somehow.
How do I properly include a single Qt component (in this case QVector2D) and compile the project using g++?
First of all, you should never specify absolute paths in you includes. If someone else wants to use your code, they would need to modify all the files to point to the correct headers on their system. Apart from that you're using internal headers that you're not supposed to include yourself. At the very top of the Qt documentation for QVector2D you can find what header you're supposed to include to use the QVector2D class.
So test.cpp should look like this:
#include <QVector2D>
// For spline library
#include <SplineLibrary/spline_library/spline.h>
#include <SplineLibrary/spline_library/vector.h>
#include <SplineLibrary/spline_library/splines/uniform_cr_spline.h>
int main()
{
std::vector<QVector2D> splinePoints{
QVector2D( 0, 1),
...
};
UniformCRSpline<QVector2D> mySpline(splinePoints);
QVector2D interpolatedPosition = mySpline.getPosition(0.5f);
}
Compiler flags
Now, since you have a custom installation path for Qt5.8, the compiler can't find the header in the default search path, so when compiling this file you need to tell the compiler where to search for the Qt headers. As indicated by the line QT += Gui in the documentation I linked above, QVector2D is part of the QtGui sublibrary, so you need to include the headers in the directory /home/user/Qt/5.8/gcc_64/include/QtGui/. The compiler flag to do so is -isystem /home/user/Qt/5.8/gcc_64/include/QtGui.
However, the QtGui headers themselves depend on QtCore headers, but their path is given relative to the /home/user/Qt5.8/gcc_64/include directory, so in order for the compiler to find the header files the QtGui headers depend on you also need to add the compiler flag -isystem /home/user/Qt/5.8/gcc_64/include. Btw this is also the reason why you got the error QtCore/qconfig.h: No such file or directory compilation terminated., there is no such file QtCore/qconfig.h in the directory where test.cpp is located, nor is there one in the system include path, and you didn't give the compiler the additional path where to look for it.
So the compilation should be successful when executing g++ -std=c++14 -isystem /home/user/Qt/5.8/gcc_64/include -isystem /home/user/Qt/5.8/gcc_64/include/QtGui -fPIC -c test.cpp (assuming that the compiler previously didn't have any problem to find SplineLibrarys includes).
Linker flags
The previous command just compiles test.cpp (note the -c flag), but doesn't produce a binary that you can run. The linker has the same problem as the compiler - it doesn't know where to find the precompiled Qt libraries to link against unless you tell it where to look for them. The flag to do so is -L/home/user/Qt/5.8/gcc_64/lib.
In addition to telling the linker where to look for the precompiled libraries, you also need to tell it which ones you're using. As I've mentioned before, QVector2D is part of the QtGui sublibrary, so you need to add -lQt5Gui. Since QtGui depends on QtCore, -lQt5Core also needs to be added.
Assuming you used the default installer, your installation of Qt only includes dynamic libraries, so you also need to tell the linker to store the information where to find the library files in the created binary. The flag you need to add for this is -Wl,-rpath=/home/user/Qt/5.8/gcc_64/lib.
So putting everything together, the final command you need to run is g++ -std=c++14 -fPIC -isystem /home/user/Qt/5.8/gcc_64/include -isystem /home/user/Qt/5.8/gcc_64/include/QtGui -L /home/user/Qt/5.8/gcc_64/lib -Wl,-rpath=/home/user/Qt/5.8/gcc_64/lib test.cpp -lQt5Core -lQt5Gui.
If you use clang instead of gcc, the same command runs just fine if you replace g++ by clang++.

Makefile Dependencies, What Should Be a Dependency?

I have a conceptual question regarding makefile dependencies and this is because I see inconsistency online about this.
Let's say I have the following files:
main.cpp uses-> my_math.cpp and my_strings.cpp
my_math.cpp uses-> my_math.h
my_strings.cpp uses-> my_strings.h
If I have a makefile, with the general outlay of:
program: $(all_objs)
g++ $(all_objs) -o program
main.o: ...
.......
my_math.o: ...
.......
my_strings.o: ...
.......
I don't know what should go into each dependency. Like, math.o #includes my_math.h and my_strings.h, does that mean that main.cpp needs to recompile if I change my_math.h? But why? It uses it like a library, right? It doesn't need to recompile main.cpp or does it?
As in, should the result for main.o be:
1) main.o: main.cpp
gcc -c main.cpp
2) main.o: main.cpp my_strings.cpp my_strings.h my_math.cpp my_math.h
gcc -c main.cpp
3) main.o: main.cpp my_strings.cpp my_strings.h my_math.cpp my_math.h
gcc -c main.cpp my_strings.cpp my_math.cpp
I'm a bit lost on dependencies and how linking works.
Any help would be appreciated! Thank you!
The dependencies are everything whose change requires recompiling the source code. That includes not only your #include-d headers, but also the indirectly included system headers, and even (in principle) the compiler and build chain itself (when you upgrade your C++ compiler, you should recompile all your software). If some of your C++ code is generated from some source (e.g. by tools like GNU bison or Qt moc, or by your own script), both the sources and the generating tools are dependencies. Read also about package managers.
Practically speaking, the GCC compiler is able to output most make dependencies, notably with -M and related processor options. Read also about auto dependencies generation. See also this.
(in practice, you generally don't code in your Makefile some explicit dependency on the compiler itself; but you should not forget to make clean when the compiler has been upgraded)
Unless your main.cpp is including my_strings.cpp (which is not conventional and is very bad taste), your make rule won't have a dependency from my_strings.cpp to main.o. But probably your main.cpp is #include-ing (directly or indirectly) my_strings.h so main.o should depend not only on main.cpp but also on my_strings.h
As a rule of thumb, your object file my_strings.o depends on the source file my_strings.cpp and all the header files which are directly or indirectly #include-d in it. Your main program executable depends on all its object files and the libraries you are linking into it. Order of program arguments to g++ matters a lot.
It uses it like a library, right?
From what you are showing, you don't have any own libraries (but you probably use the standard C++ library, and perhaps some other system libraries). On Linux these are lib*.a files (static libraries) or lib*.so files (shared libraries). A library is an organized agglomeration of object code -and sometimes other resources.
I'm a bit lost on dependencies and how linking works.
Understand the difference between source code files, object files (they contain relocation information) and executables (on Linux, object files and executable files and shared libraries are using the ELF format). Read also about the role of compilers, linkers (the g++ program can run both) & build automation (for which you are using make).
Read Program Library HowTo and much more about translation units and linkers (& name mangling), notably Levine's book on Linkers & loaders.
See also this & that & this (examples about Makefile for C++ programs).
BTW, you should use g++ (not gcc) when compiling C++ code. There are significant differences (even if gcc is sometimes able to compile C++ or Fortran code, you'll mostly use gcc to compile C code). And (assuming you use specifically GNU make) your Makefile should mention $(CXX) (not g++). You need to understand the builtin rules of make (run once make -p to get them) and you'll better take advantage of them (e.g. use $(COMPILE.cc) or $(COMPILE.cpp) etc...). You certainly should pass -Wall -Wextra (to get all warnings, and even more), and -g (to get debugging information) to g++. Practically speaking, you should set your CXXFLAGS variable in your Makefile.
Take time to carefully read GNU make documentation and Invoking GCC.
Look into the Makefile-s of existing free software projects. For various reasons, some projects are generating their Makefile-s with tools like autoconf or cmake. But most simple projects don't need that generality, and you should be able to write your own Makefile for your C++ projects. Of course, take inspiration from existing code.
If you have
main.cpp uses-> my_math.cpp and my_strings.cpp
my_math.cpp uses-> my_math.h
my_strings.cpp uses-> my_strings.h
The purpose of Make is to maintain dependency between modules in two different ways, by building .o files and by linking .o files.
you can picture it as a dependency tree where main.o is the root
main.o
/ \
my_math.o my_strings.o
for each .o there is also a dependency tree with regard to source files e.g.
main.o my_math.o my_strings.o
/ \ / \ / \
main.cpp main.h my_math.cpp my_math.h my_strings.cpp my_strings.h
So when make builds, it sets up a dependency tree with main.o at its root and then tries to build all .o files needed for main. When all .o files have been built they are linked.
By following the dependency tree Make ensures that main will be linked/built when one of the dependent modules is changed.
However if you have used something like say a constant from one of the included headers #define MAXSTRING 32 you are no longer merely dependent on the .o file, you are then dependent on the header content so you need to make sure that main.o is built if the header is changed since linking is then not enough so you add the .h in the dependency
main.o
/ | \
my_math.o my_strings.o my_strings.h
Of course there are ways to make the header more robust to avoid that dependency but is another question.
Your cpp files do not depend on other cpp files in terms of compilation. Simple cpp file should only depend on h files.
In your question you say main.cpp depends on my_math.cpp and my_strings.cpp, but I think it is not true. I can guess you have #includes there and these are your dependecies.
Generally speaking dependencies for cpp files are all #included h files.
Usually there are no dependencies between cpp files. You just generate o files by compiling them. Then your final binary depends on all o files.

Linking pcap library in OpenWrt Makefile

My simple pcap test app compiles and runs fine using: gcc main.c -o test -lpcap
but when using the OpenWrt SDK: make package/myapp/compile V=s
I get the error message:
main.c:(.text.startup+0x24): undefined reference to `pcap_lookupdev'
collect2: error: ld returned 1 exit status
From what I've read, I need to add the line:
LDFLAGS = -lpcap
to one of the Makefiles, but I'm not sure where it should go. What confuses me is that I can use the pcap constant PCAP_ERRBUF_SIZE, can anyone tell me why I can access this, but not pcap functions?
main.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <pcap.h>
int main(int argc, char **argv)
{
printf("Hello PCAP!\n");
char *dev, errbuf[PCAP_ERRBUF_SIZE];
printf("%d\n\n", PCAP_ERRBUF_SIZE);
// Make works without this part
dev = pcap_lookupdev(errbuf);
printf("Device: %s\n", dev);
return 0;
}
Makefile
include $(TOPDIR)/rules.mk
PKG_NAME:=myapp
PKG_VERSION:=0.1
PKG_RELEASE:=1
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
define Package/myapp
SECTION:=utils
CATEGORY:=Utilities
DEPENDS:=+libpcap
TITLE:=Intro to PCAP for OpenWrt
endef
define Package/myapp/description
Outputs device name
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
LDFLAGS=-lpcap
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Package/myapp/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/myapp $(1)/usr/bin/
$(INSTALL_DIR) $(1)/etc/init.d/
$(INSTALL_BIN) files/myapp.init $(1)/etc/init.d/myapp
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) files/myapp.config $(1)/etc/config/myapp
endef
$(eval $(call BuildPackage,myapp))
Constants and the like used in code are resolved during compilation and come from header files. So the pcap.h header file is found (apparently by default).
I would have expected DEPENDS:=+libpcap to handle the linking for you (I'm not sure why else it would be necessary, but ). (Is that the correct format for that line?)
You actually want LDLIBS not LDFLAGS for this (assuming you are using the built-in rules and variables). See 10.3 Implicit Variables for what they each mean.
Without knowing what the rest of that make framework is doing though I can't say whether either LDLIBS or LDFLAGS will actually work though. That framework might have its own variable for this.
I figured out how to compile native C code for OpenWrt (runnin on a mips processor inside of a TP-LINK router) that depends on other libs (also in C) and generate .ipk s for both (the library and the executable) via a single makecommand. The library itself needed to be fetched from
I documented the efforts on my blog here
Basically there are three Makefiles involved - one for the library which tells the build system where to get the tarball from. The other two would be for your native C code. Consider my case for example: I want compile my code (mfm383c) that makes uses of a library (libmodbus):
/package/libmodbus/Makefile - this specifies URL from where to get the tar ball of the sources and the system will fetch the sources and compile it for you. It also tells the system where to place the .so file when the .ipk is installed on the OpenWrt target
/package/mfm383c/src/Makefile - this Makefile take care of telling the build system how to compile the .c and .h and also passes the dependency flag to the linker (-lmodbus)
/package/mfm383c/Makefile - This Makefile is the most important of the three - it tells the build system to build the libmodbus library before building mfm383c to ensure that the dependencies are met. We also need to make sure that the modbus.h file included in mfm383c.c can be found in the right place. The most notable section of this file being the following line at the end:
$(eval $(call BuildPackage,mfm383c,+libmodbus))
and the part about the code being dependent on another package in the define section:
DEPENDS:=+libmodbus
All three makefile are posted on my blog - they were too big to post here

How do I correctly link in static libraries with g++?

I have a rather complex build I'm trying to do, but I'll simplify it a little bit for this question. I have three c++ files (main.cpp file2.cpp and file3.cpp) that I am trying to compile and link against 3 static libs (libx.a liby.z libz.a) to produce an executable.
There are many dependencies involved.
All three c files are dependent on all 3 libs. libx is dependent on liby and libz. And finally, libx is also dependent on several callback functions contained in file2.cpp.
What command line would build this correctly? I have tried dozens of variations and nothing has satisfied the linker yet.
If it matters, the libs are pure c code compiled with gcc. Sources are c++ and I'm compiling/linking with g++. I have this working correctly as a visual studio project, and am trying to port to linux.
From your post:
g++ main.cpp file2.cpp file3.cpp -lx -ly -lz
However, if static linking is causing you problems, or you need to distribute any of the libs, then you may consider making them shared objects (.so files, commonly called DSOs). In that case, when you build libx.a, for example, compile all the sources to object files, and then combine them with
g++ -shared *.o -o libx.so -ly -lz
(this version assumes that liby.a and libz.a are stills static, and will be combined into libx.so
You may need to use extern "C" { } in your .cpp files to include the header for the C libs.
See Including C Headers in C++ in How To Mix C and C++.

How to make 64 shared 64-bit linux compatible library (*.so), for C++ code

My requirement is to work on some interface .h files. Right now I have .h and .cpp/.cc files in my project.
I need to compile it into shared 64-bit linux compatible library (*.so), using NetBeans/ Eclipse on Linux Fedora.
Since the GCC C++ ABI conventions did slightly change (in particular because of C++ standard libraries evolution, or name mangling convention) from one GCC version to the next (e.g. from g++-4.4 to g++-4.6) your shared library may be dependent upon the version of g++ used to build it
(In practice, the changes are often small inside g++, so you might be non affected)
If you want a symbol to be publicly accessible with dlsym you should preferably declare it extern "C" in your header files (otherwise you should mangle its name).
Regarding how to make a shared library, read documentation like Program Library Howto.
See also this question
And I suggest building your shared libraries with ordinary command-line tools (eg Makefile-s). Don't depend upon a complex IDE like NetBeans/ Eclipse to build them (they are invoking command-line utilities anyway).
If you are compiling a library from the 3 C++ source files called a.cc, b.cc, and c.cc respectively;
g++ -fpic -Wall -c a.cc
g++ -fpic -Wall -c b.cc
g++ -fpic -Wall -c c.cc
g++ -shared -Wl,-soname,libmylib.so.0 -o libmylib.so.0.0.0 a.o b.o c.o
Then you install the library using ldconfig, see man 8 ldconfig
you can then compile the program that uses the libary as follows (but be sure to prefix extern "C" before the class declarations in the header files included in the source code using the library.)
g++ -o myprog main.cc -lmylib
I have tried these compile options with my own sample code, and have been successful.
Basically What is covered in Shared Libraries applies to C++, just replace gcc with g++.
The theory behind all of this is;
Libraries are loaded dynamically when the program is first loaded, as can be confirmed by doing a system call trace on a running program, e.g. strace -o trace.txt ls which will dump a list of the system calls that the program made during execution into a file called trace.txt. At the top of the file you will see that the program (in this case ls) had indeed mmapped all the library's into memory.
Since libraries are loaded dynamically, it is unknown at link time where the library code will exist in the program's virtual address space during run time. Therefore library code must be compiled using position independent code - Hence the -fpic option which tells the translation stage to generate assembly code that has been coded with position independent code in mind. If you tell gcc/g++ to stop after the translation stage, with the -S (upper case S) option, and then look at resulting '.s' file, once with the -fpic option, and once without, you will see the difference (i.e. the dynamic code has #GOTPCREL and #PLT, at least on x86_64).
The linker, of course must be told to link all the ELF relocatatable object types into executable code suitable for use as a Linux shared library.