How to generate code coverage with running lcov program at the same time - lcov

I have a large project with unittest binaries running on the other machines. So, the gcda files were generated on the other machines. Then, I download them to the local machine but the different dirs. Each of the dirs has the sources code.
For example: dir gcda1/src/{*.gcda, *.gcno, *.h, *.cpp}..., dir gcda2/src/{*.gcda, *.gcno, *.h, *.cpp}....
Because the project is very large, so I have to run multiple lcov processes at the same time to generate info files to save time. And then merge these info files.
The problem is, when I merge these info files, it will take dir infos, for example:
gcda1/src/unittest1.cpp
gcda2/src/unittest1.cpp
I want this:
src/unittest1.cpp
#src/unittest1.cpp # this is expected to merge with above
The commands I use:
$ cd gcda1
$ lcov --rc lcov_branch_coverage=1 -c -d ./ -b ./ --no-external -o gcda1.info
$ cd ../gcda2
$ lcov --rc lcov_branch_coverage=1 -c -d ./ -b ./ --no-external -o gcda2.info
$ cd ..
$ lcov -a gcda1/gcda1.info -a gcda1/gcda2.info -o gcda.info
$ genhtml gcda.info -o output
The root dir contains the source code.

Description
Well, I have found a method to solve this problem finally.
The info files lcov generated are plain text file. So we can edit them directly.
Once you open these files, you will see every file line start with SF. Like below:
SF:/path/to/your/source/code.h
SF:/path/to/your/source/code.cpp
...
Problem
In my problem, these will be:
// file gcda1.info
SF:/path/to/root_dir/gcda1/src/unittest1.cpp
// file gcda2.info
SF:/path/to/root_dir/gcda2/src/unittest1.cpp
And, after lcov merge, it will be:
// file gcda.info
SF:/path/to/root_dir/gcda1/src/unittest1.cpp
SF:/path/to/root_dir/gcda2/src/unittest1.cpp
But, I expect this:
// file gcda.info
SF:/path/to/root_dir/src/unittest1.cpp
Method
My method to solve the problem is editing the info files directly.
First, edit gcda1.info and gcda2.info, change /path/to/root_dir/gcda1/src/unittest1.cpp to /path/to/root_dir/src/unittest1.cpp, and /path/to/root_dir/gcda2/src/unittest1.cpp to /path/to/root_dir/src/unittest1.cpp.
Then merge them like below and generate html report:
$ lcov -a gcda1.info -a gcda2.info -o gcda.info
$ genhtml gcda.info -o output
In a large project, we could not manually edit each info file, otherwise you will collapse.
We can use sed to help us. Like below:
$ sed "s/\(^SF.*\/\)gcda[0-9]+\/\(.*\)/\1\2/g" gcda_tmp.info > gcda.info

Related

Is it possible to exclude a specific subdirectory from a podman volume mount?

For example, let's say you have a directory dir/ with an arbitrary number of subdirectories including dir/subdir/, and you want to mount dir/ to a podman container with every subdirectory also mounted except dir/subdir/.
Is this possible in podman? If so, is it possible to do this purely with the arguments of a podman run command?
Is not possible, the entire folder will be available inside the container.
You can overcome this with permissions, acl or even symbolic links. In the last case, create a second folder with links pointing to only the folders you want to be available inside the container.
Use an extra bind-mount to hide the directory dir/subdir/
In other words, first bind-mount dir/ and then bind-mount an empty directory over dir/subdir to hide its contents.
$ mkdir dir
$ mkdir dir/subdir
$ mkdir dir/subdir2
$ mkdir emptydir
$ touch dir/subdir/file1.txt
$ touch dir/subdir2/file2.txt
$ podman pull -q docker.io/library/fedora
b2aa39c304c27b96c1fef0c06bee651ac9241d49c4fe34381cab8453f9a89c7d
$ podman run --rm \
-v ./dir:/dir:Z \
-v ./emptydir:/dir/subdir:Z \
docker.io/library/fedora find /dir
/dir
/dir/subdir
/dir/subdir2
/dir/subdir2/file2.txt
In the output from the command find /dir there is no file dir/subdir/file1.txt

Mercurial: rename using --include option

I am trying to move(via the rename tool) a group of source files but still keep them tracked. Mercurial's rename tool has the --include option for handling multiple names. When I a try to move the files, I get the current directory added to the final name. When I remove the preceding "./" only the file name is referenced.
I am using the -I option to include a pattern of files. For reference:
https://www.selenic.com/mercurial/hg.1.html#rename
I am using Mercurial on windows through Cygwin64.
This is the directory that I am in:
$ pwd
/cygdrive/c/Users/me/thisProject/apple
This is what I want.
$ hg rename -f -v -I '*.c' ./ banana
moving one.c to .banana\one.c
moving two.c to .banana\two.c
moving three.c to .banana\three.c
This is what I don't want.
$ hg rename -f -v -I '*.c' ./ ./banana
moving one.c to banana\apple\one.c
moving two.c to banana\apple\two.c
moving three.c to banana\apple\three.c
Why does adding a "./" to the destination add the current directory name as an extra folder in the output?

How to drop a prefix from hg archive?

I would like to export files from a repository, ignoring changes in the working tree. Furthermore, rather than exporting everything, I would like to see a subset of it. The destination directory might already contain some files and those must be overwritten.
Given:
project/some/sub/dir/
I would like to export it to:
output/dir/
In git, I can use:
git archive --prefix=dir/ HEAD -- some/sub/dir/ | tar -xv -C output
What is the equivalent command in hg? If I use hg archive -t files -I some/sub/dir output/, then I get output/some/sub/dir. I could pipe the result through tar, but then I have to manually calculate the prefix that should be dropped:
hg archive -t tar -I some/sub/dir/ - |
tar -xv -C output --strip-components=3
(in reality, I have some other tar patterns that should be ignored such as --exclude='.*'). Any ideas? This export will be done for three other directories located in the repository.
Current situation:
srcdir=some/sub/dir
dstdir=output/dir
# hg archive auto-adds a 'proj-version' prefix. Given the srcdir,
# proj-version/some/sub/dir/X should become dstdir/X, so strip 4 components
prefixlength=$(grep -c / <<<"/${srcdir%%/}/")
hg archive -t tar -I "$srcdir" - |
tar -xv -C "$dstdir" --strip-components=$prefixlength
You can
hg archive ... && cd output/some/sub/dir && tar ... isn't it?
Build intermediate repo (Convert Extension), where some/sub/dir/ will be root of this repository (understand also sample from Converting from Mercurial topic) and get tar'red archive directly from hg archive for intermediate repository

Creating custom DVD for RHEL 7 with kickstart

I am trying to create a custom CD/DVD to deploy RHEL 7 with kickstart file. Here is what I did:
Edited isolinux.cfg (in the ISOLinux folder) and grub.cfg file (in the EFI\BOOT folder).
Created ISO using mkisofs.
But it is not working. Am I using correct files/method?
Edit the ISO image and put the ks.cfg file that you have created.
Preferably, put the ks.cfg file inside ks directory. More information can be found here.
You need to use the new command. Here is an example of what will work:
Add the kickstart file to your download and exploded ISO.
Run this command in the area with the ISO and kickstart and point to another location to build the ISO:
genisoimage -r -v -V "OEL6 with KS for OVM Manager" -cache-inodes -J -l -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -o OEL6U6_OVM_Manager.iso /var/www/html/Template/ISO/
I found the way to create custom DVD from the RHEL7 page.
Mount the downloaded image
mount -t iso9660 -o loop path/to/image.iso /mnt/iso
Create a working directory - a directory where you want to place the contents of the ISO image.
mkdir /tmp/ISO
Copy all contents of the mounted image to your new working directory. Make sure to use the -p option to preserve file and directory permissions and ownership.
cp -pRf /mnt/iso /tmp/ISO
Unmount the image.
umount /mnt/iso
Make sure your current working directory is the top-level directory of the extracted ISO image - e.g. /tmp/ISO/iso. Create the new ISO image using genisoimage:
genisoimage -U -r -v -T -J -joliet-long -V "RHEL-7.1 Server.x86_64" -Volset "RHEL-7.1 Server.x86_64" -A "RHEL-7.1 Server.x86_64" -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot -e images/efiboot.img -no-emul-boot -o ../NEWISO.iso .
Hope the answer will helpful:
I am editing my answer due to the comments posted. Here is a more comprehensive solution:
(A) You need to create the ISO properly. I found helpful information in this URL.
Here is the line that I actually ended up with, for my MBR/UEFI ISO creation:
mkisofs -U -A "<Volume Header>" -V "RHEL-7.1 x86_64" -volset "RHEL-7.1 x86_64" -J -joliet-long -r -v -T -x ./lost+found -o ${OUTPUT}/${HOST}.iso -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot -e images/efiboot.img -no-emul-boot -boot-load-size 18755 /dir/where/sources/for/ISO/are/located
Be careful with the -V parameter, as it has to match what the kernel has defined for inst.stage2. In the default grub.conf included in the boot disk, it is configured to be "hd:LABEL=RHEL-7.1\x20x86_64" which matches with the settings above.
(B) You need the correct setup for EFI for RHEL7. For some reason, this has changed from RHEL6, where you could just use the /EFI/BOOT/BOOTX64.conf. Now it uses the /EFI/BOOT/grub.cfg. Common wisdom from Red Hat Manuals state to add the inst.ks= parameter to the kernel line. The grub.cfg that comes in the /EFI/BOOT directory of the RHEL7 boot iso actually has the linuxefi parameter, instead of the kernel one, I would guess they would work the same. If you are including the KS file on the CD, this should get you there.
Good Luck!

Getting CMake to build out of source without wrapping scripts

I'm trying to get CMake to build into a directory 'build', as in project/build, where the CMakeLists.txt is in project/.
I know I can do:
mkdir build
cd build
cmake ../
but that is cumbersome. I could put it in a script and call it, but then it's unpleasant to provide different arguments to CMake (like -G "MSYS Makefiles"), or I would need to edit this file on each platform.
Preferably I would do something like SET(CMAKE_OUTPUT_DIR build) in the main CMakeLists.txt. Please tell me that this is possible, and if so, how? Or some other out of source build method that makes it easy to specify different arguments?
CMake 3.13 or newer supports the command line options -S and -B to specify source and binary directory, respectively.
cmake -S . -B build -G "MSYS Makefiles"
This will look for the CMakeLists.txt in the current folder and create a build folder (if it does not yet exist) in it.
For older versions of CMake, you can use the undocumented CMake options -H and -B to specify the source and binary directory upon invoking cmake:
cmake -H. -Bbuild -G "MSYS Makefiles"
Note that there must not be a space character between the option and the directory path.
A solution that I found recently is to combine the out-of-source build concept with a Makefile wrapper.
In my top-level CMakeLists.txt file, I include the following to prevent in-source builds:
if ( ${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR} )
message( FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt." )
endif()
Then, I create a top-level Makefile, and include the following:
# -----------------------------------------------------------------------------
# CMake project wrapper Makefile ----------------------------------------------
# -----------------------------------------------------------------------------
SHELL := /bin/bash
RM := rm -rf
MKDIR := mkdir -p
all: ./build/Makefile
# $(MAKE) -C build
./build/Makefile:
# ($(MKDIR) build > /dev/null)
# (cd build > /dev/null 2>&1 && cmake ..)
distclean:
# ($(MKDIR) build > /dev/null)
# (cd build > /dev/null 2>&1 && cmake .. > /dev/null 2>&1)
#- $(MAKE) --silent -C build clean || true
#- $(RM) ./build/Makefile
#- $(RM) ./build/src
#- $(RM) ./build/test
#- $(RM) ./build/CMake*
#- $(RM) ./build/cmake.*
#- $(RM) ./build/*.cmake
#- $(RM) ./build/*.txt
ifeq ($(findstring distclean,$(MAKECMDGOALS)),)
$(MAKECMDGOALS): ./build/Makefile
# $(MAKE) -C build $(MAKECMDGOALS)
endif
The default target all is called by typing make, and invokes the target ./build/Makefile.
The first thing the target ./build/Makefile does is to create the build directory using $(MKDIR), which is a variable for mkdir -p. The directory build is where we will perform our out-of-source build. We provide the argument -p to ensure that mkdir does not scream at us for trying to create a directory that may already exist.
The second thing the target ./build/Makefile does is to change directories to the build directory and invoke cmake.
Back to the all target, we invoke $(MAKE) -C build, where $(MAKE) is a Makefile variable automatically generated for make. make -C changes the directory before doing anything. Therefore, using $(MAKE) -C build is equivalent to doing cd build; make.
To summarize, calling this Makefile wrapper with make all or make is equivalent to doing:
mkdir build
cd build
cmake ..
make
The target distclean invokes cmake .., then make -C build clean, and finally, removes all contents from the build directory. I believe this is exactly what you requested in your question.
The last piece of the Makefile evaluates if the user-provided target is or is not distclean. If not, it will change directories to build before invoking it. This is very powerful because the user can type, for example, make clean, and the Makefile will transform that into an equivalent of cd build; make clean.
In conclusion, this Makefile wrapper, in combination with a mandatory out-of-source build CMake configuration, make it so that the user never has to interact with the command cmake. This solution also provides an elegant method to remove all CMake output files from the build directory.
P.S. In the Makefile, we use the prefix # to suppress the output from a shell command, and the prefix #- to ignore errors from a shell command. When using rm as part of the distclean target, the command will return an error if the files do not exist (they may have been deleted already using the command line with rm -rf build, or they were never generated in the first place). This return error will force our Makefile to exit. We use the prefix #- to prevent that. It is acceptable if a file was removed already; we want our Makefile to keep going and remove the rest.
Another thing to note: This Makefile may not work if you use a variable number of CMake variables to build your project, for example, cmake .. -DSOMEBUILDSUSETHIS:STRING="foo" -DSOMEOTHERBUILDSUSETHISTOO:STRING="bar". This Makefile assumes you invoke CMake in a consistent way, either by typing cmake .. or by providing cmake a consistent number of arguments (that you can include in your Makefile).
Finally, credit where credit is due. This Makefile wrapper was adapted from the Makefile provided by the C++ Application Project Template.
This answer was originally posted here. I thought it applied to your situation as well.
Based on the previous answers, I wrote the following module that you can include to enforce an out-of-source build.
set(DEFAULT_OUT_OF_SOURCE_FOLDER "cmake_output")
if (${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
message(WARNING "In-source builds not allowed. CMake will now be run with arguments:
cmake -H. -B${DEFAULT_OUT_OF_SOURCE_FOLDER}
")
# Run CMake with out of source flag
execute_process(
COMMAND ${CMAKE_COMMAND} -H. -B${DEFAULT_OUT_OF_SOURCE_FOLDER}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
# Cause fatal error to stop the script from further execution
message(FATAL_ERROR "CMake has been ran to create an out of source build.
This error prevents CMake from running an in-source build.")
endif ()
This works, however I already noticed two downsides:
When the user is lazy and simply runs cmake ., they will always see a FATAL_ERROR. I could not find another way to prevent CMake from doing any other operations and exit early.
Any command line arguments passed to the original call to cmake will not be passed to the "out-of-source build call".
Suggestions to improve this module are welcome.