Using cmake_llvm_rc when cross-compiling.

Hi,

I’m trying to cross-compiling libraries with CLang-cl and llvm-rc.

First, CMake glues together the parameter key and the parameter value together which is not supported by llvm-rc.
For example: /l0x409 -DGOOGLE_PROTOBUF_CMAKE_BUILD

Second, I don’t know why, but building the RC file with vcpkg for glew works fine, the RC file is being pre-processed before it is sent to llvm-rc, but for protobuf, the RC file is not.

Here are extracts of the rules.ninja:

glew ninja.rules

#############################################
# Rule for compiling RC files.

rule RC_COMPILER__glew_s_Release
  depfile = $DEP_FILE
  deps = gcc
  command = /vcpkg/downloads/tools/cmake-3.19.2-linux/cmake-3.19.2-Linux-x86_64/bin/cmake -E cmake_llvm_rc $in $out.pp /usr/bin/clang-cl-9 $DEFINES -DRC_INVOKED $INCLUDES $FLAGS -clang:-MD -clang:-MF -clang:$DEP_FILE  -E -- $in ++ /clang_windows_sdk/llvm-rc $DEFINES -I SOURCE_DIR $INCLUDES /fo $out $out.pp
  description = Building RC object $out

protobuf ninja.rules

#############################################
# Rule for compiling RC files.

rule RC_COMPILER__libprotobuf-lite_Release
  depfile = $DEP_FILE
  deps = gcc
  command = /clang_windows_sdk/llvm-rc /l0x409 $DEFINES /fo$out $in
  description = Building RC object $out

How can I force cmake to call the cmake_llvm_rc preprocessor ?

I suspect that the CMake code is poking variables that CMake uses to track what the RC compiler is and how CMake should use it. Is there anything “interesting” in protobuf’s CMake that is trying to mess with llvm-rc itself?

Hmm, the only thing I can find about CMake and the RC file is this code:

if (MSVC)
  # Build with multiple processes
  add_definitions(/MP)
  # MSVC warning suppressions
  add_definitions(
    /wd4018 # 'expression' : signed/unsigned mismatch
    /wd4065 # switch statement contains 'default' but no 'case' labels
    /wd4146 # unary minus operator applied to unsigned type, result still unsigned
    /wd4244 # 'conversion' conversion from 'type1' to 'type2', possible loss of data
    /wd4251 # 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2'
    /wd4267 # 'var' : conversion from 'size_t' to 'type', possible loss of data
    /wd4305 # 'identifier' : truncation from 'type1' to 'type2'
    /wd4307 # 'operator' : integral constant overflow
    /wd4309 # 'conversion' : truncation of constant value
    /wd4334 # 'operator' : result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
    /wd4355 # 'this' : used in base member initializer list
    /wd4506 # no definition for inline function 'function'
    /wd4800 # 'type' : forcing value to bool 'true' or 'false' (performance warning)
    /wd4996 # The compiler encountered a deprecated declaration.
  )
  # Allow big object
  add_definitions(/bigobj)
  string(REPLACE "/" "\\" PROTOBUF_SOURCE_WIN32_PATH ${protobuf_SOURCE_DIR})
  string(REPLACE "/" "\\" PROTOBUF_BINARY_WIN32_PATH ${protobuf_BINARY_DIR})
  string(REPLACE "." ","  protobuf_RC_FILEVERSION "${protobuf_VERSION}")
  configure_file(extract_includes.bat.in extract_includes.bat)

  # Suppress linker warnings about files with no symbols defined.
  set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221")

  # Configure Resource Compiler
  enable_language(RC)
  # use English language (0x409) in resource compiler
  set(rc_flags "/l0x409")
  # fix rc.exe invocations because of usage of add_definitions()
  set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> ${rc_flags} <DEFINES> /fo<OBJECT> <SOURCE>")

  configure_file(version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY)
endif (MSVC)

Thanks to your comment, I found the culprit:

set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> ${rc_flags} <DEFINES> /fo<OBJECT> <SOURCE>")

Commenting this line works when using llvm-rc. And for my first issue, I built a wrapper that split the parameter key from the parameter value.

Yeah, that is “messing” with CMake internals. Protobuf really shouldn’t be doing that and instead file an issue to have CMake just work properly.