link.pas 20 KB

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