Make generate_export_header.bzl work for Windows. (#1355)

* Make generate_export_header.bzl work for Windows.

While I'm here, bring the generated code slightly closer to what CMake
would generate nowadays.

Fixes #1351.

* Fix define.

* Fix export_import_condition.

* Fix guard.
diff --git a/BUILD.bazel b/BUILD.bazel
index dce4d64..4bf5bfc 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -55,6 +55,10 @@
         ":windows": [],
         "//conditions:default": posix_copts,
     }),
+    local_defines = select({
+        ":windows": ["benchmark_EXPORTS"],
+        "//conditions:default": [],
+    }),
 )
 
 cc_library(
diff --git a/WORKSPACE b/WORKSPACE
index 949eb98..bb44e7b 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -4,6 +4,15 @@
 load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
 
 http_archive(
+    name = "platforms",
+    sha256 = "379113459b0feaf6bfbb584a91874c065078aa673222846ac765f86661c27407",
+    urls = [
+        "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.5/platforms-0.0.5.tar.gz",
+        "https://github.com/bazelbuild/platforms/releases/download/0.0.5/platforms-0.0.5.tar.gz",
+    ],
+)
+
+http_archive(
     name = "com_google_absl",
     sha256 = "f41868f7a938605c92936230081175d1eae87f6ea2c248f41077c8f88316f111",
     strip_prefix = "abseil-cpp-20200225.2",
diff --git a/config/generate_export_header.bzl b/config/generate_export_header.bzl
index 0d0b671..35e9871 100644
--- a/config/generate_export_header.bzl
+++ b/config/generate_export_header.bzl
@@ -36,33 +36,44 @@
 #
 # -*- python -*-
 
-def _make_identifier(s):
-    result = ""
-    for i in range(len(s)):
-        result += s[i] if s[i].isalnum() else "_"
-
-    return result
-
 # Defines the implementation actions to generate_export_header.
 def _generate_export_header_impl(ctx):
+    windows_constraint = ctx.attr._windows_constraint[platform_common.ConstraintValueInfo]
     output = ctx.outputs.out
 
-    guard = _make_identifier(output.basename.upper())
+    if ctx.target_platform_has_constraint(windows_constraint):
+      export_attr = "__declspec(dllexport)"
+      import_attr = "__declspec(dllimport)"
+      no_export_attr = ""
+      deprecated_attr = "__declspec(deprecated)"
+    else:
+      export_attr = "__attribute__((visibility(\"default\")))"
+      import_attr = "__attribute__((visibility(\"default\")))"
+      no_export_attr = "__attribute__((visibility(\"hidden\")))"
+      deprecated_attr = "__attribute__((__deprecated__))"
 
     content = [
-        "#ifndef %s" % guard,
-        "#define %s" % guard,
+        "#ifndef %s_H" % ctx.attr.export_macro_name,
+        "#define %s_H" % ctx.attr.export_macro_name,
         "",
         "#ifdef %s" % ctx.attr.static_define,
         "#  define %s" % ctx.attr.export_macro_name,
         "#  define %s" % ctx.attr.no_export_macro_name,
         "#else",
-        "#  define %s __attribute__((visibility(\"default\")))" % ctx.attr.export_macro_name,  # noqa
-        "#  define %s __attribute__((visibility(\"hidden\")))" % ctx.attr.no_export_macro_name,  # noqa
+        "#  ifndef %s" % ctx.attr.export_macro_name,
+        "#    ifdef %s" % ctx.attr.export_import_condition,
+        "#      define %s %s" % (ctx.attr.export_macro_name, export_attr),
+        "#    else",
+        "#      define %s %s" % (ctx.attr.export_macro_name, import_attr),
+        "#    endif",
+        "#  endif",
+        "#  ifndef %s" % ctx.attr.no_export_macro_name,
+        "#    define %s %s" % (ctx.attr.no_export_macro_name, no_export_attr),
+        "#  endif",
         "#endif",
         "",
         "#ifndef %s" % ctx.attr.deprecated_macro_name,
-        "#  define %s __attribute__ ((__deprecated__))" % ctx.attr.deprecated_macro_name,  # noqa
+        "#  define %s %s" % (ctx.attr.deprecated_macro_name, deprecated_attr),
         "#endif",
         "",
         "#ifndef %s" % ctx.attr.export_deprecated_macro_name,
@@ -82,12 +93,14 @@
 _generate_export_header_gen = rule(
     attrs = {
         "out": attr.output(mandatory = True),
+        "export_import_condition": attr.string(),
         "export_macro_name": attr.string(),
         "deprecated_macro_name": attr.string(),
         "export_deprecated_macro_name": attr.string(),
         "no_export_macro_name": attr.string(),
         "no_export_deprecated_macro_name": attr.string(),
         "static_define": attr.string(),
+        "_windows_constraint": attr.label(default = "@platforms//os:windows"),
     },
     output_to_genfiles = True,
     implementation = _generate_export_header_impl,
@@ -97,6 +110,7 @@
         lib = None,
         name = None,
         out = None,
+        export_import_condition = None,
         export_macro_name = None,
         deprecated_macro_name = None,
         export_deprecated_macro_name = None,
@@ -121,6 +135,9 @@
         name = "__%s_export_h" % lib
     if out == None:
         out = "%s_export.h" % lib
+    if export_import_condition == None:
+        # CMake does not uppercase the <lib>_EXPORTS define.
+        export_import_condition = "%s_EXPORTS" % lib
     if export_macro_name == None:
         export_macro_name = "%s_EXPORT" % lib.upper()
     if deprecated_macro_name == None:
@@ -138,6 +155,7 @@
     _generate_export_header_gen(
         name = name,
         out = out,
+        export_import_condition = export_import_condition,
         export_macro_name = export_macro_name,
         deprecated_macro_name = deprecated_macro_name,
         export_deprecated_macro_name = export_deprecated_macro_name,