Library Interchange

Introduction

This chapter is about the library interchange definition format, LID.

The DRM defines an interchange format for Dylan source files, but does not define an interchange format for Dylan libraries. Without such an agreed format, different Dylan development environments would find it difficult to import and build libraries developed using another Dylan vendor’s environment. It would also be impossible to automate the process of importing a library into another environment.

LID solves this problem. It allows you to describe Dylan library sources in a form that any Dylan environment should be able to understand. Harlequin and other Dylan vendors have adopted LID to make it easier to port applications from one environment to another.

Note

LID is a convention, and not an extension to the Dylan language.

Note

The Open Dylan environment can convert LID files to its own internal project file format, the .hdp file. It can also save project files as LID files with the File > Save As command in the project window.

LID files

LID works by supplementing each set of library sources with a LID file. A LID file describes a Dylan library using a set of keyword statements. Together, these statements provide enough information for specifying and locating the information necessary to build a library from its source. This means all Dylan libraries designed for interchange consist of at least two files: a LID file, and one or more files containing the library source code.

Thus a LID file performs a similar function to the makefile used in some C and C++ development environments.

LID files have the file extension .lid.

Every file referred to by a LID file must reside in the same folder (directory) as the LID file.

LID keyword statements

A LID file consists of a series of keyword/value statements, just like the Dylan source file interchange format. In this section, we describe the standard LID keywords.

Library:

LID file keyword

Library: *library-name*

Names the Dylan library being described. The library-name must be the name of the Dylan library that the LID file describes. This keyword is required in every LID file, and it may appear only once per LID file.

Files:

LID file keyword

Files: *file-designators*

Associates a set of files with the library named by the Library: keyword. This keyword can appear one or more times per LID file. Every file specified is considered to be associated with the library.

A file designator is something that can be mapped to a concrete file name. Only one file designator can appear per line of the LID file. See File naming conventions for a description of the format of file designators and how they are mapped to concrete file names.

The order in which the designated source files are specified with the Files: keyword in the LID file determines the initialization order across the files within the defined library.

All the files must be specified relative to the same folder (directory) as the LID file.

Synopsis:

LID file keyword

Synopsis: *arbitrary text*

A concise description of the library.

Keywords:

LID file keyword

Keywords: *comma-separated phrases*

Any number of phrases, separated by commas, that are relevant to the description or use of the library.

Author:

LID file keyword

Author: *arbitrary text*

The name of the library’s author.

Major-Version:

LID file keyword

Major-Version: *number*

The current major version number of the library.

Minor-Version:

LID file keyword

Minor-Version: *number*

The current minor version number of the library.

Description:

LID file keyword

Description: *arbitrary text*

A description of the library. The intention of this keyword is to provide a fuller, less concise description than that given by the Synopsis: keyword.

Comment:

LID file keyword

Comment: *arbitrary text*

Any additional comments about the library.

Open Dylan’s LID extensions

This section contains extensions to LID that Open Dylan supports.

Specifying foreign files and resource files

The following keywords allow you to specify that files of foreign source code and resource files are a part of the library.

C-Source-Files:

LID file keyword

C-Source-Files: *c-source-files*

Identifies one or more C source files which are to be included as part of the library. Dylan environments copy these files to their build area and ensure that they are compiled by the appropriate batch file. The filenames specified must include the .c suffix.

C-Header-Files:

LID file keyword

C-Header-Files: *c-header-files*

Identifies one or more C header files included as part of the library. Dylan environments copy these files to their build area and ensure that they are compiled by the appropriate batch file. Any files specified using the C-Source-Files: or RC-Files: keywords depend on these header files in order to decide when they need to be recompiled. The file names given here must include the .h suffix.

C-Object-Files:

LID file keyword

C-Object-Files: *c-object-files*

Identifies one or more C object files included as part of the library. Dylan environments copy these files to their build area and ensure that they are compiled by the appropriate batch file and included in the final output as .DLL or .EXE files. The file names given here must include the .obj suffix on Windows or .o on other platforms, except when using this keyword in conjunction with a static library.

In some situations, a static library needs to be copied into the build area and linked into the project. This is typically when writing a binding for an external library written in C. In this situation, the C-Object-Files keyword may be useful.

RC-Files:

LID file keyword

RC-Files: *resource-files*

Identifies one or more resource files to be included as part of the library. Dylan environments copy these files to their build area and ensure that they are compiled by the appropriate batch file. The resulting resource object files are included in the .DLL or .EXE built for the library. The file names given here must include the .rc suffix.

C-Libraries:

LID file keyword

C-Libraries: *c-lib-files*

Identifies one or more C libraries to be included in the link phase when building the .DLL or .EXE for the library. Paths to search for libraries can also be added with this keyword. Arbitrary linker options can not be specified using this keyword.

On Windows, this value for this keyword is passed directly to the linker. However, on Unix and Mac OS X, the requirements are a bit more stringent and the arguments should be passed one per line and be one of the following:

-L path:
Add a path to the search path for shared libraries.
-llibrary:
Link against the specified shared library. This should be either in the regular linker search path or have a path specified via a -L flag.
library.a:

Link against the specified static library.

Note

Note that this may cause a problem if you are using this to link a static library that hasn’t been built with -fPIC into a shared library on the x86_64-linux platform.

Note

In general, you don’t want to use this keyword to link a static library into a shared library since this keyword propagates to dependent libraries as discussed below.

-F path:
Add a path to the search path for frameworks. (Mac OS X only)
-framework framework:
Link against the specified shared library. This should be either in the regular linker search path or have a path specified via a -F flag. (Mac OS X only)

Unlike the other keywords described in this section, the C-Libraries: keyword propagates to dependent libraries. For example, suppose library A uses library B, and the LID file or library B specifies

C-Libraries: foo.lib

In this case, both library A and library B are linked against foo.lib.

Specifying compilation details

The following keywords control aspects of compilation for the library.

LID:

LID keyword

LID: *file-name.lid*

Specifies the name of a LID file to process and includes the settings contained in that file into the current LID file.

This is commonly used to share common definitions and settings between platform or OS specific LID files.

Jam-Includes:

LID keyword

Jam-Includes: *file-name.jam*

Specifies the name of a JAM file to process. This is typically used when integrating with a third party library and needing custom flags for the C compiler or linker.

An example JAM (for a library, not an executable) file might look like:

{
  local _dll = [ FDLLName $(image) ] ;
  LINKLIBS on $(_dll) += `pkg-config --libs gtk+-3.0` ;
  CCFLAGS += `pkg-config --cflags gtk+-3.0` ;
}

The use of backticks `...` will execute the command enclosed within and return the output of that command.

Executable:

LID keyword

Executable: *name*

Specifies the name of the executable (that is, .DLL or .EXE) file to be generated for this library.

The suffix (.DLL, .EXE) should not be included in the name as the appropriate suffix will be added automatically.

If this keyword is not specified, the compiler generates a default name for the executable from the name of the library. With some library names, particularly when you are building a DLL, you may need to specify this keyword to override the default name and avoid conflicts with other DLLs from a third party.

Base-Address:

LID keyword

Base-Address: *address*

Specifies the base address of the DLL built from this Dylan library. The address must be a hexadecimal value. For convenience, you can use either Dylan (#xNNNNNNNN) or C (0xNNNNNNNN) notations when specifying the address.

This base address is ignored when building a .EXE file.

If this keyword is not specified, the compiler will compute a default base address for the library. However, it is possible for more than one library to end up with the same default base address. If an application uses any of these libraries, all but one of them will have to be relocated when the application starts. This process is automatic, but cuts down on the amount of sharing, increases your application’s memory footprint, and slows down load time. In such circumstances, you may want to give one or more libraries an explicit base address using this keyword.

Note

This keyword is only used on Windows and is ignored on other platforms.

Linker-Options:

LID keyword

Linker-Options: *options*

Specifies additional options and libraries to be passed to the linker when building this DLL or EXE. Unlike the C-Libraries: keyword, the options and libraries specified here apply only to this Dylan library; they are not propagated to any libraries which use this library.

File naming conventions

In practice, importing a source distribution into a Dylan program involves unpacking the source distribution into its own subtree and then informing the environment of the location of the tree root. The environment then walks the entire subtree locating LID files, which describe the libraries in the distribution by giving a name to, and designating the source files associated with, each library.

Importing a Dylan program into the environment in this way requires two things:

  1. That the LID files in the distribution can be identified.
  2. That the file designators supplied to the Files: keyword in LID files can be mapped to the corresponding source filenames on disk.

If you are importing files from a platform that does not insist on, or conventionally use, standard filename suffixes to identify the filetype (such as MacOS), then you must rename your source files as follows:

  • LID files must be given filenames with the suffix .lid.
  • Dylan source files must be given filenames with the suffix .dylan.

The file designators that appear in LID files may be a string of characters of any length, constructed from the set of hyphen, underscore, and the mixed-case alphanumeric characters. Note that you do not have to specify the source filename suffix as part of the filename designator. This ensures that the LID files themselves do not need to be edited when importing source code from a platform, such as MacOS, that does not insist on particular filename suffixes to specify the file type.

The name of a LID file is not significant, and in particular need not be the same as the library name. Hierarchical directory structure can be used to organize multi-library systems as long as the files directly associated with each library are in a single directory.

Application example

This section contains an example of a complete Dylan application that uses a generic factorial calculation routine to return the value of the factorial of 100. Two libraries are defined: the factorial library provides an implementation of the generic factorial routine, and the factorial-application library provides a method that calls the generic routine and returns the appropriate result.

File: fact.lid. LID file describing the components of the factorial library.

Library: factorial
Synopsis: Provides a naive implementation of the factorial
          function
Keywords: factorial, integer, simple, recursive
Files: library
       fact

File: library.dylan. Defines the factorial library and its one module.

Module: dylan-user

define library factorial
  use dylan;
  export factorial;
end;

define module factorial
  export fact;
end;

File: fact.dylan. Defines the method for calculating a factorial.

Module: factorial

define generic fact(n);

define method fact(n == 0)
  1;
end;

define method fact(n)
  n * fact(n - 1);
end;

File: app.lid. LID file describing the components of the factorial-application library.

Library: factorial-application
Synopsis: Computes factorial 100
Files: library
       app
Start-Module: factorial-application
Start-Function: main

File: library.dylan. Defines the factorial-application library and its one module.

Module: dylan-user

define library factorial-application
  use dylan;
  use factorial;
end library;

define module factorial-application
  use dylan;
  use factorial;
end module;

File: app.dylan. Defines a routine that calls the factorial routine.

Module: factorial-application

define method main (#rest ignore)
  fact(100);
end method;

The following example demonstrates how files of foreign source code and resource files can be integrated into a Dylan library:

Library: app-with-foreign-code
Synopsis: Uses some C code and resources
Files: dylan-code
C-Source-Files: first.c
  second.c
C-Header-Files: headers.h
RC-Files: extra-resources.rc