I am trying to test a node-js addon (built with cmake-js) with google test.
I am building on Mac OS.
The addon target builds and runs ok, but I have problems with the googletest target.
I am getting linking errors related to undefined V8 methods.
In CMakeLists.txt I printed (with message) the variables CMAKE_JS_SRC and CMAKE_JS_LIB and they are both empty. If CMAKE_JS_LIB is empty I don't see how target_link_libraries() should work to add the node/v8 library to my test executable...
If instead of using add_executable() I use add_library() the google_test target builds but of course I can not run it since it is not an executable anymore.
Can you help?
Below is my CMakeLists.txt:
make_minimum_required(VERSION 3.14)
include_directories(my_project)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_C_FLAGS "-Wno-pointer-sign -fno-signed-char -std=c99 -fpermissive")
set(CMAKE_CXX_FLAGS "-Wno-pointer-sign -fno-signed-char -std=c99 -fpermissive")
project (addon)
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.12.1
)
FetchContent_MakeAvailable(googletest)
include_directories(${CMAKE_JS_INC} "my_project/include/pkcs11/v2.40/")
file(GLOB SOURCE_FILES "my_project/*.c" "my_project/*.h" "my_project/*.cpp")
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")
target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB} )
## google_test
enable_testing()
file(GLOB TEST_FILES "test/*.cc" "test/utils/*.c")
add_executable(
my_project_google_test
${TEST_FILES)
)
target_include_directories(my_project_google_test
PRIVATE
test/utils/*.h
)
target_link_libraries(
my_project_google_test
PRIVATE
GTest::gtest_main
${CMAKE_JS_LIB}
)
include(GoogleTest)
gtest_discover_tests(my_project_google_test)
CMAKE_JS_LIB is empty everywhere except on Windows.
Install v8 from Homebrew if you haven't done it yet: brew install v8.
Link the app to v8
target_link_libraries(
my_project_google_test
PRIVATE
v8
)
Other v8 libraries can be required, you have not post all errors: v8_libbase v8_libplatform.
Related
I was checking the quickstarter to use googletest with cmake. I was wondering how I should modify the CMakeLists.txt they provide (given below) in order to use googlemock.
cmake_minimum_required(VERSION 3.14)
project(my_project)
# GoogleTest requires at least C++14
set(CMAKE_CXX_STANDARD 14)
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
enable_testing()
add_executable(
hello_test
hello_test.cc
)
target_link_libraries(
hello_test
GTest::gtest_main
)
include(GoogleTest)
gtest_discover_tests(hello_test)
for the moment, #include <gtest/gtest.h> works but #include <gmock/gmock.h> doesn't
GMock should be available via GTest::gmock cmake target. At least this is the target name used in the cmake configuration files of a GTest build installed via cmake.
target_link_libraries(
hello_test
GTest::gmock
)
I want to use protobuf in my C++ library. All dependencies so far are included using cmake's FetchContent module. I want to do the same with protobuf. However, I run into the following problem: Unknown CMake command "protobuf_generate_cpp". Any hints on how to solve this?
Excerpt of my CMakeLists.txt:
FetchContent_Declare(fmt
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
GIT_TAG 9.0.0)
FetchContent_Declare(protobuf
GIT_REPOSITORY https://github.com/protocolbuffers/protobuf.git
GIT_TAG v21.4)
FetchContent_MakeAvailable(fmt protobuf)
include_directories(${Protobuf_INCLUDE_DIRS})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS message.proto)
This works for me:
FetchContent_Declare(protobuf
GIT_REPOSITORY https://github.com/protocolbuffers/protobuf.git
GIT_TAG v21.4
SOURCE_SUBDIR cmake
FIND_PACKAGE_ARGS NAMES protobuf
)
FetchContent_MakeAvailable(protobuf)
On the consumer end do this
include(FindProtobuf)
find_package(protobuf CONFIG REQUIRED)
Note: This has only been tested on CMake v3.25
protobuf_generate_cpp is from FindProtobuf. It doesn't seem to work with a protoc that was build in the project with FetchContent. You'll have to call the protoc binary explicitly.
set(GENERATED_CODE_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated)
set(PROTO_SRCS ${GENERATED_CODE_DIR}/message.pb.cc)
set(PROTO_HDRS ${GENERATED_CODE_DIR}/message.pb.h)
set(PROTOC ${protobuf_BINARY_DIR}/protoc)
set(PROTO_DIR ${CMAKE_CURRENT_SOURCE_DIR})
add_custom_command(
OUTPUT ${PROTO_SRCS} ${PROTO_HDRS}
COMMAND ${PROTOC} --proto_path ${PROTO_DIR} message.proto --cpp_out ${GENERATED_CODE_DIR}
DEPENDS ${PROTOC} ${PROTO_DIR}/message.proto
)
I tried to used https://github.com/julianxhokaxhiu/SteamworksSDKCI to use steam api on a simple SFML application (helloworld).
I wanted to use cmake to learn it, but I am struggling to understand how the provided CMakeLists and Find*.cmake file are expected to be used.
Currently, I have modified the CMakeLists to change the INSTALL_DIR
INSTALL_DIR "${CMAKE_BINARY_DIR}/../../vendor"
and my CMakeLists is :
cmake_minimum_required(VERSION 3.19)
project(SfmlWithCMake VERSION 1.0)
include(FetchContent)
set (CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake_steam")
# Configure external project
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/cmake_steam)
execute_process(
COMMAND ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR}/cmake_steam
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/cmake_steam
)
# Build external project
execute_process(
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR}/cmake_steam
)
set(BUILD_SHARED_LIBS OFF)
FetchContent_Declare(
SFML
GIT_REPOSITORY https://github.com/SFML/SFML.git
GIT_TAG 2.5.1
)
FetchContent_MakeAvailable(SFML)
find_package(STEAMWORKSSDK REQUIRED)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED true)
# Generate config.h
configure_file(config.h.in config.h)
add_executable(
SfmlWithCMake
main.cpp
)
get_target_property(STEAMSDK STEAMWORKSSDK::STEAMWORKSSDK INCLUDE_DIRECTORIES)
target_include_directories(
SfmlWithCMake
PRIVATE
"${PROJECT_BINARY_DIR}"
"${STEAMSDK}"
)
target_link_libraries(
SfmlWithCMake
sfml-graphics
STEAMWORKSSDK::STEAMWORKSSDK
-static gcc stdc++ winpthread -dynamic
)
install(TARGETS SfmlWithCMake DESTINATION bin)
How to get include directories?
I do not succeed to add the steam include to the target_include_directories.
Here the ${STEAMSDK} is my last attempt to get the directory.
If I replace this by ${PROJECT_BINARY_DIR}/vendor/include, everything works.
Also, why does the SFML include are automatically added to my target include directories and not the steam one?
Am I using the Find*.cmake file the right way?
I understood that ExternalProject_Add was performed at build time and thus, as the find_package is needed at configue time, I added the two "execute_process". But, the readme on github only says to do the find package and add the target to target_link_libraries...
Thanks.
I have compiled and installed with CMake the library SDL_bgi to a custom prefix /custom/prefix/. This library uses SDL2.
Now I want to use it in another project with the structure below but I get a linker error when I compile with make:
/usr/bin/c++ CMakeFiles/test.dir/test.cpp.o -o test -Wl,-rpath,/custom/prefix/lib: /custom/prefix/lib/libSDL_bgi.so
/usr/bin/ld: /custom/prefix/lib/libSDL_bgi.so: undefined reference to `SDL_DestroyWindow'
/usr/bin/ld: /custom/prefix/lib/libSDL_bgi.so: undefined reference to `SDL_CreateRenderer'
I have also written the file cmake/modules/FindSDL_bgi.cmake so that may be wrong as well.
If I compile with the following command I can compile correctly:
g++ test.cpp -I . -lSDL_bgi -lSDL2 -I /custom/prefix/include/ -L /custom/prefix/lib/
What am I doing wrongly?
Project structure:
cmake/modules/FindSDL_bgi.cmake
src/test/CMakeLists.txt
src/test/test.cpp
CMakeLists.txt
Libraries:
/usr/lib/libSDL.so
/usr/include/SDL.h
/custom/prefix/lib/libSDL_bgi.so
/custom/prefix/include/graphics.h
/custom/prefix/include/SDL2/libSDL_bgi.h
cmake/modules/FindSDL_bgi.cmake:
# - Try to find LibXml2
# Once done this will define
# SDL_BGI_FOUND - System has LibXml2
# SDL_BGI_INCLUDE_DIRS - The LibXml2 include directories
# SDL_BGI_LIBRARIES - The libraries needed to use LibXml2
# Hardcoded for now
set(SDL_BGI_PATH
/custom/prefix/
)
set(SDL_BGI_SEARCH_PATHS
/usr
/usr/local
/opt
${SDL_BGI_PATH}
)
find_path(SDL_BGI_INCLUDE_DIR graphics.h
HINTS
$ENV{SDL2DIR}
PATH_SUFFIXES include
PATHS ${SDL2_SEARCH_PATHS}
)
find_library(SDL_BGI_LIBRARY
NAMES SDL_bgi
HINTS
$ENV{SDL2DIR}
PATH_SUFFIXES lib64 lib
PATHS ${SDL2_SEARCH_PATHS}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(SDL_bgi REQUIRED_VARS SDL_BGI_LIBRARY SDL_BGI_INCLUDE_DIR)
CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(programmi_kennedy)
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/modules")
set(COMPAT_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/include/
)
find_package(SDL_bgi REQUIRED)
add_subdirectory(src/test)
src/CMakeLists.txt:
add_executable(test test.cpp)
target_include_directories(test PUBLIC ${SDL_BGI_INCLUDE_DIR})
target_link_libraries(test PRIVATE ${SDL_BGI_LIBRARY})
install(TARGETS test DESTINATION bin)
/custom/prefix/include/graphics.h:
#include <SDL2/SDL_bgi.h>
What I was missing is to link to SDL2 with find_package(SDL2 REQUIRED) and link to SDL2::SDL2. (I did try to link to ${SDL2_LIBRARIES} but the syntax is different now). Thanks to #KamilCuk to point me to the right direction.
EDIT:
I changed the FindBGI_sdl.cmake module in order to search for the dependencies (SDL2) and link against them using the INTERFACE keyword. In this way the target test can link only against SDL_bgi and have the dependencies resolved automatically.
src/CMakeLists.txt:
add_executable(test test.cpp)
target_link_libraries(test PRIVATE SDL_bgi::SDL_bgi)
install(TARGETS test DESTINATION bin)
cmake/modules/FindSDL_bgi.cmake:
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
FindSDL_bgi
-------
Finds the SDL_bgi library.
Imported Targets
^^^^^^^^^^^^^^^^
This module provides the following imported targets, if found:
``SDL_bgi::SDL_bgi``
The SDL_bgi library
Result Variables
^^^^^^^^^^^^^^^^
This will define the following variables:
``SDL_bgi_FOUND``
True if the system has the SDL_bgi library.
``SDL_bgi_VERSION``
The version of the SDL_bgi library which was found.
``SDL_bgi_INCLUDE_DIRS``
Include directories needed to use SDL_bgi.
``SDL_bgi_LIBRARIES``
Libraries needed to link to SDL_bgi.
Cache Variables
^^^^^^^^^^^^^^^
The following cache variables may also be set:
``SDL_bgi_INCLUDE_DIR``
The directory containing ``foo.h``.
``SDL_bgi_LIBRARY``
The path to the SDL_bgi library.
#]=======================================================================]
find_package(SDL2 REQUIRED)
find_package(PkgConfig)
pkg_check_modules(PC_SDL_bgi QUIET SDL_bgi)
find_path(SDL_bgi_INCLUDE_DIR
NAMES graphics.h
PATHS ${PC_SDL_bgi_INCLUDE_DIRS}
)
find_library(SDL_bgi_LIBRARY
NAMES SDL_bgi
PATHS ${PC_SDL_bgi_LIBRARY_DIRS}
)
set(SDL_bgi_VERSION ${PC_SDL_bgi_VERSION})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(SDL_bgi
FOUND_VAR SDL_bgi_FOUND
REQUIRED_VARS
SDL_bgi_LIBRARY
SDL_bgi_INCLUDE_DIR
VERSION_VAR SDL_bgi_VERSION
)
if(SDL_bgi_FOUND AND NOT TARGET SDL_bgi::SDL_bgi)
add_library(SDL_bgi::SDL_bgi UNKNOWN IMPORTED)
set_target_properties(SDL_bgi::SDL_bgi PROPERTIES
IMPORTED_LOCATION "${SDL_bgi_LIBRARY}"
INTERFACE_COMPILE_OPTIONS "${PC_SDL_bgi_CFLAGS_OTHER}"
INTERFACE_INCLUDE_DIRECTORIES "${SDL_bgi_INCLUDE_DIR}"
)
target_link_libraries(SDL_bgi::SDL_bgi INTERFACE SDL2::SDL2)
endif()
mark_as_advanced(
SDL_bgi_INCLUDE_DIR
SDL_bgi_LIBRARY
SDL2_DIR
)
Useful references:
https://pabloariasal.github.io/2018/02/19/its-time-to-do-cmake-right/
https://cmake.org/cmake/help/v3.17/manual/cmake-developer.7.html
I'm trying to build libpng with CMAKE, but it requires zlib, so I'm trying to build them both but not having any luck. I like FetchContent so I can specify a GIT_TAG and easily update that in the future if needed. For now I have just a blank test.c file to illustrate the problem.
I get these link errors:
LNK1120 1 unresolved externals
MinimalApp\out\build\x64-Debug\_deps\libpng-build\png-fix-itxt.exe
LNK2019 unresolved external symbol crc32 referenced in function main
When I build with this CMakeLists.txt
cmake_minimum_required (VERSION 3.14)
include(FetchContent)
project(MinimalApp)
FetchContent_Declare(
zlib
GIT_REPOSITORY https://github.com/madler/zlib.git
GIT_TAG v1.2.11
)
FetchContent_MakeAvailable(zlib)
set(ZLIB_INCLUDE_DIR ${zlib_SOURCE_DIR} ${zlib_BINARY_DIR})
set(PNG_BUILD_ZLIB ON CACHE BOOL "Custom zlib Location, else find_package is used")
FetchContent_Declare(
libpng
GIT_REPOSITORY https://github.com/glennrp/libpng.git
GIT_TAG v1.6.37
)
FetchContent_MakeAvailable(libpng)
include_directories(
${libpng_SOURCE_DIR}
${libpng_BINARY_DIR}
)
add_library(MinimalApp SHARED
"test.c"
)
set_target_properties(MinimalApp PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/../bin/${CMAKE_BUILD_TYPE}/x64
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/../bin/${CMAKE_BUILD_TYPE}/x64
)
My test.c file is blank.
I ran into this problem recently and I believe you also need to set the ZLIB_LIBRARY cmake variable. libpng expects this variable to be set if you are using PNG_BUILD_ZLIB.
This can be as simple as:
set(ZLIB_LIBRARY zlib)