link.pas 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  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. cclasses,
  23. systems,
  24. fmodule,
  25. globtype;
  26. Type
  27. TLinkerInfo=record
  28. ExeCmd,
  29. DllCmd : array[1..3] of string;
  30. ResName : string[100];
  31. ScriptName : string[100];
  32. ExtraOptions : string;
  33. DynamicLinker : string[100];
  34. end;
  35. TLinker = class(TAbstractLinker)
  36. public
  37. ObjectFiles,
  38. DLLFiles,
  39. SharedLibFiles,
  40. StaticLibFiles : TStringList;
  41. Constructor Create;virtual;
  42. Destructor Destroy;override;
  43. procedure AddModuleFiles(hp:tmodule);
  44. Procedure AddObject(const S,unitpath : String;isunit:boolean);
  45. Procedure AddDLL(const S : String);
  46. Procedure AddStaticLibrary(const S : String);
  47. Procedure AddSharedLibrary(S : String);
  48. Procedure AddStaticCLibrary(const S : String);
  49. Procedure AddSharedCLibrary(S : String);
  50. Function MakeExecutable:boolean;virtual;
  51. Function MakeSharedLibrary:boolean;virtual;
  52. Function MakeStaticLibrary:boolean;virtual;
  53. end;
  54. TExternalLinker = class(TLinker)
  55. public
  56. Info : TLinkerInfo;
  57. Constructor Create;override;
  58. Destructor Destroy;override;
  59. Function FindUtil(const s:string):String;
  60. Function DoExec(const command:string; para:TCmdStr;showinfo,useshell:boolean):boolean;
  61. procedure SetDefaultInfo;virtual;
  62. Function MakeStaticLibrary:boolean;override;
  63. end;
  64. TInternalLinker = class(TLinker)
  65. private
  66. procedure readobj(const fn:string);
  67. public
  68. Constructor Create;override;
  69. Destructor Destroy;override;
  70. Function MakeExecutable:boolean;override;
  71. end;
  72. var
  73. Linker : TLinker;
  74. function FindObjectFile(s : string;const unitpath:string;isunit:boolean) : string;
  75. function FindLibraryFile(s:string;const prefix,ext:string;var foundfile : string) : boolean;
  76. function FindDLL(const s:string;var founddll:string):boolean;
  77. procedure InitLinker;
  78. procedure DoneLinker;
  79. Implementation
  80. uses
  81. {$IFDEF USE_SYSUTILS}
  82. SysUtils,
  83. {$ELSE USE_SYSUTILS}
  84. dos,
  85. {$ENDIF USE_SYSUTILS}
  86. cutils,
  87. script,globals,verbose,ppu,
  88. aasmbase,aasmtai,aasmcpu,
  89. ogbase,ogmap;
  90. type
  91. TLinkerClass = class of Tlinker;
  92. {*****************************************************************************
  93. Helpers
  94. *****************************************************************************}
  95. { searches an object file }
  96. function FindObjectFile(s:string;const unitpath:string;isunit:boolean) : string;
  97. var
  98. found : boolean;
  99. foundfile : string;
  100. begin
  101. findobjectfile:='';
  102. if s='' then
  103. exit;
  104. {When linking on target, the units has not been assembled yet,
  105. so there is no object files to look for at
  106. the host. Look for the corresponding assembler file instead,
  107. because it will be assembled to object file on the target.}
  108. if isunit and (cs_link_on_target in aktglobalswitches) then
  109. s:= ForceExtension(s,target_info.asmext);
  110. { when it does not belong to the unit then check if
  111. the specified file exists without searching any paths }
  112. if not isunit then
  113. begin
  114. if FileExists(FixFileName(s)) then
  115. begin
  116. foundfile:=ScriptFixFileName(s);
  117. found:=true;
  118. end;
  119. end;
  120. if pos('.',s)=0 then
  121. s:=s+target_info.objext;
  122. { find object file
  123. 1. output unit path
  124. 2. output exe path
  125. 3. specified unit path (if specified)
  126. 4. cwd
  127. 5. unit search path
  128. 6. local object path
  129. 7. global object path
  130. 8. exepath (not when linking on target) }
  131. found:=false;
  132. if isunit and (OutputUnitDir<>'') then
  133. found:=FindFile(s,OutPutUnitDir,foundfile)
  134. else
  135. if OutputExeDir<>'' then
  136. found:=FindFile(s,OutPutExeDir,foundfile);
  137. if (not found) and (unitpath<>'') then
  138. found:=FindFile(s,unitpath,foundfile);
  139. if (not found) then
  140. found:=FindFile(s, CurDirRelPath(source_info), foundfile);
  141. if (not found) then
  142. found:=UnitSearchPath.FindFile(s,foundfile);
  143. if (not found) then
  144. found:=current_module.localobjectsearchpath.FindFile(s,foundfile);
  145. if (not found) then
  146. found:=objectsearchpath.FindFile(s,foundfile);
  147. if not(cs_link_on_target in aktglobalswitches) and (not found) then
  148. found:=FindFile(s,exepath,foundfile);
  149. if not(cs_link_extern in aktglobalswitches) and (not found) then
  150. Message1(exec_w_objfile_not_found,s);
  151. {Restore file extension}
  152. if isunit and (cs_link_on_target in aktglobalswitches) then
  153. foundfile:= ForceExtension(foundfile,target_info.objext);
  154. findobjectfile:=ScriptFixFileName(foundfile);
  155. end;
  156. { searches a (windows) DLL file }
  157. function FindDLL(const s:string;var founddll:string):boolean;
  158. var
  159. sysdir : string;
  160. Found : boolean;
  161. begin
  162. Found:=false;
  163. { Look for DLL in:
  164. 1. Current dir
  165. 2. Library Path
  166. 3. windir,windir/system,windir/system32 }
  167. Found:=FindFile(s,'.'+source_info.DirSep,founddll);
  168. if (not found) then
  169. Found:=librarysearchpath.FindFile(s,founddll);
  170. if (not found) then
  171. begin
  172. {$IFDEF USE_SYSUTILS}
  173. sysdir:=FixPath(GetEnvironmentVariable('windir'),false);
  174. {$ELSE USE_SYSUTILS}
  175. sysdir:=FixPath(GetEnv('windir'),false);
  176. {$ENDIF USE_SYSUTILS}
  177. Found:=FindFile(s,sysdir+';'+sysdir+'system'+source_info.DirSep+';'+sysdir+'system32'+source_info.DirSep,founddll);
  178. end;
  179. if (not found) then
  180. begin
  181. message1(exec_w_libfile_not_found,s);
  182. FoundDll:=s;
  183. end;
  184. FindDll:=Found;
  185. end;
  186. { searches an library file }
  187. function FindLibraryFile(s:string;const prefix,ext:string;var foundfile : string) : boolean;
  188. var
  189. found : boolean;
  190. paths : string;
  191. begin
  192. findlibraryfile:=false;
  193. foundfile:=s;
  194. if s='' then
  195. exit;
  196. { split path from filename }
  197. paths:=SplitPath(s);
  198. s:=SplitFileName(s);
  199. { add prefix 'lib' }
  200. if (prefix<>'') and (Copy(s,1,length(prefix))<>prefix) then
  201. s:=prefix+s;
  202. { add extension }
  203. if (ext<>'') and (Copy(s,length(s)-length(ext)+1,length(ext))<>ext) then
  204. s:=s+ext;
  205. { readd the split path }
  206. s:=paths+s;
  207. if FileExists(s) then
  208. begin
  209. foundfile:=ScriptFixFileName(s);
  210. FindLibraryFile:=true;
  211. exit;
  212. end;
  213. { find libary
  214. 1. cwd
  215. 2. local libary dir
  216. 3. global libary dir
  217. 4. exe path of the compiler (not when linking on target) }
  218. found:=FindFile(s, CurDirRelPath(source_info), foundfile);
  219. if (not found) and (current_module.outputpath^<>'') then
  220. found:=FindFile(s,current_module.outputpath^,foundfile);
  221. if (not found) then
  222. found:=current_module.locallibrarysearchpath.FindFile(s,foundfile);
  223. if (not found) then
  224. found:=librarysearchpath.FindFile(s,foundfile);
  225. if not(cs_link_on_target in aktglobalswitches) and (not found) then
  226. found:=FindFile(s,exepath,foundfile);
  227. foundfile:=ScriptFixFileName(foundfile);
  228. findlibraryfile:=found;
  229. end;
  230. {*****************************************************************************
  231. TLINKER
  232. *****************************************************************************}
  233. Constructor TLinker.Create;
  234. begin
  235. Inherited Create;
  236. ObjectFiles:=TStringList.Create_no_double;
  237. DLLFiles:=TStringList.Create_no_double;
  238. SharedLibFiles:=TStringList.Create_no_double;
  239. StaticLibFiles:=TStringList.Create_no_double;
  240. end;
  241. Destructor TLinker.Destroy;
  242. begin
  243. ObjectFiles.Free;
  244. DLLFiles.Free;
  245. SharedLibFiles.Free;
  246. StaticLibFiles.Free;
  247. end;
  248. procedure TLinker.AddModuleFiles(hp:tmodule);
  249. var
  250. mask : longint;
  251. begin
  252. with hp do
  253. begin
  254. { link unit files }
  255. if (flags and uf_no_link)=0 then
  256. begin
  257. { create mask which unit files need linking }
  258. mask:=link_allways;
  259. { static linking ? }
  260. if (cs_link_static in aktglobalswitches) then
  261. begin
  262. if (flags and uf_static_linked)=0 then
  263. begin
  264. { if smart not avail then try static linking }
  265. if (flags and uf_smart_linked)<>0 then
  266. begin
  267. Message1(exec_t_unit_not_static_linkable_switch_to_smart,modulename^);
  268. mask:=mask or link_smart;
  269. end
  270. else
  271. Message1(exec_e_unit_not_smart_or_static_linkable,modulename^);
  272. end
  273. else
  274. mask:=mask or link_static;
  275. end;
  276. { smart linking ? }
  277. if (cs_link_smart in aktglobalswitches) then
  278. begin
  279. if (flags and uf_smart_linked)=0 then
  280. begin
  281. { if smart not avail then try static linking }
  282. if (flags and uf_static_linked)<>0 then
  283. begin
  284. Message1(exec_t_unit_not_smart_linkable_switch_to_static,modulename^);
  285. mask:=mask or link_static;
  286. end
  287. else
  288. Message1(exec_e_unit_not_smart_or_static_linkable,modulename^);
  289. end
  290. else
  291. mask:=mask or link_smart;
  292. end;
  293. { shared linking }
  294. if (cs_link_shared in aktglobalswitches) then
  295. begin
  296. if (flags and uf_shared_linked)=0 then
  297. begin
  298. { if shared not avail then try static linking }
  299. if (flags and uf_static_linked)<>0 then
  300. begin
  301. Message1(exec_t_unit_not_shared_linkable_switch_to_static,modulename^);
  302. mask:=mask or link_static;
  303. end
  304. else
  305. Message1(exec_e_unit_not_shared_or_static_linkable,modulename^);
  306. end
  307. else
  308. mask:=mask or link_shared;
  309. end;
  310. { unit files }
  311. while not linkunitofiles.empty do
  312. AddObject(linkunitofiles.getusemask(mask),path^,true);
  313. while not linkunitstaticlibs.empty do
  314. AddStaticLibrary(linkunitstaticlibs.getusemask(mask));
  315. while not linkunitsharedlibs.empty do
  316. AddSharedLibrary(linkunitsharedlibs.getusemask(mask));
  317. end;
  318. { Other needed .o and libs, specified using $L,$LINKLIB,external }
  319. mask:=link_allways;
  320. while not linkotherofiles.empty do
  321. AddObject(linkotherofiles.Getusemask(mask),path^,false);
  322. while not linkotherstaticlibs.empty do
  323. AddStaticCLibrary(linkotherstaticlibs.Getusemask(mask));
  324. while not linkothersharedlibs.empty do
  325. AddSharedCLibrary(linkothersharedlibs.Getusemask(mask));
  326. { (Windows) DLLs }
  327. while not linkdlls.empty do
  328. AddDLL(linkdlls.Getusemask(mask));
  329. end;
  330. end;
  331. Procedure TLinker.AddObject(const S,unitpath : String;isunit:boolean);
  332. begin
  333. ObjectFiles.Concat(FindObjectFile(s,unitpath,isunit));
  334. end;
  335. Procedure TLinker.AddDLL(const S : String);
  336. begin
  337. DLLFiles.Concat(s);
  338. end;
  339. Procedure TLinker.AddSharedLibrary(S:String);
  340. begin
  341. if s='' then
  342. exit;
  343. { remove prefix 'lib' }
  344. if Copy(s,1,length(target_info.sharedlibprefix))=target_info.sharedlibprefix then
  345. Delete(s,1,length(target_info.sharedlibprefix));
  346. { remove extension if any }
  347. if Copy(s,length(s)-length(target_info.sharedlibext)+1,length(target_info.sharedlibext))=target_info.sharedlibext then
  348. Delete(s,length(s)-length(target_info.sharedlibext)+1,length(target_info.sharedlibext)+1);
  349. { ready to be added }
  350. SharedLibFiles.Concat(S);
  351. end;
  352. Procedure TLinker.AddStaticLibrary(const S:String);
  353. var
  354. ns : string;
  355. found : boolean;
  356. begin
  357. if s='' then
  358. exit;
  359. found:=FindLibraryFile(s,target_info.staticlibprefix,target_info.staticlibext,ns);
  360. if not(cs_link_extern in aktglobalswitches) and (not found) then
  361. Message1(exec_w_libfile_not_found,s);
  362. StaticLibFiles.Concat(ns);
  363. end;
  364. Procedure TLinker.AddSharedCLibrary(S:String);
  365. begin
  366. if s='' then
  367. exit;
  368. { remove prefix 'lib' }
  369. if Copy(s,1,length(target_info.sharedclibprefix))=target_info.sharedclibprefix then
  370. Delete(s,1,length(target_info.sharedclibprefix));
  371. { remove extension if any }
  372. if Copy(s,length(s)-length(target_info.sharedclibext)+1,length(target_info.sharedclibext))=target_info.sharedclibext then
  373. Delete(s,length(s)-length(target_info.sharedclibext)+1,length(target_info.sharedclibext)+1);
  374. { ready to be added }
  375. SharedLibFiles.Concat(S);
  376. end;
  377. Procedure TLinker.AddStaticCLibrary(const S:String);
  378. var
  379. ns : string;
  380. found : boolean;
  381. begin
  382. if s='' then
  383. exit;
  384. found:=FindLibraryFile(s,target_info.staticclibprefix,target_info.staticclibext,ns);
  385. if not(cs_link_extern in aktglobalswitches) and (not found) then
  386. Message1(exec_w_libfile_not_found,s);
  387. StaticLibFiles.Concat(ns);
  388. end;
  389. function TLinker.MakeExecutable:boolean;
  390. begin
  391. MakeExecutable:=false;
  392. Message(exec_e_exe_not_supported);
  393. end;
  394. Function TLinker.MakeSharedLibrary:boolean;
  395. begin
  396. MakeSharedLibrary:=false;
  397. Message(exec_e_dll_not_supported);
  398. end;
  399. Function TLinker.MakeStaticLibrary:boolean;
  400. begin
  401. MakeStaticLibrary:=false;
  402. Message(exec_e_dll_not_supported);
  403. end;
  404. {*****************************************************************************
  405. TEXTERNALLINKER
  406. *****************************************************************************}
  407. Constructor TExternalLinker.Create;
  408. begin
  409. inherited Create;
  410. { set generic defaults }
  411. FillChar(Info,sizeof(Info),0);
  412. if cs_link_on_target in aktglobalswitches then
  413. begin
  414. Info.ResName:=outputexedir+inputfile+'_link.res';
  415. Info.ScriptName:=outputexedir+inputfile+'_script.res';
  416. end
  417. else
  418. begin
  419. Info.ResName:='link.res';
  420. Info.ScriptName:='script.res';
  421. end;
  422. { set the linker specific defaults }
  423. SetDefaultInfo;
  424. { Allow Parameter overrides for linker info }
  425. with Info do
  426. begin
  427. if ParaLinkOptions<>'' then
  428. ExtraOptions:=ParaLinkOptions;
  429. if ParaDynamicLinker<>'' then
  430. DynamicLinker:=ParaDynamicLinker;
  431. end;
  432. end;
  433. Destructor TExternalLinker.Destroy;
  434. begin
  435. inherited destroy;
  436. end;
  437. Procedure TExternalLinker.SetDefaultInfo;
  438. begin
  439. end;
  440. Function TExternalLinker.FindUtil(const s:string):string;
  441. var
  442. Found : boolean;
  443. FoundBin : string;
  444. UtilExe : string;
  445. begin
  446. if cs_link_on_target in aktglobalswitches then
  447. begin
  448. { If linking on target, don't add any path PM }
  449. FindUtil:=AddExtension(s,target_info.exeext);
  450. exit;
  451. end;
  452. UtilExe:=AddExtension(s,source_info.exeext);
  453. FoundBin:='';
  454. Found:=false;
  455. if utilsdirectory<>'' then
  456. Found:=FindFile(utilexe,utilsdirectory,Foundbin);
  457. if (not Found) then
  458. Found:=FindExe(utilexe,Foundbin);
  459. if (not Found) and not(cs_link_extern in aktglobalswitches) then
  460. begin
  461. Message1(exec_e_util_not_found,utilexe);
  462. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  463. end;
  464. if (FoundBin<>'') then
  465. Message1(exec_t_using_util,FoundBin);
  466. FindUtil:=FoundBin;
  467. end;
  468. Function TExternalLinker.DoExec(const command:string; para:TCmdStr;showinfo,useshell:boolean):boolean;
  469. var
  470. exitcode: longint;
  471. begin
  472. DoExec:=true;
  473. if not(cs_link_extern in aktglobalswitches) then
  474. begin
  475. if useshell then
  476. exitcode := shell(maybequoted(command)+' '+para)
  477. else
  478. {$IFDEF USE_SYSUTILS}
  479. try
  480. if ExecuteProcess(command,para) <> 0
  481. then begin
  482. Message(exec_e_error_while_linking);
  483. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  484. DoExec:=false;
  485. end;
  486. except on E:EOSError do
  487. begin
  488. Message(exec_e_cant_call_linker);
  489. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  490. DoExec:=false;
  491. end;
  492. end
  493. end;
  494. {$ELSE USE_SYSUTILS}
  495. begin
  496. swapvectors;
  497. exec(command,para);
  498. swapvectors;
  499. exitcode := dosexitcode;
  500. end;
  501. if (doserror<>0) then
  502. begin
  503. Message(exec_e_cant_call_linker);
  504. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  505. DoExec:=false;
  506. end
  507. else
  508. if (exitcode<>0) then
  509. begin
  510. Message(exec_e_error_while_linking);
  511. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  512. DoExec:=false;
  513. end;
  514. end;
  515. {$ENDIF USE_SYSUTILS}
  516. { Update asmres when externmode is set }
  517. if cs_link_extern in aktglobalswitches then
  518. begin
  519. if showinfo then
  520. begin
  521. if DLLsource then
  522. AsmRes.AddLinkCommand(Command,Para,current_module.sharedlibfilename^)
  523. else
  524. AsmRes.AddLinkCommand(Command,Para,current_module.exefilename^);
  525. end
  526. else
  527. AsmRes.AddLinkCommand(Command,Para,'');
  528. end;
  529. end;
  530. Function TExternalLinker.MakeStaticLibrary:boolean;
  531. var
  532. smartpath : TCmdStr;
  533. function GetNextFiles(const maxCmdLength : AInt; var item : TStringListItem) : string;
  534. begin
  535. result := '';
  536. while (assigned(item) and ((length(result) + length(item.str) + 1) < maxCmdLength)) do begin
  537. result := result + ' ' + item.str;
  538. item := TStringListItem(item.next);
  539. end;
  540. end;
  541. var
  542. binstr : string;
  543. success : boolean;
  544. cmdstr, nextcmd : TCmdStr;
  545. current : TStringListItem;
  546. begin
  547. MakeStaticLibrary:=false;
  548. { remove the library, to be sure that it is rewritten }
  549. RemoveFile(current_module.staticlibfilename^);
  550. { Call AR }
  551. smartpath:=current_module.outputpath^+FixPath(lower(current_module.modulename^)+target_info.smartext,false);
  552. SplitBinCmd(target_ar.arcmd,binstr,cmdstr);
  553. Replace(cmdstr,'$LIB',maybequoted(current_module.staticlibfilename^));
  554. { create AR commands }
  555. success := true;
  556. nextcmd := cmdstr;
  557. current := TStringListItem(SmartLinkOFiles.First);
  558. repeat
  559. Replace(nextcmd,'$FILES',GetNextFiles(240 - length(nextcmd), current));
  560. success:=DoExec(FindUtil(binstr),nextcmd,false,true);
  561. nextcmd := cmdstr;
  562. until (not assigned(current)) or (not success);
  563. { Clean up }
  564. if not(cs_asm_leave in aktglobalswitches) then
  565. if not(cs_link_extern in aktglobalswitches) then
  566. begin
  567. while not SmartLinkOFiles.Empty do
  568. RemoveFile(SmartLinkOFiles.GetFirst);
  569. RemoveDir(smartpath);
  570. end
  571. else
  572. begin
  573. AsmRes.AddDeleteCommand(FixFileName(smartpath+current_module.asmprefix^+'*'+target_info.objext));
  574. AsmRes.Add('rmdir '+smartpath);
  575. end;
  576. MakeStaticLibrary:=success;
  577. end;
  578. {*****************************************************************************
  579. TINTERNALLINKER
  580. *****************************************************************************}
  581. Constructor TInternalLinker.Create;
  582. begin
  583. inherited Create;
  584. exemap:=nil;
  585. exeoutput:=nil;
  586. end;
  587. Destructor TInternalLinker.Destroy;
  588. begin
  589. exeoutput.free;
  590. exeoutput:=nil;
  591. inherited destroy;
  592. end;
  593. procedure TInternalLinker.readobj(const fn:string);
  594. var
  595. objdata : TAsmObjectData;
  596. objinput : tobjectinput;
  597. begin
  598. Comment(V_Info,'Reading object '+fn);
  599. objinput:=exeoutput.newobjectinput;
  600. objdata:=objinput.newobjectdata(fn);
  601. if objinput.readobjectfile(fn,objdata) then
  602. exeoutput.addobjdata(objdata);
  603. { release input object }
  604. objinput.free;
  605. end;
  606. function TInternalLinker.MakeExecutable:boolean;
  607. var
  608. s : string;
  609. begin
  610. MakeExecutable:=false;
  611. { no support yet for libraries }
  612. if (not StaticLibFiles.Empty) or
  613. (not SharedLibFiles.Empty) then
  614. internalerror(123456789);
  615. if (cs_link_map in aktglobalswitches) then
  616. exemap:=texemap.create(current_module.mapfilename^);
  617. { read objects }
  618. readobj(FindObjectFile('prt0','',false));
  619. while not ObjectFiles.Empty do
  620. begin
  621. s:=ObjectFiles.GetFirst;
  622. if s<>'' then
  623. readobj(s);
  624. end;
  625. { generate executable }
  626. exeoutput.GenerateExecutable(current_module.exefilename^);
  627. { close map }
  628. if assigned(exemap) then
  629. begin
  630. exemap.free;
  631. exemap:=nil;
  632. end;
  633. MakeExecutable:=true;
  634. end;
  635. {*****************************************************************************
  636. Init/Done
  637. *****************************************************************************}
  638. procedure InitLinker;
  639. var
  640. lk : TlinkerClass;
  641. begin
  642. if (cs_link_internal in aktglobalswitches) and
  643. assigned(target_info.link) then
  644. begin
  645. lk:=TLinkerClass(target_info.link);
  646. linker:=lk.Create;
  647. end
  648. else if assigned(target_info.linkextern) then
  649. begin
  650. lk:=TlinkerClass(target_info.linkextern);
  651. linker:=lk.Create;
  652. end
  653. else
  654. begin
  655. linker:=Tlinker.Create;
  656. end;
  657. end;
  658. procedure DoneLinker;
  659. begin
  660. if assigned(linker) then
  661. Linker.Free;
  662. end;
  663. {*****************************************************************************
  664. Initialize
  665. *****************************************************************************}
  666. const
  667. ar_gnu_ar_info : tarinfo =
  668. (
  669. id : ar_gnu_ar;
  670. arcmd : 'ar rs $LIB $FILES'
  671. );
  672. initialization
  673. RegisterAr(ar_gnu_ar_info);
  674. end.