diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -2024,7 +2024,8 @@ // Lipo if necessary, we do it this way because we need to set the arch flag // so that -Xarch_ gets overwritten. - if (Inputs.size() == 1 || Act->getType() == types::TY_Nothing) + bool LipoNeeded = Inputs.size() != 1 && Act->getType() != types::TY_Nothing; + if (!LipoNeeded) Actions.append(Inputs.begin(), Inputs.end()); else Actions.push_back(C.MakeAction(Inputs, Act->getType())); @@ -2034,16 +2035,17 @@ bool enablesDebugInfo = A && !A->getOption().matches(options::OPT_g0) && !A->getOption().matches(options::OPT_gstabs); bool isGeneratingTemporaryObject = - ContainsCompileOrAssembleAction(Actions.back()) || isUsingLTO(); + ContainsCompileOrAssembleAction(Actions.back()) || isUsingLTO() || + LipoNeeded; if ((enablesDebugInfo || willEmitRemarks(Args)) && isGeneratingTemporaryObject) { // Add a 'dsymutil' step if necessary, when debug info is enabled and we // are linking a temporary object. This occurs when we have a compiler - // or assmbler input or if LTO is enabled. We need to run 'dsymutil' - // ourselves in such cases because the debug info will refer to the - // temporary object file which will be removed at the end of the - // compilation process. + // or assembler input, if LTO is enabled, or if we're building multiple + // architectures. We need to run 'dsymutil' ourselves in such cases + // because the debug info will refer to the temporary object file which + // will be removed at the end of the compilation process. if (Act->getType() == types::TY_Image) { ActionList Inputs; Inputs.push_back(Actions.back()); diff --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h --- a/clang/lib/Driver/ToolChains/Darwin.h +++ b/clang/lib/Driver/ToolChains/Darwin.h @@ -59,10 +59,10 @@ }; class LLVM_LIBRARY_VISIBILITY Linker : public MachOTool { - bool NeedsTempPath(const InputInfoList &Inputs, + bool NeedsTempPath(const InputInfo &Outputs, const InputInfoList &Inputs, const llvm::opt::ArgList &Args) const; void AddLinkArgs(Compilation &C, const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs, + llvm::opt::ArgStringList &CmdArgs, const InputInfo &Outputs, const InputInfoList &Inputs, unsigned Version[5]) const; public: diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -167,7 +167,8 @@ CmdArgs.push_back("-force_cpusubtype_ALL"); } -bool darwin::Linker::NeedsTempPath(const InputInfoList &Inputs, +bool darwin::Linker::NeedsTempPath(const InputInfo &Output, + const InputInfoList &Inputs, const ArgList &Args) const { Arg *A = Args.getLastArg(options::OPT_g_Group); if (A && !A->getOption().matches(options::OPT_g0) && @@ -181,6 +182,11 @@ if (Input.getType() != types::TY_Object) return true; + // If we're going to use lipo (i.e. the linker output is a temporary file too) + // then we'll need to run dsymutil after linking too + if (Inputs.size() != 1 && Output.getType() != types::TY_Nothing) + return true; + return false; } @@ -209,6 +215,7 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args, ArgStringList &CmdArgs, + const InputInfo &Output, const InputInfoList &Inputs, unsigned Version[5]) const { const Driver &D = getToolChain().getDriver(); @@ -228,7 +235,8 @@ options::OPT_fno_application_extension, false)) CmdArgs.push_back("-application_extension"); - if (D.isUsingLTO() && Version[0] >= 116 && NeedsTempPath(Inputs, Args)) { + if (D.isUsingLTO() && Version[0] >= 116 && + NeedsTempPath(Output, Inputs, Args)) { std::string TmpPathName; if (D.getLTOMode() == LTOK_Full) { // If we are using full LTO, then automatically create a temporary file @@ -541,7 +549,7 @@ // I'm not sure why this particular decomposition exists in gcc, but // we follow suite for ease of comparison. - AddLinkArgs(C, Args, CmdArgs, Inputs, Version); + AddLinkArgs(C, Args, CmdArgs, Output, Inputs, Version); if (willEmitRemarks(Args) && checkRemarksOptions(getToolChain().getDriver(), Args, diff --git a/clang/test/Driver/darwin-dsymutil.c b/clang/test/Driver/darwin-dsymutil.c --- a/clang/test/Driver/darwin-dsymutil.c +++ b/clang/test/Driver/darwin-dsymutil.c @@ -61,3 +61,14 @@ // CHECK-DSYMUTIL-LTO: "/usr/bin/ld" "-demangle" "-object_path_lto" // CHECK-DSYMUTIL-LTO: "/usr/bin/dsymutil" "-o" "a.out.dSYM" "a.out" + +// Check that clang provides the linker with a temporary object file path and +// runs dsymutil when building for multiple architectures. +// RUN: touch %t.o +// RUN: %clang -target x86_64-apple-darwin10 -arch x86_64 -arch arm64 %t.o -g \ +// RUN: -flto -### 2> %t +// RUN: FileCheck -check-prefix=CHECK-DSYMUTIL-MULTIARCH < %t %s + +// CHECK-DSYMUTIL-MULTIARCH: "/usr/bin/ld" "-demangle" "-object_path_lto" +// CHECK-DSYMUTIL-MULTIARCH: "/usr/bin/ld" "-demangle" "-object_path_lto" +// CHECK-DSYMUTIL-MULTIARCH: "/usr/bin/dsymutil" "-o" "a.out.dSYM" "a.out"