Trying to build statically an application using libxml2 I have errors like
undefined reference to `__imp_xmlTextReaderRead'
Removing the -static option it works perfectly.
The command I used is:
gcc -o myapp.exe `xml2-config --cflags` -I /mingw64/include myapp.c `xml2-config --libs` -static
To rectify the undefined references to symbols of the form
__imp_xml*, predefine preprocessor macroLIBXML_STATICon yourgcccommandline, like so:Why?
You are working with
gccon Windows. The undefined references of the form__imp_xml*show that your compiler is working in the expectation that your code will be dynamically linked againstlibxml2.dllat runtime, and to that end will be linked against that DLL's import librarylibxml2.libat buildtime. The__imp_xml*references will be resolved by that buildtime import library in proxy forlibxml2.dll. Your compiler is emitting these references to discharge DLL import declarations of the form__declspec(dllimport) xml*that it finds in the source code, after preprocessing.The presence of these
dllimportdeclarations proves that the compiler is seeing preprocessed code not intended to enable static linkage againstlibxml2, i.e. linkage against the static librarylibxml2.a, in which symbols are defined without the__imp_prefix.But you are a specifying static linkage (
-static). This prohibits the linker from considering import libraries, even if they are available. The library options that accrue in your commandline by shell-expansion ofxml2-config --libswill be of the form-l xml2 [...]. In the presence of-static, the linker will attempt to resolve-l xml2by scanning its search directories only for alibxml2.a, notlibxml2.libAccordingly, the undefined
__imp_xml*reference errors go away, as you observe, when you remove the-staticoption from your commandline - because the linker is then at liberty to search forlibxml2.lib.Since you want a static linkage, the compiler ought not to be seeing preprocessed code destined for dynamic linkage. But however that problem might be solved for the compiler, the
-staticoption will not do it, because that is a linkage option and does not influence compilation.The preprocessor does influence compilation and
libxml2uses the preprocessor macroLIBXML_STATICas a switch to decide whether the API function declarations in its public header files will emerge from preprocessing prefixed with__declspec(dllimport), or with__declspec(dllexport), or with neither. The relevant preprocessor boilerplate is found in the header filelibxml2/libxml/exmlexports.h, which will be included by anylibxml2public header file that you include in your own code.(The comments are all mine.)
That's why you need to define
LIBXML_STATICbefore compilation commences, per commandline option-DLIBXML_STATIC, to suppress the default production of client code that presumes dynamic linkage.But...
Be forewarned that not all undefined symbol linkage errors will necessarily go away with the
__imp_xml*ones. If you specify-static, then the linker must find static versions of all the libraries required by your program: not justlibxml2, but also all those thatlibxml2recursively depends on. There are quite a few of those and it is not unlikely you haven't installed static versions of them all.If you do have them all, your app will be a very large executable with a very small power-to-weight ratio. You may or may not have already reckoned with that. If it would suffice for your needs to link
libxml2itself statically, but not its whole dependency chain, you can do that too. Consult the GNU linker's commandline options to learn about the relevant linker options-Bstaticand-Bdynamic, and also the GCC's commandline options concerning the option-Wlto see howgcccan pass linker-specific options to the linker.