Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to link a gfortran static library?



  • Hi, I saw this post below:

    Re: [SOLVED] Compiling Fortran code with gfortran within a C++ project

    I added the @LIBS += -lgfortran@ in my *.pro file, but I still got a lot of linking errors like:

    undefined reference to `_gfortran_date_and_time'
    undefined reference to `_gfortran_st_write'
    undefined reference to `_gfortran_adjustl'
    undefined reference to `_gfortran_transfer_integer_write'
    

    I added my static Fortran library by Qt Creator IDE Wizard, and it added these lines in my *.pro file:

    unix:!macx: LIBS += -L$$PWD/../test/ -lmylib
    
    INCLUDEPATH += $$PWD/../test
    DEPENDPATH += $$PWD/../test
    
    unix:!macx: PRE_TARGETDEPS += $$PWD/../test/libmylib.a
    

    How can I solve it?


  • Lifetime Qt Champion

    Hi,

    Might be a silly question but are the architectures compatible ?


  • Qt Champions 2017

    @fem_dev said in How to link a gfortran static library?:

    I added the @LIBS += -lgfortran@ in my *.pro file

    In which pro file? You should add this to the application project file, which I don't see in the snippet you provided.



  • @kshegunov I compile my Fortran code using Ubuntu terminal and gfortran...

    // Compile and get *.o file:
    gfortran -c -g fortran.f90
    
    // Add *.o file to a Linux library *.a
    ar cr libmylib.a *.o
    
    // (Optional) Add internal library object indexes:
    ranlib libmylib.a
    

    So, I copied this library file libmylib.a to my Qt C++ application folder and added it to my Qt project using Qt Creator IDE Wizard

    My Qt C++ Application PRO file:

    QT -= gui
    
    CONFIG += c++11 console
    CONFIG -= app_bundle
    @LIBS += -lgfortran@
    
    # The following define makes your compiler emit warnings if you use
    # any Qt feature that has been marked deprecated (the exact warnings
    # depend on your compiler). Please consult the documentation of the
    # deprecated API in order to know how to port your code away from it.
    DEFINES += QT_DEPRECATED_WARNINGS
    
    # You can also make your code fail to compile if it uses deprecated APIs.
    # In order to do so, uncomment the following line.
    # You can also select to disable deprecated APIs only up to a certain version of Qt.
    #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
    
    SOURCES += \
            main.cpp
    
    # Default rules for deployment.
    qnx: target.path = /tmp/$${TARGET}/bin
    else: unix:!android: target.path = /opt/$${TARGET}/bin
    !isEmpty(target.path): INSTALLS += target
    
    unix:!macx: LIBS += -L$$PWD/../test/ -lmylib
    
    INCLUDEPATH += $$PWD/../test
    DEPENDPATH += $$PWD/../test
    
    unix:!macx: PRE_TARGETDEPS += $$PWD/../test/libmylib.a
    

    Here is my Qt main.cpp file:

    #include <QCoreApplication>
    
    extern "C" {
        void f_analysis_x(const char* data_file_path, const int job_id);
    }
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        const char project_path[44] = "/home/nycholas/Desktop/test/my_project.json";
        const int job_id = 0;
    
        f_analysis_x(project_path, job_id);
    
        return a.exec();
    }
    

    The function called f_analysis_x() is my Fortran function that is located inside the libmylib.a file.

    But when I hit the Compile button, I got these linker errors:

    undefined reference to `_gfortran_date_and_time'
    undefined reference to `_gfortran_st_write'
    undefined reference to `_gfortran_adjustl'
    undefined reference to `_gfortran_transfer_integer_write'
    

    What I can do?

    Both Fortran library and Qt C++ applications are builded in the same system:

    • Ubuntu 18 x64
    • gfortran
    • Qt Creator IDE 4.10

  • Qt Champions 2017

    @LIBS += -lgfortran@
    should be without @, this is a remnant from old forum formatting. qmake should've warned you that the line is invalid. What you should see

    The name f_analysis_x in fortran resolves to f_analysis_x_ in C terms, so if the function's called myfunc in fortran, it should be declared as myfunc_ in C (yes, C-linkage is required). Finally, fortran doesn't know what const is, so don't lie to your C compiler. Another thing may be that you have a static libgfortran and a dynamic one in your distro, check that. And finally you can inspect what symbols are undefined in your static lib, and what symbols libgfortran provides with the nm tool. My advice - if you have that particular code available in C/C++ use that and forget fortran.
    Also take a look here: https://stackoverflow.com/questions/23551416/unable-to-link-to-libgfortran-a



  • @kshegunov thank you...

    So, I remove the @ sign, but I got the same linker erros about gfortran symbols.
    The updated line is:

    LIBS += -lgfortran
    

    Yes, by default the function name will contain a _ at the end, but I'm using Fortran 2003 C ISO BINDING Interface:

    subroutine f_analysis_x(project_path, job_id) bind(C)
    

    So the function name is only f_analysis_x and it is working good on Windows x64 platform. My problem is only when I try to do the same process in the Linux environment.

    On Windows 10 x64, I'm using Intel Visual Fortran 2019 with Microsoft Visual Studio 2019 to do my Fortran library *.lib file.
    And using Microsoft Visual Studio 2019 to compile and link my C++ code together with my Fortran library.
    It's working good!

    So, in Ubuntu, I'm using gfortran (Terminal) and Qt Creator IDE 4.10.

    Why I'm getting these linker errors about gfortran?


  • Qt Champions 2017

    @fem_dev said in How to link a gfortran static library?:

    Why I'm getting these linker errors about gfortran?

    Because for some reason the linker can't find the symbols. Why that is, I'm not sure. My best advice is to run nm (and grep the output) on the libgfortran and on your library and see:

    1. that your library does in fact reference these functions (you should see them as undefined symbols in the output)
    2. that your libgfortran does expose them (i.e. they should be marked as defined in the output) exactly as they're requested from 1)


  • @fem_dev said in How to link a gfortran static library?:

    So, I copied this library file libmylib.a to my Qt C++ application folder

    then you said

    The updated line is:
    LIBS += -lgfortran

    so what is the actual name of the Fortran library you built?
    is it just a name issue regarding the actual file and what you use in the .pro configuration?



  • @Pablo-J-Rogina and @kshegunov

    Thank you for your help. Now I will organize my question in a better way:
    I have only 2 source-code files:

    • main.cpp
    • fortran.f90

    So, I compile the Fortran source-code and generate a Linux library called libmylib.a:

    // Compile and get *.o file:
    gfortran -c -g fortran.f90
    
    // Add *.o file to a Linux library *.a
    ar rcs libmylib.a fortran.o
    

    Now I imported this libmylib.a file to Qt Creator IDE using the IDE import external library Wizard.

    Here is my entire *.pro file:

    QT -= gui
    
    CONFIG += c++11 console
    CONFIG -= app_bundle
    LIBS += -lgfortran
    
    DEFINES += QT_DEPRECATED_WARNINGS
    
    SOURCES += \
            main.cpp
    
    # Default rules for deployment.
    qnx: target.path = /tmp/$${TARGET}/bin
    else: unix:!android: target.path = /opt/$${TARGET}/bin
    !isEmpty(target.path): INSTALLS += target
    
    unix:!macx: LIBS += -L$$PWD/../test/ -lmylib
    
    INCLUDEPATH += $$PWD/../test
    DEPENDPATH += $$PWD/../test
    
    unix:!macx: PRE_TARGETDEPS += $$PWD/../test/libmylib.a
    

    Here is my main.cpp file:

    #include <QCoreApplication>
    
    extern "C" {
        // yes, I updated the function input arguments:
        void f_subroutine(const char* c_str, const size_t len, const int job_id);
    }
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        const char c_str[] = "/home/nycholas/Desktop/test/my_project.json";
    
        f_subroutine(c_str, strlen(c_str), 0);
    
        return a.exec();
    }
    

    But when I hit the Compile button, I got these linker errors:

    undefined reference to `_gfortran_date_and_time'
    undefined reference to `_gfortran_st_write'
    undefined reference to `_gfortran_adjustl'
    undefined reference to `_gfortran_transfer_integer_write'
    undefined reference to `_gfortran_string_trim'
    undefined reference to `_gfortran_concat_string'
    

    I think that Qt Creator IDE is not linking with gfortran library even using this line in the *.pro file:

    LIBS += -lgfortran
    

    @kshegunov about nm libmylib.a I got basically this result:

    0000000000000000 T f_subroutine
                     U _gfortran_adjustl
                     U _gfortran_concat_string
                     U _gfortran_date_and_time
                     U _gfortran_stop_numeric
                     U _gfortran_string_trim
                     U _gfortran_st_write
                     U _gfortran_st_write_done
                     U _gfortran_transfer_integer_write
                     U _GLOBAL_OFFSET_TABLE_
    

    Finally, if I go outside Qt world and try to compile and link just using the Linux Terminal, all goes Ok, no errors and works great!

    // Compile C++ and link the Fortran library
    g++ -Wall -g main.cpp -L . -lmylib -lgfortran -o app
    
    // run application:
    ./app
    

    So, what is the difference between the compile/link sequence that I have done just using the Linux Terminal and using Qt Creator IDE?
    How can I solve this gfortran linker errors on Qt Creator IDE?


  • Qt Champions 2017

    @fem_dev said in How to link a gfortran static library?:

    So, what is the difference between the compile/link sequence that I have done just using the Linux Terminal and using Qt Creator IDE?

    There's quite a lot of them, as I imagine the Qt compile line is as long as the distance between London and New York. But first thing first:

    1. Do yourself a favor and enable relocations; compile with -fPIC.
    2. Would you humor me and move the LIBS += -lgfortran at the end of your project file, after you've linked your library?
    3. Also you provided only half of what I asked for. Not only did I request the nm output from your library, but I also wanted you to list the symbols from the libgfortran in your path and grep against one of the missing symbols, say _gfortran_date_and_time.


  • @kshegunov thank you a lot for your informations! Today I learned a little bit more about Qt compile/link process.

    1. Do yourself a favor and enable relocations; compile with -fPIC
    

    Ok. I did it now!

    2. Would you humor me and move the LIBS += -lgfortran at the end of your project file, after you've linked your library?
    

    Ok! I moved this line to the end of *.pro file and now I can compile and link with my Fortran static library with no errors!
    This solved my problem! Thanks!

    3. [...]  but I also wanted you to list the symbols from the libgfortran in your path and grep against one of the missing symbols, say _gfortran_date_and_time.
    

    In the library *.a folder I typed:

    nm libmylib.a | grep libgfortran
    

    And I got no results. Total clean.



  • @fem_dev said in How to link a gfortran static library?:

    This solved my problem! Thanks!

    Great, so don't forget to mark your post as solved then. Thanks


Log in to reply