How to refer to the source directory in qmake? - qmake

I added
version.target = version.h
version.commands = bash generate-version.sh
QMAKE_EXTRA_TARGETS += version
PRE_TARGETDEPS += version.h
to the project, but it attempts to run "generate-version.sh" in destination directory:
make: Leaving directory `.../qqq-build-desktop'
make: Entering directory `.../qqq-build-desktop'
Makefile:236: warning: overriding commands for target `version.h'
Makefile:233: warning: ignoring old commands for target `version.h'
bash generate-version.sh
bash: generate-version.sh: No such file or directory
make: Leaving directory `.../qqq-build-desktop'
There is $$DESTDIR, but I don't see $$SRCDIR. How to refer to the project directory in qmake (or how to rewrite this)?

My first thought is to try to rewrite
version.commands = bash generate-version.sh
so as not to have to invoke a shell script. Perhaps you can combine all of the statements into one line:
version.commands = echo \'char VERSION[]=\"1.0\";\' > version.h && ls && echo Done
If you are stuck with invoking the script, probably PWD or OUT_PWD are what you are looking for. From the qmake Variable Reference
PWD
This variable contains the full path leading to the directory where the qmake project file (project.pro) is located.
OUT_PWD
This variable contains the full path leading to the directory where qmake places the generated Makefile.
The one caveat that is not mentioned in the documentation is that if you are doing a recursive qmake, PWD refers to where the top level .pro file was read from. Thus if you run qmake -r from {proj-root}, when sub/sub/sub/dir-proj.pro is finally read in, PWD will still point to {proj-root}.
Assuming that generate-version.sh is in the same directory as your top level .pro file, you might try:
version.commands = bash $$PWD/generate-version.sh

I found a better and cleaner solution
version.target = version.h
version.commands = bash ${QMAKE_VAR__PRO_FILE_PWD_}/generate-version.sh
QMAKE_EXTRA_TARGETS += version
The variable _PRO_FILE_PWD_ is documented since qt 4.5 and contains the path to the directory containing the project file in use (Contains the .pro file)
But to access this variable for QMAKE_EXTRA_TARGETS, QMAKE_VAR_ must be appended.

PWD
Specifies the full path leading to the directory containing the
current file being parsed. This can be useful to refer to files within
the source tree when writing project files to support shadow builds.

I use (Linux and g++)
DEFINES += SVN_VERSION=\\\"\""`svnversion $$PWD`\""\\\"
DEFINES += COMPILE_DATE=\\\"\""`date`\""\\\"
DEFINES += SW_VERSION=\\\"\"0.5\"\\\"
which defines the macro SVNVERSON to be the svn version.
To access it from C++:
QString svnVersion = SVN_VERSION;
QString swVersion = SW_VERSION;
Explanation: On the shell I want to see this call:
-DSVN_VERSION=\""`svnversion /path/to/my/source`"\"
As you see some escapes are necessary on shell level. In the .pro-file it then has to be escaped twice.

This works and is easy to understand.
version.commands = ( cd $${PWD}; generate-version.sh )

Related

CPPCheck: Ignore dirs and all sub dirs from analyses?

I have read the manual at https://cppcheck.sourceforge.io/manual.pdf and have found that I can use -i to ignore a directory. However, in my testing it doesn't seem to ignore the whole subdir. Example, I have a library that has a very long directory path (this is simplified) but I want to ignore everything under the top level
Root
> Lib
>> Lib dir 1
>>> file.c
>> Lib dir 2
>>> file.c
The wording
To ignore certain folders you can use -i. This will skip analysis of source files in
the foo folder.
cppcheck --project=compile_commands.json -ifoo
Suggests that it will skip any files in the specified dir, not any subdirs.
Is there a way to skip the dir and all sub dirs?
The way I had to achieve this was generating a compile_commands.json from cmake then write a python script to exclude anything that matched the filter I wanted to exclude, eg /libA/ will exclude anything under libA

Unix. Parse file with full paths to SHA256 checksums files. Run command in each path/file

I have a file file.txt with filenames ending with *.sha256, including the full paths of each file. This is a toy example:
file.txt:
/path/a/9b/x3.sha256
/path/7c/7j/y2.vcf.gz.sha256
/path/e/g/7z.sha256
Each line has a different path/file. The *.sha256 files have checksums.
I want to run the command "sha256sum -c" on each of these *.sha256 files and write the output to an output_file.txt. However, this command only accepts the name of the .sha256 file, not the name including its full path. I have tried the following:
while read in; do
sha256sum -c "$in" >> output_file.txt
done < file.txt
but I get:
"sha256sum: WARNING: 1 listed file could not be read"
which is due to the path included in the command.
Any suggestion is welcome
#!/bin/bash
while read in
do
thedir=$(dirname "$in")
thefile=$(basename "$in")
cd "$thedir"
sha256sum -c "$thefile" >>output_file.txt
done < file.txt
Modify your code to extract the directory and file parts of your in variable.

How to Run just-compiled program in SConscript

I have a somewhat complex SCons build script that an some point does the following two steps:
# 1: builds unit tests (googletest, shell executable)
compile_tests = some_environment.Program(executable_path, test_sources)
# 2: runs unit tests (call earlier compiled program)
run_tests = other_environment.Command(
source = executable_path,
action = executable_path + ' --gtest_output=xml:' + test_results_path,
target = test_results_path
)
Depends(run_tests, compile_tests)
This is working fine if I run scons with this build script on its own.
If I, however, invoke it via environment.SConscript() from another SConstruct file one directory level up, then step 1 adjusts the path to the project's location while step 2 doesn't. See this output:
scons: Building targets ...
g++ -o Nuclex.Game.Native/obj/gcc-7-amd64-release/NuclexGameNativeTests -z defs -Bsymbolic Nuclex.Game.Native/obj/gcc-7-amd64-release/Tests/Timing/ClockTests.o -LNuclex.Game.Native/obj/gcc-7-amd64-release -LReferences/googletest/gcc-7-amd64-release -lNuclexGameNativeStatic -lgoogletest -lgoogletest_main -lpthread
obj/gcc-7-amd64-release/NuclexGameNativeTests --gtest_output=xml:bin/gcc-7-amd64-release/gtest-results.xml
sh: obj/gcc-7-amd64-release/NuclexGameNativeTests: No such file or directory
Line 2 builds the executable into Nuclex.Game.Native/obj/gcc-7-amd64-release/ while line 3 tries to call it in obj/gcc-7-amd64-release/, forgetting the project directory.
Should I use another way to invoke my unit test executable? Or can I query the SCons environment for its base path?
Update: reproduction case, place https://pastebin.com/W08yZuF9 as SConstruct in root directory, create subdirectory somelib and place https://pastebin.com/eiP63Yxh as SConstruct therein, also create main.cpp with a "Hello World" or other dummy program.
A SCons Action (the action parameter in the Command) will use the SCons variables to substitute sources and targets in correctly, taking into account VariantDirs and SConscript directories automatically. You can find more info on these source and target substitutions here: https://scons.org/doc/HTML/scons-man.html#variable_substitution
There is a section which explains using this in regards to SConscript and VariantDirs:
SConscript('src/SConscript', variant_dir='sub/dir')
$SOURCE => sub/dir/file.x
${SOURCE.srcpath} => src/file.x
${SOURCE.srcdir} => src
So in your example I think you want to replace executable_path with $SOURCE in the action string:
# 2: runs unit tests (call earlier compiled program)
run_tests = other_environment.Command(
source = executable_path,
action = '$SOURCE --gtest_output=xml:$TARGET',
target = test_results_path
)

Qmake INSTALLS variable - create symbolic link to directory

I am trying to add an INSTALLS rule to my qmake .pro file that will create a symlink in the build directory to the config directory in my project. Here's how I've tried to do it using the 'extra' member:
config.path = $$top_builddir/
config.files = $$rootdir/config
config.extra = ln -sf $$config.files $$config.path
INSTALLS += config
where top_builddir and rootdir are of course the paths to the build directory and root project dir, respectively.
The generated Makefile rule is:
install_config: FORCE
#test -d $(INSTALL_ROOT)/home/greg/Desktop/mg_builds/MPI-Debug || mkdir -p $(INSTALL_ROOT)/home/greg/Desktop/mg_builds/MPI-Debug
ln -sf /home/greg/Desktop/mg/config /home/greg/Desktop/mg_builds/MPI-Debug/
-$(INSTALL_DIR) /home/greg/Desktop/mg/config $(INSTALL_ROOT)/home/greg/Desktop/mg_builds/MPI-Debug/
The extra command has been added but there is also the command to cp the directory too which is causing causing the error:
cp: '/home/greg/Desktop/mg/config' and '/home/greg/Desktop/mg_builds/MPI-Debug/config' are the same file
Makefile:580: recipe for target 'install_config' failed
How can I suppress this or tell qmake to make a symlink rather than a copy?
After a little experimenting I found this works quite nicely. You can leave the .files member empty (i.e. .files =) or just omit it entirely and no copy command will be generated in the Makefile. The target directory can be written directly in the extra command. However, a .path is still required for the rule to be generated.
config.path = $$top_builddir/
config.extra = ln -sf $$rootdir/config $$config.path
INSTALLS += config
Makefile:
install_config: FORCE
#test -d $(INSTALL_ROOT)/home/greg/Desktop/mg_builds/MPI-Debug/ || mkdir -p $(INSTALL_ROOT)/home/greg/Desktop/mg_builds/MPI-Debug/
ln -sf /home/greg/Desktop/mg/config /home/greg/Desktop/mg_builds/MPI-Debug/

Scons in Scratchbox: Can't find g++

I've been using sbox with a Make-based codebase with no problems. Now
I'm using a scons-based codebase, and am getting some odd problems.
It seems that within scratchbox, scons can't find g++. For example, it
attempts to execute things like:
o hello hello.c
When it should be doing:
g++ -o hello hello.c
So presumably its g++ string variable is empty. g++ is present and in
the PATH - "which g++" produces /scratchbox/compilers/bin/g++.
The same source builds fine outside of scratchbox, so it shouldn't be
a problem with scons or the codebase. There are no special environment
variables set outside of scratchbox when it works.
If I symbolically link /usr/bin/g++ to /scratchbox/compilers/bin/g++,
it gets a bit further (produces the correct-looking g++ commands) but
then upon executing them produces:
sb_gcc_wrapper (g++):
/scratchbox/compilers/arm-linux-cs2007q3-51sb3/bin/sbox-arm-none-linux-gnueabi-g++:
No such file or directory
The file listed is present.
PATH contains /scratchbox/compilers/bin, SBOX_REDIRECT_FROM_DIRS contains /usr/bin and SBOX_REDIRECT_TO_DIRS contains /scratchbox/compilers/bin, so I think it should be able to find it.
Any suggestions would be appreciated!
Thanks,
Ray
Edit: Perhaps related - it also can't find pkg-config unless I prepend the full path within the scons file
scons does not propagate the PATH environment variable, so testing e.g. 'which g++' doesn't help much.
Either set the compilers directly, e.g.
env['CXX'] = '/scratchbox/compilers/bin/g++'
Build your own explicit PATH
path = ['/scratchbox/compilers/bin/','/bin', '/usr/bin', '/sbin','/usr/sbin']
env = Environment(ENV = {'PATH' : path})
Or use the PATH env variable from your shell
import os
env = Environment(ENV = {'PATH' : os.environ['PATH']})

Resources