ARTICLE AD BOX
While refactoring some legacy code I ran into some strange behaviour of CMake+GCC that I can not explain or correct.
This is what I have:
Debian Trixie with GCC 14.2.0 and CMake 3.31.6 A test project with two .cpp files and one .h file which builds. A test project and static lib with the same code which does not build without compiler/linker warnings.Converting some legacy sources which is not using the latest coding style I have to use printf with size_t values. Checking: sizeof(size_t) = 8, as expected for a long long unsigned base type. And in the formats used by printf a value of size_t is coded as %llu. When the value comes from 'local' code it is fine. But when the value comes from some static library code and error message is generated that the base type is long unsigned and it should be coded as %lu When I change the coding to %zu there is no warning but I assume it is not realy a fix for the problem.
While the compiler is complaining during the build of the version with the static library the result is running without problems. It is not clear to me what the status is of the compiler message. Is the footprint of size_t realy different or is this some strange artefact from using static libraries? I need to understand what is going on, just not to get confused in future problems (which might or might not have anything to do with this behavour.)
I have searched but have not found anything explaing the things that I see. If there is any questiong here related to this then I have not recognised it.
I've done some testing to get to some minimum example to recreate the behaviour 'in vitro'. Tests 4 and 5 have the same code and a different build model and do show different behavour during compiling/linking. (For all source code and test results, see below.)
three source files a test#.cpp with main(...) using printf(...) a test#list.h with a simple class. a test#list.cpp with some behavour of the class in it using printf(...)When the three files are build in one executable it compiles without any problems. When test#list.cpp is build into a static library and linked to an executable there are problems. The compiler options are not what I use for every project; -Wall;-Wshadow;-Wunused;-Wfatal-errors;-fno-diagnostics-show-caret.
My suspicion is that I forget some compiler options when building the static library but I do not know which one(s).
Here are the source files, to begin with CMakeLists.txt and then six source files (two sets of three files). Test are done with cmake 3.31.6, default install of Debian Trixie. I have done the same tests with MSVC where none of the problems occure, there I'm using cmake 4.2.1. (Not realy a good comparion, I know.)
cmake_minimum_required ( VERSION 3.31.6...4.2.1 ) project( "TestSizeT" LANGUAGES CXX) set(BUILD_SHARED_LIBS OFF) add_library(compiler_flags INTERFACE) set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,GNU>") set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>") target_compile_options( compiler_flags INTERFACE "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wshadow;-Wunused;-Wfatal-errors;-fno-diagnostics-show-caret>>" "$<${msvc_cxx}:$<BUILD_INTERFACE:-W4;/Zc:__cplusplus>>" ) add_executable(Test4 test4.cpp test4list.cpp) target_link_libraries(Test4 INTERFACE compiler_flags) add_library(libTest5 STATIC test5list.cpp) set_target_properties(libTest5 PROPERTIES LINKER_LANGUAGE CXX POSITION_INDEPENDENT_CODE ON) target_link_libraries(libTest5 INTERFACE compiler_flags) add_executable(Test5 test5.cpp) target_link_libraries(Test5 INTERFACE compiler_flags) target_link_libraries(Test5 PUBLIC libTest5)test4.cpp (except for line 1 identical to test5.cpp)
#include "test4list.h" #include <iostream> #include <cstddef> int main() { list a{}; a.add(sizeof(std::size_t)); a.dump(); fprintf(stdout, "sizeof(size_t) = (size_t)%zu\n", sizeof(std::size_t)); fprintf(stdout, "sizeof(size_t) = (long long unsigned)%llu\n", sizeof(std::size_t)); }test5.cpp (except for line 1 identical to test4.cpp)
#include "test5list.h" #include <iostream> #include <cstddef> int main() { list a{}; a.add(sizeof(std::size_t)); a.dump(); fprintf(stdout, "sizeof(size_t) = (size_t)%zu\n", sizeof(std::size_t)); fprintf(stdout, "sizeof(size_t) = (long long unsigned)%llu\n", sizeof(std::size_t)); }test4list.h and test5list.h (identical files)
#pragma once #include <vector> class list : public std::vector<int> { public: void add(int); void dump(); };test4list.cpp (except for line 1 idential to test5list.cpp)
#include "test4list.h" #include <iostream> void list::add(int value) { push_back(value); } void list::dump() { fprintf(stdout, "list: sizeof(size_t) = (size_t)%zu\n", sizeof(std::size_t)); fprintf(stdout, "list: sizeof(size_t) = (long long unsigned)%llu\n", sizeof(std::size_t)); for (size_t i = 0; i < size(); i++) { fprintf(stdout, "list[(size_t)%zu] = %d\n", i, at(i)); fprintf(stdout, "list[(long long unsigned)%llu] = %d\n", i, at(i)); } }test5list.cpp (except for line 1 idential to test4list.cpp)
#include "test5list.h" #include <iostream> void list::add(int value) { push_back(value); } void list::dump() { fprintf(stdout, "list: sizeof(size_t) = (size_t)%zu\n", sizeof(std::size_t)); fprintf(stdout, "list: sizeof(size_t) = (long long unsigned)%llu\n", sizeof(std::size_t)); for (size_t i = 0; i < size(); i++) { fprintf(stdout, "list[(size_t)%zu] = %d\n", i, at(i)); fprintf(stdout, "list[(long long unsigned)%llu] = %d\n", i, at(i)); } }The CMake generator phase is no problem and cmake build is failing Here are the details.
andre@debian:~/development/_test/SizeT$ cmake -S . -B ./build --fresh -- The CXX compiler identification is GNU 14.2.0 -- 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 (0.6s) -- Generating done (0.0s) -- Build files have been written to: /home/andre/development/_test/SizeT/build andre@debian:~/development/_test/SizeT$ cmake --build ./build --clean-first [ 14%] Building CXX object CMakeFiles/Test4.dir/test4.cpp.o [ 28%] Building CXX object CMakeFiles/Test4.dir/test4list.cpp.o [ 42%] Linking CXX executable Test4 [ 42%] Built target Test4 [ 57%] Building CXX object CMakeFiles/libTest5.dir/test5list.cpp.o [ 71%] Linking CXX static library liblibTest5.a [ 71%] Built target libTest5 [ 85%] Building CXX object CMakeFiles/Test5.dir/test5.cpp.o /home/andre/development/_test/SizeT/test5.cpp: In function ‘int main()’: /home/andre/development/_test/SizeT/test5.cpp:10:62: warning: format ‘%llu’ expects argument of type ‘long long unsigned int’, but argument 3 has type ‘long unsigned int’ [-Wformat=] [100%] Linking CXX executable Test5 [100%] Built target Test5 andre@debian:~/development/_test/SizeT$Both tests run without reporting problems.
andre@debian:~/development/_test/SizeT$ ./build/Test4 ; echo $? list: sizeof(size_t) = (size_t)8 list: sizeof(size_t) = (long long unsigned)8 list[(size_t)0] = 8 list[(long long unsigned)0] = 8 sizeof(size_t) = (size_t)8 sizeof(size_t) = (long long unsigned)8 0 andre@debian:~/development/_test/SizeT$ ./build/Test5 ; echo $? list: sizeof(size_t) = (size_t)8 list: sizeof(size_t) = (long long unsigned)8 list[(size_t)0] = 8 list[(long long unsigned)0] = 8 sizeof(size_t) = (size_t)8 sizeof(size_t) = (long long unsigned)8 0 andre@debian:~/development/_test/SizeT$