diff --git a/src/modules/uxrce_dds_client/CMakeLists.txt b/src/modules/uxrce_dds_client/CMakeLists.txt index 783fac8c0f..800d33cc42 100644 --- a/src/modules/uxrce_dds_client/CMakeLists.txt +++ b/src/modules/uxrce_dds_client/CMakeLists.txt @@ -75,6 +75,42 @@ else() file(TO_CMAKE_PATH "${microxrceddsclient_make_program}" microxrceddsclient_make_program) endif() + # On Windows / MSVC, force the libmicroxrceddsclient sub-build (and the + # nested microcdr/uclient ExternalProjects it spawns via SuperBuild.cmake) + # to use NMake Makefiles instead of inheriting the parent's Ninja + # generator. The Micro-XRCE-DDS-Client SuperBuild nests ExternalProjects + # three deep (libmicroxrceddsclient_project -> microcdr -> uclient); when + # all three layers run Ninja concurrently, the inner cmake's + # `ninja -t recompact` and `ninja -t restat build.ninja` steps race the + # outer ninja that still holds microcdr-build/build.ninja open, producing + # `ninja: error: failed recompaction: Permission denied` deterministically + # on Windows where files cannot be replaced while another process has a + # handle on them. Switching the sub-build to NMake side-steps the lock + # collision entirely; nmake.exe ships with the MSVC BuildTools and is on + # PATH after vcvars64. The microcdr/uclient compile is small enough that + # the loss of Ninja's parallelism is not measurable in the overall build. + set(microxrceddsclient_extra_args) + if(WIN32 AND NOT MINGW) + find_program(microxrceddsclient_nmake_program nmake) + if(microxrceddsclient_nmake_program) + file(TO_CMAKE_PATH "${microxrceddsclient_nmake_program}" + microxrceddsclient_make_program) + list(APPEND microxrceddsclient_extra_args + CMAKE_GENERATOR "NMake Makefiles") + else() + # Without nmake we can't switch generators; fall through to the + # parent's Ninja generator and warn so the developer sees why + # the inner build may flake on `failed recompaction`. + message(WARNING + "uxrce_dds_client: nmake not found on PATH; the " + "libmicroxrceddsclient sub-build will inherit the parent " + "Ninja generator and may hit " + "'ninja: error: failed recompaction: Permission denied'. " + "Run from a Visual Studio Developer Command Prompt " + "(vcvars64) so nmake.exe is available.") + endif() + endif() + set(microxrceddsclient_library ${CMAKE_CURRENT_BINARY_DIR}/${lib_dir}/${CMAKE_STATIC_LIBRARY_PREFIX}microxrcedds_client${CMAKE_STATIC_LIBRARY_SUFFIX}) set(microcdr_library ${CMAKE_CURRENT_BINARY_DIR}/${lib_dir}/${CMAKE_STATIC_LIBRARY_PREFIX}microcdr${CMAKE_STATIC_LIBRARY_SUFFIX}) @@ -84,6 +120,7 @@ else() PREFIX ${microxrceddsclient_build_dir} SOURCE_DIR ${microxrceddsclient_src_dir} INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR} + ${microxrceddsclient_extra_args} CMAKE_CACHE_ARGS -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER}