Skip to content

Commit 58beb50

Browse files
committed
[build] Pass a more specific compiler from CMake to Bazel
Add logic to parse 'cc'/'c++' into the appropriate underlying compiler using //tools/cc_toolchain:print_compiler_config. Linux CMake users can now inherit Drake's Bazel @rules_cc//cc/compiler logic without having to specify CMAKE_<LANG>_COMPILER as explicitly gcc or clang.
1 parent 62023e3 commit 58beb50

File tree

1 file changed

+93
-21
lines changed

1 file changed

+93
-21
lines changed

CMakeLists.txt

Lines changed: 93 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,12 @@ if(NOT Bazel_FOUND)
105105
endif()
106106

107107
get_filename_component(C_COMPILER_REALPATH "${CMAKE_C_COMPILER}" REALPATH)
108-
get_filename_component(C_COMPILER_NAME "${C_COMPILER_REALPATH}" NAME)
108+
get_filename_component(C_COMPILER_REALNAME "${C_COMPILER_REALPATH}" NAME)
109109

110110
get_filename_component(CXX_COMPILER_REALPATH "${CMAKE_CXX_COMPILER}" REALPATH)
111-
get_filename_component(CXX_COMPILER_NAME "${CXX_COMPILER_REALPATH}" NAME)
111+
get_filename_component(CXX_COMPILER_REALNAME "${CXX_COMPILER_REALPATH}" NAME)
112112

113-
if(C_COMPILER_NAME STREQUAL ccache OR CXX_COMPILER_NAME STREQUAL ccache)
113+
if(C_COMPILER_REALNAME STREQUAL ccache OR CXX_COMPILER_REALNAME STREQUAL ccache)
114114
message(FATAL_ERROR
115115
"Compilation with ccache is NOT supported due to incompatibility with Bazel"
116116
)
@@ -288,13 +288,81 @@ if(NOT PYTHON_VERSION_MAJOR_MINOR VERSION_EQUAL SUPPORTED_PYTHON_VERSION)
288288
)
289289
endif()
290290

291-
set(BAZEL_REPO_ENV)
291+
set_property(GLOBAL PROPERTY BAZEL_REPO_ENV)
292292

293+
# Set the compiler for Bazel via --repo_env={CC|CXX}=<compiler>.
294+
function(set_bazel_compiler lang compiler)
295+
if(lang STREQUAL "C")
296+
set_property(GLOBAL APPEND_STRING PROPERTY BAZEL_REPO_ENV
297+
" --repo_env=CC=${compiler}")
298+
message(STATUS "Using compiler: CC=${compiler}")
299+
else()
300+
set_property(GLOBAL APPEND_STRING PROPERTY BAZEL_REPO_ENV
301+
" --repo_env=CXX=${compiler}")
302+
message(STATUS "Using compiler: CXX=${compiler}")
303+
endif()
304+
endfunction()
305+
306+
# Use //tools/cc_toolchain:print_compiler_config to find the appropriate
307+
# path to the compiler, and set it in Bazel's repo_env. If there is an error
308+
# at any point, fallback to CMAKE_<LANG>_COMPILER.
309+
function(find_compiler lang)
310+
if(CMAKE_${lang}_COMPILER_ID STREQUAL GNU)
311+
set(compiler "gcc")
312+
elseif(CMAKE_${lang}_COMPILER_ID STREQUAL Clang)
313+
set(compiler "clang")
314+
else()
315+
# At this point, a warning would have already been emitted earlier.
316+
set_bazel_compiler("${lang}" "${CMAKE_${lang}_COMPILER}")
317+
return()
318+
endif()
319+
320+
set(COMPILER_CONFIG_ARGS
321+
run --config=${compiler}
322+
//tools/cc_toolchain:print_compiler_config)
323+
324+
execute_process(COMMAND ${Bazel_EXECUTABLE} ${COMPILER_CONFIG_ARGS}
325+
WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}"
326+
OUTPUT_VARIABLE COMPILER_CONFIG_OUTPUT
327+
RESULT_VARIABLE COMPILER_CONFIG_RETURN_VALUE)
328+
329+
if(NOT COMPILER_CONFIG_RETURN_VALUE EQUAL 0)
330+
message(WARNING "Compiler configuration could not be obtained.")
331+
set_bazel_compiler("${lang}" "${CMAKE_${lang}_COMPILER}")
332+
return()
333+
endif()
334+
335+
# Extract the compiler variable for the given language.
336+
STRING(REPLACE "\n" ";" COMPILER_CONFIG_OUTPUT "${COMPILER_CONFIG_OUTPUT}")
337+
foreach(COMPILER_CONFIG_ENTRY IN LISTS COMPILER_CONFIG_OUTPUT)
338+
# This only works for C because 'CC' ends with 'C'...
339+
if("${COMPILER_CONFIG_ENTRY}" MATCHES ".*${lang}=(.*)$")
340+
set(compiler_command "${CMAKE_MATCH_1}")
341+
endif()
342+
endforeach()
343+
message("${compiler_command}")
344+
set_bazel_compiler("${lang}" "${compiler_command}")
345+
endfunction()
346+
347+
# On Linux, where there is more than one officially supported compiler, pass
348+
# the C and CXX compilers to Bazel.
293349
if(NOT APPLE)
294-
string(APPEND BAZEL_REPO_ENV
295-
" --repo_env=CC=${CMAKE_C_COMPILER}"
296-
" --repo_env=CXX=${CMAKE_CXX_COMPILER}"
297-
)
350+
# Try to detect if 'cc' is really gcc or clang.
351+
# Otherwise, default to CMAKE_<LANG>_COMPILER.
352+
get_filename_component(C_COMPILER_NAME "${CMAKE_C_COMPILER}" NAME)
353+
if(C_COMPILER_NAME STREQUAL "cc")
354+
find_compiler("C")
355+
else()
356+
set_bazel_compiler("C" "${CMAKE_C_COMPILER}")
357+
endif()
358+
359+
# Ditto the above for c++ -> g++ or clang++.
360+
get_filename_component(CXX_COMPILER_NAME "${CMAKE_CXX_COMPILER}" NAME)
361+
if(CXX_COMPILER_NAME STREQUAL "c++")
362+
find_compiler("CXX")
363+
else()
364+
set_bazel_compiler("CXX" "${CMAKE_CXX_COMPILER}")
365+
endif()
298366
endif()
299367

300368
get_filename_component(PROJECT_BINARY_DIR_REALPATH
@@ -371,7 +439,7 @@ function(symlink_external_repository_libs NAME TARGET USE_SO_MINOR_VERSION)
371439
file(CREATE_LINK "${location}" "${workspace}/${NAME}/lib/${other_basename}" SYMBOLIC)
372440
endfunction()
373441

374-
macro(override_module NAME)
442+
function(override_module NAME)
375443
set(local_path "${CMAKE_CURRENT_BINARY_DIR}/external/workspace/${NAME}")
376444
file(GENERATE OUTPUT "${local_path}/MODULE.bazel"
377445
INPUT "${CMAKE_CURRENT_SOURCE_DIR}/cmake/external/workspace/${NAME}/MODULE.bazel.in")
@@ -381,24 +449,24 @@ macro(override_module NAME)
381449
"${PROJECT_SOURCE_DIR}/cmake/external/workspace/conversion.bzl"
382450
"${local_path}/conversion.bzl"
383451
SYMBOLIC)
384-
string(APPEND BAZEL_REPO_ENV
452+
set_property(GLOBAL APPEND_STRING PROPERTY BAZEL_REPO_ENV
385453
" --override_module=${NAME}=${local_path}")
386-
string(APPEND BAZEL_REPO_ENV
454+
set_property(GLOBAL APPEND_STRING PROPERTY BAZEL_REPO_ENV
387455
" --@drake//tools/workspace/${NAME}:with_user_${NAME}=True")
388-
endmacro()
456+
endfunction()
389457

390-
macro(override_repository NAME)
458+
function(override_repository NAME)
391459
set(local_path "${CMAKE_CURRENT_BINARY_DIR}/external/workspace/${NAME}")
392460
file(MAKE_DIRECTORY "${local_path}")
393461
file(GENERATE OUTPUT "${local_path}/MODULE.bazel"
394462
INPUT "${CMAKE_CURRENT_SOURCE_DIR}/cmake/external/workspace/${NAME}/MODULE.bazel.in")
395463
file(GENERATE OUTPUT "${local_path}/BUILD.bazel"
396464
INPUT "${CMAKE_CURRENT_SOURCE_DIR}/cmake/external/workspace/${NAME}/BUILD.bazel.in")
397-
string(APPEND BAZEL_REPO_ENV
465+
set_property(GLOBAL APPEND_STRING PROPERTY BAZEL_REPO_ENV
398466
" --override_repository=drake++drake_dep_repositories+${NAME}=${local_path}")
399-
string(APPEND BAZEL_REPO_ENV
467+
set_property(GLOBAL APPEND_STRING PROPERTY BAZEL_REPO_ENV
400468
" --@drake//tools/workspace/${NAME}:with_user_${NAME}=True")
401-
endmacro()
469+
endfunction()
402470

403471
if(APPLE AND DRAKE_CI_ENABLE_PACKAGING)
404472
# When building a macOS *.tar.gz binary release, never use Homebrew for C++
@@ -496,10 +564,10 @@ if(APPLE)
496564
# routine, and then remove this APPLE-specific logic. When doing so, don't
497565
# forget to fix our doc/_pages/from_source.md documentation at the same time.
498566
if(WITH_USER_ZLIB)
499-
string(APPEND BAZEL_REPO_ENV
567+
set_property(GLOBAL APPEND_STRING PROPERTY BAZEL_REPO_ENV
500568
" --@drake//tools/flags:zlib_repo=hardcoded")
501569
else()
502-
string(APPEND BAZEL_REPO_ENV
570+
set_property(GLOBAL APPEND_STRING PROPERTY BAZEL_REPO_ENV
503571
" --@drake//tools/flags:zlib_repo=source")
504572
endif()
505573
else()
@@ -544,7 +612,8 @@ if(WITH_GUROBI)
544612

545613
if(NOT APPLE)
546614
get_filename_component(GUROBI_HOME "${Gurobi_INCLUDE_DIRS}" DIRECTORY)
547-
string(APPEND BAZEL_REPO_ENV " --repo_env=GUROBI_HOME=${GUROBI_HOME}")
615+
set_property(GLOBAL APPEND_STRING PROPERTY BAZEL_REPO_ENV
616+
" --repo_env=GUROBI_HOME=${GUROBI_HOME}")
548617
endif()
549618
endif()
550619

@@ -592,7 +661,8 @@ if(WITH_ROBOTLOCOMOTION_SNOPT OR WITH_SNOPT)
592661
string(APPEND BAZEL_CONFIG " --config=snopt")
593662

594663
if(WITH_ROBOTLOCOMOTION_SNOPT)
595-
string(APPEND BAZEL_REPO_ENV " --repo_env=SNOPT_PATH=git")
664+
set_property(GLOBAL APPEND_STRING PROPERTY BAZEL_REPO_ENV
665+
" --repo_env=SNOPT_PATH=git")
596666
else()
597667
set(SNOPT_PATH SNOPT_PATH-NOTFOUND CACHE FILEPATH
598668
"Path to SNOPT source archive"
@@ -603,7 +673,8 @@ if(WITH_ROBOTLOCOMOTION_SNOPT OR WITH_SNOPT)
603673
)
604674
endif()
605675
mark_as_advanced(SNOPT_PATH)
606-
string(APPEND BAZEL_REPO_ENV " --repo_env=SNOPT_PATH=${SNOPT_PATH}")
676+
set_property(GLOBAL APPEND_STRING PROPERTY BAZEL_REPO_ENV
677+
" --repo_env=SNOPT_PATH=${SNOPT_PATH}")
607678
endif()
608679
endif()
609680

@@ -669,6 +740,7 @@ endforeach()
669740
# name `drake_build_cwd` isn't important, it just needs to be unique. Note,
670741
# however, that the macOS wheel builds also need to know this path, so if it
671742
# ever changes, tools/wheel/macos/build-wheel.sh will also need to be updated.
743+
get_property(BAZEL_REPO_ENV GLOBAL PROPERTY BAZEL_REPO_ENV)
672744
configure_file(cmake/bazel.rc.in drake_build_cwd/.bazelrc @ONLY)
673745
configure_file(cmake/MODULE.bazel.in drake_build_cwd/MODULE.bazel @ONLY)
674746
file(CREATE_LINK "${PROJECT_SOURCE_DIR}/.bazeliskrc" drake_build_cwd/.bazeliskrc SYMBOLIC)

0 commit comments

Comments
 (0)