From 7742b5de7071f059f77a2d963fd910d4056c5f11 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Wed, 27 Jul 2011 23:36:45 +0000 Subject: [PATCH] The -fapple-kext flag was designed to "do the right thing" for building code for use in KEXTs. However, users/Xcode still need to tweak the linker flags to do the right thing, and end up using -Xlinker, for example. Instead, have the driver "do the right thing" when linking when -fapple-kext is present on the command line, and we should have Xcode use -fapple-kext instead of setting other flags like -Xlinker -kext or -nodefaultlibs. rdar://7809940 llvm-svn: 136294 --- clang/include/clang/Driver/Driver.h | 6 +++ clang/lib/Driver/Driver.cpp | 84 +++++++++++++++++++---------- 2 files changed, 62 insertions(+), 28 deletions(-) diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h index 3ad3fb3ff4de..0e5e81a7e2b3 100644 --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -29,6 +29,7 @@ namespace llvm { namespace clang { namespace driver { class Action; + class Arg; class ArgList; class Compilation; class DerivedArgList; @@ -171,6 +172,11 @@ private: /// arguments, after applying the standard argument translations. DerivedArgList *TranslateInputArgs(const InputArgList &Args) const; + // getFinalPhase - Determine which compilation mode we are in and record + // which option we used to determine the final phase. + phases::ID getFinalPhase(const DerivedArgList &DAL, Arg **FinalPhaseArg = 0) + const; + public: Driver(StringRef _ClangExecutable, StringRef _DefaultHostTriple, diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 014b9152c47a..ac5cedf7719e 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -120,6 +120,43 @@ InputArgList *Driver::ParseArgStrings(ArrayRef ArgList) { return Args; } +// Determine which compilation mode we are in. We look for options which +// affect the phase, starting with the earliest phases, and record which +// option we used to determine the final phase. +phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, Arg **FinalPhaseArg) +const { + Arg *PhaseArg = 0; + phases::ID FinalPhase; + + // -{E,M,MM} only run the preprocessor. + if (CCCIsCPP || + (PhaseArg = DAL.getLastArg(options::OPT_E)) || + (PhaseArg = DAL.getLastArg(options::OPT_M, options::OPT_MM))) { + FinalPhase = phases::Preprocess; + + // -{fsyntax-only,-analyze,emit-ast,S} only run up to the compiler. + } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) || + (PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) || + (PhaseArg = DAL.getLastArg(options::OPT__analyze, + options::OPT__analyze_auto)) || + (PhaseArg = DAL.getLastArg(options::OPT_emit_ast)) || + (PhaseArg = DAL.getLastArg(options::OPT_S))) { + FinalPhase = phases::Compile; + + // -c only runs up to the assembler. + } else if ((PhaseArg = DAL.getLastArg(options::OPT_c))) { + FinalPhase = phases::Assemble; + + // Otherwise do everything. + } else + FinalPhase = phases::Link; + + if (FinalPhaseArg) + *FinalPhaseArg = PhaseArg; + + return FinalPhase; +} + DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { DerivedArgList *DAL = new DerivedArgList(Args); @@ -198,6 +235,23 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { } #endif + // If -fapple-kext has been specified, add -kext to linker command if not + // already done so. Also check to make sure we're actually linking. + if (Args.hasArg(options::OPT_fapple_kext) && getFinalPhase(*DAL) == + phases::Link) { + bool add_kext = true; + std::vector LinkerArgs = + Args.getAllArgValues(options::OPT_Xlinker); + for (std::vector::iterator it = LinkerArgs.begin(), + ie = LinkerArgs.end(); it != ie; it++) + if (*it == "-kext") { + add_kext = false; + break; + } + if (add_kext) + DAL->AddSeparateArg(0, Opts->getOption(options::OPT_Xlinker), "-kext"); + } + return DAL; } @@ -818,34 +872,8 @@ void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args, return; } - // Determine which compilation mode we are in. We look for options which - // affect the phase, starting with the earliest phases, and record which - // option we used to determine the final phase. - Arg *FinalPhaseArg = 0; - phases::ID FinalPhase; - - // -{E,M,MM} only run the preprocessor. - if (CCCIsCPP || - (FinalPhaseArg = Args.getLastArg(options::OPT_E)) || - (FinalPhaseArg = Args.getLastArg(options::OPT_M, options::OPT_MM))) { - FinalPhase = phases::Preprocess; - - // -{fsyntax-only,-analyze,emit-ast,S} only run up to the compiler. - } else if ((FinalPhaseArg = Args.getLastArg(options::OPT_fsyntax_only)) || - (FinalPhaseArg = Args.getLastArg(options::OPT_rewrite_objc)) || - (FinalPhaseArg = Args.getLastArg(options::OPT__analyze, - options::OPT__analyze_auto)) || - (FinalPhaseArg = Args.getLastArg(options::OPT_emit_ast)) || - (FinalPhaseArg = Args.getLastArg(options::OPT_S))) { - FinalPhase = phases::Compile; - - // -c only runs up to the assembler. - } else if ((FinalPhaseArg = Args.getLastArg(options::OPT_c))) { - FinalPhase = phases::Assemble; - - // Otherwise do everything. - } else - FinalPhase = phases::Link; + Arg *FinalPhaseArg; + phases::ID FinalPhase = getFinalPhase(Args, &FinalPhaseArg); // Reject -Z* at the top level, these options should never have been exposed // by gcc. -- GitLab