@@ -357,6 +357,37 @@ def _fill_crossfile_from_toolchain(workspace_name, tools, flags):
357357 if flags .cxx_linker_executable :
358358 dict ["CMAKE_EXE_LINKER_FLAGS_INIT" ] = _join_flags_list (workspace_name , flags .cxx_linker_executable )
359359
360+ # todo this is a kind of hacky way to handle this; I suspect once
361+ # https://github.com/bazelbuild/bazel/pull/23204 lands, it will be possible
362+ # to do this better.
363+ #
364+ # The problem being solved here is: if a toolchain wants to link the
365+ # toolchain libs statically, there are some flags that need to be passed.
366+ # Unfortunately, static linking is notoriously order-sensitive (if an
367+ # object needs a symbol, it can only be resolved by libraries _later_ than
368+ # it on the command line). This means there are scenarios where:
369+ # this works:
370+ # gcc thing.o -o stuff -l:libstdc++.a
371+ # this fails with missing symbols (like std::cout):
372+ # gcc -l:libstdc++.a -o stuff thing.o
373+ #
374+ # In other words, we need these flags to be in "<LINK_LIBRARIES>" and not
375+ # just "<LINK_FLAGS>", so they fall after the "<OBJECTS>" that might need
376+ # them and that is what this code does, by injecting these indicative flags
377+ # into CMAKE_CXX_STANDARD_LIBRARIES_INIT
378+ static_flags = []
379+ for flag in ("static-libstdc++" , "static-libgcc" , "l:libstdc++.a" ):
380+ if flags .cxx_linker_shared and _find_flag_value (flags .cxx_linker_shared , flag ):
381+ static_flags .append ("-" + flag )
382+ continue
383+
384+ if flags .cxx_linker_executable and _find_flag_value (flags .cxx_linker_executable , flag ):
385+ static_flags .append ("-" + flag )
386+ continue
387+
388+ if static_flags :
389+ dict ["CMAKE_CXX_STANDARD_LIBRARIES_INIT" ] = _join_flags_list (workspace_name , static_flags )
390+
360391 return dict
361392
362393def _find_in_cc_or_cxx (flags , flag_name_no_dashes ):
0 commit comments