Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -31,6 +31,7 @@ bool ExportDynamic; bool NoInhibitExec; bool Shared; + bool Static = false; }; extern Configuration *Config; Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -69,7 +69,8 @@ if (Path[0] == ':') { Names.push_back(Path.drop_front().str()); } else { - Names.push_back((Twine("lib") + Path + ".so").str()); + if (!Config->Static) + Names.push_back((Twine("lib") + Path + ".so").str()); Names.push_back((Twine("lib") + Path + ".a").str()); } for (StringRef Dir : Config->InputSearchPaths) { @@ -88,6 +89,17 @@ return identify_magic(MB.getBuffer()) == file_magic::unknown; } +// Runs the linker script or adds the file to the symbol table +// depending on its type. +static void addInputFile(SymbolTable *Symtab, StringRef Path) { + MemoryBufferRef MB = openFile(Path); + if (isLinkerScript(MB)) + // readLinkerScript may add files to the symbol table. + readLinkerScript(Symtab, MB); + else + Symtab->addFile(createFile(MB)); +} + void LinkerDriver::link(ArrayRef ArgsArr) { // Parse command line options. opt::InputArgList Args = Parser.parse(ArgsArr); @@ -124,17 +136,23 @@ // Create a symbol table. SymbolTable Symtab; - for (auto *Arg : Args.filtered(OPT_l, OPT_INPUT)) { - std::string Path = Arg->getValue(); - if (Arg->getOption().getID() == OPT_l) - Path = searchLibrary(Path); - MemoryBufferRef MB = openFile(Path); - if (isLinkerScript(MB)) { - // readLinkerScript may add files to the symbol table. - readLinkerScript(&Symtab, MB); + for (auto *Arg : Args) { + switch (Arg->getOption().getID()) { + case OPT_l: + addInputFile(&Symtab, searchLibrary(Arg->getValue())); + break; + case OPT_INPUT: + addInputFile(&Symtab, Arg->getValue()); + break; + case OPT_Bstatic: + Config->Static = true; + break; + case OPT_Bdynamic: + Config->Static = false; + break; + default: continue; } - Symtab.addFile(createFile(MB)); } if (Symtab.getObjectFiles().empty()) Index: ELF/Options.td =================================================================== --- ELF/Options.td +++ ELF/Options.td @@ -39,6 +39,12 @@ def shared : Flag<["-"], "shared">, HelpText<"Build a shared object">; +def Bdynamic: Flag<["-"], "Bdynamic">, + HelpText<"Link against shared libraries">; + +def Bstatic: Flag<["-"], "Bstatic">, + HelpText<"Do not link against shared libraries">; + def sysroot : Joined<["--"], "sysroot=">, HelpText<"Set the system root">; @@ -48,6 +54,11 @@ def alias_discard_locals: Flag<["-"], "X">, Alias; def alias_entry : Separate<["-"], "e">, Alias; def alias_l : Joined<["--"], "library=">, Alias; +def alias_Bdynamic_dy: Flag<["-"], "dy">, Alias; +def alias_Bdynamic_call_shared: Flag<["-"], "call_shared">, Alias; +def alias_Bstatic_dn: Flag<["-"], "dn">, Alias; +def alias_Bstatic_non_shared: Flag<["-"], "non_shared">, Alias; +def alias_Bstatic_static: Flag<["-"], "static">, Alias; // Options listed below are silently ignored now. def as_needed : Flag<["--"], "as-needed">; Index: test/elf2/libsearch.s =================================================================== --- test/elf2/libsearch.s +++ test/elf2/libsearch.s @@ -4,6 +4,7 @@ // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ // RUN: %p/Inputs/libsearch-st.s -o %tst.o // RUN: lld -flavor gnu2 -shared %tdyn.o -o %T/libls.so +// RUN: cp -f %T/libls.so %T/libls2.so // RUN: rm -f %T/libls.a // RUN: llvm-ar rcs %T/libls.a %tst.o // REQUIRES: x86 @@ -42,5 +43,34 @@ // Check long forms as well // RUN: lld -flavor gnu2 -o %t3 %t.o --library-path=%T --library=ls +// Should not search for dynamic libraries if -Bstatic is specified +// RUN: lld -flavor gnu2 -o %t3 %t.o -L%T -Bstatic -lls +// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=STATIC %s +// RUN: not lld -flavor gnu2 -o %t3 %t.o -L%T -Bstatic -lls2 2>&1 \ +// RUN: | FileCheck --check-prefix=NOLIB2 %s +// NOLIB2: Unable to find library -lls2 + +// -Bdynamic should restore default behaviour +// RUN: lld -flavor gnu2 -o %t3 %t.o -L%T -Bstatic -Bdynamic -lls +// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=DYNAMIC %s + +// -Bstatic and -Bdynamic should affect only libraries which follow them +// RUN: lld -flavor gnu2 -o %t3 %t.o -L%T -lls -Bstatic -Bdynamic +// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=DYNAMIC %s +// RUN: lld -flavor gnu2 -o %t3 %t.o -L%T -Bstatic -lls -Bdynamic +// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=STATIC %s + +// Check aliases as well +// RUN: lld -flavor gnu2 -o %t3 %t.o -L%T -dn -lls +// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=STATIC %s +// RUN: lld -flavor gnu2 -o %t3 %t.o -L%T -non_shared -lls +// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=STATIC %s +// RUN: lld -flavor gnu2 -o %t3 %t.o -L%T -static -lls +// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=STATIC %s +// RUN: lld -flavor gnu2 -o %t3 %t.o -L%T -Bstatic -dy -lls +// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=DYNAMIC %s +// RUN: lld -flavor gnu2 -o %t3 %t.o -L%T -Bstatic -call_shared -lls +// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=DYNAMIC %s + .globl _start,_bar; _start: