link.pas 17 KB

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