Comments (33)
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.
@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.
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.
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.
Friendly ping here :) @Remotion are you still having trouble compiling on Windows?
from abseil-cpp.
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
:
abseil-cpp/absl/base/internal/low_level_alloc.cc
Lines 290 to 291 in 9850abf
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.
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.
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.
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.
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.
@rongjiecomputer Thanks for the PR. We will look into removing "#include <windows.h>" from header files.
from abseil-cpp.
@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.
@zhangxy988 If that sounds too confusing, I can prepare a PR first and continue the discussion there.
from abseil-cpp.
@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.
@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.
@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>
.
from abseil-cpp.
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.
I fixed a similar issue by UNDEFing the offending macro after including Abseil.
from abseil-cpp.
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.
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.
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.
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.
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.
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.
How about creating a wrapper for
struct timeval
, so thatsys/time.h
andwinsock2.h
can be "hidden" in theabsl/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.
Right, didn't think about that. Nevermind that idea, I guess I'll have to deal with /DNOMINMAX
and #undef ERROR
.
from abseil-cpp.
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.
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.
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.
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.
Excellent, thanks @EricWF !
from abseil-cpp.
@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.
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)
- [Bug]: NegativeNaN test fails on riscv64 HOT 2
- [Bug]: Rounding absl::Time is hacky HOT 4
- [Bug]: btree_multiset memory leak with ASAN enabled HOT 6
- [Bug]: Uninitialized value in AnyInvocable.
- [Bug]: Build failure MSVC x86 with /arch:AVX2 HOT 4
- [Bug]: ABSL_ATTRIBUTE_NORETURN doesn't work in all contexts HOT 1
- [Bug]: Compilation issue on Windows 2022 with Ninja and CMake
- [Bug]: Can't link using riscv64 toolchain
- use vcpkg install absl dll lib link error HOT 1
- [Bug]: Sanitizer options may disagree between library and user leading to ODR violations
- Can't link to MSVC built abseil with clang/LLVM
- improvement : keep cmakelists clean, remove unneeded policy activations that are already active HOT 2
- [Bug]: container test_allocator should be skipped if testing is disabled HOT 3
- [Bug]: Build error during cmake quick start HOT 1
- [Bug]: 20240722.rc1 can not be built for android ndk r25b / r25c HOT 3
- [Bug]: Can't build C++20 project without .bazelrc HOT 2
- [Bug]: absl::Log Initialization in DLL Fails When Called Using ctypes on Windows
- [Bug]: Flag "-Wnon-virtual-dtor" is added to pkg-config files
- [Bug]: error while loading shared libraries: libabsl_cord_internal.so.2401.0.0: cannot open shared object file: No such file or directory
- [Bug]: asan failure in absl::Status::ToString() HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from abseil-cpp.