When I include a static library "libupnpx.a" in my project that is 6 MB, does this make my app 6 MB larger? - static-libraries

I have heard the compiler strips out unused code. But when I include a libupnpx.a static library archive of 6 MB, will this make app 6 MB larger? Or is this same as including the library source code directly?

The answer is not as simple as you may think:
Let's do an experiment:
We will create a libfoo.a with the following structure:
Makefile:
LIBOUT=libfoo.a
SRC=foo1.c foo2.c foo3.c
OBJ=$(SRC:%.c=%.o)
default: test1 test2 test3
test1: $(LIBOUT)
$(CC) -o $# test1.c -L. -lfoo
test2: $(LIBOUT)
$(CC) -o $# test2.c -L. -lfoo
test3: $(LIBOUT)
$(CC) -o $# test3.c -L. -lfoo
$(LIBOUT): $(OBJ)
$(AR) ruv $(LIBOUT) $(OBJ)
foo1.c:
#include <stdio.h>
int foo1_service_a() {
printf("Performing foo1_service_a\n");
return 0;
}
foo2.c:
#include <stdio.h>
int foo2_service_a() {
printf("Performing foo2_service_a\n");
return 0;
}
foo3.c:
#include <stdio.h>
int foo3_service_a() {
printf("Performing foo3_service_a\n");
return 0;
}
int foo3_service_b() {
printf("Performing foo3_service_b\n");
return 0;
}
And three test programs:
test1.c:
int main() {
foo1_service_a();
return 0;
}
test2.c:
int main() {
foo2_service_a();
return 0;
}
test3.c:
int main() {
foo3_service_a();
return 0;
}
When we compile them we get:
-rw-r--r-- 1 masud users 285 Aug 3 16:42 Makefile
-rw-r--r-- 1 masud users 96 Aug 3 16:38 foo1.c
-rw-r--r-- 1 masud users 1496 Aug 3 16:39 foo1.o
-rw-r--r-- 1 masud users 97 Aug 3 16:39 foo2.c
-rw-r--r-- 1 masud users 1496 Aug 3 16:39 foo2.o
-rw-r--r-- 1 masud users 173 Aug 3 16:39 foo3.c
-rw-r--r-- 1 masud users 1688 Aug 3 16:40 foo3.o
-rw-r--r-- 1 masud users 5008 Aug 3 16:40 libfoo.a
-rwxr-xr-x 1 masud users 9132 Aug 3 16:43 test1
-rw-r--r-- 1 masud users 45 Aug 3 16:43 test1.c
-rwxr-xr-x 1 masud users 9132 Aug 3 16:43 test2
-rw-r--r-- 1 masud users 45 Aug 3 16:43 test2.c
-rwxr-xr-x 1 masud users 9251 Aug 3 16:43 test3
-rw-r--r-- 1 masud users 45 Aug 3 16:43 test3.c
As you can tell that each of test1 test2 and test3 have foo1.o; foo2.o and foo3.o dictating their end sizes.
So it's the archive's content division that determines the size of the end binary.
Exercise for the reader
What happens to the sizes when you strip the binaries? do test1 test2 and test3 become the same size?
Why or why not ? :)

You can generally expect that static linking and "including the library source code directly" will have equivalent impacts on the size of the resulting executable. There are be some minor cases in which this may not be strictly true, but generally speaking, they should be approximately equivalent.

Related

MacOS Command Line - Create folder with files at once

Is it possible to write a command that will create a new directory with name passed as argument 'MyFolder' (for example) and will create four files with the same name (as part):
MyFolder.js
MyFolder.css
MyFolder.test.js
README.md
(using mkdir / touch / echo ...)
Main problem - one line command
This one-liner function should do the work:
$ function mkdir_and_files() { mkdir "${1}"; touch ${1}/${1}.js; touch ${1}/${1}.css; touch ${1}/${1}.test.js; touch ${1}/README.md; }; mkdir_and_files "MyFolder" ;
$ ls -latrh MyFolder/
total 0
drwxrwxrwt 15 root wheel 480B Aug 19 18:58 ..
-rw-r--r-- 1 user wheel 0B Aug 19 18:58 MyFolder.js
-rw-r--r-- 1 user wheel 0B Aug 19 18:58 MyFolder.css
-rw-r--r-- 1 user wheel 0B Aug 19 18:58 MyFolder.test.js
-rw-r--r-- 1 user wheel 0B Aug 19 18:58 README.md
drwxr-xr-x 6 user wheel 192B Aug 19 18:58 .
Try this:
populate_dir() { mkdir "$1"; touch "$1/$1".{js,css,test.js} "$1/README.md"; }
populate_dir MyFolder

Not able to compile with gcc using -m32

amar#pc:/local/mnt/workspace/amarn$ gcc -m32 a.c
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc.a when searching for -lgcc
/usr/bin/ld: cannot find -lgcc
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc_s.so when searching for -lgcc_s
/usr/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
amar#pc:/local/mnt/workspace/amarn$ cat a.c
#include <stdio.h>
int
main ()
{
long z;
printf("Long int size is %d bytes long!\n", sizeof(z));
;
return 0;
}
amarn#hyd-tbsbld01:/local/mnt/workspace/amarn$ uname -a
Linux mypc 4.4.0-78-generic #99-Ubuntu SMP Thu Apr 27 15:29:09 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
I made following change for gcc.
gcc was mapped to gcc-5.
I mapped gcc to gcc-4.8.
amar#mypc:/usr/bin$ ll | grep gcc
-rwxr-xr-x 1 root root 428 May 7 2006 c89-gcc
-rwxr-xr-x 1 root root 454 Apr 11 2011 c99-gcc
lrwxrwxrwx 1 root root 7 Jun 1 11:54 gcc -> gcc-4.8
-rwxr-xr-x 1 root root 776344 Jan 26 2016 gcc-4.8
-rwxr-xr-x 1 root root 915736 Nov 3 2016 gcc-5
lrwxrwxrwx 1 root root 10 Jun 1 11:55 gcc-ar -> gcc-ar-4.8
-rwxr-xr-x 1 root root 27032 Jan 26 2016 gcc-ar-4.8
-rwxr-xr-x 1 root root 31136 Nov 3 2016 gcc-ar-5
lrwxrwxrwx 1 root root 10 Jun 1 11:56 gcc-nm -> gcc-nm-4.8
-rwxr-xr-x 1 root root 27032 Jan 26 2016 gcc-nm-4.8
-rwxr-xr-x 1 root root 31136 Nov 3 2016 gcc-nm-5
lrwxrwxrwx 1 root root 14 Jun 1 11:56 gcc-ranlib -> gcc-ranlib-4.8
-rwxr-xr-x 1 root root 27032 Jan 26 2016 gcc-ranlib-4.8
-rwxr-xr-x 1 root root 31136 Nov 3 2016 gcc-ranlib-5
lrwxrwxrwx 1 root root 7 Jun 1 12:32 x86_64-linux-gnu-gcc -> gcc-4.8
lrwxrwxrwx 1 root root 7 Jan 26 2016 x86_64-linux-gnu-gcc-4.8 -> gcc-4.8
lrwxrwxrwx 1 root root 5 Nov 3 2016 x86_64-linux-gnu-gcc-5 -> gcc-5
lrwxrwxrwx 1 root root 10 Jun 1 12:34 x86_64-linux-gnu-gcc-ar -> gcc-ar-4.8
lrwxrwxrwx 1 root root 10 Jan 26 2016 x86_64-linux-gnu-gcc-ar-4.8 -> gcc-ar-4.8
lrwxrwxrwx 1 root root 8 Nov 3 2016 x86_64-linux-gnu-gcc-ar-5 -> gcc-ar-5
lrwxrwxrwx 1 root root 10 Jun 1 12:34 x86_64-linux-gnu-gcc-nm -> gcc-nm-4.8
lrwxrwxrwx 1 root root 10 Jan 26 2016 x86_64-linux-gnu-gcc-nm-4.8 -> gcc-nm-4.8
lrwxrwxrwx 1 root root 8 Nov 3 2016 x86_64-linux-gnu-gcc-nm-5 -> gcc-nm-5
lrwxrwxrwx 1 root root 14 Jun 1 12:35 x86_64-linux-gnu-gcc-ranlib -> gcc-ranlib-4.8
lrwxrwxrwx 1 root root 14 Jan 26 2016 x86_64-linux-gnu-gcc-ranlib-4.8 -> gcc-ranlib-4.8
lrwxrwxrwx 1 root root 12 Nov 3 2016 x86_64-linux-gnu-gcc-ranlib-5 -> gcc-ranlib-5

Sorting ls output by file size

I am currently sorting the output of ls -l by byte count using:
ls -l | sort -r -k5,5 -n
What if I wanted to make this work with the -# flag? Currently this will output:
-rwxr-xr-x# 1 name staff 7106 2 May 10:43 c
-rwxr-xr-x 1 name staff 675 22 Apr 17:57 a
-rwxr-xr-x 1 name staff 486 23 Apr 07:56 b
drwxr-xr-x 4 name staff 136 25 Apr 18:38 d
-rwxr-xr-x 1 name staff 120 23 Apr 07:59 e
-rwxr-xr-x 1 name staff 112 22 Apr 18:45 g
-rwxr-xr-x 1 name staff 51 22 Apr 18:45 f
total 56
com.apple.metadata:_kMDItemUserTags 42
Where I want it to take the extended attribute keys line and keep it below the appropriate file like so:
-rwxr-xr-x# 1 name staff 7106 2 May 10:43 c
com.apple.metadata:_kMDItemUserTags 42
-rwxr-xr-x 1 name staff 675 22 Apr 17:57 a
-rwxr-xr-x 1 name staff 486 23 Apr 07:56 b
drwxr-xr-x 4 name staff 136 25 Apr 18:38 d
-rwxr-xr-x 1 name staff 120 23 Apr 07:59 e
-rwxr-xr-x 1 name staff 112 22 Apr 18:45 g
-rwxr-xr-x 1 name staff 51 22 Apr 18:45 f
total 56
No need to use sort, just use the -S option with ls
ls -Sl
(that's an upper case S)

Allow calling shell functions with globs without making the user quote

Consider the following convenience bash function that is intended not to descend into directories but instead just list them:
12:17:03/shared $type lld
lld is a function
lld ()
{
ls -drlta $1
}
Let us try to use it:
12:17:44/shared $lld pic*
-rw-r--r--# 1 steve staff 249245 Jan 27 16:43 PIClustering.png
That is not correct: but if we add double quotes then it gives correct results:
12:17:20/shared $lld "pic*"
-rw-r--r--# 1 steve staff 249245 Jan 27 16:43 PIClustering.png
-rw-r--r-- 1 steve staff 2004 Jan 27 18:07 pic-15.txt
drwxr-xr-x 42 steve staff 1428 Jan 30 14:30 pic
drwxr-xr-x 43 steve staff 1462 Feb 18 14:33 picsubmean
drwxr-xr-x 41 steve staff 1394 Mar 21 08:32 picschur
The question is: how to modify the lld() function to achieve the latter behavior without requiring quotes?
Replace
ls -drlta $1
by
ls -drlta "$#"
Globs are expanded before functions or commands are called, and each result becomes a separate argument. lld pic* is shorthand for (and indistinguishable from):
lld "PIClustering.png" "pic" "pic-15.txt" "picsubmean" "picschur"
Knowing this, the solution is obvious: instead of listing just the first file specified ($1), you should list all files specified ("$#").
From #etan's comments it is not possible to achieve precisely what I was looking for. The following is a reasonable facsimile:
12:33:10/shared $type lld
lld is a function
lld ()
{
ls -drlta $1*
}
Then use it by:
12:17:44/shared $lld pic
-rw-r-----# 1 steve staff 184655 Jan 26 00:16 picInputOutputs.png
-rw-r--r-- 1 steve staff 794810294 Jan 26 01:11 pic.0126.tgz
drwxr-xr-x 43 steve staff 1462 Jan 27 16:23 picpy
-rw-r--r--# 1 steve staff 249245 Jan 27 16:43 PIClusteringFiveCirclesInputsAndOutputs.png
-rw-r--r-- 1 steve staff 2004 Jan 27 18:07 pic-15.txt
drwxr-xr-x 48 steve staff 1632 Jan 30 12:35 pic.old
Notice: without the glob/asterisk. This function tacks it on automatically. I wanted this helper because it gets used many times daily.

How to include a library in the path while compiling?

I'm reading this post about go and was trying to compile the source code found here
I downloaded the source code, compiled the first file with make and I can see the object is generated:
$pwd
/Users/oscarryz/code/go/rsc/rosetta/graph
$ls -ltR
total 136
-rw-r--r-- 1 oscarryz staff 61295 Sep 17 16:20 _go_.6
drwxr-xr-x 3 oscarryz staff 102 Sep 17 16:20 _obj
-rw-r--r-- 1 oscarryz staff 126 Sep 17 16:17 Makefile
-rw-r--r-- 1 oscarryz staff 2791 Sep 17 16:17 graph.go
./_obj:
total 0
drwxr-xr-x 3 oscarryz staff 102 Sep 17 16:20 rsc.googlecode.com
./_obj/rsc.googlecode.com:
total 0
drwxr-xr-x 3 oscarryz staff 102 Sep 17 16:20 hg
./_obj/rsc.googlecode.com/hg:
total 0
drwxr-xr-x 3 oscarryz staff 102 Sep 17 16:20 rosetta
./_obj/rsc.googlecode.com/hg/rosetta:
total 136
-rw-r--r-- 1 oscarryz staff 68486 Sep 17 16:20 graph.a
No my question is, how do I refer to that compiled code from the maze directory:
/Users/oscarryz/code/go/rsc/rosetta/maze/maze.go
Whose import declarations are:
import (
"bytes"
"fmt"
"rand"
"time"
"rsc.googlecode.com/hg/rosetta/graph"
)
And right now is failing to compile with the error message:
6g -o _go_.6 maze.go
maze.go:20: can't find import: rsc.googlecode.com/hg/rosetta/graph
make: *** [_go_.6] Error 1
Ok, I found it, wasn't that hard.
6g flags: -I DIR search for packages in DIR
I have to specify the -I option like this:
6g -I ../graph/_obj/ -o _go_.6 maze.go

Resources