@@ -23,8 +23,8 @@ use back::symbol_export::{self, ExportedSymbols};
23
23
use middle:: dependency_format:: Linkage ;
24
24
use rustc:: hir:: def_id:: { LOCAL_CRATE , CrateNum } ;
25
25
use session:: Session ;
26
- use session:: config:: CrateType ;
27
- use session :: config ;
26
+ use session:: config:: { self , CrateType , OptLevel , DebugInfoLevel } ;
27
+ use serialize :: { json , Encoder } ;
28
28
29
29
/// For all the linkers we support, and information they might
30
30
/// need out of the shared crate context before we get rid of it.
@@ -51,6 +51,12 @@ impl<'a, 'tcx> LinkerInfo {
51
51
sess : sess,
52
52
info : self
53
53
} ) as Box < Linker >
54
+ } else if sess. target . target . options . is_like_emscripten {
55
+ Box :: new ( EmLinker {
56
+ cmd : cmd,
57
+ sess : sess,
58
+ info : self
59
+ } ) as Box < Linker >
54
60
} else {
55
61
Box :: new ( GnuLinker {
56
62
cmd : cmd,
@@ -488,6 +494,155 @@ impl<'a> Linker for MsvcLinker<'a> {
488
494
}
489
495
}
490
496
497
+ pub struct EmLinker < ' a > {
498
+ cmd : & ' a mut Command ,
499
+ sess : & ' a Session ,
500
+ info : & ' a LinkerInfo
501
+ }
502
+
503
+ impl < ' a > Linker for EmLinker < ' a > {
504
+ fn include_path ( & mut self , path : & Path ) {
505
+ self . cmd . arg ( "-L" ) . arg ( path) ;
506
+ }
507
+
508
+ fn link_staticlib ( & mut self , lib : & str ) {
509
+ self . cmd . arg ( "-l" ) . arg ( lib) ;
510
+ }
511
+
512
+ fn output_filename ( & mut self , path : & Path ) {
513
+ self . cmd . arg ( "-o" ) . arg ( path) ;
514
+ }
515
+
516
+ fn add_object ( & mut self , path : & Path ) {
517
+ self . cmd . arg ( path) ;
518
+ }
519
+
520
+ fn link_dylib ( & mut self , lib : & str ) {
521
+ // Emscripten always links statically
522
+ self . link_staticlib ( lib) ;
523
+ }
524
+
525
+ fn link_whole_staticlib ( & mut self , lib : & str , _search_path : & [ PathBuf ] ) {
526
+ // not supported?
527
+ self . link_staticlib ( lib) ;
528
+ }
529
+
530
+ fn link_whole_rlib ( & mut self , lib : & Path ) {
531
+ // not supported?
532
+ self . link_rlib ( lib) ;
533
+ }
534
+
535
+ fn link_rust_dylib ( & mut self , lib : & str , _path : & Path ) {
536
+ self . link_dylib ( lib) ;
537
+ }
538
+
539
+ fn link_rlib ( & mut self , lib : & Path ) {
540
+ self . add_object ( lib) ;
541
+ }
542
+
543
+ fn position_independent_executable ( & mut self ) {
544
+ // noop
545
+ }
546
+
547
+ fn args ( & mut self , args : & [ String ] ) {
548
+ self . cmd . args ( args) ;
549
+ }
550
+
551
+ fn framework_path ( & mut self , _path : & Path ) {
552
+ bug ! ( "frameworks are not supported on Emscripten" )
553
+ }
554
+
555
+ fn link_framework ( & mut self , _framework : & str ) {
556
+ bug ! ( "frameworks are not supported on Emscripten" )
557
+ }
558
+
559
+ fn gc_sections ( & mut self , _keep_metadata : bool ) {
560
+ // noop
561
+ }
562
+
563
+ fn optimize ( & mut self ) {
564
+ // Emscripten performs own optimizations
565
+ self . cmd . arg ( match self . sess . opts . optimize {
566
+ OptLevel :: No => "-O0" ,
567
+ OptLevel :: Less => "-O1" ,
568
+ OptLevel :: Default => "-O2" ,
569
+ OptLevel :: Aggressive => "-O3" ,
570
+ OptLevel :: Size => "-Os" ,
571
+ OptLevel :: SizeMin => "-Oz"
572
+ } ) ;
573
+ }
574
+
575
+ fn debuginfo ( & mut self ) {
576
+ // Preserve names or generate source maps depending
577
+ // on debug info
578
+ self . cmd . arg ( match self . sess . opts . debuginfo {
579
+ DebugInfoLevel :: NoDebugInfo => "-g0" ,
580
+ DebugInfoLevel :: LimitedDebugInfo => "-g3" ,
581
+ DebugInfoLevel :: FullDebugInfo => "-g4"
582
+ } ) ;
583
+ }
584
+
585
+ fn no_default_libraries ( & mut self ) {
586
+ self . cmd . arg ( "-s" ) ;
587
+ self . cmd . arg ( "DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=[]" ) ;
588
+ }
589
+
590
+ fn build_dylib ( & mut self , _out_filename : & Path ) {
591
+ bug ! ( "building dynamic library is unsupported on Emscripten" )
592
+ }
593
+
594
+ fn whole_archives ( & mut self ) {
595
+ // noop
596
+ }
597
+
598
+ fn no_whole_archives ( & mut self ) {
599
+ // noop
600
+ }
601
+
602
+ fn hint_static ( & mut self ) {
603
+ // noop
604
+ }
605
+
606
+ fn hint_dynamic ( & mut self ) {
607
+ // noop
608
+ }
609
+
610
+ fn export_symbols ( & mut self , _tmpdir : & Path , crate_type : CrateType ) {
611
+ let mut arg = OsString :: new ( ) ;
612
+
613
+ let symbols = & self . info . exports [ & crate_type] ;
614
+
615
+ debug ! ( "EXPORTED SYMBOLS:" ) ;
616
+
617
+ self . cmd . arg ( "-s" ) ;
618
+ arg. push ( "EXPORTED_FUNCTIONS=" ) ;
619
+ let mut encoded = String :: new ( ) ;
620
+
621
+ {
622
+ let mut encoder = json:: Encoder :: new ( & mut encoded) ;
623
+ let res = encoder. emit_seq ( symbols. len ( ) , |encoder| {
624
+ for ( i, sym) in symbols. iter ( ) . enumerate ( ) {
625
+ encoder. emit_seq_elt ( i, |encoder| {
626
+ encoder. emit_str ( & ( "_" . to_string ( ) + sym) )
627
+ } ) ?;
628
+ }
629
+ Ok ( ( ) )
630
+ } ) ;
631
+ if let Err ( e) = res {
632
+ self . sess . fatal ( & format ! ( "failed to encode exported symbols: {}" , e) ) ;
633
+ }
634
+ }
635
+ debug ! ( "{}" , encoded) ;
636
+ arg. push ( encoded) ;
637
+
638
+ self . cmd . arg ( arg) ;
639
+ }
640
+
641
+ fn subsystem ( & mut self , _subsystem : & str ) {
642
+ // noop
643
+ }
644
+ }
645
+
491
646
fn exported_symbols ( scx : & SharedCrateContext ,
492
647
exported_symbols : & ExportedSymbols ,
493
648
crate_type : CrateType )
0 commit comments