-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Description
What Operating System(s) are you seeing this problem on?
Windows
dlib version
20.0.0
Python version
3.12.7
Compiler
MSVC 19.44.35217 & clang 19.1.5
Expected Behavior
Binaries/targets/configuration files generated using MSVC are usable in projects compiled using clang[++]
Current Behavior
If dlib is built using MSVC, the /bigobj option is always set in the configuration target, causing it to be erroneously passed to the compiler of the consuming project if the consumer is not using MSVC (i.e., using clang[++] instead).
Steps to Reproduce
- Build dlib using MSVC
- Link a consuming project to dlib (via
find_package(dlib CONFIG REQUIRED)andtarget_link_libraries(${PROJECT_NAME} PUBLIC dlib::dlib)) - Build consuming project using clang[++] (e.g., using
CMAKE_CXX_COMPILERset toclang++)
Anything else?
When dlib is built using MSVC ([clang-]cl.exe), but then linked to using another (compatible) non-MSVC compiler (i.e., clang[++]), the /bigobj setting persists outside of the relevant context (dlib's compile time), causing an error.
In my case, I'm building dlib using MSVC (cl.exe to be specific) for development on my system / within my development environment. However, when compiling my project I intend to use clang[++]. Other libraries handle this just fine, but in dlib the /bigobj option persists when attempting to run clang[++] on my project, causing the following error:
Cannot get compiler information:
Compiler exited with error code 1: C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\Llvm\x64\bin\clang++.exe -xc++ -isystemC:/Users/Nyoma/Documents/MyProject/build/debug/vcpkg_installed/x64-windows/include -O0 -std=gnu++20 -D_DEBUG -D_DLL -D_MT -Xclang --dependent-lib=msvcrtd -g -Xclang -gcodeview /bigobj -fpch-preprocess -v -dD -E
clang version 19.1.5
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\Llvm\x64\bin
clang++: error: no such file or directory: '/bigobj'
The problem appears to come from the contents active_compile_opts being injected into the generated dlib.cmake at compile time for dlib, rather than at build time for the consumer, causing /bigopt to be used even when the context has switched to no longer use MSVC.
In the generated dlib.cmake file:
set_target_properties(dlib::dlib PROPERTIES
INTERFACE_COMPILE_FEATURES "cxx_std_14"
INTERFACE_COMPILE_OPTIONS "\$<\$<COMPILE_LANGUAGE:CXX>:/bigobj>" # <-- Here
INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
INTERFACE_LINK_LIBRARIES "LAPACK::LAPACK;BLAS::BLAS;\$<LINK_ONLY:ws2_32>;\$<LINK_ONLY:winmm>;\$<\$<NOT:\$<CONFIG:DEBUG>>:${VCPKG_IMPORT_PREFIX}/lib/libpng16.lib>;\$<\$<CONFIG:DEBUG>:${VCPKG_IMPORT_PREFIX}/debug/lib/libpng16d.lib>;\$<\$<NOT:\$<CONFIG:DEBUG>>:${VCPKG_IMPORT_PREFIX}/lib/zlib.lib>;\$<\$<CONFIG:DEBUG>:${VCPKG_IMPORT_PREFIX}/debug/lib/zlibd.lib>;\$<\$<NOT:\$<CONFIG:DEBUG>>:${VCPKG_IMPORT_PREFIX}/lib/jpeg.lib>;\$<\$<CONFIG:DEBUG>:${VCPKG_IMPORT_PREFIX}/debug/lib/jpeg.lib>"
)This is caused by /bigobj being appended to the active_compile_opts variable in dlib/cmake_utils/set_compiler_specific_options.cmake:
if(MSVC)
#...
list(APPEND active_compile_opts "/bigobj")
#...
endif()and then added to the target compile properties via the following in dlib/CMakeLists.txt:
if((MSVC AND CMAKE_VERSION VERSION_LESS 3.11))
target_compile_options(dlib PUBLIC ${active_compile_opts})
target_compile_options(dlib PRIVATE ${active_compile_opts_private})
else()
target_compile_options(dlib PUBLIC $<$<COMPILE_LANGUAGE:CXX>:${active_compile_opts}>)
target_compile_options(dlib PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${active_compile_opts_private}>)
endif()((Side note 1: set_compiler_specific_options.cmake also appends /MP into active_compile_opts right after /bigobj, but it doesn't seem to appear in dlib.cmake or the clang++ call for which the error occurs. Not really sure why))
This appears to effectively apply the assumption that if MSVC was used to compile dlib initially, then any consumer must also be using MSVC, which is not necessarily true. This also introduces the problem of being unable to distribute pre-compiled dlib binaries with their generated config/target files for Windows unless we mandate that the consumer is using MSVC. If this behavior is expected for some reason, it should really be documented, but in practice it would be much better to just remove this restriction altogether. ((Side note 2: shouldn't edit: I misread the syntax, this is fine)).$<$<COMPILE_LANGUAGE:CXX>: be applied to each element of active_compile_opts[_private]? The current approach only applies it to the first option if multiple are present.
In practice, I believe this would be solved by restructuring the relevant checks so that the necessary Edit: This is wrong/misdiagnosis where/why the flag propagates in dlib but not in other libraries. Actually resolved by changing target options/features from target_compile_options calls are performed by dlib/cmake_utils/dlibConfig.cmake.in / dlibConfig.cmake when dlib is linked/consumed rather than initially compiled, and/or via via CMAKE_C[XX]_FLAGS, as these are the approaches I see from other libraries (namely CGAL). ((Side note 3: Despite having functionality for it, other dependencies that I'm using don't seem to add /bigobj to INTERFACE_COMPILE_OPTIONS even when using MSVC exclusively. I'm not super well-versed in this side of CMake/compiler interaction so I'm not 100% clear what's necessary or not here, but I thought I'd mention it)).PUBLIC to PRIVATE. See: #3125 (comment)
This is somewhat related to #2921, which noticed an issue related /bigobj when using g++/MinGW, but failed to sufficiently explain their actual configuration details or investigate what was causing the problem. This lead to vcpkg being pointed to as a potential culprit (which I believe is almost certainly wrong), or possibly attempting to link MSVC binaries with MinGW (a much more likely cause in the case of #2921 specifically, but they don't provide enough details to verify whether or not they built dlib using MSVC or MinGW).
In my case, I'm running into this issue in a repeatable context without MinGW. Admittedly, I am running into this error via vcpkg, which @davisking said the port for which is not developed by the maintainers of this library directly (#2921 (comment)); however I expect this issue would persist even outside of the vcpkg context due to the /bigobj being directly applied to the dlib.cmake target when dlib is built (I just don't currently have a workflow set up to test this outside of vcpkg).
Edit: A significant realization is that this bug makes cross-compiling much more challenging on some setups (if possible at all). Because host-side development may occur using dlib compiled via MSVC, but then target a non-MSVC compatible system for distribution (e.g., Linux, MacOS) and thus require a different compiler/linker, the /bigobj compile option will cause a build failure