How to deploy app remotely via ninja build system using qtcreator - cmake

I want to deploy my qt app to a remote Linux device. I use qtcreator, cmake, and the ninja build system. But when I want to debug my app remotely via ssh, I got following error:
ninja: error: unknown target 'install'
15:56:22: The process "/usr/bin/cmake" exited with code 1.

Read Deploying CMake Projects to Embedded Linux Devices. Depending on that you can just
Add following lines to your CMakeLists.txt:
file(WRITE "${CMAKE_SOURCE_DIR}/QtCreatorDeployment.txt" "<deployment/prefix>\n")
macro(add_deployment_file SRC DEST)
file(RELATIVE_PATH path ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
file(APPEND "${CMAKE_SOURCE_DIR}/QtCreatorDeployment.txt" "${path}/${SRC}:${DEST}\n")
endmacro()
macro(add_deployment_directory SRC DEST)
file(GLOB_RECURSE files RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${SRC}/*")
foreach(filename ${files})
get_filename_component(path ${filename} PATH)
add_deployment_file("${filename}" "${DEST}/${path}")
endforeach(filename)
endmacro()
add_deployment_file(${CMAKE_BINARY_DIR}/${PROJECT_NAME} /path/to/remote/app)
From QtCreator go to Projects/Run and just delete Install into temporary host directory step in Deployment.

Related

Setting up a cmake project properly with thirdparty

I am trying to get better on CMake. Currently I try to build a toy example that is using OpenCV that I have built from source and installed in a directory called thirdparty.
I can run build
cmake ..
cmake --build .
cmake --install . --prefix ../tmp
In build I can run ./app/TestOpenCV and get a 3x4 zero matrix as output.
If I run ../tmp/bin/TestOpenCV I get
Reason: tried: '/usr/local/lib/libopencv_gapi.406.dylib' (no such file), '/usr/lib/libopencv_gapi.406.dylib' (no such file)
It appears that the linking is not working appropriately when I install the binary. I.e. it searching for the libraries in the wrong location. How can I make this work?
I have the following structure
TestCMake
CMakeLists.txt
app
TestOpenCV.cpp
CMakeLists.txt
thirdparty
installdir
opencv_mac
bin
include
lib
share
TopLevel CMakeLists.txt
cmake_minimum_required(VERSION 3.24)
project(Tutorial VERSION 1.0)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
find_package(OpenCV REQUIRED PATHS "thirdparty/installdir/opencv_mac/lib/cmake/opencv4/" NO_DEFAULT_PATH)
include_directories(SYSTEM ${OpenCV_INCLUDE_DIRS})
add_subdirectory(app)
App level CMakeLists
add_executable(TestOpenCV TestOpenCV.cpp)
target_link_libraries(TestOpenCV ${OpenCV_LIBS})
install(TARGETS TestOpenCV
DESTINATION bin)
How can I make the binary work after installing it?

Generate script during build with cmake

I have a cmake project with a single source file called main.c. I want to additionally provide a wrapper script which calls main with specific parameters.
My CMakeLists.txt looks as follows:
cmake_minimum_required(VERSION 3.1...3.16)
file(WRITE ${CMAKE_BINARY_DIR}/wrapper "#!/usr/bin/env bash\n")
file(APPEND ${CMAKE_BINARY_DIR}/wrapper "./main options\n")
add_executable(main main.c)
add_custom_target(wrapper_target
ALL DEPENDS wrapper)
add_custom_target(main_target
ALL DEPENDS main wrapper_target)
add_dependencies(main wrapper_target)
install(
TARGETS main
RUNTIME DESTINATION bin/)
install(
PROGRAMS wrapper
DESTINATION bin/)
If I run cmake --install ., the script wrapper is installed together with the binary main. Running cmake --build . produces the script wrapper, but it is not marked as executable (on Linux).
How can I tell cmake to also generate wrapper during build and mark it as executable?
Note: I need this for an automated build system which runs build and not install, and expects a specific file to be available on build.
Try:
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/wrapper.tmp
"#!/usr/bin/env bash
# Note that './main' is relative from whatever directory you are in
# Use just main assuming the install prefix is in your bath
# Or use $<TARGET_FILE:main>
# Or maybe ${CMAKE_INSTALL_PREFIX}/bin/main
./main options
")
# add execute permissions
file(
COPY ${CMAKE_CURRENT_BINARY_DIR}/wrapper.tmp
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
)
# Rename the file
file(RENAME
${CMAKE_CURRENT_BINARY_DIR}/wrapper.tmp
${CMAKE_CURRENT_BINARY_DIR}/wrapper
)
How can I tell cmake to also generate wrapper during build and mark it as executable?
file( is a in a cmake script - it is executed during configuration phase, when cmake is executed. To generate the file during build use add_custom_command, the most "portable" way in cmake sense would be to run a cmake script inside add_custom_command:
add_custom_command
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/wrapper
COMMAND $(CMAKE_COMMAND)
-D CMAKE_CURRENT_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}
-P ${CMAKE_CURRENT_SOURCE_DIR}/the_cmake_script.cmake
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/the_cmake_script.cmake
COMMAND Generating wrapper script...
VERBATIM
)
then inside the_cmake_script.cmake you could do the script above - add_custom_command will execute the command cmake -P <the script> during build of you project. That way you can DEPEND properly on the wrapper script.
CMake 3.20 added support for FILE_PERMISSIONS attribute to the FILE command. So one could simply:
FILE(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/wrapper
CONTENT
"#!/usr/bin/env bash
./main options
"
FILE_PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ)

Trying to configure CMake tool chain on Ubuntu

The software will eventually run on an embedded Linux platform. To start, we wrote a library, with all C files in the same folder, and C++ files in a test folder under it.
MyLib
a.c
b.c
MyLib/test
test.cpp
This works on Windows 10, using CMake, Ninja and CLang plus doctest as a test framework. All of these tools are installed under vcpkg.
I am now trying to get everything configured and running on Ubuntu 16.04. All of the tools and source code have been retrieved from our repository. I have tried to build the library and test with Qt, cmake-gui and the command line without success.
Using CMake-gui, after browsing to the source and destination, clicking the Configure button causes the error
CMake Error: CMake was unable to find a build program corresponding to "Ninja".
CMAKE_MAKE_PROGRAM was not set.
The ninja program is in ~/../vcpkg/downloads/tools/ninja-1.8.2-linux/ folder.
I had different errors when trying to build from the command line.
Are there any examples of configurations that work with controlled tools instead of those in the environment?
Edit: added
CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
project(PSOC_LIB)
option(BUILD_TESTS "bulid tests project" OFF)
set(psoc_lib_VERSION_MAJOR 0)
set(psoc_lib_VERSION_MINOR 1)
set(psoc_lib_VERSION_PATCH 0)
set(psoc_lib_VERSION "${psoc_lib_VERSION_MAJOR}.${psoc_lib_VERSION_MINOR}.${psoc_lib_VERSION_PATCH}")
set(PROJ_NAME "\"PSOC Library\"") # PROJECT_NAME is a predefined variable
set(PROJECT_DESCRIPTION "\"Crossplatform library for products\"")
configure_file(include/psoc/config.h.in
${CMAKE_BINARY_DIR}/include/psoc/config.h
)
set(SOURCES
# 5 *.c files
)
add_library(PSOC_LIB ${SOURCES})
target_include_directories(PSOC_LIB PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_compile_definitions(PSOC_LIB PRIVATE _CRT_SECURE_NO_WARNINGS=1)
if (BUILD_TESTS)
include(CTest)
enable_testing()
add_subdirectory(test)
endif (BUILD_TESTS)
test/CmakeLists.txt
cmake_minimum_required(VERSION 3.10)
set(TEST_SOURCES
test.cpp
)
find_package(doctest CONFIG REQUIRED)
add_executable(test_runner test_runner.cpp ${TEST_SOURCES})
target_compile_definitions(test_runner PRIVATE _SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING) #silence warnings about allocator<void> deprecation
target_compile_definitions(test_runner PRIVATE _WIN32_WINNT=0x0601) #target windows 7
target_link_libraries(test_runner PSOC_LIB doctest::doctest)
add_test(all_tests test_runner)
Under Windows, the files in the test folder are build even when BUILD_TESTS is OFF. Under Linux, the test and Testing folders are created only when BUILD_TESTS is ON.
I created a shell script that builds an executable test file.
#!/bin/bash
# Build a debug version of the PSOC_LIB and related tests
mkdir build
cd build
../../../vcpkg_pml/vcpkg/downloads/tools/cmake-3.14.0-linux/cmake-3.14.0-Linux-x86_64/bin/cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -S ../
ninja

How can I run cmake from within cmake?

My project depends on mariadb-connector-c and I'm trying to automate the download, build and link process with cmake.
I currently download the project into a directory, I then try to execute generate ninja files and run them but I cannot run cmake at all:
execute_process(COMMAND "cmake -GNinja ." WORKING_DIRECTORY ${mariadb-connector-c_SOURCE_DIR})
I know this doesn't work because the next step, running ninja, fails:
execute_process(COMMAND "ninja" WORKING_DIRECTORY ${mariadb-connector-c_SOURCE_DIR})
cmake runs fine in CLI, I've tried using the full path to the cmake executable and replacing the dot with the variable with the full directory (which is also a valid variable, if you're wondering.)
How can I tell cmake to run cmake on that external project?
You can organize your project to a top-level CMakeLists.txt build your subprojects as ExternalProject.
This approach requires more work and maintenance of more CMake modules but it has its own benefits. I download Google Test as follows:
# Create download URL derived from version number.
set(GTEST_HOME https://github.com/google/googletest/archive)
set(GTEST_DOWNLOAD_URL ${GTEST_HOME}/release-${GTEST_VERSION}.tar.gz)
unset(GTEST_HOME)
# Download and build the Google Test library and add its properties to the third party arguments.
set(GTEST_ROOT ${THIRDPARTY_INSTALL_PATH}/gtest CACHE INTERNAL "")
ExternalProject_Add(gtest
URL ${GTEST_DOWNLOAD_URL}
CMAKE_ARGS -DBUILD_GTEST=ON -DBUILD_GMOCK=ON -DCMAKE_INSTALL_PREFIX=${GTEST_ROOT}
INSTALL_COMMAND make install
)
list(APPEND GLOBAL_THIRDPARTY_LIB_ARGS "-DGTEST_ROOT:PATH=${GTEST_ROOT}")
unset(GTEST_DOWNLOAD_URL)
unset(GTEST_ROOT)
The code abowe is inside my ExternalGoogleTest.cmake module which is included by CMakeLists.txt of third-party libraries:
set_directory_properties(PROPERTIES EP_BASE ${CMAKE_BINARY_DIR}/ThirdParty)
get_directory_property(THIRDPARTY_BASE_PATH EP_BASE)
set(THIRDPARTY_INSTALL_PATH ${THIRDPARTY_BASE_PATH}/Install)
set(GTEST_VERSION 1.8.0)
include(ExternalProject)
include(ExternalGoogleTest)
Your own project which depends on an external library will need a CMake module to build it as ExternalProject too. It can looks like:
ExternalProject_Add(my_project
DEPENDS gtest whatever
SOURCE_DIR ${CMAKE_SOURCE_DIR}/lib
CMAKE_ARGS
${GLOBAL_DEFAULT_ARGS}
${GLOBAL_THIRDPARTY_LIB_ARGS}
-DCMAKE_INSTALL_PREFIX=${DESIRED_INSTALL_PATH}/my_project
BUILD_COMMAND make
)
You can found more tips about this pattern here.

error while working with Makefile project

I am trying to debug my Makefile based project which I have imported in CLion. I created a simple CMake file as below
cmake_minimum_required(VERSION 2.8.4)
project(Project1)
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ")
add_custom_target(myProject COMMAND make -j4 DEBUG=1
CLION_EXE_DIR=${PACKAGE_DIR})
CMake tool shows me error: CMake executable not specified. I tried adding add_executable(myProject ${SOURCE_FILES}) with correct source files, but still same error.
Where as on Edit Configurations page, I cannot select any Configuration. The drop down for Configuration is empty. At the bottom I get error Error: Configuration is not specified..
When I try to debug the program, I get a warning message Configuration is still incorrect. Do you want to edit it again? I click on Continue Anyway, which compiles the program as I expect and it generates the correct executable file as well. But it cannot run the executable because of the errors in the Configurations.
I assume "CMake executable" refers to the location of the executable cmake which is called to configure your project. Probably you have to search for a setting in CLion where you can define /usr/bin/cmake or whereever your cmake resides.
This solved the problem for me (Ubuntu):
sudo apt-get install cmake