From 3d97355fc7344498318f42635412855dabb13d22 Mon Sep 17 00:00:00 2001 From: N'yoma Diamond Date: Wed, 5 Aug 2026 16:32:50 +0100 Subject: [PATCH] Gate PUBLIC compiler-specific flags by consumer compiler ID 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 https://github.com/davisking/dlib/issues/3125 and https://github.com/davisking/dlib/pull/3126. Co-Authored-By: Claude Sonnet 5 --- dlib/CMakeLists.txt | 8 +++-- .../set_compiler_specific_options.cmake | 35 +++++++++++-------- dlib/cmake_utils/test_for_avx/CMakeLists.txt | 5 +-- dlib/cmake_utils/test_for_sse4/CMakeLists.txt | 5 +-- 4 files changed, 32 insertions(+), 21 deletions(-) diff --git a/dlib/CMakeLists.txt b/dlib/CMakeLists.txt index 04b5d92059..9c2304550b 100644 --- a/dlib/CMakeLists.txt +++ b/dlib/CMakeLists.txt @@ -807,10 +807,14 @@ if (NOT TARGET dlib) target_compile_features(dlib PUBLIC cxx_std_14) if((MSVC AND CMAKE_VERSION VERSION_LESS 3.11)) - target_compile_options(dlib PUBLIC ${active_compile_opts}) + # Old CMake/VS generators can't evaluate the generator expressions below. + target_compile_options(dlib PUBLIC ${active_compile_opts_gcc_public} ${active_compile_opts_msvc_public}) target_compile_options(dlib PRIVATE ${active_compile_opts_private}) else() - target_compile_options(dlib PUBLIC $<$:${active_compile_opts}>) + # Only forward each bucket of flags to consumers using a matching + # compiler (see https://github.com/davisking/dlib/issues/3125). + target_compile_options(dlib PUBLIC $<$:${active_compile_opts_gcc_public}>) + target_compile_options(dlib PUBLIC $<$:${active_compile_opts_msvc_public}>) target_compile_options(dlib PRIVATE $<$:${active_compile_opts_private}>) endif() diff --git a/dlib/cmake_utils/set_compiler_specific_options.cmake b/dlib/cmake_utils/set_compiler_specific_options.cmake index 6e2682da08..e9dfa262e9 100644 --- a/dlib/cmake_utils/set_compiler_specific_options.cmake +++ b/dlib/cmake_utils/set_compiler_specific_options.cmake @@ -26,23 +26,28 @@ set(gcc_like_compilers GNU Clang Intel) set(intel_archs x86_64 i386 i686 AMD64 amd64 x86) -# Setup some options to allow a user to enable SSE and AVX instruction use. +# Setup some options to allow a user to enable SSE and AVX instruction use. +# +# NOTE: public flags go into active_compile_opts_gcc_public or +# active_compile_opts_msvc_public (instead of one shared list) so that +# dlib/CMakeLists.txt can forward each bucket only to consumers using a +# matching compiler. See https://github.com/davisking/dlib/issues/3125. if ((";${gcc_like_compilers};" MATCHES ";${CMAKE_CXX_COMPILER_ID};") AND (";${intel_archs};" MATCHES ";${CMAKE_SYSTEM_PROCESSOR};") AND NOT USE_AUTO_VECTOR) option(USE_SSE2_INSTRUCTIONS "Compile your program with SSE2 instructions" OFF) option(USE_SSE4_INSTRUCTIONS "Compile your program with SSE4 instructions" OFF) option(USE_AVX_INSTRUCTIONS "Compile your program with AVX instructions" OFF) if(USE_AVX_INSTRUCTIONS) - list(APPEND active_compile_opts -mavx) + list(APPEND active_compile_opts_gcc_public -mavx) message(STATUS "Enabling AVX instructions") elseif (USE_SSE4_INSTRUCTIONS) - list(APPEND active_compile_opts -msse4) + list(APPEND active_compile_opts_gcc_public -msse4) message(STATUS "Enabling SSE4 instructions") elseif(USE_SSE2_INSTRUCTIONS) - list(APPEND active_compile_opts -msse2) + list(APPEND active_compile_opts_gcc_public -msse2) message(STATUS "Enabling SSE2 instructions") endif() -elseif (MSVC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # else if using Visual Studio +elseif (MSVC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # else if using Visual Studio # Use SSE2 by default when using Visual Studio. option(USE_SSE2_INSTRUCTIONS "Compile your program with SSE2 instructions" ON) option(USE_SSE4_INSTRUCTIONS "Compile your program with SSE4 instructions" OFF) @@ -51,13 +56,13 @@ elseif (MSVC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # else if using Visu include(CheckTypeSize) check_type_size( "void*" SIZE_OF_VOID_PTR) if(USE_AVX_INSTRUCTIONS) - list(APPEND active_compile_opts /arch:AVX) + list(APPEND active_compile_opts_msvc_public /arch:AVX) message(STATUS "Enabling AVX instructions") elseif (USE_SSE4_INSTRUCTIONS) # Visual studio doesn't have an /arch:SSE2 flag when building in 64 bit modes. # So only give it when we are doing a 32 bit build. if (SIZE_OF_VOID_PTR EQUAL 4) - list(APPEND active_compile_opts /arch:SSE2) + list(APPEND active_compile_opts_msvc_public /arch:SSE2) endif() message(STATUS "Enabling SSE4 instructions") list(APPEND active_preprocessor_switches "-DDLIB_HAVE_SSE2") @@ -67,7 +72,7 @@ elseif (MSVC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # else if using Visu # Visual studio doesn't have an /arch:SSE2 flag when building in 64 bit modes. # So only give it when we are doing a 32 bit build. if (SIZE_OF_VOID_PTR EQUAL 4) - list(APPEND active_compile_opts /arch:SSE2) + list(APPEND active_compile_opts_msvc_public /arch:SSE2) endif() message(STATUS "Enabling SSE2 instructions") list(APPEND active_preprocessor_switches "-DDLIB_HAVE_SSE2") @@ -77,7 +82,7 @@ elseif((";${gcc_like_compilers};" MATCHES ";${CMAKE_CXX_COMPILER_ID};") AND ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "^arm")) option(USE_NEON_INSTRUCTIONS "Compile your program with ARM-NEON instructions" OFF) if(USE_NEON_INSTRUCTIONS) - list(APPEND active_compile_opts -mfpu=neon) + list(APPEND active_compile_opts_gcc_public -mfpu=neon) message(STATUS "Enabling ARM-NEON instructions") endif() endif() @@ -89,13 +94,13 @@ if (CMAKE_COMPILER_IS_GNUCXX) # By default, g++ won't warn or error if you forget to return a value in a # function which requires you to do so. This option makes it give a warning # for doing this. - list(APPEND active_compile_opts "-Wreturn-type") + list(APPEND active_compile_opts_gcc_public "-Wreturn-type") endif() if ("Clang" MATCHES ${CMAKE_CXX_COMPILER_ID} AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0.0) # Clang 6 had a default template recursion depth of 256. This was changed to 1024 in Clang 7. # It must be increased on Clang 6 and below to ensure that the dnn examples don't error out. - list(APPEND active_compile_opts "-ftemplate-depth=500") + list(APPEND active_compile_opts_gcc_public "-ftemplate-depth=500") endif() if (MSVC) @@ -103,17 +108,17 @@ if (MSVC) # However, code generated by file_to_code_ex and code using DNN module can have # them. So this flag enables > 65k sections, but produces .obj files # that will not be readable by VS 2005. - list(APPEND active_compile_opts "/bigobj") + list(APPEND active_compile_opts_msvc_public "/bigobj") # Build dlib with all cores. Don't propagate the setting to client programs # though since they might compile large translation units that use too much # RAM. list(APPEND active_compile_opts_private "/MP") - if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 3.3) + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 3.3) # Clang can compile all Dlib's code at Windows platform. Tested with Clang 5 - list(APPEND active_compile_opts -Xclang) - list(APPEND active_compile_opts -fcxx-exceptions) + list(APPEND active_compile_opts_msvc_public -Xclang) + list(APPEND active_compile_opts_msvc_public -fcxx-exceptions) endif() endif() diff --git a/dlib/cmake_utils/test_for_avx/CMakeLists.txt b/dlib/cmake_utils/test_for_avx/CMakeLists.txt index 44363bc5ec..0367b1058f 100644 --- a/dlib/cmake_utils/test_for_avx/CMakeLists.txt +++ b/dlib/cmake_utils/test_for_avx/CMakeLists.txt @@ -4,12 +4,13 @@ project(avx_test) set(USE_AVX_INSTRUCTIONS ON CACHE BOOL "Use AVX instructions") -# Pull this in since it sets the AVX compile options by putting that kind of stuff into the active_compile_opts list. +# Pull this in since it sets the AVX compile options by putting that kind of stuff into the +# active_compile_opts_gcc_public / active_compile_opts_msvc_public lists. include(../set_compiler_specific_options.cmake) try_run(run_result compile_result ${PROJECT_BINARY_DIR}/avx_test_try_run_build ${CMAKE_CURRENT_LIST_DIR}/avx_test.cpp - COMPILE_DEFINITIONS ${active_compile_opts}) + COMPILE_DEFINITIONS ${active_compile_opts_gcc_public} ${active_compile_opts_msvc_public}) message(STATUS "run_result = ${run_result}") message(STATUS "compile_result = ${compile_result}") diff --git a/dlib/cmake_utils/test_for_sse4/CMakeLists.txt b/dlib/cmake_utils/test_for_sse4/CMakeLists.txt index 6d3a5b372b..0da5d7fd3d 100644 --- a/dlib/cmake_utils/test_for_sse4/CMakeLists.txt +++ b/dlib/cmake_utils/test_for_sse4/CMakeLists.txt @@ -4,12 +4,13 @@ project(sse4_test) set(USE_SSE4_INSTRUCTIONS ON CACHE BOOL "Use SSE4 instructions") -# Pull this in since it sets the SSE4 compile options by putting that kind of stuff into the active_compile_opts list. +# Pull this in since it sets the SSE4 compile options by putting that kind of stuff into the +# active_compile_opts_gcc_public / active_compile_opts_msvc_public lists. include(../set_compiler_specific_options.cmake) try_run(run_result compile_result ${PROJECT_BINARY_DIR}/sse4_test_try_run_build ${CMAKE_CURRENT_LIST_DIR}/sse4_test.cpp - COMPILE_DEFINITIONS ${active_compile_opts}) + COMPILE_DEFINITIONS ${active_compile_opts_gcc_public} ${active_compile_opts_msvc_public}) message(STATUS "run_result = ${run_result}") message(STATUS "compile_result = ${compile_result}")