link.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 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. Interface
  21. { Needed for LFN support in path to the executable }
  22. {$ifdef GO32V2}
  23. {$define ALWAYSSHELL}
  24. {$endif}
  25. uses cobjects,files;
  26. Type
  27. TLinkerInfo=record
  28. ExeCmd,
  29. DllCmd : array[1..3] of string[80];
  30. ResName : string[12];
  31. ExtraOptions : string;
  32. DynamicLinker : string[80];
  33. end;
  34. PLinker=^TLinker;
  35. TLinker = Object
  36. public
  37. Info : TLinkerInfo;
  38. ObjectFiles,
  39. SharedLibFiles,
  40. StaticLibFiles : TStringContainer;
  41. { Methods }
  42. Constructor Init;
  43. Destructor Done;
  44. procedure AddModuleFiles(hp:pmodule);
  45. function FindObjectFile(s : string) : string;
  46. function FindLibraryFile(s:string;const ext:string) : string;
  47. Procedure AddObject(const S : String);
  48. Procedure AddStaticLibrary(const S : String);
  49. Procedure AddSharedLibrary(S : String);
  50. Function FindUtil(const s:string):String;
  51. Function DoExec(const command,para:string;showinfo,useshell:boolean):boolean;
  52. { Virtuals }
  53. procedure SetDefaultInfo;virtual;
  54. Function MakeExecutable:boolean;virtual;
  55. Function MakeSharedLibrary:boolean;virtual;
  56. Function MakeStaticLibrary:boolean;virtual;
  57. end;
  58. Var
  59. Linker : PLinker;
  60. procedure InitLinker;
  61. procedure DoneLinker;
  62. Implementation
  63. uses
  64. {$ifdef Delphi}
  65. dmisc,
  66. {$else Delphi}
  67. dos,
  68. {$endif Delphi}
  69. globtype,systems,
  70. script,globals,verbose,ppu
  71. {$ifdef i386}
  72. {$ifndef NOTARGETLINUX}
  73. ,t_linux
  74. {$endif}
  75. {$ifndef NOTARGETOS2}
  76. ,t_os2
  77. {$endif}
  78. {$ifndef NOTARGETWIN32}
  79. ,t_win32
  80. {$endif}
  81. {$ifndef NOTARGETGO32V1}
  82. ,t_go32v1
  83. {$endif}
  84. {$ifndef NOTARGETGO32V2}
  85. ,t_go32v2
  86. {$endif}
  87. {$endif}
  88. {$ifdef m68k}
  89. {$ifndef NOTARGETLINUX}
  90. ,t_linux
  91. {$endif}
  92. {$endif}
  93. {$ifdef powerpc}
  94. {$ifndef NOTARGETLINUX}
  95. ,t_linux
  96. {$endif}
  97. {$endif}
  98. {$ifdef alpha}
  99. {$ifndef NOTARGETLINUX}
  100. ,t_linux
  101. {$endif}
  102. {$endif}
  103. ,gendef
  104. ;
  105. {*****************************************************************************
  106. TLINKER
  107. *****************************************************************************}
  108. Constructor TLinker.Init;
  109. begin
  110. ObjectFiles.Init_no_double;
  111. SharedLibFiles.Init_no_double;
  112. StaticLibFiles.Init_no_double;
  113. { set generic defaults }
  114. FillChar(Info,sizeof(Info),0);
  115. Info.ResName:='link.res';
  116. { set the linker specific defaults }
  117. SetDefaultInfo;
  118. { Allow Parameter overrides for linker info }
  119. with Info do
  120. begin
  121. if ParaLinkOptions<>'' then
  122. ExtraOptions:=ParaLinkOptions;
  123. if ParaDynamicLinker<>'' then
  124. DynamicLinker:=ParaDynamicLinker;
  125. end;
  126. end;
  127. Destructor TLinker.Done;
  128. begin
  129. ObjectFiles.Done;
  130. SharedLibFiles.Done;
  131. StaticLibFiles.Done;
  132. end;
  133. Procedure TLinker.SetDefaultInfo;
  134. begin
  135. end;
  136. procedure TLinker.AddModuleFiles(hp:pmodule);
  137. var
  138. mask : longint;
  139. {$IFDEF NEWST}
  140. procedure addobj(action:pointer);{$IFDEF TP}far;{$ENDIF}
  141. begin
  142. if Plinkitem(action)^.needlink and mask<>0 then
  143. addobject(Plinkitem(action)^.data^);
  144. end;
  145. procedure addstat(action:pointer);{$IFDEF TP}far;{$ENDIF}
  146. begin
  147. if Plinkitem(action)^.needlink and mask<>0 then
  148. addstaticlibrary(Plinkitem(action)^.data^);
  149. end;
  150. procedure addshar(action:pointer);{$IFDEF TP}far;{$ENDIF}
  151. begin
  152. if Plinkitem(action)^.needlink and mask<>0 then
  153. addsharedlibrary(Plinkitem(action)^.data^);
  154. end;
  155. {$ENDIF NEWST}
  156. begin
  157. with hp^ do
  158. begin
  159. { link unit files }
  160. if (flags and uf_no_link)=0 then
  161. begin
  162. { create mask which unit files need linking }
  163. mask:=link_allways;
  164. if hp^.is_unit then
  165. begin
  166. { static linking ? }
  167. if (cs_link_static in aktglobalswitches) then
  168. begin
  169. if (flags and uf_static_linked)=0 then
  170. begin
  171. { if smart not avail then try static linking }
  172. if (flags and uf_static_linked)<>0 then
  173. begin
  174. Comment(V_Hint,'unit '+modulename^+' can''t be static linked, switching to smart linking');
  175. mask:=mask or link_smart;
  176. end
  177. else
  178. Comment(V_Error,'unit '+modulename^+' can''t be smart or static linked');
  179. end
  180. else
  181. mask:=mask or link_static;
  182. end;
  183. { smart linking ? }
  184. if (cs_link_smart in aktglobalswitches) then
  185. begin
  186. if (flags and uf_smart_linked)=0 then
  187. begin
  188. { if smart not avail then try static linking }
  189. if (flags and uf_static_linked)<>0 then
  190. begin
  191. Comment(V_Hint,'unit '+modulename^+' can''t be smart linked, switching to static linking');
  192. mask:=mask or link_static;
  193. end
  194. else
  195. Comment(V_Error,'unit '+modulename^+' can''t be smart or static linked');
  196. end
  197. else
  198. mask:=mask or link_smart;
  199. end;
  200. { shared linking }
  201. if (cs_link_shared in aktglobalswitches) then
  202. begin
  203. if (flags and uf_shared_linked)=0 then
  204. begin
  205. { if shared not avail then try static linking }
  206. if (flags and uf_static_linked)<>0 then
  207. begin
  208. Comment(V_Hint,'unit '+modulename^+' can''t be shared linked, switching to static linking');
  209. mask:=mask or link_static;
  210. end
  211. else
  212. Comment(V_Error,'unit '+modulename^+' can''t be shared or static linked');
  213. end
  214. else
  215. mask:=mask or link_shared;
  216. end;
  217. end
  218. else
  219. begin
  220. { for programs link always static }
  221. mask:=mask or link_static;
  222. end;
  223. { unit files }
  224. {$IFDEF NEWST}
  225. linkunitofiles.foreach(@addobj);
  226. linkunitofiles.freeall;
  227. linkunitstaticlibs.foreach(@addstat);
  228. linkunitstaticlibs.freeall;
  229. linkunitsharedlibs.foreach(@addshar);
  230. linkunitsharedlibs.freeall;
  231. {$ELSE}
  232. while not linkunitofiles.empty do
  233. AddObject(linkunitofiles.getusemask(mask));
  234. while not linkunitstaticlibs.empty do
  235. AddStaticLibrary(linkunitstaticlibs.getusemask(mask));
  236. while not linkunitsharedlibs.empty do
  237. AddSharedLibrary(linkunitsharedlibs.getusemask(mask));
  238. {$ENDIF NEWST}
  239. end;
  240. { Other needed .o and libs, specified using $L,$LINKLIB,external }
  241. mask:=link_allways;
  242. {$IFDEF NEWST}
  243. linkotherofiles.foreach(@addobj);
  244. linkotherofiles.freeall;
  245. linkotherstaticlibs.foreach(@addstat);
  246. linkotherstaticlibs.freeall;
  247. linkothersharedlibs.foreach(@addshar);
  248. linkothersharedlibs.freeall;
  249. {$ELSE}
  250. while not linkotherofiles.empty do
  251. AddObject(linkotherofiles.Getusemask(mask));
  252. while not linkotherstaticlibs.empty do
  253. AddStaticLibrary(linkotherstaticlibs.Getusemask(mask));
  254. while not linkothersharedlibs.empty do
  255. AddSharedLibrary(linkothersharedlibs.Getusemask(mask));
  256. {$ENDIF NEWST}
  257. end;
  258. end;
  259. Function TLinker.FindUtil(const s:string):string;
  260. var
  261. ldfound : boolean;
  262. LastBin : string;
  263. begin
  264. LastBin:='';
  265. if utilsdirectory<>'' then
  266. LastBin:=FindFile(s+source_os.exeext,utilsdirectory,ldfound)+s+source_os.exeext;
  267. if LastBin='' then
  268. LastBin:=FindExe(s,ldfound);
  269. if (not ldfound) and not(cs_link_extern in aktglobalswitches) then
  270. begin
  271. Message1(exec_w_util_not_found,s);
  272. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  273. end;
  274. if ldfound then
  275. Message1(exec_t_using_util,LastBin);
  276. FindUtil:=LastBin;
  277. end;
  278. { searches an object file }
  279. function TLinker.FindObjectFile(s:string) : string;
  280. var
  281. found : boolean;
  282. begin
  283. findobjectfile:='';
  284. if s='' then
  285. exit;
  286. if pos('.',s)=0 then
  287. s:=s+target_info.objext;
  288. s:=FixFileName(s);
  289. if FileExists(s) then
  290. begin
  291. Findobjectfile:=s;
  292. exit;
  293. end;
  294. { find object file
  295. 1. cwd
  296. 2. unit search path
  297. 3. local object path
  298. 4. global object path
  299. 5. exepath }
  300. found:=false;
  301. findobjectfile:=FindFile(s,'.'+DirSep,found)+s;
  302. if (not found) then
  303. findobjectfile:=UnitSearchPath.FindFile(s,found)+s;
  304. if (not found) then
  305. findobjectfile:=current_module^.localobjectsearchpath.FindFile(s,found)+s;
  306. if (not found) then
  307. findobjectfile:=objectsearchpath.FindFile(s,found)+s;
  308. if (not found) then
  309. findobjectfile:=FindFile(s,exepath,found)+s;
  310. if not(cs_link_extern in aktglobalswitches) and (not found) then
  311. Message1(exec_w_objfile_not_found,s);
  312. end;
  313. { searches an library file }
  314. function TLinker.FindLibraryFile(s:string;const ext:string) : string;
  315. var
  316. found : boolean;
  317. begin
  318. findlibraryfile:='';
  319. if s='' then
  320. exit;
  321. if pos('.',s)=0 then
  322. s:=s+ext;
  323. if FileExists(s) then
  324. begin
  325. FindLibraryFile:=s;
  326. exit;
  327. end;
  328. { find libary
  329. 1. cwd
  330. 2. local libary dir
  331. 3. global libary dir
  332. 4. exe path of the compiler }
  333. found:=false;
  334. findlibraryfile:=FindFile(s,'.'+DirSep,found)+s;
  335. if (not found) then
  336. findlibraryfile:=current_module^.locallibrarysearchpath.FindFile(s,found)+s;
  337. if (not found) then
  338. findlibraryfile:=librarysearchpath.FindFile(s,found)+s;
  339. if (not found) then
  340. findlibraryfile:=FindFile(s,exepath,found)+s;
  341. if not(cs_link_extern in aktglobalswitches) and (not found) then
  342. Message1(exec_w_libfile_not_found,s);
  343. end;
  344. Procedure TLinker.AddObject(const S : String);
  345. begin
  346. ObjectFiles.Insert(FindObjectFile(s));
  347. end;
  348. Procedure TLinker.AddSharedLibrary(S:String);
  349. begin
  350. { remove prefix 'lib' }
  351. if Copy(s,1,length(target_os.libprefix))=target_os.libprefix then
  352. Delete(s,1,length(target_os.libprefix));
  353. { remove extension if any }
  354. if Copy(s,length(s)-length(target_os.sharedlibext)+1,length(target_os.sharedlibext))=target_os.sharedlibext then
  355. Delete(s,length(s)-length(target_os.sharedlibext)+1,length(target_os.sharedlibext)+1);
  356. { ready to be inserted }
  357. SharedLibFiles.Insert (S);
  358. end;
  359. Procedure TLinker.AddStaticLibrary(const S:String);
  360. begin
  361. StaticLibFiles.Insert(FindLibraryFile(s,target_os.staticlibext));
  362. end;
  363. Function TLinker.DoExec(const command,para:string;showinfo,useshell:boolean):boolean;
  364. begin
  365. DoExec:=true;
  366. if not(cs_link_extern in aktglobalswitches) then
  367. begin
  368. swapvectors;
  369. {$ifdef ALWAYSSHELL}
  370. shell(command+' '+para);
  371. {$else}
  372. if useshell then
  373. shell(command+' '+para)
  374. else
  375. exec(command,para);
  376. {$endif}
  377. swapvectors;
  378. if (doserror<>0) then
  379. begin
  380. Message(exec_w_cant_call_linker);
  381. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  382. DoExec:=false;
  383. end
  384. else
  385. if (dosexitcode<>0) then
  386. begin
  387. Message(exec_w_error_while_linking);
  388. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  389. DoExec:=false;
  390. end;
  391. end;
  392. { Update asmres when externmode is set }
  393. if cs_link_extern in aktglobalswitches then
  394. begin
  395. if showinfo then
  396. begin
  397. if DLLsource then
  398. AsmRes.AddLinkCommand(Command,Para,current_module^.sharedlibfilename^)
  399. else
  400. AsmRes.AddLinkCommand(Command,Para,current_module^.exefilename^);
  401. end
  402. else
  403. AsmRes.AddLinkCommand(Command,Para,'');
  404. end;
  405. end;
  406. function TLinker.MakeExecutable:boolean;
  407. begin
  408. MakeExecutable:=false;
  409. Message(exec_e_exe_not_supported);
  410. end;
  411. Function TLinker.MakeSharedLibrary:boolean;
  412. begin
  413. MakeSharedLibrary:=false;
  414. Message(exec_e_dll_not_supported);
  415. end;
  416. Function TLinker.MakeStaticLibrary:boolean;
  417. var
  418. smartpath,
  419. cmdstr,
  420. binstr : string;
  421. success : boolean;
  422. begin
  423. MakeStaticLibrary:=false;
  424. { remove the library, to be sure that it is rewritten }
  425. RemoveFile(current_module^.staticlibfilename^);
  426. { Call AR }
  427. smartpath:=current_module^.outputpath^+FixPath(FixFileName(current_module^.modulename^)+target_info.smartext,false);
  428. SplitBinCmd(target_ar.arcmd,binstr,cmdstr);
  429. Replace(cmdstr,'$LIB',current_module^.staticlibfilename^);
  430. Replace(cmdstr,'$FILES',FixFileName(smartpath+current_module^.asmprefix^+'*'+target_info.objext));
  431. success:=DoExec(FindUtil(binstr),cmdstr,false,true);
  432. { Clean up }
  433. if not(cs_asm_leave in aktglobalswitches) then
  434. if not(cs_link_extern in aktglobalswitches) then
  435. begin
  436. while not SmartLinkOFiles.Empty do
  437. RemoveFile(SmartLinkOFiles.Get);
  438. RemoveDir(smartpath);
  439. end
  440. else
  441. begin
  442. AsmRes.AddDeleteCommand(FixFileName(smartpath+current_module^.asmprefix^+'*'+target_info.objext));
  443. AsmRes.Add('rmdir '+smartpath);
  444. end;
  445. MakeStaticLibrary:=success;
  446. end;
  447. {*****************************************************************************
  448. Init/Done
  449. *****************************************************************************}
  450. procedure InitLinker;
  451. begin
  452. case target_info.target of
  453. {$ifdef i386}
  454. {$ifndef NOTARGETLINUX}
  455. target_i386_linux :
  456. linker:=new(plinkerlinux,Init);
  457. {$endif}
  458. {$ifndef NOTARGETWIN32}
  459. target_i386_Win32 :
  460. linker:=new(plinkerwin32,Init);
  461. {$endif}
  462. {$ifndef NOTARGETGO32V1}
  463. target_i386_Go32v1 :
  464. linker:=new(plinkergo32v1,Init);
  465. {$endif}
  466. {$ifndef NOTARGETGO32V2}
  467. target_i386_Go32v2 :
  468. linker:=new(plinkergo32v2,Init);
  469. {$endif}
  470. {$ifndef NOTARGETOS2}
  471. target_i386_os2 :
  472. linker:=new(plinkeros2,Init);
  473. {$endif}
  474. {$endif i386}
  475. {$ifdef m68k}
  476. {$ifndef NOTARGETPALMOS}
  477. target_m68k_palmos:
  478. linker:=new(plinker,Init);
  479. {$endif}
  480. {$ifndef NOTARGETLINUX}
  481. target_m68k_linux :
  482. linker:=new(plinkerlinux,Init);
  483. {$endif}
  484. {$endif m68k}
  485. {$ifdef alpha}
  486. {$ifndef NOTARGETLINUX}
  487. target_alpha_linux :
  488. linker:=new(plinkerlinux,Init);
  489. {$endif}
  490. {$endif alpha}
  491. {$ifdef powerpc}
  492. {$ifndef NOTARGETLINUX}
  493. target_powerpc_linux :
  494. linker:=new(plinkerlinux,Init);
  495. {$endif}
  496. {$endif powerpc}
  497. else
  498. linker:=new(plinker,Init);
  499. end;
  500. end;
  501. procedure DoneLinker;
  502. begin
  503. if assigned(linker) then
  504. dispose(linker,done);
  505. end;
  506. end.
  507. {
  508. $Log$
  509. Revision 1.85 2000-02-28 17:23:57 daniel
  510. * Current work of symtable integration committed. The symtable can be
  511. activated by defining 'newst', but doesn't compile yet. Changes in type
  512. checking and oop are completed. What is left is to write a new
  513. symtablestack and adapt the parser to use it.
  514. Revision 1.84 2000/02/24 18:41:39 peter
  515. * removed warnings/notes
  516. Revision 1.83 2000/02/09 13:22:54 peter
  517. * log truncated
  518. Revision 1.82 2000/01/14 14:40:37 pierre
  519. * use ./ instead of . to look into startup dir
  520. Revision 1.81 2000/01/12 10:38:18 peter
  521. * smartlinking fixes for binary writer
  522. * release alignreg code and moved instruction writing align to cpuasm,
  523. but it doesn't use the specified register yet
  524. Revision 1.80 2000/01/11 09:52:06 peter
  525. * fixed placing of .sl directories
  526. * use -b again for base-file selection
  527. * fixed group writing for linux with smartlinking
  528. Revision 1.79 2000/01/07 01:14:27 peter
  529. * updated copyright to 2000
  530. Revision 1.78 1999/11/22 22:22:30 pierre
  531. * Give better info in script
  532. Revision 1.77 1999/11/12 11:03:50 peter
  533. * searchpaths changed to stringqueue object
  534. Revision 1.76 1999/11/06 14:34:21 peter
  535. * truncated log to 20 revs
  536. Revision 1.75 1999/10/26 12:25:04 peter
  537. * fixed os2 linker
  538. Revision 1.74 1999/10/21 14:29:34 peter
  539. * redesigned linker object
  540. + library support for linux (only procedures can be exported)
  541. Revision 1.72 1999/09/16 23:05:52 florian
  542. * m68k compiler is again compilable (only gas writer, no assembler reader)
  543. Revision 1.71 1999/09/16 11:34:56 pierre
  544. * typo correction
  545. Revision 1.70 1999/09/15 22:09:16 florian
  546. + rtti is now automatically generated for published classes, i.e.
  547. they are handled like an implicit property
  548. Revision 1.69 1999/09/15 20:24:56 daniel
  549. + Dw switch now does something.
  550. Revision 1.68 1999/08/18 17:05:53 florian
  551. + implemented initilizing of data for the new code generator
  552. so it should compile now simple programs
  553. Revision 1.67 1999/08/16 15:35:23 pierre
  554. * fix for DLL relocation problems
  555. * external bss vars had wrong stabs for pecoff
  556. + -WB11000000 to specify default image base, allows to
  557. load several DLLs with debugging info included
  558. (relocatable DLL are stripped because the relocation
  559. of the .Stab section is misplaced by ldw)
  560. Revision 1.66 1999/08/11 17:26:34 peter
  561. * tlinker object is now inherited for win32 and dos
  562. * postprocessexecutable is now a method of tlinker
  563. Revision 1.65 1999/08/10 12:51:16 pierre
  564. * bind_win32_dll removed (Relocsection used instead)
  565. * now relocsection is true by default ! (needs dlltool
  566. for DLL generation)
  567. Revision 1.64 1999/07/30 23:19:45 peter
  568. * fixed placing of dynamiclinker in link.res (should be the last after
  569. all other libraries)
  570. Revision 1.63 1999/07/29 01:31:39 peter
  571. * fixed shared library linking for glibc2 systems
  572. Revision 1.62 1999/07/27 11:05:51 peter
  573. * glibc 2.1.2 support
  574. }