Linking programs

Genero programs are created by linking several .42m modules and/or .42x libraries together, where one of the modules defines a MAIN block. By convention, the resulting program file gets the 42r extension.

Note that linking is supported for backward compatibility, you should use IMPORT FGL instead. When using IMPORT FGL to import all modules used by a program, the link stage is no longer required (you can directly execute the 42m module containing the MAIN block).

Program linking is done with the fglrun tool by using the -l option. The fgllink tool can be used for convenience; it is a simple script calling fglrun -l.

The following lines show a link procedure to create a program in a UNIX™ shell session:
$ fglcomp main.4gl
$ fglcomp store.4gl
$ fgllink -o stores.42r main.42m store.42m

The purpose of the linking phase is to check for missing function symbols, and reference all the symbols in the resulting .42r program file. Any function used in the .42m modules specified in the link line must be provided. Missing symbols will result in a -1338 linker error. Note that this applies only to programs: When linking a 42x library, there can be references to undefined functions:

$ cat main.4gl
MAIN
  CALL myfunc()
END MAIN

$ fglcomp main.4gl
$ fgllink -o prog.42r main.42m
ERROR(-1338):The function 'myfunc' has not been defined in any module in the program.

The generated 42r program files do not contain the 42m p-code. When deploying your application, you must provide all 42m modules, as well as 42r program files. Since 42x library files are only used to build programs, you do not have to deploy 42x library files.

If you omit the -o option in the fgllink command, the default output file will have the .42x extension and the name of the module containing the MAIN block. The .42r file extension is used by convention to distinguish a program dictionary file from a library dictionary file.

When linking a 42r program by using 42x libraries, the modules defined in a library are included only if one of the symbols in the module is used by the program. However, all symbols of 42m modules specified in the command line will always be referenced in the resulting 42r program file. The same function symbols can be defined in distinct libraries; the linker will select the function of the first library that was specified in the command line.

All symbols referenced in a module must exist in the final 42r program dictionary file. If a symbol is not found, the runtime system stops with error -1338. This error is fatal and cannot be trapped with an exception handler.

When linking a 42r program, global symbols must be unique; otherwise, error -6203 will be returned by the linker. The same error will be returned when linking a 42x library by using modules defining the same functions.

If you do not specify an absolute path for a file, the linker searches by default for .42m modules and .42x libraries in the current directory. You can specify a search path with the FGLLDPATH environment variable:
$ FGLLDPATH=/usr/dev/lib/maths:/usr/dev/lib/utils
$ export FGLLDPATH
$ ls /usr/dev/lib/maths
mathlib1.42x
mathlib2.42x
mathmodule11.42m
mathmodule12.42m
mathmodule22.42m
$ ls /usr/dev/lib/utils
fileutils.42m
userutils.42m
dbutils.42m
$ fgllink -o myprog.42r mymodule.42m mathlib1.42x fileutils.42m

In this example the linker will find the specified files in the /usr/dev/lib/maths and /usr/dev/lib/utils directories defined in FGLLDPATH.

When creating a .42r program by linking .42m modules with .42x libraries, if the same function is defined in a .42m and in a module of a 42x library, the function of the specified .42m module will be selected by the linker, and the function of the library will be ignored. However, the linker will raise error -6203 if two .42m modules specified in the link command define the same function.

The link procedure searches recursively for the functions used by the program. For example, if the MAIN block calls function FA in module MA, and FA calls FB in module MB, all functions from module MA and MB will be included in the 42r program definition.

When linking a program with modules using the IMPORT FGL instruction, you do not have to specify the imported modules in the link line, since these modules will be loaded dynamically at runtime. However, any symbol used by the imported module must be resolved by the linker. Therefore, if the imported module uses functions that come from other modules which are not imported by this module, these non-imported modules must be specified in the link command line. For example, if the main module imports module MA to call the function FA, which in turn calls a function FB from module MB, but MA does not import MB, you will have to specify MB in the link line to have the linker resolve the FB function.

When linking a .42r program by using a .42x library, if none of the functions of a module in the .42x library are used in the program, the complete module is excluded by the linker. This may cause undefined function errors at runtime, such as when a function is only used in a dynamic call (an initialization function, for example.)

The following case illustrates this behavior:

$ cat x1.4gl
function fx11()
end function
function fx12()
end function

$ cat x2.4gl
function fx21()
end function
function fx22()
end function

$ cat prog.4gl
main
  call fx11()
end main

$ fglcomp x1.4gl
$ fglcomp x2.4gl
$ fglcomp prog.4gl

$ fgllink -o lib.42x x1.42m x2.42m

$ fgllink -o prog.42r prog.42m lib.42x

Here, module x1.42m (with functions fx11 and fx12) will be referenced in the .42r program file, but functions of module x2.42m will not. At runtime, any dynamic call to functions fx21() or fx22() will fail with an un-trappable error -1338.

If you are using C-Extensions, you may need to use the -e option to specify the list of extension modules if the IMPORT keyword is not used:

$ fgllink -e extlib,extlib2,extlib3 -o stores.42r main.42m store.42m