How to configure linking with system libraries in CM3

This document explains how to configure linking Modula3 code with external libraries installed on your system. It is of interest to people who want to write Modula3 wrappers for libraries written in other programming languages, and to people who have problems with CM3 detecting libraries installed on their systems.

How CM3 links programs

When CM3 links an executable, it calls a function written in Quake that implements linking for the target. This function is called m3_link(). It is defined in the CM3 configuration file cm3.cfg, and can pull in system libraries if requested.

The following is an example m3_link() implementation, taken from CM3 5.4 on FreeBSD. It is just here for illustration. We do not need to elaborate on it for the purpose of this document. Alas, it should be very obvious to people who are familiar with the Quake language, and somewhat obvious to those how don't.

proc m3_link (prog, options, objects, imported_libs, shared) is
  local args = []
  if M3_PROFILING args += "-pg" end
  args += [ "-o", prog, options, objects, imported_libs ]
  if shared
    return try_exec ("@" & SYSTEM_CC, args)
  else
    return try_exec ("@" & SYSTEM_CC, "-static", args)
  end
end

The SYSTEM_LIBS Array

Information about libraries installed on your system is gathered in the SYSTEM_LIBS array, which is also defined in cm3.cfg. It defines the arguments cm3 should pass as the imported_libs argument to m3_link() in order to link with a given library. The SYSTEM_LIBS array is usually set up by the cminstall program during CM3 installation.

Let's look at an example definition (taken from the FreeBSD version):

SYSTEM_LIBS = {
  "LIBC"       : [ "-lm" ],
  "FLEX-BISON" : [ "-L/usr/lib", "-lfl" ],
  "POSTGRES95" : [ "-L/usr/local/lib", "-lpq" ],
  "OPENGL"     : [ "-L/usr/X11R6/lib", "-lGLU", "-lGL", "-lXext" ],
  "ODBC"       : [ "-L/usr/local/lib", "-lodbc" ],
  "MOTIF"      : [ "-L/usr/X11R6/lib", "-lXm" ],
  "X11"        : [ "-L/usr/X11R6/lib", "-lXaw", "-lXmu", "-lXext",
                        "-lXt", "-lSM", "-lICE", "-lX11" ],
  "TCP"        : [ ]
}

Consider the line

  "POSTGRES95" : [ "-L/usr/local/lib", "-lpq" ],
   

"POSTGRES95" is the name the library can be refered to from an m3makefile. To import a system library into a module, the import_sys_lib function can be used. For example, you could put the following Quake code into an m3makefile to import the postgresql system library:

   if SYSTEM_LIBS contains "POSTGRES95"
     import_sys_lib ("POSTGRES95")
   end 
  

The part [ "-L/usr/local/lib", "-lpq" ] contains the flags that will be passed in the to link an executable with the system library.

You can add further linker options to the array. Popular ones are "-Xlinker" and "-Bdynamic", which together enable dynamic linking on platforms that use the GNU linker:

[ "-Xlinker", "-Bdynamic", "-L/usr/local/lib", "-lpq" ]

This is the default on the Linux platform since CM3 5.4, since a lot of Linux distributions stopped shipping static libraries.

The line:

  "TCP"        : [ ]
  

in the example indicates that no external libraries are needed to link with the TCP library. This is true since the library has been integrated into CM3 a long time ago. It is still defined in SYSTEM_LIBS for backward compatibility, in case a program expects the library to be external.


m3-support{at}elego.de