Author Topic: It seems we don't need to create a dummy file to list gcc include paths  (Read 9732 times)

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5917
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Hi, all.

In the function below

Code
wxArrayString NativeParser::GetGCCCompilerDirs(const wxString &cpp_compiler, const wxString &base)
{
    wxArrayString gcc_compiler_dirs;

    // for starters , only do this for gnu compiler
//    Manager::Get()->GetLogManager()->DebugLog(_T("CompilerID ") + CompilerID);
    //    wxString Command("mingw32-g++ -v -E -x c++ - < nul");
    // specifying "< nul", does not seem to work
    // workaround : create a dummy file (let's hope it does not exist)
    // do the trick only for c++, not needed then for C (since this is a subset of C++)
    wxString DummyFileName = wxFileName::CreateTempFileName(_T("Dummy_z4hsdkl9nf7ba3L9nv41"));
    if(!DummyFileName.IsEmpty())
    {
        // let's construct the command
        wxString Command = cpp_compiler + _T(" -v -E -x c++ ") + DummyFileName;
        // action time  (everything shows up on the error stream
        wxArrayString Output, Errors;
        wxExecute(Command, Output, Errors, wxEXEC_NODISABLE);
        int nCount = Errors.GetCount();
        // the include dir (1 per line) show up between the lines
        // #include <...> search starts here:
        // End of search list
        //   let's hope this does not change too quickly, otherwise we need
        // to adjust our search code (for several versions ...)
        bool bStart = false;
        for(int idxCount = 0; idxCount < nCount; ++idxCount)
        {
            if (!bStart && Errors[idxCount] == _("#include <...> search starts here:"))
            {
                bStart = true;
            }
            else if (bStart && Errors[idxCount] == _("End of search list."))
            {
                bStart = false; // could jump out of for loop if we want
            }
            else if (bStart)
            {
//                Manager::Get()->GetLogManager()->DebugLog("include dir " + Errors[idxCount]);
                // get rid of the leading space (more general : any whitespace)in front
                wxRegEx reg(_T("^[ \t]*(.*)"));
                if(reg.Matches(Errors[idxCount]))
                {
                    wxString out = reg.GetMatch(Errors[idxCount], 1);
                    if(!out.IsEmpty())
                    {
                        wxFileName dir(out);
                        if (NormalizePath(dir,base))
                        {
                            Manager::Get()->GetLogManager()->DebugLog(_T("Caching GCC dir: ") + dir.GetFullPath());
                            gcc_compiler_dirs.Add(dir.GetFullPath());
                        }
                        else
                        #if wxCHECK_VERSION(2, 9, 0)
                            Manager::Get()->GetLogManager()->DebugLog(F(_T("Error normalizing path: '%s' from '%s'"),out.wx_str(),base.wx_str()));
                        #else
                            Manager::Get()->GetLogManager()->DebugLog(F(_T("Error normalizing path: '%s' from '%s'"),out.c_str(),base.c_str()));
                        #endif
                    }
                }
            }
        } // end for : idx : idxCount
        // clean up our temp file
        ::wxRemoveFile(DummyFileName);
    } // Dummy is open

    return gcc_compiler_dirs;
}

A dummy file will be created to input to the command line like:

mingw32-g++ -v -E -x c++ dummyfilename

So, we need to create a dummyfile and after getting all the include paths, we need to delete this file.


After search on Google for an hour, I found there is a way to avoid this:
See this page:

http://gcc.gnu.org/ml/gcc-help/2004-02/msg00142.html

it use these command, it use a minus sign to replace a dummy file name.

mingw32-g++ -v -E -x c++ -

Sees work fine in MinGW, here is the report:

Code

D:\test>mingw32-g++ -v -E -x c++ -
Using built-in specs.
Target: mingw32
Configured with: ../gcc-4.4.0/configure --prefix=/mingw --build=mingw32 --enable
-languages=c,ada,c++,fortran,objc,obj-c++ --disable-nls --disable-win32-registry
 --disable-werror --enable-threads --disable-symvers --enable-cxx-flags='-fno-fu
nction-sections -fno-data-sections' --enable-fully-dynamic-string --enable-libgo
mp --enable-version-specific-runtime-libs --enable-sjlj-exceptions --with-pkgver
sion='TDM-1 mingw32' --with-bugurl=http://www.tdragon.net/recentgcc/bugs.php
Thread model: win32
gcc version 4.4.0 (TDM-1 mingw32)
COLLECT_GCC_OPTIONS='-v' '-E' '-mtune=i386'
 d:/mingw/bin/../libexec/gcc/mingw32/4.4.0/cc1plus.exe -E -quiet -v -iprefix d:\
mingw\bin\../lib/gcc/mingw32/4.4.0/ - -mtune=i386
ignoring nonexistent directory "d:\mingw\bin\../lib/gcc/mingw32/4.4.0/../../../.
./mingw32/include"
ignoring duplicate directory "d:/mingw/lib/gcc/../../lib/gcc/mingw32/4.4.0/inclu
de/c++"
ignoring duplicate directory "d:/mingw/lib/gcc/../../lib/gcc/mingw32/4.4.0/inclu
de/c++/mingw32"
ignoring duplicate directory "d:/mingw/lib/gcc/../../lib/gcc/mingw32/4.4.0/inclu
de/c++/backward"
ignoring duplicate directory "/mingw/lib/gcc/mingw32/4.4.0/../../../../include"
ignoring duplicate directory "d:/mingw/lib/gcc/../../include"
ignoring duplicate directory "d:/mingw/lib/gcc/../../lib/gcc/mingw32/4.4.0/inclu
de"
ignoring duplicate directory "d:/mingw/lib/gcc/../../lib/gcc/mingw32/4.4.0/inclu
de-fixed"
ignoring nonexistent directory "d:/mingw/lib/gcc/../../lib/gcc/mingw32/4.4.0/../
../../../mingw32/include"
ignoring duplicate directory "/mingw/include"
#include "..." search starts here:
#include <...> search starts here:
 d:\mingw\bin\../lib/gcc/mingw32/4.4.0/include/c++
 d:\mingw\bin\../lib/gcc/mingw32/4.4.0/include/c++/mingw32
 d:\mingw\bin\../lib/gcc/mingw32/4.4.0/include/c++/backward
 d:\mingw\bin\../lib/gcc/mingw32/4.4.0/../../../../include
 d:\mingw\bin\../lib/gcc/mingw32/4.4.0/include
 d:\mingw\bin\../lib/gcc/mingw32/4.4.0/include-fixed
End of search list.



Thanks. :D

If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Very nice finding, ollydbg.  8)

Instead of "-", I would use /dev/null or nul depending on operating system, since otherwise gcc will hang (at least does here). Also, if you already call g++, the -x c++ is not needed.
Now, the question is whether to call gcc or g++, actually it would be nice to always call the "correct" compiler depending on whether you compile C or C++ so include paths would be different for C (which they are in real, too) ... but projects may be mixed, and you don't want to call an external program for every single source file parsed...
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5917
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Oh, Yes, you are right.

In MinGW, I found that if only use "-", then gcc will hang up. So, can this method be used in Windows?

Edit:
I'm sorry, I mis understand your previous message. Now I catch the point fully :D,

In Windows, this command works ( no hang up):
mingw32-g++ -v -E -x c++ nul
In Linux, this command works:
mingw32-g++ -v -E -x c++ /dev/null


In Linux, using "/dev/null" is better. I also found in the web page below:

http://www.linuxquestions.org/questions/showthread.php?p=2344101#post2344101


For the C or C++ issue, I think g++ is better, because it include all the C headers.  :D
« Last Edit: May 25, 2009, 12:58:08 pm by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5917
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
I add a patch in BerliOS

https://developer.berlios.de/patch/index.php?func=detailpatch&patch_id=2783&group_id=5358

I would be happier any dev can test that under Linux. :D
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.