Question & Answer
Question
I get unresolved external references when trying to compile and link my program with the CPLEX CallableLibrary. What's wrong?
Answer
Unresolved external references occur when the symbol for a function or global
variable is referenced in a program, but none of the object files or libraries
specified in the link step contain a definition for that symbol. While the error
message may initially appear confusing, most unresolved external references
fall into a few distinct categories that are straightforward to correct. So,
an organized approach to categorize them can save significant time and effort.
While the following discussion focuses on linking problems that arise
with the CPLEX Callable Library, many of the tips here may be useful in fixing
linking errors in other applications.
Let's start with some general tactics that can help isolate the source of the
linker error.
I. Try to reproduce the error with as simple an example as possible.
In the context of CPLEX, this means try to compile and link one of the simple
C or C++ examples (e.g. lpex1.c or ilolpex1.cpp, respectively) and see if the
linker
error occurs there. If so, you have a smaller example with which to work.
If not, focus on the differences between your program and the CPLEX example
program as likely sources of the error. Your ILOG CPLEX software distribution
includes make files or projects for the example programs you can use to compile and link
the
the examples.
II. Make use of some helpful tools available on your operating system.
Under Unix, the nm utility allows you to examine symbols in object files and
libraries. By applying the nm utility to both the CPLEX Callable Library and
the object files that call its functions, you can see if the symbol names
associated
with the functions are consistent. For example, use the following command to
search an object file for the symbol associated with the CPLEX function
CPXopenCPLEX():
nm -o lpex1.o | grep CPXopenCPLEX
The resulting output is:
lpex1.o: U CPXopenCPLEX
The output indicates lists the symbol for the CPXopenCPLEX function as
it appears in the object file. The 'U' symbol indicates that this function call
is not resolved in this object file; the function resides in some other object
file or library.
Now, apply the same command to the CPLEX Callable Library libcplex.a.
nm -o libcplex.a | grep CPXopenCPLEX
The resulting output is:
libcplex.a:envlib.o:00000000 T CPXopenCPLEX
By comparing the nm output of libcplex.a and lpex1.o, we see that in this case
the function symbol names match. However, if the symbols did not match in some
way (e.g. the symbol appeared as CPXopenCPLEX@4 in lpex1.o), that mismatch
is the cause of the linker error and must be corrected in order for the program
to link properly. Note that a 'T' appears in the output for libcplex.a because,
unlike lpex1.o, libcplex.a contains the actual function in question.
Refer to a man page or Unix manual for more information on the nm utility.
Windows based computers typically lack the nm utility. However, you can
accomplish
similar symbol comparisons using the library manager of your compiler, using
your linker to generate a map file, or by simply opening your object file and
CPLEX Callable Library from a text editor. Most library managers have an option
that enables you to obtain an extensive symbol listing of a library or object
file. In some cases you may need to first create a library from your object
file. These listings allow you to compare symbol names in a manner similar to
the one described above with the nm utility. If not, generate a map file with
your linker and examine the symbol names therein. Otherwise, you can often
search
for symbols with a text editor. Even though the object and library files are
binary, many text editors will still allow you to search them for character
strings corresponding to symbol names.
III. Determine the type of unresolved symbol.
In many cases, identifying the type of unresolved symbol immediately sheds light
on the source of the trouble. Here is a list of the most common types of linker
errors, and the appropriate action to either fix the problem or obtain
additional
information.
* The linker issues unresolved errors for all CPLEX functions in your program.
Possible causes include:
1. Your link statement doesn't properly identify the CPLEX Callable Library.
Compare your compile and link statement with the ones in the examples make file
that comes
with your ILOG CPLEX software. This may help you identify errors or omissions
in
your compile and link statement.
2. The CPLEX function names in the object files of your program do not match
those of the CPLEX library because the compiler has put a prefix or suffix
around
the function names. Try compiling and linking one of the simple CPLEX example
programs that comes with your software distribution. If you can reproduce the
error, use the nm or lib utilities as described above to compare the function
names. If they don't match, check your compiler's documentation for any options
that affect function names. Examples include the Watcom compiler, which by
default
appends an underscore to the function names (use the -5s option from the
compile line or the Pentium Stack based calling convention from the IDE to
suppress
the underscore), and FORTRAN compilers which frequently translate function names
to upper case (most of them support the -U or some similar option that will
cause the compiler to generate case sensitive names).
3. If you wrote the calling program, be sure that the function prototypes
in the CPLEX header file cplex.h are surrounded by the 'extern "C"'
statement. This will occur automatically with CPLEX 6.0 and later, but you will
need to use this statement with earlier versions of CPLEX.
4. Your copy of the CPLEX callable library has been corrupted or is of the wrong
format. Examples include trying to link to an old SunOS 4 CPLEX Callable Library
on a Sun machine running Solaris, or trying to link from Borland C Builder to
the import library that comes with your CPLEX distribution instead of one
generated
from the CPLEX DLL using Borland's implib utility. In such cases, you
should be able to reproduce the error with one of the CPLEX example programs.
Also, under Unix, the 'file' utility program determines
the type of an individual file.
* The linker issues unresolved errors for only certain CPLEX functions in your
program.
This type of error occurs much less frequently. Check the spelling of the
functions
that generate the errors. Focus on other differences between the CPLEX functions
in libcplex.a that the linker finds and the ones that generate the errors. Use
the nm utility if necessary.
* The linker issues errors for functions with names such as "pow",
"sqrt", "ceil" and "floor". Yet, your program
does call any of these functions.
These are functions in the standard math libraries for your C or C++ compiler.
You need to add the -lm option to your compile and link statement.
* (Windows only) The linker issues errors involving functions 'main' or
'winmain'.
When you build a Windows program, your compiler typically allows you to
specify whether the application is a Console based or Windows based application.
Console based applications require a 'main' routine, while Windows based
applications require a 'winmain' routine. If you wrote your program to be a
Console application but inadvertently specified a Windows application in your
project or link statement, the linker expects the main routine to be 'winmain',
yet your program specifies 'main' as the main routine. The result is a linker
error.
* The linker issues errors for functions with name that are neither in your
program nor in the CPLEX Callable Library.
All CPLEX functions begin with a 'CPX' prefix. If you get linker errors that
do not have this prefix, are not called by your program, and are not part of
the math libraries as mentioned previously, your system or compiler may be
improperly
configured to find all the libraries needed for your program. You may need to
add a directory to your path, add another linker option to enable the compiler
to find another library, update an out of date or corrupted library used by
your compiler, or modify a compiler or linker environment variable to fix the
problem. Once again, the nm utility can help under Unix. For example, suppose
you compile and link your program and get an unresolved symbol for a function
'weirdfunc'. You know your own program doesn't call this function, and the CPLEX
library doesn't contain it since it lacks the 'CPX' prefix. Therefore,
'weirdfunc'
is probably a low level system function called by a system call made either
by your program or the CPLEX library. You can find out if this function resides
in one of the standard C libraries by going to the directory containing these
libraries (typically /usr/lib) and typing the following command:
nm -o *.a | grep weirdfunc
This should help you determine the library containing this function. Also,
for symbols like these, searching the web for the unresolved symbol name
can often shed some light on the cause of the problem.
So, to summarize, an organized approach to linker errors should help reduce
the time spent correcting them. By reproducing the error with as simple an
example
as possible, making use of all available system tools, and classifying the type
of error, most linker errors can be resolved quite quickly.
Historical Number
cplex/FAQ/8
Was this topic helpful?
Document Information
Modified date:
16 June 2018
UID
swg21399926