rust_1.90.0.bb 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. SUMMARY = "Rust compiler and runtime libaries"
  2. HOMEPAGE = "http://www.rust-lang.org"
  3. SECTION = "devel"
  4. LICENSE = "(MIT | Apache-2.0) & Unicode-3.0"
  5. LIC_FILES_CHKSUM = "file://COPYRIGHT;md5=11a3899825f4376896e438c8c753f8dc"
  6. inherit rust
  7. inherit cargo_common
  8. DEPENDS += "llvm"
  9. # native rust uses cargo/rustc from binary snapshots to bootstrap
  10. # but everything else should use our native builds
  11. DEPENDS:append:class-target = " cargo-native rust-native"
  12. DEPENDS:append:class-nativesdk = " cargo-native rust-native"
  13. RDEPENDS:${PN}:append:class-target = " gcc g++ binutils"
  14. # Otherwise we'll depend on what we provide
  15. INHIBIT_DEFAULT_RUST_DEPS:class-native = "1"
  16. # We don't need to depend on gcc-native because yocto assumes it exists
  17. PROVIDES:class-native = "virtual/${TARGET_PREFIX}rust"
  18. S = "${RUSTSRC}"
  19. # Use at your own risk, accepted values are stable, beta and nightly
  20. RUST_CHANNEL ?= "stable"
  21. PV .= "${@bb.utils.contains('RUST_CHANNEL', 'stable', '', '-${RUST_CHANNEL}', d)}"
  22. export FORCE_CRATE_HASH = "${BB_TASKHASH}"
  23. RUST_ALTERNATE_EXE_PATH ?= "${STAGING_BINDIR}/llvm-config"
  24. RUST_ALTERNATE_EXE_PATH_NATIVE = "${STAGING_BINDIR_NATIVE}/llvm-config"
  25. # We don't want to use bitbakes vendoring because the rust sources do their
  26. # own vendoring.
  27. CARGO_DISABLE_BITBAKE_VENDORING = "1"
  28. setup_cargo_environment () {
  29. # The first step is to build bootstrap and some early stage tools,
  30. # these are build for the same target as the snapshot, e.g.
  31. # x86_64-unknown-linux-gnu.
  32. # Later stages are build for the native target (i.e. target.x86_64-linux)
  33. cargo_common_do_configure
  34. }
  35. inherit rust-target-config
  36. do_rust_setup_snapshot () {
  37. for installer in "${UNPACKDIR}/rust-snapshot-components/"*"/install.sh"; do
  38. "${installer}" --prefix="${WORKDIR}/rust-snapshot" --disable-ldconfig
  39. done
  40. # Some versions of rust (e.g. 1.18.0) tries to find cargo in stage0/bin/cargo
  41. # and fail without it there.
  42. mkdir -p ${RUSTSRC}/build/${RUST_BUILD_SYS}
  43. ln -sf ${WORKDIR}/rust-snapshot/ ${RUSTSRC}/build/${RUST_BUILD_SYS}/stage0
  44. # Need to use uninative's loader if enabled/present since the library paths
  45. # are used internally by rust and result in symbol mismatches if we don't
  46. if [ ! -z "${UNINATIVE_LOADER}" -a -e "${UNINATIVE_LOADER}" ]; then
  47. for bin in cargo rustc rustdoc; do
  48. patchelf ${WORKDIR}/rust-snapshot/bin/$bin --set-interpreter ${UNINATIVE_LOADER}
  49. done
  50. fi
  51. }
  52. addtask rust_setup_snapshot after do_unpack before do_configure
  53. addtask do_test_compile after do_configure do_rust_gen_targets
  54. do_rust_setup_snapshot[dirs] += "${WORKDIR}/rust-snapshot"
  55. do_rust_setup_snapshot[vardepsexclude] += "UNINATIVE_LOADER"
  56. do_rust_setup_snapshot[depends] += "patchelf-native:do_populate_sysroot"
  57. RUSTC_BOOTSTRAP = "${STAGING_BINDIR_NATIVE}/rustc"
  58. CARGO_BOOTSTRAP = "${STAGING_BINDIR_NATIVE}/cargo"
  59. RUSTC_BOOTSTRAP:class-native = "${WORKDIR}/rust-snapshot/bin/rustc"
  60. CARGO_BOOTSTRAP:class-native = "${WORKDIR}/rust-snapshot/bin/cargo"
  61. python do_configure() {
  62. import json
  63. import configparser
  64. # toml is rather similar to standard ini like format except it likes values
  65. # that look more JSON like. So for our purposes simply escaping all values
  66. # as JSON seem to work fine.
  67. e = lambda s: json.dumps(s)
  68. config = configparser.RawConfigParser()
  69. # [target.ARCH-poky-linux]
  70. host_section = "target.{}".format(d.getVar('RUST_HOST_SYS'))
  71. config.add_section(host_section)
  72. llvm_config_target = d.expand("${RUST_ALTERNATE_EXE_PATH}")
  73. llvm_config_build = d.expand("${RUST_ALTERNATE_EXE_PATH_NATIVE}")
  74. config.set(host_section, "llvm-config", e(llvm_config_target))
  75. config.set(host_section, "cxx", e(d.expand("${RUST_TARGET_CXX}")))
  76. config.set(host_section, "cc", e(d.expand("${RUST_TARGET_CC}")))
  77. config.set(host_section, "linker", e(d.expand("${RUST_TARGET_CCLD}")))
  78. if "musl" in host_section:
  79. config.set(host_section, "musl-root", e(d.expand("${STAGING_DIR_HOST}${exec_prefix}")))
  80. # If we don't do this rust-native will compile it's own llvm for BUILD.
  81. # [target.${BUILD_ARCH}-unknown-linux-gnu]
  82. build_section = "target.{}".format(d.getVar('RUST_BUILD_SYS'))
  83. if build_section != host_section:
  84. config.add_section(build_section)
  85. config.set(build_section, "llvm-config", e(llvm_config_build))
  86. config.set(build_section, "cxx", e(d.expand("${RUST_BUILD_CXX}")))
  87. config.set(build_section, "cc", e(d.expand("${RUST_BUILD_CC}")))
  88. config.set(build_section, "linker", e(d.expand("${RUST_BUILD_CCLD}")))
  89. target_section = "target.{}".format(d.getVar('RUST_TARGET_SYS'))
  90. if target_section != host_section and target_section != build_section:
  91. config.add_section(target_section)
  92. config.set(target_section, "llvm-config", e(llvm_config_target))
  93. config.set(target_section, "cxx", e(d.expand("${RUST_TARGET_CXX}")))
  94. config.set(target_section, "cc", e(d.expand("${RUST_TARGET_CC}")))
  95. config.set(target_section, "linker", e(d.expand("${RUST_TARGET_CCLD}")))
  96. # [llvm]
  97. config.add_section("llvm")
  98. config.set("llvm", "static-libstdcpp", e(False))
  99. config.set("llvm", "download-ci-llvm", e(False))
  100. if "llvm" in (d.getVar('TC_CXX_RUNTIME') or ""):
  101. config.set("llvm", "use-libcxx", e(True))
  102. # [rust]
  103. config.add_section("rust")
  104. config.set("rust", "rpath", e(True))
  105. config.set("rust", "remap-debuginfo", e(True))
  106. config.set("rust", "download-rustc", e(False))
  107. config.set("rust", "llvm-tools", e(False))
  108. config.set("rust", "lld", e(False))
  109. config.set("rust", "use-lld", e(False))
  110. config.set("rust", "channel", e(d.expand("${RUST_CHANNEL}")))
  111. # Whether or not to optimize the compiler and standard library
  112. config.set("rust", "optimize", e(True))
  113. # Emits extraneous output from tests to ensure that failures of the test
  114. # harness are debuggable just from logfiles
  115. config.set("rust", "verbose-tests", e(True))
  116. # [build]
  117. config.add_section("build")
  118. config.set("build", "submodules", e(False))
  119. config.set("build", "docs", e(False))
  120. rustc = d.getVar('RUSTC_BOOTSTRAP')
  121. config.set("build", "rustc", e(rustc))
  122. cargo = d.getVar('CARGO_BOOTSTRAP')
  123. config.set("build", "cargo", e(cargo))
  124. config.set("build", "extended", e(False))
  125. config.set("build", "vendor", e(True))
  126. config.set("build", "target", e([d.getVar("RUST_TARGET_SYS")]))
  127. config.set("build", "host", e([d.getVar("RUST_HOST_SYS")]))
  128. # We can't use BUILD_SYS since that is something the rust snapshot knows
  129. # nothing about when trying to build some stage0 tools (like fabricate)
  130. config.set("build", "build", e(d.getVar("RUST_BUILD_SYS")))
  131. # [install]
  132. config.add_section("install")
  133. # ./x.py install doesn't have any notion of "destdir"
  134. # but we can prepend ${D} to all the directories instead
  135. config.set("install", "prefix", e(d.getVar("D") + d.getVar("prefix")))
  136. config.set("install", "bindir", e(d.getVar("D") + d.getVar("bindir")))
  137. config.set("install", "libdir", e(d.getVar("D") + d.getVar("libdir")))
  138. config.set("install", "datadir", e(d.getVar("D") + d.getVar("datadir")))
  139. config.set("install", "mandir", e(d.getVar("D") + d.getVar("mandir")))
  140. config.set("install", "sysconfdir", e(d.getVar("D") + d.getVar("sysconfdir")))
  141. with open("config.toml", "w") as f:
  142. f.write('change-id = 116881\n\n')
  143. config.write(f)
  144. # set up ${WORKDIR}/cargo_home
  145. bb.build.exec_func("setup_cargo_environment", d)
  146. }
  147. # llvm-config expects static libraries to be in the 'lib' directory rather than 'lib64' when
  148. # multilibs enabled. Since we are copying the natively built llvm-config into the target sysroot
  149. # and executing it there, it will default to searching in 'lib', as it is unaware of the 'lib64'
  150. # directory. To ensure llvm-config can locate the necessary libraries, create a symlink from 'lib'
  151. do_compile:append:class-target() {
  152. # Ensure llvm-config can find static libraries in multilib setup
  153. lib64_dir="${STAGING_DIR_TARGET}/usr/lib64"
  154. lib_dir="${STAGING_DIR_TARGET}/usr/lib"
  155. if [ -d "$lib64_dir" ]; then
  156. # If lib does not exist, symlink it to lib64
  157. if [ ! -e "$lib_dir" ]; then
  158. ln -s lib64 "$lib_dir"
  159. fi
  160. # Only do per-file symlinking if lib is a real directory (not symlink)
  161. if [ -d "$lib_dir" ] && [ ! -L "$lib_dir" ]; then
  162. for lib64_file in "${lib64_dir}"/libLLVM*.a; do
  163. if [ -e "$lib64_file" ]; then
  164. lib_name=$(basename "${lib64_file}")
  165. target_link="${lib_dir}/${lib_name}"
  166. if [ ! -e "${target_link}" ]; then
  167. ln -s "../lib64/${lib_name}" "${target_link}"
  168. fi
  169. fi
  170. done
  171. fi
  172. fi
  173. }
  174. rust_runx () {
  175. echo "COMPILE ${PN}" "$@"
  176. # CFLAGS, LDFLAGS, CXXFLAGS, CPPFLAGS are used by rust's build for a
  177. # wide range of targets (not just TARGET). Yocto's settings for them will
  178. # be inappropriate, avoid using.
  179. unset CFLAGS
  180. unset LDFLAGS
  181. unset CXXFLAGS
  182. unset CPPFLAGS
  183. export RUSTFLAGS="${RUST_DEBUG_REMAP} -Clink-arg=-lz -Clink-arg=-lzstd"
  184. # Copy the natively built llvm-config into the target so we can run it. Horrible,
  185. # but works!
  186. if [ ${RUST_ALTERNATE_EXE_PATH_NATIVE} != ${RUST_ALTERNATE_EXE_PATH} -a ! -f ${RUST_ALTERNATE_EXE_PATH} ]; then
  187. mkdir -p `dirname ${RUST_ALTERNATE_EXE_PATH}`
  188. cp ${RUST_ALTERNATE_EXE_PATH_NATIVE} ${RUST_ALTERNATE_EXE_PATH}
  189. if [ -e ${STAGING_LIBDIR_NATIVE}/libc++.so.1 ]; then
  190. patchelf --set-rpath \$ORIGIN/../../../../../`basename ${STAGING_DIR_NATIVE}`${libdir_native} ${RUST_ALTERNATE_EXE_PATH}
  191. else
  192. patchelf --remove-rpath ${RUST_ALTERNATE_EXE_PATH}
  193. fi
  194. fi
  195. oe_cargo_fix_env
  196. python3 src/bootstrap/bootstrap.py ${@oe.utils.parallel_make_argument(d, '-j %d')} "$@" --verbose
  197. }
  198. rust_runx[vardepsexclude] += "PARALLEL_MAKE"
  199. require rust-source.inc
  200. require rust-snapshot.inc
  201. INSANE_SKIP:${PN}:class-native = "already-stripped"
  202. FILES:${PN} += "${libdir}/rustlib"
  203. FILES:${PN} += "${libdir}/*.so"
  204. FILES:${PN}-dev = ""
  205. do_compile () {
  206. }
  207. do_test_compile[dirs] = "${B}"
  208. do_test_compile () {
  209. rust_runx build src/tools/remote-test-server --target "${RUST_TARGET_SYS}"
  210. }
  211. ALLOW_EMPTY:${PN} = "1"
  212. PACKAGES =+ "${PN}-rustdoc ${PN}-tools-clippy ${PN}-tools-rustfmt"
  213. FILES:${PN}-rustdoc = "${bindir}/rustdoc"
  214. FILES:${PN}-tools-clippy = "${bindir}/cargo-clippy ${bindir}/clippy-driver"
  215. FILES:${PN}-tools-rustfmt = "${bindir}/rustfmt"
  216. RDEPENDS:${PN}-rustdoc = "${PN}"
  217. RDEPENDS:${PN}-tools-clippy = "${PN}"
  218. RDEPENDS:${PN}-tools-rustfmt = "${PN}"
  219. SUMMARY:${PN}-tools-clippy = "A collection of lints to catch common mistakes and improve your Rust code"
  220. SUMMARY:${PN}-tools-rustfmt = "A tool for formatting Rust code according to style guidelines"
  221. do_install () {
  222. rust_do_install
  223. }
  224. rust_do_install() {
  225. rust_runx install
  226. }
  227. rust_do_install:class-nativesdk() {
  228. export PSEUDO_UNLOAD=1
  229. rust_runx install
  230. rust_runx install clippy
  231. rust_runx install rustfmt
  232. unset PSEUDO_UNLOAD
  233. install -d ${D}${bindir}
  234. for i in cargo-clippy clippy-driver rustfmt; do
  235. cp build/${RUST_BUILD_SYS}/stage1-tools/${RUST_HOST_SYS}/release/$i ${D}${bindir}
  236. patchelf --set-rpath "\$ORIGIN/../lib" ${D}${bindir}/$i
  237. done
  238. chown root:root ${D}/ -R
  239. rm ${D}${libdir}/rustlib/uninstall.sh
  240. rm ${D}${libdir}/rustlib/install.log
  241. rm ${D}${libdir}/rustlib/manifest*
  242. rm ${D}${libdir}/rustlib/${RUST_HOST_SYS}/lib/libstd*.so
  243. ENV_SETUP_DIR=${D}${base_prefix}/environment-setup.d
  244. mkdir "${ENV_SETUP_DIR}"
  245. RUST_ENV_SETUP_SH="${ENV_SETUP_DIR}/rust.sh"
  246. RUST_HOST_TRIPLE=`echo ${RUST_HOST_SYS} | tr '[:lower:]' '[:upper:]' | sed 's/-/_/g'`
  247. RUST_HOST_CC=`echo ${RUST_HOST_SYS} | sed 's/-/_/g'`
  248. SDKLOADER=${@bb.utils.contains('SDK_ARCH', 'x86_64', 'ld-linux-x86-64.so.2', '', d)}${@bb.utils.contains('SDK_ARCH', 'i686', 'ld-linux.so.2', '', d)}${@bb.utils.contains('SDK_ARCH', 'aarch64', 'ld-linux-aarch64.so.1', '', d)}${@bb.utils.contains('SDK_ARCH', 'ppc64le', 'ld64.so.2', '', d)}${@bb.utils.contains('SDK_ARCH', 'riscv64', 'ld-linux-riscv64-lp64d.so.1', '', d)}
  249. cat <<- EOF > "${RUST_ENV_SETUP_SH}"
  250. export CARGO_TARGET_${RUST_HOST_TRIPLE}_RUNNER="\$OECORE_NATIVE_SYSROOT/lib/${SDKLOADER}"
  251. export CC_$RUST_HOST_CC="${CCACHE}${HOST_PREFIX}gcc"
  252. EOF
  253. }
  254. FILES:${PN} += "${base_prefix}/environment-setup.d"
  255. EXTRA_TOOLS ?= "cargo-clippy clippy-driver rustfmt"
  256. rust_do_install:class-target() {
  257. export PSEUDO_UNLOAD=1
  258. rust_runx install
  259. rust_runx install clippy
  260. rust_runx install rustfmt
  261. unset PSEUDO_UNLOAD
  262. install -d ${D}${bindir}
  263. for i in ${EXTRA_TOOLS}; do
  264. cp build/${RUST_BUILD_SYS}/stage1-tools/${RUST_HOST_SYS}/release/$i ${D}${bindir}
  265. patchelf --set-rpath "\$ORIGIN/../lib" ${D}${bindir}/$i
  266. done
  267. install -d ${D}${libdir}/rustlib/${RUST_HOST_SYS}
  268. install -m 0644 ${WORKDIR}/rust-targets/${RUST_HOST_SYS}.json ${D}${libdir}/rustlib/${RUST_HOST_SYS}/target.json
  269. chown root:root ${D}/ -R
  270. rm ${D}${libdir}/rustlib/uninstall.sh
  271. rm ${D}${libdir}/rustlib/install.log
  272. rm ${D}${libdir}/rustlib/manifest*
  273. rm ${D}${libdir}/rustlib/${RUST_HOST_SYS}/lib/libstd*.so
  274. }
  275. addtask do_update_snapshot after do_patch
  276. do_update_snapshot[nostamp] = "1"
  277. # Run with `bitbake -c update_snapshot rust` to update `rust-snapshot.inc`
  278. # with the checksums for the rust snapshot associated with this rustc-src
  279. # tarball.
  280. python do_update_snapshot() {
  281. import json
  282. import re
  283. import sys
  284. from collections import defaultdict
  285. key_value_pairs = {}
  286. with open(os.path.join(d.getVar("S"), "src", "stage0")) as f:
  287. for line in f:
  288. # Skip empty lines or comments
  289. if not line.strip() or line.startswith("#"):
  290. continue
  291. # Split the line into key and value using '=' as separator
  292. match = re.match(r'(\S+)\s*=\s*(\S+)', line.strip())
  293. if match:
  294. key = match.group(1)
  295. value = match.group(2)
  296. key_value_pairs[key] = value
  297. # Extract the required values from key_value_pairs
  298. config_dist_server = key_value_pairs.get('dist_server', '')
  299. compiler_date = key_value_pairs.get('compiler_date', '')
  300. compiler_version = key_value_pairs.get('compiler_version', '')
  301. src_uri = defaultdict(list)
  302. # Assuming checksums_sha256 is now a key-value pair like: checksum_key = checksum_value
  303. for k, v in key_value_pairs.items():
  304. # Match the pattern for checksums
  305. if "dist" in k and "tar.xz" in k:
  306. m = re.search(f"dist/{compiler_date}/(?P<component>.*)-{compiler_version}-(?P<arch>.*)-unknown-linux-gnu\\.tar\\.xz", k)
  307. if m:
  308. component = m.group('component')
  309. arch = m.group('arch')
  310. src_uri[arch].append(f"SRC_URI[{component}-snapshot-{arch}.sha256sum] = \"{v}\"")
  311. # Create the snapshot string with the extracted values
  312. snapshot = """\
  313. ## This is information on the rust-snapshot (binary) used to build our current release.
  314. ## snapshot info is taken from rust/src/stage0
  315. ## Rust is self-hosting and bootstraps itself with a pre-built previous version of itself.
  316. ## The exact (previous) version that has been used is specified in the source tarball.
  317. ## The version is replicated here.
  318. SNAPSHOT_VERSION = "%s"
  319. """ % compiler_version
  320. # Add the checksum components to the snapshot
  321. for arch, components in src_uri.items():
  322. snapshot += "\n".join(components) + "\n\n"
  323. # Add the additional snapshot URIs
  324. snapshot += """\
  325. SRC_URI += " \\
  326. ${RUST_DIST_SERVER}/dist/${RUST_STD_SNAPSHOT}.tar.xz;name=rust-std-snapshot-${RUST_BUILD_ARCH};subdir=rust-snapshot-components \\
  327. ${RUST_DIST_SERVER}/dist/${RUSTC_SNAPSHOT}.tar.xz;name=rustc-snapshot-${RUST_BUILD_ARCH};subdir=rust-snapshot-components \\
  328. ${RUST_DIST_SERVER}/dist/${CARGO_SNAPSHOT}.tar.xz;name=cargo-snapshot-${RUST_BUILD_ARCH};subdir=rust-snapshot-components \\
  329. "
  330. RUST_DIST_SERVER = "%s"
  331. RUST_STD_SNAPSHOT = "rust-std-${SNAPSHOT_VERSION}-${RUST_BUILD_ARCH}-unknown-linux-gnu"
  332. RUSTC_SNAPSHOT = "rustc-${SNAPSHOT_VERSION}-${RUST_BUILD_ARCH}-unknown-linux-gnu"
  333. CARGO_SNAPSHOT = "cargo-${SNAPSHOT_VERSION}-${RUST_BUILD_ARCH}-unknown-linux-gnu"
  334. """ % config_dist_server
  335. # Write the updated snapshot information to the rust-snapshot.inc file
  336. with open(os.path.join(d.getVar("THISDIR"), "rust-snapshot.inc"), "w") as f:
  337. f.write(snapshot)
  338. }
  339. RUSTLIB_DEP:class-nativesdk = ""
  340. # musl builds include libunwind.a
  341. INSANE_SKIP:${PN} = "staticdev"
  342. BBCLASSEXTEND = "native nativesdk"