Gate PUBLIC compiler-specific flags by consumer compiler ID - #3157
Conversation
Fixes cross-compiler linking (e.g. MSVC-built dlib consumed by clang++) where PUBLIC flags like /bigobj were unconditionally forced onto every downstream consumer regardless of which compiler it used. Splits the shared active_compile_opts list into active_compile_opts_gcc_public and active_compile_opts_msvc_public, and forwards each bucket to consumers only via a COMPILE_LANG_AND_ID generator expression matching their own compiler. MSVC consumers still get /bigobj automatically; non-MSVC consumers no longer receive it. See davisking#3125 and davisking#3126. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
The fail on Python / Ubuntu appears to be a separate problem. Builds fine but one runtime test produces a failing result. Seems likely to be a stochastic error since it passed fine on the Windows check or maybe caused by some difference under the hood between Windows vs. Linux/Ubuntu regarding floating point operations? In any case I don't think it's a result of this change As a side note: With this fix in place, it may be worth adding new CI checks that verify future changes don't regress this issue |
|
Yeah that error wasn't your PR. I'll review this stuff in a bit. Seems good at first glance though. |
Select compiler-specific options when the installed package is consumed instead of exporting options for the compiler that built dlib. This preserves /bigobj for MSVC and clang-cl, avoids passing it to clang++, and translates configured SIMD options to the consumer's frontend. Add regression coverage for installed packages using MSVC, clang++, and clang-cl.
|
I pushed a commit that keeps compiler-specific options out of the installed target and reconstructs them in dlibConfig.cmake for the consuming compiler. This is necessary because dlib may be built with one compiler frontend and consumed with another—for example, built with MSVC and consumed with GNU-style Clang or clang-cl. The new arrangement should keep the existing behavior for build-tree users, selects /bigobj, SIMD, exception, warning, and template-depth options according to the consumer’s |
|
Alright, CI is happy. This still working for you? |
|
Yup this looks good. All functional from my end |
|
Sweet. Thanks for the PR :D |
Backport the fix from davisking/dlib#3157: compiler-specific PUBLIC flags (e.g. /bigobj, /arch:AVX, -mavx) are now gated in dlibConfig.cmake by the *consuming* compiler's ID instead of being forced onto every downstream consumer regardless of which compiler they use. This fixes builds where dlib is built with MSVC and consumed with a non-MSVC compiler such as Clang++, which previously failed because /bigobj was rejected by Clang. Fixes microsoft#49035. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Fixes #3125.
Problem
dlib's CMake build applies compiler-specific flags (e.g.
/bigobjon MSVC,-mavx/-msse4on GCC-like compilers) to thedlibtarget withPUBLICscope, so they get baked into the exporteddlib.cmakeand forced onto every downstream consumer regardless of what compiler the consumer uses. This breaks whenever the build compiler and consumer compiler differ, since a flag one compiler understands is often rejected outright by another (the reported case: MSVC-built dlib +clang++consumer, whereclang++errors on/bigobj).This is especially easy to hit with vcpkg: a triplet controls which compiler builds a dependency independently of what compiler the consuming project uses, so it's entirely normal to end up with an MSVC-built dlib (per triplet) linked into a project built with
clang++(my case) without doing anything unusual.#3126 tried fixing this by making the flags
PRIVATE, but that stops them reaching any consumer, including same-compiler ones that need them (e.g. MSVC clients that rely on/bigobjbeing set automatically), which is why it stalled.This fix
Keep the flags
PUBLIC, but gate each one behind a generator expression checked against the consumer's compiler ID instead of the compiler dlib itself was built with:dlib/cmake_utils/set_compiler_specific_options.cmake: splitsactive_compile_optsintoactive_compile_opts_gcc_public(GNU/Clang/Intel flags) andactive_compile_opts_msvc_public(MSVC-only flags).dlib/CMakeLists.txt: applies each bucket viatarget_compile_options(dlib PUBLIC $<$<COMPILE_LANG_AND_ID:CXX,...>:...>), so a bucket only reaches a consumer whose ownCXX_COMPILER_IDmatches. A mismatched consumer gets neither.test_for_sse4/test_for_avxCMakeLists updated for the renamed variables.A same-compiler consumer sees no behavior change. A different-compiler consumer no longer receives flags it can't parse.
COMPILE_LANG_AND_IDneeds CMake ≥3.15; dlib already requires ≥3.17.Testing
dlib.cmakenow shows$<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/bigobj>instead of an unconditional/bigobj.clang++(x86_64-pc-windows-msvc) via a downstream CMake+vcpkg project — fails on/bigobjbefore this change, compiles and links cleanly after.Known limitation
clang-cl building dlib + clang-cl consuming it won't get
/bigobjforwarded either, sinceCXX_COMPILER_IDisClangthere, notMSVC.$<CXX_COMPILER_FRONTEND_VARIANT:MSVC>would cover it but needs CMake ≥3.30. Can add behind a version check if wanted.