link.pas 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352
  1. {
  2. Copyright (c) 1998-2002 by Peter Vreman
  3. This unit handles the linker and binder calls for programs and
  4. libraries
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit link;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. sysutils,
  23. cclasses,
  24. systems,
  25. fmodule,
  26. globtype,
  27. ogbase;
  28. Type
  29. TLinkerInfo=record
  30. ExeCmd,
  31. DllCmd,
  32. ExtDbgCmd : array[1..3] of string;
  33. ResName : string[100];
  34. ScriptName : string[100];
  35. ExtraOptions : TCmdStr;
  36. DynamicLinker : string[100];
  37. end;
  38. TLinker = class(TAbstractLinker)
  39. public
  40. HasResources,
  41. HasExports : boolean;
  42. SysInitUnit : string[20];
  43. ObjectFiles,
  44. SharedLibFiles,
  45. StaticLibFiles,
  46. FrameworkFiles : TCmdStrList;
  47. Constructor Create;virtual;
  48. Destructor Destroy;override;
  49. procedure AddModuleFiles(hp:tmodule);
  50. Procedure AddObject(const S,unitpath : TCmdStr;isunit:boolean);
  51. Procedure AddStaticLibrary(const S : TCmdStr);
  52. Procedure AddSharedLibrary(S : TCmdStr);
  53. Procedure AddStaticCLibrary(const S : TCmdStr);
  54. Procedure AddSharedCLibrary(S : TCmdStr);
  55. Procedure AddFramework(S : TCmdStr);
  56. procedure AddImportSymbol(const libname,symname,symmangledname:TCmdStr;OrdNr: longint;isvar:boolean);virtual;
  57. Procedure InitSysInitUnitName;virtual;
  58. Function MakeExecutable:boolean;virtual;
  59. Function MakeSharedLibrary:boolean;virtual;
  60. Function MakeStaticLibrary:boolean;virtual;
  61. procedure ExpandAndApplyOrder(var Src:TCmdStrList);
  62. procedure LoadPredefinedLibraryOrder;virtual;
  63. function ReOrderEntries : boolean;
  64. end;
  65. TExternalLinker = class(TLinker)
  66. public
  67. Info : TLinkerInfo;
  68. Constructor Create;override;
  69. Destructor Destroy;override;
  70. Function FindUtil(const s:TCmdStr):TCmdStr;
  71. Function DoExec(const command:TCmdStr; para:TCmdStr;showinfo,useshell:boolean):boolean;
  72. procedure SetDefaultInfo;virtual;
  73. Function MakeStaticLibrary:boolean;override;
  74. end;
  75. TBooleanArray = array [1..1024] of boolean;
  76. PBooleanArray = ^TBooleanArray;
  77. TInternalLinker = class(TLinker)
  78. private
  79. FCExeOutput : TExeOutputClass;
  80. FCObjInput : TObjInputClass;
  81. { Libraries }
  82. FStaticLibraryList : TFPHashObjectList;
  83. FImportLibraryList : TFPHashObjectList;
  84. procedure Load_ReadObject(const para:TCmdStr);
  85. procedure Load_ReadStaticLibrary(const para:TCmdStr);
  86. procedure ParseScript_Handle;
  87. procedure ParseScript_PostCheck;
  88. procedure ParseScript_Load;
  89. procedure ParseScript_Order;
  90. procedure ParseScript_MemPos;
  91. procedure ParseScript_DataPos;
  92. procedure PrintLinkerScript;
  93. function RunLinkScript(const outputname:TCmdStr):boolean;
  94. protected
  95. linkscript : TCmdStrList;
  96. ScriptCount : longint;
  97. IsHandled : PBooleanArray;
  98. property CObjInput:TObjInputClass read FCObjInput write FCObjInput;
  99. property CExeOutput:TExeOutputClass read FCExeOutput write FCExeOutput;
  100. property StaticLibraryList:TFPHashObjectList read FStaticLibraryList;
  101. property ImportLibraryList:TFPHashObjectList read FImportLibraryList;
  102. procedure DefaultLinkScript;virtual;abstract;
  103. public
  104. IsSharedLibrary : boolean;
  105. UseStabs : boolean;
  106. Constructor Create;override;
  107. Destructor Destroy;override;
  108. Function MakeExecutable:boolean;override;
  109. Function MakeSharedLibrary:boolean;override;
  110. procedure AddImportSymbol(const libname,symname,symmangledname:TCmdStr;OrdNr: longint;isvar:boolean);override;
  111. end;
  112. var
  113. Linker : TLinker;
  114. function FindObjectFile(s : TCmdStr;const unitpath:TCmdStr;isunit:boolean) : TCmdStr;
  115. function FindLibraryFile(s:TCmdStr;const prefix,ext:TCmdStr;var foundfile : TCmdStr) : boolean;
  116. function FindDLL(const s:TCmdStr;var founddll:TCmdStr):boolean;
  117. procedure InitLinker;
  118. procedure DoneLinker;
  119. Implementation
  120. uses
  121. cutils,cfileutl,cstreams,
  122. script,globals,verbose,comphook,ppu,fpccrc,
  123. aasmbase,aasmtai,aasmdata,aasmcpu,
  124. owbase,owar,ogmap;
  125. type
  126. TLinkerClass = class of Tlinker;
  127. {*****************************************************************************
  128. Helpers
  129. *****************************************************************************}
  130. function GetFileCRC(const fn:string):cardinal;
  131. var
  132. fs : TCStream;
  133. bufcount,
  134. bufsize : Integer;
  135. buf : pbyte;
  136. begin
  137. result:=0;
  138. bufsize:=64*1024;
  139. fs:=CFileStreamClass.Create(fn,fmOpenRead or fmShareDenyNone);
  140. if CStreamError<>0 then
  141. begin
  142. fs.Free;
  143. Comment(V_Error,'Can''t open file: '+fn);
  144. exit;
  145. end;
  146. getmem(buf,bufsize);
  147. repeat
  148. bufcount:=fs.Read(buf^,bufsize);
  149. result:=UpdateCrc32(result,buf^,bufcount);
  150. until bufcount<bufsize;
  151. freemem(buf);
  152. fs.Free;
  153. end;
  154. { searches an object file }
  155. function FindObjectFile(s:TCmdStr;const unitpath:TCmdStr;isunit:boolean) : TCmdStr;
  156. var
  157. found : boolean;
  158. foundfile : TCmdStr;
  159. begin
  160. findobjectfile:='';
  161. if s='' then
  162. exit;
  163. {When linking on target, the units has not been assembled yet,
  164. so there is no object files to look for at
  165. the host. Look for the corresponding assembler file instead,
  166. because it will be assembled to object file on the target.}
  167. if isunit and (cs_link_on_target in current_settings.globalswitches) then
  168. s:=ChangeFileExt(s,target_info.asmext);
  169. { when it does not belong to the unit then check if
  170. the specified file exists without searching any paths }
  171. if not isunit then
  172. begin
  173. if FileExists(FixFileName(s),false) then
  174. begin
  175. foundfile:=ScriptFixFileName(s);
  176. found:=true;
  177. end;
  178. end;
  179. if pos('.',s)=0 then
  180. s:=s+target_info.objext;
  181. { find object file
  182. 1. output unit path
  183. 2. output exe path
  184. 3. specified unit path (if specified)
  185. 4. cwd
  186. 5. unit search path
  187. 6. local object path
  188. 7. global object path
  189. 8. exepath (not when linking on target)
  190. for all finds don't use the directory caching }
  191. found:=false;
  192. if isunit and (OutputUnitDir<>'') then
  193. found:=FindFile(s,OutPutUnitDir,false,foundfile)
  194. else
  195. if OutputExeDir<>'' then
  196. found:=FindFile(s,OutPutExeDir,false,foundfile);
  197. if (not found) and (unitpath<>'') then
  198. found:=FindFile(s,unitpath,false,foundfile);
  199. if (not found) then
  200. found:=FindFile(s, CurDirRelPath(source_info),false,foundfile);
  201. if (not found) then
  202. found:=UnitSearchPath.FindFile(s,false,foundfile);
  203. if (not found) then
  204. found:=current_module.localobjectsearchpath.FindFile(s,false,foundfile);
  205. if (not found) then
  206. found:=objectsearchpath.FindFile(s,false,foundfile);
  207. if not(cs_link_on_target in current_settings.globalswitches) and (not found) then
  208. found:=FindFile(s,exepath,false,foundfile);
  209. if not(cs_link_nolink in current_settings.globalswitches) and (not found) then
  210. Message1(exec_w_objfile_not_found,s);
  211. {Restore file extension}
  212. if isunit and (cs_link_on_target in current_settings.globalswitches) then
  213. foundfile:= ChangeFileExt(foundfile,target_info.objext);
  214. findobjectfile:=ScriptFixFileName(foundfile);
  215. end;
  216. { searches a (windows) DLL file }
  217. function FindDLL(const s:TCmdStr;var founddll:TCmdStr):boolean;
  218. var
  219. sysdir : TCmdStr;
  220. Found : boolean;
  221. begin
  222. Found:=false;
  223. { Look for DLL in:
  224. 1. Current dir
  225. 2. Library Path
  226. 3. windir,windir/system,windir/system32 }
  227. Found:=FindFile(s,'.'+source_info.DirSep,false,founddll);
  228. if (not found) then
  229. Found:=librarysearchpath.FindFile(s,false,founddll);
  230. { when cross compiling, it is pretty useless to search windir etc. for dlls }
  231. if (not found) and (source_info.system=target_info.system) then
  232. begin
  233. sysdir:=FixPath(GetEnvironmentVariable('windir'),false);
  234. Found:=FindFile(s,sysdir+';'+sysdir+'system'+source_info.DirSep+';'+sysdir+'system32'+source_info.DirSep,false,founddll);
  235. end;
  236. if (not found) then
  237. begin
  238. message1(exec_w_libfile_not_found,s);
  239. FoundDll:=s;
  240. end;
  241. FindDll:=Found;
  242. end;
  243. { searches an library file }
  244. function FindLibraryFile(s:TCmdStr;const prefix,ext:TCmdStr;var foundfile : TCmdStr) : boolean;
  245. var
  246. found : boolean;
  247. paths : TCmdStr;
  248. begin
  249. findlibraryfile:=false;
  250. foundfile:=s;
  251. if s='' then
  252. exit;
  253. { split path from filename }
  254. paths:=ExtractFilePath(s);
  255. s:=ExtractFileName(s);
  256. { add prefix 'lib' }
  257. if (prefix<>'') and (Copy(s,1,length(prefix))<>prefix) then
  258. s:=prefix+s;
  259. { add extension }
  260. if (ext<>'') and (Copy(s,length(s)-length(ext)+1,length(ext))<>ext) then
  261. s:=s+ext;
  262. { readd the split path }
  263. s:=paths+s;
  264. if FileExists(s,false) then
  265. begin
  266. foundfile:=ScriptFixFileName(s);
  267. FindLibraryFile:=true;
  268. exit;
  269. end;
  270. { find libary
  271. 1. cwd
  272. 2. local libary dir
  273. 3. global libary dir
  274. 4. exe path of the compiler (not when linking on target)
  275. for all searches don't use the directory cache }
  276. found:=FindFile(s, CurDirRelPath(source_info), false,foundfile);
  277. if (not found) and (current_module.outputpath^<>'') then
  278. found:=FindFile(s,current_module.outputpath^,false,foundfile);
  279. if (not found) then
  280. found:=current_module.locallibrarysearchpath.FindFile(s,false,foundfile);
  281. if (not found) then
  282. found:=librarysearchpath.FindFile(s,false,foundfile);
  283. if not(cs_link_on_target in current_settings.globalswitches) and (not found) then
  284. found:=FindFile(s,exepath,false,foundfile);
  285. foundfile:=ScriptFixFileName(foundfile);
  286. findlibraryfile:=found;
  287. end;
  288. {*****************************************************************************
  289. TLINKER
  290. *****************************************************************************}
  291. Constructor TLinker.Create;
  292. begin
  293. Inherited Create;
  294. ObjectFiles:=TCmdStrList.Create_no_double;
  295. SharedLibFiles:=TCmdStrList.Create_no_double;
  296. StaticLibFiles:=TCmdStrList.Create_no_double;
  297. FrameworkFiles:=TCmdStrList.Create_no_double;
  298. end;
  299. Destructor TLinker.Destroy;
  300. begin
  301. ObjectFiles.Free;
  302. SharedLibFiles.Free;
  303. StaticLibFiles.Free;
  304. FrameworkFiles.Free;
  305. end;
  306. procedure TLinker.AddModuleFiles(hp:tmodule);
  307. var
  308. mask : longint;
  309. i,j : longint;
  310. ImportLibrary : TImportLibrary;
  311. ImportSymbol : TImportSymbol;
  312. begin
  313. with hp do
  314. begin
  315. if (flags and uf_has_resourcefiles)<>0 then
  316. HasResources:=true;
  317. if (flags and uf_has_exports)<>0 then
  318. HasExports:=true;
  319. { link unit files }
  320. if (flags and uf_no_link)=0 then
  321. begin
  322. { create mask which unit files need linking }
  323. mask:=link_always;
  324. { static linking ? }
  325. if (cs_link_static in current_settings.globalswitches) then
  326. begin
  327. if (flags and uf_static_linked)=0 then
  328. begin
  329. { if smart not avail then try static linking }
  330. if (flags and uf_smart_linked)<>0 then
  331. begin
  332. Message1(exec_t_unit_not_static_linkable_switch_to_smart,modulename^);
  333. mask:=mask or link_smart;
  334. end
  335. else
  336. Message1(exec_e_unit_not_smart_or_static_linkable,modulename^);
  337. end
  338. else
  339. mask:=mask or link_static;
  340. end;
  341. { smart linking ? }
  342. if (cs_link_smart in current_settings.globalswitches) then
  343. begin
  344. if (flags and uf_smart_linked)=0 then
  345. begin
  346. { if smart not avail then try static linking }
  347. if (flags and uf_static_linked)<>0 then
  348. begin
  349. { if not create_smartlink_library, then smart linking happens using the
  350. regular object files
  351. }
  352. if create_smartlink_library then
  353. Message1(exec_t_unit_not_smart_linkable_switch_to_static,modulename^);
  354. mask:=mask or link_static;
  355. end
  356. else
  357. Message1(exec_e_unit_not_smart_or_static_linkable,modulename^);
  358. end
  359. else
  360. mask:=mask or link_smart;
  361. end;
  362. { shared linking }
  363. if (cs_link_shared in current_settings.globalswitches) then
  364. begin
  365. if (flags and uf_shared_linked)=0 then
  366. begin
  367. { if shared not avail then try static linking }
  368. if (flags and uf_static_linked)<>0 then
  369. begin
  370. Message1(exec_t_unit_not_shared_linkable_switch_to_static,modulename^);
  371. mask:=mask or link_static;
  372. end
  373. else
  374. Message1(exec_e_unit_not_shared_or_static_linkable,modulename^);
  375. end
  376. else
  377. mask:=mask or link_shared;
  378. end;
  379. { unit files }
  380. while not linkunitofiles.empty do
  381. AddObject(linkunitofiles.getusemask(mask),path^,true);
  382. while not linkunitstaticlibs.empty do
  383. AddStaticLibrary(linkunitstaticlibs.getusemask(mask));
  384. while not linkunitsharedlibs.empty do
  385. AddSharedLibrary(linkunitsharedlibs.getusemask(mask));
  386. end;
  387. { Other needed .o and libs, specified using $L,$LINKLIB,external }
  388. mask:=link_always;
  389. while not linkotherofiles.empty do
  390. AddObject(linkotherofiles.Getusemask(mask),path^,false);
  391. while not linkotherstaticlibs.empty do
  392. AddStaticCLibrary(linkotherstaticlibs.Getusemask(mask));
  393. while not linkothersharedlibs.empty do
  394. AddSharedCLibrary(linkothersharedlibs.Getusemask(mask));
  395. while not linkotherframeworks.empty do
  396. AddFramework(linkotherframeworks.Getusemask(mask));
  397. { Known Library/DLL Imports }
  398. for i:=0 to ImportLibraryList.Count-1 do
  399. begin
  400. ImportLibrary:=TImportLibrary(ImportLibraryList[i]);
  401. for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
  402. begin
  403. ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
  404. AddImportSymbol(ImportLibrary.Name,ImportSymbol.Name,
  405. ImportSymbol.MangledName,ImportSymbol.OrdNr,ImportSymbol.IsVar);
  406. end;
  407. end;
  408. end;
  409. end;
  410. procedure TLinker.AddImportSymbol(const libname,symname,symmangledname:TCmdStr;OrdNr: longint;isvar:boolean);
  411. begin
  412. end;
  413. Procedure TLinker.AddObject(const S,unitpath : TCmdStr;isunit:boolean);
  414. begin
  415. ObjectFiles.Concat(FindObjectFile(s,unitpath,isunit));
  416. end;
  417. Procedure TLinker.AddSharedLibrary(S:TCmdStr);
  418. begin
  419. if s='' then
  420. exit;
  421. { remove prefix 'lib' }
  422. if Copy(s,1,length(target_info.sharedlibprefix))=target_info.sharedlibprefix then
  423. Delete(s,1,length(target_info.sharedlibprefix));
  424. { remove extension if any }
  425. if Copy(s,length(s)-length(target_info.sharedlibext)+1,length(target_info.sharedlibext))=target_info.sharedlibext then
  426. Delete(s,length(s)-length(target_info.sharedlibext)+1,length(target_info.sharedlibext)+1);
  427. { ready to be added }
  428. SharedLibFiles.Concat(S);
  429. end;
  430. Procedure TLinker.AddStaticLibrary(const S:TCmdStr);
  431. var
  432. ns : TCmdStr;
  433. found : boolean;
  434. begin
  435. if s='' then
  436. exit;
  437. found:=FindLibraryFile(s,target_info.staticlibprefix,target_info.staticlibext,ns);
  438. if not(cs_link_nolink in current_settings.globalswitches) and (not found) then
  439. Message1(exec_w_libfile_not_found,s);
  440. StaticLibFiles.Concat(ns);
  441. end;
  442. Procedure TLinker.AddSharedCLibrary(S:TCmdStr);
  443. begin
  444. if s='' then
  445. exit;
  446. { remove prefix 'lib' }
  447. if Copy(s,1,length(target_info.sharedclibprefix))=target_info.sharedclibprefix then
  448. Delete(s,1,length(target_info.sharedclibprefix));
  449. { remove extension if any }
  450. if Copy(s,length(s)-length(target_info.sharedclibext)+1,length(target_info.sharedclibext))=target_info.sharedclibext then
  451. Delete(s,length(s)-length(target_info.sharedclibext)+1,length(target_info.sharedclibext)+1);
  452. { ready to be added }
  453. SharedLibFiles.Concat(S);
  454. end;
  455. Procedure TLinker.AddFramework(S:TCmdStr);
  456. begin
  457. if s='' then
  458. exit;
  459. { ready to be added }
  460. FrameworkFiles.Concat(S);
  461. end;
  462. Procedure TLinker.AddStaticCLibrary(const S:TCmdStr);
  463. var
  464. ns : TCmdStr;
  465. found : boolean;
  466. begin
  467. if s='' then
  468. exit;
  469. found:=FindLibraryFile(s,target_info.staticclibprefix,target_info.staticclibext,ns);
  470. if not(cs_link_nolink in current_settings.globalswitches) and (not found) then
  471. Message1(exec_w_libfile_not_found,s);
  472. StaticLibFiles.Concat(ns);
  473. end;
  474. procedure AddImportSymbol(const libname,symname,symmangledname:TCmdStr;OrdNr: longint;isvar:boolean);
  475. begin
  476. end;
  477. procedure TLinker.InitSysInitUnitName;
  478. begin
  479. end;
  480. function TLinker.MakeExecutable:boolean;
  481. begin
  482. MakeExecutable:=false;
  483. Message(exec_e_exe_not_supported);
  484. end;
  485. Function TLinker.MakeSharedLibrary:boolean;
  486. begin
  487. MakeSharedLibrary:=false;
  488. Message(exec_e_dll_not_supported);
  489. end;
  490. Function TLinker.MakeStaticLibrary:boolean;
  491. begin
  492. MakeStaticLibrary:=false;
  493. Message(exec_e_dll_not_supported);
  494. end;
  495. Procedure TLinker.ExpandAndApplyOrder(var Src:TCmdStrList);
  496. var
  497. p : TLinkStrMap;
  498. i : longint;
  499. begin
  500. // call Virtual TLinker method to initialize
  501. LoadPredefinedLibraryOrder;
  502. // something to do?
  503. if (LinkLibraryAliases.count=0) and (LinkLibraryOrder.Count=0) Then
  504. exit;
  505. p:=TLinkStrMap.Create;
  506. // expand libaliases, clears src
  507. LinkLibraryAliases.expand(src,p);
  508. // writeln(src.count,' ',p.count,' ',linklibraryorder.count,' ',linklibraryaliases.count);
  509. // apply order
  510. p.UpdateWeights(LinkLibraryOrder);
  511. p.SortOnWeight;
  512. // put back in src
  513. for i:=0 to p.count-1 do
  514. src.insert(p[i].Key);
  515. p.free;
  516. end;
  517. procedure TLinker.LoadPredefinedLibraryOrder;
  518. begin
  519. end;
  520. function TLinker.ReOrderEntries : boolean;
  521. begin
  522. result:=(LinkLibraryOrder.count>0) or (LinkLibraryAliases.count>0);
  523. end;
  524. {*****************************************************************************
  525. TEXTERNALLINKER
  526. *****************************************************************************}
  527. Constructor TExternalLinker.Create;
  528. begin
  529. inherited Create;
  530. { set generic defaults }
  531. FillChar(Info,sizeof(Info),0);
  532. if cs_link_on_target in current_settings.globalswitches then
  533. begin
  534. Info.ResName:=outputexedir+ChangeFileExt(inputfilename,'_link.res');
  535. Info.ScriptName:=outputexedir+ChangeFileExt(inputfilename,'_script.res');
  536. end
  537. else
  538. begin
  539. Info.ResName:='link.res';
  540. Info.ScriptName:='script.res';
  541. end;
  542. { set the linker specific defaults }
  543. SetDefaultInfo;
  544. { Allow Parameter overrides for linker info }
  545. with Info do
  546. begin
  547. if ParaLinkOptions<>'' then
  548. ExtraOptions:=ParaLinkOptions;
  549. if ParaDynamicLinker<>'' then
  550. DynamicLinker:=ParaDynamicLinker;
  551. end;
  552. end;
  553. Destructor TExternalLinker.Destroy;
  554. begin
  555. inherited destroy;
  556. end;
  557. Procedure TExternalLinker.SetDefaultInfo;
  558. begin
  559. end;
  560. Function TExternalLinker.FindUtil(const s:TCmdStr):TCmdStr;
  561. var
  562. Found : boolean;
  563. FoundBin : TCmdStr;
  564. UtilExe : TCmdStr;
  565. begin
  566. if cs_link_on_target in current_settings.globalswitches then
  567. begin
  568. { If linking on target, don't add any path PM }
  569. FindUtil:=ChangeFileExt(s,target_info.exeext);
  570. exit;
  571. end;
  572. UtilExe:=ChangeFileExt(s,source_info.exeext);
  573. FoundBin:='';
  574. Found:=false;
  575. if utilsdirectory<>'' then
  576. Found:=FindFile(utilexe,utilsdirectory,false,Foundbin);
  577. if (not Found) then
  578. Found:=FindExe(utilexe,false,Foundbin);
  579. if (not Found) and not(cs_link_nolink in current_settings.globalswitches) then
  580. begin
  581. Message1(exec_e_util_not_found,utilexe);
  582. current_settings.globalswitches:=current_settings.globalswitches+[cs_link_nolink];
  583. end;
  584. if (FoundBin<>'') then
  585. Message1(exec_t_using_util,FoundBin);
  586. FindUtil:=FoundBin;
  587. end;
  588. Function TExternalLinker.DoExec(const command:TCmdStr; para:TCmdStr;showinfo,useshell:boolean):boolean;
  589. var
  590. exitcode: longint;
  591. begin
  592. DoExec:=true;
  593. if not(cs_link_nolink in current_settings.globalswitches) then
  594. begin
  595. FlushOutput;
  596. if useshell then
  597. exitcode:=shell(maybequoted(command)+' '+para)
  598. else
  599. try
  600. exitcode:=ExecuteProcess(command,para);
  601. except on E:EOSError do
  602. begin
  603. Message(exec_e_cant_call_linker);
  604. current_settings.globalswitches:=current_settings.globalswitches+[cs_link_nolink];
  605. DoExec:=false;
  606. end;
  607. end;
  608. if (exitcode<>0) then
  609. begin
  610. Message(exec_e_error_while_linking);
  611. current_settings.globalswitches:=current_settings.globalswitches+[cs_link_nolink];
  612. DoExec:=false;
  613. end;
  614. end;
  615. { Update asmres when externmode is set }
  616. if cs_link_nolink in current_settings.globalswitches then
  617. begin
  618. if showinfo then
  619. begin
  620. if DLLsource then
  621. AsmRes.AddLinkCommand(Command,Para,current_module.sharedlibfilename^)
  622. else
  623. AsmRes.AddLinkCommand(Command,Para,current_module.exefilename^);
  624. end
  625. else
  626. AsmRes.AddLinkCommand(Command,Para,'');
  627. end;
  628. end;
  629. Function TExternalLinker.MakeStaticLibrary:boolean;
  630. function GetNextFiles(const maxCmdLength : Longint; var item : TCmdStrListItem) : TCmdStr;
  631. begin
  632. result := '';
  633. while (assigned(item) and ((length(result) + length(item.str) + 1) < maxCmdLength)) do begin
  634. result := result + ' ' + item.str;
  635. item := TCmdStrListItem(item.next);
  636. end;
  637. end;
  638. var
  639. binstr, scriptfile : TCmdStr;
  640. cmdstr, nextcmd, smartpath : TCmdStr;
  641. current : TCmdStrListItem;
  642. script: Text;
  643. scripted_ar : boolean;
  644. success : boolean;
  645. begin
  646. MakeStaticLibrary:=false;
  647. { remove the library, to be sure that it is rewritten }
  648. DeleteFile(current_module.staticlibfilename^);
  649. { Call AR }
  650. smartpath:=FixPath(ChangeFileExt(current_module.asmfilename^,target_info.smartext),false);
  651. SplitBinCmd(target_ar.arcmd,binstr,cmdstr);
  652. binstr := FindUtil(utilsprefix + binstr);
  653. scripted_ar:=target_ar.id=ar_gnu_ar_scripted;
  654. if scripted_ar then
  655. begin
  656. scriptfile := FixFileName(smartpath+'arscript.txt');
  657. Replace(cmdstr,'$SCRIPT',maybequoted(scriptfile));
  658. Assign(script, scriptfile);
  659. Rewrite(script);
  660. try
  661. writeln(script, 'CREATE ' + current_module.staticlibfilename^);
  662. current := TCmdStrListItem(SmartLinkOFiles.First);
  663. while current <> nil do
  664. begin
  665. writeln(script, 'ADDMOD ' + current.str);
  666. current := TCmdStrListItem(current.next);
  667. end;
  668. writeln(script, 'SAVE');
  669. writeln(script, 'END');
  670. finally
  671. Close(script);
  672. end;
  673. success:=DoExec(binstr,cmdstr,false,true);
  674. end
  675. else
  676. begin
  677. Replace(cmdstr,'$LIB',maybequoted(current_module.staticlibfilename^));
  678. { create AR commands }
  679. success := true;
  680. current := TCmdStrListItem(SmartLinkOFiles.First);
  681. repeat
  682. nextcmd := cmdstr;
  683. Replace(nextcmd,'$FILES',GetNextFiles(2047, current));
  684. success:=DoExec(binstr,nextcmd,false,true);
  685. until (not assigned(current)) or (not success);
  686. end;
  687. if (target_ar.arfinishcmd <> '') then
  688. begin
  689. SplitBinCmd(target_ar.arfinishcmd,binstr,cmdstr);
  690. binstr := FindUtil(utilsprefix + binstr);
  691. Replace(cmdstr,'$LIB',maybequoted(current_module.staticlibfilename^));
  692. success:=DoExec(binstr,cmdstr,false,true);
  693. end;
  694. { Clean up }
  695. if not(cs_asm_leave in current_settings.globalswitches) then
  696. if not(cs_link_nolink in current_settings.globalswitches) then
  697. begin
  698. while not SmartLinkOFiles.Empty do
  699. DeleteFile(SmartLinkOFiles.GetFirst);
  700. if scripted_ar then
  701. DeleteFile(scriptfile);
  702. RemoveDir(smartpath);
  703. end
  704. else
  705. begin
  706. AsmRes.AddDeleteCommand(FixFileName(smartpath+current_module.asmprefix^+'*'+target_info.objext));
  707. if scripted_ar then
  708. AsmRes.AddDeleteCommand(scriptfile);
  709. AsmRes.AddDeleteDirCommand(smartpath);
  710. end;
  711. MakeStaticLibrary:=success;
  712. end;
  713. {*****************************************************************************
  714. TINTERNALLINKER
  715. *****************************************************************************}
  716. Constructor TInternalLinker.Create;
  717. begin
  718. inherited Create;
  719. linkscript:=TCmdStrList.Create;
  720. FStaticLibraryList:=TFPHashObjectList.Create(true);
  721. FImportLibraryList:=TFPHashObjectList.Create(true);
  722. exemap:=nil;
  723. exeoutput:=nil;
  724. UseStabs:=false;
  725. CObjInput:=TObjInput;
  726. ScriptCount:=0;
  727. IsHandled:=nil;
  728. end;
  729. Destructor TInternalLinker.Destroy;
  730. begin
  731. linkscript.free;
  732. StaticLibraryList.Free;
  733. ImportLibraryList.Free;
  734. if assigned(IsHandled) then
  735. begin
  736. FreeMem(IsHandled,sizeof(boolean)*ScriptCount);
  737. IsHandled:=nil;
  738. ScriptCount:=0;
  739. end;
  740. if assigned(exeoutput) then
  741. begin
  742. exeoutput.free;
  743. exeoutput:=nil;
  744. end;
  745. if assigned(exemap) then
  746. begin
  747. exemap.free;
  748. exemap:=nil;
  749. end;
  750. inherited destroy;
  751. end;
  752. procedure TInternalLinker.AddImportSymbol(const libname,symname,symmangledname:TCmdStr;OrdNr: longint;isvar:boolean);
  753. var
  754. ImportLibrary : TImportLibrary;
  755. ImportSymbol : TFPHashObject;
  756. begin
  757. ImportLibrary:=TImportLibrary(ImportLibraryList.Find(libname));
  758. if not assigned(ImportLibrary) then
  759. ImportLibrary:=TImportLibrary.Create(ImportLibraryList,libname);
  760. ImportSymbol:=TFPHashObject(ImportLibrary.ImportSymbolList.Find(symname));
  761. if not assigned(ImportSymbol) then
  762. ImportSymbol:=TImportSymbol.Create(ImportLibrary.ImportSymbolList,symname,symmangledname,OrdNr,isvar);
  763. end;
  764. procedure TInternalLinker.Load_ReadObject(const para:TCmdStr);
  765. var
  766. objdata : TObjData;
  767. objinput : TObjinput;
  768. objreader : TObjectReader;
  769. fn : TCmdStr;
  770. begin
  771. fn:=FindObjectFile(para,'',false);
  772. Comment(V_Tried,'Reading object '+fn);
  773. objinput:=CObjInput.Create;
  774. objdata:=objinput.newObjData(para);
  775. objreader:=TObjectreader.create;
  776. if objreader.openfile(fn) then
  777. begin
  778. if objinput.ReadObjData(objreader,objdata) then
  779. exeoutput.addobjdata(objdata);
  780. end;
  781. { release input object }
  782. objinput.free;
  783. objreader.free;
  784. end;
  785. procedure TInternalLinker.Load_ReadStaticLibrary(const para:TCmdStr);
  786. var
  787. objreader : TObjectReader;
  788. begin
  789. { TODO: Cleanup ignoring of FPC generated libimp*.a files}
  790. { Don't load import libraries }
  791. if copy(ExtractFileName(para),1,6)='libimp' then
  792. exit;
  793. Comment(V_Tried,'Opening library '+para);
  794. objreader:=TArObjectreader.create(para);
  795. TStaticLibrary.Create(StaticLibraryList,para,objreader,CObjInput);
  796. end;
  797. procedure TInternalLinker.ParseScript_Handle;
  798. var
  799. s, para, keyword : String;
  800. hp : TCmdStrListItem;
  801. i : longint;
  802. begin
  803. hp:=TCmdStrListItem(linkscript.first);
  804. i:=0;
  805. while assigned(hp) do
  806. begin
  807. inc(i);
  808. s:=hp.str;
  809. if (s='') or (s[1]='#') then
  810. continue;
  811. keyword:=Upper(GetToken(s,' '));
  812. para:=GetToken(s,' ');
  813. if Trim(s)<>'' then
  814. Comment(V_Warning,'Unknown part "'+s+'" in "'+hp.str+'" internal linker script');
  815. if (keyword<>'SYMBOL') and
  816. (keyword<>'SYMBOLS') and
  817. (keyword<>'STABS') and
  818. (keyword<>'PROVIDE') and
  819. (keyword<>'ZEROS') and
  820. (keyword<>'BYTE') and
  821. (keyword<>'WORD') and
  822. (keyword<>'LONG') and
  823. (keyword<>'QUAD') and
  824. (keyword<>'ENTRYNAME') and
  825. (keyword<>'ISSHAREDLIBRARY') and
  826. (keyword<>'IMAGEBASE') and
  827. (keyword<>'READOBJECT') and
  828. (keyword<>'READSTATICLIBRARY') and
  829. (keyword<>'EXESECTION') and
  830. (keyword<>'ENDEXESECTION') and
  831. (keyword<>'OBJSECTION') and
  832. (keyword<>'HEADER')
  833. then
  834. Comment(V_Warning,'Unknown keyword "'+keyword+'" in "'+hp.str
  835. +'" internal linker script');
  836. hp:=TCmdStrListItem(hp.next);
  837. end;
  838. ScriptCount:=i;
  839. if ScriptCount>0 then
  840. begin
  841. GetMem(IsHandled,sizeof(boolean)*ScriptCount);
  842. Fillchar(IsHandled^,sizeof(boolean)*ScriptCount,#0);
  843. end;
  844. end;
  845. procedure TInternalLinker.ParseScript_PostCheck;
  846. var
  847. s : String;
  848. hp : TCmdStrListItem;
  849. i : longint;
  850. begin
  851. hp:=TCmdStrListItem(linkscript.first);
  852. i:=0;
  853. while assigned(hp) do
  854. begin
  855. inc(i);
  856. if not IsHandled^[i] then
  857. begin
  858. s:=hp.str;
  859. Comment(V_Warning,'"'+hp.str+
  860. '" internal linker script not handled');
  861. end;
  862. hp:=TCmdStrListItem(hp.next);
  863. end;
  864. end;
  865. procedure TInternalLinker.ParseScript_Load;
  866. var
  867. s,
  868. para,
  869. keyword : String;
  870. hp : TCmdStrListItem;
  871. i : longint;
  872. handled : boolean;
  873. begin
  874. exeoutput.Load_Start;
  875. hp:=TCmdStrListItem(linkscript.first);
  876. i:=0;
  877. while assigned(hp) do
  878. begin
  879. inc(i);
  880. s:=hp.str;
  881. if (s='') or (s[1]='#') then
  882. begin
  883. IsHandled^[i]:=true;
  884. continue;
  885. end;
  886. handled:=true;
  887. keyword:=Upper(GetToken(s,' '));
  888. para:=GetToken(s,' ');
  889. if keyword='SYMBOL' then
  890. ExeOutput.Load_Symbol(para)
  891. else if keyword='PROVIDE' then
  892. ExeOutput.Load_ProvideSymbol(para)
  893. else if keyword='ENTRYNAME' then
  894. ExeOutput.Load_EntryName(para)
  895. else if keyword='ISSHAREDLIBRARY' then
  896. ExeOutput.Load_IsSharedLibrary
  897. else if keyword='IMAGEBASE' then
  898. ExeOutput.Load_ImageBase(para)
  899. else if keyword='READOBJECT' then
  900. Load_ReadObject(para)
  901. else if keyword='STABS' then
  902. UseStabs:=true
  903. else if keyword='READSTATICLIBRARY' then
  904. Load_ReadStaticLibrary(para)
  905. else
  906. handled:=false;
  907. if handled then
  908. IsHandled^[i]:=true;
  909. hp:=TCmdStrListItem(hp.next);
  910. end;
  911. end;
  912. procedure TInternalLinker.ParseScript_Order;
  913. var
  914. s,
  915. para,
  916. keyword : String;
  917. hp : TCmdStrListItem;
  918. i : longint;
  919. handled : boolean;
  920. begin
  921. exeoutput.Order_Start;
  922. hp:=TCmdStrListItem(linkscript.first);
  923. i:=0;
  924. while assigned(hp) do
  925. begin
  926. inc(i);
  927. s:=hp.str;
  928. if (s='') or (s[1]='#') then
  929. continue;
  930. handled:=true;
  931. keyword:=Upper(GetToken(s,' '));
  932. para:=GetToken(s,' ');
  933. if keyword='EXESECTION' then
  934. ExeOutput.Order_ExeSection(para)
  935. else if keyword='ENDEXESECTION' then
  936. ExeOutput.Order_EndExeSection
  937. else if keyword='OBJSECTION' then
  938. ExeOutput.Order_ObjSection(para)
  939. else if keyword='ZEROS' then
  940. ExeOutput.Order_Zeros(para)
  941. else if keyword='BYTE' then
  942. ExeOutput.Order_Values(1,para)
  943. else if keyword='WORD' then
  944. ExeOutput.Order_Values(2,para)
  945. else if keyword='LONG' then
  946. ExeOutput.Order_Values(4,para)
  947. else if keyword='QUAD' then
  948. ExeOutput.Order_Values(8,para)
  949. else if keyword='SYMBOL' then
  950. ExeOutput.Order_Symbol(para)
  951. else if keyword='PROVIDE' then
  952. ExeOutput.Order_ProvideSymbol(para)
  953. else
  954. handled:=false;
  955. if handled then
  956. IsHandled^[i]:=true;
  957. hp:=TCmdStrListItem(hp.next);
  958. end;
  959. exeoutput.Order_End;
  960. end;
  961. procedure TInternalLinker.ParseScript_MemPos;
  962. var
  963. s,
  964. para,
  965. keyword : String;
  966. hp : TCmdStrListItem;
  967. i : longint;
  968. handled : boolean;
  969. begin
  970. exeoutput.MemPos_Start;
  971. hp:=TCmdStrListItem(linkscript.first);
  972. i:=0;
  973. while assigned(hp) do
  974. begin
  975. inc(i);
  976. s:=hp.str;
  977. if (s='') or (s[1]='#') then
  978. continue;
  979. handled:=true;
  980. keyword:=Upper(GetToken(s,' '));
  981. para:=GetToken(s,' ');
  982. if keyword='EXESECTION' then
  983. ExeOutput.MemPos_ExeSection(para)
  984. else if keyword='ENDEXESECTION' then
  985. ExeOutput.MemPos_EndExeSection
  986. else if keyword='HEADER' then
  987. ExeOutput.MemPos_Header
  988. else
  989. handled:=false;
  990. if handled then
  991. IsHandled^[i]:=true;
  992. hp:=TCmdStrListItem(hp.next);
  993. end;
  994. end;
  995. procedure TInternalLinker.ParseScript_DataPos;
  996. var
  997. s,
  998. para,
  999. keyword : String;
  1000. hp : TCmdStrListItem;
  1001. i : longint;
  1002. handled : boolean;
  1003. begin
  1004. exeoutput.DataPos_Start;
  1005. hp:=TCmdStrListItem(linkscript.first);
  1006. i:=0;
  1007. while assigned(hp) do
  1008. begin
  1009. inc(i);
  1010. s:=hp.str;
  1011. if (s='') or (s[1]='#') then
  1012. continue;
  1013. handled:=true;
  1014. keyword:=Upper(GetToken(s,' '));
  1015. para:=GetToken(s,' ');
  1016. if keyword='EXESECTION' then
  1017. ExeOutput.DataPos_ExeSection(para)
  1018. else if keyword='ENDEXESECTION' then
  1019. ExeOutput.DataPos_EndExeSection
  1020. else if keyword='HEADER' then
  1021. ExeOutput.DataPos_Header
  1022. else if keyword='SYMBOLS' then
  1023. ExeOutput.DataPos_Symbols
  1024. else
  1025. handled:=false;
  1026. if handled then
  1027. IsHandled^[i]:=true;
  1028. hp:=TCmdStrListItem(hp.next);
  1029. end;
  1030. end;
  1031. procedure TInternalLinker.PrintLinkerScript;
  1032. var
  1033. hp : TCmdStrListItem;
  1034. begin
  1035. if not assigned(exemap) then
  1036. exit;
  1037. exemap.Add('Used linker script');
  1038. exemap.Add('');
  1039. hp:=TCmdStrListItem(linkscript.first);
  1040. while assigned(hp) do
  1041. begin
  1042. exemap.Add(hp.str);
  1043. hp:=TCmdStrListItem(hp.next);
  1044. end;
  1045. end;
  1046. function TInternalLinker.RunLinkScript(const outputname:TCmdStr):boolean;
  1047. label
  1048. myexit;
  1049. var
  1050. bsssize : aword;
  1051. bsssec : TExeSection;
  1052. dbgname : TCmdStr;
  1053. begin
  1054. result:=false;
  1055. Message1(exec_i_linking,outputname);
  1056. FlushOutput;
  1057. { TODO: Load custom linker script}
  1058. DefaultLinkScript;
  1059. exeoutput:=CExeOutput.Create;
  1060. if (cs_link_map in current_settings.globalswitches) then
  1061. exemap:=texemap.create(current_module.mapfilename^);
  1062. PrintLinkerScript;
  1063. { Check that syntax is OK }
  1064. ParseScript_Handle;
  1065. { Load .o files and resolve symbols }
  1066. ParseScript_Load;
  1067. exeoutput.ResolveSymbols(StaticLibraryList);
  1068. { Generate symbols and code to do the importing }
  1069. exeoutput.GenerateLibraryImports(ImportLibraryList);
  1070. { Fill external symbols data }
  1071. exeoutput.FixupSymbols;
  1072. if ErrorCount>0 then
  1073. goto myexit;
  1074. { parse linker options specific for output format }
  1075. exeoutput.ParseScript (linkscript);
  1076. { Create .exe sections and add .o sections }
  1077. ParseScript_Order;
  1078. exeoutput.RemoveUnreferencedSections;
  1079. { if UseStabs then, this would remove
  1080. STABS for empty linker scripts }
  1081. exeoutput.MergeStabs;
  1082. exeoutput.RemoveEmptySections;
  1083. if ErrorCount>0 then
  1084. goto myexit;
  1085. { Calc positions in mem }
  1086. ParseScript_MemPos;
  1087. exeoutput.FixupRelocations;
  1088. exeoutput.PrintMemoryMap;
  1089. if ErrorCount>0 then
  1090. goto myexit;
  1091. if cs_link_separate_dbg_file in current_settings.globalswitches then
  1092. begin
  1093. { create debuginfo, which is an executable without data on disk }
  1094. dbgname:=ChangeFileExt(outputname,'.dbg');
  1095. exeoutput.ExeWriteMode:=ewm_dbgonly;
  1096. ParseScript_DataPos;
  1097. exeoutput.WriteExeFile(dbgname);
  1098. { create executable with link to just created debuginfo file }
  1099. exeoutput.ExeWriteMode:=ewm_exeonly;
  1100. exeoutput.RemoveDebugInfo;
  1101. exeoutput.GenerateDebugLink(ExtractFileName(dbgname),GetFileCRC(dbgname));
  1102. ParseScript_MemPos;
  1103. ParseScript_DataPos;
  1104. exeoutput.WriteExeFile(outputname);
  1105. end
  1106. else
  1107. begin
  1108. exeoutput.ExeWriteMode:=ewm_exefull;
  1109. ParseScript_DataPos;
  1110. exeoutput.WriteExeFile(outputname);
  1111. end;
  1112. { Post check that everything was handled }
  1113. ParseScript_PostCheck;
  1114. { TODO: fixed section names}
  1115. status.codesize:=exeoutput.findexesection('.text').size;
  1116. status.datasize:=exeoutput.findexesection('.data').size;
  1117. bsssec:=exeoutput.findexesection('.bss');
  1118. if assigned(bsssec) then
  1119. bsssize:=bsssec.size
  1120. else
  1121. bsssize:=0;
  1122. { Executable info }
  1123. Message1(execinfo_x_codesize,tostr(status.codesize));
  1124. Message1(execinfo_x_initdatasize,tostr(status.datasize));
  1125. Message1(execinfo_x_uninitdatasize,tostr(bsssize));
  1126. Message1(execinfo_x_stackreserve,tostr(stacksize));
  1127. myexit:
  1128. { close map }
  1129. if assigned(exemap) then
  1130. begin
  1131. exemap.free;
  1132. exemap:=nil;
  1133. end;
  1134. { close exe }
  1135. exeoutput.free;
  1136. exeoutput:=nil;
  1137. result:=true;
  1138. end;
  1139. function TInternalLinker.MakeExecutable:boolean;
  1140. begin
  1141. IsSharedLibrary:=false;
  1142. result:=RunLinkScript(current_module.exefilename^);
  1143. end;
  1144. function TInternalLinker.MakeSharedLibrary:boolean;
  1145. begin
  1146. IsSharedLibrary:=true;
  1147. result:=RunLinkScript(current_module.sharedlibfilename^);
  1148. end;
  1149. {*****************************************************************************
  1150. Init/Done
  1151. *****************************************************************************}
  1152. procedure InitLinker;
  1153. var
  1154. lk : TlinkerClass;
  1155. begin
  1156. if (cs_link_extern in current_settings.globalswitches) and
  1157. assigned(target_info.linkextern) then
  1158. begin
  1159. lk:=TlinkerClass(target_info.linkextern);
  1160. linker:=lk.Create;
  1161. end
  1162. else
  1163. if assigned(target_info.link) then
  1164. begin
  1165. lk:=TLinkerClass(target_info.link);
  1166. linker:=lk.Create;
  1167. end
  1168. else
  1169. linker:=Tlinker.Create;
  1170. end;
  1171. procedure DoneLinker;
  1172. begin
  1173. if assigned(linker) then
  1174. Linker.Free;
  1175. end;
  1176. {*****************************************************************************
  1177. Initialize
  1178. *****************************************************************************}
  1179. const
  1180. ar_gnu_ar_info : tarinfo =
  1181. (
  1182. id : ar_gnu_ar;
  1183. arcmd : 'ar qS $LIB $FILES';
  1184. arfinishcmd : 'ar s $LIB'
  1185. );
  1186. ar_gnu_ar_scripted_info : tarinfo =
  1187. (
  1188. id : ar_gnu_ar_scripted;
  1189. arcmd : 'ar -M < $SCRIPT';
  1190. arfinishcmd : ''
  1191. );
  1192. ar_gnu_gar_info : tarinfo =
  1193. ( id : ar_gnu_gar;
  1194. arcmd : 'gar qS $LIB $FILES';
  1195. arfinishcmd : 'gar s $LIB'
  1196. );
  1197. initialization
  1198. RegisterAr(ar_gnu_ar_info);
  1199. RegisterAr(ar_gnu_ar_scripted_info);
  1200. RegisterAr(ar_gnu_gar_info);
  1201. end.