441e35bea8709df3612e128a48db5faf889914ca
[goodguy/cin-manual-latex.git] / parts / Developer.tex
1 \chapter{Developer's Section}%
2 \label{cha:Developer's_Section}
3
4 \section{How Builds Really Work and Even More Options}
5 \label{sec:How Builds Really Work and Even More Options}
6
7 This section describes how builds really work if you want to know more about making changes or understanding the process; probably only for a developer or system administrator.
8 \medskip
9
10 Builds occur in 4 basic steps:
11 \smallskip
12 \begin{enumerate}[nosep]
13         \item unpack/patch source code
14         \item configure build
15         \item make build targets
16         \item installation
17 \end{enumerate}
18
19 So, an example of what happens in 4 steps for a single-user build would be as follows:
20 \smallskip
21
22 \begin{enumerate}[nosep]
23         \item unpack/patch source code\newline
24         git clone --depth 1 ``git:/{\dots}/target'' cinelerra5\newline
25         ./autogen.sh
26         \item configure build\newline
27         ./configure --with-single-user
28         \item make build targets\newline
29         make 2{\textgreater}\&1 {\textbar} tee log
30         \item installation\newline
31         make install
32 \end{enumerate}
33 \medskip
34
35 A lot of things can be tweaked to change the results. \ Mostly these changes are parameters to the configure step, which can change important build related items, like the application name, or where and what the target system directories should be. \ This makes it possible to have several versions at the same time on the same computer if needed. \ To see what it is that the makefiles use to build Cinelerra, look at the resulting top-level global\_config file which is created by the ./configure step.
36 \medskip
37
38 Building Cinelerra requires many thirdparty libraries, and it is recommended that you use the static build version included in the git repo. \ Some of them are patched, and fix significant bugs. \ It is important to note that because system installation historically has been with as many shared objects as possible, the defaults are that any system library detected during configuration setup will be used, whe\begin{lstlisting}[numbers=none]n the package is built ``-{}-without-single-user'', which is the default build. \ To build with static thirdparty libraries for system install to the system /usr area, use:
39 \smallskip
40
41 \hspace{2em}.configure -{}-enable-static-build --prefix=/usr
42 \medskip
43
44 Sometimes, additional package parameters and variables are needed during thirdparty builds. \ These optional values occur before and after the ``configure'' and ``make'' commands during a build. \ A presentation of the format of the package qualified variable names and how they appear in the build procedure are:
45 \medskip
46
47 \hspace{2em}
48 \begin{tabular}{@{}ll}
49         pkg.cfg\_vars & prepended to configure\\
50         pkg.cfg\_params & appended to configure\\
51         pkg.mak\_vars & prepended to make\\
52         pkg.mak\_params & appended to make\\
53     pkg.cflags & added as CFLAGS+=\$(cflags) to pkg.vars\\
54         pkg.cppflags & added as CPPFLAGS+=\$(cppflags) to pkg.vars\\
55 \end{tabular}
56 \bigskip
57
58 These steps are done for EACH of the packages in the thirdparty build:
59 \smallskip
60
61 \hspace{2em}{\textless}pkg.cfg\_vars{\textgreater} ./configure {\textless}pkg.cfg\_params{\textgreater}
62
63 \hspace{2em}{\textless}pkg.mak\_vars{\textgreater} make {\textless}pkg.mak\_params{\textgreater}
64 \bigskip
65
66 The thirdparty Makefile has a set of default vars and params used to build each of the needed thirdparty packages, but you can specify new or overriding values for these Makefile substitutions. \ These thirdparty build config changes are specified in the top-level file: cin\_config. \ By using this file, you can save the configuration changes made for the current build to use the next time you do a new build. \ For example, to add an include file path to the giflib build, add this line to cin\_config:
67 \medskip
68
69 \hspace{2em}giflib.cflags := -I/usr/local/include/giflib5
70 \medskip
71
72 To have a param/var change apply to all thirdparty builds, use:
73 \medskip
74
75 \hspace{2em}CFG\_VARS, CFG\_PARAMS, MAK\_VARS, MAK\_PARAMS
76 \medskip
77
78 CFLAGS, CXXFLAGS and LDFLAGS are forwarded to the thirdparty build environment via:
79 \medskip
80
81 \hspace{2em}CFLAGS=-ggdb ./configure -{}-with-single-user
82 \medskip
83
84 However, there is no guarantee that the thirdparty build will honor the environmental flags.
85
86 Finally, there are build controls, which enable/disable and set build features.
87 \bigskip
88
89 A few of the more useful ./configure -{}-parameters are:
90 \smallskip
91
92 \hspace{2em}
93 \begin{tabular}{@{}ll}
94         {}-{}-with-jobs=n & where n=number of build jobs; defaults to 1.5*cpus+2\\
95         {}-{}-enable-static-build & build all 3rd party libs; defaults to yes if single-user, else no\\
96         {}-{}-with-single-user& build installs to {\textless}build\_path{\textgreater}/bin; \ no system installation\\
97 \end{tabular}
98
99 \medskip
100
101 The ./configure command builds ``global\_config''. \ The global\_config is read by the thirdparty/Makefile to create the recipes and definitions used by the thirdparty build.
102 \medskip
103
104 There are a lot of different options.  Thirdparty library build control is available in the configure step of the build.  Thirdparty libraries are built on a demand basis.  So if you use:
105 \medskip
106
107 \hspace{2em}
108 \begin{tabular}{@{}ll}
109   --enable-libname=auto & \# the static-build enable, or the lack of a system library causes a build\\
110   --enable-libname=yes  &  \# this forces the thirdparty build\\
111   --enable-libname=no   &  \# this forces no thirdparty build\\
112 \end{tabular}
113 \medskip
114
115 FFmpeg is a ``strongly connected component''in the build linkage and widely influences the Cinelerra library demands.  It is possible to make small additions to the ffmpeg configuration step using the environment variable FFMPEG\_EXTRA\_CFG.  For example, to eliminate the use of libvdpau (an nvidia support library) in the ffmpeg configuration step after you have determined that it is causing an error, use:
116
117 \begin{itemize}[label={},nosep]
118         \item make clean
119         \item autogen.sh
120         \item export FFMPEG\_EXTRA\_CFG={\textquotedbl} -{}-disable-vdpau{\textquotedbl} 
121         \item ./configure {\dots}
122 \end{itemize}
123 \medskip
124
125 Specific information on using the current ffmpeg GIT repository follows.  You have to supply the actual URL location of the ffmpeg git as you can see in this example ?bld.sh? script:
126 \medskip
127
128 \begin{lstlisting}[numbers=none]
129 #!/bin/bash\newline
130 () ./autogen.sh\newline
131 ./configure --with-single-user --with-booby --with-git-ffmpeg=https://git.ffmpeg.org/ffmpeg.git
132 make && make install ) 2>1 | tee log
133 mv Makefile Makefile.cfg
134 cp Makefile.devel Makefile
135 \end{lstlisting}
136
137 Since the procedure for obtaining the latest ffmpeg version is not always kept up-to-date and the line numbers will always change, you may have to create that patch first. \ Generally those line numbers are only updated by a developer when a new stable version with worthwhile features is actually included in the Cinelerra build. FFmpeg is constantly changing and many times the git version is not as stable as desired.
138
139 \section{Thirdparty Parallel Build}
140 \label{sec:Thirdparty Parallel Build}
141
142 The Makefile in the thirdparty build directory employs a set of macros used to create a build rule set of thirdparty library build dependencies.  The standard build sequence of [source, config, build] is used to prepare thirdparty products as static libraries.  Build package dependency can be specified in the Makefile std-build macro call.  These Makefile macro calls define the rules used for each thirdparty build.  The expanded rule definitions may be viewed by using:
143 \smallskip
144
145 \hspace{2em}make -C thirdparty rules
146 \medskip
147
148 Individual package libraries can be rebuilt, via:
149 \smallskip
150 \hspace{2em}make -C thirdparty <pkg>-clean;  make -C thirdparty <pkg>
151 \medskip
152
153 The rule targets create the set of thirdparty packages which are built from local source archive copies of thirdparty source code and patches, if needed.  The build rule set of dependencies allows for compiling multiple thirdparty programs simultaneously using maximum computer resources.  This parallel build speeds up the process considerably.  For example, these are full static build timings on the production build machine (full build includes building all thirdparty programs as well as all of Cinelerra):
154 \medskip
155
156 \hspace{2em}
157 \begin{tabular}{@{}rcr}
158         1 cpu & = & 61 mins\\
159         12 cpus & = & 7.5 mins\\
160         24 cpus & = & 2 mins\\
161 \end{tabular}
162
163 \section{Find Lock Problems with Booby Trap}
164 \label{sec:Find Lock Problems with Booby Trap}
165
166 A Booby Trap is used in CinGG for setting a trap to catch lock problems that might have been missed. \ It will trap boobies only if compile by adding ``-{}-with-booby'' on the configuration command line. \ \ This is the default if you compile using ./bld.sh from the GIT repository. \ It should not interfere with normal execution.
167 \medskip
168
169 If you have the time and inclination, enable -{}-with-booby and send any trap output that you find. \ Maybe you will catch some boobies and if you do, send a snapshot of any boobies you find.
170 \medskip
171
172 There are 2 potential traps:
173 \begin{itemize}[nosep]
174         \item If you try to unlock a lock when it is not locked
175         \item If you execute a drawing operation without holding the window lock
176 \end{itemize}
177 \medskip
178
179 The trap prints the following in the controlling terminal window:
180 \medskip
181
182 \hspace{2em}BOOBY!hspace{2em}{\textless}backtrace{\textgreater}
183 \medskip
184
185 An example backtrace is below along with a hint below on how to analyze:
186
187 \begin{lstlisting}[numbers=none]
188 /home/cin5/bin/./cin(_Z5boobyv+0x3f) [0x557069fa9b2f] /home/cin5/bin/./cin(_ZN13BC_WindowBase9draw_lineEiiiiP9BC_Pixmap+0x3b)0x557069fb9a9b]
189 /home/cin5/bin/./cin(\_ZN10BC_ListBox11draw_borderEi+0x73)[0x557069f7dc73]
190 /home/cin5/bin/./cin(+0x9707fb) [0x557069f7e7fb]
191 /home/cin5/bin/./cin(\ZN10BC\ListBox16center\selectionEv+0x4e)[0x557069f7f2ae]
192 /home/cin5/bin/plugins/video/sketcher.plugin(_ZN17SketcherCurveList6updateEi+0x1a0)[0x7f1b8002a4c0]
193 /home/cin5/bin/plugins/video/sketcher.plugin(_ZN18SketcherCurveColor17handle_done_eventEi+0x76)[0x7f1b8002a5f6]
194 /home/cin5/bin/./cin(_ZN15BC_DialogThread3runEv+0xd8)[0x557069f6fb78]
195 /home/cin5/bin/./cin(_ZN6Thread10entrypointEPv+0x45)[0x557069fc5995]
196 /usr/lib/libpthread.so.0(+0x7a9d) [0x7f1b91b4ea9d]
197 /usr/lib/libc.so.6(clone+0x43) [0x7f1b90accb23]
198 \end{lstlisting}
199
200 To see which routine is reporting the booby key in:
201 \smallskip
202
203 \hspace{2em}c++filt
204 \smallskip
205
206 And then the 2nd line in the backtrace above:
207 \smallskip
208
209 \hspace{2em}\_ZN13BC\_WindowBase9draw\_lineEiiiiP9BC\_Pixmap
210 \smallskip
211
212 It comes back with the routine as:
213 \smallskip
214
215 \hspace{2em}BC\_WindowBase::draw\_line(int, int, int, int, BC\_Pixmap*)
216 \medskip
217
218 \section{Valgrind Support Level}
219 \label{sec:Valgrind Support Level}
220
221 Valgrind is a memory mis-management detector.  It shows you memory leaks, deallocation errors, mismanaged threads, rogue reads/writes, etc.  Cinelerra-GG memory management is designed to work with Valgrind detection methods.  This assists in developing reliable code.  Use of Valgrind points out problems so that they can be fixed.  For example, when this version of Cinelerra shuts down, it deallocates memory instead of just stopping, thus making memory leak detection possible.
222 \medskip
223
224 The best way to compile and run valgrind is to run the developer static build. This takes 2 steps and you must already have gdb and valgrind installed:
225 \medskip
226
227 \begin{enumerate}[nosep]
228         \item The standard static build:\newline
229                 cd /path/cinelerra-5.1\newline
230                 make clean\newline
231                 ./bld.sh
232         \item run the incremental rebuild for debug objs\newline
233                 CFLAGS=-ggdb make -j8 rebuild\_all
234 \end{enumerate}
235 \medskip
236
237 Now your Cinelerra obj has all of the debug stuff. Next run valgrind as root for the most useful results:
238 \smallskip
239
240 \hspace{2em}cd /path/cinelerra-5.1/cinelerra
241
242 \hspace{2em}valgrind -{}-log-file=/tmp/log -{}-leak-check=full -{}-num-callers=32 ./ci
243 \medskip
244
245 This runs Cinelerra under the control of valgrind, and produces a log file in /tmp which will list information about any leaks, usually clearly identifiable. \ Be sure to Quit out of Cinelerra normally instead of Ctrl-C or a SEGV otherwise the program does not have a chance to cleanup and there will be some false alarms. But it runs very slowly, and is basically single threaded, which means that race conditions may be impossible to catch... like one thread deletes memory that another thread is currently using. But overall it is a big help and if you test any new features, please email the log output. \ A lot of effort when writing the code was put into trying to be sure that all of the object constructors have matching destructors so that the leaks can be identified. There are already several libraries that create predictable memory leaks and valgrind does a good job for most of these.
246 \medskip
247
248 It is impossible to test everything with valgrind because some things are just too big and slow for a practical test. \ Occasionally you can find a leak or an illegal memory access. There are several false alarms that are difficult to avoid {\textquotedbl}Conditional jump{\textquotedbl} messages, and {\textquotedbl}unhandled DW\_OP\_{\textquotedbl}, but anything with the word {\textquotedbl}illegal{\textquotedbl} in the message is important. Memory leaks that originate in Cinelerra are good to find and fix, but are usually not deadly.
249
250 \section{CFLAGS has -Wall}
251 \label{sec:CFLAGS has -Wall}
252 When compiling Cinelerra-GG Infinity a CFLAGS option used is "Wall" where the "W" represents warnings and "all" means all.  This causes the compile to check for simple mistakes that can be detected automatically and issue warnings when the code is questionable.  It can also detect situations where the compiler will generate incorrect code, like type-punned pointer.  By turning on this flag, when new code is vetted for predictable mistakes, the code can be corrected before becoming manifested in the application.
253
254 \section{Prof2 -- A Profiler}
255 \label{sec:Prof2 -- A Profiler}
256
257 Frequently there is a problem with a program running slow and you do not know why. \ You need a thumbnail analysis of where the program is spending most of its time without all of the overwhelming details. \ This is when a Profiler comes in handy.
258 \medskip
259
260 There are many different profilers available -- this particular one does not do anything special and is fairly ordinary in that it just characterizes frequency of execution of various regions in the program. \ However, it has some pretty good strengths as listed next.
261 \medskip
262 \begin{enumerate}[nosep]
263         \item It takes very little or no preconditioning, i.e. setup
264         \item The effect it has on the running program is minimal
265         \item It runs almost at full speed, which is really nice
266         \item It is not particularly thread aware
267         \item Reports where it is executing at intervals of 100 times a second
268 \end{enumerate}
269 \subsection{Setup}
270
271 This profiler works on x86\_64 systems and you must be root to compile and run it. \ Also, you must install your operating system's ``iberty'' -- for example, which would be binutils-devel for Fedora or libiberty-dev for Ubuntu 18.
272 \medskip
273
274 Go to the top level Cinelerra directory.
275
276 Key in: \ \ \ \ cd prof2
277
278 Key in: \ \ \ \ make clean all install
279
280 Later, if you wanttitle to remove this from the system, key in: \ \ \ \ make uninstall
281 \subsection{How to use}
282
283 The program you are profiling should be compiled debuggable with stack frame and symbols enabled.
284 \medskip
285
286 To see help, key in: \ \ prof -h
287 \smallskip
288
289 usage: -h [-o path] [-d] [-e] [-p libpath] [-012] [-u \#] cmd args...
290
291 \hspace{2em}
292 \begin{tabular}{@{}ll}
293         -o & profile output pathname, -=stdout, -{}-=stderr\\
294         -d & debug otitleutput enabled\\
295         -e & child debug output enabled\\
296         -p & specify path for libprofile.so\\
297         -0 & usr+sys cpu timer intervals (sigprof)\\
298         -1 & usr only cpu timer intervals (sigvtalrm)\\
299         -2 & real time timer intervals (sigalrm)\\
300         -u & profile timer interval in usecs\\
301 \end{tabular}
302 \medskip
303
304 To execute the profiler, key in: \ \ 
305 \medskip
306
307 \hspace{2em}prof -o /tmp/prof\_list.txt ./cin
308 \medskip
309
310 where /tmp/prof\_list.txt is the output file and in this case ``cin'' is the Cinelerra binary file. \ The pid of this command will be displayed on the startup window. \ This comes in handy in the use case where there is a lot of initial load and possible configuration setup inside of Cinelerra and you want to profile plugins and not necessarily all of the setup steps. \ Then you can use the following command in another window to continue running Cinelerra and obtain the more useful information:
311 \medskip
312
313 \hspace{2em}kill -USR1 pid
314 \medskip
315
316 Running this command refreshes the memory maps used for profiling. \ When you are profiling a plugin, you want to run this AFTER the plugin loads.
317 \medskip
318
319 \subsection{Results}
320
321 There are 3 sections in the resulting output file of this stochastic quick analysis.
322 \medskip
323
324 \begin{enumerate}[nosep]
325         \item The first section is a histogram of the timer intervals of that sample set. \ Each function occupies a region of addresses. \ One hundred times a second, the profiler samples the program address in the region of execution.
326         \item In the second section, there is another histogram of the cumulative frequency of all things in the call stack and this should point out who is the culprit. \ For example, a codec calls a bunch of subroutines, the cost of the subroutines is accumulated to the codec parent caller. \ This makes the actual cpu user much more apparent.
327         \item The last section is for the library spaces. \ Each library occupies a region and the profiler adds up the time spent in each of the libraries by frequency.
328 \end{enumerate}
329 \smallskip
330
331 On the very bottom is a 1 line summary which shows you if there is a bad guy and who it is.
332 \medskip
333
334 \subsection{Sample output}
335
336 \medskip
337
338 %\begin{lstlisting}[numbers=none] %\textwidth
339
340 ---- profile start ----\\
341 1020 ticks 43 modules 81412 syms\\
342 \begin{tabular}{@{}rrp{\linewidth-6em}}
343  0.010s & 0.1\% & Autos::copy(long, long, FileXML*, int, int) /mnt0/build5/cinelerra-5.1/bin/cin\\
344  0.010s & 0.1\% & BinFolders::copy\_from(BinFolders*) /mnt0/build5/cinelerra-5.1/bin/cin\\
345  0.010s & 0.1\% & cstrdup(char const*)     /mnt0/build5/cinelerra-5.1/bin/cin\\
346  0.010s & 0.1\% & XMLBuffer::encode\_data(char*, char const*, int) /mnt0/build5/cinelerra-5.1/bin/cin\\
347  0.010s & 0.1\% & XMLBuffer::encoded\_length(char const*, int) /mnt0/build5/cinelerra-5.1/bin/cin\\
348  0.010s & 0.1\% & PluginClient::send\_configure\_change() /mnt0/build5/cinelerra-5.1/bin/cin\\
349  0.010s & 0.1\% & UndoVersion::scan\_lines(UndoHashTable*, char*, char*) /mnt0/.../cin\\
350  0.010s & 0.1\% & UndoStackItem::set\_data(char*) /mnt0/build5/cinelerra-5.1/bin/cin\\
351  0.010s & 0.1\% & UndoStack::load(\_IO\_FILE*) /mnt0/build5/cinelerra-5.1/bin/cin\\
352  0.010s & 0.1\% & BC\_Bitmap::cur\_bfr()     /mnt0/build5/cinelerra-5.1/bin/cin\\
353  0.010s & 0.1\% & YUV::init\_tables(int, int*, int*, int*, int*, int*, int*, int*, int*, int*, int*, int*, int*, int*, int*) /mnt0/build5/cinelerra-5.1/bin/cin\\
354 \end{tabular}\\
355 ...\\
356 ...\\
357 ---- profile calls ----\\
358 \begin{tabular}{@{}rrl}
359  0.010s & 0.1\% & AutoConf::save\_xml(FileXML*)   1.0 /mnt0/build5/cinelerra-5.1/bin/cin\\
360  0.010s & 0.1\% & Automation::copy(long, long, FileXML*, int, int)   1.0 /mnt0/.../cin\\
361  0.010s & 0.1\% & AWindow::run()             1.0 /mnt0/build5/cinelerra-5.1/bin/cin\\
362  0.010s & 0.1\% & Canvas::stop\_single()      1.0 /mnt0/build5/cinelerra-5.1/bin/cin\\
363  0.010s & 0.1\% & ColorPicker::new\_gui()     1.0 /mnt0/build5/cinelerra-5.1/bin/cin\\
364  0.010s & 0.1\% & ColorWindow::create\_objects()   1.0 /mnt0/build5/cinelerra-5.1/bin/cin\\
365  0.010s & 0.1\% & PaletteWheel::draw(float, float)   1.0 /mnt0/build5/cinelerra-5.1/bin/cin\\
366  0.010s & 0.1\% & PaletteHex::update()       1.0 /mnt0/build5/cinelerra-5.1/bin/cin\\
367  0.010s & 0.1\% & CWindowGUI::draw\_status(int)   1.0 /mnt0/build5/cinelerra-5.1/bin/cin\\
368  0.010s & \textbf{0.1\%} & CWindowCanvas::status\_event()   1.0 /mnt0/build5/cinelerra-5.1/bin/cin\\
369 \end{tabular}\\
370 ...\\
371 ...\\
372 \begin{tabular}{@{}rrl}
373  0.990s & \textbf{9.7\%} & BC\_Xfer::xfer\_slices(int)   1.0 /mnt0/build5/cinelerra-5.1/bin/cin\\
374  1.880s & \textbf{18.4\%} & DirectUnit::process\_package(LoadPackage*)   1.0 /mnt0/build5/cinelerra-5.1/bin/cin\\
375  1.880s & \textbf{18.4\%} & DirectUnit::rgba8888()     1.0 /mnt0/build5/cinelerra-5.1/bin/cin\\
376  3.910s & \textbf{38.3\%} & \_\_init\_array\_end           1.1 /mnt0/build5/cinelerra-5.1/bin/cin\\
377  5.450s & \textbf{53.4\%} & LoadClient::run()          1.0 /mnt0/build5/cinelerra-5.1/bin/cin\\
378  7.890s & \textbf{77.4\%} & Thread::entrypoint(void*)   1.0 /mnt0/build5/cinelerra-5.1/bin/cin\\
379  7.890s & \textbf{77.4\%} & start\_thread               1.0 /lib64/libpthread-2.28.so\\
380 \end{tabular}\\
381 ----\\
382 ----\\
383 \begin{tabular}{@{}rrl}
384  0.010s & 0.1\%/  0.0\% & /lib64/libm-2.28.so\\
385  0.010s & 0.1\%/  0.0\% & /lib64/libexpat.so.1.6.8\\
386  0.020s & 0.2\%/  0.1\% & /lib64/libXext.so.6.4.0\\
387  0.020s & 0.2\%/  0.1\% & /lib64/libXft.so.2.3.2\\
388  0.020s & 0.2\%/  0.1\% & /lib64/libxcb.so.1.1.0\\
389  0.040s & 0.4\%/  0.2\% & /lib64/ld-2.28.so\\
390  0.050s & 0.5\%/  0.2\% & /lib64/libpng16.so.16.34.0\\
391  0.130s & 1.3\%/  0.6\% & /lib64/libX11.so.6.3.0\\
392  0.180s & 1.8\%/  0.8\% & /lib64/libz.so.1.2.11\\
393  0.200s & 2.0\%/  0.9\% & /lib64/libfontconfig.so.1.12.0\\
394  0.380s & 3.7\%/  1.8\% & /lib64/libpthread-2.28.so\\
395  1.660s & 16.3\%/ 7.7\% & /lib64/libc-2.28.so\\
396  7.480s & 73.3\%/34.7\% & /mnt0/build5/cinelerra-5.1/bin/cin\\
397 \end{tabular}\\
398
399 \textbf{10.200t 0.001u+0.000s 21.566r  47.3\%}
400 \\
401 ---- profile end ----
402 %\end{lstlisting}
403 \medskip
404
405 The summary line above in Bold represents the User time, System time, Real time and the percentage is how much Timer time elapsed over Real time so in this case the measurement covers 47.3\% of time. 
406 \medskip
407
408 So why use a Profiler? \ Because it is the ``ls'' for executable functions!!