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:
.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.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.#pragma
instructions. While this worked, every SFML file has dozens of different errors, and I want to avoid using #pragma
s everywhere (or wrapping SFML's headers in my own headers that just wrap the #include
instruction in #pragma
s).Is it even possible to suppress these warnings for my library headers without #pragma
s? 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:
Use -Wno-dev to suppress it. You can disable the warning like this when you are configuring your build.
To suppress this warning use the unused attribute (see Variable Attributes). This warning is also enabled by -Wunused , which is enabled by -Wall . Warn whenever a static function is declared but not defined or a non-inline static function is unused.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With