I would like to cmake on the first step of my vsomeip build. However, I get an error where:
GTEST_ROOT is not defined. For building the tests the variable
GTEST_ROOT has to be defined. Tests can not be built.
I am an amateur in this subject, so please bear with me.
This repository depends on GTest as mentioned here in the documentation. The CMake attempts to find the GTest source code locally and build a static library of GTest. So, you should add the GTEST_ROOT directory when calling cmake using the -D definition flag:
cmake -DGTEST_ROOT=/path/to/your/gtest/dir ..
Related
Prologue
I have a preset-based plain CMake project so that I can build and test it with cmake --preset $PRESET && cmake --build --preset $PRESET && ctest --preset $PRESET. Note that it nicely interacts with Microsoft's CMake Tools extension for Visual Studio Code, be it for building, testing, debugging and Intellisense.
Since I want to handle multiple presets in parallel, I set CMakePresets.json's binaryDir property to ${sourceDir}/build/${presetName}/.
Issue
I want to also build this plain CMake project with colcon. colcon build --cmake-args "--preset $PRESET" doesn't work, though, as it produces
WARNING:colcon.colcon_cmake.task.cmake.build:Could not build CMake package 'root_project_name' because the CMake cache has no 'CMAKE_PROJECT_NAME' variable
root_project_name being the argument to CMake's project() command in the top CMakeLists.txt.
How can I resolve this warning and the subsequent build failure?
Straightforward solution
Not setting CMakePresets.json's binaryDir property at all works fine with colcon, but doesn't allow for multiple preset builds in parallel.
Solution with multiple preset builds in parallel
The reason for this behavior is colcon-core's build verb's passing the build base directory (default: build) suffixed by the found package's name (here: root_project_name) to the colcon-cmake extension here.
The solution is to pass the correct build base to colcon (i.e. colcon build --build-base ./build/$PRESET/ --cmake-args "--preset $PRESET") and to adapt your CMakePresets.json's binaryDir property to ${sourceDir}/build/${presetName}/root_project_name/.
Note that this then works with colcon test as well, i.e. colcon test --build-base ./build/$PRESET/ --ctest-args "--preset $PRESET".
When running the follow CMake command, I am receiving an error. I am working with CMake version 3.20.5.
cmake --clean-first ./src/basis_universal/CMakeLists.txt
CMake Error: Unknown argument --clean-first
However, --clean-first appears to be supported.
Just to make it abundantly clear to you... typically there are 2 steps you take in any cmake project... configuration and building.
In the configuration step, CMake looks for the files on your system, the compiler, etc. and prepares everything for building.
The building step of actually turning your code into an executable is a second, separate step.
When you run
cmake --clean-first ./src/basis_universal/CMakeLists.txt
you are just configuring your project. The --clean-first command is not available during configuration.
After configuration, you need to build your project. In that step, you can use the --clean-first option.
I am using cmake version 3.14.0-rc3 to make my codes. When I target any code written in C or C++ in my CMakelist.txt as follows, it works pretty and makes the executable file.
cmake_minimum_required(VERSION 3.3)
PROJECT (HELLO)
ADD_EXECUTABLE(hello hello_world.cpp)
but while I am trying to make this code with Tcl scripts, it fails and I receive the following fatal error:
Fatal error while making a tcl script with cmake
Can anyone help me to overcome this issue? It seems that cmake is not normally able to compile Tcl scripts.
Thank in advance for your kind replies and helps.
Bests,
Daryon
You have to watch out for a different path, e.g., running custom commands or adding custom targets to your CMake project. You seem to confuse the nature of libraries, executables, and external commands in the context of CMake, I am afraid.
I think there should be a way to execute Tcl scripts with CMake as
well.
You might want to attempt the following: In CMakeLists.txt, you define a custom target MyTarget that calls out to a TCLSH executable, if available:
CMAKE_MINIMUM_REQUIRED(VERSION 3.3)
PROJECT (HELLO)
find_program (TCLSH tclsh)
if (TCLSH)
add_custom_target(
MyTarget ALL
COMMAND TCLSH myScript.tcl
)
endif (TCLSH)
(1) find_program and if/endif will make the custom target only available under the condition that an executable called tclsh was found.
(2) myScript.tcl is a Tcl script in your project directory.
(3) Running cmake . && make will call out to effectively to: tclsh myScript.tcl, producing:
$cmake . && make
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/hello
This is a message written by Tcl scripts
Built target MyTarget
This is just to get you started, you will have to read more about adding commands, targets, or executing sub-processes from within CMake.
I am building a project with cmake. The project uses the external library plplot; I have configured cmake to the library and headers, and that is cached in variables ${PLPLOT_LIBRARY}, ${PLPLOT_LIB_PATH} and ${PLPLOT_INCLUDE_PATH}. In the plplot library a function has changed name: plwid -> plwidth and I want to detect that. I have written a small try_compile() test:
try_compile(HAVE_PLWID ${CMAKE_BINARY_DIR} cmake/tests/test_plwid.c)
However this test will always fail, because I have to pass header and library information to the try_compile process. Invoking gcc manually like this:
gcc -I${PLPLOT_INCLUDE_PATH} cmake/tests/test_plwid.c -L${PLPLOT_LIB_PATH} -l${PLPLOT_LIBRARY}
works. However I don understand how to pass the necessary flags to the try_compilecommand: I have tried:
try_compile(HAVE_PLWID ${CMAKE_BINARY_DIR} cmake/tests/test_plwid.c
INCLUDE_DIRECTORIES ${PLPLOT_INCLUDE_PATH}
LINK_DIRECTORIES ${PLPLOT_LIB_PATH}
LINK_LIBRARIES ${PLPLOT_LIBRARY})
Then I just get the cmake configure error:
Attempt at a recursive or nested TRY_COMPILE in directory
/path/to/build
I am quite confident the ${PLPLOT_XXX} variables are correct, at least the rest of the build works fine based on these variables.
Update: If I invoke cmakewith the --debug_trycompile command and go to the build/CMakeFiles/CMakeTmp directory and invoke cmakethere manually as:
cmake . -DINCLUDE_DIRECTORIES=/path/plplot/include -DLINK_DIRECTORIES=/path/to/plplot/lib -DLINK_LIBRARIES=plplotd
The test program will build and link correctly; so it seems the challenge is to pass these options correctly to the try_compile() cmake command invocation?
The LINK_DIRECTORIES and INCLUDE_DIRECTORIES cannot be passed as options to try_compile but have to passed as extra flags with the CMAKE_FLAGS option in the following way:
try_compile(HAVE_PLWID "${CMAKE_BINARY_DIR}/temp" "${CMAKE_SOURCE_DIR}/tests/test_plwid.c"
LINK_LIBRARIES ${PLPLOT_LIBRARY}
CMAKE_FLAGS
"-DINCLUDE_DIRECTORIES=${PLPLOT_INCLUDE_PATH}"
"-DLINK_DIRECTORIES=${PLPLOT_LIB_PATH}")
I was trying to parallelize a Fortran program using MPI. I use CMake to do the build of my program. It was difficult to find support on getting CMake to create a working makefile for Fortran with MPI support on google, but from what I could gather, I added the following commands to my CMakeLists.txt script:
find_package(MPI REQUIRED)
add_definitions(${MPI_Fortran_COMPILE_FLAGS})
include_directories(${MPI_Fortran_INCLUDE_DIRS})
link_directories(${MPI_FortranLIBRARY_DIRS})
This will locate MPI on my system and then set the variables found in the following three commands. In my linking line, I added the MPI libraries variable to the list of the other libraries that my program needed to build.
target_link_libraries(${exe_name} otherlibs ${MPI_FortranLIBRARY_DIRS})
Doing cmake and then make worked to build the program and the program ran; however, when I tried to add more to the source which required me to include the mpif.h include file, my compilation failed due to not being able to find this header file. I also could not use mpi because the compiler cannot find the mpi.mod file in the path.
I inserted "message" commands into my CMakeLists.txt file and printed out the values of the variables that I was using for including and linking. It turns out that the variables, MPI_Fortran_INCLUDE_DIRS and MPI_FortranLIBRARY_DIRS weren't set to anything. A check of the module that CMake is actually using to set these variables (FindMPI.cmake) showed these variables to be non-existent. I changed my CMakeLists.txt file to use the correct variables:
find_package(MPI REQUIRED)
add_definitions(${MPI_Fortran_COMPILE_FLAGS})
include_directories(${MPI_Fortran_INCLUDE_PATH})
link_directories(${MPI_Fortran_LIBRARIES})
target_link_libraries(${exe_name} otherlibs ${MPI_Fortran_LIBRARIES})
Now when I execute make, the compiler could find both mpif.h as well as mpi.mod.
UPDATE:
I want to mention that this solution worked for cmake version 2.8.10.1. When I moved my CMakeLists.txt scripts to a different machine that has cmake version 2.8.4, I get the same error about mpi.mod missing during the link stage. I checked the FindMPI.cmake module and, sure enough, there are no variables that specify the language (i.e. there is no MPI_Fortran_LIBRARIES variable, just a MPI_LIBRARIES variable, and this variable is not getting set to the correct location of the mpi library on that system. So this solution will be dependent on cmake version.
Sounds like you are not using the mpi compiler. That is fine, but you have to add a lot of flags then. There is not really an mpi compiler but a wrapper that sets the flags to be able to use mpi. With cmake I was able to do this by defining the fortran compiler I was going to use BEFORE the call to cmake. It's not a nice solution since you loose portability, but it works. I'm trying to find a better solution and define inside cmake what compiler to use, but have not been able to do so. In other words, this works for me:
FC=mpif90 cmake ../.
make
I was having the same problem as you. Hope this solves the issue. If anybody finds how to define the fortran compiler INSIDE cmake please post it!
as you've already noticed, you misspelled the name of two variables, namely MPI_Fortran_LIBRARIES and MPI_Fortran_LIBRARIES
It is useful also to add:
cmake_minimum_required(VERSION 2.8.10)
at the very beginning of your CMake to be sure that these variables will be defined.