Ian Branch 127 Posted March 20, 2023 Hi Team, Please excuse my ignorance here.. If I use in my App just one function out of a library of functions from a unit say, myunit.pas in my uses clause. When the Delphi compiles/builds the App, does it only incorporate the function I am using or all the functions in myunit.pas? Hopefully/preferably the former, but I will have to accept it may be the latter... 😉  Regards & TIA, Ian Share this post Link to post
programmerdelphi2k 237 Posted March 20, 2023 (edited) hi @Ian Branch  by default, in my tests, the compiler "incorporate" just the code used in your final app (EXE). ex. if a unit "MyFunc.pas" have 2 procedure, and I use just 1 procedure in my code, then, we waiting that just 1 procedure (code) will be linked in our app (exe).  you can test in your project, follow me: create a unit "uMyFunctions" with 2 procedures (proc and func) named "prcHelloWorld" and "fncHelloWorld" (does not matter the code executed into it ok) now, in your app, just "uses" 1 procedure, for example: "prcHelloWorld" now, build your project (creating your EXEcutable) now, open your EXE with Notepad++ (for example) and search for two procedure above... you'll find just the procedure named: "prcHelloWorld" because, "fncHelloWorld" was not used in your app! you see? unit uMyFunctions; interface procedure prcHelloWorld; function fncHelloWorld: string; implementation procedure prcHelloWorld; var LHello: string; begin LHello := 'Hey Delphi'; end; function fncHelloWorld: string; begin result := 'hello'; result := result + ' world'; end; end.  type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} uses uMyFunctions; procedure TForm1.Button1Click(Sender: TObject); begin prcHelloWorld; // <-- just these will be in your final Executable!!! end; end.  Edited March 20, 2023 by programmerdelphi2k Share this post Link to post
Ian Branch 127 Posted March 21, 2023 Excellent! Thank you. It had always been an irritating thought in the back of my head that the whole library/unit was included. in some form. Although logic would dictate otherwise. I breath easier now. Share this post Link to post
David Heffernan 2345 Posted March 21, 2023 (edited) I'm not sure that @programmerdelphi2k is correct here.  Consider RTTI. The compiler / linker can strip any code that it knows cannot be called. But with RTTI code can be referenced in ways that are only known at runtime. Therefore any code that can be reached by RTTI cannot be stripped.. Even if the linked knows, through static analysis, that it cannot be called directly Edited March 21, 2023 by David Heffernan Share this post Link to post
Fr0sT.Brutal 900 Posted March 21, 2023 (edited) Fast & simple check whether a code is compiled into binary: build in debug mode and look at dots near line numbers. No dots - code was stripped by linker Edited March 21, 2023 by Fr0sT.Brutal Share this post Link to post
FPiette 383 Posted March 21, 2023 I adding to what other said, be aware that if the unit has initialization/finalization sections, then any code referenced directly or indirectly referenced by these section will also be linked in. Share this post Link to post
programmerdelphi2k 237 Posted March 21, 2023 We must consider all the code that is "indirectly" called in a software, because, in this way, I am only considering, and only, the code that I directly invoked! By the way, there is a lot of cloudiness here too! now imagine that a library (collection of codes - functions, procedures, types, etc...) were all incorporated into the final software, how big would it be? (even if super compression was present)... and, why then should there be a pre-analysis of the compiler and linker before the final task: creating the executable binary (standalone or not)... what is the meaning of all this? Well, just as "non-significant things" (like "comments", etc...) don't even make sense to remain in a final binary, I don't see why a piece of code that never was or would be referenced should "continue to exist" inside the software... however, as I've said before, I'm no expert or engineer to claim such an idea. it is clear that if someone can prove and demonstrate the opposite, the initial question could be closed with a golden key, however, always with reservations, because somewhere in this "infinite universe", and, "in this non-flat Earth" there will be someone who disagree and counter with other evidence to the contrary. The witch hunt is open.... wield your swords and spells. Â question: So is the "whole" RTL incorporated into the final binary? (no exceptions: ALL OF IT) And the VCL, too?... since there is a chain of calls between classes and interfaces. Share this post Link to post
Fr0sT.Brutal 900 Posted March 21, 2023 28 minutes ago, programmerdelphi2k said: So is the "whole" RTL incorporated into the final binary? (no exceptions: ALL OF IT) No Share this post Link to post
programmerdelphi2k 237 Posted March 21, 2023 (edited) of course, not? *was a sarcarsm 😂 Edited March 21, 2023 by programmerdelphi2k Share this post Link to post
programmerdelphi2k 237 Posted March 22, 2023 now, see how many "things" can be found in your app with a simple "Form1" empty... nothing more than this you can repeat the Notepad++ open Exe and find all types/class showed here!!! all will be found ... but YOU dont coded nothing isnt ? +/- Lines: 1361, Types: 534, Others: 827 (classes) var Form1: TForm1; implementation {$R *.dfm} uses System.Rtti; var LTypesCount: array [0 .. 1] of integer = ( 0, 0 ); procedure TForm1.Button1Click(Sender: TObject); var LCtx : TRttiContext; LType: TRttiType; LText: string; begin LCtx := TRttiContext.Create; // for LType in LCtx.GetTypes do begin if LType.IsInstance then begin LText := LText + '===> Instance: ' + LType.Name + slinebreak; inc(LTypesCount[0]); end else begin LText := LText + ' Type: ' + LType.Name + slinebreak; inc(LTypesCount[1]); end; end; // Memo1.Text := LText; // // Lines: 1424, Types: 515, Others: 814 Memo1.Lines.Add(Format('Lines: %d, Types: %d, Others: %d', [Memo1.Lines.Count, LTypesCount[0], LTypesCount[1]])); // // "----> Instance: TMessageListenerMethod" I can find it, but it was not directly referenced in my code! end; end. Â Share this post Link to post
Pat Foley 51 Posted March 22, 2023 {$WEAKLINKRTTI ON} {$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])} 14 hours ago, programmerdelphi2k said: // Lines: 1424, Types: 515, Others: 814 To get the line count to Lines: 1277, Types: 482, Others: 784 insert above switches in the dpr. This works even on the Emb and Cantu examples.  Share this post Link to post