link.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  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. sysdir:=FixPath(GetEnv('windir'),false);
  173. Found:=FindFile(s,sysdir+';'+sysdir+'system'+source_info.DirSep+';'+sysdir+'system32'+source_info.DirSep,founddll);
  174. end;
  175. if (not found) then
  176. begin
  177. message1(exec_w_libfile_not_found,s);
  178. FoundDll:=s;
  179. end;
  180. FindDll:=Found;
  181. end;
  182. { searches an library file }
  183. function FindLibraryFile(s:string;const prefix,ext:string;var foundfile : string) : boolean;
  184. var
  185. found : boolean;
  186. paths : string;
  187. begin
  188. findlibraryfile:=false;
  189. foundfile:=s;
  190. if s='' then
  191. exit;
  192. { split path from filename }
  193. paths:=SplitPath(s);
  194. s:=SplitFileName(s);
  195. { add prefix 'lib' }
  196. if (prefix<>'') and (Copy(s,1,length(prefix))<>prefix) then
  197. s:=prefix+s;
  198. { add extension }
  199. if (ext<>'') and (Copy(s,length(s)-length(ext)+1,length(ext))<>ext) then
  200. s:=s+ext;
  201. { readd the split path }
  202. s:=paths+s;
  203. if FileExists(s) then
  204. begin
  205. foundfile:=ScriptFixFileName(s);
  206. FindLibraryFile:=true;
  207. exit;
  208. end;
  209. { find libary
  210. 1. cwd
  211. 2. local libary dir
  212. 3. global libary dir
  213. 4. exe path of the compiler (not when linking on target) }
  214. found:=FindFile(s, CurDirRelPath(source_info), foundfile);
  215. if (not found) and (current_module.outputpath^<>'') then
  216. found:=FindFile(s,current_module.outputpath^,foundfile);
  217. if (not found) then
  218. found:=current_module.locallibrarysearchpath.FindFile(s,foundfile);
  219. if (not found) then
  220. found:=librarysearchpath.FindFile(s,foundfile);
  221. if not(cs_link_on_target in aktglobalswitches) and (not found) then
  222. found:=FindFile(s,exepath,foundfile);
  223. foundfile:=ScriptFixFileName(foundfile);
  224. findlibraryfile:=found;
  225. end;
  226. {*****************************************************************************
  227. TLINKER
  228. *****************************************************************************}
  229. Constructor TLinker.Create;
  230. begin
  231. Inherited Create;
  232. ObjectFiles:=TStringList.Create_no_double;
  233. DLLFiles:=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. DLLFiles.Free;
  241. SharedLibFiles.Free;
  242. StaticLibFiles.Free;
  243. end;
  244. procedure TLinker.AddModuleFiles(hp:tmodule);
  245. var
  246. mask : longint;
  247. begin
  248. with hp do
  249. begin
  250. { link unit files }
  251. if (flags and uf_no_link)=0 then
  252. begin
  253. { create mask which unit files need linking }
  254. mask:=link_allways;
  255. { static linking ? }
  256. if (cs_link_static in aktglobalswitches) then
  257. begin
  258. if (flags and uf_static_linked)=0 then
  259. begin
  260. { if smart not avail then try static linking }
  261. if (flags and uf_smart_linked)<>0 then
  262. begin
  263. Message1(exec_t_unit_not_static_linkable_switch_to_smart,modulename^);
  264. mask:=mask or link_smart;
  265. end
  266. else
  267. Message1(exec_e_unit_not_smart_or_static_linkable,modulename^);
  268. end
  269. else
  270. mask:=mask or link_static;
  271. end;
  272. { smart linking ? }
  273. if (cs_link_smart in aktglobalswitches) then
  274. begin
  275. if (flags and uf_smart_linked)=0 then
  276. begin
  277. { if smart not avail then try static linking }
  278. if (flags and uf_static_linked)<>0 then
  279. begin
  280. Message1(exec_t_unit_not_smart_linkable_switch_to_static,modulename^);
  281. mask:=mask or link_static;
  282. end
  283. else
  284. Message1(exec_e_unit_not_smart_or_static_linkable,modulename^);
  285. end
  286. else
  287. mask:=mask or link_smart;
  288. end;
  289. { shared linking }
  290. if (cs_link_shared in aktglobalswitches) then
  291. begin
  292. if (flags and uf_shared_linked)=0 then
  293. begin
  294. { if shared not avail then try static linking }
  295. if (flags and uf_static_linked)<>0 then
  296. begin
  297. Message1(exec_t_unit_not_shared_linkable_switch_to_static,modulename^);
  298. mask:=mask or link_static;
  299. end
  300. else
  301. Message1(exec_e_unit_not_shared_or_static_linkable,modulename^);
  302. end
  303. else
  304. mask:=mask or link_shared;
  305. end;
  306. { unit files }
  307. while not linkunitofiles.empty do
  308. AddObject(linkunitofiles.getusemask(mask),path^,true);
  309. while not linkunitstaticlibs.empty do
  310. AddStaticLibrary(linkunitstaticlibs.getusemask(mask));
  311. while not linkunitsharedlibs.empty do
  312. AddSharedLibrary(linkunitsharedlibs.getusemask(mask));
  313. end;
  314. { Other needed .o and libs, specified using $L,$LINKLIB,external }
  315. mask:=link_allways;
  316. while not linkotherofiles.empty do
  317. AddObject(linkotherofiles.Getusemask(mask),path^,false);
  318. while not linkotherstaticlibs.empty do
  319. AddStaticCLibrary(linkotherstaticlibs.Getusemask(mask));
  320. while not linkothersharedlibs.empty do
  321. AddSharedCLibrary(linkothersharedlibs.Getusemask(mask));
  322. { (Windows) DLLs }
  323. while not linkdlls.empty do
  324. AddDLL(linkdlls.Getusemask(mask));
  325. end;
  326. end;
  327. Procedure TLinker.AddObject(const S,unitpath : String;isunit:boolean);
  328. begin
  329. ObjectFiles.Concat(FindObjectFile(s,unitpath,isunit));
  330. end;
  331. Procedure TLinker.AddDLL(const S : String);
  332. begin
  333. DLLFiles.Concat(s);
  334. end;
  335. Procedure TLinker.AddSharedLibrary(S:String);
  336. begin
  337. if s='' then
  338. exit;
  339. { remove prefix 'lib' }
  340. if Copy(s,1,length(target_info.sharedlibprefix))=target_info.sharedlibprefix then
  341. Delete(s,1,length(target_info.sharedlibprefix));
  342. { remove extension if any }
  343. if Copy(s,length(s)-length(target_info.sharedlibext)+1,length(target_info.sharedlibext))=target_info.sharedlibext then
  344. Delete(s,length(s)-length(target_info.sharedlibext)+1,length(target_info.sharedlibext)+1);
  345. { ready to be added }
  346. SharedLibFiles.Concat(S);
  347. end;
  348. Procedure TLinker.AddStaticLibrary(const S:String);
  349. var
  350. ns : string;
  351. found : boolean;
  352. begin
  353. if s='' then
  354. exit;
  355. found:=FindLibraryFile(s,target_info.staticlibprefix,target_info.staticlibext,ns);
  356. if not(cs_link_extern in aktglobalswitches) and (not found) then
  357. Message1(exec_w_libfile_not_found,s);
  358. StaticLibFiles.Concat(ns);
  359. end;
  360. Procedure TLinker.AddSharedCLibrary(S:String);
  361. begin
  362. if s='' then
  363. exit;
  364. { remove prefix 'lib' }
  365. if Copy(s,1,length(target_info.sharedclibprefix))=target_info.sharedclibprefix then
  366. Delete(s,1,length(target_info.sharedclibprefix));
  367. { remove extension if any }
  368. if Copy(s,length(s)-length(target_info.sharedclibext)+1,length(target_info.sharedclibext))=target_info.sharedclibext then
  369. Delete(s,length(s)-length(target_info.sharedclibext)+1,length(target_info.sharedclibext)+1);
  370. { ready to be added }
  371. SharedLibFiles.Concat(S);
  372. end;
  373. Procedure TLinker.AddStaticCLibrary(const S:String);
  374. var
  375. ns : string;
  376. found : boolean;
  377. begin
  378. if s='' then
  379. exit;
  380. found:=FindLibraryFile(s,target_info.staticclibprefix,target_info.staticclibext,ns);
  381. if not(cs_link_extern in aktglobalswitches) and (not found) then
  382. Message1(exec_w_libfile_not_found,s);
  383. StaticLibFiles.Concat(ns);
  384. end;
  385. function TLinker.MakeExecutable:boolean;
  386. begin
  387. MakeExecutable:=false;
  388. Message(exec_e_exe_not_supported);
  389. end;
  390. Function TLinker.MakeSharedLibrary:boolean;
  391. begin
  392. MakeSharedLibrary:=false;
  393. Message(exec_e_dll_not_supported);
  394. end;
  395. Function TLinker.MakeStaticLibrary:boolean;
  396. begin
  397. MakeStaticLibrary:=false;
  398. Message(exec_e_dll_not_supported);
  399. end;
  400. {*****************************************************************************
  401. TEXTERNALLINKER
  402. *****************************************************************************}
  403. Constructor TExternalLinker.Create;
  404. begin
  405. inherited Create;
  406. { set generic defaults }
  407. FillChar(Info,sizeof(Info),0);
  408. if cs_link_on_target in aktglobalswitches then
  409. begin
  410. Info.ResName:=outputexedir+inputfile+'_link.res';
  411. Info.ScriptName:=outputexedir+inputfile+'_script.res';
  412. end
  413. else
  414. begin
  415. Info.ResName:='link.res';
  416. Info.ScriptName:='script.res';
  417. end;
  418. { set the linker specific defaults }
  419. SetDefaultInfo;
  420. { Allow Parameter overrides for linker info }
  421. with Info do
  422. begin
  423. if ParaLinkOptions<>'' then
  424. ExtraOptions:=ParaLinkOptions;
  425. if ParaDynamicLinker<>'' then
  426. DynamicLinker:=ParaDynamicLinker;
  427. end;
  428. end;
  429. Destructor TExternalLinker.Destroy;
  430. begin
  431. inherited destroy;
  432. end;
  433. Procedure TExternalLinker.SetDefaultInfo;
  434. begin
  435. end;
  436. Function TExternalLinker.FindUtil(const s:string):string;
  437. var
  438. Found : boolean;
  439. FoundBin : string;
  440. UtilExe : string;
  441. begin
  442. if cs_link_on_target in aktglobalswitches then
  443. begin
  444. { If linking on target, don't add any path PM }
  445. FindUtil:=AddExtension(s,target_info.exeext);
  446. exit;
  447. end;
  448. UtilExe:=AddExtension(s,source_info.exeext);
  449. FoundBin:='';
  450. Found:=false;
  451. if utilsdirectory<>'' then
  452. Found:=FindFile(utilexe,utilsdirectory,Foundbin);
  453. if (not Found) then
  454. Found:=FindExe(utilexe,Foundbin);
  455. if (not Found) and not(cs_link_extern in aktglobalswitches) then
  456. begin
  457. Message1(exec_e_util_not_found,utilexe);
  458. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  459. end;
  460. if (FoundBin<>'') then
  461. Message1(exec_t_using_util,FoundBin);
  462. FindUtil:=FoundBin;
  463. end;
  464. Function TExternalLinker.DoExec(const command:string; para:TCmdStr;showinfo,useshell:boolean):boolean;
  465. var
  466. exitcode: longint;
  467. begin
  468. DoExec:=true;
  469. if not(cs_link_extern in aktglobalswitches) then
  470. begin
  471. if useshell then
  472. exitcode := shell(maybequoted(command)+' '+para)
  473. else
  474. {$IFDEF USE_SYSUTILS}
  475. try
  476. if ExecuteProcess(command,para) <> 0
  477. then begin
  478. Message(exec_e_error_while_linking);
  479. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  480. DoExec:=false;
  481. end;
  482. except on E:EOSError do
  483. begin
  484. Message(exec_e_cant_call_linker);
  485. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  486. DoExec:=false;
  487. end;
  488. end
  489. end;
  490. {$ELSE USE_SYSUTILS}
  491. begin
  492. swapvectors;
  493. exec(command,para);
  494. swapvectors;
  495. exitcode := dosexitcode;
  496. end;
  497. if (doserror<>0) then
  498. begin
  499. Message(exec_e_cant_call_linker);
  500. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  501. DoExec:=false;
  502. end
  503. else
  504. if (exitcode<>0) then
  505. begin
  506. Message(exec_e_error_while_linking);
  507. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  508. DoExec:=false;
  509. end;
  510. end;
  511. {$ENDIF USE_SYSUTILS}
  512. { Update asmres when externmode is set }
  513. if cs_link_extern in aktglobalswitches then
  514. begin
  515. if showinfo then
  516. begin
  517. if DLLsource then
  518. AsmRes.AddLinkCommand(Command,Para,current_module.sharedlibfilename^)
  519. else
  520. AsmRes.AddLinkCommand(Command,Para,current_module.exefilename^);
  521. end
  522. else
  523. AsmRes.AddLinkCommand(Command,Para,'');
  524. end;
  525. end;
  526. Function TExternalLinker.MakeStaticLibrary:boolean;
  527. var
  528. smartpath,
  529. cmdstr : TCmdStr;
  530. binstr : string;
  531. success : boolean;
  532. begin
  533. MakeStaticLibrary:=false;
  534. { remove the library, to be sure that it is rewritten }
  535. RemoveFile(current_module.staticlibfilename^);
  536. { Call AR }
  537. smartpath:=current_module.outputpath^+FixPath(lower(current_module.modulename^)+target_info.smartext,false);
  538. SplitBinCmd(target_ar.arcmd,binstr,cmdstr);
  539. Replace(cmdstr,'$LIB',maybequoted(current_module.staticlibfilename^));
  540. Replace(cmdstr,'$FILES',FixFileName(smartpath+current_module.asmprefix^+'*'+target_info.objext));
  541. success:=DoExec(FindUtil(binstr),cmdstr,false,true);
  542. { Clean up }
  543. if not(cs_asm_leave in aktglobalswitches) then
  544. if not(cs_link_extern in aktglobalswitches) then
  545. begin
  546. while not SmartLinkOFiles.Empty do
  547. RemoveFile(SmartLinkOFiles.GetFirst);
  548. RemoveDir(smartpath);
  549. end
  550. else
  551. begin
  552. AsmRes.AddDeleteCommand(FixFileName(smartpath+current_module.asmprefix^+'*'+target_info.objext));
  553. AsmRes.Add('rmdir '+smartpath);
  554. end;
  555. MakeStaticLibrary:=success;
  556. end;
  557. {*****************************************************************************
  558. TINTERNALLINKER
  559. *****************************************************************************}
  560. Constructor TInternalLinker.Create;
  561. begin
  562. inherited Create;
  563. exemap:=nil;
  564. exeoutput:=nil;
  565. end;
  566. Destructor TInternalLinker.Destroy;
  567. begin
  568. exeoutput.free;
  569. exeoutput:=nil;
  570. inherited destroy;
  571. end;
  572. procedure TInternalLinker.readobj(const fn:string);
  573. var
  574. objdata : TAsmObjectData;
  575. objinput : tobjectinput;
  576. begin
  577. Comment(V_Info,'Reading object '+fn);
  578. objinput:=exeoutput.newobjectinput;
  579. objdata:=objinput.newobjectdata(fn);
  580. if objinput.readobjectfile(fn,objdata) then
  581. exeoutput.addobjdata(objdata);
  582. { release input object }
  583. objinput.free;
  584. end;
  585. function TInternalLinker.MakeExecutable:boolean;
  586. var
  587. s : string;
  588. begin
  589. MakeExecutable:=false;
  590. { no support yet for libraries }
  591. if (not StaticLibFiles.Empty) or
  592. (not SharedLibFiles.Empty) then
  593. internalerror(123456789);
  594. if (cs_link_map in aktglobalswitches) then
  595. exemap:=texemap.create(current_module.mapfilename^);
  596. { read objects }
  597. readobj(FindObjectFile('prt0','',false));
  598. while not ObjectFiles.Empty do
  599. begin
  600. s:=ObjectFiles.GetFirst;
  601. if s<>'' then
  602. readobj(s);
  603. end;
  604. { generate executable }
  605. exeoutput.GenerateExecutable(current_module.exefilename^);
  606. { close map }
  607. if assigned(exemap) then
  608. begin
  609. exemap.free;
  610. exemap:=nil;
  611. end;
  612. MakeExecutable:=true;
  613. end;
  614. {*****************************************************************************
  615. Init/Done
  616. *****************************************************************************}
  617. procedure InitLinker;
  618. var
  619. lk : TlinkerClass;
  620. begin
  621. if (cs_link_internal in aktglobalswitches) and
  622. assigned(target_info.link) then
  623. begin
  624. lk:=TLinkerClass(target_info.link);
  625. linker:=lk.Create;
  626. end
  627. else if assigned(target_info.linkextern) then
  628. begin
  629. lk:=TlinkerClass(target_info.linkextern);
  630. linker:=lk.Create;
  631. end
  632. else
  633. begin
  634. linker:=Tlinker.Create;
  635. end;
  636. end;
  637. procedure DoneLinker;
  638. begin
  639. if assigned(linker) then
  640. Linker.Free;
  641. end;
  642. {*****************************************************************************
  643. Initialize
  644. *****************************************************************************}
  645. const
  646. ar_gnu_ar_info : tarinfo =
  647. (
  648. id : ar_gnu_ar;
  649. arcmd : 'ar rs $LIB $FILES'
  650. );
  651. initialization
  652. RegisterAr(ar_gnu_ar_info);
  653. end.