How to compile with a static library using MinGW?

How to compile with a static library using MinGW?

12
Basic UserBasic User
12

    Oct 03, 2015#1

    This question has never been asked before in this forum. It is a relatively easy process with other IDEs such as code::block, bloodshed dev c++, even with Visual Studio. Yet I am having a headache trying to replicate this process in UEStudio.

    Let's say that I am using UEStudio to build a default static library project using the default static library template supplied with UEStudio MinGW configuration. Let's call the project name TestLib. In addition to the default int InitLibrary(void) function supplied in the cpp file, I just want to add a function in this static library to print out the words "Test Print".

    TestStaticLib.h file:

    Code: Select all

    #include "stdio.h"
    #include <iostream>
    
    void TestPrint ();
    TestStaticLib.cpp file:

    Code: Select all

    #include "TestStaticLib.h"
    
    int InitLibrary(void)
    {
    	return 1;
    }
    
    void TestPrint (){
    
    	std::cout << "Test Print" << std::endl;
    }
    That is it. I build the static library without errors or warnings, and UEStudio outputs the files: TestStaticLib.a, TestStaticLib.o

    This ends the process of building a static library using UEStudio ...

    Now here is where the problems starts ...

    I now try to build a default console project using the default console template, call it TestConsole, and bring in the TestStaticLib:

    TestConsole.h file:

    Code: Select all

    #include "stdio.h"
    #include "TestStaticLib.h"
    TestConsole.cpp file:

    Code: Select all

    #include "TestConsole.h"
    
    int main(int argc, char* argv[])
    {
    	
    	TestPrint ();
    	return 0;
    }
    
    Compiler configurations:

    Under compiler options:

    Additional Include Directories = C:\Static\TestStaticLib (where the TestStaticLib.h file resides)

    Under Linker Options:

    Libraries = -lstdc++ -lkernel32 -user32 -lgdi32 -lcomctl32 -lcomdlg32 -lTestStaticLib (note that is -lTestStaticLib for Link)
    LibraryPath = C:\Static\TestStaticLib\Debug

    When I build, I got the error:

    Code: Select all

    c:/program files (x86)/idm computer solutions/mingw/bin/../lib/gcc/mingw32/4.7.1/../../../mingw32/bin/ld.exe: cannot find -lTestStaticLib
    I have put in every possible paths, under compiler options, linker options that I know of, so I really cannot understand why I still get the error message saying it cannot finds -lTestStaticLib.

    I am hoping my description is cleared and hoping someone can shed some lights into this issue and/or point me to the correct direction.

    Just out of curiosity, do I have to prefix my static library name with "lib" as in "libTestStaticLib" instead of just "TestStaticLib"?

    Thanks again.

    6,685587
    Grand MasterGrand Master
    6,685587

      Oct 03, 2015#2

      First, UEStudio is an IDE not designed for a specific compiler or a specific set of compilers as for example Visual Studio is. The GUI of IDEs written for specific compiler(s) are of course more or less perfectly designed for the supported compilers and documentation/help of those IDEs explain the features of the IDE as well as the features and options of the supported compilers, too.

      UEStudio is a general IDE not written for a specific compiler set. UEStudio can be customized using configuration files for various compilers, assemblers and interpreters. So every user can tailor-made UEStudio for own requirements. You need a compiler option frequently in various projects not included in the configuration files for the compiler, edit the configuration file(s) of used compiler. Or the compiler options dialog of the used compiler contains options you never need, edit the configuration file(s) and remove those options. You can design what is offered in compiler options window and what is not shown there.

      And UEStudio never compiles something itself. It just calls the compilers according to the definitions made in the configuration file(s) of used compiler, assembler or interpreter. So it is up to you how your projects are compiled.

      Of course beginners whether being familiar with the syntax of the configuration files read in by UEStudio and additionally also not having read the documentation of the used compiler need time to study and try out some things before they have knowledge to make changes on compiler settings and configurations quickly for their own purposes. But in my point of view it is worth this time to spent on as it makes coding later more efficient. A GUI designed by myself for my purposes is always better than a GUI designed by others for anybody.

      Second, you should never include in a later public header file of a library other header files not needed for the header file itself. The header file of your library TestStaticLib.h is included in the applications.

      So why to force the compiler to include header file iostream on compilation of TestConsole.cpp via TestStaticLib.h although this C++ source code file does not use class iostream at all?

      Header files of libraries should include as less header files as possible to make file dependency tree as small as possible for the applications using the library.

      So the file TestStaticLib.h should contain only

      Code: Select all

      #ifndef TESTSTATICLIB_H
      #define TESTSTATICLIB_H
      
      void TestPrint();
      
      #endif
      
      as this all needed for using this library function in applications.

      Using an include guard as demonstrated here to avoid multiple declarations in applications on repeating includes is also standard for library header files.

      Third, never include public header files from C or C++ standard libraries or any other libraries with double quotes. Standard C header file stdio.h is definitely not a header file of your static library project. So it should be included with angle brackets and not with double quotes. I explained already in this post the difference between #include <PublicHeaderFile.h> and #include "LocalHeaderFile.h". Take a C/C++ course or read a C/C++ introduction book if you don't understand my short description about the difference.

      Fourth, include as less header files as needed for a successful compilation of a source file.

      The class cout is declared in header file iostream. If your C++ source code file compiles with including this file only, don't include other header files.

      I think, standard C++ header file iostream includes itself standard C header file stdio.h and therefore it is not needed that you include stdio.h in your source code. But I don't really know if that is true as not yet verified by me. Well, you don't need to know what C++ header file iostream includes itself as long as your source code file compiles with including just header file iostream.

      By the way: stdio.h is a standard C header file. In C++ source code files standard C++ header file cstdio should be included (with angle brackets) when needed and not the C header file (although compilation works also with stdio.h as this C header file is prepared for compilation with C++ code).

      So your C++ library source code file TestStaticLib.cpp should contain:

      Code: Select all

      #include <iostream>
      #include "TestStaticLib.h"
      
      int InitLibrary(void)
      {
         return 1;
      }
      
      void TestPrint()
      {
         std::cout << "Test Print" << std::endl;
      }
      

      Clipper52a wrote:Just out of curiosity, do I have to prefix my static library name with "lib" as in "libTestStaticLib" instead of just "TestStaticLib"?
      On *nix operating systems file names of libraries usually start with lib and end with .so (shared object) for dynamic linked libraries or with .a (archive) for static libraries, see for example Is lib{library name}.a / .so a naming convention for static libraries in Linux? on StackOverflow.

      But on Windows libraries usually do not start with lib and the file extension is .lib for a static library and .dll for a dynamically loaded library.

      But MinGW (Minimalist GNU C/C++ compiler for Windows) is a Windows port of Unix GCC and therefore uses the naming convention from Unix also on Windows.

      Does MinGW required that the library file of a static library is named libLibraryName.a on referencing the library with just -lLibraryName and adding the directory containing the library file to list of library paths?

      Well, I don't know has I don't have MinGW installed and do not have read the documentation of MinGW. I think so according to the StackOverflow article referenced above. But I don't know it for sure and I can't verify it with a simple try.

      So let us look in documentation of GCC on Options for Linking and on MinGW HOWTOs and more specific on HOWTO Specify the Location of Libraries for use with MinGW.

      Also helpful is to enable in UEStudio the option Show build commands when executing in dialog opened by clicking on Advanced Build Options in menu Build to see in output window not only the results of a build, but also the commands really used making it possible to cross-check them with the documentation of the compiler.

      And last but not least when nothing other helps, the free tool Process Monitor from Sysinternals (Microsoft)
      • with a Filter rule Path contains file/directory name part then Include added with button Add and
      • having just Show File System Activity enabled from the 5 symbols on right side of toolbar of Process Monitor
      is also a great help on cannot find file ... error messages. It can be easily seen in Process Monitor where an application searches with which file names for a file.

      We can see in section [Variables] the line

      Code: Select all

      LOPT   = -mconsole $(Linker Options) $(LibraryPath) $(NoStartFiles) $(NoDefaultLibs) $(NoStdLib) $(Static) $(Shared)
      with looking on %ProgramFiles(x86)%\IDM Computer Solutions\UEStudio\configs\MinGW Compiler\Win32 Console Application which can be also viewed from within UEStudio by opening this file in UEStudio or using Build - Select Compiler and clicking on button Edit configuration with MinGW Compiler - Win32 Console Application being selected.

      This line defines the linker options used finally on line starting with Cmd0 = in section Build which is read by UEStudio on clicking on build command in toolbar displayed with option Show build commands when executing enabled in output window.

      You want to do here something which is not typical because typically either all library functions are linked dynamically to the application or all are linked statically. You want just your own library function linked statically to the application and all standard library functions dynamically.

      From what I read on the referenced pages I think you need to set in compiler options in section LINKER OPTIONS:

      Libraries = -lstdc++ -lkernel32 -user32 -lgdi32 -lcomctl32 -lcomdlg32 C:\Static\TestStaticLib\Debug\TestStaticLib.a
      LibraryPath =

      Your static library is specified with complete file name and with full path without -l as using -l with library name only would result in searching in all directories specified in LibraryPath = appended on command line after option -L for libTestStaticLib.a and libTestStaticLib.so according to documentations about linking option -l.

      This MinGW specific library search feature does not work here as your static library does not start with lib. Therefore it is necessary to specify the library file with complete file name and path.

      See also gcc -L / -l option flags and StackOverflow question How do I link a library file in GCC that does not start with lib?

      According to this answer on above referenced StackOverflow question the following linker options should also work:

      Libraries = -lstdc++ -lkernel32 -user32 -lgdi32 -lcomctl32 -lcomdlg32 -l:TestStaticLib.a
      LibraryPath = C:\Static\TestStaticLib\Debug

      PS: Now I know more about MinGW than I ever wanted to know because of not using this compiler for myself. I hope you learned here also how to find information in world wide web about MinGW usage and how to debug build process in UEStudio.
      Best regards from an UC/UE/UES for Windows user from Austria

      12
      Basic UserBasic User
      12

        Oct 05, 2015#3

        Hello Mofi,

        Thank you for your responds. Actually I was going to remove my question right after I posted it because as you said, I have thought of the nature of my question being a compiler specific so it may not be an appropriate question to post regarding a general IDE such as UEStudio.

        You have put in a wealth of information here, especially in regards to some of the unusual linkage usages in the MinGW compiler: the -l switch, the lib library prefix, the use of full path + file name linkages to get around some of the predicaments in the naming of library files, etc. which was very tricky to solve, and not to mention the enabling of the "show build commands when executing" option which is not turned on by default but when enabled, make things a lot easier to debug. I am glad and was very happy you share this information with us. Thanks again.