9
9
#include " Cygwin.h"
10
10
#include " clang/Config/config.h"
11
11
#include " clang/Driver/CommonArgs.h"
12
+ #include " clang/Driver/Compilation.h"
12
13
#include " clang/Driver/Driver.h"
13
14
#include " clang/Driver/Options.h"
14
15
#include " llvm/Support/Path.h"
@@ -30,6 +31,8 @@ Cygwin::Cygwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
30
31
Generic_GCC::PushPPaths (PPaths);
31
32
32
33
path_list &Paths = getFilePaths ();
34
+ if (GCCInstallation.isValid ())
35
+ Paths.push_back (GCCInstallation.getInstallPath ().str ());
33
36
34
37
Generic_GCC::AddMultiarchPaths (D, SysRoot, " lib" , Paths);
35
38
@@ -107,3 +110,272 @@ void Cygwin::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
107
110
addExternCSystemInclude (DriverArgs, CC1Args, SysRoot + " /usr/include" );
108
111
addExternCSystemInclude (DriverArgs, CC1Args, SysRoot + " /usr/include/w32api" );
109
112
}
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
+ const char *OutputFile = Output.getFilename ();
202
+ // GCC implicitly adds an .exe extension if it is given an output file name
203
+ // that lacks an extension.
204
+ // GCC used to do this only when the compiler itself runs on windows, but
205
+ // since GCC 8 it does the same when cross compiling as well.
206
+ if (!llvm::sys::path::has_extension (OutputFile)) {
207
+ CmdArgs.push_back (Args.MakeArgString (Twine (OutputFile) + " .exe" ));
208
+ OutputFile = CmdArgs.back ();
209
+ } else
210
+ CmdArgs.push_back (OutputFile);
211
+
212
+ if (!Args.hasArg (options::OPT_nostdlib, options::OPT_nostartfiles,
213
+ options::OPT_r)) {
214
+ const bool IsShared = Args.hasArg (options::OPT_shared);
215
+ if (Args.hasArg (options::OPT_mdll) || IsShared) {
216
+ CmdArgs.push_back (" -e" );
217
+ CmdArgs.push_back (ToolChain.getArch () == llvm::Triple::x86
218
+ ? " __cygwin_dll_entry@12"
219
+ : " _cygwin_dll_entry" );
220
+ CmdArgs.push_back (" --enable-auto-image-base" );
221
+ }
222
+
223
+ if (!Args.hasArg (options::OPT_mdll) && !IsShared)
224
+ CmdArgs.push_back (Args.MakeArgString (ToolChain.GetFilePath (" crt0.o" )));
225
+ if (ToolChain.GetRuntimeLibType (Args) == ToolChain::RLT_CompilerRT) {
226
+ std::string crtbegin =
227
+ ToolChain.getCompilerRT (Args, " crtbegin" , ToolChain::FT_Object);
228
+ if (ToolChain.getVFS ().exists (crtbegin)) {
229
+ std::string P;
230
+ P = crtbegin;
231
+ CmdArgs.push_back (Args.MakeArgString (P));
232
+ }
233
+ }
234
+ if (IsShared)
235
+ CmdArgs.push_back (
236
+ Args.MakeArgString (ToolChain.GetFilePath (" crtbeginS.o" )));
237
+ else
238
+ CmdArgs.push_back (
239
+ Args.MakeArgString (ToolChain.GetFilePath (" crtbegin.o" )));
240
+
241
+ // Add crtfastmath.o if available and fast math is enabled.
242
+ ToolChain.addFastMathRuntimeIfAvailable (Args, CmdArgs);
243
+ }
244
+
245
+ Args.addAllArgs (CmdArgs, {options::OPT_L, options::OPT_u});
246
+
247
+ ToolChain.AddFilePathLibArgs (Args, CmdArgs);
248
+
249
+ if (D.isUsingLTO ())
250
+ tools::addLTOOptions (ToolChain, Args, CmdArgs, Output, Inputs,
251
+ D.getLTOMode () == LTOK_Thin);
252
+
253
+ if (Args.hasArg (options::OPT_Z_Xlinker__no_demangle))
254
+ CmdArgs.push_back (" --no-demangle" );
255
+
256
+ bool NeedsSanitizerDeps =
257
+ tools::addSanitizerRuntimes (ToolChain, Args, CmdArgs);
258
+ bool NeedsXRayDeps = tools::addXRayRuntime (ToolChain, Args, CmdArgs);
259
+ tools::addLinkerCompressDebugSectionsOption (ToolChain, Args, CmdArgs);
260
+ tools::AddLinkerInputs (ToolChain, Inputs, Args, CmdArgs, JA);
261
+
262
+ bool saw_high_entropy_va = false ;
263
+ for (const char *Arg : CmdArgs)
264
+ if (StringRef (Arg) == " --high-entropy-va" ||
265
+ StringRef (Arg) == " --disable-high-entropy-va" )
266
+ saw_high_entropy_va = true ;
267
+ if (!saw_high_entropy_va)
268
+ CmdArgs.push_back (" --disable-high-entropy-va" );
269
+
270
+ tools::addHIPRuntimeLibArgs (ToolChain, C, Args, CmdArgs);
271
+
272
+ // The profile runtime also needs access to system libraries.
273
+ getToolChain ().addProfileRTLibs (Args, CmdArgs);
274
+
275
+ if (D.CCCIsCXX () &&
276
+ !Args.hasArg (options::OPT_nostdlib, options::OPT_nodefaultlibs,
277
+ options::OPT_r)) {
278
+ if (ToolChain.ShouldLinkCXXStdlib (Args)) {
279
+ bool OnlyLibstdcxxStatic = Args.hasArg (options::OPT_static_libstdcxx) &&
280
+ !Args.hasArg (options::OPT_static);
281
+ if (OnlyLibstdcxxStatic)
282
+ CmdArgs.push_back (" -Bstatic" );
283
+ ToolChain.AddCXXStdlibLibArgs (Args, CmdArgs);
284
+ if (OnlyLibstdcxxStatic)
285
+ CmdArgs.push_back (" -Bdynamic" );
286
+ }
287
+ CmdArgs.push_back (" -lm" );
288
+ }
289
+
290
+ // Silence warnings when linking C code with a C++ '-stdlib' argument.
291
+ Args.ClaimAllArgs (options::OPT_stdlib_EQ);
292
+
293
+ // Additional linker set-up and flags for Fortran. This is required in order
294
+ // to generate executables. As Fortran runtime depends on the C runtime,
295
+ // these dependencies need to be listed before the C runtime below (i.e.
296
+ // AddRunTimeLibs).
297
+ if (D.IsFlangMode () &&
298
+ !Args.hasArg (options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
299
+ ToolChain.addFortranRuntimeLibraryPath (Args, CmdArgs);
300
+ ToolChain.addFortranRuntimeLibs (Args, CmdArgs);
301
+ CmdArgs.push_back (" -lm" );
302
+ }
303
+
304
+ if (!Args.hasArg (options::OPT_nostdlib, options::OPT_r)) {
305
+ if (!Args.hasArg (options::OPT_nodefaultlibs)) {
306
+ if (IsStatic)
307
+ CmdArgs.push_back (" --start-group" );
308
+
309
+ if (NeedsSanitizerDeps)
310
+ tools::linkSanitizerRuntimeDeps (ToolChain, Args, CmdArgs);
311
+
312
+ if (NeedsXRayDeps)
313
+ tools::linkXRayRuntimeDeps (ToolChain, Args, CmdArgs);
314
+
315
+ bool WantPthread = Args.hasArg (options::OPT_pthread) ||
316
+ Args.hasArg (options::OPT_pthreads);
317
+
318
+ // Use the static OpenMP runtime with -static-openmp
319
+ bool StaticOpenMP = Args.hasArg (options::OPT_static_openmp) &&
320
+ !Args.hasArg (options::OPT_static);
321
+
322
+ // FIXME: Only pass GompNeedsRT = true for platforms with libgomp that
323
+ // require librt. Most modern Linux platforms do, but some may not.
324
+ if (tools::addOpenMPRuntime (C, CmdArgs, ToolChain, Args, StaticOpenMP,
325
+ JA.isHostOffloading (Action::OFK_OpenMP),
326
+ /* GompNeedsRT= */ true ))
327
+ // OpenMP runtimes implies pthreads when using the GNU toolchain.
328
+ // FIXME: Does this really make sense for all GNU toolchains?
329
+ WantPthread = true ;
330
+
331
+ tools::AddRunTimeLibs (ToolChain, D, CmdArgs, Args);
332
+
333
+ if (WantPthread)
334
+ CmdArgs.push_back (" -lpthread" );
335
+
336
+ if (Args.hasArg (options::OPT_fsplit_stack))
337
+ CmdArgs.push_back (" --wrap=pthread_create" );
338
+
339
+ if (!Args.hasArg (options::OPT_nolibc))
340
+ CmdArgs.push_back (" -lc" );
341
+
342
+ // Cygwin specific
343
+ CmdArgs.push_back (" -lcygwin" );
344
+ if (Args.hasArg (options::OPT_mwindows)) {
345
+ CmdArgs.push_back (" -lgdi32" );
346
+ CmdArgs.push_back (" -lcomdlg32" );
347
+ }
348
+ CmdArgs.push_back (" -ladvapi32" );
349
+ CmdArgs.push_back (" -lshell32" );
350
+ CmdArgs.push_back (" -luser32" );
351
+ CmdArgs.push_back (" -lkernel32" );
352
+
353
+ if (IsStatic)
354
+ CmdArgs.push_back (" --end-group" );
355
+ else
356
+ tools::AddRunTimeLibs (ToolChain, D, CmdArgs, Args);
357
+ }
358
+
359
+ if (!Args.hasArg (options::OPT_nostartfiles)) {
360
+ if (ToolChain.GetRuntimeLibType (Args) == ToolChain::RLT_CompilerRT) {
361
+ std::string crtend =
362
+ ToolChain.getCompilerRT (Args, " crtend" , ToolChain::FT_Object);
363
+ if (ToolChain.getVFS ().exists (crtend)) {
364
+ std::string P;
365
+ P = crtend;
366
+ CmdArgs.push_back (Args.MakeArgString (P));
367
+ }
368
+ }
369
+ CmdArgs.push_back (Args.MakeArgString (ToolChain.GetFilePath (" crtend.o" )));
370
+ }
371
+ }
372
+
373
+ Args.addAllArgs (CmdArgs, {options::OPT_T, options::OPT_t});
374
+
375
+ const char *Exec = Args.MakeArgString (ToolChain.GetLinkerPath ());
376
+ C.addCommand (std::make_unique<Command>(JA, *this ,
377
+ ResponseFileSupport::AtFileCurCP (),
378
+ Exec, CmdArgs, Inputs, Output));
379
+ }
380
+
381
+ auto Cygwin::buildLinker () const -> Tool * { return new cygwin::Linker (*this ); }
0 commit comments