rust/mk/rt.mk

352 lines
13 KiB
Makefile
Raw Normal View History

# Copyright 2014 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
################################################################################
# Native libraries built as part of the rust build process
#
# This portion of the rust build system is meant to keep track of native
# dependencies and how to build them. It is currently required that all native
# dependencies are built as static libraries, as slinging around dynamic
# libraries isn't exactly the most fun thing to do.
#
# This section should need minimal modification to add new libraries. The
# relevant variables are:
#
# NATIVE_LIBS
# This is a list of all native libraries which are built as part of the
# build process. It will build all libraries into RT_OUTPUT_DIR with the
# appropriate name of static library as dictated by the target platform
#
# NATIVE_DEPS_<lib>
# This is a list of files relative to the src/rt directory which are
# needed to build the native library. Each file will be compiled to an
# object file, and then all the object files will be assembled into an
# archive (static library). The list contains files of any extension
#
# If adding a new library, you should update the NATIVE_LIBS list, and then list
# the required files below it. The list of required files is a list of files
# that's per-target so you're allowed to conditionally add files based on the
# target.
################################################################################
NATIVE_LIBS := rust_builtin hoedown morestack miniz \
std: Extract librustrt out of libstd As part of the libstd facade efforts, this commit extracts the runtime interface out of the standard library into a standalone crate, librustrt. This crate will provide the following services: * Definition of the rtio interface * Definition of the Runtime interface * Implementation of the Task structure * Implementation of task-local-data * Implementation of task failure via unwinding via libunwind * Implementation of runtime initialization and shutdown * Implementation of thread-local-storage for the local rust Task Notably, this crate avoids the following services: * Thread creation and destruction. The crate does not require the knowledge of an OS threading system, and as a result it seemed best to leave out the `rt::thread` module from librustrt. The librustrt module does depend on mutexes, however. * Implementation of backtraces. There is no inherent requirement for the runtime to be able to generate backtraces. As will be discussed later, this functionality continues to live in libstd rather than librustrt. As usual, a number of architectural changes were required to make this crate possible. Users of "stable" functionality will not be impacted by this change, but users of the `std::rt` module will likely note the changes. A list of architectural changes made is: * The stdout/stderr handles no longer live directly inside of the `Task` structure. This is a consequence of librustrt not knowing about `std::io`. These two handles are now stored inside of task-local-data. The handles were originally stored inside of the `Task` for perf reasons, and TLD is not currently as fast as it could be. For comparison, 100k prints goes from 59ms to 68ms (a 15% slowdown). This appeared to me to be an acceptable perf loss for the successful extraction of a librustrt crate. * The `rtio` module was forced to duplicate more functionality of `std::io`. As the module no longer depends on `std::io`, `rtio` now defines structures such as socket addresses, addrinfo fiddly bits, etc. The primary change made was that `rtio` now defines its own `IoError` type. This type is distinct from `std::io::IoError` in that it does not have an enum for what error occurred, but rather a platform-specific error code. The native and green libraries will be updated in later commits for this change, and the bulk of this effort was put behind updating the two libraries for this change (with `rtio`). * Printing a message on task failure (along with the backtrace) continues to live in libstd, not in librustrt. This is a consequence of the above decision to move the stdout/stderr handles to TLD rather than inside the `Task` itself. The unwinding API now supports registration of global callback functions which will be invoked when a task fails, allowing for libstd to register a function to print a message and a backtrace. The API for registering a callback is experimental and unsafe, as the ramifications of running code on unwinding is pretty hairy. * The `std::unstable::mutex` module has moved to `std::rt::mutex`. * The `std::unstable::sync` module has been moved to `std::rt::exclusive` and the type has been rewritten to not internally have an Arc and to have an RAII guard structure when locking. Old code should stop using `Exclusive` in favor of the primitives in `libsync`, but if necessary, old code should port to `Arc<Exclusive<T>>`. * The local heap has been stripped down to have fewer debugging options. None of these were tested, and none of these have been used in a very long time. [breaking-change]
2014-06-04 04:11:49 +02:00
rustrt_native rust_test_helpers
# $(1) is the target triple
define NATIVE_LIBRARIES
NATIVE_DEPS_hoedown_$(1) := hoedown/src/autolink.c \
hoedown/src/buffer.c \
hoedown/src/document.c \
hoedown/src/escape.c \
hoedown/src/html.c \
hoedown/src/html_blocks.c \
hoedown/src/html_smartypants.c \
hoedown/src/stack.c \
hoedown/src/version.c
NATIVE_DEPS_miniz_$(1) = miniz.c
std: Extract librustrt out of libstd As part of the libstd facade efforts, this commit extracts the runtime interface out of the standard library into a standalone crate, librustrt. This crate will provide the following services: * Definition of the rtio interface * Definition of the Runtime interface * Implementation of the Task structure * Implementation of task-local-data * Implementation of task failure via unwinding via libunwind * Implementation of runtime initialization and shutdown * Implementation of thread-local-storage for the local rust Task Notably, this crate avoids the following services: * Thread creation and destruction. The crate does not require the knowledge of an OS threading system, and as a result it seemed best to leave out the `rt::thread` module from librustrt. The librustrt module does depend on mutexes, however. * Implementation of backtraces. There is no inherent requirement for the runtime to be able to generate backtraces. As will be discussed later, this functionality continues to live in libstd rather than librustrt. As usual, a number of architectural changes were required to make this crate possible. Users of "stable" functionality will not be impacted by this change, but users of the `std::rt` module will likely note the changes. A list of architectural changes made is: * The stdout/stderr handles no longer live directly inside of the `Task` structure. This is a consequence of librustrt not knowing about `std::io`. These two handles are now stored inside of task-local-data. The handles were originally stored inside of the `Task` for perf reasons, and TLD is not currently as fast as it could be. For comparison, 100k prints goes from 59ms to 68ms (a 15% slowdown). This appeared to me to be an acceptable perf loss for the successful extraction of a librustrt crate. * The `rtio` module was forced to duplicate more functionality of `std::io`. As the module no longer depends on `std::io`, `rtio` now defines structures such as socket addresses, addrinfo fiddly bits, etc. The primary change made was that `rtio` now defines its own `IoError` type. This type is distinct from `std::io::IoError` in that it does not have an enum for what error occurred, but rather a platform-specific error code. The native and green libraries will be updated in later commits for this change, and the bulk of this effort was put behind updating the two libraries for this change (with `rtio`). * Printing a message on task failure (along with the backtrace) continues to live in libstd, not in librustrt. This is a consequence of the above decision to move the stdout/stderr handles to TLD rather than inside the `Task` itself. The unwinding API now supports registration of global callback functions which will be invoked when a task fails, allowing for libstd to register a function to print a message and a backtrace. The API for registering a callback is experimental and unsafe, as the ramifications of running code on unwinding is pretty hairy. * The `std::unstable::mutex` module has moved to `std::rt::mutex`. * The `std::unstable::sync` module has been moved to `std::rt::exclusive` and the type has been rewritten to not internally have an Arc and to have an RAII guard structure when locking. Old code should stop using `Exclusive` in favor of the primitives in `libsync`, but if necessary, old code should port to `Arc<Exclusive<T>>`. * The local heap has been stripped down to have fewer debugging options. None of these were tested, and none of these have been used in a very long time. [breaking-change]
2014-06-04 04:11:49 +02:00
NATIVE_DEPS_rust_builtin_$(1) := rust_builtin.c \
rust_android_dummy.c
msvc: Implement runtime support for unwinding Now that LLVM has been updated, the only remaining roadblock to implementing unwinding for MSVC is to fill out the runtime support in `std::rt::unwind::seh`. This commit does precisely that, fixing up some other bits and pieces along the way: * The `seh` unwinding module now uses `RaiseException` to initiate a panic. * The `rust_try.ll` file was rewritten for MSVC (as it's quite different) and is located at `rust_try_msvc_64.ll`, only included on MSVC builds for now. * The personality function for all landing pads generated by LLVM is hard-wired to `__C_specific_handler` instead of the standard `rust_eh_personality` lang item. This is required to get LLVM to emit SEH unwinding information instead of DWARF unwinding information. This also means that on MSVC the `rust_eh_personality` function is entirely unused (but is defined as it's a lang item). More details about how panicking works on SEH can be found in the `rust_try_msvc_64.ll` or `seh.rs` files, but I'm always open to adding more comments! A key aspect of this PR is missing, however, which is that **unwinding is still turned off by default for MSVC**. There is a [bug in llvm][llvm-bug] which causes optimizations to inline enough landing pads that LLVM chokes. If the compiler is optimized at `-O1` (where inlining isn't enabled) then it can bootstrap with unwinding enabled, but when optimized at `-O2` (inlining is enabled) then it hits a fatal LLVM error. [llvm-bug]: https://llvm.org/bugs/show_bug.cgi?id=23884
2015-06-19 23:57:06 +02:00
NATIVE_DEPS_rustrt_native_$(1) := arch/$$(HOST_$(1))/record_sp.S
NATIVE_DEPS_rust_test_helpers_$(1) := rust_test_helpers.c
NATIVE_DEPS_morestack_$(1) := arch/$$(HOST_$(1))/morestack.S
################################################################################
# You shouldn't find it that necessary to edit anything below this line.
################################################################################
# While we're defining the native libraries for each target, we define some
# common rules used to build files for various targets.
RT_OUTPUT_DIR_$(1) := $(1)/rt
$$(RT_OUTPUT_DIR_$(1))/%.o: $(S)src/rt/%.c $$(MKFILE_DEPS)
@mkdir -p $$(@D)
@$$(call E, compile: $$@)
$$(Q)$$(call CFG_COMPILE_C_$(1), $$@, \
$$(call CFG_CC_INCLUDE_$(1),$$(S)src/rt/hoedown/src) \
$$(call CFG_CC_INCLUDE_$(1),$$(S)src/rt) \
$$(RUNTIME_CFLAGS_$(1))) $$<
$$(RT_OUTPUT_DIR_$(1))/%.o: $(S)src/rt/%.S $$(MKFILE_DEPS) \
$$(LLVM_CONFIG_$$(CFG_BUILD))
@mkdir -p $$(@D)
@$$(call E, compile: $$@)
$$(Q)$$(call CFG_ASSEMBLE_$(1),$$@,$$<)
# On MSVC targets the compiler's default include path (e.g. where to find system
# headers) is specified by the INCLUDE environment variable. This may not be set
# so the ./configure script scraped the relevant values and this is the location
# that we put them into cl.exe's environment.
ifeq ($$(findstring msvc,$(1)),msvc)
$$(RT_OUTPUT_DIR_$(1))/%.o: \
export INCLUDE := $$(CFG_MSVC_INCLUDE_PATH_$$(HOST_$(1)))
$(1)/rustllvm/%.o: \
export INCLUDE := $$(CFG_MSVC_INCLUDE_PATH_$$(HOST_$(1)))
endif
endef
$(foreach target,$(CFG_TARGET),$(eval $(call NATIVE_LIBRARIES,$(target))))
# A macro for devining how to build third party libraries listed above (based
# on their dependencies).
#
# $(1) is the target
# $(2) is the lib name
define THIRD_PARTY_LIB
OBJS_$(2)_$(1) := $$(NATIVE_DEPS_$(2)_$(1):%=$$(RT_OUTPUT_DIR_$(1))/%)
OBJS_$(2)_$(1) := $$(OBJS_$(2)_$(1):.c=.o)
OBJS_$(2)_$(1) := $$(OBJS_$(2)_$(1):.cpp=.o)
OBJS_$(2)_$(1) := $$(OBJS_$(2)_$(1):.S=.o)
NATIVE_$(2)_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),$(2))
$$(RT_OUTPUT_DIR_$(1))/$$(NATIVE_$(2)_$(1)): $$(OBJS_$(2)_$(1))
@$$(call E, link: $$@)
$$(Q)$$(call CFG_CREATE_ARCHIVE_$(1),$$@) $$^
endef
$(foreach target,$(CFG_TARGET), \
$(eval $(call RUNTIME_RULES,$(target))))
$(foreach lib,$(NATIVE_LIBS), \
$(foreach target,$(CFG_TARGET), \
$(eval $(call THIRD_PARTY_LIB,$(target),$(lib)))))
################################################################################
# Building third-party targets with external build systems
#
# This location is meant for dependencies which have external build systems. It
# is still assumed that the output of each of these steps is a static library
# in the correct location.
################################################################################
define DEF_THIRD_PARTY_TARGETS
# $(1) is the target triple
ifeq ($$(CFG_WINDOWSY_$(1)), 1)
# This isn't necessarily a desired option, but it's harmless and works around
# what appears to be a mingw-w64 bug.
#
# https://sourceforge.net/p/mingw-w64/bugs/395/
JEMALLOC_ARGS_$(1) := --enable-lazy-lock
else ifeq ($(OSTYPE_$(1)), apple-ios)
JEMALLOC_ARGS_$(1) := --disable-tls
else ifeq ($(findstring android, $(OSTYPE_$(1))), android)
JEMALLOC_ARGS_$(1) := --disable-tls
endif
2015-04-09 00:12:08 +02:00
ifdef CFG_ENABLE_DEBUG_JEMALLOC
JEMALLOC_ARGS_$(1) += --enable-debug --enable-fill
endif
################################################################################
# jemalloc
################################################################################
ifdef CFG_ENABLE_FAST_MAKE
JEMALLOC_DEPS := $(S)/.gitmodules
else
JEMALLOC_DEPS := $(wildcard \
$(S)src/jemalloc/* \
$(S)src/jemalloc/*/* \
$(S)src/jemalloc/*/*/* \
$(S)src/jemalloc/*/*/*/*)
endif
# See #17183 for details, this file is touched during the build process so we
# don't want to consider it as a dependency.
JEMALLOC_DEPS := $(filter-out $(S)src/jemalloc/VERSION,$(JEMALLOC_DEPS))
JEMALLOC_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),jemalloc)
ifeq ($$(CFG_WINDOWSY_$(1)),1)
JEMALLOC_REAL_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),jemalloc_s)
else
JEMALLOC_REAL_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),jemalloc_pic)
endif
JEMALLOC_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(JEMALLOC_NAME_$(1))
JEMALLOC_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/jemalloc
JEMALLOC_LOCAL_$(1) := $$(JEMALLOC_BUILD_DIR_$(1))/lib/$$(JEMALLOC_REAL_NAME_$(1))
$$(JEMALLOC_LOCAL_$(1)): $$(JEMALLOC_DEPS) $$(MKFILE_DEPS)
@$$(call E, make: jemalloc)
cd "$$(JEMALLOC_BUILD_DIR_$(1))"; "$(S)src/jemalloc/configure" \
$$(JEMALLOC_ARGS_$(1)) --with-jemalloc-prefix=je_ $(CFG_JEMALLOC_FLAGS) \
--build=$$(CFG_GNU_TRIPLE_$(CFG_BUILD)) --host=$$(CFG_GNU_TRIPLE_$(1)) \
CC="$$(CC_$(1)) $$(CFG_JEMALLOC_CFLAGS_$(1))" \
AR="$$(AR_$(1))" \
RANLIB="$$(AR_$(1)) s" \
CPPFLAGS="-I $(S)src/rt/" \
EXTRA_CFLAGS="-g1 -ffunction-sections -fdata-sections"
$$(Q)$$(MAKE) -C "$$(JEMALLOC_BUILD_DIR_$(1))" build_lib_static
2014-06-14 08:23:31 +02:00
ifeq ($$(CFG_DISABLE_JEMALLOC),)
RUSTFLAGS_alloc := --cfg jemalloc
ifeq ($(1),$$(CFG_BUILD))
ifneq ($$(CFG_JEMALLOC_ROOT),)
$$(JEMALLOC_LIB_$(1)): $$(CFG_JEMALLOC_ROOT)/libjemalloc_pic.a
@$$(call E, copy: jemalloc)
$$(Q)cp $$< $$@
else
$$(JEMALLOC_LIB_$(1)): $$(JEMALLOC_LOCAL_$(1))
$$(Q)cp $$< $$@
endif
else
$$(JEMALLOC_LIB_$(1)): $$(JEMALLOC_LOCAL_$(1))
$$(Q)cp $$< $$@
endif
2014-06-14 08:23:31 +02:00
else
$$(JEMALLOC_LIB_$(1)): $$(MKFILE_DEPS)
$$(Q)touch $$@
endif
################################################################################
# compiler-rt
################################################################################
ifdef CFG_ENABLE_FAST_MAKE
COMPRT_DEPS := $(S)/.gitmodules
else
COMPRT_DEPS := $(wildcard \
$(S)src/compiler-rt/* \
$(S)src/compiler-rt/*/* \
$(S)src/compiler-rt/*/*/* \
$(S)src/compiler-rt/*/*/*/*)
endif
COMPRT_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),compiler-rt)
COMPRT_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(COMPRT_NAME_$(1))
COMPRT_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/compiler-rt
# Note that on MSVC-targeting builds we hardwire CC/AR to gcc/ar even though
# we're targeting MSVC. This is because although compiler-rt has a CMake build
# config I can't actually figure out how to use it, so I'm not sure how to use
# cl.exe to build the objects. Additionally, the compiler-rt library when built
# with gcc has the same ABI as cl.exe, so they're largely compatible
COMPRT_CC_$(1) := $$(CC_$(1))
COMPRT_AR_$(1) := $$(AR_$(1))
COMPRT_CFLAGS_$(1) := $$(CFG_GCCISH_CFLAGS_$(1))
ifeq ($$(findstring msvc,$(1)),msvc)
COMPRT_CC_$(1) := gcc
COMPRT_AR_$(1) := ar
ifeq ($$(findstring i686,$(1)),i686)
COMPRT_CFLAGS_$(1) := $$(CFG_GCCISH_CFLAGS_$(1)) -m32
else
COMPRT_CFLAGS_$(1) := $$(CFG_GCCISH_CFLAGS_$(1)) -m64
endif
endif
$$(COMPRT_LIB_$(1)): $$(COMPRT_DEPS) $$(MKFILE_DEPS)
@$$(call E, make: compiler-rt)
$$(Q)$$(MAKE) -C "$(S)src/compiler-rt" \
ProjSrcRoot="$(S)src/compiler-rt" \
ProjObjRoot="$$(abspath $$(COMPRT_BUILD_DIR_$(1)))" \
CC='$$(COMPRT_CC_$(1))' \
AR='$$(COMPRT_AR_$(1))' \
RANLIB='$$(COMPRT_AR_$(1)) s' \
CFLAGS="$$(COMPRT_CFLAGS_$(1))" \
TargetTriple=$(1) \
2014-04-22 03:43:19 +02:00
triple-builtins
$$(Q)cp $$(COMPRT_BUILD_DIR_$(1))/triple/builtins/libcompiler_rt.a $$@
################################################################################
# libbacktrace
#
# We use libbacktrace on linux to get symbols in backtraces, but only on linux.
# Elsewhere we use other system utilities, so this library is only built on
# linux.
################################################################################
BACKTRACE_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),backtrace)
BACKTRACE_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(BACKTRACE_NAME_$(1))
BACKTRACE_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/libbacktrace
# We don't use this on platforms that aren't linux-based, so just make the file
# available, the compilation of libstd won't actually build it.
ifeq ($$(findstring darwin,$$(OSTYPE_$(1))),darwin)
# See comment above
$$(BACKTRACE_LIB_$(1)):
touch $$@
else
ifeq ($$(findstring ios,$$(OSTYPE_$(1))),ios)
# See comment above
$$(BACKTRACE_LIB_$(1)):
touch $$@
else
ifeq ($$(CFG_WINDOWSY_$(1)),1)
# See comment above
$$(BACKTRACE_LIB_$(1)):
touch $$@
else
ifdef CFG_ENABLE_FAST_MAKE
BACKTRACE_DEPS := $(S)/.gitmodules
else
BACKTRACE_DEPS := $(wildcard $(S)src/libbacktrace/*)
endif
# We need to export CFLAGS because otherwise it doesn't pick up cross compile
# builds. If libbacktrace doesn't realize this, it will attempt to read 64-bit
# elf headers when compiled for a 32-bit system, yielding blank backtraces.
#
# This also removes the -Werror flag specifically to prevent errors during
# configuration.
#
# Down below you'll also see echos into the config.h generated by the
# ./configure script. This is done to force libbacktrace to *not* use the
# atomic/sync functionality because it pulls in unnecessary dependencies and we
# never use it anyway.
$$(BACKTRACE_BUILD_DIR_$(1))/Makefile: $$(BACKTRACE_DEPS) $$(MKFILE_DEPS)
@$$(call E, configure: libbacktrace for $(1))
$$(Q)rm -rf $$(BACKTRACE_BUILD_DIR_$(1))
$$(Q)mkdir -p $$(BACKTRACE_BUILD_DIR_$(1))
$$(Q)(cd $$(BACKTRACE_BUILD_DIR_$(1)) && \
CC="$$(CC_$(1))" \
AR="$$(AR_$(1))" \
RANLIB="$$(AR_$(1)) s" \
CFLAGS="$$(CFG_GCCISH_CFLAGS_$(1):-Werror=) -fno-stack-protector" \
$(S)src/libbacktrace/configure --target=$(1) --host=$(CFG_BUILD))
$$(Q)echo '#undef HAVE_ATOMIC_FUNCTIONS' >> \
$$(BACKTRACE_BUILD_DIR_$(1))/config.h
$$(Q)echo '#undef HAVE_SYNC_FUNCTIONS' >> \
$$(BACKTRACE_BUILD_DIR_$(1))/config.h
$$(BACKTRACE_LIB_$(1)): $$(BACKTRACE_BUILD_DIR_$(1))/Makefile $$(MKFILE_DEPS)
@$$(call E, make: libbacktrace)
$$(Q)$$(MAKE) -C $$(BACKTRACE_BUILD_DIR_$(1)) \
INCDIR=$(S)src/libbacktrace
$$(Q)cp $$(BACKTRACE_BUILD_DIR_$(1))/.libs/libbacktrace.a $$@
endif # endif for windowsy
endif # endif for ios
endif # endif for darwin
################################################################################
# libc/libunwind for musl
#
# When we're building a musl-like target we're going to link libc/libunwind
# statically into the standard library and liblibc, so we need to make sure
# they're in a location that we can find
################################################################################
ifeq ($$(findstring musl,$(1)),musl)
$$(RT_OUTPUT_DIR_$(1))/%: $$(CFG_MUSL_ROOT)/lib/%
cp $$^ $$@
endif
endef
# Instantiate template for all stages/targets
2013-10-21 11:18:21 +02:00
$(foreach target,$(CFG_TARGET), \
$(eval $(call DEF_THIRD_PARTY_TARGETS,$(target))))