link.pas 20 KB

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