10.5.3. Accessing Files and Libraries from a Linker Command File

Many applications use custom linker command files (or LCFs) to control the placement of code and data in target memory. For example, you may want to place a specific data object from a specific file into a specific location in target memory. This is simple to do using the available LCF syntax to reference the desired object file or library. However, a problem that many developers run into when they try to do this is a linker generated “file not found” error when accessing an object file or library from inside the LCF that has been specified earlier in the command-line invocation of the linker. Most often, this error occurs because the syntax used to access the file on the linker command-line does not match the syntax that is used to access the same file in the LCF.

Consider a simple example. Imagine that you have an application that requires a table of constants called “app_coeffs” to be defined in a memory area called “DDR”. Assume also that the “app_coeffs” data object is defined in a .data section that resides in an object file, app_coeffs.c.o. The app_coeffs.c.o file is then included in the object file library app_data.lib. In your LCF, you can control the placement of the “app_coeffs” data object as follows:

SECTIONS
{
    ...
    .coeffs: { app_data.lib<app_coeffs.c.o>(.data) } > DDR
    ...
}

Now assume that the app_data.lib object library resides in a sub-directory called “lib” relative to where you are building the application. In order to gain access to app_data.lib from the build command-line, you can use a combination of the –i and –l options to set up a directory search path which the linker can use to find the app_data.lib library:

%> tiarmclang <compile options/files> -Wl,-i=./lib,-lapp_data.lib mylnk.cmd <link files>

The –i option adds the lib sub-directory to the directory search path and the –l option instructs the linker to look through the directories in the directory search path to find the app_data.lib library. However, if you do not update the reference to app_data.lib in mylnk.cmd, the linker will fail to find the app_data.lib library and generate a “file not found” error. The reason is that when the linker encounters the reference to app_data.lib inside the SECTIONS directive, there is no –l option preceding the reference. Therefore, the linker tries to open app_data.lib in the current working directory.

In essence, the linker has a few different ways of opening files:

  • If there is a path specified, the linker will look for the file in the specified location. For an absolute path, the linker will try to open the file in the specified directory. For a relative path, the linker will follow the specified path starting from the current working directory and try to open the file at that location.

  • If there is no path specified, the linker will try to open the file in the current working directory.

  • If a –l option precedes the file reference, then the linker will try to find and open the referenced file in one of the directories in the directory search path. The directory search path is set up via –i options.

As long as a file is referenced in a consistent manner on the command line and throughout any applicable LCFs, the linker will be able to find and open your object files and libraries.

Returning to the earlier example, you can insert a –l option in front of the reference to app_data.lib in mylnk.cmd to ensure that the linker will find and open the app_data.lib library when the application is built:

SECTIONS
{
    ...
    .coeffs: { -l app_data.lib<app_coeffs.c.o>(.data) } > DDR
    ...
}

Another benefit to using the –l option when referencing a file from within an LCF is that if the location of the referenced file changes, you can modify the directory search path to incorporate the new location of the file (using –i option on the command line, for example) without having to modify the LCF.