diff --git a/lld/MachO/Driver.h b/lld/MachO/Driver.h --- a/lld/MachO/Driver.h +++ b/lld/MachO/Driver.h @@ -19,6 +19,7 @@ public: MachOOptTable(); llvm::opt::InputArgList parse(ArrayRef argv); + void printHelp(const char *argv0, bool showHidden) const; }; // Create enum with OPT_xxx values for each option in Options.td diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -37,6 +37,7 @@ using namespace llvm; using namespace llvm::MachO; using namespace llvm::sys; +using namespace llvm::opt; using namespace lld; using namespace lld::macho; @@ -74,6 +75,12 @@ return args; } +void MachOOptTable::printHelp(const char *argv0, bool showHidden) const { + PrintHelp(lld::outs(), (std::string(argv0) + " [options] file...").c_str(), + "LLVM Linker", showHidden); + lld::outs() << "\n"; +} + static Optional findLibrary(StringRef name) { std::string stub = (llvm::Twine("lib") + name + ".tbd").str(); std::string shared = (llvm::Twine("lib") + name + ".dylib").str(); @@ -259,15 +266,41 @@ return false; } -static void handlePlatformVersion(opt::ArgList::iterator &it, - const opt::ArgList::iterator &end) { - // -platform_version takes 3 args, which LLVM's option library doesn't - // support directly. So this explicitly handles that. - // FIXME: stash skipped args for later use. - for (int i = 0; i < 3; ++i) { - ++it; - if (it == end || (*it)->getOption().getID() != OPT_INPUT) - fatal("usage: -platform_version platform min_version sdk_version"); +static void handlePlatformVersion(const opt::Arg *arg) { + // TODO: implementation coming very soon ... +} + +static void warnIfDeprecatedOption(const opt::Option &opt) { + if (!opt.getGroup().isValid()) + return; + if (opt.getGroup().getID() == OPT_grp_deprecated) { + warn("Option `" + opt.getPrefixedName() + "' is deprecated in ld64:"); + warn(opt.getHelpText()); + } +} + +static void warnIfUnimplementedOption(const opt::Option &opt) { + if (!opt.getGroup().isValid()) + return; + switch (opt.getGroup().getID()) { + case OPT_grp_deprecated: + // warn about deprecated options elsewhere + break; + case OPT_grp_undocumented: + warn("Option `" + opt.getPrefixedName() + + "' is undocumented. Should lld implement it?"); + break; + case OPT_grp_obsolete: + warn("Option `" + opt.getPrefixedName() + + "' is obsolete. Please modernize your usage."); + break; + case OPT_grp_ignored: + warn("Option `" + opt.getPrefixedName() + "' is ignored."); + break; + default: + warn("Option `" + opt.getPrefixedName() + + "' is not yet implemented. Stay tuned..."); + break; } } @@ -282,6 +315,14 @@ MachOOptTable parser; opt::InputArgList args = parser.parse(argsArr.slice(1)); + if (args.hasArg(OPT_help_hidden)) { + parser.printHelp(argsArr[0], /*showHidden=*/true); + return true; + } else if (args.hasArg(OPT_help)) { + parser.printHelp(argsArr[0], /*showHidden=*/false); + return true; + } + config = make(); symtab = make(); target = createTargetInfo(args); @@ -302,9 +343,9 @@ return !errorCount(); } - for (opt::ArgList::iterator it = args.begin(), end = args.end(); it != end; - ++it) { - const opt::Arg *arg = *it; + for (const auto &arg : args) { + const auto &opt = arg->getOption(); + warnIfDeprecatedOption(opt); switch (arg->getOption().getID()) { case OPT_INPUT: addFile(arg->getValue()); @@ -318,10 +359,20 @@ error("library not found for -l" + name); break; } - case OPT_platform_version: { - handlePlatformVersion(it, end); // Can advance "it". + case OPT_platform_version: + handlePlatformVersion(arg); + break; + case OPT_o: + case OPT_dylib: + case OPT_e: + case OPT_L: + case OPT_Z: + case OPT_arch: + // handled elsewhere + break; + default: + warnIfUnimplementedOption(opt); break; - } } } diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td --- a/lld/MachO/Options.td +++ b/lld/MachO/Options.td @@ -1,43 +1,1297 @@ include "llvm/Option/OptParser.td" -def L: JoinedOrSeparate<["-"], "L">, MetaVarName<"">, - HelpText<"Add directory to library search path">; +def help : Flag<["-", "--"], "help">; +def help_hidden : Flag<["--"], "help-hidden">, + HelpText<"Display help for hidden options">; -def Z: Flag<["-"], "Z">, - HelpText<"Do not add standard directories to library search path">; +// This is a complete Options.td compiled from Apple's ld(1) manpage +// dated 2018-03-07 and cross checked with ld64 source code in repo +// https://github.com/apple-opensource/ld64 at git tag "512.4" dated +// 2018-03-18. -def arch: Separate<["-"], "arch">, MetaVarName<"">, - HelpText<"Architecture to link">; +// Flags<[HelpHidden]> marks options that are not yet ported to lld, +// and serve as a scoreboard for annotating our progress toward +// implementing ld64 options in lld. As you add implementions to +// Driver.cpp, please remove the hidden flag here. -def dylib: Flag<["-"], "dylib">, HelpText<"Emit a shared library">; +def grp_kind : OptionGroup<"kind">, HelpText<"OUTPUT KIND">; -def e: Separate<["-"], "e">, HelpText<"Name of entry point symbol">; +def execute : Flag<["-"], "execute">, + HelpText<"Produce a main executable (default)">, + Flags<[HelpHidden]>, + Group; +def dylib : Flag<["-"], "dylib">, + HelpText<"Produce a shared library">, + Group; +def bundle : Flag<["-"], "bundle">, + HelpText<"Produce a bundle">, + Flags<[HelpHidden]>, + Group; +def r : Flag<["-"], "r">, + HelpText<"Merge multiple object files into one, retaining relocations">, + Flags<[HelpHidden]>, + Group; +def dylinker : Flag<["-"], "dylinker">, + HelpText<"Produce a dylinker only used when building dyld">, + Flags<[HelpHidden]>, + Group; +def dynamic : Flag<["-"], "dynamic">, + HelpText<"Link dynamically (default)">, + Flags<[HelpHidden]>, + Group; +def static : Flag<["-"], "static">, + HelpText<"Link statically">, + Flags<[HelpHidden]>, + Group; +def preload : Flag<["-"], "preload">, + HelpText<"Produce an unsegmented binary for embedded systems">, + Flags<[HelpHidden]>, + Group; +def arch : Separate<["-"], "arch">, + MetaVarName<"">, + HelpText<"The architecture (e.g. ppc, ppc64, i386, x86_64)">, + Group; +def o : Separate<["-"], "o">, + MetaVarName<"">, + HelpText<"The name of the output file (default: `a.out')">, + Group; -def install_name: Separate<["-"], "install_name">, - MetaVarName<"">, - HelpText<"Set the install path of the dynamic library.">; +def grp_libs : OptionGroup<"libs">, HelpText<"LIBRARIES">; -def l: Joined<["-"], "l">, MetaVarName<"">, - HelpText<"Base name of library searched for in -L directories">; +def l : Joined<["-"], "l">, + MetaVarName<"">, + HelpText<"Search for lib.dylib or lib.a on the library search path">, + Group; +def weak_l : Joined<["-"], "weak-l">, + MetaVarName<"">, + HelpText<"Like -l, but mark library and its references as weak imports">, + Flags<[HelpHidden]>, + Group; +def weak_library : Separate<["-"], "weak_library">, + MetaVarName<"">, + HelpText<"Like bare , but mark library and its references as weak imports">, + Flags<[HelpHidden]>, + Group; +def reexport_l : Joined<["-"], "reexport-l">, + MetaVarName<"">, + HelpText<"Like -l, but export all symbols of from newly created library">, + Flags<[HelpHidden]>, + Group; +def reexport_library : Separate<["-"], "reexport_library">, + MetaVarName<"">, + HelpText<"Like bare , but export all symbols of from newly created library">, + Flags<[HelpHidden]>, + Group; +def upward_l : Joined<["-"], "upward-l">, + MetaVarName<"">, + HelpText<"Like -l, but specify dylib as an upward dependency">, + Flags<[HelpHidden]>, + Group; +def upward_library : Separate<["-"], "upward_library">, + MetaVarName<"">, + HelpText<"Like bare , but specify dylib as an upward dependency">, + Flags<[HelpHidden]>, + Group; +def L : JoinedOrSeparate<["-"], "L">, + MetaVarName<"">, + HelpText<"Add dir to the library search path">, + Group; +def Z : Flag<["-"], "Z">, + HelpText<"Remove standard directories from the library and framework search paths">, + Group; +def syslibroot : Separate<["-"], "syslibroot">, + MetaVarName<"">, + HelpText<"Prepend to all library and framework search paths">, + Flags<[HelpHidden]>, + Group; +def search_paths_first : Flag<["-"], "search_paths_first">, + HelpText<"Search for lib.dylib and lib.a at each step in traversing search path (default for Xcode 4 and later)">, + Flags<[HelpHidden]>, + Group; +def search_dylibs_first : Flag<["-"], "search_dylibs_first">, + HelpText<"Search for lib.dylib on first pass, then for lib.a on second pass through search path (default for Xcode 3 and earlier)">, + Flags<[HelpHidden]>, + Group; +def framework : Separate<["-"], "framework">, + MetaVarName<"">, + HelpText<"Search for .framework/ on the framework search path">, + Flags<[HelpHidden]>, + Group; +def weak_framework : Separate<["-"], "weak_framework">, + MetaVarName<"">, + HelpText<"Like -framework , but mark framework and its references as weak imports">, + Flags<[HelpHidden]>, + Group; +def reexport_framework : Separate<["-"], "reexport_framework">, + MetaVarName<"">, + HelpText<"Like -framework , but export all symbols of from the newly created library">, + Flags<[HelpHidden]>, + Group; +def upward_framework : Separate<["-"], "upward_framework">, + MetaVarName<"">, + HelpText<"Like -framework , but specify the framework as an upward dependency">, + Flags<[HelpHidden]>, + Group; +def F : JoinedOrSeparate<["-"], "F">, + MetaVarName<"">, + HelpText<"Add dir to the framework search path">, + Flags<[HelpHidden]>, + Group; +def all_load : Flag<["-"], "all_load">, + HelpText<"Load all members of all static archive libraries">, + Flags<[HelpHidden]>, + Group; +def ObjC : Flag<["-"], "ObjC">, + HelpText<"Load all members of static archives that are an Objective-C class or category.">, + Flags<[HelpHidden]>, + Group; +def force_load : Separate<["-"], "force_load">, + MetaVarName<"">, + HelpText<"Load all members static archive library at ">, + Flags<[HelpHidden]>, + Group; -def o: Separate<["-"], "o">, MetaVarName<"">, - HelpText<"Path to file to write output">; +def grp_content : OptionGroup<"content">, HelpText<"ADDITIONAL CONTENT">; -def order_file: Separate<["-"], "order_file">, - HelpText<"Lay out symbols within each section in the order specified by the " - "order file">; +def sectcreate : MultiArg<["-"], "sectcreate", 3>, + MetaVarName<"
">, + HelpText<"Create
in from the contents of ">, + Flags<[HelpHidden]>, + Group; +def segcreate : MultiArg<["-"], "segcreate", 3>, + MetaVarName<"
">, + Alias, + HelpText<"Alias for -sectcreate">, + Flags<[HelpHidden]>, + Group; +def filelist : Separate<["-"], "filelist">, + MetaVarName<"">, + HelpText<"Read names of files to link from ">, + Flags<[HelpHidden]>, + Group; +def dtrace : Separate<["-"], "dtrace">, + MetaVarName<"