CMake run custom command after target fails to build - build

I know how to run a command after (or before) building a target with add_custom_command :
add_custom_command(TARGET my_target POST_BUILD
COMMAND echo "custom command"
)
But I want to ALWAYS run this command, after the target has been build or after it failed to build.
Here, when the target fails to build, the command is not launched.
Is it possible to achieve this with cmake?

Related

Add multiple executable to single gtest in Bazel

Colleagues,
I have 2 executable and 2 shell scripts for test. In Cmake I have:
add_executable(test1 test1.cpp)
add_executable(test2 test2.cpp)
add_test(NAME test_bin COMMAND test1 test2)
and
add_test(NAME test_sh
COMMAND s1.sh e1.sh)
set_tests_properties(test_sh PROPERTIES TIMEOUT 1.1)
how to do the same in Bazel BUILD? I cannot use separate command line because the tests are the part of the project and I cannot change cmd arguments

CMake with Xilinx Vitis, Generator: execution of make failed. Make command was: -f Makefile cmTC_fb383/fast &&

I'm configuring CMake to work with the Xilinx Vitis arm toolchain. My development PC is Windows 10. When I execute the command:
cmake -G"Unix Makefiles" -Baarch32 -DCMAKE_TOOLCHAIN_FILE="xilinx-aarch32.cmake"
I receive the error:
The C compiler arm-non-eabi-gcc.exe is not able to compile a simple test program.
It fails with the following output:
Change Dir: .../aarch32/CMakeFiles/CMakeTmp
Run Build Command(s): -f Makefile cmTC_fb383/fast && The parameter is incorrect
Generator: execution of make failed. Make command was: -f Makefile cmTC_fb383/fast &&
xilinx-arm.cmake contains:
set( CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY" CACHE STRING "" FORCE )
set( CMAKE_MAKE_PROGRAM $ENV{Vitis}/gnuwin/bin/make.exe )
message( ${CMAKE_MAKE_PROGRAM} )
I've verified CMAKE_MAKE_PROGRAM contains the full correct path to make.exe provided by Xilinx. Additionally, the simple test program attempts to build a library rather than an executable.
I can get around the error by adding the following lines to xilinx-aarch32.cmake to prevent the simple test program compilation:
set( CMAKE_C_COMPILER_ID_RUN TRUE )
set( CMAKE_C_COMPILER_FORCED TRUE )
set( CMAKE_CXX_COMPILER_ID_RUN TRUE )
set( CMAKE_CXX_COMPILER_FORCED TRUE )
However, cmake --build aarch32 fails with The parameter is incorrect.
With the workaround, I am able to execute make via ${Vitis}/gnuwin/bin/make.exe -C aarch32 and build successfully.
Are there additional CMake options to configure the build command?

How to find my generated shared library from cmake?

I want to create a shared library from cmake . I have a simple test.cpp .
My CMakeLists.txt looks like below
cmake_minimum_required(VERSION 2.8)
project (test)
set(CMAKE_BUILD_TYPE Release)
#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
add_library(test SHARED /home/tuhin/test/test1/test.cpp)
But I am not able to find "test" which my .so, I have seen test.dir folder created but not .so
Please help me to understand the issue.
(I suppose you read the comments and acted accordingly...)
(I also suppose you need a way to find out where your library will be placed, from within CMake build system)
The disk location of any target does not depend on CMakeLists.txt only, but also on the choice of the generator. Multi config generators like Visual Studio something, or Xcode might append configuration name as an additional directory, so you may get different results just by choosing a different generator.
This means that there is no easy way to uniquely identify disk location during configure stage. On the other hand, you may very easily check that information during the build stage:
cmake_minimum_required(VERSION 3.15)
project (lib_file_name)
add_library(my_test_lib SHARED my_test_lib.cpp)
add_custom_target(output_lib_name
ALL
COMMAND ${CMAKE_COMMAND} -E echo "my_test_lib location: $<TARGET_FILE:my_test_lib>"
)
note add_custom_target line:
new target was added, named output_lib_name
it will be executed as a part of building the default target (-> ALL)
command to build this target is asking cmake to output the file name of the target in question, using CMAke generator expressions (--> COMMAND ${CMAKE_COMMAND} -E echo "my_test_lib location: $<TARGET_FILE:my_test_lib>")
If you run it with makefile generator:
$ cmake -S /tmp -B /tmp/make-build -G "Unix Makefiles" ; cmake --build /tmp/make-build
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/make-build
Scanning dependencies of target my_test_lib
[ 50%] Building CXX object CMakeFiles/my_test_lib.dir/my_test_lib.cpp.o
[100%] Linking CXX shared library libmy_test_lib.dylib
[100%] Built target my_test_lib
Scanning dependencies of target output_lib_name
my_test_lib location: /tmp/make-build/libmy_test_lib.dylib
[100%] Built target output_lib_name
Note the line
my_test_lib location: /tmp/make-build/libmy_test_lib.dylib
if you run it with Xcode generator:
configure:
$ cmake -S /tmp -B /tmp/xcode-build -G Xcode
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/xcode-build
build release configuration:
$ cmake --build /tmp/xcode-build --config Release
........... lot of output deleted ...........
my_test_lib location: /tmp/xcode-build/Release/libmy_test_lib.dylib
** BUILD SUCCEEDED **
build debug configuration:
$ cmake --build /tmp/xcode-build --config Debug
........... lot of output deleted ...........
my_test_lib location: /tmp/xcode-build/Debug/libmy_test_lib.dylib
** BUILD SUCCEEDED **
Note how the location is different for different configuration builds, without any change in CMake build system.
At the end, this is the cmake documentation about add_custom_command, cmake generator expressions.

windeployqt doesn't deploy qwindowsd.dll for a debug application

I'm trying to use windeployqt.exe (Qt 5.13.2) to deploy dlls for a debug application generated by CMake 3.16. All the dlls are deployed correctly except for the platform plugin dll, which deploys qwindows.dll instead of qwindowsd.dll and results in the following error when I try to run the executable:
This application failed to start because no Qt platform plugin could be initialized.
So far, I've tried:
Specifying --debug on the windeployqt command line. That failed because Qt5Coredd.dll could not be found (note the double d's).
Verifying that no Qt plugin related environment variables are set.
Checked PATH to make sure it doesn't contain any folder with a platforms directory.
If I copy qwindowsd.dll manually, everything works fine. However I'd really like to figure out what I'm doing wrong with windeployqt.
This is apparently a known problem that Qt have dragged their heels on fixing, but I figured out a workaround in CMake - this works for both the Ninja generator/Visual Studio's built in CMake support as well as the regular Visual Studio solution generator
# Split windeployqt into 2 parts to fix issue with deploying debug plugins
add_custom_command(TARGET MyApp POST_BUILD
COMMAND ${QT_PATH}/bin/windeployqt --compiler-runtime --no-plugins ${MY_APP_EXE})
if (CMAKE_GENERATOR STREQUAL "Ninja")
# Ninja is a single-config generator so we can use CMAKE_BUILD_TYPE to generate different commands
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
add_custom_command(TARGET MyApp POST_BUILD
COMMAND ${QT_PATH}/bin/windeployqt --debug --no-compiler-runtime --no-translations --no-libraries ${MY_APP_EXE})
else()
add_custom_command(TARGET MyApp POST_BUILD
COMMAND ${QT_PATH}/bin/windeployqt --release --no-compiler-runtime --no-translations --no-libraries ${MY_APP_EXE})
endif()
else()
# if in MSVC we have to check the configuration at runtime instead of generating different commands
add_custom_command(TARGET MyApp POST_BUILD
COMMAND cmd.exe /c if "$(Configuration)" == "Debug" ${QT_PATH}/bin/windeployqt --debug --no-compiler-runtime --no-translations --no-libraries ${MY_APP_EXE})
add_custom_command(TARGET MyApp POST_BUILD
COMMAND cmd.exe /c if not "$(Configuration)" == "Debug" ${QT_PATH}/bin/windeployqt --release --no-compiler-runtime --no-translations --no-libraries ${MY_APP_EXE})
endif()

Cmake: How to have add_custom_command() run after all project files are built

Using Cmake v3.8, I need my custom command to run only after my newly built .hex, .map, and .elf files are produced. However, the command is not truly running after all of the *.hex, *.map, and *.elf files are produced. Here is what I have:
add_custom_command(
POST_BUILD
COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/performCrc32.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT performCrc32.out
COMMENT "Running CRC32 check..."
)
add_custom_target(
performCrc32 ALL
DEPENDS performCrc32.py
performCrc32.out
)
What am I missing, if anything?
There is no way for add commands to be executed "after the build is entirely complete".
You may add commands to be executed after specific target is built:
add_custom_command(TARGET <kernel-target> POST_BUILD
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/performCrc32.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Running CRC32 check..."
)
This would add command to be executed after <kernel-target> and all its dependencies will be built. Note on the absence of OUTPUT option in this case.
This is preferrable way for post-build checks, as a check will be performed every time target is actually (re)built.
You may bind your custom command to your custom target (as usual), and add dependencies for the target:
add_custom_command(
COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/performCrc32.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT performCrc32.out
COMMENT "Running CRC32 check..."
)
add_custom_target(
performCrc32 ALL
DEPENDS performCrc32.py
performCrc32.out
)
add_dependencies(performCrc32 <hex-targets...> <map-targets> <elf-target>)
In this case command will be executed after all dependent targets are built. However, the command will be executed only first build: once OUTPUT file will be created, the command won't be executed again.
POST_BUILD option for add_custom_command is applicable only for TARGET flow of this command, as described above. I am curious why CMake doesn't emit error for your case, when you use POST_BUILD without TARGET.