link.pas 21 KB

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