Skip to content

Commit dce445b

Browse files
committed
[Clang][Driver] Revise Cygwin ToolChain to call linker directly
...so that libc++, compiler-rt, and libunwind can be used by the options: -stdlib=libc++, -rtlib=compiler-rt, and -unwindlib=libunwind respectively. Along with this change, the test for this driver is also trimmed a bit. This is a follow-up patch to the commit 52924a2. Signed-off-by: Takashi Yano <[email protected]>
1 parent 7bbb65c commit dce445b

File tree

9 files changed

+330
-12
lines changed

9 files changed

+330
-12
lines changed

clang/lib/Driver/ToolChain.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,8 @@ static StringRef getArchNameForCompilerRTLib(const ToolChain &TC,
684684
StringRef ToolChain::getOSLibName() const {
685685
if (Triple.isOSDarwin())
686686
return "darwin";
687+
if (Triple.isWindowsCygwinEnvironment())
688+
return "cygwin";
687689

688690
switch (Triple.getOS()) {
689691
case llvm::Triple::FreeBSD:

clang/lib/Driver/ToolChains/Cygwin.cpp

Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "Cygwin.h"
1010
#include "clang/Config/config.h"
1111
#include "clang/Driver/CommonArgs.h"
12+
#include "clang/Driver/Compilation.h"
1213
#include "clang/Driver/Driver.h"
1314
#include "clang/Driver/Options.h"
1415
#include "llvm/Support/Path.h"
@@ -30,6 +31,8 @@ Cygwin::Cygwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
3031
Generic_GCC::PushPPaths(PPaths);
3132

3233
path_list &Paths = getFilePaths();
34+
if (GCCInstallation.isValid())
35+
Paths.push_back(GCCInstallation.getInstallPath().str());
3336

3437
Generic_GCC::AddMultiarchPaths(D, SysRoot, "lib", Paths);
3538

@@ -107,3 +110,263 @@ void Cygwin::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
107110
addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
108111
addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include/w32api");
109112
}
113+
114+
void cygwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
115+
const InputInfo &Output,
116+
const InputInfoList &Inputs,
117+
const ArgList &Args,
118+
const char *LinkingOutput) const {
119+
const auto &ToolChain = getToolChain();
120+
const Driver &D = ToolChain.getDriver();
121+
122+
const bool IsStatic = Args.hasArg(options::OPT_static);
123+
124+
ArgStringList CmdArgs;
125+
126+
// Silence warning for "clang -g foo.o -o foo"
127+
Args.ClaimAllArgs(options::OPT_g_Group);
128+
// and "clang -emit-llvm foo.o -o foo"
129+
Args.ClaimAllArgs(options::OPT_emit_llvm);
130+
// and for "clang -w foo.o -o foo". Other warning options are already
131+
// handled somewhere else.
132+
Args.ClaimAllArgs(options::OPT_w);
133+
134+
if (!D.SysRoot.empty())
135+
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
136+
137+
if (Args.hasArg(options::OPT_s))
138+
CmdArgs.push_back("-s");
139+
140+
CmdArgs.push_back("-m");
141+
switch (ToolChain.getArch()) {
142+
case llvm::Triple::x86:
143+
CmdArgs.push_back("i386pe");
144+
break;
145+
case llvm::Triple::x86_64:
146+
CmdArgs.push_back("i386pep");
147+
break;
148+
case llvm::Triple::arm:
149+
case llvm::Triple::thumb:
150+
// FIXME: this is incorrect for WinCE
151+
CmdArgs.push_back("thumb2pe");
152+
break;
153+
case llvm::Triple::aarch64:
154+
if (Args.hasArg(options::OPT_marm64x))
155+
CmdArgs.push_back("arm64xpe");
156+
else if (ToolChain.getEffectiveTriple().isWindowsArm64EC())
157+
CmdArgs.push_back("arm64ecpe");
158+
else
159+
CmdArgs.push_back("arm64pe");
160+
break;
161+
case llvm::Triple::mipsel:
162+
CmdArgs.push_back("mipspe");
163+
break;
164+
default:
165+
D.Diag(diag::err_target_unknown_triple)
166+
<< ToolChain.getEffectiveTriple().str();
167+
}
168+
169+
Arg *SubsysArg =
170+
Args.getLastArg(options::OPT_mwindows, options::OPT_mconsole);
171+
if (SubsysArg && SubsysArg->getOption().matches(options::OPT_mwindows)) {
172+
CmdArgs.push_back("--subsystem");
173+
CmdArgs.push_back("windows");
174+
} else if (SubsysArg &&
175+
SubsysArg->getOption().matches(options::OPT_mconsole)) {
176+
CmdArgs.push_back("--subsystem");
177+
CmdArgs.push_back("console");
178+
}
179+
180+
CmdArgs.push_back("--wrap=_Znwm");
181+
CmdArgs.push_back("--wrap=_Znam");
182+
CmdArgs.push_back("--wrap=_ZdlPv");
183+
CmdArgs.push_back("--wrap=_ZdaPv");
184+
CmdArgs.push_back("--wrap=_ZnwmRKSt9nothrow_t");
185+
CmdArgs.push_back("--wrap=_ZnamRKSt9nothrow_t");
186+
CmdArgs.push_back("--wrap=_ZdlPvRKSt9nothrow_t");
187+
CmdArgs.push_back("--wrap=_ZdaPvRKSt9nothrow_t");
188+
189+
if (Args.hasArg(options::OPT_mdll))
190+
CmdArgs.push_back("--dll");
191+
else if (Args.hasArg(options::OPT_shared))
192+
CmdArgs.push_back("--shared");
193+
if (Args.hasArg(options::OPT_static))
194+
CmdArgs.push_back("-Bstatic");
195+
else
196+
CmdArgs.push_back("-Bdynamic");
197+
198+
CmdArgs.push_back("--dll-search-prefix=cyg");
199+
200+
CmdArgs.push_back("-o");
201+
CmdArgs.push_back(Output.getFilename());
202+
203+
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
204+
options::OPT_r)) {
205+
const bool IsShared = Args.hasArg(options::OPT_shared);
206+
if (Args.hasArg(options::OPT_mdll) || IsShared) {
207+
CmdArgs.push_back("-e");
208+
CmdArgs.push_back(ToolChain.getArch() == llvm::Triple::x86
209+
? "__cygwin_dll_entry@12"
210+
: "_cygwin_dll_entry");
211+
CmdArgs.push_back("--enable-auto-image-base");
212+
}
213+
214+
if (!Args.hasArg(options::OPT_mdll) && !IsShared)
215+
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
216+
if (ToolChain.GetRuntimeLibType(Args) == ToolChain::RLT_CompilerRT) {
217+
std::string crtbegin =
218+
ToolChain.getCompilerRT(Args, "crtbegin", ToolChain::FT_Object);
219+
if (ToolChain.getVFS().exists(crtbegin)) {
220+
std::string P;
221+
P = crtbegin;
222+
CmdArgs.push_back(Args.MakeArgString(P));
223+
}
224+
}
225+
if (IsShared)
226+
CmdArgs.push_back(
227+
Args.MakeArgString(ToolChain.GetFilePath("crtbeginS.o")));
228+
else
229+
CmdArgs.push_back(
230+
Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o")));
231+
232+
// Add crtfastmath.o if available and fast math is enabled.
233+
ToolChain.addFastMathRuntimeIfAvailable(Args, CmdArgs);
234+
}
235+
236+
Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u});
237+
238+
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
239+
240+
if (D.isUsingLTO())
241+
tools::addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs,
242+
D.getLTOMode() == LTOK_Thin);
243+
244+
if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
245+
CmdArgs.push_back("--no-demangle");
246+
247+
bool NeedsSanitizerDeps =
248+
tools::addSanitizerRuntimes(ToolChain, Args, CmdArgs);
249+
bool NeedsXRayDeps = tools::addXRayRuntime(ToolChain, Args, CmdArgs);
250+
tools::addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs);
251+
tools::AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
252+
253+
bool saw_high_entropy_va = false;
254+
for (const char *Arg : CmdArgs)
255+
if (StringRef(Arg) == "--high-entropy-va" ||
256+
StringRef(Arg) == "--disable-high-entropy-va")
257+
saw_high_entropy_va = true;
258+
if (!saw_high_entropy_va)
259+
CmdArgs.push_back("--disable-high-entropy-va");
260+
261+
tools::addHIPRuntimeLibArgs(ToolChain, C, Args, CmdArgs);
262+
263+
// The profile runtime also needs access to system libraries.
264+
getToolChain().addProfileRTLibs(Args, CmdArgs);
265+
266+
if (D.CCCIsCXX() &&
267+
!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
268+
options::OPT_r)) {
269+
if (ToolChain.ShouldLinkCXXStdlib(Args)) {
270+
bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
271+
!Args.hasArg(options::OPT_static);
272+
if (OnlyLibstdcxxStatic)
273+
CmdArgs.push_back("-Bstatic");
274+
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
275+
if (OnlyLibstdcxxStatic)
276+
CmdArgs.push_back("-Bdynamic");
277+
}
278+
CmdArgs.push_back("-lm");
279+
}
280+
281+
// Silence warnings when linking C code with a C++ '-stdlib' argument.
282+
Args.ClaimAllArgs(options::OPT_stdlib_EQ);
283+
284+
// Additional linker set-up and flags for Fortran. This is required in order
285+
// to generate executables. As Fortran runtime depends on the C runtime,
286+
// these dependencies need to be listed before the C runtime below (i.e.
287+
// AddRunTimeLibs).
288+
if (D.IsFlangMode() &&
289+
!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
290+
ToolChain.addFortranRuntimeLibraryPath(Args, CmdArgs);
291+
ToolChain.addFortranRuntimeLibs(Args, CmdArgs);
292+
CmdArgs.push_back("-lm");
293+
}
294+
295+
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_r)) {
296+
if (!Args.hasArg(options::OPT_nodefaultlibs)) {
297+
if (IsStatic)
298+
CmdArgs.push_back("--start-group");
299+
300+
if (NeedsSanitizerDeps)
301+
tools::linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs);
302+
303+
if (NeedsXRayDeps)
304+
tools::linkXRayRuntimeDeps(ToolChain, Args, CmdArgs);
305+
306+
bool WantPthread = Args.hasArg(options::OPT_pthread) ||
307+
Args.hasArg(options::OPT_pthreads);
308+
309+
// Use the static OpenMP runtime with -static-openmp
310+
bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) &&
311+
!Args.hasArg(options::OPT_static);
312+
313+
// FIXME: Only pass GompNeedsRT = true for platforms with libgomp that
314+
// require librt. Most modern Linux platforms do, but some may not.
315+
if (tools::addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP,
316+
JA.isHostOffloading(Action::OFK_OpenMP),
317+
/* GompNeedsRT= */ true))
318+
// OpenMP runtimes implies pthreads when using the GNU toolchain.
319+
// FIXME: Does this really make sense for all GNU toolchains?
320+
WantPthread = true;
321+
322+
tools::AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
323+
324+
if (WantPthread)
325+
CmdArgs.push_back("-lpthread");
326+
327+
if (Args.hasArg(options::OPT_fsplit_stack))
328+
CmdArgs.push_back("--wrap=pthread_create");
329+
330+
if (!Args.hasArg(options::OPT_nolibc))
331+
CmdArgs.push_back("-lc");
332+
333+
// Cygwin specific
334+
CmdArgs.push_back("-lcygwin");
335+
if (Args.hasArg(options::OPT_mwindows)) {
336+
CmdArgs.push_back("-lgdi32");
337+
CmdArgs.push_back("-lcomdlg32");
338+
}
339+
CmdArgs.push_back("-ladvapi32");
340+
CmdArgs.push_back("-lshell32");
341+
CmdArgs.push_back("-luser32");
342+
CmdArgs.push_back("-lkernel32");
343+
344+
if (IsStatic)
345+
CmdArgs.push_back("--end-group");
346+
else
347+
tools::AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
348+
}
349+
350+
if (!Args.hasArg(options::OPT_nostartfiles)) {
351+
if (ToolChain.GetRuntimeLibType(Args) == ToolChain::RLT_CompilerRT) {
352+
std::string crtend =
353+
ToolChain.getCompilerRT(Args, "crtend", ToolChain::FT_Object);
354+
if (ToolChain.getVFS().exists(crtend)) {
355+
std::string P;
356+
P = crtend;
357+
CmdArgs.push_back(Args.MakeArgString(P));
358+
}
359+
}
360+
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
361+
}
362+
}
363+
364+
Args.addAllArgs(CmdArgs, {options::OPT_T, options::OPT_t});
365+
366+
const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
367+
C.addCommand(std::make_unique<Command>(JA, *this,
368+
ResponseFileSupport::AtFileCurCP(),
369+
Exec, CmdArgs, Inputs, Output));
370+
}
371+
372+
auto Cygwin::buildLinker() const -> Tool * { return new cygwin::Linker(*this); }

clang/lib/Driver/ToolChains/Cygwin.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,25 @@ class LLVM_LIBRARY_VISIBILITY Cygwin : public Generic_GCC {
2727
void
2828
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
2929
llvm::opt::ArgStringList &CC1Args) const override;
30+
31+
protected:
32+
Tool *buildLinker() const override;
33+
};
34+
35+
namespace cygwin {
36+
class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
37+
public:
38+
Linker(const ToolChain &TC) : Tool("cygwin::Linker", "linker", TC) {}
39+
40+
bool hasIntegratedCPP() const override { return false; }
41+
bool isLinkJob() const override { return true; }
42+
43+
void ConstructJob(Compilation &C, const JobAction &JA,
44+
const InputInfo &Output, const InputInfoList &Inputs,
45+
const llvm::opt::ArgList &TCArgs,
46+
const char *LinkingOutput) const override;
3047
};
48+
} // end namespace cygwin
3149

3250
} // end namespace toolchains
3351
} // end namespace driver

clang/test/Driver/Inputs/basic_cross_cygwin_tree/usr/lib/gcc/i686-pc-msys/10/crtend.o

Whitespace-only changes.

clang/test/Driver/Inputs/basic_cross_cygwin_tree/usr/lib/gcc/x86_64-pc-cygwin/10/crtend.o

Whitespace-only changes.

clang/test/Driver/Inputs/basic_cygwin_tree/usr/lib/crt0.o

Whitespace-only changes.

clang/test/Driver/Inputs/basic_cygwin_tree/usr/lib/gcc/i686-pc-cygwin/10/crtend.o

Whitespace-only changes.

clang/test/Driver/Inputs/basic_cygwin_tree/usr/lib/gcc/x86_64-pc-msys/10/crtend.o

Whitespace-only changes.

0 commit comments

Comments
 (0)