link.pas 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  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. if useshell then
  466. exitcode := shell(maybequoted(command)+' '+para)
  467. else
  468. {$IFDEF USE_SYSUTILS}
  469. try
  470. if ExecuteProcess(command,para) <> 0
  471. then begin
  472. Message(exec_e_error_while_linking);
  473. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  474. DoExec:=false;
  475. end;
  476. except on E:EOSError do
  477. begin
  478. Message(exec_e_cant_call_linker);
  479. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  480. DoExec:=false;
  481. end;
  482. end
  483. end;
  484. {$ELSE USE_SYSUTILS}
  485. begin
  486. swapvectors;
  487. exec(command,para);
  488. swapvectors;
  489. exitcode := dosexitcode;
  490. end;
  491. if (doserror<>0) then
  492. begin
  493. Message(exec_e_cant_call_linker);
  494. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  495. DoExec:=false;
  496. end
  497. else
  498. if (exitcode<>0) then
  499. begin
  500. Message(exec_e_error_while_linking);
  501. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  502. DoExec:=false;
  503. end;
  504. end;
  505. {$ENDIF USE_SYSUTILS}
  506. { Update asmres when externmode is set }
  507. if cs_link_extern in aktglobalswitches then
  508. begin
  509. if showinfo then
  510. begin
  511. if DLLsource then
  512. AsmRes.AddLinkCommand(Command,Para,current_module.sharedlibfilename^)
  513. else
  514. AsmRes.AddLinkCommand(Command,Para,current_module.exefilename^);
  515. end
  516. else
  517. AsmRes.AddLinkCommand(Command,Para,'');
  518. end;
  519. end;
  520. Function TExternalLinker.MakeStaticLibrary:boolean;
  521. var
  522. smartpath : TCmdStr;
  523. function GetNextFiles(const maxCmdLength : AInt; var item : TStringListItem) : string;
  524. begin
  525. result := '';
  526. while (assigned(item) and ((length(result) + length(item.str) + 1) < maxCmdLength)) do begin
  527. result := result + ' ' + item.str;
  528. item := TStringListItem(item.next);
  529. end;
  530. end;
  531. var
  532. binstr : string;
  533. success : boolean;
  534. cmdstr, nextcmd : TCmdStr;
  535. current : TStringListItem;
  536. begin
  537. MakeStaticLibrary:=false;
  538. { remove the library, to be sure that it is rewritten }
  539. RemoveFile(current_module.staticlibfilename^);
  540. { Call AR }
  541. smartpath:=current_module.outputpath^+FixPath(lower(current_module.modulename^)+target_info.smartext,false);
  542. SplitBinCmd(target_ar.arcmd,binstr,cmdstr);
  543. Replace(cmdstr,'$LIB',maybequoted(current_module.staticlibfilename^));
  544. { create AR commands }
  545. success := true;
  546. nextcmd := cmdstr;
  547. current := TStringListItem(SmartLinkOFiles.First);
  548. repeat
  549. Replace(nextcmd,'$FILES',GetNextFiles(240 - length(nextcmd), current));
  550. success:=DoExec(FindUtil(binstr),nextcmd,false,true);
  551. nextcmd := cmdstr;
  552. until (not assigned(current)) or (not success);
  553. { Clean up }
  554. if not(cs_asm_leave in aktglobalswitches) then
  555. if not(cs_link_extern in aktglobalswitches) then
  556. begin
  557. while not SmartLinkOFiles.Empty do
  558. RemoveFile(SmartLinkOFiles.GetFirst);
  559. RemoveDir(smartpath);
  560. end
  561. else
  562. begin
  563. AsmRes.AddDeleteCommand(FixFileName(smartpath+current_module.asmprefix^+'*'+target_info.objext));
  564. AsmRes.Add('rmdir '+smartpath);
  565. end;
  566. MakeStaticLibrary:=success;
  567. end;
  568. {*****************************************************************************
  569. TINTERNALLINKER
  570. *****************************************************************************}
  571. Constructor TInternalLinker.Create;
  572. begin
  573. inherited Create;
  574. exemap:=nil;
  575. exeoutput:=nil;
  576. end;
  577. Destructor TInternalLinker.Destroy;
  578. begin
  579. exeoutput.free;
  580. exeoutput:=nil;
  581. inherited destroy;
  582. end;
  583. procedure TInternalLinker.readobj(const fn:string);
  584. var
  585. objdata : TAsmObjectData;
  586. objinput : tobjectinput;
  587. begin
  588. Comment(V_Info,'Reading object '+fn);
  589. objinput:=exeoutput.newobjectinput;
  590. objdata:=objinput.newobjectdata(fn);
  591. if objinput.readobjectfile(fn,objdata) then
  592. exeoutput.addobjdata(objdata);
  593. { release input object }
  594. objinput.free;
  595. end;
  596. function TInternalLinker.MakeExecutable:boolean;
  597. var
  598. s : string;
  599. begin
  600. MakeExecutable:=false;
  601. { no support yet for libraries }
  602. if (not StaticLibFiles.Empty) or
  603. (not SharedLibFiles.Empty) then
  604. internalerror(123456789);
  605. if (cs_link_map in aktglobalswitches) then
  606. exemap:=texemap.create(current_module.mapfilename^);
  607. { read objects }
  608. readobj(FindObjectFile('prt0','',false));
  609. while not ObjectFiles.Empty do
  610. begin
  611. s:=ObjectFiles.GetFirst;
  612. if s<>'' then
  613. readobj(s);
  614. end;
  615. { generate executable }
  616. exeoutput.GenerateExecutable(current_module.exefilename^);
  617. { close map }
  618. if assigned(exemap) then
  619. begin
  620. exemap.free;
  621. exemap:=nil;
  622. end;
  623. MakeExecutable:=true;
  624. end;
  625. {*****************************************************************************
  626. Init/Done
  627. *****************************************************************************}
  628. procedure InitLinker;
  629. var
  630. lk : TlinkerClass;
  631. begin
  632. if (cs_link_internal in aktglobalswitches) and
  633. assigned(target_info.link) then
  634. begin
  635. lk:=TLinkerClass(target_info.link);
  636. linker:=lk.Create;
  637. end
  638. else if assigned(target_info.linkextern) then
  639. begin
  640. lk:=TlinkerClass(target_info.linkextern);
  641. linker:=lk.Create;
  642. end
  643. else
  644. begin
  645. linker:=Tlinker.Create;
  646. end;
  647. end;
  648. procedure DoneLinker;
  649. begin
  650. if assigned(linker) then
  651. Linker.Free;
  652. end;
  653. {*****************************************************************************
  654. Initialize
  655. *****************************************************************************}
  656. const
  657. ar_gnu_ar_info : tarinfo =
  658. (
  659. id : ar_gnu_ar;
  660. arcmd : 'ar rs $LIB $FILES'
  661. );
  662. initialization
  663. RegisterAr(ar_gnu_ar_info);
  664. end.