t_darwin.pas 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792
  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,triplet,
  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 $RPATH -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 $RPATH -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 $RPATH -dynamic -dylib -L. -o $EXE $ARCH $VERSION $SYSROOT $LIBSEARCHPATH $FILELIST $LIBRARIES'
  113. else
  114. DllCmd[1]:='ld $PRTOBJ $TARGET $OPT $GCSECTIONS $MAP $LTO $ORDERSYMS $RPATH -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 MacOSXVersionMin.relationto(10,8,0)>=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. (MacOSXVersionMin.relationto(10,6,0)>=0) then
  149. exit('crt1.10.6.o');
  150. if MacOSXVersionMin.relationto(10,5,0)>=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 iPhoneOSVersionMin.relationto(6,0,0)>=0 then
  161. exit('');
  162. if iPhoneOSVersionMin.relationto(3,1,0)>=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 iPhoneOSVersionMin.relationto(8,1,0)>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 MacOSXVersionMin.relationto(10,8,0)>=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 MacOSXVersionMin.relationto(10,6,0)>=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 iPhoneOSVersionMin.relationto(3,1,0)>=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 iPhoneOSVersionMin.relationto(8,1,0)>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 MacOSXVersionMin.relationto(10,6,0)>=0 then
  244. exit('');
  245. if MacOSXVersionMin.relationto(10,5,0)>=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 iPhoneOSVersionMin.relationto(3,1,0)>=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 iPhoneOSVersionMin.relationto(8,1,0)>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.isvalid then
  312. begin
  313. result:='-macosx_version_min '+MacOSXVersionMin.str;
  314. end
  315. else if iPhoneOSVersionMin.isvalid then
  316. begin
  317. if target_info.system in [system_i386_iphonesim,system_x86_64_iphonesim] then
  318. result:='-ios_simulator_version_min '+iPhoneOSVersionMin.str
  319. else
  320. result:='-iphoneos_version_min '+iPhoneOSVersionMin.str;
  321. end
  322. else
  323. begin
  324. internalerror(2022090920)
  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. asanstr,
  433. ordersymfile,
  434. linkfiles: TCmdStr;
  435. GCSectionsStr,
  436. StaticStr,
  437. StripStr,
  438. sanitizerLibraryDir: TCmdStr;
  439. success : boolean;
  440. begin
  441. if not(cs_link_nolink in current_settings.globalswitches) then
  442. Message1(exec_i_linking,current_module.exefilename);
  443. { Create some replacements }
  444. StaticStr:='';
  445. StripStr:='';
  446. GCSectionsStr:='';
  447. mapstr:='';
  448. targetstr:='';
  449. ltostr:='';
  450. if (cs_link_map in current_settings.globalswitches) then
  451. mapstr:='-map '+maybequoted(ChangeFileExt(current_module.exefilename,'.map'));
  452. if (cs_link_staticflag in current_settings.globalswitches) then
  453. StaticStr:='-static';
  454. if (cs_link_strip in current_settings.globalswitches) then
  455. StripStr:='-x';
  456. if (cs_link_smart in current_settings.globalswitches) then
  457. GCSectionsStr:='-dead_strip -no_dead_strip_inits_and_terms';
  458. { add custom LTO library if using custom clang }
  459. if (cs_lto in current_settings.moduleswitches) and
  460. not(cs_link_on_target in current_settings.globalswitches) and
  461. (utilsdirectory<>'') and
  462. FileExists(utilsdirectory+'/../lib/libLTO.dylib',false) then
  463. begin
  464. ltostr:='-lto_library '+maybequoted(utilsdirectory+'/../lib/libLTO.dylib');
  465. end;
  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. if AddSanitizerLibrariesAndGetSearchDir('darwin',sanitizerLibraryDir) then
  481. begin
  482. { also add the executable path as search path in case the asan
  483. library gets copied into the application bundle }
  484. Replace(cmdstr,'$RPATH','-rpath @executable_path -rpath '+maybequoted(sanitizerLibraryDir))
  485. end
  486. else
  487. begin
  488. Replace(cmdstr,'$RPATH','');
  489. end;
  490. { Write list of files to link }
  491. linkfiles:=WriteFileList;
  492. Replace(cmdstr,'$STATIC',StaticStr);
  493. Replace(cmdstr,'$STRIP',StripStr);
  494. Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
  495. Replace(cmdstr,'$PRTOBJ',GetDarwinPrtobjName(false));
  496. Replace(cmdstr,'$ARCH', GetLinkArch);
  497. Replace(cmdstr,'$VERSION',GetLinkVersion);
  498. Replace(cmdstr,'$SYSROOT',GetSysroot);
  499. Replace(cmdstr,'$LIBSEARCHPATH',GetLibSearchPath);
  500. Replace(cmdstr,'$FILELIST','-filelist '+maybequoted(linkfiles));
  501. Replace(cmdstr,'$LIBRARIES',GetLibraries);
  502. BinStr:=FindUtil(utilsprefix+BinStr);
  503. { create dsym file? }
  504. extdbgbinstr:='';
  505. extdbgcmdstr:='';
  506. if (target_dbg.id in [dbg_dwarf2,dbg_dwarf3,dbg_dwarf4]) and
  507. (cs_link_separate_dbg_file in current_settings.globalswitches) then
  508. begin
  509. extdbgbinstr:=FindUtil(utilsprefix+'dsymutil');
  510. extdbgcmdstr:=maybequoted(current_module.exefilename);
  511. end;
  512. success:=DoExec(BinStr,CmdStr,true,false);
  513. if success and
  514. (extdbgbinstr<>'') then
  515. success:=DoExec(extdbgbinstr,extdbgcmdstr,false,false);
  516. { Remove ReponseFile }
  517. if (success) and not(cs_link_nolink in current_settings.globalswitches) then
  518. begin
  519. DeleteFile(outputexedir+Info.ResName);
  520. if ordersymfile<>'' then
  521. DeleteFile(ordersymfile);
  522. DeleteFile(linkfiles);
  523. end;
  524. { Post process }
  525. if success and not(cs_link_nolink in current_settings.globalswitches) then
  526. success:=PostProcessExecutable(current_module.exefilename,false);
  527. MakeExecutable:=success; { otherwise a recursive call to link method }
  528. end;
  529. function tlinkerdarwin.MakeSharedLibrary: boolean;
  530. var
  531. InitStr,
  532. FiniStr,
  533. binstr,
  534. cmdstr,
  535. mapstr,
  536. ltostr,
  537. ordersymfile,
  538. targetstr,
  539. extdbgbinstr,
  540. extdbgcmdstr,
  541. linkfiles,
  542. GCSectionsStr,
  543. sanitizerLibraryDir: TCmdStr;
  544. exportedsyms: text;
  545. success : boolean;
  546. begin
  547. MakeSharedLibrary:=false;
  548. GCSectionsStr:='';
  549. mapstr:='';
  550. ltostr:='';
  551. if not(cs_link_nolink in current_settings.globalswitches) then
  552. Message1(exec_i_linking,current_module.sharedlibfilename);
  553. { Write symbol order file }
  554. ordersymfile:=WriteSymbolOrderFile;
  555. if (cs_link_smart in current_settings.globalswitches) then
  556. GCSectionsStr:='-dead_strip -no_dead_strip_inits_and_terms';
  557. if (cs_link_map in current_settings.globalswitches) then
  558. mapstr:='-map '+maybequoted(ChangeFileExt(current_module.sharedlibfilename,'.map'));
  559. { add custom LTO library if using custom clang }
  560. if (cs_lto in current_settings.moduleswitches) and
  561. not(cs_link_on_target in current_settings.globalswitches) and
  562. (utilsdirectory<>'') and
  563. FileExists(utilsdirectory+'/../lib/libLTO.dylib',false) then
  564. begin
  565. ltostr:='-lto_library '+maybequoted(utilsdirectory+'/../lib/libLTO.dylib');
  566. end;
  567. targetstr:='';
  568. InitStr:='-init FPC_LIB_START';
  569. FiniStr:='-fini FPC_LIB_EXIT';
  570. { Call linker }
  571. SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
  572. Replace(cmdstr,'$EXE',maybequoted(ExpandFileName(current_module.sharedlibfilename)));
  573. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  574. Replace(cmdstr,'$TARGET',targetstr);
  575. Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
  576. Replace(cmdstr,'$INIT',InitStr);
  577. Replace(cmdstr,'$FINI',FiniStr);
  578. Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
  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. { add asan library if known }
  586. if AddSanitizerLibrariesAndGetSearchDir('darwin',sanitizerLibraryDir) then
  587. begin
  588. { also add the executable path as search path in case the asan
  589. library gets copied into the application bundle }
  590. Replace(cmdstr,'$RPATH','-rpath @executable_path -rpath '+maybequoted(sanitizerLibraryDir))
  591. end
  592. else
  593. begin
  594. Replace(cmdstr,'$RPATH','');
  595. end;
  596. { Write list of files to link }
  597. linkfiles:=WriteFileList;
  598. Replace(cmdstr,'$PRTOBJ',GetDarwinPrtobjName(true));
  599. Replace(cmdstr,'$ARCH', GetLinkArch);
  600. Replace(cmdstr,'$VERSION',GetLinkVersion);
  601. Replace(cmdstr,'$SYSROOT',GetSysroot);
  602. Replace(cmdstr,'$LIBSEARCHPATH',GetLibSearchPath);
  603. Replace(cmdstr,'$FILELIST','-filelist '+maybequoted(linkfiles));
  604. Replace(cmdstr,'$LIBRARIES',GetLibraries);
  605. BinStr:=FindUtil(utilsprefix+BinStr);
  606. { create dsym file? }
  607. extdbgbinstr:='';
  608. extdbgcmdstr:='';
  609. if (target_dbg.id in [dbg_dwarf2,dbg_dwarf3,dbg_dwarf4]) and
  610. (cs_link_separate_dbg_file in current_settings.globalswitches) then
  611. begin
  612. extdbgbinstr:=FindUtil(utilsprefix+'dsymutil');
  613. extdbgcmdstr:=maybequoted(current_module.sharedlibfilename);
  614. end;
  615. LinkSymsFileName:='';
  616. if not texportlibunix(exportlib).exportedsymnames.empty then
  617. begin
  618. LinkSymsFileName:=UniqueName('linksyms')+'.fpc';
  619. assign(exportedsyms,outputexedir+LinkSymsFileName);
  620. rewrite(exportedsyms);
  621. repeat
  622. writeln(exportedsyms,texportlibunix(exportlib).exportedsymnames.getfirst);
  623. until texportlibunix(exportlib).exportedsymnames.empty;
  624. close(exportedsyms);
  625. cmdstr:=cmdstr+' -exported_symbols_list '+maybequoted(outputexedir+LinkSymsFileName);
  626. end;
  627. success:=DoExec(BinStr,cmdstr,true,false);
  628. if (success and
  629. (extdbgbinstr<>'') and
  630. (cs_link_nolink in current_settings.globalswitches)) then
  631. success:=DoExec(extdbgbinstr,extdbgcmdstr,false,false);
  632. { Strip the library ? }
  633. if success and (cs_link_strip in current_settings.globalswitches) then
  634. begin
  635. SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
  636. Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename));
  637. success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,false,false);
  638. end;
  639. { Remove temporary files }
  640. if (success) and not(cs_link_nolink in current_settings.globalswitches) then
  641. begin
  642. DeleteFile(outputexedir+Info.ResName);
  643. if ordersymfile<>'' then
  644. DeleteFile(ordersymfile);
  645. if LinkSymsFileName<>'' then
  646. DeleteFile(outputexedir+LinkSymsFileName);
  647. DeleteFile(linkfiles);
  648. end;
  649. MakeSharedLibrary:=success; { otherwise a recursive call to link method }
  650. end;
  651. function TLinkerDarwin.postprocessexecutable(const fn : string;isdll:boolean):boolean;
  652. begin
  653. Result:=PostProcessMachExecutable(fn,isdll);
  654. end;
  655. {*****************************************************************************
  656. Initialize
  657. *****************************************************************************}
  658. initialization
  659. RegisterLinker(ld_darwin,tlinkerdarwin);
  660. {$ifdef x86_64}
  661. RegisterImport(system_x86_64_darwin,timportlibdarwin);
  662. RegisterExport(system_x86_64_darwin,texportlibdarwin);
  663. RegisterTarget(system_x86_64_darwin_info);
  664. RegisterImport(system_x86_64_iphonesim,timportlibdarwin);
  665. RegisterExport(system_x86_64_iphonesim,texportlibdarwin);
  666. RegisterTarget(system_x86_64_iphonesim_info);
  667. {$endif}
  668. {$ifdef i386}
  669. RegisterImport(system_i386_darwin,timportlibdarwin);
  670. RegisterExport(system_i386_darwin,texportlibdarwin);
  671. RegisterTarget(system_i386_darwin_info);
  672. RegisterImport(system_i386_iphonesim,timportlibdarwin);
  673. RegisterExport(system_i386_iphonesim,texportlibdarwin);
  674. RegisterTarget(system_i386_iphonesim_info);
  675. {$endif i386}
  676. {$ifdef powerpc}
  677. RegisterImport(system_powerpc_darwin,timportlibdarwin);
  678. RegisterExport(system_powerpc_darwin,texportlibdarwin);
  679. RegisterTarget(system_powerpc_darwin_info);
  680. {$endif powerpc}
  681. {$ifdef powerpc64}
  682. RegisterImport(system_powerpc64_darwin,timportlibdarwin);
  683. RegisterExport(system_powerpc64_darwin,texportlibdarwin);
  684. RegisterTarget(system_powerpc64_darwin_info);
  685. {$endif powerpc64}
  686. {$ifdef arm}
  687. RegisterImport(system_arm_ios,timportlibdarwin);
  688. RegisterExport(system_arm_ios,texportlibdarwin);
  689. RegisterTarget(system_arm_ios_info);
  690. {$endif arm}
  691. {$ifdef aarch64}
  692. RegisterImport(system_aarch64_ios,timportlibdarwin);
  693. RegisterExport(system_aarch64_ios,texportlibdarwin);
  694. RegisterTarget(system_aarch64_ios_info);
  695. RegisterImport(system_aarch64_darwin,timportlibdarwin);
  696. RegisterExport(system_aarch64_darwin,texportlibdarwin);
  697. RegisterTarget(system_aarch64_darwin_info);
  698. {$endif aarch64}
  699. RegisterRes(res_macho_info,TWinLikeResourceFile);
  700. RegisterRes(res_macosx_ext_info,TWinLikeResourceFile);
  701. end.