TL;DR: Why moving stuff around from the CMakeLists.txt to a dedicated toolchain file plays a role for find_package?
Trying to cross-compile with cmake and compile/link against pthread, I have the following dummy source file and CMakeLists.txt which work as expected together:
main.cc
#include <iostream>
#include <bits/c++config.h> // needed in the real world
int main()
{
std::cout << "Hello World !\n";
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.0.0)
project(test VERSION 0.0.1)
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_CXX_COMPILER_TARGET arm-linux-gnueabihf)
add_compile_options(-mtune=cortex-a9)
add_compile_definitions(_ARM_GCC_)
# Looking for cross compiler includes; maybe looking for rootfs-like stuff would be better
file(GLOB cross_includes LIST_DIRECTORIES true "/usr/arm-linux-gnueabihf/include/c++/*/arm-linux-gnueabihf/")
include_directories(SYSTEM ${cross_includes})
include_directories(SYSTEM /usr/arm-linux-gnueabihf/include)
find_package(Threads REQUIRED) # Not strictly necessary in this example but needed in the real world
add_executable(test main.cc)
Test:
$> rm -rf build/ && cmake -B build/ && make VERBOSE=1 -C build/
-- The C compiler identification is Clang 11.0.1
-- The CXX compiler identification is Clang 11.0.1
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/clang - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/clang++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Configuring done
-- Generating done
-- Build files have been written to: /home/jp/sandbox/so/cmake/build
make: Entering directory '/home/jp/sandbox/so/cmake/build'
/usr/bin/cmake -S/home/jp/sandbox/so/cmake -B/home/jp/sandbox/so/cmake/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /home/jp/sandbox/so/cmake/build/CMakeFiles /home/jp/sandbox/so/cmake/build//CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/home/jp/sandbox/so/cmake/build'
make -f CMakeFiles/test.dir/build.make CMakeFiles/test.dir/depend
make[2]: Entering directory '/home/jp/sandbox/so/cmake/build'
cd /home/jp/sandbox/so/cmake/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/jp/sandbox/so/cmake /home/jp/sandbox/so/cmake /home/jp/sandbox/so/cmake/build /home/jp/sandbox/so/cmake/build /home/jp/sandbox/so/cmake/build/CMakeFiles/test.dir/DependInfo.cmake --color=
Dependee "/home/jp/sandbox/so/cmake/build/CMakeFiles/test.dir/DependInfo.cmake" is newer than depender "/home/jp/sandbox/so/cmake/build/CMakeFiles/test.dir/depend.internal".
Dependee "/home/jp/sandbox/so/cmake/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/home/jp/sandbox/so/cmake/build/CMakeFiles/test.dir/depend.internal".
Scanning dependencies of target test
make[2]: Leaving directory '/home/jp/sandbox/so/cmake/build'
make -f CMakeFiles/test.dir/build.make CMakeFiles/test.dir/build
make[2]: Entering directory '/home/jp/sandbox/so/cmake/build'
[ 50%] Building CXX object CMakeFiles/test.dir/main.cc.o
/usr/bin/clang++ --target=arm-linux-gnueabihf -D_ARM_GCC_ -isystem /usr/arm-linux-gnueabihf/include/c++/10/arm-linux-gnueabihf -isystem /usr/arm-linux-gnueabihf/include -g -mtune=cortex-a9 -std=c++17 -o CMakeFiles/test.dir/main.cc.o -c /home/jp/sandbox/so/cmake/main.cc
[100%] Linking CXX executable test
/usr/bin/cmake -E cmake_link_script CMakeFiles/test.dir/link.txt --verbose=1
/usr/bin/clang++ --target=arm-linux-gnueabihf -g -rdynamic CMakeFiles/test.dir/main.cc.o -o test
make[2]: Leaving directory '/home/jp/sandbox/so/cmake/build'
[100%] Built target test
make[1]: Leaving directory '/home/jp/sandbox/so/cmake/build'
/usr/bin/cmake -E cmake_progress_start /home/jp/sandbox/so/cmake/build/CMakeFiles 0
make: Leaving directory '/home/jp/sandbox/so/cmake/build'
So far, everything works fine.
Now, the tricky part: I'd like to put the cross-compilation specific stuff in a toolchain.cmake file
toolchain.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_CXX_COMPILER_TARGET arm-linux-gnueabihf)
add_compile_options(-mtune=cortex-a9)
add_compile_definitions(_ARM_GCC_)
# Looking for cross compiler includes; maybe looking for rootfs-like stuff would be better
file(GLOB cross_includes LIST_DIRECTORIES true "/usr/arm-linux-gnueabihf/include/c++/*/arm-linux-gnueabihf/")
include_directories(SYSTEM ${cross_includes})
include_directories(SYSTEM /usr/arm-linux-gnueabihf/include)
new CMakeLists.txt
cmake_minimum_required(VERSION 3.0.0)
project(test VERSION 0.0.1)
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
find_package(Threads REQUIRED) # Not strictly necessary in this example but needed in the real world
add_executable(test main.cc)
Test:
$> rm -rf build/ && cmake -B build/ -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake && make VERBOSE=1 -C build/
-- The C compiler identification is Clang 11.0.1
-- The CXX compiler identification is Clang 11.0.1
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/clang - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/clang++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Looking for pthread.h
-- Looking for pthread.h - not found
CMake Error at /usr/share/cmake-3.18/Modules/FindPackageHandleStandardArgs.cmake:165 (message):
Could NOT find Threads (missing: Threads_FOUND)
Call Stack (most recent call first):
/usr/share/cmake-3.18/Modules/FindPackageHandleStandardArgs.cmake:458 (_FPHSA_FAILURE_MESSAGE)
/usr/share/cmake-3.18/Modules/FindThreads.cmake:234 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
CMakeLists.txt:11 (find_package)
-- Configuring incomplete, errors occurred!
See also "/home/jp/sandbox/so/cmake/build/CMakeFiles/CMakeOutput.log".
See also "/home/jp/sandbox/so/cmake/build/CMakeFiles/CMakeError.log".
Actually, cmake finds pthread.h but clang cannot compile it (wrong floating point abi used; stubs-hard.h should be included)
build/CMakeFiles/CMakeError.log
Determining if the include file pthread.h exists failed with the following output:
Change Dir: /home/jp/sandbox/so/cmake/build/CMakeFiles/CMakeTmp
Run Build Command(s):/usr/bin/gmake cmTC_76e89/fast && /usr/bin/gmake -f CMakeFiles/cmTC_76e89.dir/build.make CMakeFiles/cmTC_76e89.dir/build
gmake[1]: Entering directory '/home/jp/sandbox/so/cmake/build/CMakeFiles/CMakeTmp'
Building C object CMakeFiles/cmTC_76e89.dir/CheckIncludeFile.c.o
/usr/bin/clang -D_ARM_GCC_ -isystem /usr/arm-linux-gnueabihf/include/c++/10/arm-linux-gnueabihf -isystem /usr/arm-linux-gnueabihf/include/gnu -isystem /usr/arm-linux-gnueabihf/include -mtune=cortex-a9 -o CMakeFiles/cmTC_76e89.dir/CheckIncludeFile.c.o -c /home/jp/sandbox/so/cmake/build/CMakeFiles/CMakeTmp/CheckIncludeFile.c
In file included from /home/jp/sandbox/so/cmake/build/CMakeFiles/CMakeTmp/CheckIncludeFile.c:1:
In file included from /usr/arm-linux-gnueabihf/include/pthread.h:21:
In file included from /usr/arm-linux-gnueabihf/include/features.h:485:
/usr/arm-linux-gnueabihf/include/gnu/stubs.h:7:11: fatal error: 'gnu/stubs-soft.h' file not found
# include <gnu/stubs-soft.h>
^~~~~~~~~~~~~~~~~~
1 error generated.
gmake[1]: *** [CMakeFiles/cmTC_76e89.dir/build.make:85: CMakeFiles/cmTC_76e89.dir/CheckIncludeFile.c.o] Error 1
gmake[1]: Leaving directory '/home/jp/sandbox/so/cmake/build/CMakeFiles/CMakeTmp'
gmake: *** [Makefile:140: cmTC_76e89/fast] Error 2
Some more Info:
I made sure the toolchain.cmake is considered (triggered a parse error to check)
$> cat toolchain.cmake CMakeLists.txt
produces the same output as the "original" CMakeLists.txt
pthread.h can be found on my System at the following locations:
$> find /usr/ -name pthread.h
/usr/arm-linux-gnueabi/include/pthread.h
/usr/arm-linux-gnueabihf/include/pthread.h
/usr/include/newlib/pthread.h /usr/include/pthread.h
As #Tsyvarev pointed out, the CMakeError.log contained useful information (the question was edited with its content).
The issue:
cmake finds pthread.h but clang cannot compile it
...
/usr/arm-linux-gnueabihf/include/gnu/stubs.h:7:11: fatal error: 'gnu/stubs-soft.h' file not found
...
The clang invocation is interesting because of "/usr/bin/clang" (expected clang++) and no -target flag used
The solution:
Tell cmake to also use a specific -target flag for C cross-compilers supoorting it:
Add the following in target.cmake
set(CMAKE_C_COMPILER_TARGET arm-linux-gnueabihf)
(Same target as CMAKE_CXX_COMPILER_TARGET)
Let's say I have a library A and a project B which uses A.
project(libA)
function(calledWhenLink target)
message(STATUS Hi ${target}) # Should print "Hi exeB"
endfunction()
add_library(libA INTERFACE)
project(exeB)
find_package(A REQUIRED)
target_link_library(exeB libA)
Is it possible to automatically call calledWhenLink() when the executable links to the library ?
Reasoning: As said in a comment, the original problem is that VTK needs to call CMake vtk_module_autoinit. My library uses VTK, and it seems better for all the samples to automatically call this when linked to the lib instead of copy paste the code in each CMakeLists. The problem is that vtk_module_autoinit is not working when called with the lib target instead ot the exe in my tests.
Yes, it is possible to run arbitrary CMake code at build time. However, it is not at all clear what you're really trying to do, so this might not be a good approach.
Here's a minimal example:
cmake_minimum_required(VERSION 3.21)
project(example)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post-link.cmake" [[
message(STATUS "Hi ${target}")
]])
add_executable(exeB main.cpp)
add_custom_command(
TARGET exeB POST_BUILD
COMMAND "${CMAKE_COMMAND}"
-Dtarget=exeB
-P "${CMAKE_CURRENT_BINARY_DIR}/post-link.cmake"
)
Test interaction:
alex#alex-ubuntu:~/test$ cmake -G Ninja -S . -B build
-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/alex/test/build
alex#alex-ubuntu:~/test$ cmake --build build/ --verbose
[1/2] /usr/bin/c++ -MD -MT CMakeFiles/exeB.dir/main.cpp.o -MF CMakeFiles/exeB.dir/main.cpp.o.d -o CMakeFiles/exeB.dir/main.cpp.o -c /home/alex/test/main.cpp
[2/2] : && /usr/bin/c++ CMakeFiles/exeB.dir/main.cpp.o -o exeB && cd /home/alex/test/build && /usr/bin/cmake -Dtarget=exeB -P /home/alex/test/build/post-link.cmake
-- Hi exeB
Similar questions already exist but I haven't found an answer that works.
I need to build a wxWidgets project in Windows using MinGW, I would like to use the cmake command from the command line (I installed mingw, cmake and bash using chocolatey)
I would like to avoid compiling wxWidgets so I am using the pre-built binaries MinGW-w64 10.2 (Headers + Dev x64 + Release x64), I unpack them to C:\wxWidgets-3.1.5
I've tried a number of combinations of arguments for cmake but haven't found one that works on the first run, I say first run because I've found one that works on the second:
cmake .. -G "MinGW Makefiles" \
-DwxWidgets_ROOT_DIR=/c/wxWidgets-3.1.5/ \
-DwxWidgets_LIB_DIR=/c/wxWidgets-3.1.5/lib/gcc1020_x64_dll/
I am not a cmake expert but I imagine that by specifying these arguments in the first run they are cached and in the second run they are used, bypassing the search.
What I would like to know is what arguments I have to give to get them to be found correctly, _CONFIGURATION, _ROOT_DIR, _LIBRARIES, _INCLUDE_DIRS don't seem to have any effect.
↓ edit ↓
CMakelists.txt:
cmake_minimum_required(VERSION 3.18)
project(Test)
set(wxWidgets_USE_LIBS)
find_package(wxWidgets REQUIRED)
if(wxWidgets_FOUND)
include(${wxWidgets_USE_FILE})
add_executable(MyTest WIN32 main.cpp)
target_link_libraries(MyTest ${wxWidgets_LIBRARIES})
else(wxWidgets_FOUND)
message("wxWidgets not found!")
endif(wxWidgets_FOUND)
command line used:
cmake .. -G "MinGW Makefiles" -DwxWidgets_ROOT_DIR=/c/wxWidgets-3.1.5/ -DwxWidgets_LIB_DIR=/c/wxWidgets-3.1.5/lib/gcc1020_x64_dll/ -DwxWidgets_wxrc_EXECUTABLE=/c/wxWidgets-3.1.5/lib/gcc1020_x64_dll/wxrc.exe -DCMAKE_BUILD_TYPE=Release -DwxWidgets_LIBRARIES=/c/wxWidgets-3.1.5/lib/gcc1020_x64_dll/ -DwxWidgets_INCLUDE_DIRS=/c/wxWidgets-3.1.5/include/
first run:
-- The C compiler identification is GNU 10.2.0
-- The CXX compiler identification is GNU 10.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/ProgramData/chocolatey/bin/gcc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/ProgramData/chocolatey/bin/g++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Could NOT find wxWidgets (missing: wxWidgets_LIBRARIES wxWidgets_INCLUDE_DIRS core base)
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/Alex/Documents/Progetti/wx-test/build
wxWidgets not found!
second run:
-- Found wxWidgets: debug;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxmsw31ud_core.a;optimized;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxmsw31u_core.a;debug;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxbase31ud.a;optimized;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxbase31u.a;debug;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxbase31ud_net.a;optimized;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxbase31u_net.a;debug;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxpngd.a;optimized;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxpng.a;debug;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxtiffd.a;optimized;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxtiff.a;debug;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxjpegd.a;optimized;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxjpeg.a;debug;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxzlibd.a;optimized;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxzlib.a;debug;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxregexud.a;optimized;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxregexu.a;debug;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxexpatd.a;optimized;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxexpat.a;winmm;comctl32;uuid;oleacc;uxtheme;rpcrt4;shlwapi;version;wsock32 (found version "3.1.5") found components: core base net png tiff jpeg zlib regex expat
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/Alex/Documents/Progetti/wx-test/build
if I use find_package(wxWidgets REQUIRED):
CMake Error at C:/Program Files/CMake/share/cmake-3.21/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
Could NOT find wxWidgets (missing: wxWidgets_LIBRARIES
wxWidgets_INCLUDE_DIRS)
Call Stack (most recent call first):
C:/Program Files/CMake/share/cmake-3.21/Modules/FindPackageHandleStandardArgs.cmake:594 (_FPHSA_FAILURE_MESSAGE)
C:/Program Files/CMake/share/cmake-3.21/Modules/FindwxWidgets.cmake:1025 (find_package_handle_standard_args)
CMakeLists.txt:24 (find_package)
Thanks to Process Monitor I noticed that FindwxWidgets.cmake looks for libraries in gcc_dll/ (not gcc2010_x64_dll/), once the directory was renamed cmake -G "MinGW Makefiles" -DwxWidgets_ROOT_DIR=/c/wxWidgets-3.1.5 was enough to find the directory on the first run.
I am new to Cmake and Gtest. I have a problem with in CMake
find_package(GMock REQUIRED)
and
target_link_libraries(runtest ${GMOCK_BOTH_LIBRARIES} pthread).
When I build the project, CMake is unable find the GMock packages.
But when I mentioned the absolute paths of library, it is working fine.
For example:
set(GMOCK_INCLUDE_DIRS /usr/local/include/gmock)
set(GMOCK_BOTH_LIBRARIES /usr/local/lib/libgmock.a /usr/local/lib/libgmock_main.a /usr/local/lib/libgtest.a /usr/local/lib/libgtest_main.a)
Now the problem is my Supervisor recommended me to find the solution to run the code using find packages only. After doing some research, I came to know that FindGMock.cmake file is missing from the Cmake modules. I added it and run code again with find_package(), but still it is not working.
Errors are undefined references to functionalities of Gmock and Gtest.
For instance :
undefined reference to `testing::Message::Message()'.
undefined reference to testing::internal::GetBoolAssertionFailureMessage.
undefined reference totesting::internal::AssertHelper::~AssertHelper()'
Like this there too many errors.
Could anyone please explain me, how to make CMake to find the GMock packages automatically?
Here's a step-by-step example of building and linking to GMock from a CMake project on Linux from scratch. Steps 0-4 cover building and installing GMock while steps 5 and beyond address the question.
These steps are fairly generic and will work with little modification for any project that provides its own CMake package.
Step 0: Create a working directory
From my home folder, I created a blank directory called test:
alex:~$ mkdir test
alex:~$ cd test
alex:~/test$ ls
Step 1: Download GMock
GMock is included in the Google Test repository, so we clone that repository.
alex:~/test$ git clone https://github.com/google/googletest
Cloning into 'googletest'...
remote: Enumerating objects: 24427, done.
remote: Counting objects: 100% (92/92), done.
remote: Compressing objects: 100% (45/45), done.
remote: Total 24427 (delta 44), reused 72 (delta 38), pack-reused 24335
Receiving objects: 100% (24427/24427), 10.32 MiB | 2.68 MiB/s, done.
Resolving deltas: 100% (18062/18062), done.
Step 2: Configure GMock
We'll use the following command to build the googletest repository; GMock is included by default.
$ cmake -S googletest/ -B _build/googletest -DCMAKE_BUILD_TYPE=RelWithDebInfo
The -S flag sets the source directory to the root of the Google Test repository we just cloned. This tells CMake which project it's building. The -B flag sets the binary directory to ~/test/_build/googletest, which is where CMake will store intermediate build outputs before they are installed. This should always be distinct from the source directory. Finally, since we are using a single-configuration generator (Make is the default on Linux), we must specify the build type at this time. I have chosen RelWithDebInfo to keep debugging easy, but also to enable optimizations.
In general, you should always build your project with in the same configuration as its dependencies, so we'll use RelWithDebInfo again later.
For more detail on how to configure generic CMake projects, I'll refer you to this question/answer: How do I build a CMake project?
Finally, here's the output of running the command:
alex:~/test$ cmake -S googletest/ -B _build/googletest -DCMAKE_BUILD_TYPE=RelWithDebInfo
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found Python: /usr/bin/python3.10 (found version "3.10.4") found components: Interpreter
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Configuring done
-- Generating done
-- Build files have been written to: /home/alex/test/_build/googletest
Step 3: Build GMock
Now we'll go ahead and run the build. The following command will work with any single-config generator:
alex:~/test$ cmake --build _build/googletest/
[ 12%] Building CXX object googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o
[ 25%] Linking CXX static library ../lib/libgtest.a
[ 25%] Built target gtest
[ 37%] Building CXX object googlemock/CMakeFiles/gmock.dir/src/gmock-all.cc.o
[ 50%] Linking CXX static library ../lib/libgmock.a
[ 50%] Built target gmock
[ 62%] Building CXX object googlemock/CMakeFiles/gmock_main.dir/src/gmock_main.cc.o
[ 75%] Linking CXX static library ../lib/libgmock_main.a
[ 75%] Built target gmock_main
[ 87%] Building CXX object googletest/CMakeFiles/gtest_main.dir/src/gtest_main.cc.o
[100%] Linking CXX static library ../lib/libgtest_main.a
[100%] Built target gtest_main
The build should complete relatively quickly.
Step 4: Installing GMock
At this point, you could run sudo cmake --install _build/googletest/ to install it globally to /usr/local, but I wouldn't recommend this. It's much better to keep a frequently updated dependency like Google Test/GMock tied to the project that's using it.
Instead, we will install it to a project-local prefix, like so:
alex:~/test$ cmake --install _build/googletest/ --prefix _local
-- Install configuration: "RelWithDebInfo"
-- Installing: /home/alex/test/_local/include
-- Installing: /home/alex/test/_local/include/gmock
-- Installing: /home/alex/test/_local/include/gmock/gmock-matchers.h
-- Installing: /home/alex/test/_local/include/gmock/gmock-function-mocker.h
-- Installing: /home/alex/test/_local/include/gmock/internal
-- Installing: /home/alex/test/_local/include/gmock/internal/gmock-pp.h
-- Installing: /home/alex/test/_local/include/gmock/internal/gmock-internal-utils.h
-- Installing: /home/alex/test/_local/include/gmock/internal/gmock-port.h
-- Installing: /home/alex/test/_local/include/gmock/internal/custom
-- Installing: /home/alex/test/_local/include/gmock/internal/custom/gmock-port.h
-- Installing: /home/alex/test/_local/include/gmock/internal/custom/gmock-matchers.h
-- Installing: /home/alex/test/_local/include/gmock/internal/custom/gmock-generated-actions.h
-- Installing: /home/alex/test/_local/include/gmock/internal/custom/README.md
-- Installing: /home/alex/test/_local/include/gmock/gmock-more-actions.h
-- Installing: /home/alex/test/_local/include/gmock/gmock-more-matchers.h
-- Installing: /home/alex/test/_local/include/gmock/gmock-nice-strict.h
-- Installing: /home/alex/test/_local/include/gmock/gmock.h
-- Installing: /home/alex/test/_local/include/gmock/gmock-cardinalities.h
-- Installing: /home/alex/test/_local/include/gmock/gmock-spec-builders.h
-- Installing: /home/alex/test/_local/include/gmock/gmock-actions.h
-- Installing: /home/alex/test/_local/lib/libgmock.a
-- Installing: /home/alex/test/_local/lib/libgmock_main.a
-- Installing: /home/alex/test/_local/lib/pkgconfig/gmock.pc
-- Installing: /home/alex/test/_local/lib/pkgconfig/gmock_main.pc
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestTargets.cmake
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestTargets-relwithdebinfo.cmake
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestConfigVersion.cmake
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestConfig.cmake
-- Up-to-date: /home/alex/test/_local/include
-- Installing: /home/alex/test/_local/include/gtest
-- Installing: /home/alex/test/_local/include/gtest/gtest-param-test.h
-- Installing: /home/alex/test/_local/include/gtest/internal
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-port-arch.h
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-string.h
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-death-test-internal.h
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-type-util.h
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-port.h
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-internal.h
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-param-util.h
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-filepath.h
-- Installing: /home/alex/test/_local/include/gtest/internal/custom
-- Installing: /home/alex/test/_local/include/gtest/internal/custom/README.md
-- Installing: /home/alex/test/_local/include/gtest/internal/custom/gtest.h
-- Installing: /home/alex/test/_local/include/gtest/internal/custom/gtest-port.h
-- Installing: /home/alex/test/_local/include/gtest/internal/custom/gtest-printers.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-matchers.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-death-test.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-spi.h
-- Installing: /home/alex/test/_local/include/gtest/gtest.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-test-part.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-typed-test.h
-- Installing: /home/alex/test/_local/include/gtest/gtest_prod.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-assertion-result.h
-- Installing: /home/alex/test/_local/include/gtest/gtest_pred_impl.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-message.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-printers.h
-- Installing: /home/alex/test/_local/lib/libgtest.a
-- Installing: /home/alex/test/_local/lib/libgtest_main.a
-- Installing: /home/alex/test/_local/lib/pkgconfig/gtest.pc
-- Installing: /home/alex/test/_local/lib/pkgconfig/gtest_main.pc
The --prefix flag tells cmake --install into which directory to install the project. Here, we've chosen a directory named _local in our working directory. The name of this folder is arbitrary. I've chosen this name to mirror the /usr/local prefix naming and to play nicely with a common .gitignore strategy of ignoring top-level directories prefixed with and underscore.
Notice in the command output what's getting installed. Headers, the GTest and GMock static libraries, yes, but also pkg-config files and, most importantly, the CMake package files:
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestTargets.cmake
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestTargets-relwithdebinfo.cmake
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestConfigVersion.cmake
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestConfig.cmake
These are the files that find_package will use (soon) to load GTest into a dependent project. The two standard files are GTestConfig.cmake and GTestConfigVersion.cmake. The first one is the most important, and it's responsible for actually implementing the CMake package. It will ultimately load GTestTargets.cmake and GTestTargets-relwithdebinfo.cmake, which are specific to GTest. Notice also how RelWithDebInfo appears again in the generated file name; that's because config-specific information is stored there. If you want to support multiple configs, you'll need to redo steps 2-4 with a new CMAKE_BUILD_TYPE (e.g. Debug, Release, MinSizeRel)
Step 5: Creating an example project
Let's create a simple example project now that uses GMock. First, we'll create a directory for it:
alex:~/test$ mkdir example
and now we'll go in and create some files:
alex:~/test$ cd example/
alex:~/test/example$ touch CMakeLists.txt main.cpp
Using your favorite text editor, add the following contents to main.cpp:
#include <gmock/gmock.h>
using namespace testing;
struct Example : public Test {};
TEST_F(Example, AlwaysPass) { ASSERT_THAT(0, Eq(0)); }
TEST_F(Example, AlwaysFail) { ASSERT_THAT(0, Eq(1)); }
This is as basic of a "hello world" for GMock as I could come up with. It has one test that always passes and another that always fails (just so we can see the various outputs).
Now we'll write the build script in CMakeLists.txt:
cmake_minimum_required(VERSION 3.23)
project(example)
find_package(GTest REQUIRED)
add_executable(example main.cpp)
target_link_libraries(example PRIVATE GTest::gmock_main)
Once again, this is as simple as can be.
The first two lines are required boilerplate. They must always1 appear as the first two lines of your project, in that order, with nothing before or in between.
The first command, cmake_minimum_required, tells CMake which set of backwards-compatibility policies to enable. It does not put CMake into an emulation mode or anything like that. You must test your build with the version written there because CMake will not stop you from using features that are too new for the declared minimum version.
The second command, project, names your project and kicks off CMake's compiler detection routines.
Next, we tell CMake that this project depends on the GTest package by issuing find_package(GTest REQUIRED). The REQUIRED argument kills the configure step if the package cannot be found. The name GTest is derived from the GTestConfig.cmake file. For any CMake project XYZ, its main package file must be named either XYZConfig.cmake or XYZ-config.cmake.
Finally, we add our test executable example and link it to the target GTest::gmock_main. This target provides a main function in addition to the GMock standard library. If you want to write your own main, then link to GTest::gmock instead.
1. with very few exceptions that are hardly worth mentioning
Step 6: Building and running the example
Now we're finally ready to build and run the example. Let's go back up to our working directory:
alex:~/test/example$ cd ..
alex:~/test$
And now we'll go ahead and configure the build:
alex:~/test$ cmake -S example -B _build/example -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_PREFIX_PATH=$PWD/_local
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found GTest: /home/alex/test/_local/lib/cmake/GTest/GTestConfig.cmake (found version "1.11.0")
-- Configuring done
-- Generating done
-- Build files have been written to: /home/alex/test/_build/example
Note the -DCMAKE_PREFIX_PATH=$PWD/_local flag. That's telling CMake that there are additional libraries and CMake packages in $PWD/_local and so find_package and the other find_* commands should look there. If you didn't pass this flag, you might see an error like this:
CMake Error at /usr/share/cmake-3.23/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
Could NOT find GTest (missing: GTEST_LIBRARY GTEST_INCLUDE_DIR
GTEST_MAIN_LIBRARY)
Call Stack (most recent call first):
/usr/share/cmake-3.23/Modules/FindPackageHandleStandardArgs.cmake:594 (_FPHSA_FAILURE_MESSAGE)
/usr/share/cmake-3.23/Modules/FindGTest.cmake:270 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
CMakeLists.txt:4 (find_package)
-- Configuring incomplete, errors occurred!
See also "/home/alex/test/_build/example/CMakeFiles/CMakeOutput.log".
Now that we're configured, we can build the example:
alex:~/test$ cmake --build _build/example/
[ 50%] Building CXX object CMakeFiles/example.dir/main.cpp.o
[100%] Linking CXX executable example
[100%] Built target example
and then run it:
alex:~/test$ _build/example/example
Running main() from gmock_main.cc
[==========] Running 2 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 2 tests from Example
[ RUN ] Example.AlwaysPass
[ OK ] Example.AlwaysPass (0 ms)
[ RUN ] Example.AlwaysFail
/home/alex/test/example/main.cpp:8: Failure
Value of: 0
Expected: is equal to 1
Actual: 0 (of type int)
[ FAILED ] Example.AlwaysFail (0 ms)
[----------] 2 tests from Example (0 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test suite ran. (0 ms total)
[ PASSED ] 1 test.
[ FAILED ] 1 test, listed below:
[ FAILED ] Example.AlwaysFail
1 FAILED TEST
As you can see, our passing test passed, and our failing test failed, as expected!
Step 6: CTest integration (optional)
If we want, we can integrate this with CTest for easier running of multiple GMock binaries down the line. Here's the new CMakeLists.txt
cmake_minimum_required(VERSION 3.23)
project(example)
enable_testing() # ------------------------ ADDED 1
find_package(GTest REQUIRED)
include(GoogleTest) # ------------------------ ADDED 2
add_executable(example main.cpp)
target_link_libraries(example PRIVATE GTest::gmock_main)
gtest_discover_tests(example) # ------------------------ ADDED 3
Aside from the three lines marked ADDED, nothing has changed. The first added line simply enables CTest support. The second added line imports CMake's native support for Google Test. Finally, the third line tells CTest that the example executable contains GTest tests.
After making these edits, an incremental build will automatically re-run CMake.
alex:~/test$ cmake --build _build/example/
-- Configuring done
-- Generating done
-- Build files have been written to: /home/alex/test/_build/example
Consolidate compiler generated dependencies of target example
[ 50%] Linking CXX executable example
[100%] Built target example
And now we can use the CTest runner on our build directory:
alex:~/test$ ctest --test-dir _build/example/
Internal ctest changing into directory: /home/alex/test/_build/example
Test project /home/alex/test/_build/example
Start 1: Example.AlwaysPass
1/2 Test #1: Example.AlwaysPass ............... Passed 0.00 sec
Start 2: Example.AlwaysFail
2/2 Test #2: Example.AlwaysFail ...............***Failed 0.00 sec
50% tests passed, 1 tests failed out of 2
Total Test time (real) = 0.00 sec
The following tests FAILED:
2 - Example.AlwaysFail (Failed)
Errors while running CTest
Output from these tests are in: /home/alex/test/_build/example/Testing/Temporary/LastTest.log
Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely.
And once again, we can see that our passing test passed and our failing test failed. Hooray!
I am trying to compile a library with both, C++ and CUDA source files. I am using GNU make with CMake. My compiler of choice is clang, since CUDA only supports gcc up to version 5 and Debian 9 has gcc 6 as its oldest version and I have to use software that is provided by the Debian 9 or 10 repositories.
CMake version is 3.9.0
clang version is 3.8.1
cc and c++ in /usr/bin correctly link to clang and clang++ ẃhich also link to the correct files.
Unfortunately the initial checks of CMake for CUDA fail although everything, as far as I can see, seems to be set up correctly. It looks like the arguments aren't passed correctly to the CUDA compiler.
This is a part of my project's main CMake file:
cmake_minimum_required (VERSION 3.9.0 FATAL_ERROR)
project (dev)
find_package(CUDA REQUIRED)
set(CUDA_HOST_COMPILATION_CPP ON)
set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -Wno-deprecated-gpu-targets -ccbin clang-3.8")
The library's CMake file looks like this:
cmake_minimum_required(VERSION 3.9.0 FATAL_ERROR)
project (libname LANGUAGES CXX CUDA)
file(GLOB SOURCES "*.cu" "*.cpp")
add_library(libname ${SOURCES})
set_target_properties(libname PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
set_target_properties(libname PROPERTIES POSITION_INDEPENDENT_CODE ON)
This is the output of CMake:
-- The C compiler identification is Clang 3.8.1
-- The CXX compiler identification is Clang 3.8.1
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Found CUDA: /usr (found version "8.0")
-- The CUDA compiler identification is unknown
-- Check for working CUDA compiler: /usr/bin/nvcc
-- Check for working CUDA compiler: /usr/bin/nvcc -- broken
The CUDA/nvcc tests of CMake fails with the following errors:
Change Dir: /home/user/projects/hamonIC-linux-experimental/current_state/working_copy/code/build/CMakeFiles/CMakeTmp
Run Build Command:"/usr/bin/make" "cmTC_6d1a9/fast"
/usr/bin/make -f CMakeFiles/cmTC_6d1a9.dir/build.make
CMakeFiles/cmTC_6d1a9.dir/build
make[1]: Entering directory
'/home/user/projects/hamonIC-linux-experimental/current_state/working_copy/code/build/CMakeFiles/CMakeTmp'
Building CUDA object CMakeFiles/cmTC_6d1a9.dir/main.cu.o
/usr/bin/nvcc -x cu -c
/home/user/projects/hamonIC-linux-experimental/current_state/working_copy/code/build/CMakeFiles/CMakeTmp/main.cu
-o CMakeFiles/cmTC_6d1a9.dir/main.cu.o
nvcc warning : The 'compute_20', 'sm_20', and 'sm_21' architectures are
deprecated, and may be removed in a future release (Use
-Wno-deprecated-gpu-targets to suppress warning).
ERROR: No supported gcc/g++ host compiler found, but clang-3.8 is
available.
Use 'nvcc -ccbin clang-3.8' to use that instead.
CMakeFiles/cmTC_6d1a9.dir/build.make:65: recipe for target
'CMakeFiles/cmTC_6d1a9.dir/main.cu.o' failed
make[1]: *** [CMakeFiles/cmTC_6d1a9.dir/main.cu.o] Error 1
make[1]: Leaving directory
'/home/user/projects/hamonIC-linux-experimental/current_state/working_copy/code/build/CMakeFiles/CMakeTmp'
Makefile:126: recipe for target 'cmTC_6d1a9/fast' failed
make: *** [cmTC_6d1a9/fast] Error 2
CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
hic_iplibrary/source/ciccommon/CMakeLists.txt:7 (project)
The CUDA NVCC flags in CMake have to be semicolon delimited and not whitespace delimited.
Change the flags in your CMakeLists.txt to use:
set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS};-Wno-deprecated-gpu-targets;-ccbin=clang-3.8")
and that should allow CMake to pass your flags to NVCC.