Custom compilation flag to enable specific feature - c++

I have a Qt project which requires a library (gphoto2) to enable some features that are not essential. I'd like to add some sort of configuration option to my qmake or make call to enable features using this library, so I can compile without it being installed.
What is the best way to configure something like this?
I guess I need some way to add a define based on a compiler parameter, which I can query in my code using #ifdef ...

I assume you use make (without qmake). It is reasonable and quite easy to use GNU make (alone) on Qt projects. You could use some other build automation tool like ninja.
Then you could decide to enable that Gphoto feature by compiling your code with -DWITH_GPHOTO and using #if WITH_GPHOTO in your C++ code.
You would compile by adding
CXXFLAGS+= -DWITH_GPHOTO
in your Makefile
I won't call that a "custom compiler flag" (e.g. like GCC plugins can provide) but a preprocessor flag. It is pretty standard practice.
Maybe you also want to pass such flags to moc. Then your Makefile is running moc thru some rule and command, which you could tailor too.
BTW, you might consider GNU autoconf or some other Makefile generator like cmake. I don't think you should spend too much time on these...
PS. I don't know how that idea translates into qmake and leave you to find out.

Assuming, you are using qmake, you can add a preprocessor definition depending on the existence of a file or an environment variable.
You could add a qmake project for compiling your external library and place it relative to your own project by default.
LIBGPHOTO2_PATH = $$getenv(LIBGPHOTO2PATH)
isEmpty(LIBGPHOTO2_PATH): LIBGPHOTO2_PATH = ../../libgphoto2
exists($$LIBGPHOTO2_PATH/libgphoto2.pri): include($$LIBGPHOTO2_PATH/libgphoto2.pri)
In libgphoto2.pri you add a preprocessor definition to indicate the presence of libgphoto2, add include and linker paths etc.:
DEFINES += WITH_LIBGPHOTO2
In the code of your dependent project, you check for the presence using #ifdef.
Instead of creating a qmake-project to compile, you could also check for the presence of the compiled library at a given path and set values directly (I don't know how libgphoto compiles, so I assume a default directory structure with include/, lib/ etc):
LIBGPHOTO2_PATH=$$getenv(LIBGPHOTO2PATH)
isEmpty(LIBGPHOTO2_PATH): LIBGPHOTO2_PATH = ../../libgphoto2
exists($$LIBGPHOTO2_PATH/include) {
DEFINES += WITH_LIBGPHOTO2
INCLUDEPATH += $$LIBGPHOTO2_PATH/include
LIBS += -L$$LIBGPHOTO2_PATH/lib -lgphoto2
}
You should however consider to move to something more modern like qbs, which is a lot faster, more flexible and easier to read.

Related

Including libsimdpp in a CMake project

I decided to use libsimdpp for vectorization of my C++ code. Problem is, there is next to no documentation on how to get started.
Í assumed inclusion would be simple given that it's also CMake based like the project I'm doing, so I just tried to copy over the directory and set the include path. Well, turns out this is not enough: You need to define the appropriate flags to specify which SIMD flavor you want to compile for. libsimdpp includes a CMake macro just for that and it works wonders. I'm not sure however how to get going from here and it feels like I'm working against CMake rather than with it by copying things around and deleting stuff.
Would anyone with a firm understanding of CMake set out to explain what to do in a step-by-step fashion? Thanks!
You should check out the simdpp/test/CMakeLists.txt file where the tests of libsimdpp are compiled. The relevant parts are these:
foreach(SRC ${TEST1_ARCH_SOURCES})
simdpp_multiarch(TEST1_ARCH_GEN_SOURCES ${SRC} ${COMPILABLE_ARCHS})
endforeach()
add_executable(test1 EXCLUDE_FROM_ALL
${TEST1_SOURCES}
${TEST1_ARCH_GEN_SOURCES}
)
Basically, TEST1_ARCH_SOURCES contains the code that uses libsimdpp. simdpp_multiarch copies the sources around and sets appropriate compile flags for them, so that implementations for e.g. SSE2 and AVX2 can be linked into the same executable. Then these generated sources (TEST1_ARCH_GEN_SOURCES) are added into the executable.

Correct installation of config.h for shared library using autotools

I am converting a C++ program which uses the autotools build system to use a shared library, introducing the use of libtool. Most of the program functionality is being placed in the shared library, which is loaded by the main program, so that the common code can be accessed by other programs in future.
Throughout the program and library sources the autoheader generated config.h is used with the usual macro:
#if HAVE_CONFIG_H
# include <config.h>
#endif
In configure.ac I use the macro to generate it:
AC_CONFIG_HEADERS([config.h])
My question is, do I need to install config.h for others to be able to use my library, and if so, what is the appropriate way to do it, and should it be renamed to avoid conflicts etc?
The most information I have found on this is here:
http://www.openismus.com/documents/linux/building_libraries/building_libraries#installingheaders
But this is hardly an official source.
Never ever install autoheader's config.h.
The last thing the users of your library need is interference from the macros leaking out of your config.h. Your library may have HAVE_FOOBAR, but my software might be compiled in a way that foobar is disabled, so that HAVE_FOOBAR will break my compilation.
The AX_PREFIX_CONFIG macro from the archive is a workaround, where everything gets prefixed.
A better approach is to create a template file (e.g. blargconfig.h.in) with lines like:
typedef #BLARG_TYPE# blarg_int_t;
#BLARG_RANDOM_INCLUDE#
And then AC_SUBST() those variables in configure.ac:
AC_SUBST(BLARG_TYPE, ["unsigned short"])
AC_SUBST(BLARG_RANDOM_INCLUDE, ["#include <somerandomheader.h>"])
Then list it as an output file:
AC_CONFIG_FILES([Makefile
src/Makefile
...
include/blargconfig.h])
The .h file should be listed with nodist_include_HEADERS; the .h.in file will be automatically distributed because it's listed in AC_CONFIG_FILES.
Destination for such files is commonly $libdir/packagename/include. See GLib for example, although they generate glibconfig.h without a template (by writing the whole creation code inline in configure.ac, as the autobook suggests). I find this approach less maintainable than using AC_SUBST, but it's more flexible.
Of course, to help the compiler find the platform-dependent header you'll probably also want to write a pkgconfig script, like GLib does.
You will need to install config.h if it affects the interface. In practical terms, if the #define's are required by the header(s), not just the .cc implementation / compilation units.
If config.h is a problem, you can specify another name in the AC_CONFIG_HEADERS macro. e.g., AC_CONFIG_HEADERS([foo_config.h]).
The easiest way to install the header, assuming automake, is with:
nodist_include_HEADERS = foo_config.h
in the top-level Makefile.am. the nodist prefix tells automake that foo_config.h is generated rather than distributed with the package.
If not using automake, install foo_config.h in $includedir. $exec_prefix/include is arguably a more correct location for a generated header, but in practice the former location is fine.
I avoid using config.h, by passing relevant definitions in CPPFLAGS or foo_CPPFLAGS along with AC_SUBST to Makefile.am for source builds, or AC_SUBST to foo.h.in to generate headers at configure-time. A lot of config.h is test-generated noise. It requires more infrastructure, but it's what I prefer. I wouldn't recommend this approach unless you're comfortable with the autotools.

Making library name part of include path in make?

Say I'm working on a library, foo. Within my libraries source files, I'd like to include headers the same way a user of my library would:
#include <foo/bar.hpp>
// code defining bar methods here
In boost for example, includes of other headers within boost are done that way, e.g. <boost/shared_ptr.hpp>, rather than the relative quoted "../shared_ptr.hpp" style. I looked at how some other libraries accomplish this and it appears they add a redundant directory to their file layout in order to do it, e.g. the boost code lives in "boost_1_4_1/boost" rather than just "boost_1_4_1/".
Switching to that scheme is annoying if you already have source control using an existing layout. What's the best way with GNU make to layer it on? My only thought is to add a target that all build targets depend on that makes a hidden folder with a symlink inside to my source tree, and add that hidden folder to the include path. Perhaps there's a less obfuscated way?
Couldn't you use -I gcc key of INC option for your Makefile?
gcc:
gcc -c -I/home/joseph/dev/foo/headers
Makefile:
INC=-I/home/joseph/dev/foo/headers
In this case you would have only one place to make this change, Makefile.

Using a class from another project in C++

I have access to a large C++ project, full of files and with a very complicated makefile courtesy of automake & friends
Here is an idea of the directory structure.
otherproject/
folder1/
some_headers.h
some_files.cpp
...
folderN/
more_headers.h
more_files.cpp
build/
lots_of things here
objs/
lots_of_stuff.o
an_executable_I_dont_need.exe
my_stuff/
my_program.cpp
I want to use a class from the big project, declared in say, "some_header.h"
/* my_program.cpp */
#include "some_header.h"
int main()
{
ThatClass x;
x.frobnicate();
}
I managed to compile my file by painstakingly passing lots of "-I" options to gcc so that it could find all the header files
g++ my_program.cpp -c -o myprog.o -I../other/folder1 ... -I../other/folderN
When it comes to compiling I have to manually include all his ".o"s, which is probably overkill
g++ -o my_executable myprog.o ../other/build/objs/*.o
However, not only do I have to do things like manually removing his "main.o" from the list, but this isn't even enough since I forgot to also link against all the libraries that he happened to use.
otherproject/build/objs/StreamBuffer.h:50: undefined reference to `gzread'
At this point I am starting to feel I am probably doing something very wrong. How should I proceed? What is the usual and what is the best approach this kind of issue?
I need this to work on Linux in case something platform-specific needs to be done.
Generally the project's .o files should come grouped together into a library (on Linux, .a file if it's a static library, or .so if it's a dynamic library), and you link to the library using the -L option to specify the location and the -l option to specify the library name.
For example, if the library file is at /path/to/big_project/libbig_project.a, you would add the options -L /path/to/big_project -l big_project to your gcc command line.
If the project doesn't have a library file that you can link to (e.g. it's not a library but an executable program and you just want some of the code used by the executable program), you might want to try asking the project's author to create such a library file (if he/she is familiar with "automake and friends" it shouldn't be too much trouble for him), or try doing so yourself.
EDIT Another suggestion: you said the project comes with a makefile. Try makeing it with the makefile, and see what its compiler command line looks like. Does it have many includes and individual object files as well?
Treating an application which was not developed as a library as if it was a library isn't likely to work. As an offhand example, omitting the main might wind up cutting out initialization code that the class you want depends upon.
The responsible thing to do here is to read the code, understand it, and turn the functionality you want into a proper library. Build the "exe you don't need" with debug symbols and set breakpoints in the constructors and methods of the class. Step into them so you get a grasp on the functionality and what parts of the program are relevant and irrelevant to your needs.
Hopefully the code is under some kind of version control system that supports branching (such as Git). If not, make your own repository that does. Edit the files until you've organized them into a library and code that uses the library. Make sure it works properly within the context of the original program. Then turn around and use this library in your own program.
If you've done a good job, you might be able to convince the original authors to accept the separation back into their original codebase. If not, at least version control has your back so you can manage integration of future changes.

Is it possible to specify specific flags/define for DLL/SO build?

How can I specify some unique flags for DLL only builds. By default libtool adds -DDLL_EXPORT which is fine for most projects that follow GNU conventions, but if I work, for example, with Boost I may need to specify for my library flags: -DDLL_EXPORT -DBOOST_ALL_DYN_LINK for DLL only builds, also sometimes I want conditional builds so I need some specific defines for DLL/SO build.
Unfortunately I can't find a way how to do this with libtool, what flags should I use?
P.S.: Don't even try to suggest to move to CMake.
Example:
I use library foo that links to bar and requires -DBAR_EXPORTS to get symbols for dynamic library only.
Is there something like
libfoo_la_dynamic_CXXFLAGS = -DBAR_EXPORTS
Anybody?
Alternative Solution: (quite ugly)
Create a file `defines.h
#if defined(PIC) || defined(DLL_EXPORT)
#define BAR_EXPORTS
#endif
And then:
libfoo_la_CXXFLAGS += -include defines.h
Ugly but should work.
You can disable building shared library by default with
LT_INIT([disable-shared])
then you can use AM_CONDITIONAL combined with --enabled-shared and set the extra definitions if shared library is explicitly requested. IOW, enable building static or shared, but not both at the same time.
Not that pretty, but could you use a conditional to check if DLL_EXPORT is defined and if it is define the others you need?
I'm not that good with autotools, I prefer CMake but you seem quite against that.