Build multiple versions of a binary with qmake - c++

I want to build two versions of my program, a "normal" version, and one in which the address sanitizer has been activated. As of now, I have this in my QSoas.pro
sanitizer {
message("Activating the address sanitizer code")
OBJECTS_DIR = build-snt
QMAKE_CXXFLAGS += -fno-omit-frame-pointer -fsanitize=address
LIBS += -fsanitize=address
TARGET = $$join(TARGET,,,-snt)
}
This way, I can do:
~ qmake
~ make
to get the normal version, and
~ qmake CONFIG+=sanitizer
~ make
to get the version with the address sanitizer.
This is fine, but a little cumbersome, especially since I need in fact many other configuration options on the qmake command-line. Is there a way to have two targets, so that I could simply run
~ qmake
~ make
~ make my-sanitized-exe

The most natural way, IMO, is an out-of-source build. That is, create a subdirectory called "sanitizer", go into it, and build your Makefile(s) the same way you do it with cmake, meson etc.:
mkdir sanitizer
cd sanitizer
qmake CONFIG+=sanitizer ../Qsoas.pro
QMake natively supports out-of-source builds, so everything should be fine. However, if you need to distiguish between the source and build directories, you can use the variables $$PWD and $$OUT_PWD.
See also qmake's manual for shadowed() function to translate the paths automatically.

This is my proposal on how you can achieve the desired behavior. The idea is using two (or more) different Makefiles that will tell the make tool what to do. To create a set of Makefiles I would do this (roughly):
~ qmake -o ./normal/Makefile
to create a normal version, and:
~ qmake CONFIG+=sanitizer -o ./sanitizer/Makefile
to create a Makefile for sanitizer.
Now, if I want to build a normal version I call:
~ make -f ./normal/Makefile
and
~ make -f ./sanitizer/Makefile
to build an alternative version.
Hopefully this will work.

Related

Makefile deferred compilation

I have a simple makefile with a variable for the compiler flags, it also contains some targets that modify that variable and append some flags.
My point with it is to be able to run, for example:
make debug perf
that would in turn add to the variable the flags required to build under that configuration. The problem is that if I run it, it does compile the executable with the debug info, and then tries to compile with the performance tools, and obviously does nothing. Can make only execute the compilation step after both targets run?
Makefile:
CFLAGS = -std=c11 -Wall -pedantic -D_GNU_SOURCE
executable: gcc $(CFLAGS) main.c -o exe
debug: CFLAGS += -g
debug: executable
perf: CFLAGS += -D__PERF__
perf: executable
Make version 4.2.1
One approach is to have different executable files for different flag combinations, ie
executable # default to release build
executable.dbg # with -g
executable.perf # with -D__PERF__
executable.dbgperf # with both
The two advantages are
you're never unsure how some executable file was built, and you never accidentally test the wrong thing / waste time trying to debug something with no debug symbols, etc.
Make's file dependency logic actually works correctly
This does assume you have a manageable number of flag combinations. If there are too many, the profusion of targets may make your Makefile impractical.
I exactly have the same requirements! :-) As this, I compile my executables with all the options in the filename like: myprog-debug-coverage and so on. All the object files goes to a directory like build-myprog-debug-coverage as example. All this has the advantage that there is no need to recompile all if you need it once for debug, do a change and compile for coverage and after next change for debug again.
The first thing you must do is to filter out all non-targets which are needed for the options like debug with:
debug:
#:
to simply do nothing.
In addition, you filter out the non-targets with something like:
export FOUND_ACTIONS=$(filter $(ACTIONS), $(MAKECMDGOALS))
and process these variables later on into the flags you need for compilation like:
$(eval $(call CHECK_FOR_CMDGOAL,debug,export LCXXFLAGS+= -DDEBUG -DGDB_HELPER -g,build_dir_ext=$(build_dir_ext)-debug))
and after that you can write your standard recipes with the found flags from the variables.
I can't give you a ready to use Makefile here as my one is a bit larger while processing a lot of flags like different compilers, memory debug libraries as efence, build for coverage and much more.
I'm in hope that you can catch the idea how to process the pseudo targets for flags and the real targets and how a Makefile can split both.
And yes, that is not how a Makefile works typically. But I believe it is really convenient at the end of the day. Giving manual CXXFLAGS and so on did not the job, as you as a user have a complete list of flags, libs and options on the comand line, which is a nightmare.
This makes no sense to me. Why would you want to compile file(s) as debug, generating a program executable that is built with debug, then in the same make command recompile the same file(s) with optimization, generating a program executable that is built with optimization.
In a single directory there can be only one file named executable, so how can you build the same file twice and have two different versions at the same time? How do you intend to run the debug executable versus the perf executable?
You either need to build different files, or you need to build them into different directories (one for debug and one for perf). I recommend the latter.
But to answer your specific question: it is not possible in make to build the same target multiple different times in the same invocation of make. Once a single make invocation tries to build a target named foo, it will never try to build that target again no matter how many other targets might list it as a prerequisite. If you re-run make again, it will try again to build foo (one time).

Qt Creator: technical differences between Release and Debug builds

A bunch of questions concerning the build process using QtCreator:
In QtCreator, you can differ between a Release, a Debug and a Profiler build. C. f. the following image:
What do these things exactly (!) do? I was not able to find and answer in the internet.
Especially, I am interested in whether the Debug mode adds the item "debug" to the qmake variable "CONFIG", the "-g" switch to ask g++ to add debugging information for gdb (my debugger) etc.
Which debugger is meant by "CONFIG += debug": the "normal" debugger GDB (in my case) or the QML Debugger?
Why is it so common to use "+=" in the project file and not "*="? The second variant does not add an item to the qmake Variable if it is already present. Does this mean that multiple equal items in the qmake special variables are harmless?
Many thanks in advance!
You can see what they do by observing the qmake command line that gets invoked in the "Compiler Output" window pane:
Release: qmake MyProject.pro "CONFIG+=qtquickcompiler"
Debug: qmake MyProject.pro "CONFIG+=debug" "CONFIG+=qml_debug"
Profile: qmake MyProject.pro "CONFIG+=qml_debug" "CONFIG+=qtquickcompiler" "CONFIG+=force_debug_info" "CONFIG+=separate_debug_info"
gdb has no -g option, did you mean gcc? The effect of CONFIG+=debug is to pass the -g option to gcc, as you can see from this line in Qt/mkspecs/common/gcc-base.conf:
QMAKE_CFLAGS_DEBUG += -g
Compiling a debug build just means your compiled libraries and executables will be unoptimised and contain extra information useful to debuggers. There is no requirement to execute in a specific debugger, or indeed any debugger at all. You could also run a release build in a debugger, although you might find the results less reliable.
Multiple equal items in qmake special variables are usually harmless, and in the case of CONFIG they can even be meaningful. For example, it is legal for CONFIG to contain both debug and release. In this case, the last one in the list will take effect. Consider the difference between += and *= in the following examples:
CONFIG = debug
CONFIG += release
CONFIG += debug # now CONFIG = debug release debug, so debug is the effective mode
CONFIG = debug
CONFIG += release
CONFIG *= debug # now CONFIG = debug release, so release is the effective mode
There is another reason why *= might not be favoured on the command line: many shells will treat any argument containing * as a file glob/wildcard to be expanded unless it is escaped or quoted.

How to bundle libstdc++.so.* correctly?

How to correctly locate libstdc++.so.* used to compile an autotools project, in order to bundle it with the distribution?
After our team switched to C++11, we need to bundle the new libstdc++.so.6 with every distribution of our software, but how to correctly find the library?
Cygwin: /lib/gcc/x86_64-pc-cygwin/5.2.0
Linux: /usr/lib64
Custom install: /usr/local/gcc-5.2.0/lib64
I already tried:
install-exec-local:
cp $(shell dirname $(shell which ${CXX}))/../lib64/libstdc++.so.6 ${prefix}/lib
(instead of make dist, we make install into a configured prefix and then bundle the prefix)
And this works, but not for Cygwin, and I'm not sure it will work on other platforms, thus my question.
Edit
See this question for a rationale of bundling libstdc++.so with the software. It works very well. We also use dlopen to load .sos that depend on libstdc++.so so it's harder to link statically than it sounds.
The only issue is locating the libstdc++.so.6 at make dist time (or our equivalent thereof), so that I can cp it to our distribution's ${prefix}/lib directory, before tar-gzipping it and delivering it to the customer. Ideally, I'm looking for something like g++ --print-path-to-libstdc++.so.
The target system, where the software is run, has an older libstdc++.so, that's the whole reason for bundling our own.
g++ -print-file-name=libstdc++.so
Why don't you just link with the -static-libstdc++ option (and -static-libgcc too if you need it)? Then you don't have to worry about bundling, library search paths, etc.
Such a simple thing, but so hard to do.
On Cygwin/MSys, it looks like g++ -print-file-name= only echoes the same file name you provide to it, without adding path.
Instead of focusing on CXX, I tried ldd BINFILE. And that does work on both Linux and Cygwin/MSys, providing full path. But on the latter - only if the binary is 64-bit; for 32-bit, it only shows paths to wow64*.dll.
The only solution which worked for all binaries on both Linux and Windows was:
objdump -p BINFILE | sed -n 's/\s*\(DLL Name:\|NEEDED\)\s*\(.*\)$/\2/p'
But - this gives only file names, without paths. Plus, complex sed query does not provide the best maintainability.
So I think the best solution is to hard-code file names for each OS, and use CXX location as the base for path - like the OP proposed.
Here is a Makefile.am snippet for copying all libraries, but only on Windows (within configure.ac, AM_CONDITIONAL([TARGET_WINDOWS],... needs to be set).
if TARGET_WINDOWS
install-exec-hook:
mkdir -p "$(DESTDIR)${prefix}/lib"
$(eval lib_SHARED_INSTALL := $(shell objdump -p BINFILE$(EXEEXT) | sed -n 's/\s*\(DLL Name:\|NEEDED\)\s*\(.*\)$$/\2/p' | xargs -I {} find $(shell dirname $(shell which ${CXX})) -name '{}'))
cp $(lib_SHARED_INSTALL) $(DESTDIR)${prefix}/lib
endif

qmake assigning variables in command line

I am having trouble understanding how assignments in the command line work.
when I run:
qmake-qt4 -project -o project.pro
qmake-qt4 -o qMakeFile "CFLAGS += -std=c++11"
make -f qMakeFile
and after the qMakeFile is make, CFLAGS is unchanged.
I'm sure it's something obvious I am missing.
You have a couple of issues in here:
You are trying to set a C++ option for the CFLAGS variable as opposed to CXXFLAGS.
if I were, I would pass the "CFLAGS+=-std=c++11" to the first qmake run when the project file is created because the variable will be put into the generated qmake file, then, rather than just into the Makefile with your current approach.
This would useful in the sense that when you re-run qmake for some reason, you do not need to pass the CFLAGS explicitly all the time to make sure it will be in your Makefile.
Furthermore, you should consider using the QMAKE_CXX_FLAGS variable instead of raw CXXFLAGS in a qmake project file.
Even furthermore, qmake has better support for c++11 through the CONFIG1 variable.
Another thing is that I would personally remove the needless extra spaces around the appending assignment. If you check out, this generates needless extra spaces in the Makefile, which then need to be escaped and so on.
Also, I am not sure why you need to generate custom Makefile name.
I would personally just write something like this:
qmake -project "QMAKE_CXXFLAGS+=-std=c++11" # only executed once
or this is even more recommended:
qmake -project "CONFIG+=c++11" # only executed once
qmake && make
Please make sure you have a recent enough compiler version that supports this option and C++11 in general. Sometimes, people fall into the trap that they do not notice they would be using an old version that did not support it for the time.

How to Use CCache with CMake?

I would like to do the following: If CCache is present in PATH, use "ccache g++" for compilation, else use g++. I tried writing a small my-cmake script containing
CC="ccache gcc" CXX="ccache g++" cmake $*
but it does not seem to work (running make still does not use ccache; I checked this using CMAKE_VERBOSE_MAKEFILE on).
Update:
As per this link I tried changing my script to
cmake -D CMAKE_CXX_COMPILER="ccache" -D CMAKE_CXX_COMPILER_ARG1="g++" -D CMAKE_C_COMPILER="ccache" -D CMAKE_C_COMPILER_ARG1="gcc" $*
but cmake bails out complaining that a test failed on using the compiler ccache (which can be expected).
As of CMAKE 3.4 you can do:
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
It is now possible to specify ccache as a launcher for compile commands and link commands (since cmake 2.8.0). That works for Makefile and Ninja generator. To do this, just set the following properties :
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) # Less useful to do it for linking, see edit2
endif(CCACHE_FOUND)
It is also possible to set these properties only for specific directories or targets.
For Ninja, this is possible since version 3.4.
For XCode, Craig Scott gives a workaround in his answer.
Edit : Thanks to uprego and Lekensteyn's comment, I edited the answer to check if ccache is available before using it as launcher and for which generators is it possible to use a compile launcher.
Edit2: #Emilio Cobos recommended to avoid doing that for the linking part as ccache doesn't improve linking speed and can mess with other types of cache like sccache
I personally have /usr/lib/ccache in my $PATH. This directory contains loads of symlinks for every possible name the compiler could be called from (like gcc and gcc-4.3), all pointing to ccache.
And I didn't even create the symlinks. That directory comes pre-filled when I install ccache on Debian.
From CMake 3.1, it is possible to use ccache with the Xcode generator and Ninja is supported from CMake 3.4 onwards. Ninja will honour RULE_LAUNCH_COMPILE just like the Unix Makefiles generator (so #Babcool's answer gets you there for Ninja too), but getting ccache working for the Xcode generator takes a little more work. The following article explains the method in detail, focussing on a general implementation which works for all three CMake generators and making no assumptions about setting up ccache symlinks or the underlying compiler used (it still lets CMake decide the compiler):
https://crascit.com/2016/04/09/using-ccache-with-cmake/
The general gist of the article is as follows. The start of your CMakeLists.txt file should be set up something like this:
cmake_minimum_required(VERSION 2.8)
find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM)
# Support Unix Makefiles and Ninja
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
endif()
project(SomeProject)
get_property(RULE_LAUNCH_COMPILE GLOBAL PROPERTY RULE_LAUNCH_COMPILE)
if(RULE_LAUNCH_COMPILE AND CMAKE_GENERATOR STREQUAL "Xcode")
# Set up wrapper scripts
configure_file(launch-c.in launch-c)
configure_file(launch-cxx.in launch-cxx)
execute_process(COMMAND chmod a+rx
"${CMAKE_BINARY_DIR}/launch-c"
"${CMAKE_BINARY_DIR}/launch-cxx")
# Set Xcode project attributes to route compilation through our scripts
set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_CXX "${CMAKE_BINARY_DIR}/launch-cxx")
set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_BINARY_DIR}/launch-cxx")
endif()
The two script template files launch-c.in and launch-cxx.in look like this (they should be in the same directory as the CMakeLists.txt file):
launch-c.in:
#!/bin/sh
export CCACHE_CPP2=true
exec "${RULE_LAUNCH_COMPILE}" "${CMAKE_C_COMPILER}" "$#"
launch-cxx.in:
#!/bin/sh
export CCACHE_CPP2=true
exec "${RULE_LAUNCH_COMPILE}" "${CMAKE_CXX_COMPILER}" "$#"
The above uses RULE_LAUNCH_COMPILE alone for Unix Makefiles and Ninja, but for the Xcode generator it relies on help from CMake's CMAKE_XCODE_ATTRIBUTE_... variables support. The setting of the CC and CXX user-defined Xcode attributes to control the compiler command and LD and LDPLUSPLUS for the linker command is not, as far as I can tell, a documented feature of Xcode projects, but it does seem to work. If anyone can confirm it is officially supported by Apple, I'll update the linked article and this answer accordingly.
I didn't like to set a symlink from g++ to ccache. And CXX="ccache g++" didn't work for me as some cmake test case wanted to have just the compiler program without attributes.
So I used a small bash script instead:
#!/bin/bash
ccache g++ "$#"
and saved it as an executable in /usr/bin/ccache-g++.
Then C configured cmake to use /usr/bin/ccache-g++ as C++ compiler.
This way it passes the cmake test cases and I feel more comfortable than having symlinks that I might forget about in 2 or 3 weeks and then maybe wonder if something doesn't work...
I verified the following works (source: this link):
CC="gcc" CXX="g++" cmake -D CMAKE_CXX_COMPILER="ccache" -D CMAKE_CXX_COMPILER_ARG1="g++" -D CMAKE_C_COMPILER="ccache" -D CMAKE_C_COMPILER_ARG1="gcc" $*
Update: I later realized that even this does not work. Strangely it works every alternate time (the other times cmake complains).
Let me add one important item that was not mentioned here before.
While bootstrapping a minimalistic build system from the ubuntu:18.04 docker image, I've found that order of installation makes a difference.
In my case ccache worked fine when calling gcc, but failed to catch invocations of the same compiler by the other names: cc and c++.
To fully install ccache, you need to make sure all compilers are installed first, or add a call to update-ccache symlinks to be safe.
sudo /usr/sbin/update-ccache-symlinks
export PATH="/usr/lib/ccache/:$PATH"```
... and then (due to updated symlinks) also calls to cc and c++ get caught!
In my opinion the best way is to symlink gcc,g++ to ccache, but if you would like to use within cmake, try this:
export CC="ccache gcc" CXX="ccache g++" cmake ...
Here are 2 methods I think are clean/robust, and also don't pollute your CMake code.
1.) Set environment variables
This method is nice since you don't have to individually set it up for each CMake project. The con is you may not want ccache for each CMake project.
# Requires CMake 3.17 (https://cmake.org/cmake/help/latest/envvar/CMAKE_LANG_COMPILER_LAUNCHER.html)
export CMAKE_CXX_COMPILER_LAUNCHER=/usr/bin/ccache
export CMAKE_C_COMPILER_LAUNCHER=/usr/bin/ccache
2.) Pass in cache variables during project configuration
Con a bit annoying to do for each project. This can be negated by your IDE though.
# Requires CMake 3.4
$ cmake ... -D CMAKE_CXX_COMPILER_LAUNCHER=/usr/bin/ccache \
-D CMAKE_C_COMPILER_LAUNCHER=/usr/bin/ccache
NOTE: It isn't really necessary to specify the full path.
If ccache is in your path you can just specify ccache instead.
export CMAKE_CXX_COMPILER_LAUNCHER=ccache
export CMAKE_C_COMPILER_LAUNCHER=ccache
It is extending #Nicolas answer.
Add following line to your cmake file:
list(PREPEND CMAKE_PROGRAM_PATH /usr/lib/ccache)
Or add it as argument to cmake configuration step:
cmake -DCMAKE_PROGRAM_PATH=/usr/lib/ccache