t_darwin.pas 29 KB

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