t_nwl.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. {
  2. Copyright (c) 1998-2004 by Peter Vreman
  3. This unit implements support import,export,link routines
  4. for the (i386) Netware libc target
  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. Currently generating NetWare-NLM's only work under Linux and win32.
  17. (see http://home.arcor.de/armin.diehl/fpcnw for binutils working
  18. with win32) while not included in fpc-releases.
  19. The following compiler-swiches are supported for NetWare:
  20. $DESCRIPTION : NLM-Description, will be displayed at load-time
  21. $M : For Stack-Size, Heap-Size will be ignored
  22. 32K is the accepted minimum
  23. $VERSION x.x.x : Sets Major, Minor and Revision
  24. $SCREENNAME : Sets the ScreenName
  25. $THREADNAME : Sets current threadname
  26. Additional parameters for the nlmvonv-inputfile can be passed with
  27. -k, i.e. -kREENTRANT will add the option REENTRANT to the nlmconv
  28. inputfile. A ; will be converted into a newline
  29. Exports will be handled like in win32:
  30. procedure bla; cdecl;
  31. begin
  32. end;
  33. exports foo name 'Bar';
  34. The path to the import-Files must be specified by the library-path.
  35. All external modules are defined as autoload. (Note: the import-files have
  36. to be in unix-format for exe2nlm)
  37. By default, the most import files are included in freepascal.
  38. e.g. function getgrnam(name:Pchar):Pgroup;cdecl;external 'libc' 'getgrnam';
  39. sets IMPORT @libc.imp and MODULE libc.
  40. To avoid setting the autoload, use ! in the name, e.g.
  41. procedure EnterDebugger;cdecl;external '!netware' name 'EnterDebugger';
  42. Function simply defined as external work without generating autoload and
  43. IMPORT but you will get a warning from nlmconv.
  44. If you dont have nlmconv, compile gnu-binutils with
  45. ./configure --enable-targets=i386-netware
  46. make all
  47. Debugging is possible with gdb and a converter from gdb to ndi available
  48. at http://home.arcor.de/armin.diehl/gdbnw
  49. A sample program:
  50. Program Hello;
  51. (*$DESCRIPTION HelloWorldNlm*)
  52. (*$VERSION 1.2.3*)
  53. (*$ScreenName Hello*)
  54. (*$M 60000,60000*)
  55. begin
  56. writeLn ('hello world');
  57. end.
  58. compile with:
  59. ppc386 -Tnetwlibc hello
  60. Libraries are supported but this needs at least netware 5.1 sp6,
  61. 6.0 sp3 or netware 6.5
  62. In case there is a xdc file with the same name as the nlm name,
  63. this file will be used for nlmconv. Otherwise a temp xdc will
  64. be created and used.
  65. ****************************************************************************
  66. }
  67. unit t_nwl;
  68. {$i fpcdefs.inc}
  69. interface
  70. implementation
  71. {$ifdef netwlibc}
  72. {$define netware}
  73. {$endif}
  74. uses
  75. SysUtils,
  76. cutils,cfileutils,
  77. verbose,systems,globtype,globals,
  78. symconst,script,
  79. fmodule,aasmbase,aasmtai,aasmdata,aasmcpu,cpubase,symsym,symdef,
  80. import,export,link,i_nwl,ogbase
  81. {$ifdef netware} ,dos {$endif}
  82. ;
  83. type
  84. timportlibnetwlibc=class(timportlib)
  85. procedure generatelib;override;
  86. end;
  87. texportlibnetwlibc=class(texportlib)
  88. procedure preparelib(const s : string);override;
  89. procedure exportprocedure(hp : texported_item);override;
  90. procedure exportvar(hp : texported_item);override;
  91. procedure generatelib;override;
  92. end;
  93. tlinkernetwlibc=class(texternallinker)
  94. private
  95. NLMConvLinkFile: TLinkRes; {for second pass, fist pass is ld}
  96. Function WriteResponseFile(isdll:boolean) : Boolean;
  97. public
  98. constructor Create;override;
  99. procedure SetDefaultInfo;override;
  100. function MakeNetwareLoadableModule (isLib : boolean):boolean;
  101. function MakeExecutable:boolean;override;
  102. function MakeSharedLibrary:boolean;override;
  103. end;
  104. Const tmpLinkFileName = '~link~tmp.o';
  105. minStackSize = 32768;
  106. {*****************************************************************************
  107. TIMPORTLIBNETWARE
  108. *****************************************************************************}
  109. procedure timportlibnetwlibc.generatelib;
  110. var
  111. i : longint;
  112. ImportLibrary : TImportLibrary;
  113. begin
  114. for i:=0 to current_module.ImportLibraryList.Count-1 do
  115. begin
  116. ImportLibrary:=TImportLibrary(current_module.ImportLibraryList[i]);
  117. current_module.linkothersharedlibs.add(ImportLibrary.Name,link_always);
  118. end;
  119. end;
  120. {*****************************************************************************
  121. TEXPORTLIBNETWARE
  122. *****************************************************************************}
  123. procedure texportlibnetwlibc.preparelib(const s:string);
  124. begin
  125. end;
  126. procedure texportlibnetwlibc.exportprocedure(hp : texported_item);
  127. var
  128. hp2 : texported_item;
  129. begin
  130. { first test the index value }
  131. if (hp.options and eo_index)<>0 then
  132. begin
  133. Comment(V_Error,'can''t export with index under netware');
  134. exit;
  135. end;
  136. { use pascal name is none specified }
  137. if (hp.options and eo_name)=0 then
  138. begin
  139. hp.name:=stringdup(hp.sym.name);
  140. hp.options:=hp.options or eo_name;
  141. end;
  142. { now place in correct order }
  143. hp2:=texported_item(current_module._exports.first);
  144. while assigned(hp2) and
  145. (hp.name^>hp2.name^) do
  146. hp2:=texported_item(hp2.next);
  147. { insert hp there !! }
  148. if assigned(hp2) and (hp2.name^=hp.name^) then
  149. begin
  150. { this is not allowed !! }
  151. Message1(parser_e_export_name_double,hp.name^);
  152. exit;
  153. end;
  154. if hp2=texported_item(current_module._exports.first) then
  155. current_module._exports.insert(hp)
  156. else if assigned(hp2) then
  157. begin
  158. hp.next:=hp2;
  159. hp.previous:=hp2.previous;
  160. if assigned(hp2.previous) then
  161. hp2.previous.next:=hp;
  162. hp2.previous:=hp;
  163. end
  164. else
  165. current_module._exports.concat(hp);
  166. end;
  167. procedure texportlibnetwlibc.exportvar(hp : texported_item);
  168. begin
  169. hp.is_var:=true;
  170. exportprocedure(hp);
  171. end;
  172. procedure texportlibnetwlibc.generatelib;
  173. var
  174. hp2 : texported_item;
  175. pd : tprocdef;
  176. begin
  177. hp2:=texported_item(current_module._exports.first);
  178. while assigned(hp2) do
  179. begin
  180. if (not hp2.is_var) and
  181. (hp2.sym.typ=procsym) then
  182. begin
  183. { the manglednames can already be the same when the procedure
  184. is declared with cdecl }
  185. pd:=tprocdef(tprocsym(hp2.sym).ProcdefList[0]);
  186. if pd.mangledname<>hp2.name^ then
  187. begin
  188. {$ifdef i386}
  189. { place jump in al_procedures }
  190. current_asmdata.asmlists[al_procedures].concat(Tai_align.Create_op(4,$90));
  191. current_asmdata.asmlists[al_procedures].concat(Tai_symbol.Createname_global(hp2.name^,AT_FUNCTION,0));
  192. current_asmdata.asmlists[al_procedures].concat(Taicpu.Op_sym(A_JMP,S_NO,current_asmdata.RefAsmSymbol(pd.mangledname)));
  193. current_asmdata.asmlists[al_procedures].concat(Tai_symbol_end.Createname(hp2.name^));
  194. {$endif i386}
  195. end;
  196. end
  197. else
  198. //Comment(V_Error,'Exporting of variables is not supported under netware');
  199. Message1(parser_e_no_export_of_variables_for_target,'netware');
  200. hp2:=texported_item(hp2.next);
  201. end;
  202. end;
  203. {*****************************************************************************
  204. TLINKERNETWARE
  205. *****************************************************************************}
  206. Constructor TLinkerNetwlibc.Create;
  207. begin
  208. Inherited Create;
  209. end;
  210. procedure TLinkerNetwlibc.SetDefaultInfo;
  211. begin
  212. with Info do
  213. begin
  214. {$ifndef netware}
  215. ExeCmd[1]:= FindUtil(utilsprefix+'ld') + ' -Ur -T $RES $STRIP -o $TMPOBJ';
  216. ExeCmd[2]:= FindUtil(utilsprefix+'nlmconv') + ' -T$RES';
  217. {$else}
  218. {for running on netware we need absolute pathes since ld has another working directory}
  219. ExeCmd[1]:= FindUtil(utilsprefix+'ld') + ' -Ur -T '+FExpand(outputexedir+Info.ResName)+' $STRIP -o '+Fexpand(outputexedir+tmpLinkFileName);
  220. ExeCmd[2]:= FindUtil(utilsprefix+'nlmconv') + ' -T'+FExpand(outputexedir+'n'+Info.ResName);
  221. {$endif}
  222. end;
  223. end;
  224. Function TLinkerNetwlibc.WriteResponseFile(isdll:boolean) : Boolean;
  225. Var
  226. linkres : TLinkRes;
  227. i : longint;
  228. s,s2,s3 : TCmdStr;
  229. ProgNam : string [80];
  230. NlmNam : string [80];
  231. hp2 : texported_item; { for exports }
  232. p : byte;
  233. begin
  234. WriteResponseFile:=False;
  235. ProgNam := current_module.exefilename^;
  236. i:=Pos(target_info.exeext,ProgNam);
  237. if i>0 then
  238. Delete(ProgNam,i,255);
  239. NlmNam := ProgNam + target_info.exeext;
  240. { Open link.res file }
  241. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName); {for ld}
  242. NLMConvLinkFile:=TLinkRes.Create(outputexedir+'n'+Info.ResName); {for nlmconv, written in CreateExeFile}
  243. p := Pos ('"', Description);
  244. while (p > 0) do
  245. begin
  246. delete (Description,p,1);
  247. p := Pos ('"', Description);
  248. end;
  249. if Description <> '' then
  250. NLMConvLinkFile.Add('DESCRIPTION "' + Description + '"');
  251. NLMConvLinkFile.Add('VERSION '+tostr(dllmajor)+','+tostr(dllminor)+','+tostr(dllrevision));
  252. p := Pos ('"', nwscreenname);
  253. while (p > 0) do
  254. begin
  255. delete (nwscreenname,p,1);
  256. p := Pos ('"', nwscreenname);
  257. end;
  258. p := Pos ('"', nwthreadname);
  259. while (p > 0) do
  260. begin
  261. delete (nwthreadname,p,1);
  262. p := Pos ('"', nwthreadname);
  263. end;
  264. p := Pos ('"', nwcopyright);
  265. while (p > 0) do
  266. begin
  267. delete (nwcopyright,p,1);
  268. p := Pos ('"', nwcopyright);
  269. end;
  270. if nwscreenname <> '' then
  271. NLMConvLinkFile.Add('SCREENNAME "' + nwscreenname + '"');
  272. if nwthreadname <> '' then
  273. NLMConvLinkFile.Add('THREADNAME "' + nwthreadname + '"');
  274. if nwcopyright <> '' then
  275. NLMConvLinkFile.Add('COPYRIGHT "' + nwcopyright + '"');
  276. if stacksize < minStackSize then stacksize := minStackSize;
  277. str (stacksize, s);
  278. NLMConvLinkFile.Add ('STACKSIZE '+s);
  279. {$ifndef netware}
  280. NLMConvLinkFile.Add ('INPUT '+outputexedir+tmpLinkFileName);
  281. {$else}
  282. NLMConvLinkFile.Add ('INPUT '+FExpand(outputexedir+tmpLinkFileName));
  283. {$endif}
  284. { add objectfiles, start with nwpre always }
  285. LinkRes.Add ('INPUT(');
  286. s2 := FindObjectFile('nwplibc','',false);
  287. if s2 = '' then
  288. s2 := FindObjectFile('libcpre.gcc','',false);
  289. Comment (V_Debug,'adding Object File '+s2);
  290. {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
  291. if isDll then {needed to provide main}
  292. s2 := FindObjectFile('nwl_dlle','',false)
  293. else
  294. s2 := FindObjectFile('nwl_main','',false);
  295. Comment (V_Debug,'adding Object File '+s2);
  296. {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
  297. { main objectfiles, add to linker input }
  298. while not ObjectFiles.Empty do
  299. begin
  300. s:=ObjectFiles.GetFirst;
  301. if s<>'' then
  302. begin
  303. s2 := FindObjectFile (s,'',false);
  304. Comment (V_Debug,'adding Object File '+s2);
  305. {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
  306. end;
  307. end;
  308. LinkRes.Add (')');
  309. { output file (nlm), add to nlmconv }
  310. {$ifndef netware}
  311. NLMConvLinkFile.Add ('OUTPUT ' + NlmNam);
  312. {$else}
  313. NLMConvLinkFile.Add ('OUTPUT ' + FExpand(NlmNam));
  314. {$endif}
  315. { start and stop-procedures }
  316. NLMConvLinkFile.Add ('START _LibCPrelude');
  317. NLMConvLinkFile.Add ('EXIT _LibCPostlude');
  318. NLMConvLinkFile.Add ('CHECK _LibCCheckUnload');
  319. NLMConvLinkFile.Add ('REENTRANT'); { needed by older libc versions }
  320. if not (cs_link_strip in current_settings.globalswitches) then
  321. begin
  322. NLMConvLinkFile.Add ('DEBUG');
  323. Comment(V_Debug,'DEBUG');
  324. end;
  325. { Write staticlibraries }
  326. if not StaticLibFiles.Empty then
  327. begin
  328. LinkRes.Add ('GROUP(');
  329. While not StaticLibFiles.Empty do
  330. begin
  331. S:=lower (StaticLibFiles.GetFirst);
  332. if s<>'' then
  333. begin
  334. {ad: that's a hack !
  335. whith -XX we get the .a files as static libs (in addition to the
  336. imported libraries}
  337. if (pos ('.a',s) <> 0) OR (pos ('.A', s) <> 0) then
  338. begin
  339. S2 := FindObjectFile(s,'',false);
  340. {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
  341. Comment(V_Debug,'adding Object File (StaticLibFiles) '+S2);
  342. end else
  343. begin
  344. i:=Pos(target_info.staticlibext,S);
  345. if i>0 then
  346. Delete(S,i,255);
  347. S := S + '.imp'; S2 := '';
  348. librarysearchpath.FindFile(S,false,S2);
  349. {$ifdef netware}
  350. Comment(V_Debug,'IMPORT @'+s2);
  351. s2 := FExpand (S2);
  352. {$endif}
  353. NLMConvLinkFile.Add('IMPORT @'+S2);
  354. Comment(V_Debug,'IMPORT @'+s2);
  355. end;
  356. end
  357. end;
  358. LinkRes.Add (')');
  359. end;
  360. if not SharedLibFiles.Empty then
  361. begin
  362. While not SharedLibFiles.Empty do
  363. begin
  364. {becuase of upper/lower case mix, we may get duplicate
  365. names but nlmconv ignores that.
  366. Here we are setting the import-files for nlmconv. I.e. for
  367. the module libc or libc.nlm we add IMPORT @libc.imp and also
  368. the module libc.nlm (autoload)
  369. If a lib name begins with !, only the IMPORT will be generated
  370. ? may it be better to set autoload's via StaticLibFiles ? }
  371. S:=lower (SharedLibFiles.GetFirst);
  372. if s<>'' then
  373. begin
  374. s2:=s;
  375. i:=Pos(target_info.sharedlibext,S);
  376. if i>0 then
  377. Delete(S,i,255);
  378. if s[1] = '!' then
  379. begin // special, with ! only the imp will be included but no module is autoloaded, needed i.e. for netware.imp inlcuded in libc ndk
  380. delete (s,1,1);
  381. S := S + '.imp';
  382. librarysearchpath.FindFile(S,false,S3);
  383. {$ifdef netware}
  384. Comment(V_Debug,'IMPORT @'+S3);
  385. S3 := FExpand (S3);
  386. {$endif}
  387. NLMConvLinkFile.Add('IMPORT @'+S3);
  388. Comment(V_Debug,'IMPORT @'+S3);
  389. end else
  390. begin
  391. S := S + '.imp';
  392. librarysearchpath.FindFile(S,false,S3);
  393. {$ifdef netware}
  394. Comment(V_Debug,'IMPORT @'+S3);
  395. S3 := FExpand (S3);
  396. {$endif}
  397. NLMConvLinkFile.Add('IMPORT @'+S3);
  398. NLMConvLinkFile.Add('MODULE '+s2);
  399. Comment(V_Debug,'MODULE '+S2);
  400. Comment(V_Debug,'IMPORT @'+S3);
  401. end;
  402. end
  403. end;
  404. end;
  405. { write exports }
  406. hp2:=texported_item(current_module._exports.first);
  407. while assigned(hp2) do
  408. begin
  409. if not hp2.is_var then
  410. begin
  411. { Export the Symbol }
  412. Comment(V_Debug,'EXPORT '+hp2.name^);
  413. NLMConvLinkFile.Add ('EXPORT '+hp2.name^);
  414. end
  415. else
  416. { really, i think it is possible }
  417. {Comment(V_Error,'Exporting of variables is not supported under netware');}
  418. Message1(parser_e_no_export_of_variables_for_target,'netware');
  419. hp2:=texported_item(hp2.next);
  420. end;
  421. { Write and Close response for ld, response for nlmconv is in NLMConvLinkFile(not written) }
  422. linkres.writetodisk;
  423. LinkRes.Free;
  424. { pass options from -k to nlmconv, ; is interpreted as newline }
  425. s := ParaLinkOptions;
  426. while(Length(s) > 0) and (s[1] = ' ') do
  427. delete (s,1,1);
  428. p := pos ('"',s);
  429. while p > 0 do
  430. begin
  431. delete (s,p,1);
  432. p := pos ('"',s);
  433. end;
  434. p := pos (';',s);
  435. while p > 0 do
  436. begin
  437. s2 := copy(s,1,p-1);
  438. comment (V_Debug,'adding "'+s2+'" to nlmvonv input');
  439. NLMConvLinkFile.Add(s2);
  440. delete (s,1,p);
  441. p := pos (';',s);
  442. end;
  443. if s <> '' then
  444. begin
  445. comment (V_Debug,'adding "'+s+'" to nlmvonv input');
  446. NLMConvLinkFile.Add(s);
  447. end;
  448. WriteResponseFile:=True;
  449. end;
  450. Const
  451. xdc : Array[0..127] of char = (
  452. 'B','A','G','F',#2,#0,#0,#0,#1,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
  453. #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#2,#0,#0,#0,#0,#0,#0,#0,#16,#0,#0,
  454. #0,#7,'M','P','K','_','B','a','g',#0,#0,#0,#0,#0,#0,#0,#0,#11,'M','T',
  455. ' ','S','a','f','e',' ','N','L','M',#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
  456. #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
  457. #0,#0,#0,#0,#0,#0,#1,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0);
  458. function TLinkerNetwlibc.MakeNetwareLoadableModule (isLib : boolean):boolean;
  459. var
  460. binstr,
  461. cmdstr : TCmdStr;
  462. xdcname : string;
  463. success : boolean;
  464. StripStr : string[2];
  465. xdcpresent,usexdc : boolean;
  466. f : file;
  467. begin
  468. if not(cs_link_nolink in current_settings.globalswitches) then
  469. Message1(exec_i_linking,current_module.exefilename^);
  470. { Create some replacements }
  471. StripStr:='';
  472. if (cs_link_strip in current_settings.globalswitches) then
  473. StripStr:='-s';
  474. { Write used files and libraries and create Headerfile for
  475. nlmconv in NLMConvLinkFile }
  476. WriteResponseFile(isLib);
  477. if isLib then
  478. NLMConvLinkFile.Add('FLAG_ON 1024'); {0x400 Specifies whether the NLM is a shared library.}
  479. { if we have a xdc file, dont touch it, otherwise create a new
  480. one and remove it after nlmconv }
  481. xdcname := ChangeFileExt(current_module.exefilename^,'.xdc');
  482. xdcpresent := FileExists (xdcname,false);
  483. if not xdcpresent then
  484. begin
  485. assign (f,xdcname);
  486. rewrite(f,1);
  487. if ioresult = 0 then
  488. begin
  489. blockwrite (f,xdc,sizeof(xdc));
  490. close(f);
  491. usexdc := (IOResult = 0);
  492. end else
  493. usexdc := false;
  494. end else
  495. usexdc := true;
  496. if usexdc then
  497. NLMConvLinkFile.Add('XDCDATA '+xdcname);
  498. { Call linker, this will generate a new object file that will be passed
  499. to nlmconv. Otherwise we could not create nlms without debug info }
  500. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  501. Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
  502. Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
  503. Replace(cmdstr,'$STRIP',StripStr);
  504. Replace(cmdstr,'$TMPOBJ',maybequoted(outputexedir+tmpLinkFileName));
  505. Comment (v_debug,'Executing '+BinStr+' '+cmdstr);
  506. success:=DoExec(FindUtil(BinStr),CmdStr,true,false);
  507. { Remove ReponseFile }
  508. if (success) and not(cs_link_nolink in current_settings.globalswitches) then
  509. DeleteFile(outputexedir+Info.ResName);
  510. { Call nlmconv }
  511. if success then
  512. begin
  513. NLMConvLinkFile.writetodisk;
  514. NLMConvLinkFile.Free;
  515. SplitBinCmd(Info.ExeCmd[2],binstr,cmdstr);
  516. Replace(cmdstr,'$RES',maybequoted(outputexedir+'n'+Info.ResName));
  517. Comment (v_debug,'Executing '+BinStr+' '+cmdstr);
  518. success:=DoExec(FindUtil(BinStr),CmdStr,true,false);
  519. if (success) and not(cs_link_nolink in current_settings.globalswitches) then
  520. begin
  521. DeleteFile(outputexedir+'n'+Info.ResName);
  522. DeleteFile(outputexedir+tmpLinkFileName);
  523. if not xdcpresent then
  524. if usexdc then
  525. DeleteFile (xdcname);
  526. end;
  527. end;
  528. MakeNetwareLoadableModule:=success; { otherwise a recursive call to link method }
  529. end;
  530. function TLinkerNetwlibc.MakeExecutable:boolean;
  531. begin
  532. MakeExecutable := MakeNetwareLoadableModule (false);
  533. end;
  534. function TLinkerNetwlibc.MakeSharedLibrary:boolean;
  535. begin
  536. MakeSharedLibrary := MakeNetwareLoadableModule (true);
  537. end;
  538. {*****************************************************************************
  539. Initialize
  540. *****************************************************************************}
  541. initialization
  542. RegisterExternalLinker(system_i386_netwlibc_info,TLinkerNetwlibc);
  543. RegisterImport(system_i386_netwlibc,TImportLibNetwlibc);
  544. RegisterExport(system_i386_netwlibc,TExportLibNetwlibc);
  545. RegisterTarget(system_i386_netwlibc_info);
  546. end.