I'm trying to create a project in C using Gtest for unit tests.
For this, I have installed Xcode developer tools (because I'm in macOS big sur environment). and after this, I am cloning gtest and adding to submodules.
But, when I am trying to run test, the error appear :
googletest/googletest/include/gtest/gtest.h:52:10: fatal error: 'cstddef' file not found
After trying to reinstall Xcode tools, download the header to set it in my env, I have no more idea.
Do you have any idea to fix this or anybody had the same ?
Thank
PS : this is my CMakeLists
cmake_minimum_required(VERSION 3.0)
project(MasterDSA)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -o3")
add_library(Addition src/addition.c include/addition.h)
add_executable(Main src/main.c)
target_link_libraries(Main Addition)
set_target_properties(Main
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/bin")
set (gtest_force_shared_crt ON CACHE BOOL "MSVC defaults to shared CRT" FORCE)
add_subdirectory(googletest/googletest)
target_compile_definitions(gtest
PUBLIC
GTEST_LANG_CXX20
GTEST_HAS_TR1_TUPLE=0
)
add_executable(tests)
target_sources(tests
PRIVATE
test/addition_test.c
)
set_target_properties(tests PROPERTIES COMPILE_FLAGS "${cxx_strict}")
target_link_libraries(tests gtest gtest_main Core)
You are attempting to compile C++ code (in gtest.h) with a C compiler. (CMake chooses a C compiler for source files whose names end with .c.) C and C++ are different languages, not, generally speaking, source compatible in either direction. You must compile C with a C compiler, and C++ with a C++ compiler.
If considerable care is exercised then it is possible to write code in the shared subset of the two languages or that use the preprocessor to adapt to the chosen language, but this is uncommon, except sometimes for headers that declare functions and external objects having (from the C++ perspective) C linkage. That evidently is not how your gtest.h is written.
Your main options are:
convert your project to a C++ project. This has significant implications, so do not do it lightly.
write C++ tests for your C code. This may or may not be viable.
choose a C test framework instead of C++-specific GTest.
Related
As the title suggest, I'd like to use cmake to build a project, and depending on the source file, enforcing a different c++ standard.
The reason is : I am working on a library and would like to make it c++03 compliant for compatibility, but would like to use Google test suite which requires c++11.
So the unit tests would be compiled with c++11, but I'd like my library to fail at compilation if there is reference to a c++11 only feature.
So just do that - ompile your library with one standard, and your tests with the other. Nowadays, https://stackoverflow.com/a/61281312/9072753 method should be preferred.
add_library(mylib lib1.cpp)
set_target_properties(mylib
PROPERTIES
CXX_STANDARD 03
CXX_EXTENSIONS off
)
add_executable(mytest main.cpp)
set_target_properties(mytest
PROPERTIES
CXX_STANDARD 11
CXX_EXTENSIONS off
)
target_link_libraries(mytest PRIVATE mylib)
add_test(NAME mytest COMMAND mytest)
You can do that, if they are used by different targets, using add_targrt_compile_options , as follows.
Assuming you want to use c++03 with the lib and c++11 with the exec, you may use something like what follows
add_executable(exec1 main.cpp)
add_library(lib1 STATIC lib1.cpp)
target_compile_options(lib1 PRIVATE -std=c++03)
target_compile_options(exec1 PRIVATE -std=c++11)
I have worked on a project where I was using g++ to compile C code in files that end in .c. The reason is that I'm told that g++ has better warning messages.
I am switching the build process for this project to use CMake. I found that initially CMake wanted to use gcc to compile C files. This failed because of things like declaring variables at use time. So I tried to use g++ to compile C files by using the setting
set(CMAKE_C_COMPILER_INIT g++)
in the CMakeLists.txt file. But this results in the error message:
#error "The CMAKE_C_COMPILER is set to a C++ compiler"
I have been renaming my .c files to .cpp to fix this problem as that seems to be the easiest way for me to make things work, and perhaps the best way too. But I was wondering if it is possible to force CMake to use g++ to compile C files.
You should not override the compiler for this purpose. If you really need to compile your C files as C++ then you should teach cmake that your files belong to C++ language:
set_source_files_properties(filename.c PROPERTIES LANGUAGE CXX )
To have cmake treat all C files as C++ files use:
file(GLOB_RECURSE CFILES "${CMAKE_SOURCE_DIR}/*.c")
SET_SOURCE_FILES_PROPERTIES(${CFILES} PROPERTIES LANGUAGE CXX )
If you need to switch the whole project, set it in the project directive:
project(derproject LANGUAGES CXX)
set_source_files_properties
The CMake setting of (my) choice here would be the set_source_files_properties command. https://cmake.org/cmake/help/latest/command/set_source_files_properties.html
set(qpid_dispatch_SOURCES
alloc.c
alloc_pool.c
aprintf.c
amqp.c
atomic.c
# [...]
)
set_source_files_properties(${qpid_dispatch_SOURCES} PROPERTIES LANGUAGE CXX)
add_library(qpid-dispatch OBJECT ${qpid_dispatch_SOURCES})
As described in the linked docs, CMake 3.18 changed the scoped effect of set_source_files_properties. See the DIRECTORY and TARGET_DIRECTORY options. Therefore, to apply source file property recursively to all files in your project, your CMakeLists.txt should look something like this
cmake_minimum_required(VERSION 3.20)
project(qpid-dispatch LANGUAGES C CXX)
# [...]
add_subdirectory(src)
add_subdirectory(tests)
add_subdirectory(router)
# [...]
file(GLOB_RECURSE CFILES "*.c")
set_source_files_properties(${CFILES}
DIRECTORY src tests router
PROPERTIES LANGUAGE CXX)
I'm currently trying to setup a project that will make use of multiple compilers (including Clang, MSVC, and GCC) using Visual Studio 2019's new CMake functionalities (notably using Clang and Ninja in conjunction with CMake and VS2019).
I'm using CMake to configure the project to be "compiler-agnostic", so that I don't need to edit the code itself to handle different compilers via pre-processor instructions or #pragma instructions.
This project needs to be configured to have a high warning level (/W4 for MSVC, -Wall, -Wextra, and -Wpedantic for Clang), and must treat warnings as errors.
I don't have any issues when it comes to configuring the MSVC portion of the project. A lot of these settings have "sane" defaults that "just work" as I'd expect them to. When it comes to Clang, however, I've encountered a problem:
I can't seem to disable warnings for third-party library header files. I'm currently using the Dear Imgui and SFML libraries. Since Dear Imgui isn't pre-compiled, I simply do the following in my CMakeLists.txt file to include it:
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/libs/imgui
)
I use the statically linked version of SFML, so I do the following to include it:
# Find SFML and link statically to it.
# Note: We need to set the SFML_DIR variable manually.
set(SFML_STATIC_LIBRARIES TRUE)
set(SFML_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libs/SFML-2.5.1/lib/cmake/SFML")
find_package(SFML 2.5.1 COMPONENTS system audio window graphics REQUIRED)
target_link_libraries(${PROJECT_NAME}
PRIVATE
sfml-system
sfml-audio
sfml-window
sfml-graphics
)
Sadly, SFML doesn't currently follow the current CMake standard way of adding libraries, so it's kind of weird to work with or configure it via CMake.
Now, the above works just fine when it comes to including the libraries in my project (but it might be something I need to change, so I've included it in the post). The problems come when I try to impose the warnings and warnings-as-errors configurations to them when using Clang.
Here are the parts of my CMakeLists.txt file which handle Clang and my C++ configurations:
# Set project to use C++ 17 standard.
set_target_properties(
${PROJECT_NAME}
PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
)
target_compile_options(${PROJECT_NAME} PRIVATE
# All warnings, warnings as errors, be pedantic.
-Wall
-Wextra
-Werror
-Wpedantic
# Disable warnings about C++98 incompatibility. We're using C++17 features...
-Wno-c++98-compat
-Wno-c++98-compat-pedantic
)
Using the above configuration results in hundreds of warnings/errors in Dear Imgui's source files (due to the usage of "old-school" C++/C-style code), as well as a whole bunch of them in SFML's own source files and header files.
I've been looking for ways to get around this for nearly a week, before settling on the following solution (which doesn't entirely work, more on that later):
set(LIBS_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/libs")
set(IMGUI_FOLDER "${LIBS_FOLDER}/imgui")
set(SFML_FOLDER "${LIBS_FOLDER}/SFML-2.5.1/include/SFML")
file(GLOB LIBRARY_FILES
# Dear-imgui
"${IMGUI_FOLDER}/*.cpp"
"${IMGUI_FOLDER}/misc/freetype/*.cpp"
"${IMGUI_FOLDER}/misc/fonts/*.cpp"
"${IMGUI_FOLDER}/misc/cpp/*.cpp"
# SFML
"${SFML_FOLDER}/Audio/*.cpp"
"${SFML_FOLDER}/Graphics/*.cpp"
"${SFML_FOLDER}/Network/*.cpp"
"${SFML_FOLDER}/System/*.cpp"
"${SFML_FOLDER}/Window/*.cpp"
)
set_source_files_properties(
${LIBRARY_FILES}
PROPERTIES
COMPILE_FLAGS
"-Wno-everything"
)
I begin by GLOB-ing my library source files (NOTE: I know GLOB is usually looked down upon, but I felt like using it with third-party library files was fine since they're not supposed to change anyway). I then pass them to the set_source_files_properties function to apply the -Wno-everything flag, which seems to properly suppress all errors and warnings from those files.
Everything seems to work just fine, except for one warning which I can't seem to disable without using a #pragma instruction in my code (which I want to avoid). When compiling an empty main function that includes SFML headers, I get warnings about their .hpp files (which can't be passed to the set_source_files_properties function).
This:
#include <SFML/Graphics.hpp>
int main()
{
}
Results in the following warnings/errors:
zero as null pointer constant [-Werror,-Wzero-as-null-pointer-constant]
declaration is marked with '\deprecated' command but does not have a deprecation attribute [-Werror,-Wdocumentation-deprecated-sync]
declaration is marked with '\deprecated' command but does not have a deprecation attribute [-Werror,-Wdocumentation-deprecated-sync]
declaration is marked with '\deprecated' command but does not have a deprecation attribute [-Werror,-Wdocumentation-deprecated-sync]
In these respective SFML files:
ThreadLocal.hpp (57)
Keyboard.hpp (161)
Event.hpp (105)
PrimitiveType.hpp (52)
Other things I've tried that didn't work:
Putting the .h/.hpp files in the set_source_files_properties CMake function (alongside the .cpp files). Works for Dear Imgui, but all its errors were in .cpp files, not its headers. Doesn't work for SFML's headers.
(Not for SFML, but for Dear Imgui) Including the directories as SYSTEM includes to suppress the warnings. Doesn't appear to work on Windows. Can't really do this with SFML, since I'm using CMake's find_package function instead of doing everything manually.
Using #pragma instructions. While this worked, every SFML file has dozens of different errors, and I want to avoid using #pragmas everywhere (or wrapping SFML's headers in my own headers that just wrap the #include instruction in #pragmas).
Is it even possible to suppress these warnings for my library headers without #pragmas? I've never really used Clang before, so apologies if this seems like a simple question, but searching online hasn't really given me anything that would work:
Outside of a commandline (I'm using Visual Studio with CMake).
On Windows (the system flag doesn't seem to work with this setup).
That would work with CMake specifically.
You can mark the include paths as SYSTEM. Most compilers will not report warnings in system headers. In your case that might look something like this:
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/libs/imgui)
set_target_properties(sfml-system PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:sfml-system,INTERFACE_INCLUDE_DIRECTORIES>)
set_target_properties(sfml-audio PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:sfml-audio,INTERFACE_INCLUDE_DIRECTORIES>)
set_target_properties(sfml-window PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:sfml-window,INTERFACE_INCLUDE_DIRECTORIES>)
set_target_properties(sfml-graphics PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:sfml-graphics,INTERFACE_INCLUDE_DIRECTORIES>)
For example, this dummy project:
project(example)
cmake_minimum_required(VERSION 3.18)
add_library(dep INTERFACE)
target_include_directories(dep INTERFACE include)
file(WRITE include/header.h "static int a;")
add_library(lib STATIC lib.c)
target_link_libraries(lib PRIVATE dep)
target_compile_options(lib PRIVATE -Wunused -Werror)
file(WRITE lib.c "#include <header.h>")
Fails with:
$ cmake . && make
include/header.h:1:12: error: ‘a’ defined but not used [-Werror=unused-variable]
But after adding this line:
set_target_properties(dep PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:dep,INTERFACE_INCLUDE_DIRECTORIES>)
It builds with no errors.
There is a way to suppress warnings from third party headers in a CMake way.
target_include_directories(<target> [SYSTEM] [AFTER|BEFORE]
<INTERFACE|PUBLIC|PRIVATE> [items1...]
[<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
The system keyword is most likely what you want.
If SYSTEM is specified, the compiler will be told
the directories are meant as system include directories on some platforms
The SYSTEM keyword adds -isystem for GCC/Clang. Instead of treating the directory like a normal include directory.
# GCC docs
Warnings from system headers are normally suppressed.
On the assumption that they usually do not indicate real problems
and would only make the compiler output harder to read.
For a while there was no solution for MSVC until recently in CMake 3.22, because the MSVC compiler finally added support for this.
Here is the MSVC blog post where they talk about the new compiler functionality.
The “Ninja” and “NMake Makefiles” generators now use
the MSVC “-external:I” flag for system includes.
This became available as of VS 16.10
(toolchain version 14.29.30037).
I'm attempting to run a cmake hello world program on Windows 7 x64 with both Visual Studio 2010 and Cygwin, but can't seem to get either to work. My directory structure is as follows:
HelloWorld
-- CMakeLists.txt
-- src/
-- -- CMakeLists.txt
-- -- main.cpp
-- build/
I do a cd build followed by a cmake .., and get an error stating that
CMake Error: CMake can not determine linker language for target:helloworld
CMake Error: Cannot determine link language for target "helloworld".
However, if I change the extension of main.cpp to main.c both on my filsystem and in src/CMakeLists.txt everything works as expected. This is the case running from both the Visual Studio Command Prompt (Visual Studio Solution Generator) and the Cygwin Terminal (Unix Makefiles Generator).
Any idea why this code wouldn't work?
CMakeLists.txt
PROJECT(HelloWorld C)
cmake_minimum_required(VERSION 2.8)
# include the cmake modules directory
set(CMAKE_MODULE_PATH ${HelloWorld_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
add_subdirectory(src)
src/CMakeLists.txt
# Include the directory itself as a path to include directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Create a variable called helloworld_SOURCES containing all .cpp files:
set(HelloWorld_SOURCES main.cpp)
# Create an executable file called helloworld from sources:
add_executable(hello ${HelloWorld_SOURCES })
src/main.cpp
int main()
{
return 0;
}
I also got the error you mention:
CMake Error: CMake can not determine linker language for target:helloworld
CMake Error: Cannot determine link language for target "helloworld".
In my case this was due to having C++ files with the .cc extension.
If CMake is unable to determine the language of the code correctly you can use the following:
set_target_properties(hello PROPERTIES LINKER_LANGUAGE CXX)
The accepted answer that suggests appending the language to the project() statement simply adds more strict checking for what language is used (according to the documentation), but it wasn't helpful to me:
Optionally you can specify which languages your project supports.
Example languages are CXX (i.e. C++), C, Fortran, etc. By default C
and CXX are enabled. E.g. if you do not have a C++ compiler, you can
disable the check for it by explicitly listing the languages you want
to support, e.g. C. By using the special language "NONE" all checks
for any language can be disabled. If a variable exists called
CMAKE_PROJECT__INCLUDE_FILE, the file pointed to by that
variable will be included as the last step of the project command.
In my case, it was just because there were no source file in the target. All of my code was a template with the source code in the header file. Adding an empty file.cpp solved the problem.
Try changing
PROJECT(HelloWorld C)
into
PROJECT(HelloWorld C CXX)
or just
PROJECT(HelloWorld)
See: https://cmake.org/cmake/help/latest/command/project.html
Confusing as it might be, the error also happens when a cpp file included in the project does not exist.
If you list your source files in CMakeLists.txt and mistakenly type a file name then you get this error.
I want to add another solution in case a library without any source files shall be build. Such libraries are also known as header only libraries. By default add_library expects at least one source file added or otherwise the mentioned error occurs. Since header only libraries are quite common, cmake has the INTERFACE keyword to build such libraries. The INTERFACE keyword is used as shown below and it eliminates the need for empty source files added to the library.
add_library(myLibrary INTERFACE)
target_include_directories(myLibrary INTERFACE {CMAKE_CURRENT_SOURCE_DIR})
The example above would build a header only library including all header files in the same directory as the CMakeLists.txt. Replace {CMAKE_CURRENT_SOURCE_DIR} with a path in case your header files are in a different directory than the CMakeLists.txt file.
Have a look at this blog post or the cmake documentation for further info regarding header only libraries and cmake.
A bit unrelated answer to OP but for people like me with a somewhat similar problem.
Use Case: Ubuntu (C, Clion, Auto-completion):
I had the same error,
CMake Error: Cannot determine link language for target "hello".
set_target_properties(hello PROPERTIES LINKER_LANGUAGE C) help fixes that problem but the headers aren't included to the project and the autocompletion wont work.
This is what i had
cmake_minimum_required(VERSION 3.5)
project(hello)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES ./)
add_executable(hello ${SOURCE_FILES})
set_target_properties(hello PROPERTIES LINKER_LANGUAGE C)
No errors but not what i needed, i realized including a single file as source will get me autocompletion as well as it will set the linker to C.
cmake_minimum_required(VERSION 3.5)
project(hello)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES ./1_helloworld.c)
add_executable(hello ${SOURCE_FILES})
I also faced a similar error while compiling my C-based code. I fixed the issue by correcting the source file path in my cmake file. Please check the source file path of each source file mentioned in your cmake file. This might help you too.
Simply check the path to source file. (to the respective cpp)
By default the JNI Native folder is named as jni . Renaming it to cpp fixed the issue
I managed to solve mine, by changing
add_executable(file1.cpp)
to
add_executable(ProjectName file1.cpp)
I'm attempting to run a cmake hello world program on Windows 7 x64 with both Visual Studio 2010 and Cygwin, but can't seem to get either to work. My directory structure is as follows:
HelloWorld
-- CMakeLists.txt
-- src/
-- -- CMakeLists.txt
-- -- main.cpp
-- build/
I do a cd build followed by a cmake .., and get an error stating that
CMake Error: CMake can not determine linker language for target:helloworld
CMake Error: Cannot determine link language for target "helloworld".
However, if I change the extension of main.cpp to main.c both on my filsystem and in src/CMakeLists.txt everything works as expected. This is the case running from both the Visual Studio Command Prompt (Visual Studio Solution Generator) and the Cygwin Terminal (Unix Makefiles Generator).
Any idea why this code wouldn't work?
CMakeLists.txt
PROJECT(HelloWorld C)
cmake_minimum_required(VERSION 2.8)
# include the cmake modules directory
set(CMAKE_MODULE_PATH ${HelloWorld_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
add_subdirectory(src)
src/CMakeLists.txt
# Include the directory itself as a path to include directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Create a variable called helloworld_SOURCES containing all .cpp files:
set(HelloWorld_SOURCES main.cpp)
# Create an executable file called helloworld from sources:
add_executable(hello ${HelloWorld_SOURCES })
src/main.cpp
int main()
{
return 0;
}
I also got the error you mention:
CMake Error: CMake can not determine linker language for target:helloworld
CMake Error: Cannot determine link language for target "helloworld".
In my case this was due to having C++ files with the .cc extension.
If CMake is unable to determine the language of the code correctly you can use the following:
set_target_properties(hello PROPERTIES LINKER_LANGUAGE CXX)
The accepted answer that suggests appending the language to the project() statement simply adds more strict checking for what language is used (according to the documentation), but it wasn't helpful to me:
Optionally you can specify which languages your project supports.
Example languages are CXX (i.e. C++), C, Fortran, etc. By default C
and CXX are enabled. E.g. if you do not have a C++ compiler, you can
disable the check for it by explicitly listing the languages you want
to support, e.g. C. By using the special language "NONE" all checks
for any language can be disabled. If a variable exists called
CMAKE_PROJECT__INCLUDE_FILE, the file pointed to by that
variable will be included as the last step of the project command.
In my case, it was just because there were no source file in the target. All of my code was a template with the source code in the header file. Adding an empty file.cpp solved the problem.
Try changing
PROJECT(HelloWorld C)
into
PROJECT(HelloWorld C CXX)
or just
PROJECT(HelloWorld)
See: https://cmake.org/cmake/help/latest/command/project.html
Confusing as it might be, the error also happens when a cpp file included in the project does not exist.
If you list your source files in CMakeLists.txt and mistakenly type a file name then you get this error.
I want to add another solution in case a library without any source files shall be build. Such libraries are also known as header only libraries. By default add_library expects at least one source file added or otherwise the mentioned error occurs. Since header only libraries are quite common, cmake has the INTERFACE keyword to build such libraries. The INTERFACE keyword is used as shown below and it eliminates the need for empty source files added to the library.
add_library(myLibrary INTERFACE)
target_include_directories(myLibrary INTERFACE {CMAKE_CURRENT_SOURCE_DIR})
The example above would build a header only library including all header files in the same directory as the CMakeLists.txt. Replace {CMAKE_CURRENT_SOURCE_DIR} with a path in case your header files are in a different directory than the CMakeLists.txt file.
Have a look at this blog post or the cmake documentation for further info regarding header only libraries and cmake.
A bit unrelated answer to OP but for people like me with a somewhat similar problem.
Use Case: Ubuntu (C, Clion, Auto-completion):
I had the same error,
CMake Error: Cannot determine link language for target "hello".
set_target_properties(hello PROPERTIES LINKER_LANGUAGE C) help fixes that problem but the headers aren't included to the project and the autocompletion wont work.
This is what i had
cmake_minimum_required(VERSION 3.5)
project(hello)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES ./)
add_executable(hello ${SOURCE_FILES})
set_target_properties(hello PROPERTIES LINKER_LANGUAGE C)
No errors but not what i needed, i realized including a single file as source will get me autocompletion as well as it will set the linker to C.
cmake_minimum_required(VERSION 3.5)
project(hello)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES ./1_helloworld.c)
add_executable(hello ${SOURCE_FILES})
I also faced a similar error while compiling my C-based code. I fixed the issue by correcting the source file path in my cmake file. Please check the source file path of each source file mentioned in your cmake file. This might help you too.
Simply check the path to source file. (to the respective cpp)
By default the JNI Native folder is named as jni . Renaming it to cpp fixed the issue
I managed to solve mine, by changing
add_executable(file1.cpp)
to
add_executable(ProjectName file1.cpp)