Cross-compile and deploy from linux to windows



  • Hello everyone,

    I am having some troubles compiling and creating an installer of an application I made. I would like to deploy it for Windows, but I am using linux (elementary). I am aware I need to use Mingw, and I installed mingw-w64, but still I couldnt get QtCreator to recognize it. Should QtCreator also be compiled for windows? Could someone walk me through how I do this cross-compilation?
    I have tried to use all the code and compile it under windows for windows, but then my multi-threading is not working for some reason, compiles with no error, but it just not multi-threaded. So I wanted to try cross-compilation from linux. Any advice?

    Thanks a lot!


  • Moderators

    @Tranquil said in Cross-compile and deploy from linux to windows:

    I have tried to use all the code and compile it under windows for windows, but then my multi-threading is not working for some reason, compiles with no error, but it just not multi-threaded. So I wanted to try cross-compilation from linux.

    Cross-compilation will not magically make your program multi-threaded. You need to change your code, not your tools.

    Can you show us the code that is supposed to be multi-threaded?

    I am aware I need to use Mingw, and I installed mingw-w64, but still I couldnt get QtCreator to recognize it. Should QtCreator also be compiled for windows?

    As I mentioned, cross-compilation will not help you here. But if you still want to do it, then you need:

    • MinGW that is compiled for Linux but targets Windows
    • Qt that is compiled for Windows (compiled using the same version of MinGW)
    • (Optional) Qt Creator that is compiled for Linux

  • Moderators

    @Tranquil Are you trying to build for windows using mingw in windows? Or are you trying to do it in linux?

    As a long time linux developer, I've found it's 1000x easier to build for each OS inside of a development environment for that OS.

    You should set up a vagrant or regular vm with a development environment including mingw and Qt in order to build and package your windows binaries.

    The multithreading thing is confusing... What exactly is not working with your threads? If they built they should work. What threading are you using? pthreads, windows threads, native C++ threads?



  • Thank you both for your help.
    I have decided to do the compilation in windows. And after few very bizarre errors, I successfully compiled it. I even had to rename some of my header files, as they were interfering with some other classes, I suppose. In any case, it compiles now, however it does not have the functionality. The application should read selected text files within a qtconcurrent loop.

    As I need to supply few variables to the QtConcurrent::map, I have created a container with pointers.

    struct DataLink{
        string* name;
        vector<dataType>* file;
        vector<dataType>* varfile;
        vector<dataType>* fftfile;
    };
    

    That container is filled with this function:

        QVector<DataLink> dataLinks;
        for (unsigned int i=0; i<data.fileNames.size(); ++i){
            DataLink datalink;
            datalink.name = &(data.fileNames[i]);
            datalink.file = &(data.defData[i]);
            datalink.varfile = &(data.varData[i]);
            dataLinks.push_back(datalink);
        }
        return dataLinks;
    

    Once the files are selected by the user, this function is started:

    // Convert QStringList into vector<string>
    std::vector<string> fileNamesVec;
    for (int i = 0; i < fileNames.size(); ++i) {
          std::string tmp = fileNames[i].toStdString();
          fileNamesVec.push_back(tmp);
    }
    this->data.fileNames = fileNamesVec;
    
    // Allocate data
    for (unsigned int i = 0; i<data.fileNames.size(); ++i){
         data.defData.push_back({0});
         data.varData.push_back({0});
    }
    // Import files
    Reader * reader = new Reader;
    reader->doProcessMulti(this->data);
    delete reader;
    

    My reading class (function doProcessOne):

    ifstream is((*datalink.name).c_str());
    istream_iterator<dataType> start(is), end;
    vector<dataType> extr(start, end);
    tmp = extr;
    extr.clear();
    

    And the main part (function doProcessMulti):

    QVector<DataLink> dataLinks = dataExtraction(data);
    
    QProgressDialog dialog;
    dialog.setWindowTitle("Reading");
    dialog.setLabelText(QString("Processing..."));
    
    QFutureWatcher<void> watcher;
    
    QObject::connect(&dialog, SIGNAL(canceled()), &watcher, SLOT(cancel()));
    QObject::connect(&watcher, SIGNAL(finished()), &dialog, SLOT(reset()));
    QObject::connect(&watcher, SIGNAL(progressRangeChanged(int,int)), &dialog, SLOT(setRange(int,int)));
    QObject::connect(&watcher, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int)));
    
    watcher.setFuture(QtConcurrent::map(dataLinks, [this] (DataLink& datalink) {doProcessOne(datalink);}));
    
    dialog.exec();
    

    Under linux it works perfectly well, and I can see multiple threads being used. Under windows, even though it compiles, it remains stuck and it does not read files at all. I did not include all the code, as it would be too much. I hope it makes sense. Thanks.



  • Simply You can use mxe for cross compilation from linux to Windows targets (not only qt, its supports the wide range of varios open-source libraries and tools like qt, sdl, wxwidgets, cryptopp and others)
    Just type:
    git clone https://github.com/mxe/mxe.git
    cd mxe
    make qt qt5 MXE_TARGETS='x86_64-w64-mingw32.shared i686-w64-mingw32.shared x86_64-w64-mingw32.static i686-w64-mingw32.static'

    Cross toolchain building process may take up to 10 hours (on my cor i5-2350 laptop) but it will download and build qt4.8.7 and the latest (5.11.1 in my case) qt versions (and dependencies also ) for mingw 32 and 64 bit static and shared respectively. After You can add new kit in QtCreator assuming the path of mingw compiler and qmake executable (mxe builds compiler too, no need to install mingw seperatly) .
    That's all, u can compile existing qt project into MS Windows exe file.

    About running windows exe-s in Linux - just install WINE
    https://www.winehq.org/


  • Moderators

    @Tranquil said in Cross-compile and deploy from linux to windows:

    And after few very bizarre errors, I successfully compiled it. I even had to rename some of my header files, as they were interfering with some other classes, I suppose.

    What were the "bizarre errors"? What were the names that you had to change? (All of these details can provide useful clues; pay attention to them)

    Under windows, even though it compiles, it remains stuck and it does not read files at all.

    Is this on a physical machine or a virtual machine? How many CPU cores does the machine have? (Qt Concurrent scales according to the number of cores)



  • @JKSH Errors were:

    1. error: missing binary operator before token "(" #if QT_DEPRECATED_SINCE(5, 3)
    2. Qt Creator code model “could not parse an included file” warning and errors in derived template classes: incomplete type 'QMetaObject' named in nested name specifier

    The first one I fixed by renaming my header (and according cpp) files: system.h, process.h, filter.h. The second one was fixed after including into the project file the following variable: QT_OPENGL = desktop.

    Yes, I am using my laptop to compile, and it has intel i7 2.2GHz with 4 cores and 8 logical processors. Well, basically I am using a dual boot, so the same hardware is applied for the working Linux version and non-working Windows version.

    EDIT
    I have simulated my program in a small unit test, and I figured out that multi-threading should actually work, but my problem lies right after the line:

    istream_iterator<dataType> start(is), end;
    vector<dataType> extr(start, end); // This one is problematic
    

    Well, the problem lies, I believe, in the importing text files. They are single column, but have tab separation before every float, per line. In linux this gets converted into two spaces and it somehow works. But in windows it does not. Do you have any idea how to go around this issue? I would love the fastest way to read files into vectors.


  • Moderators

    @Tranquil said in Cross-compile and deploy from linux to windows:

    error: missing binary operator before token "(" #if QT_DEPRECATED_SINCE(5, 3)

    ...

    The first one I fixed by renaming my header (and according cpp) files: system.h, process.h, filter.h.

    This fix makes sense, as the generic filenames could have clashed with system headers provided by your compiler.

    • Have you re-compiled your project in Linux after renaming your files? Does your project still work as expected?

    Qt Creator code model “could not parse an included file” warning and errors in derived template classes: incomplete type 'QMetaObject' named in nested name specifier

    ...

    The second one was fixed after including into the project file the following variable: QT_OPENGL = desktop.

    This fix looks curious.

    • Which class had this error? Your own custom class, or a Qt-provided class?
    • How did you learn about this variable, and how did you know this would fix the problem?

    Yes, I am using my laptop to compile, and it has intel i7 2.2GHz with 4 cores and 8 logical processors. Well, basically I am using a dual boot, so the same hardware is applied for the working Linux version and non-working Windows version.

    OK, now we know it's not a hardware issue.

    EDIT
    I have simulated my program in a small unit test, and I figured out that multi-threading should actually work, but my problem lies right after the line:

    istream_iterator<dataType> start(is), end;
    vector<dataType> extr(start, end); // This one is problematic
    

    Well, the problem lies, I believe, in the importing text files. They are single column, but have tab separation before every float, per line.

    • What is dataType? Please show the struct.
    • What does your text file look line? Please post a few sample lines.

    In linux this gets converted into two spaces and it somehow works. But in windows it does not.

    • Who does the conversion?

    I would love the fastest way to read files into vectors.

    • How big is each file?
    • How many files does your program need to read?


  • @JKSH
    It does work after renaming the classes. I will keep them with the new names in both cases.
    For the second problem, the error was in the definition of a MainWindow, so Qt provided class (complained about QObject). But I got this warning in code model that some includes are not included, so it would make sense. I googled for hours, and then found randomly on a Qt discussion, hidden deep in comments, someone from the Qt team mentioned the variable QT_OPENGL, and it worked. I can try to find the link if you want.
    dataType is basically double, I just renamed it in case I decide to change it easily to float in the whole code.
    The conversion is done automatically, I believe. If I take the file from windows, it would be different than taking it from windows, copying to linux, and returning to windows. I have to double check that, but some of them have tab spacing, and some two white spaces.
    Each file is from 50 to 600 Mb, and sometimes I import 2, and sometimes 7 of them, so lets say up to 10.
    0_1537403579104_files.png


  • Moderators

    @Tranquil
    I don't know how you read your text-file. But if it is for example with QTextStream, you coulc read line by line, call QString QString::simplified() const on it. that removes all leading and trailing whitespaces and reduces al other whitespaces to a simple single space. That should include tab and multiple spaces.

    Than QString::splitRef(QChar::Space); on it and you have a vector of all your entries (in StringRef format) -> convert it to your container.