Version Numbers in a project with Qt - qt

Version numbers are needed all over a project; in installers, code, toolchains etc. I despise duplication. I want my version numbers to be stored in one central authoritative location.
I am working with C/C++ and using Qt on various platforms. In Qt, qmake projects specify version numbers like:
VERSION = 1.2.3
In code I use something like in a header like Version.h:
#define VERSION_MAJ 1
#define VERSION_MIN 2
#define VERSION_REV 3
#define VERSION_STRING \"VERSION_MAJ\" "." \"VERSION_MIN\" "." \"VERSION_REV\"
My installer toolchain has support for C preprocessing so I can use the same version specified in Version.h. However, I don't know how to get qmake to use the same version number. I thought I could preprocess the pro file, but that won't work as # characters mean a comment in pro files and the C preprocessor will fall over.
Anyone know of a good way to keep my version number centralised?

I use something like this in my build system
#.pro file
#Application version
VERSION_MAJOR = 1
VERSION_MINOR = 0
VERSION_BUILD = 0
DEFINES += "VERSION_MAJOR=$$VERSION_MAJOR"\
"VERSION_MINOR=$$VERSION_MINOR"\
"VERSION_BUILD=$$VERSION_BUILD"
#Target version
VERSION = $${VERSION_MAJOR}.$${VERSION_MINOR}.$${VERSION_BUILD}
And after that you can use VERSION_MAJOR and others as normal macro in your application.

If you want to be able to store your version numbers in a c header file, you can do so and then import them into the Qt project variables in the project file. Something like the below should work:
Version.h:
#define MY_MAJOR_VERSION 3
#define MY_MINOR_VERSION 1
.pro
HEADERS += Version.h
VERSION_MAJOR = MY_MAJOR_VERSION
VERSION_MINOR = MY_MINOR_VERSION
The advantage of doing it this way round is that you can then use your authoritative header file if you need to compile other parts of the project away from Qt.

Related

Call Rmath via Ctypes from Ocaml on OS X

I want to use R's mathematical functions as provided in libRmath from Ocaml. I successfully installed the library via brew tap homebrew science && brew install --with-librmath-only r. I end up with a .dylib in /usr/local/lib and a .h in /usr/local/include. Following the Ocaml ctypes tutorial, i do this in utop
#require "ctypes.foreign";;
open Ctypes;;
open Foreign;;
let test_pow = foreign "pow_di" (float #-> int #-> returning float);;
this complains that it can't find the symbol. What am I doing wrong? Do I need to open the dynamic library first? Set some environment variables? After googling, I also did this:
nm -gU /usr/local/lib/libRmath.dylib
which gives a bunch of symbols all with a leading underscore including 00000000000013ff T _R_pow_di. In the header file, pow_di is defined via some #define directive from _R_pow_di. I did try variations of the name like "R_pow_di" etc.
Edit: I tried compiling a simple C program using Rmath using Xcode. After setting the include path manually to include /usr/local/include, Xcode can find the header file Rmath.h. However, inside the header file, there is an include of R_ext/Boolean.h which does not seem to exist. This error is flagged by Xcode and compilation stops.
Noob alert: this may be totally obvious to a C programmer...
In order to use external library you still need to link. There're at least two different ways, either link using compiler, or link even more dynamically using dlopen.
For the first method use the following command (as an initial approximation):
ocamlbuild -pkg ctypes.foreign -lflags -cclib,-lRmath yourapp.native
under premise that your code is put into yourapp.ml file.
The second method is to use ctypes interface to dlopen to open the library. Using the correct types and name for the C function call, this goes like this:
let library = Dl.dlopen ~filename:"libRmath.dylib" ~flags:[]
let test_pow = foreign ~from:library "R_pow_di" (double #-> int #-> returning double)

Replace function $$find always returns nothing

I have a QT project file (.pro), and would like to add some compiler specific flags.
Rather than typing out if win32-msvc2013|win32-msvc2010|... for every version of MSVC, I thought I could just search for the substring "msvc".
I did some research and found the find function, which seems perfect for the job.
To test this, I added message($$find($$QMAKESPEC, "*msvc*")) to the project file. However, it always prints blank, regardless of whether or not the $$QMAKESPEC variable contains the substring "msvc". I've also tried message($$find($$QMAKESPEC, "msvc")), message($$find($$QMAKESPEC, msvc)) and message($$find($$QMAKESPEC, *msvc*)).
I checked the value of $$QMAKESPEC with message($$QMAKESPEC), and it printed E:/Qt/5.4/msvc2013_64/mkspecs/win32-msvc2013.
How can I use the find function to check for a substring in a variable in a QT project file?
Update
Frank Osterfeld suggested using msvc { ... } in the comments, which works great! However I feel this question is still useful as $$find still isn't working as expected.
Version Info
Qt Creator 3.3.2 (opensource)
Based on Qt 5.4.1 (MSVC 2010, 32 bit)
Built on Mar 4 2015 at 00:09:05
From revision 3af3fe7ad3
There are qmake methods that take a string and there are methods that take a variable.
Replace $$find($$QMAKESPEC, "msvc") by $$find(QMAKESPEC, "msvc").
Testme
message("Test me")
message($$QMAKESPEC)
# MSVC
message($$find($$QMAKESPEC, "msvc"))
message($$find(QMAKESPEC, "msvc"))
# linux
message($$find($$QMAKESPEC, "linux"))
message($$find(QMAKESPEC, "linux"))
# g++ does not work because it is a regular expression
message($$find($$QMAKESPEC, "g++"))
message($$find(QMAKESPEC, "g++"))
# g\+\+ does work
message($$find($$QMAKESPEC, "g\+\+"))
message($$find(QMAKESPEC, "g\+\+"))

QtCreator: kit-specific precompiler macro definitions

I am using QtCreator 3.1.1 to build a cross-platform project, and so I arranged to have different compilation kits for targeting my desktop PC and my BeagleBoneBlack (BBB).
Now I would like to define some macro in qmake project file (.pro) which are specific only for a given kit.
In other words I would like do in my .pro file something like:
if(kit == BBB)
DEFINES += MY_BBB_MACRO
elseif(kit == Desktop)
DEFINES += MY_DESKTOP_MACRO
else
DEFINES += OTHER_MACRO
Is is possible? How can I do that?
I obtained some help on Qt forum (take a look here) about this problem...
Anyway the solution consists in using qmake built-in test functions.
Basically I've added some CONFIG directive in QtCreator's project management: in the following screenshot you can see for example you can see that I've added CONFIG+=BBB in the project configuration for BBB kit; in the same way I've added CONFIG+=AM335x and CONFIG+=Desktop to AM335x and Desktop kits, respectively...
Then, in my .pro file I've added something like:
and now in my source code I can use something like #ifdef PLATFORM_BBB, #ifdef PLATFORM_AM335X and #ifdef PLATFORM_DESKTOP for differentiating the program behavior depending on compilation kit.
I found another solution.
First, add additional arguments in Projects using CONFIG+=Variable name for kit.
And in .pro file, write some code like below.
Desktop {
message("Desktop is selected")
}
RPI {
message("rpi is selected")
target.path = /home/pi
INSTALLS += target
}
If you look at the general message tab, you can see that the setting works well.

Compiling QtOpenCL with QT5

Anyone managed to compile library QtOpenCL using Qt5 (possibly under Window)?
edit: I managed to compile the code by porting it to QT5. I leave here in the question the dirty parts that I would like to replace in my method and describe what I did in the answer.
I was not able to provide the include path to my opencl installation so I
manually modified src/opencl/opencl.pro by adding the line
INCLUDEPATH += " *[absolute path to the openCL include folder]* "
QMAKE_LIBDIR_OPENCL = "*[absolute path to the opencl lib folder]*"
manually modified src/openclgl/openclgl.pro by adding the line
INCPATH += " *[absolute path to the openCL include folder]* "
QMAKE_LIBDIR_OPENCL = "*[absolute path to the opencl lib folder]*"
Anyone knows how to fix this in a cleaner way?
Here are the changes I had to introduce:
Modify the .pro files in order to add the OpenCL library. This is still an open problem for me. How to fix this in a cleaner way?
Link the projects (both opencl.pro and openclgl.pro) to the additional required Qt module QtConcurrent:
QT += concurrent
Fix the #include style by removing the packages, e.g. #include <qtconcurrentrun.h> instead of the old #include
<QtCore/qtconcurrentrun.h>
Fix qclvector.cpp by replacing qMalloc, qfree, qMemCopy with, respectively, std::malloc, std::free, std::memcpy
Moreover modify the initialization of ref in the constructor from ref = 1 to ref.store(1);
Removing all the macros QT_LICENSED_MODULE
This is enough to compile at least QtOpenCL and QtOpenCLGL using QT5

Qt auto software version?

Does Qt maintain any sort of versioning information about your program like .NET does? Like the build number? Or does it provide an easy way to access the SVN revision?
No.
But if you're using qmake then you can set compiler flags in the build system based on the results of arbitrary commands, which might be usable to do what you want.
For example, if you were using git, you could do something like this in your .pro file:
REVISION = $$system(git rev-parse HEAD)
DEFINES += APP_REVISION=$$REVISION
That would give you an APP_REVISION macro when compiling your program, which you could use like this:
// stringize macro
#define _STR(X) #X
#define STR(X) _STR(X)
QTextStream(cout) << "MyApp revision " STR(APP_REVISION) << endl;

Resources