diff mbox

[v4,3/3] rust: new package

Message ID 20170402194651.28684-4-eric.le.bihan.dev@free.fr
State Changes Requested
Headers show

Commit Message

Eric Le Bihan April 2, 2017, 7:46 p.m. UTC
This new package provides the compiler for the Rust programming language.

Currently, only the host variant is built.

The Rust compiler uses LLVM as its backend: a copy of LLVM source code
is provided and CMake is used to build it. It is possible to use a
pre-built external copy. When LLVM/clang will be available in Buildroot,
it would be possible to benefit from this feature and thus decrease
build time.

LLVM is configured to generate code for x86, ARM, PowerPC and MIPS
architectures.

The Rust compiler uses Cargo as its build system and is written in Rust.
Therefore this package depends on cargo-bootstrap and rust-bootstrap.

The internal build process is as follows:

 1. rustc-stage0, provided by rust-bootstrap, is used to build
    rustc-stage1.
 2. rust-stage1 builds the final Rust compiler (rust-stage2)
    and the standard library for the host architecture.
 3. the standard library for the target architecture is built.

The target architecture to support is given by the GNU/LLVM target
triple. Rust supports some predefined targets [1]. As the build system
expects the triple to be in the form of <arch>-unknown-<system> and
Buildroot toolchain wrapper uses <arch>-buildroot-<system>, the package
Makefile defines the $(RUST_TARGET_NAME) and uses it instead of
$(GNU_TARGET_NAME).

When compiling Rust code with this compiler, the generated program only
depends on the target C library, as it is statically linked to the Rust
standard library and any other code from Rust packages (a.k.a.
"crates").

If the jemalloc package is selected, support for this memory allocator
will be enabled in the target standard library.

[1] https://forge.rust-lang.org/platform-support.html

Signed-off-by: Eric Le Bihan <eric.le.bihan.dev@free.fr>
---
 DEVELOPERS                  |  1 +
 package/Config.in.host      |  1 +
 package/rust/Config.in.host | 33 ++++++++++++++++++
 package/rust/rust.hash      |  2 ++
 package/rust/rust.mk        | 85 +++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 122 insertions(+)
 create mode 100644 package/rust/Config.in.host
 create mode 100644 package/rust/rust.hash
 create mode 100644 package/rust/rust.mk

Comments

Jörg Krause April 7, 2017, 7:18 a.m. UTC | #1
Hi Eric,

On Sun, 2017-04-02 at 21:46 +0200, Eric Le Bihan wrote:
> This new package provides the compiler for the Rust programming
> language.
> 
> Currently, only the host variant is built.
> 
> The Rust compiler uses LLVM as its backend: a copy of LLVM source
> code
> is provided and CMake is used to build it. It is possible to use a
> pre-built external copy. When LLVM/clang will be available in
> Buildroot,
> it would be possible to benefit from this feature and thus decrease
> build time.
> 
> LLVM is configured to generate code for x86, ARM, PowerPC and MIPS
> architectures.
> 
> The Rust compiler uses Cargo as its build system and is written in
> Rust.
> Therefore this package depends on cargo-bootstrap and rust-bootstrap.
> 
> The internal build process is as follows:
> 
>  1. rustc-stage0, provided by rust-bootstrap, is used to build
>     rustc-stage1.
>  2. rust-stage1 builds the final Rust compiler (rust-stage2)
>     and the standard library for the host architecture.
>  3. the standard library for the target architecture is built.

So, we are doing the following: fetch the predecessor rust version
1.15.1 as binary to use it as stage0 compiler for building the latest
rust stable version 1.16.0. Why not just fetch the latest stable
version and install it into the host dir? The same goes with libstd and
cargo. I mean, we have to fetch some binaries anyway, so why do the
time-consuming build steps anyway? Shouldn't there be at least the
option just to fetch the latest stable version?

> The target architecture to support is given by the GNU/LLVM target
> triple. Rust supports some predefined targets [1]. As the build
> system
> expects the triple to be in the form of <arch>-unknown-<system> and
> Buildroot toolchain wrapper uses <arch>-buildroot-<system>, the
> package
> Makefile defines the $(RUST_TARGET_NAME) and uses it instead of
> $(GNU_TARGET_NAME).
> 
> When compiling Rust code with this compiler, the generated program
> only
> depends on the target C library, as it is statically linked to the
> Rust
> standard library and any other code from Rust packages (a.k.a.
> "crates").
> 
> If the jemalloc package is selected, support for this memory
> allocator
> will be enabled in the target standard library.
> 
> [1] https://forge.rust-lang.org/platform-support.html
> 
> Signed-off-by: Eric Le Bihan <eric.le.bihan.dev@free.fr>
> ---
>  DEVELOPERS                  |  1 +
>  package/Config.in.host      |  1 +
>  package/rust/Config.in.host | 33 ++++++++++++++++++
>  package/rust/rust.hash      |  2 ++
>  package/rust/rust.mk        | 85
> +++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 122 insertions(+)
>  create mode 100644 package/rust/Config.in.host
>  create mode 100644 package/rust/rust.hash
>  create mode 100644 package/rust/rust.mk
> 
> diff --git a/DEVELOPERS b/DEVELOPERS
> index 1fed408..c0e7833 100644
> --- a/DEVELOPERS
> +++ b/DEVELOPERS
> @@ -450,6 +450,7 @@ F:	package/hicolor-icon-theme/
>  F:	package/jemalloc/
>  F:	package/ninja/
>  F:	package/rust-bootstrap
> +F:	package/rust
>  F:	package/s6/
>  F:	package/s6-dns/
>  F:	package/s6-linux-init/
> diff --git a/package/Config.in.host b/package/Config.in.host
> index 38f919a..ef5f23f 100644
> --- a/package/Config.in.host
> +++ b/package/Config.in.host
> @@ -39,6 +39,7 @@ menu "Host utilities"
>  	source "package/python-lxml/Config.in.host"
>  	source "package/qemu/Config.in.host"
>  	source "package/raspberrypi-usbboot/Config.in.host"
> +	source "package/rust/Config.in.host"
>  	source "package/s6-rc/Config.in.host"
>  	source "package/sam-ba/Config.in.host"
>  	source "package/squashfs/Config.in.host"
> diff --git a/package/rust/Config.in.host
> b/package/rust/Config.in.host
> new file mode 100644
> index 0000000..384a071
> --- /dev/null
> +++ b/package/rust/Config.in.host
> @@ -0,0 +1,33 @@
> +config BR2_PACKAGE_HOST_RUST_ARCH_SUPPORTS
> +	bool
> +	default y
> +	depends on BR2_HOSTARCH = "x86_64" || BR2_HOSTARCH = "x86"
> +	depends on  BR2_i386 || BR2_x86_64 \
> +		|| BR2_arm  || BR2_aarch64 \
> +		|| BR2_powerpc  || BR2_powerpc64 \
> +		|| BR2_mips || BR2_mipsel || BR2_mips64 ||
> BR2_mips64el
> +	depends on !BR2_ARM_CPU_ARMV4 && !BR2_ARM_CPU_ARMV5
> +	depends on !BR2_MIPS_NABI32
> +	depends on BR2_TOOLCHAIN_USES_GLIBC
> +	depends on BR2_HOST_GCC_AT_LEAST_4_7 # required by LLVM
> +	# triggers ICE on trunc_int_for_mode, at explow.c:56
> +	depends on BR2_TOOLCHAIN_GCC_AT_LEAST_5 || !BR2_aarch64
> +
> +comment "host-rust needs a toolchain w/ gcc >= 5"
> +	depends on !BR2_TOOLCHAIN_GCC_AT_LEAST_5 && BR2_aarch64
> +
> +config BR2_PACKAGE_HOST_RUST
> +	bool "host rust"
> +	depends on BR2_PACKAGE_HOST_RUST_ARCH_SUPPORTS
> +	help
> +	  Compiler for the Rust programming language.
> +
> +	  This package will build the compiler for the host as well
> as
> +	  a cross-compiled version of the Rust standard library for
> the
> +	  target.
> +
> +	  Note that the target standard library does not need to be
> +	  present on the target root filesystem, as it is statically
> +	  linked to the program.
> +
> +	  http://www.rust-lang.org
> diff --git a/package/rust/rust.hash b/package/rust/rust.hash
> new file mode 100644
> index 0000000..3b04dfd
> --- /dev/null
> +++ b/package/rust/rust.hash
> @@ -0,0 +1,2 @@
> +# Locally calculated
> +sha256
> f966b31eb1cd9bd2df817c391a338eeb5b9253ae0a19bf8a11960c560f96e8b4  rus
> tc-1.16.0-src.tar.gz
> diff --git a/package/rust/rust.mk b/package/rust/rust.mk
> new file mode 100644
> index 0000000..12f4428
> --- /dev/null
> +++ b/package/rust/rust.mk
> @@ -0,0 +1,85 @@
> +####################################################################
> ############
> +#
> +# rust
> +#
> +####################################################################
> ############
> +
> +RUST_VERSION = 1.16.0
> +RUST_SOURCE = rustc-$(RUST_VERSION)-src.tar.gz
> +RUST_SITE = https://static.rust-lang.org/dist
> +RUST_LICENSE = Apache-2.0 or MIT
> +RUST_LICENSE_FILES = LICENSE-APACHE LICENSE-MIT
> +
> +HOST_RUST_DEPENDENCIES = \
> +	toolchain \
> +	host-rust-bootstrap \
> +	host-cargo-bootstrap \
> +	host-python \
> +	host-cmake
> +
> +ifeq ($(BR2_PACKAGE_JEMALLOC),y)
> +HOST_RUST_DEPENDENCIES += jemalloc
> +HOST_RUST_JEMALLOC_ENABLED = true
> +HOST_RUST_JEMALLOC_CONF = 'jemalloc =
> "$(STAGING_DIR)/usr/lib/libjemalloc_pic.a"'
> +else
> +HOST_RUST_JEMALLOC_ENABLED = false
> +endif
> +
> +HOST_RUST_BUILD_OPTS = $(if $(VERBOSE),--verbose)
> +
> +RUST_TARGET_NAME := $(subst buildroot,unknown,$(GNU_TARGET_NAME))
> +
> +ifeq ($(BR2_ARM_CPU_ARMV7A),y)
> +RUST_TARGET_NAME := $(subst arm-,armv7-,$(RUST_TARGET_NAME))
> +endif
> +
> +ifeq ($(BR2_MIPS_NABI64),y)
> +RUST_TARGET_NAME := $(subst -gnu,-gnuabi64,$(RUST_TARGET_NAME))
> +endif
> +
> +define HOST_RUST_CONFIGURE_CMDS
> +	(cd $(@D); \
> +		echo '[build]' > config.toml; \
> +		echo 'target = ["$(RUST_TARGET_NAME)"]' >>
> config.toml; \
> +		echo 'cargo =
> "$(HOST_CARGO_BOOTSTRAP_DIR)/cargo/bin/cargo"' >> config.toml; \
> +		echo 'rustc =
> "$(HOST_RUST_BOOTSTRAP_DIR)/rustc/bin/rustc"' >> config.toml; \
> +		echo 'python = "$(HOST_DIR)/usr/bin/python2"' >>
> config.toml; \
> +		echo 'submodules = false' >> config.toml; \
> +		echo 'vendor = true' >> config.toml; \
> +		echo 'compiler-docs = false' >> config.toml; \
> +		echo 'docs = false' >> config.toml; \
> +		echo '[install]' >> config.toml; \
> +		echo 'prefix = "$(HOST_DIR)/usr"' >> config.toml; \
> +		echo '[rust]' >> config.toml; \
> +		echo 'use-jemalloc = $(HOST_RUST_JEMALLOC_ENABLED)'
> >> config.toml; \
> +		echo '[target.$(RUST_TARGET_NAME)]' >> config.toml;
> \
> +		echo 'cc = "$(TARGET_CROSS)gcc"' >> config.toml; \
> +		echo 'cxx = "$(TARGET_CROSS)g++"' >> config.toml; \
> +		echo $(HOST_RUST_JEMALLOC_CONF) >> config.toml; \
> +	)
> +endef
> +
> +define HOST_RUST_BUILD_CMDS
> +	(cd $(@D); $(HOST_MAKE_ENV) $(HOST_RUST_MAKE_ENV) python2
> x.py \
> +		build $(HOST_RUST_BUILD_OPTS))
> +endef
> +
> +define HOST_RUST_INSTALL_LIBSTD_TARGET
> +	(cd $(@D)/build/tmp/dist/rust-std-$(RUST_VERSION)-dev-
> $(RUST_TARGET_NAME); \
> +		./install.sh \
> +			--prefix=$(HOST_DIR)/usr \
> +			--docdir=$(HOST_DIR)/usr/share/doc/rust \
> +			--libdir=$(HOST_DIR)/usr/lib \
> +			--mandir=$(HOST_DIR)/usr/share/man \
> +			--disable-ldconfig)
> +endef
> +
> +define HOST_RUST_INSTALL_CMDS
> +	(cd $(@D); $(HOST_MAKE_ENV) $(HOST_RUST_MAKE_ENV) python2
> x.py \
> +		dist $(HOST_RUST_BUILD_OPTS))
> +	(cd $(@D); $(HOST_MAKE_ENV) $(HOST_RUST_MAKE_ENV) python2
> x.py \
> +		dist --install $(HOST_RUST_BUILD_OPTS))
> +	$(HOST_RUST_INSTALL_LIBSTD_TARGET)
> +endef
> +
> +$(eval $(host-generic-package))

Best regards,
Jörg Krause
Eric Le Bihan April 8, 2017, 10:09 a.m. UTC | #2
Hi!

On 17-04-07 09:18:42, Jörg Krause wrote:
> Hi Eric,
>
> On Sun, 2017-04-02 at 21:46 +0200, Eric Le Bihan wrote:
> > This new package provides the compiler for the Rust programming
> > language.
> >
> > Currently, only the host variant is built.
> >
> > The Rust compiler uses LLVM as its backend: a copy of LLVM source
> > code
> > is provided and CMake is used to build it. It is possible to use a
> > pre-built external copy. When LLVM/clang will be available in
> > Buildroot,
> > it would be possible to benefit from this feature and thus decrease
> > build time.
> >
> > LLVM is configured to generate code for x86, ARM, PowerPC and MIPS
> > architectures.
> >
> > The Rust compiler uses Cargo as its build system and is written in
> > Rust.
> > Therefore this package depends on cargo-bootstrap and rust-bootstrap.
> >
> > The internal build process is as follows:
> >
> >  1. rustc-stage0, provided by rust-bootstrap, is used to build
> >     rustc-stage1.
> >  2. rust-stage1 builds the final Rust compiler (rust-stage2)
> >     and the standard library for the host architecture.
> >  3. the standard library for the target architecture is built.
>
> So, we are doing the following: fetch the predecessor rust version
> 1.15.1 as binary to use it as stage0 compiler for building the latest
> rust stable version 1.16.0. Why not just fetch the latest stable
> version and install it into the host dir? The same goes with libstd and
> cargo. I mean, we have to fetch some binaries anyway, so why do the
> time-consuming build steps anyway? Shouldn't there be at least the
> option just to fetch the latest stable version?
>
It is true that building the Rust compiler is time consuming. As stated
in the comment, this can be decreased if LLVM was already available. But
if LLVM itself is built from source and not fetched as binary from
Internet, then the issue is still there.

Currently Buildroot only offers downloading binary versions of the C/C++
cross-compilers. It does not take into account alternative C/C++
cross-compilers like LLVM/Clang or compilers for new languages like
Rust, D, or Haskell (though I do not know if Haskell is useful on
embedded systems).

So, would it help to have a "Programming Languages" section in
menuconfig where you can select Rust (or any other language) and choose
between a using a pre-built compiler or build it from source?

And where shoud LLVM/clang be exposed?

Note: Building a cross-compiler for D can be done via a patch to GCC
thanks to GDC [1], but IIRC cross-compiling libphobos, the standard
library, is another matter.

[1] https://github.com/D-Programming-GDC/GDC/releases

> > The target architecture to support is given by the GNU/LLVM target
> > triple. Rust supports some predefined targets [1]. As the build
> > system
> > expects the triple to be in the form of <arch>-unknown-<system> and
> > Buildroot toolchain wrapper uses <arch>-buildroot-<system>, the
> > package
> > Makefile defines the $(RUST_TARGET_NAME) and uses it instead of
> > $(GNU_TARGET_NAME).
> >
> > When compiling Rust code with this compiler, the generated program
> > only
> > depends on the target C library, as it is statically linked to the
> > Rust
> > standard library and any other code from Rust packages (a.k.a.
> > "crates").
> >
> > If the jemalloc package is selected, support for this memory
> > allocator
> > will be enabled in the target standard library.
> >
> > [1] https://forge.rust-lang.org/platform-support.html
> >
> > Signed-off-by: Eric Le Bihan <eric.le.bihan.dev@free.fr>
> > ---
> >  DEVELOPERS                  |  1 +
> >  package/Config.in.host      |  1 +
> >  package/rust/Config.in.host | 33 ++++++++++++++++++
> >  package/rust/rust.hash      |  2 ++
> >  package/rust/rust.mk        | 85
> > +++++++++++++++++++++++++++++++++++++++++++++
> >  5 files changed, 122 insertions(+)
> >  create mode 100644 package/rust/Config.in.host
> >  create mode 100644 package/rust/rust.hash
> >  create mode 100644 package/rust/rust.mk
> >
> > diff --git a/DEVELOPERS b/DEVELOPERS
> > index 1fed408..c0e7833 100644
> > --- a/DEVELOPERS
> > +++ b/DEVELOPERS
> > @@ -450,6 +450,7 @@ F:	package/hicolor-icon-theme/
> >  F:	package/jemalloc/
> >  F:	package/ninja/
> >  F:	package/rust-bootstrap
> > +F:	package/rust
> >  F:	package/s6/
> >  F:	package/s6-dns/
> >  F:	package/s6-linux-init/
> > diff --git a/package/Config.in.host b/package/Config.in.host
> > index 38f919a..ef5f23f 100644
> > --- a/package/Config.in.host
> > +++ b/package/Config.in.host
> > @@ -39,6 +39,7 @@ menu "Host utilities"
> >  	source "package/python-lxml/Config.in.host"
> >  	source "package/qemu/Config.in.host"
> >  	source "package/raspberrypi-usbboot/Config.in.host"
> > +	source "package/rust/Config.in.host"
> >  	source "package/s6-rc/Config.in.host"
> >  	source "package/sam-ba/Config.in.host"
> >  	source "package/squashfs/Config.in.host"
> > diff --git a/package/rust/Config.in.host
> > b/package/rust/Config.in.host
> > new file mode 100644
> > index 0000000..384a071
> > --- /dev/null
> > +++ b/package/rust/Config.in.host
> > @@ -0,0 +1,33 @@
> > +config BR2_PACKAGE_HOST_RUST_ARCH_SUPPORTS
> > +	bool
> > +	default y
> > +	depends on BR2_HOSTARCH = "x86_64" || BR2_HOSTARCH = "x86"
> > +	depends on  BR2_i386 || BR2_x86_64 \
> > +		|| BR2_arm  || BR2_aarch64 \
> > +		|| BR2_powerpc  || BR2_powerpc64 \
> > +		|| BR2_mips || BR2_mipsel || BR2_mips64 ||
> > BR2_mips64el
> > +	depends on !BR2_ARM_CPU_ARMV4 && !BR2_ARM_CPU_ARMV5
> > +	depends on !BR2_MIPS_NABI32
> > +	depends on BR2_TOOLCHAIN_USES_GLIBC
> > +	depends on BR2_HOST_GCC_AT_LEAST_4_7 # required by LLVM
> > +	# triggers ICE on trunc_int_for_mode, at explow.c:56
> > +	depends on BR2_TOOLCHAIN_GCC_AT_LEAST_5 || !BR2_aarch64
> > +
> > +comment "host-rust needs a toolchain w/ gcc >= 5"
> > +	depends on !BR2_TOOLCHAIN_GCC_AT_LEAST_5 && BR2_aarch64
> > +
> > +config BR2_PACKAGE_HOST_RUST
> > +	bool "host rust"
> > +	depends on BR2_PACKAGE_HOST_RUST_ARCH_SUPPORTS
> > +	help
> > +	  Compiler for the Rust programming language.
> > +
> > +	  This package will build the compiler for the host as well
> > as
> > +	  a cross-compiled version of the Rust standard library for
> > the
> > +	  target.
> > +
> > +	  Note that the target standard library does not need to be
> > +	  present on the target root filesystem, as it is statically
> > +	  linked to the program.
> > +
> > +	  http://www.rust-lang.org
> > diff --git a/package/rust/rust.hash b/package/rust/rust.hash
> > new file mode 100644
> > index 0000000..3b04dfd
> > --- /dev/null
> > +++ b/package/rust/rust.hash
> > @@ -0,0 +1,2 @@
> > +# Locally calculated
> > +sha256
> > f966b31eb1cd9bd2df817c391a338eeb5b9253ae0a19bf8a11960c560f96e8b4  rus
> > tc-1.16.0-src.tar.gz
> > diff --git a/package/rust/rust.mk b/package/rust/rust.mk
> > new file mode 100644
> > index 0000000..12f4428
> > --- /dev/null
> > +++ b/package/rust/rust.mk
> > @@ -0,0 +1,85 @@
> > +####################################################################
> > ############
> > +#
> > +# rust
> > +#
> > +####################################################################
> > ############
> > +
> > +RUST_VERSION = 1.16.0
> > +RUST_SOURCE = rustc-$(RUST_VERSION)-src.tar.gz
> > +RUST_SITE = https://static.rust-lang.org/dist
> > +RUST_LICENSE = Apache-2.0 or MIT
> > +RUST_LICENSE_FILES = LICENSE-APACHE LICENSE-MIT
> > +
> > +HOST_RUST_DEPENDENCIES = \
> > +	toolchain \
> > +	host-rust-bootstrap \
> > +	host-cargo-bootstrap \
> > +	host-python \
> > +	host-cmake
> > +
> > +ifeq ($(BR2_PACKAGE_JEMALLOC),y)
> > +HOST_RUST_DEPENDENCIES += jemalloc
> > +HOST_RUST_JEMALLOC_ENABLED = true
> > +HOST_RUST_JEMALLOC_CONF = 'jemalloc =
> > "$(STAGING_DIR)/usr/lib/libjemalloc_pic.a"'
> > +else
> > +HOST_RUST_JEMALLOC_ENABLED = false
> > +endif
> > +
> > +HOST_RUST_BUILD_OPTS = $(if $(VERBOSE),--verbose)
> > +
> > +RUST_TARGET_NAME := $(subst buildroot,unknown,$(GNU_TARGET_NAME))
> > +
> > +ifeq ($(BR2_ARM_CPU_ARMV7A),y)
> > +RUST_TARGET_NAME := $(subst arm-,armv7-,$(RUST_TARGET_NAME))
> > +endif
> > +
> > +ifeq ($(BR2_MIPS_NABI64),y)
> > +RUST_TARGET_NAME := $(subst -gnu,-gnuabi64,$(RUST_TARGET_NAME))
> > +endif
> > +
> > +define HOST_RUST_CONFIGURE_CMDS
> > +	(cd $(@D); \
> > +		echo '[build]' > config.toml; \
> > +		echo 'target = ["$(RUST_TARGET_NAME)"]' >>
> > config.toml; \
> > +		echo 'cargo =
> > "$(HOST_CARGO_BOOTSTRAP_DIR)/cargo/bin/cargo"' >> config.toml; \
> > +		echo 'rustc =
> > "$(HOST_RUST_BOOTSTRAP_DIR)/rustc/bin/rustc"' >> config.toml; \
> > +		echo 'python = "$(HOST_DIR)/usr/bin/python2"' >>
> > config.toml; \
> > +		echo 'submodules = false' >> config.toml; \
> > +		echo 'vendor = true' >> config.toml; \
> > +		echo 'compiler-docs = false' >> config.toml; \
> > +		echo 'docs = false' >> config.toml; \
> > +		echo '[install]' >> config.toml; \
> > +		echo 'prefix = "$(HOST_DIR)/usr"' >> config.toml; \
> > +		echo '[rust]' >> config.toml; \
> > +		echo 'use-jemalloc = $(HOST_RUST_JEMALLOC_ENABLED)'
> > >> config.toml; \
> > +		echo '[target.$(RUST_TARGET_NAME)]' >> config.toml;
> > \
> > +		echo 'cc = "$(TARGET_CROSS)gcc"' >> config.toml; \
> > +		echo 'cxx = "$(TARGET_CROSS)g++"' >> config.toml; \
> > +		echo $(HOST_RUST_JEMALLOC_CONF) >> config.toml; \
> > +	)
> > +endef
> > +
> > +define HOST_RUST_BUILD_CMDS
> > +	(cd $(@D); $(HOST_MAKE_ENV) $(HOST_RUST_MAKE_ENV) python2
> > x.py \
> > +		build $(HOST_RUST_BUILD_OPTS))
> > +endef
> > +
> > +define HOST_RUST_INSTALL_LIBSTD_TARGET
> > +	(cd $(@D)/build/tmp/dist/rust-std-$(RUST_VERSION)-dev-
> > $(RUST_TARGET_NAME); \
> > +		./install.sh \
> > +			--prefix=$(HOST_DIR)/usr \
> > +			--docdir=$(HOST_DIR)/usr/share/doc/rust \
> > +			--libdir=$(HOST_DIR)/usr/lib \
> > +			--mandir=$(HOST_DIR)/usr/share/man \
> > +			--disable-ldconfig)
> > +endef
> > +
> > +define HOST_RUST_INSTALL_CMDS
> > +	(cd $(@D); $(HOST_MAKE_ENV) $(HOST_RUST_MAKE_ENV) python2
> > x.py \
> > +		dist $(HOST_RUST_BUILD_OPTS))
> > +	(cd $(@D); $(HOST_MAKE_ENV) $(HOST_RUST_MAKE_ENV) python2
> > x.py \
> > +		dist --install $(HOST_RUST_BUILD_OPTS))
> > +	$(HOST_RUST_INSTALL_LIBSTD_TARGET)
> > +endef
> > +
> > +$(eval $(host-generic-package))
>
> Best regards,
> Jörg Krause

--
ELB
Jörg Krause April 10, 2017, 7:02 p.m. UTC | #3
Hi,

On Sat, 2017-04-08 at 12:09 +0200, Eric Le Bihan wrote:
> Hi!
> 
> On 17-04-07 09:18:42, Jörg Krause wrote:
> > Hi Eric,
> > 
> > On Sun, 2017-04-02 at 21:46 +0200, Eric Le Bihan wrote:
> > > This new package provides the compiler for the Rust programming
> > > language.
> > > 
> > > Currently, only the host variant is built.
> > > 
> > > The Rust compiler uses LLVM as its backend: a copy of LLVM source
> > > code
> > > is provided and CMake is used to build it. It is possible to use a
> > > pre-built external copy. When LLVM/clang will be available in
> > > Buildroot,
> > > it would be possible to benefit from this feature and thus decrease
> > > build time.
> > > 
> > > LLVM is configured to generate code for x86, ARM, PowerPC and MIPS
> > > architectures.
> > > 
> > > The Rust compiler uses Cargo as its build system and is written in
> > > Rust.
> > > Therefore this package depends on cargo-bootstrap and rust-bootstrap.
> > > 
> > > The internal build process is as follows:
> > > 
> > >  1. rustc-stage0, provided by rust-bootstrap, is used to build
> > >     rustc-stage1.
> > >  2. rust-stage1 builds the final Rust compiler (rust-stage2)
> > >     and the standard library for the host architecture.
> > >  3. the standard library for the target architecture is built.
> > 
> > So, we are doing the following: fetch the predecessor rust version
> > 1.15.1 as binary to use it as stage0 compiler for building the latest
> > rust stable version 1.16.0. Why not just fetch the latest stable
> > version and install it into the host dir? The same goes with libstd and
> > cargo. I mean, we have to fetch some binaries anyway, so why do the
> > time-consuming build steps anyway? Shouldn't there be at least the
> > option just to fetch the latest stable version?
> > 
> 
> It is true that building the Rust compiler is time consuming. As stated
> in the comment, this can be decreased if LLVM was already available. But
> if LLVM itself is built from source and not fetched as binary from
> Internet, then the issue is still there.
> 
> Currently Buildroot only offers downloading binary versions of the C/C++
> cross-compilers. It does not take into account alternative C/C++
> cross-compilers like LLVM/Clang or compilers for new languages like
> Rust, D, or Haskell (though I do not know if Haskell is useful on
> embedded systems).

For now, we could use the host rustc package to fetch the latest stable
binary for the host architecture. Additionally, we could add the option
to build the Rust compiler within Buildroot. In my opinion, this option
only makes sense if the compiler can be configured meaningfully.

> So, would it help to have a "Programming Languages" section in
> menuconfig where you can select Rust (or any other language) and choose
> between a using a pre-built compiler or build it from source?

In my opinion it would make more sense to have a menu "Toolchains" with
the submenus "C/C++ Toolchain", "Rust Toolchain", ...

> And where shoud LLVM/clang be exposed?

I would put it into "C/C++ Toolchain" (if we had such a menu).

> Note: Building a cross-compiler for D can be done via a patch to GCC
> thanks to GDC [1], but IIRC cross-compiling libphobos, the standard
> library, is another matter.
> 
> [1] https://github.com/D-Programming-GDC/GDC/releases

Jörg
Arnout Vandecappelle April 10, 2017, 9:43 p.m. UTC | #4
On 10-04-17 21:02, Jörg Krause wrote:
> Hi,
> 
> On Sat, 2017-04-08 at 12:09 +0200, Eric Le Bihan wrote:
[snip]
>> Currently Buildroot only offers downloading binary versions of the C/C++
>> cross-compilers. It does not take into account alternative C/C++
>> cross-compilers like LLVM/Clang or compilers for new languages like
>> Rust, D, or Haskell (though I do not know if Haskell is useful on
>> embedded systems).

 There's a huge difference between alternative C/C++ compilers and compilers for
other languages.

 Compilers for other languages we already have: python, mono, erlang. These are
just normal packages, and any package in that language depends on the host-xxx
package to provide the compiler. Similar to how packages that use the cmake
buildsystem depend on the host-cmake package.

 Alternative C/C++ compilers are something else entirely, because they replace
the special 'toolchain' target.

 Only when you can build an entire system with only the Rust compiler and
without C/C++ compiler you can consider them equivalent. That day is still far away.

> For now, we could use the host rustc package to fetch the latest stable
> binary for the host architecture. Additionally, we could add the option
> to build the Rust compiler within Buildroot. In my opinion, this option
> only makes sense if the compiler can be configured meaningfully.

 I agree.


>> So, would it help to have a "Programming Languages" section in
>> menuconfig where you can select Rust (or any other language) and choose
>> between a using a pre-built compiler or build it from source?
> 
> In my opinion it would make more sense to have a menu "Toolchains" with
> the submenus "C/C++ Toolchain", "Rust Toolchain", ...

 Given what I wrote above, I disagree. For the time being it's fine in the host
packages menu. If that menu becomes too large, we could add something like an
'Alternative programming languages' menu.



>> And where shoud LLVM/clang be exposed?
> 
> I would put it into "C/C++ Toolchain" (if we had such a menu).

 That's slightly more complicated. LLVM is just a library so it's just in the
host menu. clang is a compiler that can be a replacement for gcc, so it'd have
to go into the toolchain menu.

 Actually, Romain is working on LLVM/Clang. He's going to start adding it as a
normal host package, so not as a replacement of gcc as the toolchain.

 Regards,
 Arnout

> 
>> Note: Building a cross-compiler for D can be done via a patch to GCC
>> thanks to GDC [1], but IIRC cross-compiling libphobos, the standard
>> library, is another matter.
>>
>> [1] https://github.com/D-Programming-GDC/GDC/releases
> 
> Jörg
> _______________________________________________
> buildroot mailing list
> buildroot@busybox.net
> http://lists.busybox.net/mailman/listinfo/buildroot
>
Jörg Krause April 13, 2017, 6:05 a.m. UTC | #5
Hi,

On Mon, 2017-04-10 at 23:43 +0200, Arnout Vandecappelle wrote:
> 
> On 10-04-17 21:02, Jörg Krause wrote:
> > Hi,
> > 
> > On Sat, 2017-04-08 at 12:09 +0200, Eric Le Bihan wrote:
> 
> [snip]
> > > Currently Buildroot only offers downloading binary versions of the C/C++
> > > cross-compilers. It does not take into account alternative C/C++
> > > cross-compilers like LLVM/Clang or compilers for new languages like
> > > Rust, D, or Haskell (though I do not know if Haskell is useful on
> > > embedded systems).
> 
>  There's a huge difference between alternative C/C++ compilers and compilers for
> other languages.
> 
>  Compilers for other languages we already have: python, mono, erlang. These are
> just normal packages, and any package in that language depends on the host-xxx
> package to provide the compiler. Similar to how packages that use the cmake
> buildsystem depend on the host-cmake package.
> 
>  Alternative C/C++ compilers are something else entirely, because they replace
> the special 'toolchain' target.
> 
>  Only when you can build an entire system with only the Rust compiler and
> without C/C++ compiler you can consider them equivalent. That day is still far away.

I see!

> > For now, we could use the host rustc package to fetch the latest stable
> > binary for the host architecture. Additionally, we could add the option
> > to build the Rust compiler within Buildroot. In my opinion, this option
> > only makes sense if the compiler can be configured meaningfully.
> 
>  I agree.

Cool.

@Eric: Do you mind to do that? By default fetch the latest stable
release, and alternatively offer an option to build a "Custom Rust
package". I think it would also be helpful to have at least one Rust
package to add as a proof of concept.

> 
> > > So, would it help to have a "Programming Languages" section in
> > > menuconfig where you can select Rust (or any other language) and choose
> > > between a using a pre-built compiler or build it from source?
> > 
> > In my opinion it would make more sense to have a menu "Toolchains" with
> > the submenus "C/C++ Toolchain", "Rust Toolchain", ...
> 
>  Given what I wrote above, I disagree. For the time being it's fine in the host
> packages menu. If that menu becomes too large, we could add something like an
> 'Alternative programming languages' menu.
> 

Sounds reasonable.

> 
> > > And where shoud LLVM/clang be exposed?
> > 
> > I would put it into "C/C++ Toolchain" (if we had such a menu).
> 
>  That's slightly more complicated. LLVM is just a library so it's just in the
> host menu. clang is a compiler that can be a replacement for gcc, so it'd have
> to go into the toolchain menu.
> 
>  Actually, Romain is working on LLVM/Clang. He's going to start adding it as a
> normal host package, so not as a replacement of gcc as the toolchain.

Nice!

Jörg
Eric Le Bihan April 13, 2017, 4:49 p.m. UTC | #6
Le 2017-04-13 06:05, Jörg Krause a écrit :
> Hi,
> 
> On Mon, 2017-04-10 at 23:43 +0200, Arnout Vandecappelle wrote:
>> 
>> On 10-04-17 21:02, Jörg Krause wrote:
[snip]
>> > For now, we could use the host rustc package to fetch the latest stable
>> > binary for the host architecture. Additionally, we could add the option
>> > to build the Rust compiler within Buildroot. In my opinion, this option
>> > only makes sense if the compiler can be configured meaningfully.
>> 
>>  I agree.
> 
> Cool.
> 
> @Eric: Do you mind to do that? By default fetch the latest stable
> release, and alternatively offer an option to build a "Custom Rust
> package". I think it would also be helpful to have at least one Rust
> package to add as a proof of concept.

Currently this patch series provides:

- rust-bootstrap, which fetches the binary version N-1 of rust.
- cargo-bootstrap, which fetches a nightly binary version of cargo.
- rust, which uses the two previous packages to build version N of rust.

I also have another patch series which adds a new package for cargo, 
which
uses cargo-bootstrap and rust to build Cargo from source.

IMHO, modifying the current version of the rust package to download the
latest version and providing an option to build from source would make
the Makefile of the package more complicated.

Would it not be better to use host virtual packages? Something like:

- rust-rustc: host virtual package, with two providers:
   * rustc-bin: fetches binary version N of rustc and libstd (host and
     target).
   * rustc: builds version N of rustc and libstd (host and target).
     Depends on rust-bootstrap (version N-1) and cargo-bootstrap.
- rust-cargo: host virtual package with two providers:
   * cargo-bin: fetches binary version N of Cargo.
   * cargo: builds version N of Cargo using rust and cargo-bootstrap.

And instead of littering the package directory with rust-* and cargo-*,
how about putting all these packages in a parent directory named
package/rust?

The file package/Config.in.host should also be modified to include
package/rust/Config.in.host, which would present the options to select
the providers for rust-rustc and rust-cargo.
Arnout Vandecappelle April 13, 2017, 9:09 p.m. UTC | #7
On 13-04-17 18:49, Eric Le Bihan wrote:
> Le 2017-04-13 06:05, Jörg Krause a écrit :
>> Hi,
>>
>> On Mon, 2017-04-10 at 23:43 +0200, Arnout Vandecappelle wrote:
>>>
>>> On 10-04-17 21:02, Jörg Krause wrote:
> [snip]
>>> > For now, we could use the host rustc package to fetch the latest stable
>>> > binary for the host architecture. Additionally, we could add the option
>>> > to build the Rust compiler within Buildroot. In my opinion, this option
>>> > only makes sense if the compiler can be configured meaningfully.
>>>
>>>  I agree.
>>
>> Cool.
>>
>> @Eric: Do you mind to do that? By default fetch the latest stable
>> release, and alternatively offer an option to build a "Custom Rust
>> package". I think it would also be helpful to have at least one Rust
>> package to add as a proof of concept.
> 
> Currently this patch series provides:
> 
> - rust-bootstrap, which fetches the binary version N-1 of rust.
> - cargo-bootstrap, which fetches a nightly binary version of cargo.
> - rust, which uses the two previous packages to build version N of rust.
> 
> I also have another patch series which adds a new package for cargo, which
> uses cargo-bootstrap and rust to build Cargo from source.
> 
> IMHO, modifying the current version of the rust package to download the
> latest version and providing an option to build from source would make
> the Makefile of the package more complicated.

 I think Joerg's point is that we could just as well have *only* rust-bootstrap
(which would then be named "rust", of course). Why would you fetch version N-1
to build version N, if you can just fetch version N?

 If there is a reason to actually build it (like we need to set some options),
then it makes sense to have the -bootstrap.

> 
> Would it not be better to use host virtual packages? Something like:
> 
> - rust-rustc: host virtual package, with two providers:
>   * rustc-bin: fetches binary version N of rustc and libstd (host and
>     target).
>   * rustc: builds version N of rustc and libstd (host and target).
>     Depends on rust-bootstrap (version N-1) and cargo-bootstrap.
> - rust-cargo: host virtual package with two providers:
>   * cargo-bin: fetches binary version N of Cargo.
>   * cargo: builds version N of Cargo using rust and cargo-bootstrap.

 This actually sounds like an elegant solution to me. And it scales, i.e. you
can start just adding rustc-bin and cargo-bin, and later add rustc and cargo if
it's useful for something.


> And instead of littering the package directory with rust-* and cargo-*,
> how about putting all these packages in a parent directory named
> package/rust?

 Since you haven't proposed any package yet that depends on rust, it's hard to
say. We prefer to avoid subdirectories because it makes things harder to find -
we actually moved things out of a few subdirectories some years ago. The ones
that are left are the obvious ones: qt5, gstreamer{,1}, x11r7.

 For Rust, I don't see how it makes much sense. It could make sense for things
like perl, python and lua because there the packages are really tied to the
language (except for a few user-facing applications, but these don't usually
have a python- prefix).

 For Rust, however, I think the packages that depend on it are not so tied to
the language. They'll either be user-facing applications, or libraries that may
just as well be linked with C code. No? So the rust/ directory would have just
rust and cargo...

 What *does* make sense, is to keep rust and cargo together in Config.in.host.

 Regards,
 Arnout


> The file package/Config.in.host should also be modified to include
> package/rust/Config.in.host, which would present the options to select
> the providers for rust-rustc and rust-cargo.
> 
>
diff mbox

Patch

diff --git a/DEVELOPERS b/DEVELOPERS
index 1fed408..c0e7833 100644
--- a/DEVELOPERS
+++ b/DEVELOPERS
@@ -450,6 +450,7 @@  F:	package/hicolor-icon-theme/
 F:	package/jemalloc/
 F:	package/ninja/
 F:	package/rust-bootstrap
+F:	package/rust
 F:	package/s6/
 F:	package/s6-dns/
 F:	package/s6-linux-init/
diff --git a/package/Config.in.host b/package/Config.in.host
index 38f919a..ef5f23f 100644
--- a/package/Config.in.host
+++ b/package/Config.in.host
@@ -39,6 +39,7 @@  menu "Host utilities"
 	source "package/python-lxml/Config.in.host"
 	source "package/qemu/Config.in.host"
 	source "package/raspberrypi-usbboot/Config.in.host"
+	source "package/rust/Config.in.host"
 	source "package/s6-rc/Config.in.host"
 	source "package/sam-ba/Config.in.host"
 	source "package/squashfs/Config.in.host"
diff --git a/package/rust/Config.in.host b/package/rust/Config.in.host
new file mode 100644
index 0000000..384a071
--- /dev/null
+++ b/package/rust/Config.in.host
@@ -0,0 +1,33 @@ 
+config BR2_PACKAGE_HOST_RUST_ARCH_SUPPORTS
+	bool
+	default y
+	depends on BR2_HOSTARCH = "x86_64" || BR2_HOSTARCH = "x86"
+	depends on  BR2_i386 || BR2_x86_64 \
+		|| BR2_arm  || BR2_aarch64 \
+		|| BR2_powerpc  || BR2_powerpc64 \
+		|| BR2_mips || BR2_mipsel || BR2_mips64 || BR2_mips64el
+	depends on !BR2_ARM_CPU_ARMV4 && !BR2_ARM_CPU_ARMV5
+	depends on !BR2_MIPS_NABI32
+	depends on BR2_TOOLCHAIN_USES_GLIBC
+	depends on BR2_HOST_GCC_AT_LEAST_4_7 # required by LLVM
+	# triggers ICE on trunc_int_for_mode, at explow.c:56
+	depends on BR2_TOOLCHAIN_GCC_AT_LEAST_5 || !BR2_aarch64
+
+comment "host-rust needs a toolchain w/ gcc >= 5"
+	depends on !BR2_TOOLCHAIN_GCC_AT_LEAST_5 && BR2_aarch64
+
+config BR2_PACKAGE_HOST_RUST
+	bool "host rust"
+	depends on BR2_PACKAGE_HOST_RUST_ARCH_SUPPORTS
+	help
+	  Compiler for the Rust programming language.
+
+	  This package will build the compiler for the host as well as
+	  a cross-compiled version of the Rust standard library for the
+	  target.
+
+	  Note that the target standard library does not need to be
+	  present on the target root filesystem, as it is statically
+	  linked to the program.
+
+	  http://www.rust-lang.org
diff --git a/package/rust/rust.hash b/package/rust/rust.hash
new file mode 100644
index 0000000..3b04dfd
--- /dev/null
+++ b/package/rust/rust.hash
@@ -0,0 +1,2 @@ 
+# Locally calculated
+sha256 f966b31eb1cd9bd2df817c391a338eeb5b9253ae0a19bf8a11960c560f96e8b4  rustc-1.16.0-src.tar.gz
diff --git a/package/rust/rust.mk b/package/rust/rust.mk
new file mode 100644
index 0000000..12f4428
--- /dev/null
+++ b/package/rust/rust.mk
@@ -0,0 +1,85 @@ 
+################################################################################
+#
+# rust
+#
+################################################################################
+
+RUST_VERSION = 1.16.0
+RUST_SOURCE = rustc-$(RUST_VERSION)-src.tar.gz
+RUST_SITE = https://static.rust-lang.org/dist
+RUST_LICENSE = Apache-2.0 or MIT
+RUST_LICENSE_FILES = LICENSE-APACHE LICENSE-MIT
+
+HOST_RUST_DEPENDENCIES = \
+	toolchain \
+	host-rust-bootstrap \
+	host-cargo-bootstrap \
+	host-python \
+	host-cmake
+
+ifeq ($(BR2_PACKAGE_JEMALLOC),y)
+HOST_RUST_DEPENDENCIES += jemalloc
+HOST_RUST_JEMALLOC_ENABLED = true
+HOST_RUST_JEMALLOC_CONF = 'jemalloc = "$(STAGING_DIR)/usr/lib/libjemalloc_pic.a"'
+else
+HOST_RUST_JEMALLOC_ENABLED = false
+endif
+
+HOST_RUST_BUILD_OPTS = $(if $(VERBOSE),--verbose)
+
+RUST_TARGET_NAME := $(subst buildroot,unknown,$(GNU_TARGET_NAME))
+
+ifeq ($(BR2_ARM_CPU_ARMV7A),y)
+RUST_TARGET_NAME := $(subst arm-,armv7-,$(RUST_TARGET_NAME))
+endif
+
+ifeq ($(BR2_MIPS_NABI64),y)
+RUST_TARGET_NAME := $(subst -gnu,-gnuabi64,$(RUST_TARGET_NAME))
+endif
+
+define HOST_RUST_CONFIGURE_CMDS
+	(cd $(@D); \
+		echo '[build]' > config.toml; \
+		echo 'target = ["$(RUST_TARGET_NAME)"]' >> config.toml; \
+		echo 'cargo = "$(HOST_CARGO_BOOTSTRAP_DIR)/cargo/bin/cargo"' >> config.toml; \
+		echo 'rustc = "$(HOST_RUST_BOOTSTRAP_DIR)/rustc/bin/rustc"' >> config.toml; \
+		echo 'python = "$(HOST_DIR)/usr/bin/python2"' >> config.toml; \
+		echo 'submodules = false' >> config.toml; \
+		echo 'vendor = true' >> config.toml; \
+		echo 'compiler-docs = false' >> config.toml; \
+		echo 'docs = false' >> config.toml; \
+		echo '[install]' >> config.toml; \
+		echo 'prefix = "$(HOST_DIR)/usr"' >> config.toml; \
+		echo '[rust]' >> config.toml; \
+		echo 'use-jemalloc = $(HOST_RUST_JEMALLOC_ENABLED)' >> config.toml; \
+		echo '[target.$(RUST_TARGET_NAME)]' >> config.toml; \
+		echo 'cc = "$(TARGET_CROSS)gcc"' >> config.toml; \
+		echo 'cxx = "$(TARGET_CROSS)g++"' >> config.toml; \
+		echo $(HOST_RUST_JEMALLOC_CONF) >> config.toml; \
+	)
+endef
+
+define HOST_RUST_BUILD_CMDS
+	(cd $(@D); $(HOST_MAKE_ENV) $(HOST_RUST_MAKE_ENV) python2 x.py \
+		build $(HOST_RUST_BUILD_OPTS))
+endef
+
+define HOST_RUST_INSTALL_LIBSTD_TARGET
+	(cd $(@D)/build/tmp/dist/rust-std-$(RUST_VERSION)-dev-$(RUST_TARGET_NAME); \
+		./install.sh \
+			--prefix=$(HOST_DIR)/usr \
+			--docdir=$(HOST_DIR)/usr/share/doc/rust \
+			--libdir=$(HOST_DIR)/usr/lib \
+			--mandir=$(HOST_DIR)/usr/share/man \
+			--disable-ldconfig)
+endef
+
+define HOST_RUST_INSTALL_CMDS
+	(cd $(@D); $(HOST_MAKE_ENV) $(HOST_RUST_MAKE_ENV) python2 x.py \
+		dist $(HOST_RUST_BUILD_OPTS))
+	(cd $(@D); $(HOST_MAKE_ENV) $(HOST_RUST_MAKE_ENV) python2 x.py \
+		dist --install $(HOST_RUST_BUILD_OPTS))
+	$(HOST_RUST_INSTALL_LIBSTD_TARGET)
+endef
+
+$(eval $(host-generic-package))