Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow users to override or filter list of exported symbols passed to the WASM linker #104130

Open
Manishearth opened this issue Nov 7, 2022 · 12 comments
Labels
A-linkage Area: linking into static, shared libraries and binaries O-wasm Target: WASM (WebAssembly), http://webassembly.org/

Comments

@Manishearth
Copy link
Member

Currently, the way export visibility is handled in WASM is that rustc manually passes a list of all exported functions to the WASM linker:

for sym in symbols {
self.cmd.arg("--export").arg(&sym);
}

In almost every mode of compilation for Rust it doesn't matter too much if the exports list covers more than is needed, because there's a linker at the very end dealing with this. Rlibs and staticlibs may end up containing extra symbols, but the end binary will have dead code removed by the final linker. Dynamic libraries end up containing extra symbols which is a disk size issue (not a huge deal), but the dynamic linker's capable of only paging in the necessary bits.

The landscape is very different for WASM, however. In WASM, the final binary is a .wasm file that gets sent over the network, and its size matters. It's impractical to compile large libraries to a single .wasm file and recommend everyone use it since most users will not be using 99% of that wasm file.

There are tools for doing dead code elimination in JS, usually going by the name "tree shaking". Furthermore it's often practical for a WASM user to just list out the symbols they need.

With all of this, it would be useful to be able to customize which symbols get exported as a part of the linker process, rather than updating the code (as different library clients will need different things and it might not always be practical to pepper the library with a hundred client specific cfgs, nor is it an appropriate separation of concerns)

It would be nice if rust had a pair of codegen flags that would:

  • Allow explicitly allowlisting/listing symbols that get passed down to rust-lld --export
  • Allow explicitly denylisting symbols that get passed down to rust-lld --export, to "filter out" features

cc @sffc

@Manishearth Manishearth added A-linkage Area: linking into static, shared libraries and binaries O-wasm Target: WASM (WebAssembly), http://webassembly.org/ labels Nov 7, 2022
@Manishearth
Copy link
Member Author

A similar issue seems to be #73958, though that applies to staticlibs too

(the flag proposed here may help that use case as well)

@sffc
Copy link

sffc commented Nov 8, 2022

Even if I manually invoke lld with a pruned set of --export arguments, everything that is no_mangle'd seems to still get exported. So I think #73958 may need to be resolved first.

@sffc
Copy link

sffc commented Nov 8, 2022

Some data for why customizing the exported symbols at link time is superior to post-processing methods such as wasm-snip:

In the ICU4X library, we export approximately 500 symbols from our WASM file. Most clients need only a small subset of the 500 symbols. I did a test where I removed about 300 of the symbols (those in the formatting and collation components) with two methods:

  1. Manually deleting the symbols from the *.rs files and re-compiling
  2. Running wasm-snip on the full *.wasm file

In both cases, the source *.wasm file was built with the same compiler options.

Results:

Method Code Size (Bytes)
Fresh Compilation 434672
Wasm-Snip 474705

CC @fitzgen

Steps to reproduce:

1. Download the icu4x repository at commit 7d4a5983e0303ff9e8ea87efae0f33ea8da4eeba 2. Create a file `build.sh` with the following contents:
#! /usr/bin/bash

set -e

# Set toolchain variable to a default if not defined
ICU4X_NIGHTLY_TOOLCHAIN="${ICU4X_NIGHTLY_TOOLCHAIN:-nightly-2022-04-05}"

# Install Rust toolchains
rustup toolchain install ${ICU4X_NIGHTLY_TOOLCHAIN}
rustup +${ICU4X_NIGHTLY_TOOLCHAIN} component add rust-src

# 100 KiB, working around a bug in older rustc
# https://github.com/unicode-org/icu4x/issues/2753
# keep in sync with .cargo/config.toml
WASM_STACK_SIZE=100000

BASEDIR=$(dirname "$(realpath "$0")")

# Build the WASM library
RUSTFLAGS="-Cpanic=abort -Copt-level=s -C link-arg=-zstack-size=${WASM_STACK_SIZE} -Clinker-plugin-lto -Ccodegen-units=1" cargo +${ICU4X_NIGHTLY_TOOLCHAIN} build \
    -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort \
    --target wasm32-unknown-unknown \
    --release \
    --package icu_capi_cdylib \
    --features wasm_default
  1. Run build.sh and save the resulting WASM file, found at target/wasm32-unknown-unknown/release/icu_capi_cdylib.wasm, as _debug/all.wasm
  2. Create a file ffi/diplomat/src/common.rs with the following content (I plan to PR this):
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).

#[diplomat::bridge]
pub mod ffi {
    use alloc::boxed::Box;

    #[diplomat::enum_convert(core::cmp::Ordering)]
    #[diplomat::rust_link(core::cmp::Ordering, Enum)]
    pub enum ICU4XOrdering {
        Less = -1,
        Equal = 0,
        Greater = 1,
    }
}
  1. Edit ffi/diplomat/src/lib.rs and comment out the modules as follows:
pub mod bidi;
// pub mod calendar;
// pub mod collator;
pub mod common;
pub mod data_struct;
// pub mod date;
// pub mod datetime;
// pub mod datetime_formatter;
// pub mod decimal;
pub mod errors;
pub mod fallbacker;
// pub mod fixed_decimal;
// pub mod list;
pub mod locale;
// pub mod locid_transform;
pub mod logging;
// pub mod normalizer;
// pub mod normalizer_properties;
// pub mod pluralrules;
pub mod properties_maps;
pub mod properties_sets;
pub mod provider;
pub mod script;
// pub mod segmenter_grapheme;
// pub mod segmenter_line;
// pub mod segmenter_sentence;
// pub mod segmenter_word;
// pub mod time;
// pub mod timezone;
// pub mod timezone_formatter;
// pub mod week;
// pub mod zoned_formatter;
  1. Re-run build.sh and save the resulting file as _debug/only_properties.wasm
  2. Run cargo install wasm-snip, and then run wasm-snip -o _debug/stripped_all.wasm _debug/only_properties.wasm ICU4XAnyCalendarKind_get_for_locale ICU4XAnyCalendarKind_get_for_bcp47 ICU4XAnyCalendarKind_bcp47 ICU4XAnyCalendarKind_destroy ICU4XCalendar_create_for_locale ICU4XCalendar_create_for_kind ICU4XCalendar_kind ICU4XCalendar_destroy ICU4XCollator_create_v1 ICU4XCollator_compare ICU4XCollator_compare_valid_utf8 ICU4XCollator_compare_utf16 ICU4XCollator_destroy ICU4XCollatorAlternateHandling_destroy ICU4XCollatorBackwardSecondLevel_destroy ICU4XCollatorCaseFirst_destroy ICU4XCollatorCaseLevel_destroy ICU4XCollatorMaxVariable_destroy ICU4XCollatorNumeric_destroy ICU4XCollatorOptionsV1_destroy ICU4XCollatorStrength_destroy ICU4XDate_create_from_iso_in_calendar ICU4XDate_create_from_codes_in_calendar ICU4XDate_to_calendar ICU4XDate_to_iso ICU4XDate_day_of_month ICU4XDate_day_of_week ICU4XDate_week_of_month ICU4XDate_week_of_year ICU4XDate_ordinal_month ICU4XDate_month_code ICU4XDate_year_in_era ICU4XDate_era ICU4XDate_months_in_year ICU4XDate_days_in_month ICU4XDate_days_in_year ICU4XDate_calendar ICU4XDate_destroy ICU4XIsoDate_create ICU4XIsoDate_to_calendar ICU4XIsoDate_to_any ICU4XIsoDate_day_of_month ICU4XIsoDate_day_of_week ICU4XIsoDate_week_of_month ICU4XIsoDate_week_of_year ICU4XIsoDate_month ICU4XIsoDate_year ICU4XIsoDate_months_in_year ICU4XIsoDate_days_in_month ICU4XIsoDate_days_in_year ICU4XIsoDate_destroy ICU4XIsoWeekday_destroy ICU4XDateTime_create_from_iso_in_calendar ICU4XDateTime_create_from_codes_in_calendar ICU4XDateTime_create_from_date_and_time ICU4XDateTime_date ICU4XDateTime_time ICU4XDateTime_to_iso ICU4XDateTime_to_calendar ICU4XDateTime_hour ICU4XDateTime_minute ICU4XDateTime_second ICU4XDateTime_nanosecond ICU4XDateTime_day_of_month ICU4XDateTime_day_of_week ICU4XDateTime_week_of_month ICU4XDateTime_week_of_year ICU4XDateTime_ordinal_month ICU4XDateTime_month_code ICU4XDateTime_year_in_era ICU4XDateTime_era ICU4XDateTime_months_in_year ICU4XDateTime_days_in_month ICU4XDateTime_days_in_year ICU4XDateTime_calendar ICU4XDateTime_destroy ICU4XIsoDateTime_create ICU4XIsoDateTime_crate_from_date_and_time ICU4XIsoDateTime_create_from_minutes_since_local_unix_epoch ICU4XIsoDateTime_date ICU4XIsoDateTime_time ICU4XIsoDateTime_to_any ICU4XIsoDateTime_minutes_since_local_unix_epoch ICU4XIsoDateTime_to_calendar ICU4XIsoDateTime_hour ICU4XIsoDateTime_minute ICU4XIsoDateTime_second ICU4XIsoDateTime_nanosecond ICU4XIsoDateTime_day_of_month ICU4XIsoDateTime_day_of_week ICU4XIsoDateTime_week_of_month ICU4XIsoDateTime_week_of_year ICU4XIsoDateTime_month ICU4XIsoDateTime_year ICU4XIsoDateTime_months_in_year ICU4XIsoDateTime_days_in_month ICU4XIsoDateTime_days_in_year ICU4XIsoDateTime_destroy ICU4XDateFormatter_create_with_length ICU4XDateFormatter_format_date ICU4XDateFormatter_format_iso_date ICU4XDateFormatter_format_datetime ICU4XDateFormatter_format_iso_datetime ICU4XDateFormatter_destroy ICU4XDateLength_destroy ICU4XDateTimeFormatter_create_with_lengths ICU4XDateTimeFormatter_format_datetime ICU4XDateTimeFormatter_format_iso_datetime ICU4XDateTimeFormatter_destroy ICU4XGregorianDateFormatter_create_with_length ICU4XGregorianDateFormatter_format_iso_date ICU4XGregorianDateFormatter_format_iso_datetime ICU4XGregorianDateFormatter_destroy ICU4XGregorianDateTimeFormatter_create_with_lengths ICU4XGregorianDateTimeFormatter_format_iso_datetime ICU4XGregorianDateTimeFormatter_destroy ICU4XTimeFormatter_create_with_length ICU4XTimeFormatter_format_time ICU4XTimeFormatter_format_datetime ICU4XTimeFormatter_format_iso_datetime ICU4XTimeFormatter_destroy ICU4XTimeLength_destroy ICU4XFixedDecimalFormatter_create_with_grouping_strategy ICU4XFixedDecimalFormatter_create_with_decimal_symbols_v1 ICU4XFixedDecimalFormatter_format ICU4XFixedDecimalFormatter_destroy ICU4XFixedDecimalGroupingStrategy_destroy ICU4XFixedDecimal_create_from_i32 ICU4XFixedDecimal_create_from_u32 ICU4XFixedDecimal_create_from_i64 ICU4XFixedDecimal_create_from_u64 ICU4XFixedDecimal_create_from_f64_with_integer_precision ICU4XFixedDecimal_create_from_f64_with_lower_magnitude ICU4XFixedDecimal_create_from_f64_with_significant_digits ICU4XFixedDecimal_create_from_f64_with_floating_precision ICU4XFixedDecimal_create_from_string ICU4XFixedDecimal_digit_at ICU4XFixedDecimal_magnitude_start ICU4XFixedDecimal_magnitude_end ICU4XFixedDecimal_nonzero_magnitude_start ICU4XFixedDecimal_nonzero_magnitude_end ICU4XFixedDecimal_is_zero ICU4XFixedDecimal_multiply_pow10 ICU4XFixedDecimal_sign ICU4XFixedDecimal_set_sign ICU4XFixedDecimal_apply_sign_display ICU4XFixedDecimal_trim_start ICU4XFixedDecimal_trim_end ICU4XFixedDecimal_pad_start ICU4XFixedDecimal_pad_end ICU4XFixedDecimal_set_max_position ICU4XFixedDecimal_trunc ICU4XFixedDecimal_half_trunc ICU4XFixedDecimal_expand ICU4XFixedDecimal_half_expand ICU4XFixedDecimal_ceil ICU4XFixedDecimal_half_ceil ICU4XFixedDecimal_floor ICU4XFixedDecimal_half_floor ICU4XFixedDecimal_half_even ICU4XFixedDecimal_concatenate_end ICU4XFixedDecimal_to_string ICU4XFixedDecimal_destroy ICU4XFixedDecimalSign_destroy ICU4XFixedDecimalSignDisplay_destroy ICU4XList_create ICU4XList_create_with_capacity ICU4XList_push ICU4XList_len ICU4XList_destroy ICU4XListFormatter_create_and_with_length ICU4XListFormatter_create_or_with_length ICU4XListFormatter_create_unit_with_length ICU4XListFormatter_format ICU4XListFormatter_destroy ICU4XListLength_destroy ICU4XLocaleCanonicalizer_create ICU4XLocaleCanonicalizer_canonicalize ICU4XLocaleCanonicalizer_destroy ICU4XLocaleExpander_create ICU4XLocaleExpander_maximize ICU4XLocaleExpander_minimize ICU4XLocaleExpander_destroy ICU4XTransformResult_destroy ICU4XComposingNormalizer_create_nfc ICU4XComposingNormalizer_create_nfkc ICU4XComposingNormalizer_normalize ICU4XComposingNormalizer_is_normalized ICU4XComposingNormalizer_destroy ICU4XDecomposingNormalizer_create_nfd ICU4XDecomposingNormalizer_create_nfkd ICU4XDecomposingNormalizer_normalize ICU4XDecomposingNormalizer_is_normalized ICU4XDecomposingNormalizer_destroy ICU4XCanonicalCombiningClassMap_create ICU4XCanonicalCombiningClassMap_get ICU4XCanonicalCombiningClassMap_get32 ICU4XCanonicalCombiningClassMap_destroy ICU4XCanonicalComposition_create ICU4XCanonicalComposition_compose ICU4XCanonicalComposition_destroy ICU4XCanonicalDecomposition_create ICU4XCanonicalDecomposition_decompose ICU4XCanonicalDecomposition_destroy ICU4XDecomposed_destroy ICU4XPluralCategories_destroy ICU4XPluralCategory_get_for_cldr_string ICU4XPluralCategory_destroy ICU4XPluralOperands_create_from_string ICU4XPluralOperands_destroy ICU4XPluralRules_create_cardinal ICU4XPluralRules_create_ordinal ICU4XPluralRules_category_for ICU4XPluralRules_categories ICU4XPluralRules_destroy ICU4XGraphemeClusterBreakIteratorLatin1_next ICU4XGraphemeClusterBreakIteratorLatin1_destroy ICU4XGraphemeClusterBreakIteratorUtf16_next ICU4XGraphemeClusterBreakIteratorUtf16_destroy ICU4XGraphemeClusterBreakIteratorUtf8_next ICU4XGraphemeClusterBreakIteratorUtf8_destroy ICU4XGraphemeClusterSegmenter_create ICU4XGraphemeClusterSegmenter_segment_utf8 ICU4XGraphemeClusterSegmenter_segment_utf16 ICU4XGraphemeClusterSegmenter_segment_latin1 ICU4XGraphemeClusterSegmenter_destroy ICU4XLineBreakIteratorLatin1_next ICU4XLineBreakIteratorLatin1_destroy ICU4XLineBreakIteratorUtf16_next ICU4XLineBreakIteratorUtf16_destroy ICU4XLineBreakIteratorUtf8_next ICU4XLineBreakIteratorUtf8_destroy ICU4XLineBreakOptionsV1_destroy ICU4XLineBreakRule_destroy ICU4XLineSegmenter_create ICU4XLineSegmenter_create_with_options_v1 ICU4XLineSegmenter_segment_utf8 ICU4XLineSegmenter_segment_utf16 ICU4XLineSegmenter_segment_latin1 ICU4XLineSegmenter_destroy ICU4XWordBreakRule_destroy ICU4XSentenceBreakIteratorLatin1_next ICU4XSentenceBreakIteratorLatin1_destroy ICU4XSentenceBreakIteratorUtf16_next ICU4XSentenceBreakIteratorUtf16_destroy ICU4XSentenceBreakIteratorUtf8_next ICU4XSentenceBreakIteratorUtf8_destroy ICU4XSentenceSegmenter_create ICU4XSentenceSegmenter_segment_utf8 ICU4XSentenceSegmenter_segment_utf16 ICU4XSentenceSegmenter_segment_latin1 ICU4XSentenceSegmenter_destroy ICU4XWordBreakIteratorLatin1_next ICU4XWordBreakIteratorLatin1_destroy ICU4XWordBreakIteratorUtf16_next ICU4XWordBreakIteratorUtf16_destroy ICU4XWordBreakIteratorUtf8_next ICU4XWordBreakIteratorUtf8_destroy ICU4XWordSegmenter_create ICU4XWordSegmenter_segment_utf8 ICU4XWordSegmenter_segment_utf16 ICU4XWordSegmenter_segment_latin1 ICU4XWordSegmenter_destroy ICU4XTime_create ICU4XTime_hour ICU4XTime_minute ICU4XTime_second ICU4XTime_nanosecond ICU4XTime_destroy ICU4XCustomTimeZone_create_from_string ICU4XCustomTimeZone_create_empty ICU4XCustomTimeZone_create_utc ICU4XCustomTimeZone_try_set_gmt_offset_seconds ICU4XCustomTimeZone_clear_gmt_offset ICU4XCustomTimeZone_gmt_offset_seconds ICU4XCustomTimeZone_is_gmt_offset_positive ICU4XCustomTimeZone_is_gmt_offset_zero ICU4XCustomTimeZone_gmt_offset_has_minutes ICU4XCustomTimeZone_gmt_offset_has_seconds ICU4XCustomTimeZone_try_set_time_zone_id ICU4XCustomTimeZone_clear_time_zone_id ICU4XCustomTimeZone_time_zone_id ICU4XCustomTimeZone_try_set_metazone_id ICU4XCustomTimeZone_clear_metazone_id ICU4XCustomTimeZone_metazone_id ICU4XCustomTimeZone_try_set_zone_variant ICU4XCustomTimeZone_clear_zone_variant ICU4XCustomTimeZone_zone_variant ICU4XCustomTimeZone_set_standard_time ICU4XCustomTimeZone_set_daylight_time ICU4XCustomTimeZone_is_standard_time ICU4XCustomTimeZone_is_daylight_time ICU4XCustomTimeZone_maybe_calculate_metazone ICU4XCustomTimeZone_destroy ICU4XMetazoneCalculator_create ICU4XMetazoneCalculator_destroy ICU4XIsoTimeZoneFormat_destroy ICU4XIsoTimeZoneMinuteDisplay_destroy ICU4XIsoTimeZoneOptions_destroy ICU4XIsoTimeZoneSecondDisplay_destroy ICU4XTimeZoneFormatter_create_with_localized_gmt_fallback ICU4XTimeZoneFormatter_create_with_iso_8601_fallback ICU4XTimeZoneFormatter_load_generic_non_location_long ICU4XTimeZoneFormatter_load_generic_non_location_short ICU4XTimeZoneFormatter_load_specific_non_location_long ICU4XTimeZoneFormatter_load_specific_non_location_short ICU4XTimeZoneFormatter_load_generic_location_format ICU4XTimeZoneFormatter_load_localized_gmt_format ICU4XTimeZoneFormatter_load_iso_8601_format ICU4XTimeZoneFormatter_format_custom_time_zone ICU4XTimeZoneFormatter_destroy ICU4XWeekCalculator_create ICU4XWeekCalculator_create_from_first_day_of_week_and_min_week_days ICU4XWeekCalculator_first_weekday ICU4XWeekCalculator_min_week_days ICU4XWeekCalculator_destroy ICU4XWeekOf_destroy ICU4XWeekRelativeUnit_destroy ICU4XGregorianZonedDateTimeFormatter_create_with_lengths ICU4XGregorianZonedDateTimeFormatter_create_with_lengths_and_iso_8601_time_zone_fallback ICU4XGregorianZonedDateTimeFormatter_format_iso_datetime_with_custom_time_zone ICU4XGregorianZonedDateTimeFormatter_destroy ICU4XZonedDateTimeFormatter_create_with_lengths ICU4XZonedDateTimeFormatter_create_with_lengths_and_iso_8601_time_zone_fallback ICU4XZonedDateTimeFormatter_format_datetime_with_custom_time_zone ICU4XZonedDateTimeFormatter_format_iso_datetime_with_custom_time_zone ICU4XZonedDateTimeFormatter_destroy
  3. Since running wasm-snip seems to deflate wasm files even if no symbols are stripped, also run: wasm-snip -o _debug/stripped_only_properties.wasm _debug/only_properties.wasm
  4. Compare the two "snipped" wasm files.

@bjorn3
Copy link
Member

bjorn3 commented Nov 8, 2022

What happens if you run wasm-opt after wasm-snip? Does that win back the 40kb?

@sffc
Copy link

sffc commented Nov 9, 2022

What happens if you run wasm-opt after wasm-snip? Does that win back the 40kb?

Running wasm-opt -all -Os and wasm-opt -all -Oz:

Method Code Size, wasm-opt -Os Code Size, wasm-opt -Oz
Fresh Compilation 361547 182729
Wasm-Snip 391710 211921

So I get back some of the difference, but there's still a 30 kB diff.

@sffc
Copy link

sffc commented Nov 10, 2022

As discussed in #73958, the root cause seems to be --export-dynamic being passed into wasm-ld.

There are a few directions here:

  1. Stop passing --export-dynamic. It doesn't seem to do anything given that all of the symbols are already being explicitly listed in --export arguments. This solution needs to be paired with another one addressing the export list.
  2. Only pass --export-dynamic and remove the --export arguments. This would solve the whole issue, since users can pass --no-export-dynamic as a link-arg and then any --export arguments that they please.
  3. Add an option -C no-default-exports or -C no-wasm-exports that disables both --export-dynamic and --export. Users can then re-enable exports as link-args.
  4. Option 1, 2, or 3 paired with -C wasm-export-includelist= and -C wasm-export-excludelist= that affect the number of --export arguments.
  5. Option 1, 2, or 3 paired with -C wasm-export-handler= which points to a script that filters the exports

Any of the above could also be generalized to non-wasm linkers if applicable, but I am mostly only aware of what goes on in wasm-ld.

@Manishearth
Copy link
Member Author

Manishearth commented Nov 11, 2022

From talking in Zulip it seems like a productive route forward would be to only implement the allowlist/denylist, ideally in a way that works for all platforms

probably need to start here.

pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
if let Some(ref exports) = tcx.sess.target.override_export_symbols {
return exports.iter().map(ToString::to_string).collect();
}
let mut symbols = Vec::new();
let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| {
if info.level.is_below_threshold(export_threshold) {
symbols.push(symbol_export::symbol_name_for_instance_in_crate(tcx, symbol, cnum));
}
});
symbols
}

and

let exported_symbols = {

@sffc
Copy link

sffc commented Dec 14, 2022

@naricc is hitting this issue as well; see unicode-org/icu4x#2868 (reply in thread)

@bjorn3
Copy link
Member

bjorn3 commented Dec 14, 2022

  1. Stop passing --export-dynamic. It doesn't seem to do anything given that all of the symbols are already being explicitly listed in --export arguments. This solution needs to be paired with another one addressing the export list.

Done by #105405 which will be in rust 1.67.

@Manishearth
Copy link
Member Author

Manishearth commented Dec 19, 2022

@bjorn3 sounds like the --export args are still being passed as normal? so i guess this pares us down to needing something like @sffc's Option 4 for the full solution

@bjorn3
Copy link
Member

bjorn3 commented Dec 19, 2022

Indeed

@sffc
Copy link

sffc commented Jan 10, 2023

I'm currently using a custom linker script as a workaround for this; would really like if this could be entirely controlled from the rustc CLI. We can either do a prettier includelist/excludelist solution (option 4) or a simpler one that removes all exports and relies on link-args to add them back (option 3)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-linkage Area: linking into static, shared libraries and binaries O-wasm Target: WASM (WebAssembly), http://webassembly.org/
Projects
None yet
Development

No branches or pull requests

3 participants