meganz / mingw-std-threads

Standard threads implementation currently still missing on MinGW GCC on Windows
BSD 2-Clause "Simplified" License
439 stars 137 forks source link

"Std-like" headers generator #62

Closed lanyizi closed 5 years ago

lanyizi commented 5 years ago

Sometimes I don't want to modify all my source files to change includes from #include <header> to #include "mingw.header.h". So I wrote some simple scripts which will generate header files named in the "standard way", allowing us to keep our #includes unchanged, but at the same time, without making changes to the system headers.

How to use

The script used to generate files requires PowerShell. I avoided to some newer features, hoping to make my script compatible with PowerShell 2.0 (which can be installed on Windows XP as well, unfortunately I don't have XP on my PC so I can't test whether my script works on XP or not...)

Example: generate_std_like_headers.bat -DestinationFolder "some/folder" g++ foo.cpp -o foo.exe -std=c++17 -Wall -Isome/folder Several headers (<thread>, <mutex> etc.) will be generated inside "some/folder", which can then be added to GCC's include path through the -I option. User provided include paths have higher priority than the system search paths, so GCC will look for these generated headers instead of real system headers.

The files tests.cpp and CMakeLists.txt inside tests folder have been modified so it can use these new generated files, by passing -DCMAKE_BUILD_TYPE=StdLikeHeaders to CMake.

Additional Options

Interactive mode You can also run generate_std_like_headers_interactive.bat, which doesn't need any command line parameters, instead it prompts for user input interactively.

Manually specifying GCC's path You can also manually specify GCC's path (it will be used to search for system headers) by using the -GccPath option, for example generate_std_like_headers.bat -DestinationFolder some\folder -GccPath C:\MinGW-w64\bin\gcc. When this options is not specified, my script will try to invoke GCC directly (assuming it's inside PATH).

"Compiler wrapper" batch script If you don't want to pass the -I option manually to the compiler, you can also use the option -GenerateCompilerWrapperWithFileName. It will create a batch script which automatically forwards any argument to g++.exe, plus a -I option.

For example: generate_std_like_headers.bat -DestinationFolder "some/folder" -GenerateCompilerWrapperWithFileName mingw-std-headers-g++.bat Then you can compile with the following command: mingw-std-headers-g++ foo.cpp -o foo.exe -std=c++17 -Wall

nmcclatchey commented 5 years ago

I like the way you think; this is a valuable contribution to the library.

Some thoughts:

lanyizi commented 5 years ago
  • The macro USE_STD_LIKE_HEADERS has a fair chance of colliding with macros from other libraries. To reduce odds of a collision, it can be prefaced with the name of the project: MINGW_STDTHREAD_USE_STD_LIKE_HEADERS.

All right, will update that soon.

  • CMake has a configure_file utility, which can be used to create a new file with various tokens replaced. This could be used to replace the bash script (which some users might not be comfortable running, especially because it creates an alias for their compiler...) with a cmake sub-file for inclusion in user's own CMake project. This would provide an alternate approach, for those who wish to make this decision on a project level, rather than on a system level.

Actually the script won't create an alias for their compiler by default, but only when user specifies explicitly the -GenerateCompilerWrapperWithFileName command line option. If the generated alias is not inside PATH then it won't be able to be referenced (directly) from other location.

I'll look into configure_file now, will make a commit as soon as I figure out how to parse GCC output from CMake (will need that to find out the exact location of system headers).

lanyizi commented 5 years ago

Should we create a project-level CMakeLists.txt (with an option to generate std-like headers)? Because otherwise it's becoming harder to work with tests.cpp if I make the std-like header generator's CMakeLists.txt in another sub directory...

lanyizi commented 5 years ago

Made some changes to allow generating headers purely from CMake (detailed description can be found also in the modified readme.md). It should fully work without any problems now, except that it works only for gcc and clang (or any other compiler that supports -H option which outputs full paths of included headers).

Edit: made a new commit with compiler checks inside CMakeLists.txt. If it's not being compiled with GCC or clang, std headers won't be generated even if CMake option MINGW_STDTHREADS_GENERATE_STDHEADERS is set. Users can use the preprocessor definition MINGW_STDTHREADS_GENERATED_STDHEADERS to know whether std-like headers have been actually generated.

alxvasilev commented 5 years ago

Hi @BSG-75 Thanks for your contribution! One thing - we still need the system <mutex> header, which is included by mingw.mutex.h. Did you test that mingw.mutex.h still works (i.e. includes the real system mutex header and not the generated one), or am I missing something?

nmcclatchey commented 5 years ago

@alxvasilev That appears to be covered by line 60 of CMakeLists.txt. Are you seeing compilation errors?

alxvasilev commented 5 years ago

I don't have the possibility to test right now, but I wonder how it can work if inside mingw.mutex.h #include<mutex> forces inclusion of the stub header instead of the needed system one.

lanyizi commented 5 years ago

@alxvasilev When any file (regardlessly of user code or headers) includes <mutex>, the generated header will be included. The generated header will in turn include system mutex header, this time not by #include <mutex>, but by using #include "{full path to system mutex file}". Then mingw.mutex.h will also be included by the generated header.

So, system's mutex is already included even before mingw.mutex.h is included.

alxvasilev commented 5 years ago

Ok, I saw it now, thanks. Then, I think all looks good. Merging.