I'm debugging a cmake file which fails to find certain packages (using find_package()). What does find_package() actually do when it searches for packages, and can I simulate it with a command line call (without invoking cmake)?
1. What find_package does:
From the documentation of find_package():
CMake searches for a file called Find.cmake in the CMAKE_MODULE_PATH followed by the CMake installation. If the file is found, it is read and processed by CMake.
On Linux, the default scripts usually are located here:
ls /usr/share/cmake*/Modules/Find*.cmake
2. How to use find_package on the command-line:
# cmake --find-package -DNAME=Boost -DCOMPILER_ID=GNU -DLANGUAGE=C -DMODE=EXIST
Boost found
# cmake --find-package -DNAME=Boost -DCOMPILER_ID=GNU -DLANGUAGE=C -DMODE=COMPILE
-I/usr/include
# cmake --find-package -DNAME=Boost -DCOMPILER_ID=GNU -DLANGUAGE=C -DMODE=LINK
-rdynamic
Related
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)
I'm trying to write generic way to run executable resulted after build using CMake's way.
git clone git#github.com:gargamel/ihatesmurfs.git
cmake -E make_directory build
cmake -Sihatesmurfs -Bbuild
cmake --build build
cmake -E chdir build
Now I want to start executable but on *nix, it's like:
./output
and on Windows:
output.exe
Is there a way to escape this with any possible CMake command?
Expanding on my comment a bit, you can modify the CMakeLists.txt file of the project to include add_custom_command. If your CMake creates an executable named HateSmurfs, you can add the custom command to run the executable after compilation completes:
add_executable(HateSmurfs smurfs.cpp)
# Add this piece of code to run the executable after it is built.
add_custom_command(
TARGET HateSmurfs
POST_BUILD
COMMAND HateSmurfs
)
According to add_custom_command documentation:
COMMAND
If COMMAND specifies an executable target name (created by the add_executable() command) it will automatically be replaced by the location of the executable created at build time.
I'm attempting to compile a program using cmake that gives me the following error(s):
CMake Error at /.../3dg.cmake:8 (enable_language):
The CMAKE_CXX_COMPILER:
CC
is not a full path and was not found in the PATH.
Tell CMake where to find the compiler by setting either the environment
variable "CXX" or the CMake cache entry CMAKE_CXX_COMPILER to the full path
to the compiler, or to the compiler name if it is in the PATH.
Call Stack (most recent call first):
CMakeLists.txt:8 (include)
CMake Error at /.../3dg.cmake:8 (enable_language):
The CMAKE_C_COMPILER:
cc
is not a full path and was not found in the PATH.
Tell CMake where to find the compiler by setting either the environment
variable "CC" or the CMake cache entry CMAKE_C_COMPILER to the full path to
the compiler, or to the compiler name if it is in the PATH.
I am setting both of these variables in my cmake file with:
set(CMAKE_C_COMPILER cc)
set(CMAKE_CXX_COMPILER CC)
Moreover, I can confirm that both of them are in my path and at the correct location.
>>which cc
/opt/cray/pe/craype/2.5.14/bin/cc
>>which CC
/opt/cray/pe/craype/2.5.14/bin/CC
And my path includes this directory!
>>echo $PATH
/opt/cray/rca/2.2.18-6.0.7.0_33.3__g2aa4f39.ari/bin:/opt/cray/alps/6.6.43-6.0.7.0_26.4__ga796da3.ari/sbin:/opt/cray/job/2.2.3-6.0.7.0_44.1__g6c4e934.ari/bin:/opt/cray/pe/hdf5/1.10.0.3/bin:/opt/cray/pe/craype/2.5.14/bin:/opt/intel/compilers_and_libraries_2018.1.163/linux/bin/intel64:/usr/common/software/metis/5.1.0/bin:/usr/common/software/darshan/3.1.4/bin:/usr/common/software/altd/2.0/bin:/usr/common/software/bin:/usr/common/mss/bin:/usr/common/nsg/bin:/opt/cray/pe/mpt/7.7.0/gni/bin:/opt/ovis/bin:/opt/ovis/sbin:/usr/syscom/nsg/sbin:/usr/syscom/nsg/bin:/opt/cray/pe/modules/3.2.10.6/bin:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games:/usr/lib/mit/bin:/usr/lib/mit/sbin:/opt/cray/pe/bin:
The cmake file sees the same path as the terminal. I have confirmed that this error goes away if I change my cmake code to:
set(CMAKE_C_COMPILER /opt/cray/pe/craype/2.5.14/bin/cc)
set(CMAKE_CXX_COMPILER /opt/cray/pe/craype/2.5.14/bin/CC)
But this is not a long term fix as the actual location of cc/CC depends on which modules I am using and the updated version of the compilers.
Does anyone know what is going on, and how to force cmake to recognize that these compilers are located in the correct location? Thanks.
Go to download page of glfw and download their source package. Now unzip it and enter into the directory.
Now generate the make file with sudo cmake -G "Unix Makefiles".
Now do sudo make and sudo cmake. The install process should be complete.
For more info take a look at here
I need to force my Cmake to build and link my MPI code with MPICH. My MPICH is installed using the Ubuntu Package manager, in a standard location /usr/lib/mpich/. However, CMake still looks for the OpenMPI libraries, which I do not use. How can I instruct CMake to look for MPICH instead?
Below, you can see the output of some basic diagnostics:
$ whereis openmpi
openmpi:
$ whereis mpich
mpich: /usr/lib/mpich /usr/include/mpich
$ mpicc -v
mpicc for MPICH version 3.2
Below, I also provide the Cmake script and the errors I get from cmake and the mpirun.mpich. My Cmake is 3.5.1 and I run on Ubuntu Xenial 16.04.
cmake_minimum_required(VERSION 3.0)
message (STATUS "Adding mpiService")
find_package(MPI REQUIRED)
set(CMAKE_C_COMPILER mpicc)
set(CMAKE_CXX_COMPILER mpicxx)
set(MPI_GUESS_LIBRARY_NAME MPICH2)
message(STATUS ${MPI_INCLUDE_PATH})
message(STATUS ${MPI_C_LIBRARIES})
#add_definitions(-DOMPI_SKIP_MPICXX)
add_executable(mpiService main.cpp)
set(CMAKE_VERBOSE_MAKEFILE ON)
include_directories(SYSTEM ${MPI_INCLUDE_PATH})
target_link_libraries(
mpiService
PRIVATE
${MPI_C_LIBRARIES}
)
From the Cmake STATUS I get the following output:
/usr/lib/openmpi/include/openmpi/opal/mca/event/libevent2021/libevent/usr/lib/openmpi/include/openmpi/opal/mca/event/libevent2021/libevent/include/usr/lib/openmpi/include/usr/lib/openmpi/include/openmpi
/usr/lib/openmpi/lib/libmpi.so
And when I run the binary I get the following:
ubuntu#node1:~$ mpirun.mpich -np 2 --host node1,node2 mpiService
mpiService: error while loading shared libraries: libmpi.so.12: cannot open shared object file: No such file or directory
mpiService: error while loading shared libraries: libmpi.so.12: cannot open shared object file: No such file or directory
How can I instruct CMake to look for MPICH instead?
According to FindMPI documentation, you may set MPI_<lang>_COMPILER variable to the desired MPI compiler:
Set MPI_<lang>_COMPILER to the MPI wrapper (mpicc, etc.) of your
choice and reconfigure. FindMPI will attempt to determine all the
necessary variables using THAT compiler's compile and link flags.
set(MPI_CXX_COMPILER <path-to-mpich-compiler>)
find_package(MPI REQUIRED)
Alternatively, since CMake version 3.10, variable MPI_EXECUTABLE_SUFFIX can be set instead:
A suffix which is appended to all names that are being looked for. For instance you may set this to .mpich or .openmpi to prefer the one or the other on Debian and its derivatives.
set(MPI_EXECUTABLE_SUFFIX ".mpich")
find_package(MPI REQUIRED)
Herewith my current solution.
find_package(MPI REQUIRED)
# ----------------
# This is the only thing that made it work
# ----------------
set(MPI_C_LIBRARIES "/usr/lib/mpich/lib/libmpich.so")
set(MPI_INCLUDE_PATH "/usr/include/mpich")
# ----------------
add_executable(mpiService main.cpp)
include_directories(SYSTEM ${MPI_INCLUDE_PATH})
target_link_libraries(
mpiService
${MPI_C_LIBRARIES}
)
I personally do not like this solution, as I have to explicitly specify the path. Any other proposed solution was still building with OpenMPI. If I find a better alternative, I will re-post.
I am trying to built a "Hello World" project with Qt 5 and cmake under MinGW.
This is the CMakeLists.txt file (taken from the on-line doc):
project(Qt5_cmake_test)
cmake_minimum_required(VERSION 2.8.11)
set(CMAKE_PREFIX_PATH "C:/Qt/Qt5.1.1/5.1.1/mingw48_32")
# Find includes in corresponding build directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Instruct CMake to run moc automatically when needed.
set(CMAKE_AUTOMOC ON)
# Find the QtWidgets library
find_package(Qt5Widgets)
# Add the source files from the current directory
aux_source_directory(. SRC_LIST)
# Tell CMake to create the executable
add_executable(${PROJECT_NAME} WIN32 ${SRC_LIST})
# Use the Widgets module from Qt5
target_link_libraries(${PROJECT_NAME} Qt5::Widgets)
The source code is the one generated automatically when creating a new project (which produces an empty window).
Configuring from the Windows command prompt with: cmake -G "MinGW Makefiles" ..\Qt5_cmake_test
I get these errors:
CMake Error at C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeMinGWFindMake.cmake:20 (message):
sh.exe was found in your PATH, here:
C:/Program Files (x86)/Git/bin/sh.exe
For MinGW make to work correctly sh.exe must NOT be in your path.
Run cmake from a shell that does not have sh.exe in your PATH.
If you want to use a UNIX shell, then use MSYS Makefiles.
Call Stack (most recent call first):
CMakeLists.txt:8 (project)
CMake Error: Error required internal CMake variable not set, cmake may be not be built correctly.
Missing variable is:
CMAKE_C_COMPILER_ENV_VAR
CMake Error: Error required internal CMake variable not set, cmake may be not be built correctly.
Missing variable is:
CMAKE_C_COMPILER
CMake Error: Could not find cmake module file:C:/Users/pietro.mele/projects/tests/buildSystem_test/Qt5_cmake_test-build/CMakeFiles/2.8.11.2/CMakeCCompiler.cmake
CMake Error: Error required internal CMake variable not set, cmake may be not be built correctly.
Missing variable is:
CMAKE_CXX_COMPILER_ENV_VAR
CMake Error: Error required internal CMake variable not set, cmake may be not be built correctly.
Missing variable is:
CMAKE_CXX_COMPILER
CMake Error: Could not find cmake module file:C:/Users/pietro.mele/projects/tests/buildSystem_test/Qt5_cmake_test-build/CMakeFiles/2.8.11.2/CMakeCXXCompiler.cma
ke
CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage
CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage
-- Configuring incomplete, errors occurred!
So it seems it is not able to find the compiler. Is there a way to let cmake find it on its own, or just giving it the CMAKE_PREFIX_PATH directory?
Do I have to manually specify all those variables in the makefile or as environment variables in Windows?
I tried both from the standard Windows command prompt and from the one provided by Qt, with the same result. Is it OK to build from the Windows command prompt, or should I do it from the MinGW's shell?
Platform:
Qt 5.1
CMake 2.8.11.2
MinGW/GCC 4.8
Windows 7
Get the git path out of your PATH before running cmake.
Here is the magic to do that:
set PATH=%PATH:C:/Program Files (x86)/Git/bin;=%
This CMakeLists.txt file works properly:
project(Qt5_cmake_test)
cmake_minimum_required(VERSION 2.8.11)
set(CMAKE_PREFIX_PATH "C:/Qt/Qt5.1.1/5.1.1/mingw48_32")
# Find includes in corresponding build directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Instruct CMake to run moc automatically when needed.
set(CMAKE_AUTOMOC ON)
# Find the Qt libraries
find_package(Qt5Core REQUIRED)
find_package(Qt5Widgets REQUIRED)
# Add the source files from the current directory
aux_source_directory(. SRC_LIST)
# Tell CMake to create the executable
add_executable(${PROJECT_NAME} WIN32 ${SRC_LIST})
# Use Qt5 modules
target_link_libraries(${PROJECT_NAME}
Qt5::Widgets
Qt5::WinMain)
The changes are:
Added find_package(Qt5Core REQUIRED).
Added Qt5::WinMain to target_link_libraries.
In some of my answer here on SO, I have described. CMake does not like sh.exe.
sh.exe was found in your PATH, here:
C:/Program Files (x86)/Git/bin/sh.exe
Solution : Rename C:/Program Files (x86)/Git/bin/sh.exe shortly.
For example:
C:/Program Files (x86)/Git/bin/shxx.exe
But do not forget when everything is built. rename properly again.