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,293 @@ 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
+ if (ToolChain.getTriple ().isArch32Bit ()) {
181
+ CmdArgs.push_back (" --wrap=_Znwj" );
182
+ CmdArgs.push_back (" --wrap=_Znaj" );
183
+ CmdArgs.push_back (" --wrap=_ZdlPv" );
184
+ CmdArgs.push_back (" --wrap=_ZdaPv" );
185
+ CmdArgs.push_back (" --wrap=_ZnwjRKSt9nothrow_t" );
186
+ CmdArgs.push_back (" --wrap=_ZnajRKSt9nothrow_t" );
187
+ CmdArgs.push_back (" --wrap=_ZdlPvRKSt9nothrow_t" );
188
+ CmdArgs.push_back (" --wrap=_ZdaPvRKSt9nothrow_t" );
189
+ } else {
190
+ CmdArgs.push_back (" --wrap=_Znwm" );
191
+ CmdArgs.push_back (" --wrap=_Znam" );
192
+ CmdArgs.push_back (" --wrap=_ZdlPv" );
193
+ CmdArgs.push_back (" --wrap=_ZdaPv" );
194
+ CmdArgs.push_back (" --wrap=_ZnwmRKSt9nothrow_t" );
195
+ CmdArgs.push_back (" --wrap=_ZnamRKSt9nothrow_t" );
196
+ CmdArgs.push_back (" --wrap=_ZdlPvRKSt9nothrow_t" );
197
+ CmdArgs.push_back (" --wrap=_ZdaPvRKSt9nothrow_t" );
198
+ }
199
+
200
+ if (Args.hasArg (options::OPT_mdll))
201
+ CmdArgs.push_back (" --dll" );
202
+ else if (Args.hasArg (options::OPT_shared))
203
+ CmdArgs.push_back (" --shared" );
204
+ if (Args.hasArg (options::OPT_static))
205
+ CmdArgs.push_back (" -Bstatic" );
206
+ else
207
+ CmdArgs.push_back (" -Bdynamic" );
208
+
209
+ CmdArgs.push_back (" --dll-search-prefix=cyg" );
210
+
211
+ CmdArgs.push_back (" -o" );
212
+ const char *OutputFile = Output.getFilename ();
213
+ // GCC implicitly adds an .exe extension if it is given an output file name
214
+ // that lacks an extension.
215
+ // GCC used to do this only when the compiler itself runs on windows, but
216
+ // since GCC 8 it does the same when cross compiling as well.
217
+ if (!llvm::sys::path::has_extension (OutputFile)) {
218
+ CmdArgs.push_back (Args.MakeArgString (Twine (OutputFile) + " .exe" ));
219
+ OutputFile = CmdArgs.back ();
220
+ } else
221
+ CmdArgs.push_back (OutputFile);
222
+
223
+ if (!Args.hasArg (options::OPT_nostdlib, options::OPT_nostartfiles,
224
+ options::OPT_r)) {
225
+ const bool IsShared = Args.hasArg (options::OPT_shared);
226
+ if (Args.hasArg (options::OPT_mdll) || IsShared) {
227
+ CmdArgs.push_back (" -e" );
228
+ CmdArgs.push_back (ToolChain.getArch () == llvm::Triple::x86
229
+ ? " __cygwin_dll_entry@12"
230
+ : " _cygwin_dll_entry" );
231
+ CmdArgs.push_back (" --enable-auto-image-base" );
232
+ }
233
+
234
+ if (!Args.hasArg (options::OPT_mdll) && !IsShared)
235
+ CmdArgs.push_back (Args.MakeArgString (ToolChain.GetFilePath (" crt0.o" )));
236
+ if (ToolChain.GetRuntimeLibType (Args) == ToolChain::RLT_CompilerRT) {
237
+ std::string crtbegin =
238
+ ToolChain.getCompilerRT (Args, " crtbegin" , ToolChain::FT_Object);
239
+ if (ToolChain.getVFS ().exists (crtbegin)) {
240
+ std::string P;
241
+ P = crtbegin;
242
+ CmdArgs.push_back (Args.MakeArgString (P));
243
+ }
244
+ }
245
+ if (IsShared)
246
+ CmdArgs.push_back (
247
+ Args.MakeArgString (ToolChain.GetFilePath (" crtbeginS.o" )));
248
+ else
249
+ CmdArgs.push_back (
250
+ Args.MakeArgString (ToolChain.GetFilePath (" crtbegin.o" )));
251
+
252
+ // Add crtfastmath.o if available and fast math is enabled.
253
+ ToolChain.addFastMathRuntimeIfAvailable (Args, CmdArgs);
254
+ }
255
+
256
+ Args.addAllArgs (CmdArgs, {options::OPT_L, options::OPT_u});
257
+
258
+ ToolChain.AddFilePathLibArgs (Args, CmdArgs);
259
+
260
+ if (D.isUsingLTO ())
261
+ tools::addLTOOptions (ToolChain, Args, CmdArgs, Output, Inputs,
262
+ D.getLTOMode () == LTOK_Thin);
263
+
264
+ if (Args.hasArg (options::OPT_Z_Xlinker__no_demangle))
265
+ CmdArgs.push_back (" --no-demangle" );
266
+
267
+ bool NeedsSanitizerDeps =
268
+ tools::addSanitizerRuntimes (ToolChain, Args, CmdArgs);
269
+ bool NeedsXRayDeps = tools::addXRayRuntime (ToolChain, Args, CmdArgs);
270
+ tools::addLinkerCompressDebugSectionsOption (ToolChain, Args, CmdArgs);
271
+ tools::AddLinkerInputs (ToolChain, Inputs, Args, CmdArgs, JA);
272
+
273
+ bool saw_high_entropy_va = false ;
274
+ bool saw_nxcompat = false ;
275
+ for (const char *Arg : CmdArgs) {
276
+ if (StringRef (Arg) == " -high-entropy-va" ||
277
+ StringRef (Arg) == " --high-entropy-va" ||
278
+ StringRef (Arg) == " -disable-high-entropy-va" ||
279
+ StringRef (Arg) == " --disable-high-entropy-va" )
280
+ saw_high_entropy_va = true ;
281
+ if (StringRef (Arg) == " -nxcompat" || StringRef (Arg) == " --nxcompat" ||
282
+ StringRef (Arg) == " -disable-nxcompat" ||
283
+ StringRef (Arg) == " --disable-nxcompat" )
284
+ saw_nxcompat = true ;
285
+ }
286
+ if (!saw_high_entropy_va)
287
+ CmdArgs.push_back (" --disable-high-entropy-va" );
288
+ if (!saw_nxcompat)
289
+ CmdArgs.push_back (" --disable-nxcompat" );
290
+
291
+ tools::addHIPRuntimeLibArgs (ToolChain, C, Args, CmdArgs);
292
+
293
+ // The profile runtime also needs access to system libraries.
294
+ getToolChain ().addProfileRTLibs (Args, CmdArgs);
295
+
296
+ if (D.CCCIsCXX () &&
297
+ !Args.hasArg (options::OPT_nostdlib, options::OPT_nodefaultlibs,
298
+ options::OPT_r)) {
299
+ if (ToolChain.ShouldLinkCXXStdlib (Args)) {
300
+ bool OnlyLibstdcxxStatic = Args.hasArg (options::OPT_static_libstdcxx) &&
301
+ !Args.hasArg (options::OPT_static);
302
+ if (OnlyLibstdcxxStatic)
303
+ CmdArgs.push_back (" -Bstatic" );
304
+ ToolChain.AddCXXStdlibLibArgs (Args, CmdArgs);
305
+ if (OnlyLibstdcxxStatic)
306
+ CmdArgs.push_back (" -Bdynamic" );
307
+ }
308
+ CmdArgs.push_back (" -lm" );
309
+ }
310
+
311
+ // Silence warnings when linking C code with a C++ '-stdlib' argument.
312
+ Args.ClaimAllArgs (options::OPT_stdlib_EQ);
313
+
314
+ // Additional linker set-up and flags for Fortran. This is required in order
315
+ // to generate executables. As Fortran runtime depends on the C runtime,
316
+ // these dependencies need to be listed before the C runtime below (i.e.
317
+ // AddRunTimeLibs).
318
+ if (D.IsFlangMode () &&
319
+ !Args.hasArg (options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
320
+ ToolChain.addFortranRuntimeLibraryPath (Args, CmdArgs);
321
+ ToolChain.addFortranRuntimeLibs (Args, CmdArgs);
322
+ CmdArgs.push_back (" -lm" );
323
+ }
324
+
325
+ if (!Args.hasArg (options::OPT_nostdlib, options::OPT_r)) {
326
+ if (!Args.hasArg (options::OPT_nodefaultlibs)) {
327
+ if (IsStatic)
328
+ CmdArgs.push_back (" --start-group" );
329
+
330
+ if (NeedsSanitizerDeps)
331
+ tools::linkSanitizerRuntimeDeps (ToolChain, Args, CmdArgs);
332
+
333
+ if (NeedsXRayDeps)
334
+ tools::linkXRayRuntimeDeps (ToolChain, Args, CmdArgs);
335
+
336
+ bool WantPthread = Args.hasArg (options::OPT_pthread) ||
337
+ Args.hasArg (options::OPT_pthreads);
338
+
339
+ // Use the static OpenMP runtime with -static-openmp
340
+ bool StaticOpenMP = Args.hasArg (options::OPT_static_openmp) &&
341
+ !Args.hasArg (options::OPT_static);
342
+
343
+ // FIXME: Only pass GompNeedsRT = true for platforms with libgomp that
344
+ // require librt. Most modern Linux platforms do, but some may not.
345
+ if (tools::addOpenMPRuntime (C, CmdArgs, ToolChain, Args, StaticOpenMP,
346
+ JA.isHostOffloading (Action::OFK_OpenMP),
347
+ /* GompNeedsRT= */ true ))
348
+ // OpenMP runtimes implies pthreads when using the GNU toolchain.
349
+ // FIXME: Does this really make sense for all GNU toolchains?
350
+ WantPthread = true ;
351
+
352
+ tools::AddRunTimeLibs (ToolChain, D, CmdArgs, Args);
353
+
354
+ if (WantPthread)
355
+ CmdArgs.push_back (" -lpthread" );
356
+
357
+ if (Args.hasArg (options::OPT_fsplit_stack))
358
+ CmdArgs.push_back (" --wrap=pthread_create" );
359
+
360
+ if (!Args.hasArg (options::OPT_nolibc))
361
+ CmdArgs.push_back (" -lc" );
362
+
363
+ // Cygwin specific
364
+ CmdArgs.push_back (" -lcygwin" );
365
+ if (Args.hasArg (options::OPT_mwindows)) {
366
+ CmdArgs.push_back (" -lgdi32" );
367
+ CmdArgs.push_back (" -lcomdlg32" );
368
+ }
369
+ CmdArgs.push_back (" -ladvapi32" );
370
+ CmdArgs.push_back (" -lshell32" );
371
+ CmdArgs.push_back (" -luser32" );
372
+ CmdArgs.push_back (" -lkernel32" );
373
+
374
+ if (IsStatic)
375
+ CmdArgs.push_back (" --end-group" );
376
+ else
377
+ tools::AddRunTimeLibs (ToolChain, D, CmdArgs, Args);
378
+ }
379
+
380
+ if (!Args.hasArg (options::OPT_nostartfiles)) {
381
+ if (ToolChain.GetRuntimeLibType (Args) == ToolChain::RLT_CompilerRT) {
382
+ std::string crtend =
383
+ ToolChain.getCompilerRT (Args, " crtend" , ToolChain::FT_Object);
384
+ if (ToolChain.getVFS ().exists (crtend)) {
385
+ std::string P;
386
+ P = crtend;
387
+ CmdArgs.push_back (Args.MakeArgString (P));
388
+ }
389
+ }
390
+ CmdArgs.push_back (Args.MakeArgString (ToolChain.GetFilePath (" crtend.o" )));
391
+ }
392
+ }
393
+
394
+ Args.addAllArgs (CmdArgs, {options::OPT_T, options::OPT_t});
395
+
396
+ const char *Exec = Args.MakeArgString (ToolChain.GetLinkerPath ());
397
+ C.addCommand (std::make_unique<Command>(JA, *this ,
398
+ ResponseFileSupport::AtFileCurCP (),
399
+ Exec, CmdArgs, Inputs, Output));
400
+ }
401
+
402
+ auto Cygwin::buildLinker () const -> Tool * { return new cygwin::Linker (*this ); }
0 commit comments