rust-common.bbclass 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #
  2. # Copyright OpenEmbedded Contributors
  3. #
  4. # SPDX-License-Identifier: MIT
  5. #
  6. inherit python3native
  7. inherit rust-target-config
  8. # Common variables used by all Rust builds
  9. export rustlibdir = "${libdir}/rustlib/${RUST_HOST_SYS}/lib"
  10. FILES:${PN} += "${rustlibdir}/*.so"
  11. FILES:${PN}-dev += "${rustlibdir}/*.rlib ${rustlibdir}/*.rmeta"
  12. FILES:${PN}-dbg += "${rustlibdir}/.debug"
  13. RUSTLIB ?= "-L ${STAGING_DIR_HOST}${rustlibdir}"
  14. RUST_DEBUG_REMAP = "--remap-path-prefix=${WORKDIR}=${TARGET_DBGSRC_DIR}"
  15. RUSTFLAGS += "${RUSTLIB} ${RUST_DEBUG_REMAP}"
  16. RUSTLIB_DEP ??= "libstd-rs"
  17. RUST_PANIC_STRATEGY ??= "unwind"
  18. def target_is_armv7(d):
  19. '''Determine if target is armv7'''
  20. # TUNE_FEATURES may include arm* even if the target is not arm
  21. # in the case of *-native packages
  22. if d.getVar('TARGET_ARCH') != 'arm':
  23. return False
  24. feat = d.getVar('TUNE_FEATURES')
  25. feat = frozenset(feat.split())
  26. mach_overrides = d.getVar('MACHINEOVERRIDES')
  27. mach_overrides = frozenset(mach_overrides.split(':'))
  28. v7=frozenset(['armv7a', 'armv7r', 'armv7m', 'armv7ve'])
  29. if mach_overrides.isdisjoint(v7) and feat.isdisjoint(v7):
  30. return False
  31. else:
  32. return True
  33. target_is_armv7[vardepvalue] = "${@target_is_armv7(d)}"
  34. # Responsible for taking Yocto triples and converting it to Rust triples
  35. def rust_base_triple(d, thing):
  36. '''
  37. Mangle bitbake's *_SYS into something that rust might support (see
  38. rust/mk/cfg/* for a list)
  39. Note that os is assumed to be some linux form
  40. '''
  41. # The llvm-target for armv7 is armv7-unknown-linux-gnueabihf
  42. if d.getVar('{}_ARCH'.format(thing)) == d.getVar('TARGET_ARCH') and target_is_armv7(d):
  43. arch = "armv7"
  44. else:
  45. arch = oe.rust.arch_to_rust_arch(d.getVar('{}_ARCH'.format(thing)))
  46. # Substituting "unknown" when vendor is empty will match rust's standard
  47. # targets when building native recipes (including rust-native itself)
  48. vendor = d.getVar('{}_VENDOR'.format(thing)) or "-unknown"
  49. # Default to glibc
  50. libc = "-gnu"
  51. os = d.getVar('{}_OS'.format(thing))
  52. # This catches ARM targets and appends the necessary hard float bits
  53. if os == "linux-gnueabi" or os == "linux-musleabi":
  54. libc = bb.utils.contains('TUNE_FEATURES', 'callconvention-hard', 'hf', '', d)
  55. elif os == "linux-gnux32" or os == "linux-muslx32":
  56. libc = ""
  57. elif "musl" in os:
  58. libc = "-musl"
  59. os = "linux"
  60. elif "elf" in os:
  61. libc = "-elf"
  62. os = "none"
  63. elif "eabi" in os:
  64. libc = "-eabi"
  65. os = "none"
  66. return arch + vendor + '-' + os + libc
  67. # In some cases uname and the toolchain differ on their idea of the arch name
  68. RUST_BUILD_ARCH = "${@oe.rust.arch_to_rust_arch(d.getVar('BUILD_ARCH'))}"
  69. # Naming explanation
  70. # Yocto
  71. # - BUILD_SYS - Yocto triple of the build environment
  72. # - HOST_SYS - What we're building for in Yocto
  73. # - TARGET_SYS - What we're building for in Yocto
  74. #
  75. # So when building '-native' packages BUILD_SYS == HOST_SYS == TARGET_SYS
  76. # When building packages for the image HOST_SYS == TARGET_SYS
  77. # This is a gross over simplification as there are other modes but
  78. # currently this is all that's supported.
  79. #
  80. # Rust
  81. # - TARGET - the system where the binary will run
  82. # - HOST - the system where the binary is being built
  83. #
  84. # Rust additionally will use two additional cases:
  85. # - undecorated (e.g. CC) - equivalent to TARGET
  86. # - triple suffix (e.g. CC:x86_64_unknown_linux_gnu) - both
  87. # see: https://github.com/rust-lang/cc-rs
  88. # The way that Rust's internal triples and Yocto triples are mapped together
  89. # its likely best to not use the triple suffix due to potential confusion.
  90. RUST_BUILD_SYS = "${@rust_base_triple(d, 'BUILD')}"
  91. RUST_BUILD_SYS[vardepvalue] = "${RUST_BUILD_SYS}"
  92. RUST_HOST_SYS = "${@rust_base_triple(d, 'HOST')}"
  93. RUST_HOST_SYS[vardepvalue] = "${RUST_HOST_SYS}"
  94. RUST_TARGET_SYS = "${@rust_base_triple(d, 'TARGET')}"
  95. RUST_TARGET_SYS[vardepvalue] = "${RUST_TARGET_SYS}"
  96. # wrappers to get around the fact that Rust needs a single
  97. # binary but Yocto's compiler and linker commands have
  98. # arguments. Technically the archiver is always one command but
  99. # this is necessary for builds that determine the prefix and then
  100. # use those commands based on the prefix.
  101. WRAPPER_DIR = "${WORKDIR}/wrapper"
  102. RUST_BUILD_CC = "${WRAPPER_DIR}/build-rust-cc"
  103. RUST_BUILD_CXX = "${WRAPPER_DIR}/build-rust-cxx"
  104. RUST_BUILD_CCLD = "${WRAPPER_DIR}/build-rust-ccld"
  105. RUST_BUILD_AR = "${WRAPPER_DIR}/build-rust-ar"
  106. RUST_TARGET_CC = "${WRAPPER_DIR}/target-rust-cc"
  107. RUST_TARGET_CXX = "${WRAPPER_DIR}/target-rust-cxx"
  108. RUST_TARGET_CCLD = "${WRAPPER_DIR}/target-rust-ccld"
  109. RUST_TARGET_AR = "${WRAPPER_DIR}/target-rust-ar"
  110. create_wrapper_rust () {
  111. file="$1"
  112. shift
  113. extras="$1"
  114. shift
  115. crate_cc_extras="$1"
  116. shift
  117. cat <<- EOF > "${file}"
  118. #!/usr/bin/env python3
  119. import os, sys
  120. orig_binary = "$@"
  121. extras = "${extras}"
  122. # Apply a required subset of CC crate compiler flags
  123. # when we build a target recipe for a non-bare-metal target.
  124. # https://github.com/rust-lang/cc-rs/blob/main/src/lib.rs#L1614
  125. if "CRATE_CC_NO_DEFAULTS" in os.environ.keys() and \
  126. "TARGET" in os.environ.keys() and not "-none-" in os.environ["TARGET"]:
  127. orig_binary += "${crate_cc_extras}"
  128. binary = orig_binary.split()[0]
  129. args = orig_binary.split() + sys.argv[1:]
  130. if extras:
  131. args.append(extras)
  132. os.execvp(binary, args)
  133. EOF
  134. chmod +x "${file}"
  135. }
  136. WRAPPER_TARGET_CC = "${CC}"
  137. WRAPPER_TARGET_CXX = "${CXX}"
  138. WRAPPER_TARGET_CCLD = "${CCLD}"
  139. WRAPPER_TARGET_LDFLAGS = "${LDFLAGS}"
  140. WRAPPER_TARGET_EXTRALD = ""
  141. # see recipes-devtools/gcc/gcc/0018-Add-ssp_nonshared-to-link-commandline-for-musl-targe.patch
  142. # we need to link with ssp_nonshared on musl to avoid "undefined reference to `__stack_chk_fail_local'"
  143. # when building MACHINE=qemux86 for musl
  144. WRAPPER_TARGET_EXTRALD:libc-musl = "-lssp_nonshared"
  145. WRAPPER_TARGET_AR = "${AR}"
  146. # compiler is used by gcc-rs
  147. # linker is used by rustc/cargo
  148. # archiver is used by the build of libstd-rs
  149. do_rust_create_wrappers () {
  150. mkdir -p "${WRAPPER_DIR}"
  151. # Yocto Build / Rust Host C compiler
  152. create_wrapper_rust "${RUST_BUILD_CC}" "" "${CRATE_CC_FLAGS}" "${BUILD_CC}" "${BUILD_LDFLAGS}"
  153. # Yocto Build / Rust Host C++ compiler
  154. create_wrapper_rust "${RUST_BUILD_CXX}" "" "${CRATE_CC_FLAGS}" "${BUILD_CXX}"
  155. # Yocto Build / Rust Host linker
  156. create_wrapper_rust "${RUST_BUILD_CCLD}" "" "" "${BUILD_CCLD}" "${BUILD_LDFLAGS}"
  157. # Yocto Build / Rust Host archiver
  158. create_wrapper_rust "${RUST_BUILD_AR}" "" "" "${BUILD_AR}"
  159. # Yocto Target / Rust Target C compiler
  160. create_wrapper_rust "${RUST_TARGET_CC}" "${WRAPPER_TARGET_EXTRALD}" "${CRATE_CC_FLAGS}" "${WRAPPER_TARGET_CC}" "${WRAPPER_TARGET_LDFLAGS}"
  161. # Yocto Target / Rust Target C++ compiler
  162. create_wrapper_rust "${RUST_TARGET_CXX}" "${WRAPPER_TARGET_EXTRALD}" "${CRATE_CC_FLAGS}" "${WRAPPER_TARGET_CXX}" "${CXXFLAGS}"
  163. # Yocto Target / Rust Target linker
  164. create_wrapper_rust "${RUST_TARGET_CCLD}" "${WRAPPER_TARGET_EXTRALD}" "" "${WRAPPER_TARGET_CCLD}" "${WRAPPER_TARGET_LDFLAGS}"
  165. # Yocto Target / Rust Target archiver
  166. create_wrapper_rust "${RUST_TARGET_AR}" "" "" "${WRAPPER_TARGET_AR}"
  167. }
  168. addtask rust_create_wrappers before do_configure after do_patch do_prepare_recipe_sysroot
  169. do_rust_create_wrappers[dirs] += "${WRAPPER_DIR}"