t_darwin.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765
  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. LinkSymsFileName : TCmdStr;
  42. function WriteFileList: TCmdStr;
  43. function GetDarwinCrt1ObjName(isdll: boolean): TCmdStr;
  44. Function GetDarwinPrtobjName(isdll: boolean): TCmdStr;
  45. function GetLinkArch: TCmdStr;
  46. function GetLinkVersion: TCmdStr;
  47. function GetSysroot: TCmdStr;
  48. function GetLibSearchPath: TCmdStr;
  49. function GetLibraries: TCmdStr;
  50. public
  51. constructor Create;override;
  52. procedure SetDefaultInfo;override;
  53. function MakeExecutable:boolean;override;
  54. function MakeSharedLibrary:boolean;override;
  55. procedure LoadPredefinedLibraryOrder; override;
  56. procedure InitSysInitUnitName; override;
  57. function postprocessexecutable(const fn : string;isdll:boolean):boolean;
  58. end;
  59. {*****************************************************************************
  60. TIMPORTLIBDARWIN
  61. *****************************************************************************}
  62. procedure timportlibdarwin.generatelib;
  63. begin
  64. end;
  65. {*****************************************************************************
  66. TEXPORTLIBDARWIN
  67. *****************************************************************************}
  68. procedure texportlibdarwin.setinitname(list: TAsmList; const s: string);
  69. begin
  70. new_section(list,sec_init_func,'',sizeof(pint));
  71. list.concat(Tai_const.Createname(s,0));
  72. end;
  73. procedure texportlibdarwin.setfininame(list: TAsmList; const s: string);
  74. begin
  75. new_section(list,sec_term_func,'',sizeof(pint));
  76. list.concat(Tai_const.Createname(s,0));
  77. end;
  78. {*****************************************************************************
  79. TLINKERBSD
  80. *****************************************************************************}
  81. constructor tlinkerdarwin.Create;
  82. begin
  83. inherited;
  84. if not Dontlinkstdlibpath Then
  85. LibrarySearchPath.AddLibraryPath(sysrootpath,'=/usr/lib',true)
  86. end;
  87. procedure tlinkerdarwin.SetDefaultInfo;
  88. begin
  89. with Info do
  90. begin
  91. {$ifndef cpu64bitaddr}
  92. { Set the size of the page at address zero to 64kb, so nothing
  93. is loaded below that address. This avoids problems with the
  94. strange Windows-compatible resource handling that assumes
  95. that addresses below 64kb do not exist.
  96. On 64bit systems, page zero is 4GB by default, so no problems
  97. there.
  98. }
  99. { In case of valgrind, don't do that, because it cannot deal with
  100. a custom pagezero size -- in general, this should not cause any
  101. problems because the resources are added at the end and most
  102. programs with problems that require Valgrind will have more
  103. than 60KB of data (first 4KB of address space is always invalid)
  104. }
  105. ExeCmd[1]:='ld $PRTOBJ $TARGET $OPT $STATIC $GCSECTIONS $STRIP $MAP $LTO $ORDERSYMS -L. -o $EXE $ARCH $VERSION $SYSROOT $LIBSEARCHPATH $FILELIST $LIBRARIES';
  106. if not(cs_gdb_valgrind in current_settings.globalswitches) then
  107. ExeCmd[1]:=ExeCmd[1]+' -pagezero_size 0x10000';
  108. {$else ndef cpu64bitaddr}
  109. ExeCmd[1]:='ld $PRTOBJ $TARGET $OPT $STATIC $GCSECTIONS $STRIP $MAP $LTO $ORDERSYMS -L. -o $EXE $ARCH $VERSION $SYSROOT $LIBSEARCHPATH $FILELIST $LIBRARIES';
  110. {$endif ndef cpu64bitaddr}
  111. if (apptype<>app_bundle) then
  112. DllCmd[1]:='ld $PRTOBJ $TARGET $OPT $GCSECTIONS $MAP $LTO $ORDERSYMS -dynamic -dylib -L. -o $EXE $ARCH $VERSION $SYSROOT $LIBSEARCHPATH $FILELIST $LIBRARIES'
  113. else
  114. DllCmd[1]:='ld $PRTOBJ $TARGET $OPT $GCSECTIONS $MAP $LTO $ORDERSYMS -dynamic -bundle -L. -o $EXE $ARCH $VERSION $SYRSROOT $LIBSEARCHPATH $FILELIST $LIBRARIES';
  115. DllCmd[2]:='strip -x $EXE';
  116. DynamicLinker:='';
  117. end;
  118. end;
  119. procedure tlinkerdarwin.LoadPredefinedLibraryOrder;
  120. begin
  121. // put your linkorder/linkalias overrides here.
  122. // Note: assumes only called when reordering/aliasing is used.
  123. LinkLibraryOrder.add('gcc','',15);
  124. LinkLibraryOrder.add('c','',50);
  125. end;
  126. procedure tlinkerdarwin.InitSysInitUnitName;
  127. begin
  128. SysInitUnit:='sysinit';
  129. end;
  130. function tlinkerdarwin.GetDarwinCrt1ObjName(isdll: boolean): TCmdStr;
  131. begin
  132. if not isdll then
  133. begin
  134. if not(cs_profile in current_settings.moduleswitches) then
  135. begin
  136. case target_info.system of
  137. system_powerpc_darwin,
  138. system_powerpc64_darwin,
  139. system_i386_darwin,
  140. system_x86_64_darwin:
  141. begin
  142. { 10.8 and later: no crt1.* }
  143. if CompareVersionStrings(MacOSXVersionMin,'10.8')>=0 then
  144. exit('');
  145. { x86: crt1.10.6.o -> crt1.10.5.o -> crt1.o }
  146. { others: crt1.10.5 -> crt1.o }
  147. if (target_info.system in [system_i386_darwin,system_x86_64_darwin]) and
  148. (CompareVersionStrings(MacOSXVersionMin,'10.6')>=0) then
  149. exit('crt1.10.6.o');
  150. if CompareVersionStrings(MacOSXVersionMin,'10.5')>=0 then
  151. exit('crt1.10.5.o');
  152. end;
  153. system_arm_ios:
  154. begin
  155. { iOS:
  156. iOS 6 and later: nothing
  157. iOS 3.1 - 5.x: crt1.3.1.o
  158. pre-iOS 3.1: crt1.o
  159. }
  160. if (CompareVersionStrings(iPhoneOSVersionMin,'6.0')>=0) then
  161. exit('');
  162. if (CompareVersionStrings(iPhoneOSVersionMin,'3.1')>=0) then
  163. exit('crt1.3.1.o');
  164. end;
  165. system_i386_iphonesim,
  166. system_x86_64_iphonesim:
  167. begin
  168. { "recent versions" must not use anything (https://github.com/llvm-mirror/clang/commit/e6d04f3d152a22077022cf9287d4c538a0918ab0 )
  169. What those recent versions could be, is anyone's guess. It
  170. still seems to work with 8.1 and no longer with 8.3, so use
  171. 8.1 as a cut-off point }
  172. if (CompareVersionStrings(iPhoneOSVersionMin,'8.1')>0) then
  173. exit('');
  174. end;
  175. system_aarch64_ios,
  176. system_aarch64_darwin:
  177. { never anything }
  178. exit('');
  179. else
  180. Internalerror(2019050709);
  181. end;
  182. { nothing special -> default }
  183. result:='crt1.o';
  184. end
  185. else
  186. begin
  187. result:='gcrt1.o';
  188. { 10.8 and later: tell the linker to use 'start' instead of "_main"
  189. as entry point }
  190. if CompareVersionStrings(MacOSXVersionMin,'10.8')>=0 then
  191. Info.ExeCmd[1]:=Info.ExeCmd[1]+' -no_new_main';
  192. end;
  193. end
  194. else
  195. begin
  196. if (apptype=app_bundle) then
  197. begin
  198. case target_info.system of
  199. system_powerpc_darwin,
  200. system_powerpc64_darwin,
  201. system_i386_darwin,
  202. system_x86_64_darwin:
  203. begin
  204. { < 10.6: bundle1.o
  205. >= 10.6: nothing }
  206. if CompareVersionStrings(MacOSXVersionMin,'10.6')>=0 then
  207. exit('');
  208. end;
  209. system_arm_ios,
  210. system_aarch64_ios:
  211. begin
  212. { iOS: < 3.1: bundle1.o
  213. >= 3.1: nothing }
  214. if (CompareVersionStrings(iPhoneOSVersionMin,'3.1')>=0) then
  215. exit('');
  216. end;
  217. system_i386_iphonesim,
  218. system_x86_64_iphonesim:
  219. begin
  220. { see rule for crt1.o }
  221. if (CompareVersionStrings(iPhoneOSVersionMin,'8.1')>0) then
  222. exit('');
  223. end;
  224. system_aarch64_darwin:
  225. exit('');
  226. else
  227. Internalerror(2019050710);
  228. end;
  229. result:='bundle1.o';
  230. end
  231. else
  232. begin
  233. case target_info.system of
  234. system_powerpc_darwin,
  235. system_powerpc64_darwin,
  236. system_i386_darwin,
  237. system_x86_64_darwin:
  238. begin
  239. { >= 10.6: nothing
  240. = 10.5: dylib1.10.5.o
  241. < 10.5: dylib1.o
  242. }
  243. if CompareVersionStrings(MacOSXVersionMin,'10.6')>=0 then
  244. exit('');
  245. if CompareVersionStrings(MacOSXVersionMin,'10.5')>=0 then
  246. exit('dylib1.10.5.o');
  247. end;
  248. system_arm_ios,
  249. system_aarch64_ios:
  250. begin
  251. { iOS: < 3.1: dylib1.o
  252. >= 3.1: nothing }
  253. if (CompareVersionStrings(iPhoneOSVersionMin,'3.1')>=0) then
  254. exit('');
  255. end;
  256. system_i386_iphonesim,
  257. system_x86_64_iphonesim:
  258. begin
  259. { see rule for crt1.o }
  260. if (CompareVersionStrings(iPhoneOSVersionMin,'8.1')>0) then
  261. exit('');
  262. end;
  263. system_aarch64_darwin:
  264. exit('');
  265. else
  266. Internalerror(2019050711);
  267. end;
  268. result:='dylib1.o';
  269. end;
  270. end;
  271. end;
  272. function tlinkerdarwin.GetDarwinPrtobjName(isdll: boolean): TCmdStr;
  273. var
  274. startupfile: TCmdStr;
  275. begin
  276. result:='';
  277. startupfile:=GetDarwinCrt1ObjName(isdll);
  278. if startupfile<>'' then
  279. begin
  280. if not librarysearchpath.FindFile(startupfile,false,result) then
  281. result:='/usr/lib/'+startupfile;
  282. end;
  283. result:=maybequoted(result);
  284. end;
  285. function tlinkerdarwin.GetLinkArch: TCmdStr;
  286. begin
  287. case target_info.system of
  288. system_powerpc_darwin:
  289. result:='-arch ppc';
  290. system_i386_darwin,
  291. system_i386_iphonesim:
  292. result:='-arch i386';
  293. system_powerpc64_darwin:
  294. result:='-arch ppc64';
  295. system_x86_64_darwin,
  296. system_x86_64_iphonesim:
  297. result:='-arch x86_64';
  298. system_arm_ios:
  299. { current versions of the linker require the sub-architecture type
  300. to be specified }
  301. result:='-arch '+lower(cputypestr[current_settings.cputype]);
  302. system_aarch64_ios,
  303. system_aarch64_darwin:
  304. result:='-arch arm64';
  305. else
  306. internalerror(2014121801);
  307. end;
  308. end;
  309. function tlinkerdarwin.GetLinkVersion: TCmdStr;
  310. begin
  311. if MacOSXVersionMin<>'' then
  312. begin
  313. result:='-macosx_version_min '+MacOSXVersionMin;
  314. end
  315. else if iPhoneOSVersionMin<>'' then
  316. begin
  317. if target_info.system in [system_i386_iphonesim,system_x86_64_iphonesim] then
  318. result:='-ios_simulator_version_min '+iPhoneOSVersionMin
  319. else
  320. result:='-iphoneos_version_min '+iPhoneOSVersionMin;
  321. end
  322. else
  323. begin
  324. result:='';
  325. end;
  326. end;
  327. function tlinkerdarwin.GetSysroot: TCmdStr;
  328. begin
  329. if sysrootpath<>'' then
  330. begin
  331. result:='-syslibroot '+maybequoted(sysrootpath);
  332. end
  333. else
  334. begin
  335. result:='';
  336. end;
  337. end;
  338. function tlinkerdarwin.GetLibSearchPath: TCmdStr;
  339. var
  340. HPath: TCmdStrListItem;
  341. begin
  342. result:='';
  343. HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
  344. while assigned(HPath) do
  345. begin
  346. result:=result+' '+maybequoted('-L'+HPath.Str);
  347. HPath:=TCmdStrListItem(HPath.Next);
  348. end;
  349. HPath:=TCmdStrListItem(LibrarySearchPath.First);
  350. while assigned(HPath) do
  351. begin
  352. result:=result+' '+maybequoted('-L'+HPath.Str);
  353. HPath:=TCmdStrListItem(HPath.Next);
  354. end;
  355. HPath:=TCmdStrListItem(current_module.localframeworksearchpath.First);
  356. while assigned(HPath) do
  357. begin
  358. result:=result+' '+maybequoted('-F'+HPath.Str);
  359. HPath:=TCmdStrListItem(HPath.Next);
  360. end;
  361. HPath:=TCmdStrListItem(FrameworkSearchPath.First);
  362. while assigned(HPath) do
  363. begin
  364. result:=result+' '+maybequoted('-F'+HPath.Str);
  365. HPath:=TCmdStrListItem(HPath.Next);
  366. end;
  367. end;
  368. function tlinkerdarwin.GetLibraries: TCmdStr;
  369. var
  370. s: TCmdStr;
  371. i: longint;
  372. begin
  373. result:='';
  374. while not SharedLibFiles.Empty do
  375. begin
  376. s:=SharedLibFiles.GetFirst;
  377. if (s<>'c') or ReOrderEntries then
  378. begin
  379. i:=Pos(target_info.sharedlibext,s);
  380. if i>0 then
  381. Delete(s,i,length(s));
  382. result:=result+' '+maybequoted('-l'+s);
  383. end;
  384. { be sure that libc is the last lib }
  385. if not ReOrderEntries then
  386. begin
  387. result:=result+' -lc'
  388. end;
  389. end;
  390. while not FrameworkFiles.empty do
  391. begin
  392. result:=result+' -framework '+maybequoted(FrameworkFiles.GetFirst);
  393. end;
  394. end;
  395. Function tlinkerdarwin.WriteFileList: TCmdStr;
  396. Var
  397. FilesList : TScript;
  398. s : TCmdStr;
  399. begin
  400. if ReOrderEntries Then
  401. ExpandAndApplyOrder(SharedLibFiles);
  402. { main objectfiles and static libraries: in filelist file to avoid overflowing command line limit }
  403. result:=UniqueName(outputexedir+'linkfiles')+'.res';
  404. FilesList:=TScript.Create(result);
  405. while not ObjectFiles.Empty do
  406. begin
  407. s:=ObjectFiles.GetFirst;
  408. if s<>'' then
  409. begin
  410. s:=TargetFixFileName(s);
  411. FilesList.Add(s);
  412. end;
  413. { Write staticlibraries }
  414. while not StaticLibFiles.Empty do
  415. begin
  416. s:=StaticLibFiles.GetFirst;
  417. FilesList.Add(s)
  418. end;
  419. end;
  420. FilesList.writetodisk;
  421. FilesList.Free;
  422. end;
  423. function tlinkerdarwin.MakeExecutable:boolean;
  424. var
  425. binstr,
  426. cmdstr,
  427. mapstr,
  428. targetstr,
  429. extdbgbinstr,
  430. extdbgcmdstr,
  431. ltostr,
  432. ordersymfile,
  433. linkfiles: TCmdStr;
  434. GCSectionsStr,
  435. StaticStr,
  436. StripStr : TCmdStr;
  437. success : boolean;
  438. begin
  439. if not(cs_link_nolink in current_settings.globalswitches) then
  440. Message1(exec_i_linking,current_module.exefilename);
  441. { Create some replacements }
  442. StaticStr:='';
  443. StripStr:='';
  444. GCSectionsStr:='';
  445. mapstr:='';
  446. targetstr:='';
  447. ltostr:='';
  448. if (cs_link_map in current_settings.globalswitches) then
  449. mapstr:='-map '+maybequoted(ChangeFileExt(current_module.exefilename,'.map'));
  450. if (cs_link_staticflag in current_settings.globalswitches) then
  451. StaticStr:='-static';
  452. if (cs_link_strip in current_settings.globalswitches) then
  453. StripStr:='-x';
  454. if (cs_link_smart in current_settings.globalswitches) then
  455. GCSectionsStr:='-dead_strip -no_dead_strip_inits_and_terms';
  456. { add custom LTO library if using custom clang }
  457. if (cs_lto in current_settings.moduleswitches) and
  458. not(cs_link_on_target in current_settings.globalswitches) and
  459. (utilsdirectory<>'') and
  460. FileExists(utilsdirectory+'/../lib/libLTO.dylib',true) then
  461. begin
  462. ltostr:='-lto_library '+maybequoted(utilsdirectory+'/../lib/libLTO.dylib');
  463. end;
  464. { Write list of files to link }
  465. linkfiles:=WriteFileList;
  466. { Write symbol order file }
  467. ordersymfile:=WriteSymbolOrderFile;
  468. { Call linker }
  469. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  470. Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename));
  471. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  472. Replace(cmdstr,'$TARGET',targetstr);
  473. Replace(cmdstr,'$MAP',mapstr);
  474. Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
  475. Replace(cmdstr,'$LTO',ltostr);
  476. if ordersymfile<>'' then
  477. Replace(cmdstr,'$ORDERSYMS','-order_file '+maybequoted(ordersymfile))
  478. else
  479. Replace(cmdstr,'$ORDERSYMS','');
  480. Replace(cmdstr,'$STATIC',StaticStr);
  481. Replace(cmdstr,'$STRIP',StripStr);
  482. Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
  483. Replace(cmdstr,'$PRTOBJ',GetDarwinPrtobjName(false));
  484. Replace(cmdstr,'$ARCH', GetLinkArch);
  485. Replace(cmdstr,'$VERSION',GetLinkVersion);
  486. Replace(cmdstr,'$SYSROOT',GetSysroot);
  487. Replace(cmdstr,'$LIBSEARCHPATH',GetLibSearchPath);
  488. Replace(cmdstr,'$FILELIST','-filelist '+maybequoted(linkfiles));
  489. Replace(cmdstr,'$LIBRARIES',GetLibraries);
  490. BinStr:=FindUtil(utilsprefix+BinStr);
  491. { create dsym file? }
  492. extdbgbinstr:='';
  493. extdbgcmdstr:='';
  494. if (target_dbg.id in [dbg_dwarf2,dbg_dwarf3]) and
  495. (cs_link_separate_dbg_file in current_settings.globalswitches) then
  496. begin
  497. extdbgbinstr:=FindUtil(utilsprefix+'dsymutil');
  498. extdbgcmdstr:=maybequoted(current_module.exefilename);
  499. end;
  500. success:=DoExec(BinStr,CmdStr,true,false);
  501. if success and
  502. (extdbgbinstr<>'') then
  503. success:=DoExec(extdbgbinstr,extdbgcmdstr,false,false);
  504. { Remove ReponseFile }
  505. if (success) and not(cs_link_nolink in current_settings.globalswitches) then
  506. begin
  507. DeleteFile(outputexedir+Info.ResName);
  508. if ordersymfile<>'' then
  509. DeleteFile(ordersymfile);
  510. DeleteFile(linkfiles);
  511. end;
  512. { Post process }
  513. if success then
  514. success:=PostProcessExecutable(current_module.exefilename,false);
  515. MakeExecutable:=success; { otherwise a recursive call to link method }
  516. end;
  517. Function tlinkerdarwin.MakeSharedLibrary:boolean;
  518. var
  519. InitStr,
  520. FiniStr,
  521. binstr,
  522. cmdstr,
  523. mapstr,
  524. ltostr,
  525. ordersymfile,
  526. targetstr,
  527. extdbgbinstr,
  528. extdbgcmdstr,
  529. linkfiles,
  530. GCSectionsStr : TCmdStr;
  531. exportedsyms: text;
  532. success : boolean;
  533. begin
  534. MakeSharedLibrary:=false;
  535. GCSectionsStr:='';
  536. mapstr:='';
  537. ltostr:='';
  538. if not(cs_link_nolink in current_settings.globalswitches) then
  539. Message1(exec_i_linking,current_module.sharedlibfilename);
  540. { Write list of files to link }
  541. linkfiles:=WriteFileList;
  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. InitStr:='-init FPC_LIB_START';
  558. FiniStr:='-fini FPC_LIB_EXIT';
  559. { Call linker }
  560. SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
  561. Replace(cmdstr,'$EXE',maybequoted(ExpandFileName(current_module.sharedlibfilename)));
  562. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  563. Replace(cmdstr,'$TARGET',targetstr);
  564. Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
  565. Replace(cmdstr,'$INIT',InitStr);
  566. Replace(cmdstr,'$FINI',FiniStr);
  567. Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
  568. Replace(cmdstr,'$MAP',mapstr);
  569. Replace(cmdstr,'$LTO',ltostr);
  570. if ordersymfile<>'' then
  571. Replace(cmdstr,'$ORDERSYMS','-order_file '+maybequoted(ordersymfile))
  572. else
  573. Replace(cmdstr,'$ORDERSYMS','');
  574. Replace(cmdstr,'$PRTOBJ',GetDarwinPrtobjName(true));
  575. Replace(cmdstr,'$ARCH', GetLinkArch);
  576. Replace(cmdstr,'$VERSION',GetLinkVersion);
  577. Replace(cmdstr,'$SYSROOT',GetSysroot);
  578. Replace(cmdstr,'$LIBSEARCHPATH',GetLibSearchPath);
  579. Replace(cmdstr,'$FILELIST','-filelist '+maybequoted(linkfiles));
  580. Replace(cmdstr,'$LIBRARIES',GetLibraries);
  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. LinkSymsFileName:='';
  592. if not texportlibunix(exportlib).exportedsymnames.empty then
  593. begin
  594. LinkSymsFileName:=UniqueName('linksyms')+'.fpc';
  595. assign(exportedsyms,outputexedir+LinkSymsFileName);
  596. rewrite(exportedsyms);
  597. repeat
  598. writeln(exportedsyms,texportlibunix(exportlib).exportedsymnames.getfirst);
  599. until texportlibunix(exportlib).exportedsymnames.empty;
  600. close(exportedsyms);
  601. cmdstr:=cmdstr+' -exported_symbols_list '+maybequoted(outputexedir+LinkSymsFileName);
  602. end;
  603. success:=DoExec(BinStr,cmdstr,true,false);
  604. if (success and
  605. (extdbgbinstr<>'') and
  606. (cs_link_nolink in current_settings.globalswitches)) then
  607. success:=DoExec(extdbgbinstr,extdbgcmdstr,false,false);
  608. { Strip the library ? }
  609. if success and (cs_link_strip in current_settings.globalswitches) then
  610. begin
  611. SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
  612. Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename));
  613. success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,false,false);
  614. end;
  615. { Remove temporary files }
  616. if (success) and not(cs_link_nolink in current_settings.globalswitches) then
  617. begin
  618. DeleteFile(outputexedir+Info.ResName);
  619. if ordersymfile<>'' then
  620. DeleteFile(ordersymfile);
  621. if LinkSymsFileName<>'' then
  622. DeleteFile(outputexedir+LinkSymsFileName);
  623. DeleteFile(linkfiles);
  624. end;
  625. MakeSharedLibrary:=success; { otherwise a recursive call to link method }
  626. end;
  627. function TLinkerDarwin.postprocessexecutable(const fn : string;isdll:boolean):boolean;
  628. begin
  629. Result:=PostProcessMachExecutable(fn,isdll);
  630. end;
  631. {*****************************************************************************
  632. Initialize
  633. *****************************************************************************}
  634. initialization
  635. RegisterLinker(ld_darwin,tlinkerdarwin);
  636. {$ifdef x86_64}
  637. RegisterImport(system_x86_64_darwin,timportlibdarwin);
  638. RegisterExport(system_x86_64_darwin,texportlibdarwin);
  639. RegisterTarget(system_x86_64_darwin_info);
  640. RegisterImport(system_x86_64_iphonesim,timportlibdarwin);
  641. RegisterExport(system_x86_64_iphonesim,texportlibdarwin);
  642. RegisterTarget(system_x86_64_iphonesim_info);
  643. {$endif}
  644. {$ifdef i386}
  645. RegisterImport(system_i386_darwin,timportlibdarwin);
  646. RegisterExport(system_i386_darwin,texportlibdarwin);
  647. RegisterTarget(system_i386_darwin_info);
  648. RegisterImport(system_i386_iphonesim,timportlibdarwin);
  649. RegisterExport(system_i386_iphonesim,texportlibdarwin);
  650. RegisterTarget(system_i386_iphonesim_info);
  651. {$endif i386}
  652. {$ifdef powerpc}
  653. RegisterImport(system_powerpc_darwin,timportlibdarwin);
  654. RegisterExport(system_powerpc_darwin,texportlibdarwin);
  655. RegisterTarget(system_powerpc_darwin_info);
  656. {$endif powerpc}
  657. {$ifdef powerpc64}
  658. RegisterImport(system_powerpc64_darwin,timportlibdarwin);
  659. RegisterExport(system_powerpc64_darwin,texportlibdarwin);
  660. RegisterTarget(system_powerpc64_darwin_info);
  661. {$endif powerpc64}
  662. {$ifdef arm}
  663. RegisterImport(system_arm_ios,timportlibdarwin);
  664. RegisterExport(system_arm_ios,texportlibdarwin);
  665. RegisterTarget(system_arm_ios_info);
  666. {$endif arm}
  667. {$ifdef aarch64}
  668. RegisterImport(system_aarch64_ios,timportlibdarwin);
  669. RegisterExport(system_aarch64_ios,texportlibdarwin);
  670. RegisterTarget(system_aarch64_ios_info);
  671. RegisterImport(system_aarch64_darwin,timportlibdarwin);
  672. RegisterExport(system_aarch64_darwin,texportlibdarwin);
  673. RegisterTarget(system_aarch64_darwin_info);
  674. {$endif aarch64}
  675. RegisterRes(res_macho_info,TWinLikeResourceFile);
  676. RegisterRes(res_macosx_ext_info,TWinLikeResourceFile);
  677. end.