link.pas 22 KB

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