I put the gtest src in to my project folder like below and wish to debug the testcase in VS.
│ CMakeLists.txt
│
├─google test source code
│
├─src
│ │ CMakeLists.txt
│ └─ CObject.h
│
└─UnitTest
TCObject.cpp
Everything is fine, I use the Cmake to generate the VS project file and open it in Visual Studio 2015.The CmakeLists.txt is like below
PROJECT (BVH)
cmake_minimum_required(VERSION 3.00)
SET(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR})
INSTALL(DIRECTORY src/shaders DESTINATION build/bin)
INSTALL(DIRECTORY scene DESTINATION build/bin)
ADD_SUBDIRECTORY(src bin)
################################
# GTest
################################
ADD_SUBDIRECTORY (googletest)
ENABLE_TESTING()
INCLUDE_DIRECTORIES(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
################################
# Unit Tests
################################
# Add test cpp file
INCLUDE_DIRECTORIES($ENV{GLM})
ADD_EXECUTABLE( runUnitTests UnitTest/TCObject.cpp )
# Link test executable against gtest & gtest_main
TARGET_LINK_LIBRARIES(runUnitTests gtest gtest_main )
ADD_TEST( runUnitTests runUnitTests )
And here is my testcase
#include<gtest/gtest.h>
#include"../src/CObject.h"
#include<glm/glm.hpp>
TEST(TestCObject,TestInitial){
CCube *cube=new CCube(glm::vec3(1,2,3),2);
EXPECT_EQ(2,cube->bounds.pMax[0]);
}
Problem 1:I can only run my testcase if I set the gtest's and gtest_main's runtime library to MDd instead of it's own MTd, I don't know if there is any problem in the future
Problem 2:If I choose to set a breakpoint and debug it, the window is just flash and disappear.Only if I change the cmake option BUILD_SHARED_LIBRARIES of gtest and copy the dll file into the place where my executable testfile locate, then I can debug my testcase
But the problem is I must copy the dll file everytime. So I wonder if there's a way to debug in the static libraries (Problem 1) or I can set the target space of gtest to reach to the place where my testfile locate (Problem 2).
Related
I have a project with a structure
├── CMakeLists.txt
├── mzl.c
├── mzl.h
└── tests
├── CMakeLists.txt
├── mzl-communication-test.c
├── mzl-setup-test.c
├── mzl-test-errors.c
└── mzl-test-errors.h
Where the top directory CMakeLists.txt file is
project(mzl)
cmake_minimum_required(VERSION 2.8)
add_subdirectory(tests)
# Enable testing for the project
enable_testing()
# Find zmq
find_library(ZMQ_LIB zmq REQUIRED)
message(STATUS "ZMQ Library: ${ZMQ_LIB}")
# Find threading library
set(CMAKE_THREAD_PREFER_PTHREAD ON)
find_package(Threads REQUIRED)
message(STATUS "Threading Library: ${CMAKE_THREAD_LIBS_INIT}")
# Set include directories for headers
set (
MZL_INCLUDE_DIRS
${CMAKE_SOURCE_DIR}
CACHE STRING "MZL Include Directories"
)
include_directories(${MZL_INCLUDE_DIRS})
# Set source files
set (
MZL_SRC_FILES
mzl.c
)
# Add library
add_library(${PROJECT_NAME} STATIC ${MZL_SRC_FILES})
# Link to zmq
target_link_libraries(${PROJECT_NAME} ${ZMQ_LIB} ${CMAKE_THREAD_LIBS_INIT})
and tests/CMakeLists.txt is
# Use MZL Source Directories (mzl headers are in top directory)
include_directories(${CMAKE_SOURCE_DIR})
# Variable from here is empty
message(STATUS "MZL Include Directories: ${MZL_INCLUDE_DIRS}")
# Files common to all tests
set ( TEST_COMMON_SOURCES
mzl-test-errors.c
)
# Library setup/shutdown testing
set(SETUP_TEST_NAME mzl-setup-test)
add_executable(${SETUP_TEST_NAME} ${TEST_COMMON_SOURCES} ${SETUP_TEST_NAME}.c)
target_link_libraries(${SETUP_TEST_NAME} ${PROJECT_NAME} ${ZMQ_LIB})
add_test(${SETUP_TEST_NAME} ${SETUP_TEST_NAME})
# Communcations test
set(COMMUNICATION_TEST_NAME mzl-communication-test)
add_executable(${COMMUNICATION_TEST_NAME} ${TEST_COMMON_SOURCES}
${COMMUNICATION_TEST_NAME}.c)
target_link_libraries(${COMMUNICATION_TEST_NAME} ${PROJECT_NAME}
${CMAKE_THREAD_LIBS_INIT} ${ZMQ_LIB})
add_test(${COMMUNICATION_TEST_NAME} ${COMMUNICATION_TEST_NAME})
Everything worked fine before I added the second test mzl-communication-test. After adding it and the lines in the tests/CMakeLists.txt after # Communications test, running ctest did nothing extra -- it still only ran the first test.
After deleting the build directory and running cmake again, I get no errors for the initial CMake run, but running make runs CMake again, resulting in an error with CMake:
CMake Error: Parse error in cache file build/CMakeCache.txt. Offending entry: include
followed by a Make error:
Makefile:203: recipe for target 'cmake_check_build_system' failed
make: *** [cmake_check_build_system] Error 1
Running make again results in everything being built, including the tests; however, running ctest results in
Test project build
No tests were found!!!
The issue seems to be with something that I am doing with CMake, but can't figure out what to do from here as I can't see anything that I'm doing differently than when it was originally working. Even my last commit to git, which was working when I committed it, is no longer working.
You need to move the enable_testing() call to be before you do add_subdirectory(tests)
# Enable testing for the project
enable_testing()
add_subdirectory(tests)
I got a situation where another Makefile is executed from a CMakeLists.txt file.
Here is my root directory structure.
.
├── client.cpp
├── CMakeLists.txt
├── proto_lib
│ ├── Makefile
│ └── math.proto
└── server.cpp
This is a simple grpc test code where I am trying to compile a proto files using a Makefile create a static library. And then link that library to the final targets in the CMakefile. Makefile is working fine. CMakefile is also working fine with one executable.
Here is the CMakefile:
cmake_minimum_required(VERSION 3.5)
project(client-server)
message(STATUS "Compiling Network Function : ${PROJECT_NAME}")
set(CMAKE_CXX_STANDARD 11)
message(STATUS "Project Directory: ${PROJECT_SOURCE_DIR}")
set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/build)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
set(LIB_FILE ${CMAKE_CURRENT_SOURCE_DIR}/proto_lib/libmylib.a)
add_custom_target(libmylib.a ALL
COMMAND make
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/proto_lib
COMMENT "grpc headers and libraries are generating..."
)
add_executable(server server.cpp)
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -g")
set(BASIC_LIBRARIES "-lpthread")
set(CMAKE_LINK_WHAT_YOU_USE ON)
set(LIBDIR "/usr/local/lib")
find_library(proto_location NAMES protobuf PATHS ${LIBDIR})
find_library(grpc_location NAMES grpc++ PATHS ${LIBDIR})
find_library(grpc_reflection_location NAMES grpc++_reflection PATHS ${LIBDIR})
find_library(dl_location NAMES dl PATHS ${LIBDIR})
find_library(grpc_location2 NAMES grpc PATHS ${LIBDIR})
if(proto_location)
message(STATUS "protobuf library found at " ${proto_location})
endif()
if(grpc_location)
message(STATUS "grpc++ found at " ${grpc_location})
endif()
if(grpc_reflection_location)
message(STATUS "grpc_reflection found at " ${grpc_reflection_location})
endif()
if(dl_location)
message(STATUS "dl found at " ${dl_location})
endif()
if(grpc_location2)
message(STATUS "grpc found at " ${grpc_location2})
endif()
target_link_libraries(server ${proto_location}
${LIB_FILE}
${grpc_location}
${grpc_reflection_location}
${dl_location}
${grpc_location2}
${BASIC_LIBRARIES}
)
When I enter the command make after CMake . in the root directory.
it starts with following output...
Scanning dependencies of target libmylib.a
[ 33%] grpc headers and libraries are generating...
[ 33%] Built target libmylib.a
etc.. etc..
and it succeeds.(The internal Makefile creates header files and static objects using proto and grpc libraries. After that server.cpp can include the headers from inside the proto_lib/ folder and CMake build succeeds)
But when I add one more executable at the end of CMakeLists.txt,
add_executable(client client.cpp)
target_link_libraries(client ${proto_location}
${LIB_FILE}
${grpc_location}
${grpc_reflection_location}
${dl_location}
${grpc_location2}
${BASIC_LIBRARIES}
)
and then cmake . && make
does not start with internal Makefile build. Instead, it starts with client build.
Scanning dependencies of target client
[ 20%] Building CXX object CMakeFiles/client.dir/client.cpp.o
/home/deka/Academic/gemini/learning/client_server_async/advanced1/client.cpp:10:10: fatal error: proto_lib/math.grpc.pb.h: No such file or directory
#include "proto_lib/math.grpc.pb.h"
Because proto_lib/Makefile is not executed first in this case therefore math.grpc.pb.h is not generated and that is what the above error is showing.
My question is: Why adding one more executable does not trigger the internal Makefile build at the start?
Thanks!
I would like to include open62541 library to my existing C++ project in Visual Studio using CMake. open62541 itself uses CMake as build tool. Project structure:
MyOPC
│ CMakeLists.txt
│ MyOPC.cpp
│ MyOPC.h
├───.vs
└───open62541
│ CMakeLists.txt
├───arch
│ │ CMakeLists.txt
├───deps
├───doc
├───examples
├───include
├───plugins
├───src
├───tests
└───tools
I would like to build open62541 togehter with my project so it will produce open62541.h file. How this could be done using CMake?
You can simply add the subdirectory of open62541 to your main CMake and before that set the corresponding CMake options. Then also add the open62541 targets to your own target and add the amalgamated source file.
E.g. to enable amalgamation:
set(UA_ENABLE_AMALGAMATION ON CACHE BOOL "" FORCE)
set(UA_LOGLEVEL 300)
add_subdirectory(open62541)
add_dependencies(${PROJECT_NAME} open62541 open62541-amalgamation-source open62541-amalgamation-header)
set (${PROJECT_NAME}_SRCS ${${PROJECT_NAME}_SRCS} "${PROJECT_BINARY_DIR}/open62541/open62541.c")
Make sure that you add the _SRCS to your own target sources.
Something similar is done here:
https://github.com/Pro/open62541-arduino
Thanks #Stefan Profanter for putting me on right direction. This is current working CMakeLists.txt:
# CMakeList.txt : Top-level CMake project file, do global configuration
# and include sub-projects here.
#
cmake_minimum_required (VERSION 3.8)
project ("MyOPC")
add_executable (${PROJECT_NAME} "MyOPC.cpp" "MyOPC.h")
# -----------------------------------
# open62541 specific settings - BEGIN
# -----------------------------------
set(UA_ENABLE_AMALGAMATION ON CACHE BOOL "" FORCE)
set(UA_LOGLEVEL 300)
add_subdirectory ("open62541")
set_source_files_properties("${PROJECT_BINARY_DIR}/open62541/open62541.c" PROPERTIES GENERATED TRUE)
set(${PROJECT_NAME}_SRCS ${${PROJECT_NAME}_SRCS} "${PROJECT_BINARY_DIR}/open62541/open62541.c")
include_directories("${PROJECT_BINARY_DIR}/open62541/")
# -----------------------------------
# open62541 specific settings - END
# -----------------------------------
add_dependencies(${PROJECT_NAME} open62541 open62541-amalgamation-source open62541-amalgamation-header)
target_link_libraries(${PROJECT_NAME} open62541)
Reference in header file MyOPC.h:
#include "open62541.h"
I am trying to incorporate GTests in my project using CMake. I followed this instruction and I get following error:
Undefined symbols for architecture x86_64:
"SomeClass::someMethod()", referenced from:
someMethod_TrivialTest_Test::TestBody() in SomeClassTest.cpp.o
ld: symbol(s) not found for architecture x86_64
Here is my CMake file:
cmake_minimum_required(VERSION 3.11)
project (someProject)
set(CMAKE_CXX_STANDARD 17)
#Include headers
include_directories("../include")
#Add source files
file(GLOB SOURCES "src/*.cpp")
add_executable(someProject ${SOURCES})
################################
# GTest
################################
# Download and unpack googletest at configure time
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download )
if(result)
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} --build .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download )
if(result)
message(FATAL_ERROR "Build step for googletest failed: ${result}")
endif()
# Prevent overriding the parent project's compiler/linker
# settings on Windows
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
# Add googletest directly to our build. This defines
# the gtest and gtest_main targets.
add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src
${CMAKE_BINARY_DIR}/googletest-build
EXCLUDE_FROM_ALL)
# The gtest/gtest_main targets carry header search path
# dependencies automatically when using CMake 2.8.11 or
# later. Otherwise we have to add them here ourselves.
if (CMAKE_VERSION VERSION_LESS 2.8.11)
include_directories("${gtest_SOURCE_DIR}/include")
endif()
# Add test cpp file
add_executable( someTests ./test/SomeClassTest.cpp)
# Link test executable against gtest & gtest_main
target_link_libraries(someTests gtest gtest_main)
add_test( someTests someTests )
My project structure (CMakeLists.txt.in is used to download the GTest library, added from the instruction mentioned above):
.
├── CMakeLists.txt
├── CMakeLists.txt.in
├── include
│ └──SomeClass.hpp
├── src
│ ├── Main.cpp
│ └── SomeClass.cpp
└── tests
└── SomeClassTest.cpp
If I manually create and link objects, it works.
g++ -c ./src/SomeClass.cpp
g++ -c ./test/SomeClassTest.cpp
g++ SomeClassTest.o SomeClass.o ./build/googletest-build/googlemock/gtest/CMakeFiles/gtest.dir/src/gtest-all.cc.o -o myTests
The object of the test class seems to be there:
./build/CMakeFiles/someTests.dir/test/SomeClassTest.cpp.o
But the directory for the someProject object is empty:
./build/CMakeFiles/someProject.dir/src/
So I am missing something in the CMake file and it is not linking properly. All the answers I could find so far were related to specifying target_link_libraries but I am not sure if that is the problem here. I am new to CMake and linking issues. Would reeeally appreciate any advice!
All the answers I could find so far were related to specifying target_link_libraries but I am not sure if that is the problem here.
You were right on track with this assumption.
Currently, you're telling CMake that there is an executable to be built from some sources and a test to be built from some other sources and linked with gtest. CMake doesn't know that the executable and your test are in any way related, though!
I see two possible solutions:
add the sources of the executable (except the one with the main function) as sources to the test.
build all of the sources from the executable (except the one with the main function) as library and link both the executable and the test to that library.
I prefer the later one, which would - roughly - look like:
add_library(someProgram_lib ${SOURCES})
add_executable(someProgram src/main.cc)
target_link_libraries(someProgram someProgram_lib)
add_executable(someTests ./test/SomeClassTest.cpp)
target_link_libraries(someTests gtest gtest_main someProgram_lib)
My code in a C++ project is organised as follows
I have several .cpp and .h files which contains my classes
I have several .cxx files which have to be compiled against the .cpp files and some external libraries.
Now, each of the .cxx files have a main() method, so I need to add a different executable for each of these files having the same name as the file.
Also, these .cxx files might not get linked to the same external libraries.
I want to write this build in CMake, in which I am kind of a newbie, how do I go about this?
My suggestion is to tackle this in two phases:
Build a library from the .cpp and .h files, using add_library
Iterate through all your .cxx files and create an executable from each, using add_executable and foreach
Build the library
This could be something as simple as
file( GLOB LIB_SOURCES lib/*.cpp )
file( GLOB LIB_HEADERS lib/*.h )
add_library( YourLib ${LIB_SOURCES} ${LIB_HEADERS} )
Build all the executables
Simply loop over all the .cpp files and create separate executables.
# If necessary, use the RELATIVE flag, otherwise each source file may be listed
# with full pathname. RELATIVE may makes it easier to extract an executable name
# automatically.
# file( GLOB APP_SOURCES RELATIVE app/*.cxx )
file( GLOB APP_SOURCES app/*.cxx )
foreach( testsourcefile ${APP_SOURCES} )
# I used a simple string replace, to cut off .cpp.
string( REPLACE ".cpp" "" testname ${testsourcefile} )
add_executable( ${testname} ${testsourcefile} )
# Make sure YourLib is linked to each app
target_link_libraries( ${testname} YourLib )
endforeach( testsourcefile ${APP_SOURCES} )
Some warnings:
file( GLOB ) is usually not recommended, because CMake will not automatically rebuild if a new file is added. I used it here, because I do not know your sourcefiles.
In some situations, source-files may be found with a full pathname. If necessary, use the RELATIVE flag for file(GLOB ...).
Manually setting the source-files requires a change to CMakeLists.txt, which triggers a rebuild. See this question for the (dis-)advantages of globbing.
I generated the testname using a string( REPLACE ... ). I could have used get_filename_component with the NAME_WE flag.
Concerning "general" CMake info, I advise you to read some of the broad "CMake Overview" questions already asked here on stackoverflow. E.g.:
https://stackoverflow.com/questions/2186110/cmake-tutorial
What are the dusty corners a newcomer to CMake will want to know?
I find myself in a similar situation when organizing an OpenGL project with multiple sample files where each of these files contain a main method.
The settings below will generate a separate executable per c/cpp file as well as copying required dependencies to the target bin folder.
Folder Structure
my-project
│── ch01_01.c
│── ch02_01.cpp
│── CMakeLists.txt
│── Resources
│ │── Libraries
│ │ │── glew
│ │ │ │── bin
│ │ │ │── include
│ │ │ │── lib
│ │ │── glfw
│ │ │ │── include
│ │ │ │── lib
CMakeLists.txt
cmake_minimum_required (VERSION 3.9)
project ("my-project")
include_directories(Resources/Libraries/glew/include
Resources/Libraries/glfw/include)
link_directories(Resources/Libraries/glew/lib
Resources/Libraries/glfw/lib)
link_libraries(opengl32.lib
glew32.lib
glfw3.lib)
set(CMAKE_EXE_LINKER_FLAGS "/NODEFAULTLIB:MSVCRT")
file(GLOB SOURCE_FILES *.c *.cpp)
foreach(SOURCE_PATH ${SOURCE_FILES})
get_filename_component(EXECUTABLE_NAME ${SOURCE_PATH} NAME_WE)
add_executable(${EXECUTABLE_NAME} ${SOURCE_PATH})
# Copy required DLLs to the target folder
add_custom_command(TARGET ${EXECUTABLE_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/Resources/Libraries/glew/bin/glew32.dll"
"${CMAKE_BINARY_DIR}/glew32.dll")
endforeach(SOURCE_PATH ${SOURCE_FILES})
Optional Steps
In Visual Studio
Open the project with 'Open a local Folder' option in the Start Window
When adding a new file you may either:
Cancel the dialog asking to automatically add_executable to CMakeLists.txt
Disable this behavior by unchecking 'Enable automatic CMake script modification for file operations from folder view' in Tools > Options > CMake
As newly added files are not picked up automatically as CMakeLists.txt is never changed, simply regenerate the cache like so:
Project > CMake Cache (x64-Debug) > Delete Cache
Project > Generate Cache for my-project
Now you may simply right click a given c/cpp file and Set as Startup Item to be able to debug it with F5.
Environment
cmake version 3.18.20081302-MSVC_2
Microsoft Visual Studio Community 2019 Version 16.8.3
Starter Template
I put together this starter template on GitHub in case you are interested.
This CMakeLists.txt works for my OpenCV project
assuming *.cpp files are in the same directory as CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(opencv LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(OpenCV REQUIRED)
include_directories( ${OpenCV_INCLUDE_DIRS} )
file( GLOB APP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp )
foreach( sourcefile ${APP_SOURCES} )
file(RELATIVE_PATH filename ${CMAKE_CURRENT_SOURCE_DIR} ${sourcefile})
string( REPLACE ".cpp" "" file ${filename} )
add_executable( ${file} ${sourcefile} )
target_link_libraries( ${file} ${OpenCV_LIBS} )
endforeach( sourcefile ${APP_SOURCES} )