auto merge of #10199 : alexcrichton/rust/no-propagate, r=brson

This commit removes the propagation of `link_args` attributes across crates. The first commit message has the reasons as to why. Additionally, this starts statically linking some C/C++ helper libraries that we have to their respective crates instead of throwing then in librustrt and then having everything depend on librustrt.

The major downside of this movement is that we're losing the ability to control visible symbols. I couldn't figure out a way to internalize symbols from a static library during the linking process, so everyone who links to librustdoc will be able to use its sundown implementation (not exactly ideal). I'm not entirely sure how to fix this (beyond generating a list of all public symbols, including rust ones, and passing that to the linker), but we may have a much easier time with this once we start using llvm's linker toolchain.

There's certainly a lot more possibilities in where this can go, but I didn't want to go too deep just yet. The main idea here is to stop propagating linker arguments and then see how we're able to start statically linking libraries as a result.

r? @catamorphism, you're going to be working on linking soon, so feel free to completely throw this away for something else!
This commit is contained in:
bors 2013-11-02 22:16:02 -07:00
commit b5c1b48048
13 changed files with 85 additions and 191 deletions

View File

@ -625,10 +625,10 @@ config.stamp: $(S)configure $(S)Makefile.in $(S)src/snapshots.txt
# new definitions), make sure definitions always precede their uses,
# especially for the dependency lists of recipes.
include $(CFG_SRC_DIR)mk/rt.mk
include $(CFG_SRC_DIR)mk/target.mk
include $(CFG_SRC_DIR)mk/host.mk
include $(CFG_SRC_DIR)mk/stage0.mk
include $(CFG_SRC_DIR)mk/rt.mk
include $(CFG_SRC_DIR)mk/rustllvm.mk
include $(CFG_SRC_DIR)mk/tools.mk
include $(CFG_SRC_DIR)mk/docs.mk

View File

@ -87,19 +87,11 @@ RUNTIME_CXXS_$(1)_$(2) := \
rt/sync/rust_thread.cpp \
rt/rust_builtin.cpp \
rt/rust_upcall.cpp \
rt/rust_uv.cpp \
rt/miniz.cpp \
rt/rust_android_dummy.cpp \
rt/rust_test_helpers.cpp
RUNTIME_CS_$(1)_$(2) := rt/sundown/src/autolink.c \
rt/sundown/src/buffer.c \
rt/sundown/src/stack.c \
rt/sundown/src/markdown.c \
rt/sundown/html/houdini_href_e.c \
rt/sundown/html/houdini_html_e.c \
rt/sundown/html/html_smartypants.c \
rt/sundown/html/html.c
RUNTIME_CS_$(1)_$(2) :=
RUNTIME_S_$(1)_$(2) := rt/arch/$$(HOST_$(1))/_context.S \
rt/arch/$$(HOST_$(1))/record_sp.S
@ -108,10 +100,7 @@ RT_BUILD_DIR_$(1)_$(2) := $$(RT_OUTPUT_DIR_$(1))/stage$(2)
RUNTIME_DEF_$(1)_$(2) := $$(RT_OUTPUT_DIR_$(1))/rustrt$$(CFG_DEF_SUFFIX_$(1))
RUNTIME_INCS_$(1)_$(2) := -I $$(S)src/rt -I $$(S)src/rt/isaac -I $$(S)src/rt/uthash \
-I $$(S)src/rt/arch/$$(HOST_$(1)) \
-I $$(S)src/rt/sundown/src \
-I $$(S)src/rt/sundown/html \
-I $$(S)src/libuv/include
-I $$(S)src/rt/arch/$$(HOST_$(1))
RUNTIME_OBJS_$(1)_$(2) := $$(RUNTIME_CXXS_$(1)_$(2):rt/%.cpp=$$(RT_BUILD_DIR_$(1)_$(2))/%.o) \
$$(RUNTIME_CS_$(1)_$(2):rt/%.c=$$(RT_BUILD_DIR_$(1)_$(2))/%.o) \
$$(RUNTIME_S_$(1)_$(2):rt/%.S=$$(RT_BUILD_DIR_$(1)_$(2))/%.o)
@ -140,10 +129,9 @@ $$(RT_BUILD_DIR_$(1)_$(2))/arch/$$(HOST_$(1))/libmorestack.a: $$(MORESTACK_OBJS_
$$(Q)$(AR_$(1)) rcs $$@ $$^
$$(RT_BUILD_DIR_$(1)_$(2))/$(CFG_RUNTIME_$(1)): $$(RUNTIME_OBJS_$(1)_$(2)) $$(MKFILE_DEPS) \
$$(RUNTIME_DEF_$(1)_$(2)) $$(LIBUV_LIB_$(1))
$$(RUNTIME_DEF_$(1)_$(2))
@$$(call E, link: $$@)
$$(Q)$$(call CFG_LINK_CXX_$(1),$$@, $$(RUNTIME_OBJS_$(1)_$(2)) \
$$(LIBUV_LIB_$(1)) \
$$(CFG_LIBUV_LINK_FLAGS_$(1)),$$(RUNTIME_DEF_$(1)_$(2)),$$(CFG_RUNTIME_$(1)))
# These could go in rt.mk or rustllvm.mk, they're needed for both.
@ -242,6 +230,54 @@ $$(LIBUV_LIB_$(1)): $$(LIBUV_DEPS) $$(LIBUV_MAKEFILE_$(1))
NO_LOAD="$$(LIBUV_NO_LOAD)" \
V=$$(VERBOSE)
endif
# libuv support functionality (extra C/C++ that we need to use libuv)
UV_SUPPORT_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),uv_support)
UV_SUPPORT_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/uv_support
UV_SUPPORT_LIB_$(1) := $$(UV_SUPPORT_DIR_$(1))/$$(UV_SUPPORT_NAME_$(1))
UV_SUPPORT_CS_$(1) := rt/rust_uv.cpp
UV_SUPPORT_OBJS_$(1) := $$(UV_SUPPORT_CS_$(1):rt/%.cpp=$$(UV_SUPPORT_DIR_$(1))/%.o)
$$(UV_SUPPORT_DIR_$(1))/%.o: rt/%.cpp
@$$(call E, compile: $$@)
@mkdir -p $$(@D)
$$(Q)$$(call CFG_COMPILE_CXX_$(1), $$@, \
-I $$(S)src/libuv/include \
$$(RUNTIME_CFLAGS_$(1))) $$<
$$(UV_SUPPORT_LIB_$(1)): $$(UV_SUPPORT_OBJS_$(1))
@$$(call E, link: $$@)
$$(Q)$$(AR_$(1)) rcs $$@ $$^
# sundown markdown library (used by librustdoc)
SUNDOWN_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),sundown)
SUNDOWN_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/sundown
SUNDOWN_LIB_$(1) := $$(SUNDOWN_DIR_$(1))/$$(SUNDOWN_NAME_$(1))
SUNDOWN_CS_$(1) := rt/sundown/src/autolink.c \
rt/sundown/src/buffer.c \
rt/sundown/src/stack.c \
rt/sundown/src/markdown.c \
rt/sundown/html/houdini_href_e.c \
rt/sundown/html/houdini_html_e.c \
rt/sundown/html/html_smartypants.c \
rt/sundown/html/html.c
SUNDOWN_OBJS_$(1) := $$(SUNDOWN_CS_$(1):rt/%.c=$$(SUNDOWN_DIR_$(1))/%.o)
$$(SUNDOWN_DIR_$(1))/%.o: rt/%.c
@$$(call E, compile: $$@)
@mkdir -p $$(@D)
$$(Q)$$(call CFG_COMPILE_C_$(1), $$@, \
-I $$(S)src/rt/sundown/src -I $$(S)src/rt/sundown/html \
$$(RUNTIME_CFLAGS_$(1))) $$<
$$(SUNDOWN_LIB_$(1)): $$(SUNDOWN_OBJS_$(1))
@$$(call E, link: $$@)
$$(Q)$$(AR_$(1)) rcs $$@ $$^
endef
# Instantiate template for all stages/targets

View File

@ -77,10 +77,15 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTUV_$(2)): \
$$(LIBRUSTUV_CRATE) $$(LIBRUSTUV_INPUTS) \
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)) \
$$(TSREQ$(1)_T_$(2)_H_$(3)) \
$$(LIBUV_LIB_$(2)) \
$$(UV_SUPPORT_LIB_$(2)) \
| $$(TLIB$(1)_T_$(2)_H_$(3))/
@$$(call E, compile_and_link: $$@)
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTUV_GLOB_$(2)),$$(notdir $$@))
$$(STAGE$(1)_T_$(2)_H_$(3)) $$(WFLAGS_ST$(1)) --out-dir $$(@D) $$< && touch $$@
$$(STAGE$(1)_T_$(2)_H_$(3)) $$(WFLAGS_ST$(1)) \
-L $$(UV_SUPPORT_DIR_$(2)) \
-L $$(dir $$(LIBUV_LIB_$(2))) \
--out-dir $$(@D) $$< && touch $$@
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTUV_GLOB_$(2)),$$(notdir $$@))
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBSYNTAX_$(3)): \
@ -117,13 +122,16 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC_$(3)): \
$$(STAGE$(1)_T_$(2)_H_$(3)) $$(WFLAGS_ST$(1)) --out-dir $$(@D) $$< && touch $$@
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTC_GLOB_$(2)),$$(notdir $$@))
# NOTE: after the next snapshot remove these '-L' flags
$$(TBIN$(1)_T_$(2)_H_$(3))/rustc$$(X_$(3)): \
$$(DRIVER_CRATE) \
$$(TSREQ$(1)_T_$(2)_H_$(3)) \
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC_$(3)) \
| $$(TBIN$(1)_T_$(2)_H_$(3))/
@$$(call E, compile_and_link: $$@)
$$(STAGE$(1)_T_$(2)_H_$(3)) --cfg rustc -o $$@ $$<
$$(STAGE$(1)_T_$(2)_H_$(3)) --cfg rustc -o $$@ $$< \
-L $$(UV_SUPPORT_DIR_$(2)) \
-L $$(dir $$(LIBUV_LIB_$(2)))
ifdef CFG_ENABLE_PAX_FLAGS
@$$(call E, apply PaX flags: $$@)
@"$(CFG_PAXCTL)" -cm "$$@"

View File

@ -358,7 +358,9 @@ $(3)/stage$(1)/test/rustuvtest-$(2)$$(X_$(2)): \
$$(LIBRUSTUV_CRATE) $$(LIBRUSTUV_INPUTS) \
$$(STDTESTDEP_$(1)_$(2)_$(3))
@$$(call E, compile_and_link: $$@)
$$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test
$$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test \
-L $$(UV_SUPPORT_DIR_$(2)) \
-L $$(dir $$(LIBUV_LIB_$(2)))
$(3)/stage$(1)/test/syntaxtest-$(2)$$(X_$(2)): \
$$(LIBSYNTAX_CRATE) $$(LIBSYNTAX_INPUTS) \
@ -392,7 +394,8 @@ $(3)/stage$(1)/test/rustdoctest-$(2)$$(X_$(2)): \
$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBSYNTAX_$(2)) \
$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBRUSTC_$(2))
@$$(call E, compile_and_link: $$@)
$$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test
$$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test \
-L $$(SUNDOWN_DIR_$(2))
endef

View File

@ -57,10 +57,12 @@ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTDOC_$(4)): \
$$(RUSTDOC_LIB) $$(RUSTDOC_INPUTS) \
$$(SREQ$(1)_T_$(4)_H_$(3)) \
$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTC_$(4)) \
$$(SUNDOWN_LIB_$(4)) \
| $$(TLIB$(1)_T_$(4)_H_$(3))/
@$$(call E, compile_and_link: $$@)
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTDOC_GLOB_$(4)),$$(notdir $$@))
$$(STAGE$(1)_T_$(4)_H_$(3)) $$(WFLAGS_ST$(1)) --out-dir $$(@D) $$< && touch $$@
$$(STAGE$(1)_T_$(4)_H_$(3)) $$(WFLAGS_ST$(1)) \
-L $$(SUNDOWN_DIR_$(4)) --out-dir $$(@D) $$< && touch $$@
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTDOC_GLOB_$(4)),$$(notdir $$@))
$$(TBIN$(1)_T_$(4)_H_$(3))/rustdoc$$(X_$(4)): \

View File

@ -16,7 +16,7 @@ use lib::llvm::llvm;
use lib::llvm::ModuleRef;
use lib;
use metadata::common::LinkMeta;
use metadata::{encoder, csearch, cstore, filesearch};
use metadata::{encoder, cstore, filesearch};
use middle::trans::context::CrateContext;
use middle::trans::common::gensym_name;
use middle::ty;
@ -1043,14 +1043,6 @@ pub fn link_args(sess: Session,
let ula = cstore::get_used_link_args(cstore);
for arg in ula.iter() { args.push(arg.to_owned()); }
// Add all the link args for external crates.
do cstore::iter_crate_data(cstore) |crate_num, _| {
let link_args = csearch::get_link_args_for_crate(cstore, crate_num);
for link_arg in link_args.move_iter() {
args.push(link_arg);
}
}
// # Extern library linking
// User-supplied library search paths (-L on the cammand line) These are

View File

@ -304,8 +304,7 @@ pub mod llvm {
use super::debuginfo::*;
use std::libc::{c_char, c_int, c_longlong, c_ushort, c_uint, c_ulonglong};
#[link_args = "-Lrustllvm -lrustllvm"]
#[link_name = "rustllvm"]
#[link_args = "-lrustllvm"]
extern {
/* Create and destroy contexts. */
pub fn LLVMContextCreate() -> ContextRef;

View File

@ -261,13 +261,6 @@ pub fn get_item_visibility(cstore: @mut cstore::CStore,
decoder::get_item_visibility(cdata, def_id.node)
}
pub fn get_link_args_for_crate(cstore: @mut cstore::CStore,
crate_num: ast::CrateNum)
-> ~[~str] {
let cdata = cstore::get_crate_data(cstore, crate_num);
decoder::get_link_args_for_crate(cdata)
}
pub fn each_impl(cstore: @mut cstore::CStore,
crate_num: ast::CrateNum,
callback: &fn(ast::DefId)) {

View File

@ -1456,16 +1456,6 @@ pub fn translate_def_id(cdata: Cmd, did: ast::DefId) -> ast::DefId {
}
}
pub fn get_link_args_for_crate(cdata: Cmd) -> ~[~str] {
let link_args = reader::get_doc(reader::Doc(cdata.data), tag_link_args);
let mut result = ~[];
do reader::tagged_docs(link_args, tag_link_args_arg) |arg_doc| {
result.push(arg_doc.as_str());
true
};
result
}
pub fn each_impl(cdata: Cmd, callback: &fn(ast::DefId)) {
let impls_doc = reader::get_doc(reader::Doc(cdata.data), tag_impls);
let _ = do reader::tagged_docs(impls_doc, tag_impls_impl) |impl_doc| {

View File

@ -75,7 +75,6 @@ struct Stats {
attr_bytes: u64,
dep_bytes: u64,
lang_item_bytes: u64,
link_args_bytes: u64,
impl_bytes: u64,
misc_bytes: u64,
item_bytes: u64,
@ -1610,19 +1609,6 @@ fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
ebml_w.end_tag(); // tag_lang_items
}
fn encode_link_args(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
ebml_w.start_tag(tag_link_args);
let link_args = cstore::get_used_link_args(ecx.cstore);
for link_arg in link_args.iter() {
ebml_w.start_tag(tag_link_args_arg);
ebml_w.writer.write(link_arg.as_bytes());
ebml_w.end_tag();
}
ebml_w.end_tag();
}
struct ImplVisitor<'self> {
ecx: &'self EncodeContext<'self>,
ebml_w: &'self mut writer::Encoder,
@ -1740,7 +1726,6 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
attr_bytes: 0,
dep_bytes: 0,
lang_item_bytes: 0,
link_args_bytes: 0,
impl_bytes: 0,
misc_bytes: 0,
item_bytes: 0,
@ -1797,11 +1782,6 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
encode_lang_items(&ecx, &mut ebml_w);
ecx.stats.lang_item_bytes = wr.tell() - i;
// Encode the link args.
i = wr.tell();
encode_link_args(&ecx, &mut ebml_w);
ecx.stats.link_args_bytes = wr.tell() - i;
// Encode the def IDs of impls, for coherence checking.
i = wr.tell();
encode_impls(&ecx, crate, &mut ebml_w);
@ -1838,7 +1818,6 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
println!(" attribute bytes: {}", ecx.stats.attr_bytes);
println!(" dep bytes: {}", ecx.stats.dep_bytes);
println!(" lang item bytes: {}", ecx.stats.lang_item_bytes);
println!(" link args bytes: {}", ecx.stats.link_args_bytes);
println!(" impl bytes: {}", ecx.stats.impl_bytes);
println!(" misc bytes: {}", ecx.stats.misc_bytes);
println!(" item bytes: {}", ecx.stats.item_bytes);

View File

@ -69,6 +69,7 @@ struct buf {
}
// sundown FFI
#[link_args = "-lsundown"]
extern {
fn sdhtml_renderer(callbacks: *sd_callbacks,
options_ptr: *html_renderopt,

View File

@ -1003,6 +1003,8 @@ pub struct uv_err_data {
err_msg: ~str,
}
// uv_support is the result of compiling rust_uv.cpp
#[link_args = "-luv_support -luv"]
extern {
fn rust_uv_handle_size(type_: uintptr_t) -> size_t;
@ -1172,3 +1174,13 @@ extern {
signum: c_int) -> c_int;
fn rust_uv_signal_stop(handle: *uv_signal_t) -> c_int;
}
// libuv requires various system libraries to successfully link on some
// platforms
#[cfg(target_os = "linux")]
#[link_args = "-lpthread"]
extern {}
#[cfg(target_os = "win32")]
#[link_args = "-lWs2_32 -lpsapi -liphlpapi"]
extern {}

View File

@ -26,92 +26,6 @@ rust_win32_rand_gen
rust_win32_rand_release
upcall_rust_personality
upcall_reset_stack_limit
rust_uv_loop_new
rust_uv_loop_delete
rust_uv_walk
rust_uv_loop_set_data
rust_uv_run
rust_uv_close
rust_uv_async_send
rust_uv_async_init
rust_uv_timer_init
rust_uv_timer_start
rust_uv_timer_stop
rust_uv_tcp_init
rust_uv_buf_init
rust_uv_strerror
rust_uv_err_name
rust_uv_ip4_addr
rust_uv_ip4_name
rust_uv_ip6_addr
rust_uv_ip6_name
rust_uv_tcp_connect
rust_uv_tcp_bind
rust_uv_tcp_connect6
rust_uv_tcp_bind6
rust_uv_tcp_getsockname
rust_uv_tcp_nodelay
rust_uv_tcp_keepalive
rust_uv_tcp_simultaneous_accepts
rust_uv_udp_init
rust_uv_udp_bind
rust_uv_udp_bind6
rust_uv_udp_send
rust_uv_udp_send6
rust_uv_udp_recv_start
rust_uv_udp_recv_stop
rust_uv_get_udp_handle_from_send_req
rust_uv_udp_getsockname
rust_uv_udp_set_membership
rust_uv_udp_set_multicast_loop
rust_uv_udp_set_multicast_ttl
rust_uv_udp_set_ttl
rust_uv_udp_set_broadcast
rust_uv_is_ipv4_sockaddr
rust_uv_is_ipv6_sockaddr
rust_uv_malloc_sockaddr_storage
rust_uv_free_sockaddr_storage
rust_uv_listen
rust_uv_accept
rust_uv_write
rust_uv_read_start
rust_uv_read_stop
rust_uv_is_ipv4_addrinfo
rust_uv_is_ipv6_addrinfo
rust_uv_get_next_addrinfo
rust_uv_addrinfo_as_sockaddr_in
rust_uv_addrinfo_as_sockaddr_in6
rust_uv_get_stream_handle_from_connect_req
rust_uv_get_stream_handle_from_write_req
rust_uv_get_loop_for_uv_handle
rust_uv_get_data_for_uv_loop
rust_uv_set_data_for_uv_loop
rust_uv_get_data_for_uv_handle
rust_uv_set_data_for_uv_handle
rust_uv_get_data_for_req
rust_uv_set_data_for_req
rust_uv_get_base_from_buf
rust_uv_get_len_from_buf
rust_uv_getaddrinfo
rust_uv_freeaddrinfo
rust_uv_idle_init
rust_uv_idle_start
rust_uv_idle_stop
rust_uv_fs_open
rust_uv_fs_unlink
rust_uv_fs_write
rust_uv_fs_read
rust_uv_fs_close
rust_uv_get_result_from_fs_req
rust_uv_get_ptr_from_fs_req
rust_uv_get_loop_from_fs_req
rust_uv_fs_stat
rust_uv_fs_fstat
rust_uv_fs_req_cleanup
rust_uv_populate_uv_stat
rust_uv_fs_mkdir
rust_uv_fs_rmdir
rust_uv_fs_readdir
rust_dbg_lock_create
rust_dbg_lock_destroy
rust_dbg_lock_lock
@ -128,9 +42,6 @@ rust_signal_little_lock
rust_wait_little_lock
tdefl_compress_mem_to_heap
tinfl_decompress_mem_to_heap
rust_uv_ip4_port
rust_uv_ip6_port
rust_uv_tcp_getpeername
rust_raw_thread_start
rust_raw_thread_join
rust_raw_thread_delete
@ -150,14 +61,6 @@ rust_dbg_extern_return_TwoU32s
rust_dbg_extern_return_TwoU64s
rust_dbg_extern_identity_double
rust_dbg_extern_identity_u8
rust_uv_handle_size
rust_uv_req_size
rust_uv_handle_type_max
rust_uv_req_type_max
rust_uv_ip4_addrp
rust_uv_ip6_addrp
rust_uv_free_ip4_addr
rust_uv_free_ip6_addr
rust_initialize_rt_tls_key
rust_dbg_next_port
rust_try
@ -172,29 +75,5 @@ rust_get_global_args_ptr
rust_take_global_args_lock
rust_drop_global_args_lock
rust_get_test_int
rust_uv_get_loop_from_getaddrinfo_req
rust_uv_spawn
rust_uv_process_kill
rust_set_stdio_container_flags
rust_set_stdio_container_fd
rust_set_stdio_container_stream
rust_uv_process_pid
rust_uv_pipe_init
rust_uv_signal_init
rust_uv_signal_start
rust_uv_signal_stop
sdhtml_renderer
sd_markdown_new
sd_markdown_render
sd_markdown_free
bufrelease
bufnew
rust_take_dlerror_lock
rust_drop_dlerror_lock
rust_uv_pipe_open
rust_uv_pipe_bind
rust_uv_pipe_connect
rust_uv_tty_init
rust_uv_tty_set_mode
rust_uv_tty_get_winsize
rust_uv_guess_handle