t_darwin.pas 28 KB

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