t_darwin.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774
  1. {
  2. Copyright (c) 1998-2002 by Peter Vreman (original Linux)
  3. (c) 2000 by Marco van de Voort (FreeBSD mods)
  4. This unit implements support import,export,link routines
  5. for the (i386)FreeBSD target
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit t_darwin;
  20. {$i fpcdefs.inc}
  21. interface
  22. implementation
  23. uses
  24. sysutils,
  25. cutils,cfileutl,cclasses,
  26. verbose,systems,globtype,globals,
  27. symconst,cscript,
  28. fmodule,aasmbase,aasmtai,aasmdata,aasmcpu,cpubase,symsym,symdef,
  29. import,export,link,comprsrc,rescmn,i_darwin,expunix,
  30. cgutils,cgbase,cgobj,cpuinfo,ogbase;
  31. type
  32. timportlibdarwin=class(timportlib)
  33. procedure generatelib;override;
  34. end;
  35. texportlibdarwin=class(texportlibunix)
  36. procedure setinitname(list: TAsmList; const s: string); override;
  37. procedure setfininame(list: TAsmList; const s: string); override;
  38. end;
  39. tlinkerdarwin=class(texternallinker)
  40. private
  41. LinkFilesFileName,
  42. LinkSymsFileName : TCmdStr;
  43. Function WriteResponseFile(isdll:boolean) : Boolean;
  44. function GetDarwinCrt1ObjName(isdll: boolean): TCmdStr;
  45. Function GetDarwinPrtobjName(isdll: boolean): TCmdStr;
  46. public
  47. constructor Create;override;
  48. procedure SetDefaultInfo;override;
  49. function MakeExecutable:boolean;override;
  50. function MakeSharedLibrary:boolean;override;
  51. procedure LoadPredefinedLibraryOrder; override;
  52. procedure InitSysInitUnitName; override;
  53. end;
  54. {*****************************************************************************
  55. TIMPORTLIBDARWIN
  56. *****************************************************************************}
  57. procedure timportlibdarwin.generatelib;
  58. begin
  59. end;
  60. {*****************************************************************************
  61. TEXPORTLIBDARWIN
  62. *****************************************************************************}
  63. procedure texportlibdarwin.setinitname(list: TAsmList; const s: string);
  64. begin
  65. new_section(list,sec_init_func,'',sizeof(pint));
  66. list.concat(Tai_const.Createname(s,0));
  67. end;
  68. procedure texportlibdarwin.setfininame(list: TAsmList; const s: string);
  69. begin
  70. new_section(list,sec_term_func,'',sizeof(pint));
  71. list.concat(Tai_const.Createname(s,0));
  72. end;
  73. {*****************************************************************************
  74. TLINKERBSD
  75. *****************************************************************************}
  76. constructor tlinkerdarwin.Create;
  77. begin
  78. inherited;
  79. if not Dontlinkstdlibpath Then
  80. LibrarySearchPath.AddLibraryPath(sysrootpath,'=/usr/lib',true)
  81. end;
  82. procedure tlinkerdarwin.SetDefaultInfo;
  83. begin
  84. with Info do
  85. begin
  86. {$ifndef cpu64bitaddr}
  87. { Set the size of the page at address zero to 64kb, so nothing
  88. is loaded below that address. This avoids problems with the
  89. strange Windows-compatible resource handling that assumes
  90. that addresses below 64kb do not exist.
  91. On 64bit systems, page zero is 4GB by default, so no problems
  92. there.
  93. }
  94. { In case of valgrind, don't do that, because it cannot deal with
  95. a custom pagezero size -- in general, this should not cause any
  96. problems because the resources are added at the end and most
  97. programs with problems that require Valgrind will have more
  98. than 60KB of data (first 4KB of address space is always invalid)
  99. }
  100. ExeCmd[1]:='ld $PRTOBJ $TARGET $EMUL $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP $MAP $LTO $ORDERSYMS -multiply_defined suppress -L. -o $EXE $CATRES $FILELIST';
  101. if not(cs_gdb_valgrind in current_settings.globalswitches) then
  102. ExeCmd[1]:=ExeCmd[1]+' -pagezero_size 0x10000';
  103. {$else ndef cpu64bitaddr}
  104. ExeCmd[1]:='ld $PRTOBJ $TARGET $EMUL $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP $MAP $LTO $ORDERSYMS -multiply_defined suppress -L. -o $EXE $CATRES $FILELIST';
  105. {$endif ndef cpu64bitaddr}
  106. if (apptype<>app_bundle) then
  107. DllCmd[1]:='ld $PRTOBJ $TARGET $EMUL $OPT $GCSECTIONS $MAP $LTO $ORDERSYMS -dynamic -dylib -multiply_defined suppress -L. -o $EXE $CATRES $FILELIST'
  108. else
  109. DllCmd[1]:='ld $PRTOBJ $TARGET $EMUL $OPT $GCSECTIONS $MAP $LTO $ORDERSYMS -dynamic -bundle -multiply_defined suppress -L. -o $EXE $CATRES $FILELIST';
  110. DllCmd[2]:='strip -x $EXE';
  111. DynamicLinker:='';
  112. end;
  113. end;
  114. procedure tlinkerdarwin.LoadPredefinedLibraryOrder;
  115. begin
  116. // put your linkorder/linkalias overrides here.
  117. // Note: assumes only called when reordering/aliasing is used.
  118. LinkLibraryOrder.add('gcc','',15);
  119. LinkLibraryOrder.add('c','',50);
  120. end;
  121. procedure tlinkerdarwin.InitSysInitUnitName;
  122. begin
  123. SysInitUnit:='sysinit';
  124. end;
  125. function tlinkerdarwin.GetDarwinCrt1ObjName(isdll: boolean): TCmdStr;
  126. begin
  127. if not isdll then
  128. begin
  129. if not(cs_profile in current_settings.moduleswitches) then
  130. begin
  131. case target_info.system of
  132. system_powerpc_darwin,
  133. system_powerpc64_darwin,
  134. system_i386_darwin,
  135. system_x86_64_darwin:
  136. begin
  137. { 10.8 and later: no crt1.* }
  138. if CompareVersionStrings(MacOSXVersionMin,'10.8')>=0 then
  139. exit('');
  140. { x86: crt1.10.6.o -> crt1.10.5.o -> crt1.o }
  141. { others: crt1.10.5 -> crt1.o }
  142. if (target_info.system in [system_i386_darwin,system_x86_64_darwin]) and
  143. (CompareVersionStrings(MacOSXVersionMin,'10.6')>=0) then
  144. exit('crt1.10.6.o');
  145. if CompareVersionStrings(MacOSXVersionMin,'10.5')>=0 then
  146. exit('crt1.10.5.o');
  147. end;
  148. system_arm_darwin:
  149. begin
  150. { iOS:
  151. iOS 6 and later: nothing
  152. iOS 3.1 - 5.x: crt1.3.1.o
  153. pre-iOS 3.1: crt1.o
  154. }
  155. if (CompareVersionStrings(iPhoneOSVersionMin,'6.0')>=0) then
  156. exit('');
  157. if (CompareVersionStrings(iPhoneOSVersionMin,'3.1')>=0) then
  158. exit('crt1.3.1.o');
  159. end;
  160. system_i386_iphonesim,
  161. system_x86_64_iphonesim:
  162. begin
  163. { "recent versions" must not use anything (https://github.com/llvm-mirror/clang/commit/e6d04f3d152a22077022cf9287d4c538a0918ab0 )
  164. What those recent versions could be, is anyone's guess. It
  165. still seems to work with 8.1 and no longer with 8.3, so use
  166. 8.1 as a cut-off point }
  167. if (CompareVersionStrings(iPhoneOSVersionMin,'8.1')>0) then
  168. exit('');
  169. end;
  170. system_aarch64_darwin:
  171. { never anything }
  172. exit('');
  173. else
  174. Internalerror(2019050709);
  175. end;
  176. { nothing special -> default }
  177. result:='crt1.o';
  178. end
  179. else
  180. begin
  181. result:='gcrt1.o';
  182. { 10.8 and later: tell the linker to use 'start' instead of "_main"
  183. as entry point }
  184. if CompareVersionStrings(MacOSXVersionMin,'10.8')>=0 then
  185. Info.ExeCmd[1]:=Info.ExeCmd[1]+' -no_new_main';
  186. end;
  187. end
  188. else
  189. begin
  190. if (apptype=app_bundle) then
  191. begin
  192. case target_info.system of
  193. system_powerpc_darwin,
  194. system_powerpc64_darwin,
  195. system_i386_darwin,
  196. system_x86_64_darwin:
  197. begin
  198. { < 10.6: bundle1.o
  199. >= 10.6: nothing }
  200. if CompareVersionStrings(MacOSXVersionMin,'10.6')>=0 then
  201. exit('');
  202. end;
  203. system_arm_darwin,
  204. system_aarch64_darwin:
  205. begin
  206. { iOS: < 3.1: bundle1.o
  207. >= 3.1: nothing }
  208. if (CompareVersionStrings(iPhoneOSVersionMin,'3.1')>=0) then
  209. exit('');
  210. end;
  211. system_i386_iphonesim,
  212. system_x86_64_iphonesim:
  213. begin
  214. { see rule for crt1.o }
  215. if (CompareVersionStrings(iPhoneOSVersionMin,'8.1')>0) then
  216. exit('');
  217. end;
  218. else
  219. Internalerror(2019050710);
  220. end;
  221. result:='bundle1.o';
  222. end
  223. else
  224. begin
  225. case target_info.system of
  226. system_powerpc_darwin,
  227. system_powerpc64_darwin,
  228. system_i386_darwin,
  229. system_x86_64_darwin:
  230. begin
  231. { >= 10.6: nothing
  232. = 10.5: dylib1.10.5.o
  233. < 10.5: dylib1.o
  234. }
  235. if CompareVersionStrings(MacOSXVersionMin,'10.6')>=0 then
  236. exit('');
  237. if CompareVersionStrings(MacOSXVersionMin,'10.5')>=0 then
  238. exit('dylib1.10.5.o');
  239. end;
  240. system_arm_darwin,
  241. system_aarch64_darwin:
  242. begin
  243. { iOS: < 3.1: dylib1.o
  244. >= 3.1: nothing }
  245. if (CompareVersionStrings(iPhoneOSVersionMin,'3.1')>=0) then
  246. exit('');
  247. end;
  248. system_i386_iphonesim,
  249. system_x86_64_iphonesim:
  250. begin
  251. { see rule for crt1.o }
  252. if (CompareVersionStrings(iPhoneOSVersionMin,'8.1')>0) then
  253. exit('');
  254. end;
  255. else
  256. Internalerror(2019050711);
  257. end;
  258. result:='dylib1.o';
  259. end;
  260. end;
  261. end;
  262. Function tlinkerdarwin.GetDarwinPrtobjName(isdll: boolean): TCmdStr;
  263. var
  264. startupfile: TCmdStr;
  265. begin
  266. result:='';
  267. startupfile:=GetDarwinCrt1ObjName(isdll);
  268. if startupfile<>'' then
  269. begin
  270. if not librarysearchpath.FindFile(startupfile,false,result) then
  271. result:='/usr/lib/'+startupfile;
  272. end;
  273. result:=maybequoted(result);
  274. end;
  275. Function tlinkerdarwin.WriteResponseFile(isdll:boolean) : Boolean;
  276. Var
  277. linkres : TLinkRes;
  278. FilesList : TLinkRes;
  279. i : longint;
  280. HPath : TCmdStrListItem;
  281. s,s1,s2 : TCmdStr;
  282. Fl1,Fl2 : Boolean;
  283. begin
  284. WriteResponseFile:=False;
  285. if ReOrderEntries Then
  286. ExpandAndApplyOrder(SharedLibFiles);
  287. { Open link.res file }
  288. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName,false);
  289. if sysrootpath<>'' then
  290. begin
  291. LinkRes.Add('-syslibroot');
  292. LinkRes.Add(sysrootpath);
  293. end;
  294. LinkRes.Add('-arch');
  295. case target_info.system of
  296. system_powerpc_darwin:
  297. LinkRes.Add('ppc');
  298. system_i386_darwin,
  299. system_i386_iphonesim:
  300. LinkRes.Add('i386');
  301. system_powerpc64_darwin:
  302. LinkRes.Add('ppc64');
  303. system_x86_64_darwin,
  304. system_x86_64_iphonesim:
  305. LinkRes.Add('x86_64');
  306. system_arm_darwin:
  307. { current versions of the linker require the sub-architecture type
  308. to be specified }
  309. LinkRes.Add(lower(cputypestr[current_settings.cputype]));
  310. system_aarch64_darwin:
  311. LinkRes.Add('arm64');
  312. else
  313. internalerror(2014121801);
  314. end;
  315. if MacOSXVersionMin<>'' then
  316. begin
  317. LinkRes.Add('-macosx_version_min');
  318. LinkRes.Add(MacOSXVersionMin);
  319. end
  320. else if iPhoneOSVersionMin<>'' then
  321. begin
  322. LinkRes.Add('-iphoneos_version_min');
  323. LinkRes.Add(iPhoneOSVersionMin);
  324. end;
  325. { Write path to search libraries }
  326. HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
  327. while assigned(HPath) do
  328. begin
  329. LinkRes.Add('-L'+HPath.Str);
  330. HPath:=TCmdStrListItem(HPath.Next);
  331. end;
  332. HPath:=TCmdStrListItem(LibrarySearchPath.First);
  333. while assigned(HPath) do
  334. begin
  335. LinkRes.Add('-L'+HPath.Str);
  336. HPath:=TCmdStrListItem(HPath.Next);
  337. end;
  338. HPath:=TCmdStrListItem(current_module.localframeworksearchpath.First);
  339. while assigned(HPath) do
  340. begin
  341. LinkRes.Add('-F'+HPath.Str);
  342. HPath:=TCmdStrListItem(HPath.Next);
  343. end;
  344. HPath:=TCmdStrListItem(FrameworkSearchPath.First);
  345. while assigned(HPath) do
  346. begin
  347. LinkRes.Add('-F'+HPath.Str);
  348. HPath:=TCmdStrListItem(HPath.Next);
  349. end;
  350. { main objectfiles }
  351. LinkFilesFileName:=UniqueName('linkfiles')+'.res';
  352. FilesList:=TLinkRes.Create(outputexedir+LinkFilesFileName,false);
  353. while not ObjectFiles.Empty do
  354. begin
  355. s:=ObjectFiles.GetFirst;
  356. if s<>'' then
  357. begin
  358. s:=TargetFixFileName(s);
  359. FilesList.Add(s);
  360. end;
  361. end;
  362. FilesList.writetodisk;
  363. FilesList.Free;
  364. { Write staticlibraries }
  365. while not StaticLibFiles.Empty do
  366. begin
  367. S:=StaticLibFiles.GetFirst;
  368. LinkRes.AddFileName(s)
  369. end;
  370. { Write sharedlibraries like -l<lib> }
  371. while not SharedLibFiles.Empty do
  372. begin
  373. S:=SharedLibFiles.GetFirst;
  374. if (s<>'c') or ReOrderEntries then
  375. begin
  376. i:=Pos(target_info.sharedlibext,S);
  377. if i>0 then
  378. Delete(S,i,255);
  379. LinkRes.Add('-l'+s);
  380. end;
  381. { be sure that libc is the last lib }
  382. if not ReOrderEntries then
  383. begin
  384. LinkRes.Add('-lc')
  385. end;
  386. end;
  387. while not FrameworkFiles.empty do
  388. begin
  389. LinkRes.Add('-framework');
  390. LinkRes.Add(FrameworkFiles.GetFirst);
  391. end;
  392. { Write and Close response }
  393. linkres.writetodisk;
  394. linkres.Free;
  395. WriteResponseFile:=True;
  396. end;
  397. function tlinkerdarwin.MakeExecutable:boolean;
  398. var
  399. binstr,
  400. cmdstr,
  401. mapstr,
  402. targetstr,
  403. emulstr,
  404. extdbgbinstr,
  405. extdbgcmdstr,
  406. ltostr,
  407. ordersymfile: TCmdStr;
  408. linkscript: TAsmScript;
  409. DynLinkStr : string[60];
  410. GCSectionsStr,
  411. StaticStr,
  412. StripStr : string[63];
  413. success : boolean;
  414. begin
  415. if not(cs_link_nolink in current_settings.globalswitches) then
  416. Message1(exec_i_linking,current_module.exefilename);
  417. { Create some replacements }
  418. StaticStr:='';
  419. StripStr:='';
  420. DynLinkStr:='';
  421. GCSectionsStr:='';
  422. linkscript:=nil;
  423. mapstr:='';
  424. targetstr:='';
  425. emulstr:='';
  426. ltostr:='';
  427. if (cs_link_map in current_settings.globalswitches) then
  428. mapstr:='-Map '+maybequoted(ChangeFileExt(current_module.exefilename,'.map'));
  429. if (cs_link_staticflag in current_settings.globalswitches) then
  430. StaticStr:='-static';
  431. if (cs_link_strip in current_settings.globalswitches) then
  432. StripStr:='-x';
  433. if (cs_link_smart in current_settings.globalswitches) then
  434. GCSectionsStr:='-dead_strip -no_dead_strip_inits_and_terms';
  435. if CShared Then
  436. begin
  437. DynLinKStr:=DynLinkStr+' -dynamic'; // one dash!
  438. end;
  439. { add custom LTO library if using custom clang }
  440. if (cs_lto in current_settings.moduleswitches) and
  441. not(cs_link_on_target in current_settings.globalswitches) and
  442. (utilsdirectory<>'') and
  443. FileExists(utilsdirectory+'/../lib/libLTO.dylib',true) then
  444. begin
  445. ltostr:='-lto_library '+maybequoted(utilsdirectory+'/../lib/libLTO.dylib');
  446. end;
  447. { Write used files and libraries }
  448. WriteResponseFile(false);
  449. { Write symbol order file }
  450. ordersymfile:=WriteSymbolOrderFile;
  451. { Call linker }
  452. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  453. Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename));
  454. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  455. Replace(cmdstr,'$TARGET',targetstr);
  456. Replace(cmdstr,'$EMUL',EmulStr);
  457. Replace(cmdstr,'$MAP',mapstr);
  458. Replace(cmdstr,'$CATRES',CatFileContent(outputexedir+Info.ResName));
  459. Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
  460. Replace(cmdstr,'$LTO',ltostr);
  461. if ordersymfile<>'' then
  462. Replace(cmdstr,'$ORDERSYMS','-order_file '+maybequoted(ordersymfile))
  463. else
  464. Replace(cmdstr,'$ORDERSYMS','');
  465. Replace(cmdstr,'$FILELIST','-filelist '+maybequoted(outputexedir+LinkFilesFileName));
  466. Replace(cmdstr,'$STATIC',StaticStr);
  467. Replace(cmdstr,'$STRIP',StripStr);
  468. Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
  469. Replace(cmdstr,'$DYNLINK',DynLinkStr);
  470. Replace(cmdstr,'$PRTOBJ',GetDarwinPrtobjName(false));
  471. BinStr:=FindUtil(utilsprefix+BinStr);
  472. { create dsym file? }
  473. extdbgbinstr:='';
  474. extdbgcmdstr:='';
  475. if (target_dbg.id in [dbg_dwarf2,dbg_dwarf3]) and
  476. (cs_link_separate_dbg_file in current_settings.globalswitches) then
  477. begin
  478. extdbgbinstr:=FindUtil(utilsprefix+'dsymutil');
  479. extdbgcmdstr:=maybequoted(current_module.exefilename);
  480. end;
  481. if not(cs_link_nolink in current_settings.globalswitches) then
  482. begin
  483. { we have to use a script to use the IFS hack }
  484. linkscript:=GenerateScript(outputexedir+'ppaslink');
  485. linkscript.AddLinkCommand(BinStr,CmdStr,'');
  486. if (extdbgcmdstr<>'') then
  487. linkscript.AddLinkCommand(extdbgbinstr,extdbgcmdstr,'');
  488. linkscript.WriteToDisk;
  489. BinStr:=linkscript.fn;
  490. if not path_absolute(BinStr) then
  491. if cs_link_on_target in current_settings.globalswitches then
  492. BinStr:='.'+target_info.dirsep+BinStr
  493. else
  494. BinStr:='.'+source_info.dirsep+BinStr;
  495. CmdStr:='';
  496. end;
  497. success:=DoExec(BinStr,CmdStr,true,true);
  498. if (success and
  499. (extdbgbinstr<>'') and
  500. (cs_link_nolink in current_settings.globalswitches)) then
  501. success:=DoExec(extdbgbinstr,extdbgcmdstr,false,true);
  502. { Remove ReponseFile }
  503. if (success) and not(cs_link_nolink in current_settings.globalswitches) then
  504. begin
  505. DeleteFile(outputexedir+Info.ResName);
  506. if ordersymfile<>'' then
  507. DeleteFile(ordersymfile);
  508. DeleteFile(linkscript.fn);
  509. linkscript.free;
  510. DeleteFile(outputexedir+LinkFilesFileName);
  511. end;
  512. MakeExecutable:=success; { otherwise a recursive call to link method }
  513. end;
  514. Function tlinkerdarwin.MakeSharedLibrary:boolean;
  515. var
  516. InitStr,
  517. FiniStr,
  518. SoNameStr : string[80];
  519. linkscript: TAsmScript;
  520. binstr,
  521. cmdstr,
  522. mapstr,
  523. ltostr,
  524. ordersymfile,
  525. targetstr,
  526. emulstr,
  527. extdbgbinstr,
  528. extdbgcmdstr : TCmdStr;
  529. GCSectionsStr : string[63];
  530. exportedsyms: text;
  531. success : boolean;
  532. begin
  533. MakeSharedLibrary:=false;
  534. GCSectionsStr:='';
  535. mapstr:='';
  536. ltostr:='';
  537. linkscript:=nil;
  538. if not(cs_link_nolink in current_settings.globalswitches) then
  539. Message1(exec_i_linking,current_module.sharedlibfilename);
  540. { Write used files and libraries }
  541. WriteResponseFile(true);
  542. { Write symbol order file }
  543. ordersymfile:=WriteSymbolOrderFile;
  544. if (cs_link_smart in current_settings.globalswitches) then
  545. GCSectionsStr:='-dead_strip -no_dead_strip_inits_and_terms';
  546. if (cs_link_map in current_settings.globalswitches) then
  547. mapstr:='-Map '+maybequoted(ChangeFileExt(current_module.sharedlibfilename,'.map'));
  548. { add custom LTO library if using custom clang }
  549. if (cs_lto in current_settings.moduleswitches) and
  550. not(cs_link_on_target in current_settings.globalswitches) and
  551. (utilsdirectory<>'') and
  552. FileExists(utilsdirectory+'/../lib/libLTO.dylib',true) then
  553. begin
  554. ltostr:='-lto_library '+maybequoted(utilsdirectory+'/../lib/libLTO.dylib');
  555. end;
  556. targetstr:='';
  557. emulstr:='';
  558. InitStr:='-init FPC_LIB_START';
  559. FiniStr:='-fini FPC_LIB_EXIT';
  560. SoNameStr:='-soname '+ExtractFileName(current_module.sharedlibfilename);
  561. { Call linker }
  562. SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
  563. Replace(cmdstr,'$EXE',maybequoted(ExpandFileName(current_module.sharedlibfilename)));
  564. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  565. Replace(cmdstr,'$TARGET',targetstr);
  566. Replace(cmdstr,'$EMUL',EmulStr);
  567. Replace(cmdstr,'$CATRES',CatFileContent(outputexedir+Info.ResName));
  568. Replace(cmdstr,'$FILELIST','-filelist '+maybequoted(outputexedir+LinkFilesFileName));
  569. Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
  570. Replace(cmdstr,'$INIT',InitStr);
  571. Replace(cmdstr,'$FINI',FiniStr);
  572. Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
  573. Replace(cmdstr,'$SONAME',SoNameStr);
  574. Replace(cmdstr,'$MAP',mapstr);
  575. Replace(cmdstr,'$LTO',ltostr);
  576. if ordersymfile<>'' then
  577. Replace(cmdstr,'$ORDERSYMS','-order_file '+maybequoted(ordersymfile))
  578. else
  579. Replace(cmdstr,'$ORDERSYMS','');
  580. Replace(cmdstr,'$PRTOBJ',GetDarwinPrtobjName(true));
  581. BinStr:=FindUtil(utilsprefix+BinStr);
  582. { create dsym file? }
  583. extdbgbinstr:='';
  584. extdbgcmdstr:='';
  585. if (target_dbg.id in [dbg_dwarf2,dbg_dwarf3]) and
  586. (cs_link_separate_dbg_file in current_settings.globalswitches) then
  587. begin
  588. extdbgbinstr:=FindUtil(utilsprefix+'dsymutil');
  589. extdbgcmdstr:=maybequoted(current_module.sharedlibfilename);
  590. end;
  591. if not texportlibunix(exportlib).exportedsymnames.empty then
  592. begin
  593. LinkSymsFileName:=UniqueName('linksyms')+'.fpc';
  594. assign(exportedsyms,outputexedir+LinkSymsFileName);
  595. rewrite(exportedsyms);
  596. repeat
  597. writeln(exportedsyms,texportlibunix(exportlib).exportedsymnames.getfirst);
  598. until texportlibunix(exportlib).exportedsymnames.empty;
  599. close(exportedsyms);
  600. cmdstr:=cmdstr+' -exported_symbols_list '+maybequoted(outputexedir)+LinkSymsFileName;
  601. end;
  602. if not(cs_link_nolink in current_settings.globalswitches) then
  603. begin
  604. { we have to use a script to use the IFS hack }
  605. linkscript:=GenerateScript(outputexedir+'ppaslink');
  606. linkscript.AddLinkCommand(BinStr,CmdStr,'');
  607. if (extdbgbinstr<>'') then
  608. linkscript.AddLinkCommand(extdbgbinstr,extdbgcmdstr,'');
  609. linkscript.WriteToDisk;
  610. BinStr:=linkscript.fn;
  611. if not path_absolute(BinStr) then
  612. if cs_link_on_target in current_settings.globalswitches then
  613. BinStr:='.'+target_info.dirsep+BinStr
  614. else
  615. BinStr:='.'+source_info.dirsep+BinStr;
  616. CmdStr:='';
  617. end;
  618. success:=DoExec(BinStr,cmdstr,true,true);
  619. if (success and
  620. (extdbgbinstr<>'') and
  621. (cs_link_nolink in current_settings.globalswitches)) then
  622. success:=DoExec(extdbgbinstr,extdbgcmdstr,false,true);
  623. { Strip the library ? }
  624. if success and (cs_link_strip in current_settings.globalswitches) then
  625. begin
  626. SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
  627. Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename));
  628. success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,false,false);
  629. end;
  630. { Remove ReponseFile }
  631. if (success) and not(cs_link_nolink in current_settings.globalswitches) then
  632. begin
  633. DeleteFile(outputexedir+Info.ResName);
  634. if ordersymfile<>'' then
  635. DeleteFile(ordersymfile);
  636. DeleteFile(linkscript.fn);
  637. linkscript.free;
  638. if not texportlibunix(exportlib).exportedsymnames.empty then
  639. DeleteFile(outputexedir+LinkSymsFileName);
  640. DeleteFile(outputexedir+LinkFilesFileName);
  641. end;
  642. MakeSharedLibrary:=success; { otherwise a recursive call to link method }
  643. end;
  644. {*****************************************************************************
  645. Initialize
  646. *****************************************************************************}
  647. initialization
  648. RegisterLinker(ld_darwin,tlinkerdarwin);
  649. {$ifdef x86_64}
  650. RegisterImport(system_x86_64_darwin,timportlibdarwin);
  651. RegisterExport(system_x86_64_darwin,texportlibdarwin);
  652. RegisterTarget(system_x86_64_darwin_info);
  653. RegisterImport(system_x86_64_iphonesim,timportlibdarwin);
  654. RegisterExport(system_x86_64_iphonesim,texportlibdarwin);
  655. RegisterTarget(system_x86_64_iphonesim_info);
  656. {$endif}
  657. {$ifdef i386}
  658. RegisterImport(system_i386_darwin,timportlibdarwin);
  659. RegisterExport(system_i386_darwin,texportlibdarwin);
  660. RegisterTarget(system_i386_darwin_info);
  661. RegisterImport(system_i386_iphonesim,timportlibdarwin);
  662. RegisterExport(system_i386_iphonesim,texportlibdarwin);
  663. RegisterTarget(system_i386_iphonesim_info);
  664. {$endif i386}
  665. {$ifdef powerpc}
  666. RegisterImport(system_powerpc_darwin,timportlibdarwin);
  667. RegisterExport(system_powerpc_darwin,texportlibdarwin);
  668. RegisterTarget(system_powerpc_darwin_info);
  669. {$endif powerpc}
  670. {$ifdef powerpc64}
  671. RegisterImport(system_powerpc64_darwin,timportlibdarwin);
  672. RegisterExport(system_powerpc64_darwin,texportlibdarwin);
  673. RegisterTarget(system_powerpc64_darwin_info);
  674. {$endif powerpc64}
  675. {$ifdef arm}
  676. RegisterImport(system_arm_darwin,timportlibdarwin);
  677. RegisterExport(system_arm_darwin,texportlibdarwin);
  678. RegisterTarget(system_arm_darwin_info);
  679. {$endif arm}
  680. {$ifdef aarch64}
  681. RegisterImport(system_aarch64_darwin,timportlibdarwin);
  682. RegisterExport(system_aarch64_darwin,texportlibdarwin);
  683. RegisterTarget(system_aarch64_darwin_info);
  684. {$endif aarch64}
  685. RegisterRes(res_macho_info,TWinLikeResourceFile);
  686. RegisterRes(res_macosx_ext_info,TWinLikeResourceFile);
  687. end.