Getting git commit id on Qt qmake project at make time - c++

On Windows 10 Qt 5.15, I'm getting git commit id on Qt qmake project at qmake time with
COMMIT = '\\"$$system(git rev-parse --verify master)\\"'
DEFINES += COMMIT_VERSION=\"$${COMMIT}\"
And on main.cpp I can print that with qDebug() << COMMIT_VERSION;
Since some commits do not require a full project rebuild I'm getting old (not the latest) commit ids.
How can I get that updated on every build?

I use Ubuntu but for doing what you want I try this:
what you do is like in cmd or terminal always type this command :
git rev-parse --verify master
so for doing this I use QProcess like this :
first of all, I create one bash file and put that command there.
I always put commands in one shell script file because it's easy and just put.sh file in the start process.
test.sh
#!/bin/sh
cd /home/parisa/projectFolderName;git rev-parse --verify master
and this is code :
QProcess *myProcess = new QProcess();
myProcess->start("/home/parisa/untitled1/test.sh");
myProcess->waitForFinished(3);
QString str = myProcess->readAll();
qDebug() << "git id : " << str;
delete myProcess;
and this is the output :
In QTCreator short cut Alt + K or Alt +G will show you the git log.

Related

The command started in the QProcess does not return a response on linux

I'm tryin get loaction of node package. Using QProcess to execute commang which node:
QProcess process;
process.start("/usr/bin/which", QStringList() << tr("node"));
process.waitForFinished(-1);
response = process.readAllStandardOutput();
qDebug() << response;
But in debug I got "".
Project located on GitHub. Problem in https://github.com/Dissfall/nodeGator/blob/develop/mainwindow.cpp
It may depend under what shell is running your app in QtCreator and under what one in terminal (bash/sh/csh etc.). The PATH variable may differ;
u can check process.exitCode() i.e. when 'which' doesn't find tool, it return 1; otherwise 0
may be, try to list the env. with:
qDebug() << "env:" << QProcessEnvironment::systemEnvironment().toStringList();
You can see actual settings in QtCreator -> Projects -> ur KIT -> Run and "Run Environment" details. There is an option to set in which environment the app is running: build/system/clear - try change.

Include Git commit hash and/or branch name in C/C++ source

I would like to know how you can get a Git commit hash and/or other information into the contents of a C++ variable in the compiled binary without having it be part of the source that's tracked by Git.
I need to keep track of firmware release information in a compiled executable running on an embedded processor. Means to identify the particular release of the firmware binary such as meaningful filenames, MD5 checksums or even date/time stamps are not available in this closed environment (i.e., there is no filesystem).
One approach is to have the device's console output produce identifying text, such as 'Release 1.2.3', 'commit hash 1bc123...', or similar. The firmware release information is only of interest to maintenance personnel, so a trained operator could examine the console output. To implement this it could potentially involve manual editing of a version string, which is then compiled into the code and output to the console at program startup.
This is acceptable for major releases where a signoff workflow is used to double-check that the version information is correct. However, this being a manual process it is inherently unreliable. For example, what if the developer forgets to update the version information? - There is now a disconnect between the compiled code and its reported version string.
A workflow where the code is freshly compiled and downloaded each time the user wants to test the hardware is not practical in the situation in question, ie., it is quite onerous to update the firmware.
An automatic way of identifying the version of the code is thus required. In the situation in question, Git is used, and the developers regularly commit their work to feature branches. Displaying the Git commit hash, and perhaps also whether or not there are unstaged changes, would be a way of identifying the status of the source code used to compile the firmware.
The requirement is that I would like my application to have information available to it so that it is able to display:
"Git commit:[01abcdef...etc], branch: experimentalStuffDoNotRelease"
Thus, I would like to automatically include Git information, such as commit hash and branch, in the compiled C and/or C++ code.
The development environment has developers using both Windows and Linux, and uses Eclipse CDT with a relatively unsophisticated workflow of: check out; compile; download to the hardware.
I use a makefile, like so:
GIT_HASH=`git rev-parse HEAD`
COMPILE_TIME=`date -u +'%Y-%m-%d %H:%M:%S UTC'`
GIT_BRANCH=`git branch | grep "^\*" | sed 's/^..//'`
export VERSION_FLAGS=-DGIT_HASH="\"$(GIT_HASH)\"" -DCOMPILE_TIME="\"$(COMPILE_TIME)\"" -DGIT_BRANCH="\"$(GIT_BRANCH)\""
all:
g++ main.cpp $(VERSION_FLAGS)
When the makefile is run, the git hash and the time of compilation are both loaded into macros accessible within the source, like so:
#include <iostream>
int main(){
std::cerr<<"hash="<<GIT_HASH<<", time="<<COMPILE_TIME<<", branch="<<GIT_BRANCH<<std::endl;
}
Which gives output like:
hash=35f531bf1c959626e1b95f2d3e1a7d1e4c58e5ec, time=2017-05-18 04:17:25 UTC, branch=master
In Eclipse CDT, use a pre-build step to generate an include file containing the relevant information, and a conditional inclusion to check that the file was created:
Right-click the project
Select Properties
Expand the C/C++ Build
Select Settings In the Build Steps tab
Enter the following in the Command text box:
git log --pretty=format:'#define GIT_INFO_PRESENT%n static const char* GIT_INFO = "Version Information=[%H,%d]\r\n";' -n 1 > ../src/gitcommit.h
This will, upon build, create a file gitcommit.h that will be included in the source code. To customise it, adjust the string to your needs. (See https://git-scm.com/docs/pretty-formats)
As an example, I produce a debug output at the beginning of the main routine to inform the user of the commit and branch (not strictly needed knowing the commit, but certainly helpful):
Put this in the file, probably at the top
#if __has_include("gitcommit.h")
#include "gitcommit.h"
#else
static const char* GIT_INFO = "Git version information not present.\r\n";
#endif
To display the information somewhere in your code, do similar to this:
printf(GIT_INFO);
Note that I haven't, in this case, made the pre-build step a shell script or Windows/DOS .bat file, as I work often in Linux or Windows.
Note that this isn't tested in Windows.
In both cases, 'git' must be executable from the standard command line.
There is a dependency on provision of __has_include. This was intended to provide simplicity so that a default include file need not be provided.
Note that the gitcommit.h file's path should be discoverable by the compiler.
Usually as part of your build you run some command that generates something like that.
For example, git describe gives you something that you could use:
echo // auto generated version: > version.h
git describe > echo // auto generated version: > version.h
echo -e "#define VERSION " >> version.h
git describe >> version.h
For example x264 use this simple script to generate it:
if [ -d .git ] && command -v git >/dev/null 2>&1 ; then
localver="$(($(git rev-list HEAD | wc -l)))"
if [ "$localver" -gt 1 ] ; then
ver_diff="$(($(git rev-list origin/master..HEAD | wc -l)))"
ver="$((localver-ver_diff))"
echo "#define X264_REV $ver"
echo "#define X264_REV_DIFF $ver_diff"
if [ "$ver_diff" -ne 0 ] ; then
ver="$ver+$ver_diff"
fi
if git status | grep -q "modified:" ; then
ver="${ver}M"
fi
ver="$ver $(git rev-list -n 1 HEAD | cut -c 1-7)"
version=" r$ver"
fi
fi
echo "#define X264_VERSION \"$version\""
echo "#define X264_POINTVER \"0.$ver\""
This will generate something like:
#define X264_VERSION " r2708 86b7198"
#define X264_POINTVER "0.148.2708 86b7198"
Here's simple solution if you need git hash and local modifications flag only:
$ cat update-version-info.sh
#!/bin/sh
version=$(git describe --always --dirty --tags)
echo "#define GIT_VERSION \"$version\"" > git-version.h
$ cat 1.c
#include <stdlib.h>
#include <stdio.h>
#include "git-version.h"
int main() {
#ifdef GIT_VERSION
printf("%s\n", GIT_VERSION);
#endif
return 0;
}
$ ./1
ee4f307-dirty
Based on #Richard's answer and my fixes for qmake/Qt, here is the solution I use:
With Qt 5.14 the following lines in .pro file work for me:
GIT_HASH="\\\"$$system(git -C \""$$_PRO_FILE_PWD_"\" rev-parse --short HEAD)\\\""
GIT_BRANCH="\\\"$$system(git -C \""$$_PRO_FILE_PWD_"\" rev-parse --abbrev-ref HEAD)\\\""
BUILD_TIMESTAMP="\\\"$$system(date -u +\""%Y-%m-%dT%H:%M:%SUTC\"")\\\""
DEFINES += GIT_HASH=$$GIT_HASH GIT_BRANCH=$$GIT_BRANCH BUILD_TIMESTAMP=$$BUILD_TIMESTAMP
In your code you can check the revision like this:
int main(int argc, char *argv[])
{
QStringList args;
for (int i = 0; i < argc; i++)
args << QString(argv[i]);
if (args.contains("-v") || args.contains("--version")) {
std::cout << QString("branch: %1, version: %2, built_at: %3").arg(GIT_BRANCH).arg(GIT_HASH).arg(BUILD_TIMESTAMP).toUtf8().constData() << std::endl;
return 0;
}
// ...
}
A C file or a C++ file can be generated by some program (for example, some shell script on Linux, or some GNU awk script, or your C program running system or popen(3) running some git command).
You just configure your build automation tool (e.g. your Makefile if you use GNU make, or your build.ninja file if you use ninja) appropriately.
Both Bismon and RefPerSys are doing so and keep their git id inside the obtained executable (displaying it when invoked with --version). Note: both are projects I created.
PS a different question is how to configure your IDE to run a particular build automation tool. This is specific to your IDE. But Eclipse CDT FAQ offers an insight.

Check if adb is installed

In Qt, I'd like to check if the adb command in a cmd is working (--> installed). I already tried to work with system and process but, wasn't able to get any information about if adb could be ran.
The solution I can think of would be iterating over all directories in PATH environmental variable and checking whether the adb file exists there or not.
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
QStringList dirs = env.value("PATH").split(":");
foreach(QString p, dirs){
QFileInfo check_file(p + "/" + "adb");
if (check_file.exists() && check_file.isFile()) {
qDebug() << "Yes!";
}
}
By the way, I tested in on my linux machine and worked fine.
Windows
On Windows machines you would need to replace adb with adb.exe and : with ;.

How to launch terminal in a specific folder?

I've tried both launching /Applications/Utilities/Terminal.app/Contents/MacOS/Terminal as a process and using std::system to launch it from sh script (open -a /Applications/Utilities/Terminal.app/Contents/MacOS/Terminal) with different arguments (detsdir as argument, cd destdir etc.). Nothing works. It either opens in ~/, or it says "destdir is a directory` and logs off.
I've also tried launching it as a process with destdir set as working directory (using QProcess::startDetached). No luck either, it opens in ~/.
You can do it like this, with osascript:
osascript -e "tell application \"Terminal\" to do script \"cd ~/Desktop\""
This will create a new terminal window with working directory ~/Desktop.
QProcess has method setWorkingDirectory()

Qt - Compilation Error: Couldn't change working directory

I am trying to compile oxideqt, a QML API for Chromium Embedded Framework (CEF), but I am experiencing an error:
11:13:58: Running steps for project oxideqt...
11:13:58: Configuration unchanged, skipping qmake step.
11:13:58: Starting: "C:\Qt\Qt5.1.1\Tools\QtCreator\bin\jom.exe"
cd qt\lib\ && ( if not exist Makefile C:\Qt\Qt5.1.1\5.1.1\msvc2010\bin\qmake.exe C:\Users\simon\Documents\oxide\qt\lib\lib.pro -spec win32-msvc2010 -o Makefile ) && C:\Qt\Qt5.1.1\Tools\QtCreator\bin\jom.exe -f Makefile
C:\Qt\Qt5.1.1\Tools\QtCreator\bin\jom.exe -f Makefile.Release
cd C:/Users/simon/Documents/oxide; ./build/gyp_oxide -IC:/Users/simon/Documents/oxide/qt/qt.gypi -Doxide_qt_libversion=0
Couldn't change working directory to C:/Users/simon/Documents/oxide; ./build/gyp_oxide -IC:/Users/simon/Documents/oxide/qt/qt.gypi -Doxide_qt_libversion=0.
jom: C:\Users\simon\Documents\build-oxideqt-Desktop_Qt_5_1_1_MSVC2010_32bit-Release\qt\lib\Makefile.Release [C:\Users\simon\Documents\oxide\Makefile.oxide] Error 1
jom: C:\Users\simon\Documents\build-oxideqt-Desktop_Qt_5_1_1_MSVC2010_32bit-Release\qt\lib\Makefile [release] Error 2
jom: C:\Users\simon\Documents\build-oxideqt-Desktop_Qt_5_1_1_MSVC2010_32bit-Release\Makefile [sub-qt-lib-lib-pro-make_first-ordered] Error 2
11:13:58: The process "C:\Qt\Qt5.1.1\Tools\QtCreator\bin\jom.exe" exited with code 2.
Error while building/deploying project oxideqt (kit: Desktop Qt 5.1.1 MSVC2010 32bit)
When executing step 'Make'
It looks like that it is doing a cd on C:/Users/simon/Documents/oxide; ./build/gyp_oxide -IC:/Users/simon/Documents/oxide/qt/qt.gypi -Doxide_qt_libversion=0, but I cannot find out which script is doing the cd.
The following are the associated .pro files:
oxideqt.pro (top level .pro)
TEMPLATE = subdirs
CONFIG += ordered
lib.file = qt/lib/lib.pro
SUBDIRS += lib
renderer.file = qt/renderer/renderer.pro
SUBDIRS += renderer
sandbox.file = qt/sandbox/sandbox.pro
SUBDIRS += sandbox
qmlplugin.file = qt/qmlplugin/qmlplugin.pro
SUBDIRS += qmlplugin
testutils.file = qt/tests/utils/testutils.pro
SUBDIRS += testutils
qmltests.file = qt/tests/qmltests/qmltests.pro
SUBDIRS += qmltests
QMAKE_CLEAN += -r \
$${OXIDE_SRC_ROOT}/Makefile.oxide \
`find $$OXIDE_SRC_ROOT -name \"*.target.oxide.mk\"` \
$$CHROMIUM_OUT_DIR
lib.pro
CONFIG += gyp disable_check
TARGET = oxide-qt
GYP_TYPE = lib
include($${OXIDE_QMAKE_PATH}/oxide_variables.pri)
GYP_LIBVERSION = $$OXIDE_QT_LIBVERSION
resources.path = $$LIBEXECDIR
resources.files = \
$${CHROMIUM_OUT_PLAT_DIR}/oxide.pak \
$${CHROMIUM_OUT_PLAT_DIR}/oxide_100_percent.pak
resources.CONFIG = no_check_exist
INSTALLS += resources
A possible reason and solution:
This looks like it is for sh, not for cmd.exe:
cd C:/Users/simon/Documents/oxide; ./build/gyp_oxide -IC:/Users/simon/Documents/oxide/qt/qt.gypi -Doxide_qt_libversion=0
If so, it may be due to faulty auto-detection of shell. A reason for that happening might be that there is sh.exe in the PATH. So, find out where it is, and either remove the folder from PATH or rename the file to sh_.exe or whatever.
To find it, this should find the file (a link) at the correct cmd.exe prompt for the build environment:
where sh
Note that if you have a lot of stuff installed, you may have several of them in your PATH, so after getting rid of first, check again... If still not solved, try removing bash from PATH too (though I have not seen that causing trouble). Also remember to restart the IDE or the command prompt if you edit system PATH, for the change to take effect. And then remember to re-run qmake.
It seems that http://bazaar.launchpad.net/~oxide-developers/oxide/oxide.trunk/view/head:/build/gyp_oxide is a python-script, which the make tries to start. Is python.exe in your PATH-variable?
Kim Kulling
I just looked over the configuration of the whole pro-files and found a lot of unix-specific paths like /usr/local. Is window as a build target at all supported?
As mentioned before the build script cannot work with cd ; command .
Maybe you can try to run it using cygwin?
Kim Kulling