Skip to content

Support mingw-w64 (from msys2) on Windows. #1570

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 32 additions & 3 deletions Release/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,33 @@ set(CPPREST_VERSION_REVISION 17)

enable_testing()

set(WERROR ON CACHE BOOL "Treat Warnings as Errors.")
if(MINGW)
# on mingw there are tons of warnings.
set(WERROR OFF CACHE BOOL "Treat Warnings as Errors.")
Comment on lines +19 to +20
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's keep WERROR on, and either address the warnings or tell people to turn it off.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressing the warnings requires a lot changes in the codebase. Could I print a CMake warning if users are working with MinGW and WERROR is ON?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah a warning is fine, I just don't like setting werror based on platform

else()
set(WERROR ON CACHE BOOL "Treat Warnings as Errors.")
endif()
set(CPPREST_EXCLUDE_WEBSOCKETS OFF CACHE BOOL "Exclude websockets functionality.")
set(CPPREST_EXCLUDE_COMPRESSION OFF CACHE BOOL "Exclude compression functionality.")
set(CPPREST_EXCLUDE_BROTLI ON CACHE BOOL "Exclude Brotli compression functionality.")
set(CPPREST_EXPORT_DIR cmake/cpprestsdk CACHE STRING "Directory to install CMake config files.")
set(CPPREST_INSTALL_HEADERS ON CACHE BOOL "Install header files.")
set(CPPREST_INSTALL ON CACHE BOOL "Add install commands.")

SET(DEFAULT_BUILD_TYPE "Release")
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to '${DEFAULT_BUILD_TYPE}' as none was specified.")
set(CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE}" CACHE STRING "Choose the type of build." FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
Comment on lines +31 to +36
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't change the build type like this, just print a warning during configuration if the build isn't likely to work.


# There's a "string table overflow" with mingw-w64 when optimization is disabled.
#
# see also: https://stackoverflow.com/questions/14125007/gcc-string-table-overflow-error-during-compilation
if(MINGW AND CMAKE_BUILD_TYPE STREQUAL "Debug")
message(FATAL_ERROR "mingw-w64 cannot build the debug version of this library")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a forward compat issue, just warn.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fixes that by using a warning.

endif()

if(IOS OR ANDROID)
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared libraries")
else()
Expand Down Expand Up @@ -97,6 +116,12 @@ elseif(UNIX AND NOT APPLE) # Note: also android
set(CPPREST_FILEIO_IMPL posix CACHE STRING "Internal use.")
set(CPPREST_HTTP_CLIENT_IMPL asio CACHE STRING "Internal use.")
set(CPPREST_HTTP_LISTENER_IMPL asio CACHE STRING "Internal use.")
elseif(MINGW)
set(CPPREST_PPLX_IMPL linux CACHE STRING "Internal use.")
set(CPPREST_WEBSOCKETS_IMPL wspp CACHE STRING "Internal use.")
set(CPPREST_FILEIO_IMPL posix CACHE STRING "Internal use.")
set(CPPREST_HTTP_CLIENT_IMPL asio CACHE STRING "Internal use.")
set(CPPREST_HTTP_LISTENER_IMPL asio CACHE STRING "Internal use.")
elseif(WINDOWS_PHONE OR WINDOWS_STORE)
set(CPPREST_PPLX_IMPL winrt CACHE STRING "Internal use.")
set(CPPREST_WEBSOCKETS_IMPL winrt CACHE STRING "Internal use.")
Expand Down Expand Up @@ -169,8 +194,12 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(LD_FLAGS "${LD_FLAGS} -Wl,-z,defs")

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive -D_GLIBCXX_USE_SCHED_YIELD -D_GLIBCXX_USE_NANOSLEEP")
if (MINGW)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive")
else()
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive -D_GLIBCXX_USE_SCHED_YIELD -D_GLIBCXX_USE_NANOSLEEP")
endif()
endif()

elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
Expand Down
17 changes: 16 additions & 1 deletion Release/include/cpprest/details/SafeInt3.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,23 @@ Please read the leading comments before using the class.

#ifndef C_ASSERT
#define C_ASSERT_DEFINED_SAFEINT
#if defined(__MINGW32__)
#define C_ASSERT(e) void __C_ASSERT__(int [(e)?1:-1])
#else // defined(__MINGW32__)
#define C_ASSERT(e) typedef char __C_ASSERT__[(e) ? 1 : -1]
#endif
#endif // defined(__MINGW32__)
#else
#if defined(__MINGW32__)
// the default definition from mingw is: extern void __C_ASSERT__(int [(e)?1:-1])
//
// When be used in class declration the compiler will complains: error: storage class specified for '__C_ASSERT__'.
// See also: https://github.com/Alexpux/mingw-w64/blob/master/mingw-w64-tools/widl/include/winnt.h
//
// But we cannot define it as `typedef char __C_ASSERT__[(e) ? 1 : -1]`, since it may conflict with the system's one.
#undef C_ASSERT
#define C_ASSERT(e) void __C_ASSERT__(int [(e)?1:-1])
#endif // defined(__MINGW32__)
#endif // C_ASSERT

// Let's test some assumptions
// We're assuming two's complement negative numbers
Expand Down
2 changes: 1 addition & 1 deletion Release/include/cpprest/details/basic_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

namespace utility
{
#ifdef _WIN32
#if defined(_WIN32)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

driveby change

#define _UTF16_STRINGS
#endif

Expand Down
4 changes: 2 additions & 2 deletions Release/include/cpprest/details/cpprest_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

#pragma once

#if defined(_WIN32)
#if defined(_WIN32) && !defined(__MINGW32__)

#if _MSC_VER >= 1900
#define CPPREST_NOEXCEPT noexcept
Expand Down Expand Up @@ -69,7 +69,7 @@
#endif // __clang__
#endif // _WIN32

#ifdef _NO_ASYNCRTIMP
#if defined(_NO_ASYNCRTIMP) || defined(__MINGW32__)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just force _NO_ASYNCRTIMP on mingw, don't special case the feature here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, actually this is a visibility macro, so I'm not sure this is even right, even on mingw if you're building a shared library I think you need __declspec(dllexport) (attribute((visibility)) may work as well)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I remember it correctly mingw-w64 (gcc) exports all symbol by default, just like what happens to the shared library on Linux.

But I would restore the dllexport behaviour on mingw-w64 by good.

#define _ASYNCRTIMP
#else // ^^^ _NO_ASYNCRTIMP ^^^ // vvv !_NO_ASYNCRTIMP vvv
#ifdef _ASYNCRT_EXPORT
Expand Down
8 changes: 4 additions & 4 deletions Release/include/cpprest/filestream.h
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,7 @@ class basic_file_buffer : public details::streambuf_state_manager<_CharType>
static pplx::task<std::shared_ptr<basic_streambuf<_CharType>>> open(
const utility::string_t& _Filename,
std::ios_base::openmode _Mode = std::ios_base::out,
#ifdef _WIN32
#if defined(_WIN32) && !defined(__MINGW32__)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all of these can probably be #ifdef _MSC_VER or similar instead. (do check if that works for clang, however)

int _Prot = (int)std::ios_base::_Openprot
#else
int _Prot = 0 // unsupported on Linux, for now
Expand Down Expand Up @@ -956,7 +956,7 @@ class file_buffer
/// <returns>A <c>task</c> that returns an opened stream buffer on completion.</returns>
static pplx::task<streambuf<_CharType>> open(const utility::string_t& file_name,
std::ios_base::openmode mode = std::ios_base::out,
#ifdef _WIN32
#if defined(_WIN32) && !defined(__MINGW32__)
int prot = _SH_DENYRD
#else
int prot = 0 // unsupported on Linux
Expand Down Expand Up @@ -1011,7 +1011,7 @@ class file_stream
/// <returns>A <c>task</c> that returns an opened input stream on completion.</returns>
static pplx::task<streams::basic_istream<_CharType>> open_istream(const utility::string_t& file_name,
std::ios_base::openmode mode = std::ios_base::in,
#ifdef _WIN32
#if defined(_WIN32) && !defined(__MINGW32__)
int prot = (int)std::ios_base::_Openprot
#else
int prot = 0
Expand All @@ -1036,7 +1036,7 @@ class file_stream
/// <returns>A <c>task</c> that returns an opened output stream on completion.</returns>
static pplx::task<streams::basic_ostream<_CharType>> open_ostream(const utility::string_t& file_name,
std::ios_base::openmode mode = std::ios_base::out,
#ifdef _WIN32
#if defined(_WIN32) && !defined(__MINGW32__)
int prot = (int)std::ios_base::_Openprot
#else
int prot = 0
Expand Down
2 changes: 1 addition & 1 deletion Release/include/cpprest/http_msg.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class status_codes
{
public:
#define _PHRASES
#define DAT(a, b, c) const static status_code a = b;
#define DAT(a, b, c) _ASYNCRTIMP const static status_code a = b;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a new dll export of global data on windows, even with msvc. Is that intended? Why do you need to do this?

#include "cpprest/details/http_constants.dat"
#undef _PHRASES
#undef DAT
Expand Down
2 changes: 1 addition & 1 deletion Release/include/cpprest/json.h
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ class value
/// <returns>The parsed object. Returns web::json::value::null if failed</returns>
_ASYNCRTIMP static value __cdecl parse(const utility::string_t& value, std::error_code& errorCode);

#ifdef _WIN32
#if defined(_WIN32)
/// <summary>
/// Parses a string and construct a JSON value.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion Release/include/cpprest/streams.h
Original file line number Diff line number Diff line change
Expand Up @@ -1723,7 +1723,7 @@ class type_parser<CharType, char> : public _type_parser_base<CharType>

#ifdef _WIN32
template<class CharType>
class type_parser<CharType, std::enable_if_t<sizeof(CharType) == 1, std::basic_string<wchar_t>>>
class type_parser<CharType, typename std::enable_if<sizeof(CharType) == 1, std::basic_string<wchar_t>>::type>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks like it's just a hack to support really old libstdc++ and gcc versions that don't have enable_if_t? Is that really needed? Can we just not support ancient GCCs on mingw?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std:: enable_if_t is not available for C++11, but for C++14. In CMakeLists.txt we just requires C++11 and gcc will throw an error here.

: public _type_parser_base<CharType>
{
typedef _type_parser_base<CharType> base;
Expand Down
6 changes: 5 additions & 1 deletion Release/include/pplx/pplx.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#endif
#endif // _WIN32

#ifdef _NO_PPLXIMP
#if defined(_NO_PPLXIMP) || defined(__MINGW32__)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like forcing these on mingw32, we should have strict visibility settings even on GCC.

#define _PPLXIMP
#else
#ifdef _PPLX_EXPORT
Expand All @@ -40,7 +40,11 @@

// Use PPLx
#ifdef _WIN32
#if defined(__MINGW32__)
#include "pplx/pplxlinux.h"
#else
#include "pplx/pplxwin.h"
#endif // defined(__MINGW32__)
#elif defined(__APPLE__)
#undef _PPLXIMP
#define _PPLXIMP
Expand Down
2 changes: 1 addition & 1 deletion Release/include/pplx/pplxinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

#if defined(_CRTBLD)
#elif defined(_WIN32)
#if (_MSC_VER >= 1700)
#if (_MSC_VER >= 1700) || defined(__MINGW32__)
#define _USE_REAL_ATOMICS
#endif
#else // GCC compiler
Expand Down
14 changes: 11 additions & 3 deletions Release/include/pplx/pplxlinux.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@

#pragma once

#if (defined(_MSC_VER))
#if defined(_MSC_VER) && !defined(__MINGW32__)
#error This file must not be included for Visual Studio
#endif

#ifndef _WIN32
#if !defined(__cplusplus_winrt)

#include "cpprest/details/cpprest_compat.h"
#include "pthread.h"
Expand Down Expand Up @@ -259,12 +259,20 @@ namespace details
/// Terminate the process due to unhandled exception
/// </summary>
#ifndef _REPORT_PPLTASK_UNOBSERVED_EXCEPTION
#if defined(__MINGW32__)
#define _REPORT_PPLTASK_UNOBSERVED_EXCEPTION() \
do \
{ \
std::terminate(); \
} while (false)
#else
#define _REPORT_PPLTASK_UNOBSERVED_EXCEPTION() \
do \
{ \
raise(SIGTRAP); \
std::terminate(); \
} while (false)
#endif // defined(__MINGW32__)
#endif //_REPORT_PPLTASK_UNOBSERVED_EXCEPTION
} // namespace details

Expand All @@ -274,4 +282,4 @@ __attribute__((always_inline)) inline void* _ReturnAddress() { return __builtin_

} // namespace pplx

#endif // !_WIN32
#endif // !defined(__cplusplus_winrt)
4 changes: 4 additions & 0 deletions Release/samples/BingRequest/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
if (NOT WINDOWS_STORE AND NOT WINDOWS_PHONE)
add_executable(BingRequest bingrequest.cpp)
target_link_libraries(BingRequest cpprest)

if(MINGW)
target_link_libraries(BingRequest ws2_32 wsock32)
endif()
endif()
13 changes: 9 additions & 4 deletions Release/samples/BingRequest/bingrequest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ using namespace concurrency::streams;
web::http::client::http_client_config client_config_for_proxy()
{
web::http::client::http_client_config client_config;
#ifdef _WIN32
#if defined(_WIN32) && !defined(__MINGW32__)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could just be msc_ver I think

wchar_t* pValue = nullptr;
std::unique_ptr<wchar_t, void (*)(wchar_t*)> holder(nullptr, [](wchar_t* p) { free(p); });
size_t len = 0;
Expand All @@ -37,7 +37,11 @@ web::http::client::http_client_config client_config_for_proxy()
#else
if (const char* env_http_proxy = std::getenv("http_proxy"))
{
#if defined(__MINGW32__)
std::wstring env_http_proxy_string(utility::conversions::to_utf16string(env_http_proxy));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why on earth does only mingw32 need this to be a wstring?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't remember the detail but there seems an error for _wdupenv_s in the _WIN32 codepath, and here std::getenv returns a string, but with mingw the web::web_proxy() requires a wstring.

#else
std::string env_http_proxy_string(env_http_proxy);
#endif
#endif
if (env_http_proxy_string == U("auto"))
client_config.set_proxy(web::web_proxy::use_auto_discovery);
Expand All @@ -48,7 +52,7 @@ web::http::client::http_client_config client_config_for_proxy()
return client_config;
}

#ifdef _WIN32
#if defined(_WIN32) && !defined(__MINGW32__)
int wmain(int argc, wchar_t* args[])
#else
int main(int argc, char* args[])
Expand All @@ -59,8 +63,9 @@ int main(int argc, char* args[])
printf("Usage: BingRequest.exe search_term output_file\n");
return -1;
}
const string_t searchTerm = args[1];
const string_t outputFileName = args[2];

const string_t searchTerm = utility::conversions::to_string_t(args[1]);
const string_t outputFileName = utility::conversions::to_string_t(args[2]);

// Open a stream to the file to write the HTTP response body into.
auto fileBuffer = std::make_shared<streambuf<uint8_t>>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ void PrintTable(const http_response& response, bool& refresh)
// Arguments: BlackJack_Client.exe <port>
// If port is not specified, client will assume that the server is listening on port 34568
//
#ifdef _WIN32
#if defined(_WIN32) && !defined(__MINGW32__)
int wmain(int argc, wchar_t* argv[])
#else
int main(int argc, char* argv[])
Expand Down
4 changes: 4 additions & 0 deletions Release/samples/BlackJack/BlackJack_Client/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ add_executable(blackjackclient
)

target_link_libraries(blackjackclient cpprest)

if(MINGW)
target_link_libraries(blackjackclient ws2_32 wsock32)
endif()
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ void on_shutdown()
// BlackJack_Server.exe <port>
// If port is not specified, will listen on 34568
//
#ifdef _WIN32
#if defined(_WIN32) && !defined(__MINGW32__)
int wmain(int argc, wchar_t* argv[])
#else
int main(int argc, char* argv[])
Expand Down
3 changes: 3 additions & 0 deletions Release/samples/BlackJack/BlackJack_Server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,8 @@ add_executable(blackjackserver
)

target_link_libraries(blackjackserver cpprest)
if(MINGW)
target_link_libraries(blackjackserver ws2_32 wsock32)
endif()

configure_pch(blackjackserver stdafx.h stdafx.cpp /Zm120)
2 changes: 1 addition & 1 deletion Release/samples/BlackJack/BlackJack_Server/Table.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#pragma once
#include "stdafx.h"

#ifdef _WIN32
#if defined(_WIN32) && !defined(__MINGW32__)
#include <concrt.h>
#endif
#include "messagetypes.h"
Expand Down
2 changes: 1 addition & 1 deletion Release/samples/CasaLens/casalens.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ void CasaLens::handle_post(http_request message)
}
}

#ifdef _WIN32
#if defined(_WIN32) && !defined(__MINGW32__)
int wmain(int argc, wchar_t* args[])
#else
int main(int argc, char* args[])
Expand Down
4 changes: 4 additions & 0 deletions Release/samples/Oauth1Client/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,8 @@ if (NOT WINDOWS_STORE AND NOT WINDOWS_PHONE)
)

target_link_libraries(oauth1client cpprest)

if(MINGW)
target_link_libraries(oauth1client ws2_32 wsock32)
endif()
endif()
2 changes: 1 addition & 1 deletion Release/samples/Oauth1Client/Oauth1Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ class twitter_session_sample : public oauth1_session_sample
}
};

#ifdef _WIN32
#if defined(_WIN32) && !defined(__MINGW32__)
int wmain(int argc, wchar_t* argv[])
#else
int main(int argc, char* argv[])
Expand Down
4 changes: 4 additions & 0 deletions Release/samples/Oauth2Client/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,8 @@ if (NOT WINDOWS_STORE AND NOT WINDOWS_PHONE)
)

target_link_libraries(oauth2client cpprest)

if(MINGW)
target_link_libraries(oauth2client ws2_32 wsock32)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all these should probably use the PRIVATE keyword.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, will fix that.

endif()
endif()
2 changes: 1 addition & 1 deletion Release/samples/Oauth2Client/Oauth2Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ class live_session_sample : public oauth2_session_sample
}
};

#ifdef _WIN32
#if defined(_WIN32) && !defined(__MINGW32__)
int wmain(int argc, wchar_t* argv[])
#else
int main(int argc, char* argv[])
Expand Down
Loading