An archive or library file is a file that contains one or more object files. Its name must begin with lib
and it must have .a
for its extention. Library files provide a convenient way to distribute pre-compiled code. In addition to the .a
file, header files with prototypes for all of the "public" functions must be provided as well.
The C standard library is distributed as a set of header and library files. Prior to writing your own LCD library, you made use of a pre-compiled library of functions for using the LCD.
Command Line Technique
A library file consists of a collection of one or more object files. The command line program to create a library file is avr-ar
and is found in the WinAVR/bin
directory. Running avr-ar
from the command line looks something like this:
avr-ar -rs libSOMETHING.a FIRST.o [SECOND.o ...]
where libSOMETHING.a
is the name of the library file you wish to create and FIRST.o
and beyond are the name(s) of the object files to be placed in the library file.
A number of command options are available. Here we have used two:
r
— This tells the program to replace the listed.o
files if they are already in the library file.s
— This tells the program to write an object-file index into the archive.
You can see a list of all of the command options by running avr-ar
without any parameters.
Suppose we wish to make a library file for our own LCD library that we wrote. The LCD implementation consists of three files:
lcd.h
— contains prototypes for "public" functions and other constants (as#define
s).lcdprivate.h
— contains prototypes for "private" functions and other constants that should only be used in the implementation of the LCD library.lcd.c
— contains the complete implementation of our LCD library.
We can create a library file for our LCD library and then distribute only the .a
file and the public header file (lcd.h
). Creating the library file is as simple as:
avr-ar -rs libLCD.a lcd.o
Makefile Technique
AVR Studio provides its own set of rules for how to compile a project. When selecting Rebuild All from the Build menu in AVR Studio the build process begins. This process includes compiling each .c
file in the project as well as linking the files together to produce a .hex
file and potentially creating other files like a .lss
file.
The Project -> Configuration Options menu option allows customization of the build process. If we wish to create a library file as part of the the build process, we can specify that by providing a custom makefile. The makefile must contain the instructions for how to create the library file. The addition to the makefile might look something like this:
## Archive into a library file (.a) $(TARGET): $(OBJECTS) avr-ar -rs $(TARGET) $(OBJECTS)
We typically start by asking AVR Studio to generate a makefile that matches its current build process. This is accomplished by Build -> Export Makefile. This file may look something like this:
############################################################################### # Makefile for the project lcd ############################################################################### ## General Flags PROJECT = lcd MCU = atmega32 TARGET = lcd.elf CC = avr-gcc.exe ## Options common to compile, link and assembly rules COMMON = -mmcu=$(MCU) ## Compile options common for all C compilation units. CFLAGS = $(COMMON) CFLAGS += -Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d ## Assembly specific flags ASMFLAGS = $(COMMON) ASMFLAGS += $(CFLAGS) ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2 ## Linker flags LDFLAGS = $(COMMON) LDFLAGS += -Wl,-Map=lcd.map ## Intel Hex file production flags HEX_FLASH_FLAGS = -R .eeprom HEX_EEPROM_FLAGS = -j .eeprom HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load" HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings ## Objects that must be built in order to link OBJECTS = lcd.o ## Objects explicitly added by the user LINKONLYOBJECTS = ## Build all: $(TARGET) lcd.hex lcd.eep lcd.lss size ## Compile lcd.o: ../lcd.c $(CC) $(INCLUDES) $(CFLAGS) -c $< ##Link $(TARGET): $(OBJECTS) $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET) %.hex: $(TARGET) avr-objcopy -O ihex $(HEX_FLASH_FLAGS) $< $@ %.eep: $(TARGET) -avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0 %.lss: $(TARGET) avr-objdump -h -S $< > $@ size: ${TARGET} @echo @avr-size -C --mcu=${MCU} ${TARGET} ## Clean target .PHONY: clean clean: -rm -rf $(OBJECTS) lcd.elf dep/* lcd.hex lcd.eep lcd.lss lcd.map ## Other dependencies -include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)
This file can then be modified to build a library file instead of a .hex
file. The modified file may look something like this:
############################################################################### # Makefile for the project lcd (modified to generate .a file) ############################################################################### ## General Flags PROJECT = lcd MCU = atmega32 TARGET = libLCD.a CC = avr-gcc.exe ## Options common to compile, link and assembly rules COMMON = -mmcu=$(MCU) ## Compile options common for all C compilation units. CFLAGS = $(COMMON) CFLAGS += -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d ## Assembly specific flags ASMFLAGS = $(COMMON) ASMFLAGS += $(CFLAGS) ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2 ## Objects that must be built in order to link OBJECTS = lcd.o ## Build all: $(TARGET) ## Compile lcd.o: lcd.c $(CC) $(INCLUDES) $(CFLAGS) -c $< ## Archive into a library file (.a) $(TARGET): $(OBJECTS) avr-ar -rs $(TARGET) $(OBJECTS) ## Clean target .PHONY: clean clean: -rm -rf $(OBJECTS) $(TARGET) dep/*
There are a number of changes between the files:
- The
TARGET
has been changed tolibLCD.a
instead oflcd.elf
- Changed
../lcd.c
tolcd.c
in the Compile section - The following sections have been removed since they are no longer needed:
- Linker flags
- Intel Hex file production flags
- Objects explicitly added by the user
- Link
- Other dependencies
- The
lcd.hex lcd.eep lcd.lss size
list has been removed from the Build and Clean target sections - The Archive section has been added.
Using a Library File
Once created, the library file can be used in any other project without needing to add the .c
source files to that project. This allows the project to use different compiler settings (e.g., a different optimization level) than were used in compiling the library code and eliminates the need to recompile the library source code in every project that uses the library code.
The library may now be used in other projects as long as the appropriate header files and the .a
file are available. If we want to use the libLCD.a
library created earlier, we need to let the project know where the libLCD.a
file is located. To do this, we must select Project -> Project Configuration and then select the Libraries option from the list on the left. Add the appropriate search path to the list on the upper right pane and then select libLCD.a
from the list of Available Link Objects and select Add Library —> in order to tell the compiler to include the libLCD.a
file when running the linker for this project. The following figure illustrates the result of these steps:
The lcd.h
file must be included in any .c
that uses functions from the library.