t_darwin.pas 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  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_ios:
  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_ios,
  171. system_aarch64_darwin:
  172. { never anything }
  173. exit('');
  174. else
  175. Internalerror(2019050709);
  176. end;
  177. { nothing special -> default }
  178. result:='crt1.o';
  179. end
  180. else
  181. begin
  182. result:='gcrt1.o';
  183. { 10.8 and later: tell the linker to use 'start' instead of "_main"
  184. as entry point }
  185. if CompareVersionStrings(MacOSXVersionMin,'10.8')>=0 then
  186. Info.ExeCmd[1]:=Info.ExeCmd[1]+' -no_new_main';
  187. end;
  188. end
  189. else
  190. begin
  191. if (apptype=app_bundle) then
  192. begin
  193. case target_info.system of
  194. system_powerpc_darwin,
  195. system_powerpc64_darwin,
  196. system_i386_darwin,
  197. system_x86_64_darwin:
  198. begin
  199. { < 10.6: bundle1.o
  200. >= 10.6: nothing }
  201. if CompareVersionStrings(MacOSXVersionMin,'10.6')>=0 then
  202. exit('');
  203. end;
  204. system_arm_ios,
  205. system_aarch64_ios:
  206. begin
  207. { iOS: < 3.1: bundle1.o
  208. >= 3.1: nothing }
  209. if (CompareVersionStrings(iPhoneOSVersionMin,'3.1')>=0) then
  210. exit('');
  211. end;
  212. system_i386_iphonesim,
  213. system_x86_64_iphonesim:
  214. begin
  215. { see rule for crt1.o }
  216. if (CompareVersionStrings(iPhoneOSVersionMin,'8.1')>0) then
  217. exit('');
  218. end;
  219. system_aarch64_darwin:
  220. exit('');
  221. else
  222. Internalerror(2019050710);
  223. end;
  224. result:='bundle1.o';
  225. end
  226. else
  227. begin
  228. case target_info.system of
  229. system_powerpc_darwin,
  230. system_powerpc64_darwin,
  231. system_i386_darwin,
  232. system_x86_64_darwin:
  233. begin
  234. { >= 10.6: nothing
  235. = 10.5: dylib1.10.5.o
  236. < 10.5: dylib1.o
  237. }
  238. if CompareVersionStrings(MacOSXVersionMin,'10.6')>=0 then
  239. exit('');
  240. if CompareVersionStrings(MacOSXVersionMin,'10.5')>=0 then
  241. exit('dylib1.10.5.o');
  242. end;
  243. system_arm_ios,
  244. system_aarch64_ios:
  245. begin
  246. { iOS: < 3.1: dylib1.o
  247. >= 3.1: nothing }
  248. if (CompareVersionStrings(iPhoneOSVersionMin,'3.1')>=0) then
  249. exit('');
  250. end;
  251. system_i386_iphonesim,
  252. system_x86_64_iphonesim:
  253. begin
  254. { see rule for crt1.o }
  255. if (CompareVersionStrings(iPhoneOSVersionMin,'8.1')>0) then
  256. exit('');
  257. end;
  258. system_aarch64_darwin:
  259. exit('');
  260. else
  261. Internalerror(2019050711);
  262. end;
  263. result:='dylib1.o';
  264. end;
  265. end;
  266. end;
  267. Function tlinkerdarwin.GetDarwinPrtobjName(isdll: boolean): TCmdStr;
  268. var
  269. startupfile: TCmdStr;
  270. begin
  271. result:='';
  272. startupfile:=GetDarwinCrt1ObjName(isdll);
  273. if startupfile<>'' then
  274. begin
  275. if not librarysearchpath.FindFile(startupfile,false,result) then
  276. result:='/usr/lib/'+startupfile;
  277. end;
  278. result:=maybequoted(result);
  279. end;
  280. Function tlinkerdarwin.WriteResponseFile(isdll:boolean) : Boolean;
  281. Var
  282. linkres : TLinkRes;
  283. FilesList : TLinkRes;
  284. i : longint;
  285. HPath : TCmdStrListItem;
  286. s : TCmdStr;
  287. begin
  288. WriteResponseFile:=False;
  289. if ReOrderEntries Then
  290. ExpandAndApplyOrder(SharedLibFiles);
  291. { Open link.res file }
  292. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName,false);
  293. if sysrootpath<>'' then
  294. begin
  295. LinkRes.Add('-syslibroot');
  296. LinkRes.Add(sysrootpath);
  297. end;
  298. LinkRes.Add('-arch');
  299. case target_info.system of
  300. system_powerpc_darwin:
  301. LinkRes.Add('ppc');
  302. system_i386_darwin,
  303. system_i386_iphonesim:
  304. LinkRes.Add('i386');
  305. system_powerpc64_darwin:
  306. LinkRes.Add('ppc64');
  307. system_x86_64_darwin,
  308. system_x86_64_iphonesim:
  309. LinkRes.Add('x86_64');
  310. system_arm_ios:
  311. { current versions of the linker require the sub-architecture type
  312. to be specified }
  313. LinkRes.Add(lower(cputypestr[current_settings.cputype]));
  314. system_aarch64_ios,
  315. system_aarch64_darwin:
  316. LinkRes.Add('arm64');
  317. else
  318. internalerror(2014121801);
  319. end;
  320. if MacOSXVersionMin<>'' then
  321. begin
  322. LinkRes.Add('-macosx_version_min');
  323. LinkRes.Add(MacOSXVersionMin);
  324. end
  325. else if iPhoneOSVersionMin<>'' then
  326. begin
  327. LinkRes.Add('-iphoneos_version_min');
  328. LinkRes.Add(iPhoneOSVersionMin);
  329. end;
  330. { Write path to search libraries }
  331. HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
  332. while assigned(HPath) do
  333. begin
  334. LinkRes.Add('-L'+HPath.Str);
  335. HPath:=TCmdStrListItem(HPath.Next);
  336. end;
  337. HPath:=TCmdStrListItem(LibrarySearchPath.First);
  338. while assigned(HPath) do
  339. begin
  340. LinkRes.Add('-L'+HPath.Str);
  341. HPath:=TCmdStrListItem(HPath.Next);
  342. end;
  343. HPath:=TCmdStrListItem(current_module.localframeworksearchpath.First);
  344. while assigned(HPath) do
  345. begin
  346. LinkRes.Add('-F'+HPath.Str);
  347. HPath:=TCmdStrListItem(HPath.Next);
  348. end;
  349. HPath:=TCmdStrListItem(FrameworkSearchPath.First);
  350. while assigned(HPath) do
  351. begin
  352. LinkRes.Add('-F'+HPath.Str);
  353. HPath:=TCmdStrListItem(HPath.Next);
  354. end;
  355. { main objectfiles }
  356. LinkFilesFileName:=UniqueName('linkfiles')+'.res';
  357. FilesList:=TLinkRes.Create(outputexedir+LinkFilesFileName,false);
  358. while not ObjectFiles.Empty do
  359. begin
  360. s:=ObjectFiles.GetFirst;
  361. if s<>'' then
  362. begin
  363. s:=TargetFixFileName(s);
  364. FilesList.Add(s);
  365. end;
  366. end;
  367. FilesList.writetodisk;
  368. FilesList.Free;
  369. { Write staticlibraries }
  370. while not StaticLibFiles.Empty do
  371. begin
  372. S:=StaticLibFiles.GetFirst;
  373. LinkRes.AddFileName(s)
  374. end;
  375. { Write sharedlibraries like -l<lib> }
  376. while not SharedLibFiles.Empty do
  377. begin
  378. S:=SharedLibFiles.GetFirst;
  379. if (s<>'c') or ReOrderEntries then
  380. begin
  381. i:=Pos(target_info.sharedlibext,S);
  382. if i>0 then
  383. Delete(S,i,255);
  384. LinkRes.Add('-l'+s);
  385. end;
  386. { be sure that libc is the last lib }
  387. if not ReOrderEntries then
  388. begin
  389. LinkRes.Add('-lc')
  390. end;
  391. end;
  392. while not FrameworkFiles.empty do
  393. begin
  394. LinkRes.Add('-framework');
  395. LinkRes.Add(FrameworkFiles.GetFirst);
  396. end;
  397. { Write and Close response }
  398. linkres.writetodisk;
  399. linkres.Free;
  400. WriteResponseFile:=True;
  401. end;
  402. function tlinkerdarwin.MakeExecutable:boolean;
  403. var
  404. binstr,
  405. cmdstr,
  406. mapstr,
  407. targetstr,
  408. emulstr,
  409. extdbgbinstr,
  410. extdbgcmdstr,
  411. ltostr,
  412. ordersymfile: TCmdStr;
  413. linkscript: TAsmScript;
  414. DynLinkStr : string[60];
  415. GCSectionsStr,
  416. StaticStr,
  417. StripStr : string[63];
  418. success : boolean;
  419. begin
  420. if not(cs_link_nolink in current_settings.globalswitches) then
  421. Message1(exec_i_linking,current_module.exefilename);
  422. { Create some replacements }
  423. StaticStr:='';
  424. StripStr:='';
  425. DynLinkStr:='';
  426. GCSectionsStr:='';
  427. linkscript:=nil;
  428. mapstr:='';
  429. targetstr:='';
  430. emulstr:='';
  431. ltostr:='';
  432. if (cs_link_map in current_settings.globalswitches) then
  433. mapstr:='-map '+maybequoted(ChangeFileExt(current_module.exefilename,'.map'));
  434. if (cs_link_staticflag in current_settings.globalswitches) then
  435. StaticStr:='-static';
  436. if (cs_link_strip in current_settings.globalswitches) then
  437. StripStr:='-x';
  438. if (cs_link_smart in current_settings.globalswitches) then
  439. GCSectionsStr:='-dead_strip -no_dead_strip_inits_and_terms';
  440. if CShared Then
  441. begin
  442. DynLinKStr:=DynLinkStr+' -dynamic'; // one dash!
  443. end;
  444. { add custom LTO library if using custom clang }
  445. if (cs_lto in current_settings.moduleswitches) and
  446. not(cs_link_on_target in current_settings.globalswitches) and
  447. (utilsdirectory<>'') and
  448. FileExists(utilsdirectory+'/../lib/libLTO.dylib',true) then
  449. begin
  450. ltostr:='-lto_library '+maybequoted(utilsdirectory+'/../lib/libLTO.dylib');
  451. end;
  452. { Write used files and libraries }
  453. WriteResponseFile(false);
  454. { Write symbol order file }
  455. ordersymfile:=WriteSymbolOrderFile;
  456. { Call linker }
  457. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  458. Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename));
  459. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  460. Replace(cmdstr,'$TARGET',targetstr);
  461. Replace(cmdstr,'$EMUL',EmulStr);
  462. Replace(cmdstr,'$MAP',mapstr);
  463. Replace(cmdstr,'$CATRES',CatFileContent(outputexedir+Info.ResName));
  464. Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
  465. Replace(cmdstr,'$LTO',ltostr);
  466. if ordersymfile<>'' then
  467. Replace(cmdstr,'$ORDERSYMS','-order_file '+maybequoted(ordersymfile))
  468. else
  469. Replace(cmdstr,'$ORDERSYMS','');
  470. Replace(cmdstr,'$FILELIST','-filelist '+maybequoted(outputexedir+LinkFilesFileName));
  471. Replace(cmdstr,'$STATIC',StaticStr);
  472. Replace(cmdstr,'$STRIP',StripStr);
  473. Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
  474. Replace(cmdstr,'$DYNLINK',DynLinkStr);
  475. Replace(cmdstr,'$PRTOBJ',GetDarwinPrtobjName(false));
  476. BinStr:=FindUtil(utilsprefix+BinStr);
  477. { create dsym file? }
  478. extdbgbinstr:='';
  479. extdbgcmdstr:='';
  480. if (target_dbg.id in [dbg_dwarf2,dbg_dwarf3]) and
  481. (cs_link_separate_dbg_file in current_settings.globalswitches) then
  482. begin
  483. extdbgbinstr:=FindUtil(utilsprefix+'dsymutil');
  484. extdbgcmdstr:=maybequoted(current_module.exefilename);
  485. end;
  486. if not(cs_link_nolink in current_settings.globalswitches) then
  487. begin
  488. { we have to use a script to use the IFS hack }
  489. linkscript:=GenerateScript(outputexedir+'ppaslink');
  490. linkscript.AddLinkCommand(BinStr,CmdStr,'');
  491. if (extdbgcmdstr<>'') then
  492. linkscript.AddLinkCommand(extdbgbinstr,extdbgcmdstr,'');
  493. linkscript.WriteToDisk;
  494. BinStr:=linkscript.fn;
  495. if not path_absolute(BinStr) then
  496. if cs_link_on_target in current_settings.globalswitches then
  497. BinStr:='.'+target_info.dirsep+BinStr
  498. else
  499. BinStr:='.'+source_info.dirsep+BinStr;
  500. CmdStr:='';
  501. end;
  502. success:=DoExec(BinStr,CmdStr,true,true);
  503. if (success and
  504. (extdbgbinstr<>'') and
  505. (cs_link_nolink in current_settings.globalswitches)) then
  506. success:=DoExec(extdbgbinstr,extdbgcmdstr,false,true);
  507. { Remove ReponseFile }
  508. if (success) and not(cs_link_nolink in current_settings.globalswitches) then
  509. begin
  510. DeleteFile(outputexedir+Info.ResName);
  511. if ordersymfile<>'' then
  512. DeleteFile(ordersymfile);
  513. DeleteFile(linkscript.fn);
  514. linkscript.free;
  515. DeleteFile(outputexedir+LinkFilesFileName);
  516. end;
  517. MakeExecutable:=success; { otherwise a recursive call to link method }
  518. end;
  519. Function tlinkerdarwin.MakeSharedLibrary:boolean;
  520. var
  521. InitStr,
  522. FiniStr,
  523. SoNameStr : string[80];
  524. linkscript: TAsmScript;
  525. binstr,
  526. cmdstr,
  527. mapstr,
  528. ltostr,
  529. ordersymfile,
  530. targetstr,
  531. emulstr,
  532. extdbgbinstr,
  533. extdbgcmdstr : TCmdStr;
  534. GCSectionsStr : string[63];
  535. exportedsyms: text;
  536. success : boolean;
  537. begin
  538. MakeSharedLibrary:=false;
  539. GCSectionsStr:='';
  540. mapstr:='';
  541. ltostr:='';
  542. linkscript:=nil;
  543. if not(cs_link_nolink in current_settings.globalswitches) then
  544. Message1(exec_i_linking,current_module.sharedlibfilename);
  545. { Write used files and libraries }
  546. WriteResponseFile(true);
  547. { Write symbol order file }
  548. ordersymfile:=WriteSymbolOrderFile;
  549. if (cs_link_smart in current_settings.globalswitches) then
  550. GCSectionsStr:='-dead_strip -no_dead_strip_inits_and_terms';
  551. if (cs_link_map in current_settings.globalswitches) then
  552. mapstr:='-Map '+maybequoted(ChangeFileExt(current_module.sharedlibfilename,'.map'));
  553. { add custom LTO library if using custom clang }
  554. if (cs_lto in current_settings.moduleswitches) and
  555. not(cs_link_on_target in current_settings.globalswitches) and
  556. (utilsdirectory<>'') and
  557. FileExists(utilsdirectory+'/../lib/libLTO.dylib',true) then
  558. begin
  559. ltostr:='-lto_library '+maybequoted(utilsdirectory+'/../lib/libLTO.dylib');
  560. end;
  561. targetstr:='';
  562. emulstr:='';
  563. InitStr:='-init FPC_LIB_START';
  564. FiniStr:='-fini FPC_LIB_EXIT';
  565. SoNameStr:='-soname '+ExtractFileName(current_module.sharedlibfilename);
  566. { Call linker }
  567. SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
  568. Replace(cmdstr,'$EXE',maybequoted(ExpandFileName(current_module.sharedlibfilename)));
  569. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  570. Replace(cmdstr,'$TARGET',targetstr);
  571. Replace(cmdstr,'$EMUL',EmulStr);
  572. Replace(cmdstr,'$CATRES',CatFileContent(outputexedir+Info.ResName));
  573. Replace(cmdstr,'$FILELIST','-filelist '+maybequoted(outputexedir+LinkFilesFileName));
  574. Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
  575. Replace(cmdstr,'$INIT',InitStr);
  576. Replace(cmdstr,'$FINI',FiniStr);
  577. Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
  578. Replace(cmdstr,'$SONAME',SoNameStr);
  579. Replace(cmdstr,'$MAP',mapstr);
  580. Replace(cmdstr,'$LTO',ltostr);
  581. if ordersymfile<>'' then
  582. Replace(cmdstr,'$ORDERSYMS','-order_file '+maybequoted(ordersymfile))
  583. else
  584. Replace(cmdstr,'$ORDERSYMS','');
  585. Replace(cmdstr,'$PRTOBJ',GetDarwinPrtobjName(true));
  586. BinStr:=FindUtil(utilsprefix+BinStr);
  587. { create dsym file? }
  588. extdbgbinstr:='';
  589. extdbgcmdstr:='';
  590. if (target_dbg.id in [dbg_dwarf2,dbg_dwarf3]) and
  591. (cs_link_separate_dbg_file in current_settings.globalswitches) then
  592. begin
  593. extdbgbinstr:=FindUtil(utilsprefix+'dsymutil');
  594. extdbgcmdstr:=maybequoted(current_module.sharedlibfilename);
  595. end;
  596. LinkSymsFileName:='';
  597. if not texportlibunix(exportlib).exportedsymnames.empty then
  598. begin
  599. LinkSymsFileName:=UniqueName('linksyms')+'.fpc';
  600. assign(exportedsyms,outputexedir+LinkSymsFileName);
  601. rewrite(exportedsyms);
  602. repeat
  603. writeln(exportedsyms,texportlibunix(exportlib).exportedsymnames.getfirst);
  604. until texportlibunix(exportlib).exportedsymnames.empty;
  605. close(exportedsyms);
  606. cmdstr:=cmdstr+' -exported_symbols_list '+maybequoted(outputexedir)+LinkSymsFileName;
  607. end;
  608. if not(cs_link_nolink in current_settings.globalswitches) then
  609. begin
  610. { we have to use a script to use the IFS hack }
  611. linkscript:=GenerateScript(outputexedir+'ppaslink');
  612. linkscript.AddLinkCommand(BinStr,CmdStr,'');
  613. if (extdbgbinstr<>'') then
  614. linkscript.AddLinkCommand(extdbgbinstr,extdbgcmdstr,'');
  615. linkscript.WriteToDisk;
  616. BinStr:=linkscript.fn;
  617. if not path_absolute(BinStr) then
  618. if cs_link_on_target in current_settings.globalswitches then
  619. BinStr:='.'+target_info.dirsep+BinStr
  620. else
  621. BinStr:='.'+source_info.dirsep+BinStr;
  622. CmdStr:='';
  623. end;
  624. success:=DoExec(BinStr,cmdstr,true,true);
  625. if (success and
  626. (extdbgbinstr<>'') and
  627. (cs_link_nolink in current_settings.globalswitches)) then
  628. success:=DoExec(extdbgbinstr,extdbgcmdstr,false,true);
  629. { Strip the library ? }
  630. if success and (cs_link_strip in current_settings.globalswitches) then
  631. begin
  632. SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
  633. Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename));
  634. success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,false,false);
  635. end;
  636. { Remove ReponseFile }
  637. if (success) and not(cs_link_nolink in current_settings.globalswitches) then
  638. begin
  639. DeleteFile(outputexedir+Info.ResName);
  640. if ordersymfile<>'' then
  641. DeleteFile(ordersymfile);
  642. DeleteFile(linkscript.fn);
  643. linkscript.free;
  644. if LinkSymsFileName<>'' then
  645. DeleteFile(outputexedir+LinkSymsFileName);
  646. DeleteFile(outputexedir+LinkFilesFileName);
  647. end;
  648. MakeSharedLibrary:=success; { otherwise a recursive call to link method }
  649. end;
  650. {*****************************************************************************
  651. Initialize
  652. *****************************************************************************}
  653. initialization
  654. RegisterLinker(ld_darwin,tlinkerdarwin);
  655. {$ifdef x86_64}
  656. RegisterImport(system_x86_64_darwin,timportlibdarwin);
  657. RegisterExport(system_x86_64_darwin,texportlibdarwin);
  658. RegisterTarget(system_x86_64_darwin_info);
  659. RegisterImport(system_x86_64_iphonesim,timportlibdarwin);
  660. RegisterExport(system_x86_64_iphonesim,texportlibdarwin);
  661. RegisterTarget(system_x86_64_iphonesim_info);
  662. {$endif}
  663. {$ifdef i386}
  664. RegisterImport(system_i386_darwin,timportlibdarwin);
  665. RegisterExport(system_i386_darwin,texportlibdarwin);
  666. RegisterTarget(system_i386_darwin_info);
  667. RegisterImport(system_i386_iphonesim,timportlibdarwin);
  668. RegisterExport(system_i386_iphonesim,texportlibdarwin);
  669. RegisterTarget(system_i386_iphonesim_info);
  670. {$endif i386}
  671. {$ifdef powerpc}
  672. RegisterImport(system_powerpc_darwin,timportlibdarwin);
  673. RegisterExport(system_powerpc_darwin,texportlibdarwin);
  674. RegisterTarget(system_powerpc_darwin_info);
  675. {$endif powerpc}
  676. {$ifdef powerpc64}
  677. RegisterImport(system_powerpc64_darwin,timportlibdarwin);
  678. RegisterExport(system_powerpc64_darwin,texportlibdarwin);
  679. RegisterTarget(system_powerpc64_darwin_info);
  680. {$endif powerpc64}
  681. {$ifdef arm}
  682. RegisterImport(system_arm_ios,timportlibdarwin);
  683. RegisterExport(system_arm_ios,texportlibdarwin);
  684. RegisterTarget(system_arm_ios_info);
  685. {$endif arm}
  686. {$ifdef aarch64}
  687. RegisterImport(system_aarch64_ios,timportlibdarwin);
  688. RegisterExport(system_aarch64_ios,texportlibdarwin);
  689. RegisterTarget(system_aarch64_ios_info);
  690. RegisterImport(system_aarch64_darwin,timportlibdarwin);
  691. RegisterExport(system_aarch64_darwin,texportlibdarwin);
  692. RegisterTarget(system_aarch64_darwin_info);
  693. {$endif aarch64}
  694. RegisterRes(res_macho_info,TWinLikeResourceFile);
  695. RegisterRes(res_macosx_ext_info,TWinLikeResourceFile);
  696. end.