link.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  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. procedure ExpandAndApplyOrder(var Src:TStringList);
  52. procedure LoadPredefinedLibraryOrder;virtual;
  53. function ReOrderEntries : boolean;
  54. end;
  55. TExternalLinker = class(TLinker)
  56. public
  57. Info : TLinkerInfo;
  58. Constructor Create;override;
  59. Destructor Destroy;override;
  60. Function FindUtil(const s:string):String;
  61. Function DoExec(const command:string; para:TCmdStr;showinfo,useshell:boolean):boolean;
  62. procedure SetDefaultInfo;virtual;
  63. Function MakeStaticLibrary:boolean;override;
  64. end;
  65. TInternalLinker = class(TLinker)
  66. private
  67. procedure readobj(const fn:string);
  68. public
  69. Constructor Create;override;
  70. Destructor Destroy;override;
  71. Function MakeExecutable:boolean;override;
  72. end;
  73. var
  74. Linker : TLinker;
  75. function FindObjectFile(s : string;const unitpath:string;isunit:boolean) : string;
  76. function FindLibraryFile(s:string;const prefix,ext:string;var foundfile : 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. SharedLibFiles:=TStringList.Create_no_double;
  238. StaticLibFiles:=TStringList.Create_no_double;
  239. end;
  240. Destructor TLinker.Destroy;
  241. begin
  242. ObjectFiles.Free;
  243. SharedLibFiles.Free;
  244. StaticLibFiles.Free;
  245. end;
  246. procedure TLinker.AddModuleFiles(hp:tmodule);
  247. var
  248. mask : longint;
  249. begin
  250. with hp do
  251. begin
  252. { link unit files }
  253. if (flags and uf_no_link)=0 then
  254. begin
  255. { create mask which unit files need linking }
  256. mask:=link_allways;
  257. { static linking ? }
  258. if (cs_link_static in aktglobalswitches) then
  259. begin
  260. if (flags and uf_static_linked)=0 then
  261. begin
  262. { if smart not avail then try static linking }
  263. if (flags and uf_smart_linked)<>0 then
  264. begin
  265. Message1(exec_t_unit_not_static_linkable_switch_to_smart,modulename^);
  266. mask:=mask or link_smart;
  267. end
  268. else
  269. Message1(exec_e_unit_not_smart_or_static_linkable,modulename^);
  270. end
  271. else
  272. mask:=mask or link_static;
  273. end;
  274. { smart linking ? }
  275. if (cs_link_smart in aktglobalswitches) then
  276. begin
  277. if (flags and uf_smart_linked)=0 then
  278. begin
  279. { if smart not avail then try static linking }
  280. if (flags and uf_static_linked)<>0 then
  281. begin
  282. Message1(exec_t_unit_not_smart_linkable_switch_to_static,modulename^);
  283. mask:=mask or link_static;
  284. end
  285. else
  286. Message1(exec_e_unit_not_smart_or_static_linkable,modulename^);
  287. end
  288. else
  289. mask:=mask or link_smart;
  290. end;
  291. { shared linking }
  292. if (cs_link_shared in aktglobalswitches) then
  293. begin
  294. if (flags and uf_shared_linked)=0 then
  295. begin
  296. { if shared not avail then try static linking }
  297. if (flags and uf_static_linked)<>0 then
  298. begin
  299. Message1(exec_t_unit_not_shared_linkable_switch_to_static,modulename^);
  300. mask:=mask or link_static;
  301. end
  302. else
  303. Message1(exec_e_unit_not_shared_or_static_linkable,modulename^);
  304. end
  305. else
  306. mask:=mask or link_shared;
  307. end;
  308. { unit files }
  309. while not linkunitofiles.empty do
  310. begin
  311. AddObject(linkunitofiles.getusemask(mask),path^,true);
  312. end;
  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. end;
  327. end;
  328. Procedure TLinker.AddObject(const S,unitpath : String;isunit:boolean);
  329. begin
  330. ObjectFiles.Concat(FindObjectFile(s,unitpath,isunit));
  331. end;
  332. Procedure TLinker.AddSharedLibrary(S:String);
  333. begin
  334. if s='' then
  335. exit;
  336. { remove prefix 'lib' }
  337. if Copy(s,1,length(target_info.sharedlibprefix))=target_info.sharedlibprefix then
  338. Delete(s,1,length(target_info.sharedlibprefix));
  339. { remove extension if any }
  340. if Copy(s,length(s)-length(target_info.sharedlibext)+1,length(target_info.sharedlibext))=target_info.sharedlibext then
  341. Delete(s,length(s)-length(target_info.sharedlibext)+1,length(target_info.sharedlibext)+1);
  342. { ready to be added }
  343. SharedLibFiles.Concat(S);
  344. end;
  345. Procedure TLinker.AddStaticLibrary(const S:String);
  346. var
  347. ns : string;
  348. found : boolean;
  349. begin
  350. if s='' then
  351. exit;
  352. found:=FindLibraryFile(s,target_info.staticlibprefix,target_info.staticlibext,ns);
  353. if not(cs_link_extern in aktglobalswitches) and (not found) then
  354. Message1(exec_w_libfile_not_found,s);
  355. StaticLibFiles.Concat(ns);
  356. end;
  357. Procedure TLinker.AddSharedCLibrary(S:String);
  358. begin
  359. if s='' then
  360. exit;
  361. { remove prefix 'lib' }
  362. if Copy(s,1,length(target_info.sharedclibprefix))=target_info.sharedclibprefix then
  363. Delete(s,1,length(target_info.sharedclibprefix));
  364. { remove extension if any }
  365. if Copy(s,length(s)-length(target_info.sharedclibext)+1,length(target_info.sharedclibext))=target_info.sharedclibext then
  366. Delete(s,length(s)-length(target_info.sharedclibext)+1,length(target_info.sharedclibext)+1);
  367. { ready to be added }
  368. SharedLibFiles.Concat(S);
  369. end;
  370. Procedure TLinker.AddStaticCLibrary(const S:String);
  371. var
  372. ns : string;
  373. found : boolean;
  374. begin
  375. if s='' then
  376. exit;
  377. found:=FindLibraryFile(s,target_info.staticclibprefix,target_info.staticclibext,ns);
  378. if not(cs_link_extern in aktglobalswitches) and (not found) then
  379. Message1(exec_w_libfile_not_found,s);
  380. StaticLibFiles.Concat(ns);
  381. end;
  382. function TLinker.MakeExecutable:boolean;
  383. begin
  384. MakeExecutable:=false;
  385. Message(exec_e_exe_not_supported);
  386. end;
  387. Function TLinker.MakeSharedLibrary:boolean;
  388. begin
  389. MakeSharedLibrary:=false;
  390. Message(exec_e_dll_not_supported);
  391. end;
  392. Function TLinker.MakeStaticLibrary:boolean;
  393. begin
  394. MakeStaticLibrary:=false;
  395. Message(exec_e_dll_not_supported);
  396. end;
  397. Procedure TLinker.ExpandAndApplyOrder(var Src:TStringList);
  398. var p : TLinkStrMap;
  399. i : Integer;
  400. begin
  401. // call Virtual TLinker method to initialize
  402. LoadPredefinedLibraryOrder;
  403. // something to do?
  404. if (LinkLibraryAliases.count=0) and (LinkLibraryOrder.Count=0) Then
  405. exit;
  406. p:=TLinkStrMap.Create;
  407. // expand libaliases, clears src
  408. LinkLibraryAliases.expand(src,p);
  409. // writeln(src.count,' ',p.count,' ',linklibraryorder.count,' ',linklibraryaliases.count);
  410. // apply order
  411. p.UpdateWeights(LinkLibraryOrder);
  412. p.SortOnWeight;
  413. // put back in src
  414. for i:=0 to p.count-1 do
  415. src.insert(p[i].Key);
  416. p.free;
  417. end;
  418. procedure TLinker.LoadPredefinedLibraryOrder;
  419. begin
  420. end;
  421. function TLinker.ReOrderEntries : boolean;
  422. begin
  423. result:=(LinkLibraryOrder.count>0) or (LinkLibraryAliases.count>0);
  424. end;
  425. {*****************************************************************************
  426. TEXTERNALLINKER
  427. *****************************************************************************}
  428. Constructor TExternalLinker.Create;
  429. begin
  430. inherited Create;
  431. { set generic defaults }
  432. FillChar(Info,sizeof(Info),0);
  433. if cs_link_on_target in aktglobalswitches then
  434. begin
  435. Info.ResName:=outputexedir+inputfile+'_link.res';
  436. Info.ScriptName:=outputexedir+inputfile+'_script.res';
  437. end
  438. else
  439. begin
  440. Info.ResName:='link.res';
  441. Info.ScriptName:='script.res';
  442. end;
  443. { set the linker specific defaults }
  444. SetDefaultInfo;
  445. { Allow Parameter overrides for linker info }
  446. with Info do
  447. begin
  448. if ParaLinkOptions<>'' then
  449. ExtraOptions:=ParaLinkOptions;
  450. if ParaDynamicLinker<>'' then
  451. DynamicLinker:=ParaDynamicLinker;
  452. end;
  453. end;
  454. Destructor TExternalLinker.Destroy;
  455. begin
  456. inherited destroy;
  457. end;
  458. Procedure TExternalLinker.SetDefaultInfo;
  459. begin
  460. end;
  461. Function TExternalLinker.FindUtil(const s:string):string;
  462. var
  463. Found : boolean;
  464. FoundBin : string;
  465. UtilExe : string;
  466. begin
  467. if cs_link_on_target in aktglobalswitches then
  468. begin
  469. { If linking on target, don't add any path PM }
  470. FindUtil:=AddExtension(s,target_info.exeext);
  471. exit;
  472. end;
  473. UtilExe:=AddExtension(s,source_info.exeext);
  474. FoundBin:='';
  475. Found:=false;
  476. if utilsdirectory<>'' then
  477. Found:=FindFile(utilexe,utilsdirectory,Foundbin);
  478. if (not Found) then
  479. Found:=FindExe(utilexe,Foundbin);
  480. if (not Found) and not(cs_link_extern in aktglobalswitches) then
  481. begin
  482. Message1(exec_e_util_not_found,utilexe);
  483. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  484. end;
  485. if (FoundBin<>'') then
  486. Message1(exec_t_using_util,FoundBin);
  487. FindUtil:=FoundBin;
  488. end;
  489. Function TExternalLinker.DoExec(const command:string; para:TCmdStr;showinfo,useshell:boolean):boolean;
  490. var
  491. exitcode: longint;
  492. begin
  493. DoExec:=true;
  494. if not(cs_link_extern in aktglobalswitches) then
  495. begin
  496. FlushOutput;
  497. if useshell then
  498. exitcode := shell(maybequoted(command)+' '+para)
  499. else
  500. {$IFDEF USE_SYSUTILS}
  501. try
  502. if ExecuteProcess(command,para) <> 0
  503. then begin
  504. Message(exec_e_error_while_linking);
  505. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  506. DoExec:=false;
  507. end;
  508. except on E:EOSError do
  509. begin
  510. Message(exec_e_cant_call_linker);
  511. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  512. DoExec:=false;
  513. end;
  514. end
  515. end;
  516. {$ELSE USE_SYSUTILS}
  517. begin
  518. swapvectors;
  519. exec(command,para);
  520. swapvectors;
  521. exitcode := dosexitcode;
  522. end;
  523. if (doserror<>0) then
  524. begin
  525. Message(exec_e_cant_call_linker);
  526. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  527. DoExec:=false;
  528. end
  529. else
  530. if (exitcode<>0) then
  531. begin
  532. Message(exec_e_error_while_linking);
  533. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  534. DoExec:=false;
  535. end;
  536. end;
  537. {$ENDIF USE_SYSUTILS}
  538. { Update asmres when externmode is set }
  539. if cs_link_extern in aktglobalswitches then
  540. begin
  541. if showinfo then
  542. begin
  543. if DLLsource then
  544. AsmRes.AddLinkCommand(Command,Para,current_module.sharedlibfilename^)
  545. else
  546. AsmRes.AddLinkCommand(Command,Para,current_module.exefilename^);
  547. end
  548. else
  549. AsmRes.AddLinkCommand(Command,Para,'');
  550. end;
  551. end;
  552. Function TExternalLinker.MakeStaticLibrary:boolean;
  553. var
  554. smartpath : TCmdStr;
  555. function GetNextFiles(const maxCmdLength : AInt; var item : TStringListItem) : string;
  556. begin
  557. result := '';
  558. while (assigned(item) and ((length(result) + length(item.str) + 1) < maxCmdLength)) do begin
  559. result := result + ' ' + item.str;
  560. item := TStringListItem(item.next);
  561. end;
  562. end;
  563. var
  564. binstr : string;
  565. success : boolean;
  566. cmdstr, nextcmd : TCmdStr;
  567. current : TStringListItem;
  568. begin
  569. MakeStaticLibrary:=false;
  570. { remove the library, to be sure that it is rewritten }
  571. RemoveFile(current_module.staticlibfilename^);
  572. { Call AR }
  573. smartpath:=current_module.outputpath^+FixPath(current_module.newfilename^+target_info.smartext,false);
  574. SplitBinCmd(target_ar.arcmd,binstr,cmdstr);
  575. binstr := FindUtil(utilsprefix + binstr);
  576. Replace(cmdstr,'$LIB',maybequoted(current_module.staticlibfilename^));
  577. { create AR commands }
  578. success := true;
  579. nextcmd := cmdstr;
  580. current := TStringListItem(SmartLinkOFiles.First);
  581. repeat
  582. Replace(nextcmd,'$FILES',GetNextFiles(240 - length(nextcmd) + 6 - length(binstr) - 1, current));
  583. success:=DoExec(binstr,nextcmd,false,true);
  584. nextcmd := cmdstr;
  585. until (not assigned(current)) or (not success);
  586. { Clean up }
  587. if not(cs_asm_leave in aktglobalswitches) then
  588. if not(cs_link_extern in aktglobalswitches) then
  589. begin
  590. while not SmartLinkOFiles.Empty do
  591. RemoveFile(SmartLinkOFiles.GetFirst);
  592. RemoveDir(smartpath);
  593. end
  594. else
  595. begin
  596. AsmRes.AddDeleteCommand(FixFileName(smartpath+current_module.asmprefix^+'*'+target_info.objext));
  597. AsmRes.AddDeleteDirCommand(smartpath);
  598. end;
  599. MakeStaticLibrary:=success;
  600. end;
  601. {*****************************************************************************
  602. TINTERNALLINKER
  603. *****************************************************************************}
  604. Constructor TInternalLinker.Create;
  605. begin
  606. inherited Create;
  607. exemap:=nil;
  608. exeoutput:=nil;
  609. end;
  610. Destructor TInternalLinker.Destroy;
  611. begin
  612. exeoutput.free;
  613. exeoutput:=nil;
  614. inherited destroy;
  615. end;
  616. procedure TInternalLinker.readobj(const fn:string);
  617. var
  618. objdata : TAsmObjectData;
  619. objinput : tobjectinput;
  620. begin
  621. Comment(V_Info,'Reading object '+fn);
  622. objinput:=exeoutput.newobjectinput;
  623. objdata:=objinput.newobjectdata(fn);
  624. if objinput.readobjectfile(fn,objdata) then
  625. exeoutput.addobjdata(objdata);
  626. { release input object }
  627. objinput.free;
  628. end;
  629. function TInternalLinker.MakeExecutable:boolean;
  630. var
  631. s : string;
  632. begin
  633. MakeExecutable:=false;
  634. { no support yet for libraries }
  635. if (not StaticLibFiles.Empty) or
  636. (not SharedLibFiles.Empty) then
  637. internalerror(123456789);
  638. if (cs_link_map in aktglobalswitches) then
  639. exemap:=texemap.create(current_module.mapfilename^);
  640. { read objects }
  641. readobj(FindObjectFile('prt0','',false));
  642. while not ObjectFiles.Empty do
  643. begin
  644. s:=ObjectFiles.GetFirst;
  645. if s<>'' then
  646. readobj(s);
  647. end;
  648. { generate executable }
  649. exeoutput.GenerateExecutable(current_module.exefilename^);
  650. { close map }
  651. if assigned(exemap) then
  652. begin
  653. exemap.free;
  654. exemap:=nil;
  655. end;
  656. MakeExecutable:=true;
  657. end;
  658. {*****************************************************************************
  659. Init/Done
  660. *****************************************************************************}
  661. procedure InitLinker;
  662. var
  663. lk : TlinkerClass;
  664. begin
  665. if (cs_link_internal in aktglobalswitches) and
  666. assigned(target_info.link) then
  667. begin
  668. lk:=TLinkerClass(target_info.link);
  669. linker:=lk.Create;
  670. end
  671. else if assigned(target_info.linkextern) then
  672. begin
  673. lk:=TlinkerClass(target_info.linkextern);
  674. linker:=lk.Create;
  675. end
  676. else
  677. begin
  678. linker:=Tlinker.Create;
  679. end;
  680. end;
  681. procedure DoneLinker;
  682. begin
  683. if assigned(linker) then
  684. Linker.Free;
  685. end;
  686. {*****************************************************************************
  687. Initialize
  688. *****************************************************************************}
  689. const
  690. ar_gnu_ar_info : tarinfo =
  691. (
  692. id : ar_gnu_ar;
  693. arcmd : 'ar rs $LIB $FILES'
  694. );
  695. initialization
  696. RegisterAr(ar_gnu_ar_info);
  697. end.