GithubHelp home page GithubHelp logo

Comments (33)

vslashg avatar vslashg commented on August 25, 2024 1

While this doesn't address the struct timeval issue, I'm happy to report that Abseil should no longer call functions named max or min inside header files without wrapping those names in parenthesis to thwart the preprocessor. The vcpkg patch should no longer be necessary.

from abseil-cpp.

zhangxy988 avatar zhangxy988 commented on August 25, 2024

@Remotion "Currently it appears to be impossible to compile Abseil using VS 2017 without errors." Could you please provide details on what specific compiling errors you are getting and how to reproduce the errors?
I just tried running all unit tests with VS 2017 15.3 and it worked fine (except for something related to expression SFINAE with container_test which I don't think is related to windows.h).

from abseil-cpp.

Remotion avatar Remotion commented on August 25, 2024

I did not use Bazel to build, instate I more or less simple dropped files into existing VS2017.4 project and just tried to compile it.

There ware a lot of compiler errors, for example with
#define min
that collided with
std::min

I see now here WIN32_LEAN_AND_MEAN so this probably why there is no problems if build using bazel.

from abseil-cpp.

zhangxy988 avatar zhangxy988 commented on August 25, 2024

So let me rephrase the issue:
Abseil #includes <windows.h> from some files (e.g. clock.cc, waiter.h) where it's conflicting with usage of std::min because <windows.h> #defines min as a macro.
I think the general approach for this kind of issue is to configure the build to predefine WIN32_LEAN_AND_MEAN, just like what we did in our bazel buid file.
Defining WIN32_LEAN_AND_MEAN in code (before each #include <windows.h>) doesn't solve this issue in all cases because it depends on the header inclusion order. For example, <windows.h> could be #included by another non-Abseil header file before any Abseil file is #included (which might not have WIN32_LEAN_AND_MEAN defined).
So I would suggest fixing this issue at the build system level rather than at source code level.

from abseil-cpp.

JonathanDCohen avatar JonathanDCohen commented on August 25, 2024

Friendly ping here :) @Remotion are you still having trouble compiling on Windows?

from abseil-cpp.

zivsha avatar zivsha commented on August 25, 2024

FYI, just cloned abseil to my cmake project (with googletest and cctz with Sarcasm's PR for CMake support) and only issue I'm having is with the usual std::max:

arena->pagesize = std::max(system_info.dwPageSize,
system_info.dwAllocationGranularity);

I did not wish to #define NOMINMAX so I just wrapped it with parentheses like so, and my project compiled (only using absl::base and absl::strings):

    arena->pagesize = (std::max)(system_info.dwPageSize,
                               system_info.dwAllocationGranularity);

from abseil-cpp.

JonathanDCohen avatar JonathanDCohen commented on August 25, 2024

I'm curious about what happens if you try to use, for example, absl/memory/memory.h, which has a numeric_limits<...>::max() call.

We aim to be portable without users modifying code like this, so if the issue is MSVC min and max macros then this seems like an easily solvable problem

from abseil-cpp.

Remotion avatar Remotion commented on August 25, 2024

I am tried abseil from vcpkg and it work in most cases.
But there are still problems with some header files like <time.h>.
It directly includes <winsock2.h>.

Of course the solution for the users is pretty simple ether define NOMINMAX and WIN32_LEAN_AND_MEAN for the whole project or define this just before including <time.h>.

from abseil-cpp.

ras0219-msft avatar ras0219-msft commented on August 25, 2024

I've applied the workaround suggested by @zivsha in vcpkg as a post-build "patch":
https://github.com/Microsoft/vcpkg/blob/3ae740cef8e34ebb447752b3e0c628dc39553315/ports/abseil/portfile.cmake#L30-L36.

@Remotion does that solve the issue for you?

Edit: this only solves the problem for some files; others have calls to Some::Type::max() which also need to be addressed.

Edit: Perhaps a solution based on push_macro and pop_macro around the contents of each header is better? https://docs.microsoft.com/en-us/cpp/preprocessor/push-macro

from abseil-cpp.

rongjiecomputer avatar rongjiecomputer commented on August 25, 2024

I created PR #55 with some other fixes for MSVC (tested with VS 2017 15.3).

Ideally, windows.h should not be used in header files because windows.h is well-known for its namespace/macro polluting issue. Most C++ libraries like libstdc++, libc++ and Boost avoid including windows.h in header file at all cost. Abseil should follow this best practice too.

from abseil-cpp.

zhangxy988 avatar zhangxy988 commented on August 25, 2024

@rongjiecomputer Thanks for the PR. We will look into removing "#include <windows.h>" from header files.

from abseil-cpp.

rongjiecomputer avatar rongjiecomputer commented on August 25, 2024

@zhangxy988 I am willing to help on this one.

My plan is to create a new internal header file (absl/base/internal/windows_types.h?).

In this header file, we will define some of the Windows type like DWORD, SHORT needed by Abseil in internal namespace (absl::base_internal, absl::base_internal::win32?). Access them as absl::base_internal::win32::DWORD etc..

For SRWLOCK and CONDITION_VARIABLE (used in waiter.h), we can declare two structs with exact same member fields but named as ABSL_SRWLOCK, ABSL_CONDITION_VARIABLE, so that user can still include windows.h without conflict. We can reinterpret_cast pointers back to PSRWLOCK and PCONDITION_VARIABLE in source file (Win32 functions only need pointers to SRWLOCK and CONDITION_VARIABLE).

spinlock_win32.inc directly uses Sleep function. One way is to create a absl::base_internal::sleep function and use Sleep to implement this function in source file. Another way is to just declare VOID WINAPI Sleep(DWORD dwMilliseconds) in absl/base/internal/windows_types.h. Both will not cause any inconvenience to the user.

EDIT: I just realized that base/internal/spinlock_win32.inc is only included in base/internal/spinlock_wait.cc, so technically it is a source file rather than header file. No refactoring is needed. 😄

You can see Chrome's implementation of windows_types.h at https://cs.chromium.org/chromium/src/base/win/windows_types.h.

Note:

  • Source file can continue to use windows.h.
  • There is no need to worry about forward declaration of Windows type and functions not working in future versions of Windows SDK. Windows API is one of the most stable API (in terms of API compatibility) in the world. In fact, this is why Microsoft refuses to fix windows.h to avoid breaking old codes.

from abseil-cpp.

rongjiecomputer avatar rongjiecomputer commented on August 25, 2024

@zhangxy988 If that sounds too confusing, I can prepare a PR first and continue the discussion there.

from abseil-cpp.

zhangxy988 avatar zhangxy988 commented on August 25, 2024

@rongjiecomputer : Sorry for the late reply! I lost track of this issue recently.
Thanks for your concrete suggestion. TBH, I don't think I have the technical expertise to make a decision here. I will run this by in our team and will let you know soon. For now, please hold on making a PR (I don't want to waste your time).

from abseil-cpp.

rongjiecomputer avatar rongjiecomputer commented on August 25, 2024

@zhangxy988 I made an edit to my suggestion (see strikethrough and EDIT), in case you already forwarded the old suggestion to your team. I made the mistake because I thought .inc file is the same as .h (header) file.

from abseil-cpp.

rongjiecomputer avatar rongjiecomputer commented on August 25, 2024

@zhangxy988 For the current open-sourced version of Abseil, very few headers that are transitively included in public headers actually need <windows.h>. My suggestion in #34 (comment) isn't needed for now.

After #143 and #144 are merged, <absl/time/time.h> will be the only header that includes <windows.h> (from <winsock2.h>).

I filed a feature request to Microsoft to see if they can move struct timeval out of <winsock2.h>.

https://developercommunity.visualstudio.com/content/problem/291705/move-timeval-struct-out-of-winsock2h.html

from abseil-cpp.

bstaletic avatar bstaletic commented on August 25, 2024

I've been having troubles with Windows.h leaking macros. Specifically max macro caused a compilation error in one place, which I did work around with /DNOMINMAX, but also ERROR gets defined as constant, which actually breaks an enum that is part of the public interface. Granted, I could probably change the enum values because documentation states that only the first letter of the value is important, but it is still breaking public API.

The only place where windows.h is included in a header is in synchronization/internal/waiter.h and as of commit 968a34f it is affecting users of absl::flat_hash_map.

from abseil-cpp.

ojura avatar ojura commented on August 25, 2024

I fixed a similar issue by UNDEFing the offending macro after including Abseil.

from abseil-cpp.

bstaletic avatar bstaletic commented on August 25, 2024

I've tried #undef-ing ERROR right before using my DiagnosticKind::ERROR because that's easier than #undef-ing right after including abseil. The build bots are still running, but it seems to work. Still, it would be nice to not have to work around things like this.

from abseil-cpp.

rongjiecomputer avatar rongjiecomputer commented on August 25, 2024

The only place where windows.h is included in a header is in synchronization/internal/waiter.h and as of commit 968a34f it is affecting users of absl::flat_hash_map.

synchronization/internal/waiter.h is not transitively included by any public header files, so it should not cause any issue to Abseil consumer. I think you are getting windows.h because winsock2.h included by absl/time/time.h (and other header files that include absl/time/time.h) will include windows.h.

from abseil-cpp.

bstaletic avatar bstaletic commented on August 25, 2024

That makes sense. I definitely have absl/time/time.h transitively included and when I tried to trace how waiter.h got included I couldn't figure it out, so it makes sense that it's winsock2.h that's causing me troubles. Still 968a34f is the commit hash where the problem got introduced.

For the record, #undef-ing ERROR did work.

from abseil-cpp.

bstaletic avatar bstaletic commented on August 25, 2024

Is there a reason that I'm missing for including winsock2.h in time.h? The only thing in that header that is also guarded by _MSC_VER is:

  // Copyable.
#if !defined(__clang__) && defined(_MSC_VER) && _MSC_VER < 1910
  // Explicitly defining the constexpr copy constructor avoids an MSVC bug.
  constexpr Duration(const Duration& d)
      : rep_hi_(d.rep_hi_), rep_lo_(d.rep_lo_) {}
#else
  constexpr Duration(const Duration& d) = default;
#endif

And nothing in that snippet depends on windows API.

from abseil-cpp.

rongjiecomputer avatar rongjiecomputer commented on August 25, 2024

absl/time/time.h needs the definition of struct timeval. Most OS put the definition in sys/time.h, but Microsoft put it in winsock2.h.

I filed https://developercommunity.visualstudio.com/content/problem/291705/move-timeval-struct-out-of-winsock2h.html awhile ago, MSVC team said they forwarded the request to Windows SDK team, but no update since then.

from abseil-cpp.

bstaletic avatar bstaletic commented on August 25, 2024

MSVC team said they forwarded the request to Windows SDK team, but no update since then.

That sounds familiar, but I won't rant about MSVC now.

How about creating a wrapper for struct timeval, so that sys/time.h and winsock2.h can be "hidden" in the absl/time/time.cc? Granted, pImpl idiom does introduce an extra indirection and a function call and thus a theoretical performance hit.

from abseil-cpp.

rongjiecomputer avatar rongjiecomputer commented on August 25, 2024

How about creating a wrapper for struct timeval, so that sys/time.h and winsock2.h can be "hidden" in the absl/time/time.cc? Granted, pImpl idiom does introduce an extra indirection and a function call and thus a theoretical performance hit.

That would be an API breaking change as timeval is part of function signature of public APIs. Those functions are probably used by many people now, I doubt Abseil team will consider breaking API for MSVC.

Duration DurationFromTimespec(timespec ts);
Duration DurationFromTimeval(timeval tv);
timespec ToTimespec(Duration d);
timeval ToTimeval(Duration d);
Time TimeFromTimespec(timespec ts);
Time TimeFromTimeval(timeval tv);
timespec ToTimespec(Time t);
timeval ToTimeval(Time t);

from abseil-cpp.

bstaletic avatar bstaletic commented on August 25, 2024

Right, didn't think about that. Nevermind that idea, I guess I'll have to deal with /DNOMINMAX and #undef ERROR.

from abseil-cpp.

Wartortle avatar Wartortle commented on August 25, 2024

Adding more to this. There's no direct requirement I can see other than the declaration of timeval and pulling in Winsock2.h (or Windows.h) into this drags in a whole heap of other nastiness like min/max macros and heaven knows what else.

Whilst it's not considered a valid change, perhaps something like this instead that allows some degree of coexistence within a code base that needs to control Windows.h inclusion in a better way.

Replace:
#include <winsock2.h>

With:
#ifndef WINSOCKAPI
struct timeval {
long tv_sec; /* seconds /
long tv_usec; /
and microseconds */
};
#endif

from abseil-cpp.

rongjiecomputer avatar rongjiecomputer commented on August 25, 2024

That fix will prevent user from including winsock2.h after including Abseil's header files. This will probably break some existing code.

from abseil-cpp.

Wartortle avatar Wartortle commented on August 25, 2024

Yeah, well, including Winsock2.h breaks a number of things for our code and the solution from here on in can be addressed entirely in client code by including Windows or Winsock before Abseil so IMHO that's a better compromise.

Admittedly, it's rubbish either way but them's the cards we've got, I suppose.

from abseil-cpp.

EricWF avatar EricWF commented on August 25, 2024

There are changes upcoming that remove the winsock2.h includes. This will require users on Windows to include the header themselves if they want to use parts of absl/time/time.h, but it will prevent the inclusion of windows.h by default.

from abseil-cpp.

Wartortle avatar Wartortle commented on August 25, 2024

Excellent, thanks @EricWF !

from abseil-cpp.

rongjiecomputer avatar rongjiecomputer commented on August 25, 2024

@EricWF Your change at https://github.com/abseil/abseil-cpp/blob/master/absl/time/time.h#L68 is brilliant! I don't need to include winsock2.h as long as I don't use timeval related Abseil functions (a), and when I need it, including winsock2.h before or after absl/time/time.h are both OK.

Why forward declaration is enough to compile in (a) when timeval is used as return type and parameter in those Abseil functions?

from abseil-cpp.

EricWF avatar EricWF commented on August 25, 2024

I was a bit concerned using a forward declaration as well. I thought the incomplete type might break overload resolution whenever it participated, but that's not the case.

The compiler doesn't care about the completeness of the return type until you attempt to actually use the function.

It's similar for the parameter type when passed by value. The compiler will effectively ignore the overload taking an incomplete type while it's incomplete -- unless you pass it an argument of the exact same type.

In short, it works... thankfully.

I'm going to close this issue as resolved. Woo!

from abseil-cpp.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.