Building Libraries

A library is a collection of frequently used functions (for example, functions like strcpy () , printf() , strcmp() , and atoi() ), that can be incorporated into a program on an as-needed basis. For example, if a program used strcmp() , then the code for strcmp() would be pulled from the appropriate library and included in the application. Regardless of how many functions are in the library, only the code for functions actually referenced by the program is pulled into the program. So, at least two things are gained as a result of using a library:

  • A library saves a project from having to add strcmp.o , printf.o , atoi.o, etc. to the link line. The programming team does not even need to be aware of what functions they are getting from the library. The programmers merely include something like -lc on the linker line, and the rest is magic.

  • A library reduces the size of the final program module (as compared to including the library source) because unneeded functions are not pulled into the executable.

In some cases, you might want to build your own library. For example, if the code that interfaces to some peripheral widget is to be used by several projects and you want the benefits mentioned above, it might make sense to package the interface functions as a library.

If you know only a little about the process, you might attempt to create a library by putting all of the related functions ( widget_funcA() , widget_funcB() , and widget_funcC() ) into a single file, compiling it with - c to generate an object ( .o ) file, and then using some tool ( lib or ar usually) to create a library ( .a ) file from the .o file.

Unfortunately , this approach doesnt have the desired effect because all of the functions were compiled to a single .o file. A library is basically a concatenation of object modules (or .o files). When the linker goes to the library looking for a currently unresolved reference, it looks through each of the object modules for a match. When it finds a match, it pulls that entire object module into the program code, regardless of the number of functions in that module. If several functions were originally compiled together into a common .o file, referencing one of those functions results in all of the functions being incorporated into the finished program. The users of such a library are unknowingly getting more for their money! Unfortunately, more is not good in a tight-memory space embedded system. Fortunately, this problem is easily resolved. When building a library, put each function in a separate file that gets built separately.

Wasted space isnt the only reason to avoid monolithic libraries. Suppose that I want to use the previously mentioned library to interface to my widget; however, I have a special case where I want to write my own widget_funcB() and use the librarys widget_funcA() . With a monolithic build, Ill end up with two widget_funcB() s in my program because when the linker goes to the library to get widget_funcA() , the other function comes with it. Now there is a name clash between the widget_funcB() in the library and the widget_funcB() that I wrote.

In my experience, this problem is most common when trying to use my own printf(). (Yes, you will need to write your own printf() sooner or later in embedded systems programming!) I want my printf() to call vsprintf() (provided by the library), but, unfortunately, printf() and vsprintf() are in the same object module in the library. I cant call vsprintf() because the linker says that there are two printf() functions (mine and the one pulled in as a result of using vsprintf() ).

The important thing to remember is that whenever you build your own library, you build it as a lot of individual one-function-per-file modules. Youll save headaches and memory space!



Embedded Systems Firmware Demystified
Embedded Systems Firmware Demystified (With CD-ROM)
ISBN: 1578200997
EAN: 2147483647
Year: 2002
Pages: 118
Authors: Ed Sutter

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net