diff --git a/CMakeLists.txt b/CMakeLists.txt
index a67a325ad0ff34b2c3241c63d8d7ffaf5dfd2dcc..770c284fb9242a202e1c68da090c5c03cda0adc2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -29,9 +29,14 @@ version_numbers (
 option (BUILD_SHARED_LIBS "Request build of shared libraries." OFF)
 set (GFLAGS_SHARED_LIBS ${BUILD_SHARED_LIBS})
 
+option (BUILD_NEGATIVE_COMPILATION_TESTS "Request addition of negative compilation tests." OFF)
+mark_as_advanced(BUILD_NEGATIVE_COMPILATION_TESTS)
+
 set (GFLAGS_NAMESPACE "gflags" CACHE STRING "C++ namespace identifier of gflags library.")
 mark_as_advanced (GFLAGS_NAMESPACE)
 
+mark_as_advanced (CLEAR CMAKE_INSTALL_PREFIX)
+mark_as_advanced (CMAKE_CONFIGURATION_TYPES)
 if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CXX_FLAGS AND NOT CMAKE_C_FLAGS)
   set (
     CMAKE_BUILD_TYPE "Release"
@@ -121,7 +126,7 @@ else ()
   set (__ATTRIBUTE__UNUSED)
 endif ()
 
-configure_sources (PUBLIC_HDRS  ${PUBLIC_HDRS})
+configure_headers (PUBLIC_HDRS  ${PUBLIC_HDRS})
 configure_sources (PRIVATE_HDRS ${PRIVATE_HDRS})
 configure_sources (GFLAGS_SRCS  ${GFLAGS_SRCS})
 
@@ -133,16 +138,19 @@ set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY "lib")
 
 # ----------------------------------------------------------------------------
 # add library target
-if (WIN32 AND BUILD_SHARED_LIBS)
-  add_definitions (-DGFLAGS_DLL_EXPORT)
-endif ()
 include_directories ("${PROJECT_SOURCE_DIR}/src")
 include_directories ("${PROJECT_BINARY_DIR}/include")
 include_directories ("${PROJECT_BINARY_DIR}/include/${GFLAGS_NAMESPACE}")
 
 add_library (gflags           ${GFLAGS_SRCS} ${PRIVATE_HDRS} ${PUBLIC_HDRS})
 add_library (gflags_nothreads ${GFLAGS_SRCS} ${PRIVATE_HDRS} ${PUBLIC_HDRS})
-set_target_properties (gflags_nothreads PROPERTIES COMPILE_DEFINITIONS NO_THREADS)
+
+if (WIN32 AND BUILD_SHARED_LIBS)
+  set_target_properties (gflags           PROPERTIES COMPILE_DEFINITIONS GFLAGS_DLL_EXPORT)
+  set_target_properties (gflags_nothreads PROPERTIES COMPILE_DEFINITIONS "GFLAGS_DLL_EXPORT;NO_THREADS")
+else ()
+  set_target_properties (gflags_nothreads PROPERTIES COMPILE_DEFINITIONS NO_THREADS)
+endif ()
 
 # ----------------------------------------------------------------------------
 # installation
@@ -191,14 +199,8 @@ configure_file (cmake/config.cmake.in "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-con
 
 # ----------------------------------------------------------------------------
 # testing - MUST follow the generation of the build tree config file
-
-# TODO(andreas) Replace Bash scripts such that tests can be run on Windows (e.g., Python).
-#               The gflags_unittest.sh script should best be replaced by multiple
-#               add_test commands in the test/CMakeLists.txt file.
-if (UNIX)
-  include (CTest)
-  if (BUILD_TESTING)
-    enable_testing ()
-    add_subdirectory (test)
-  endif ()
-endif ()
+include (CTest)
+if (BUILD_TESTING)
+  enable_testing ()
+  add_subdirectory (test)
+endif ()
\ No newline at end of file
diff --git a/cmake/utils.cmake b/cmake/utils.cmake
index 717a5086145ece606cf0af940b6db3b5ed66e084..bb6cb1845208e22907bdc01ee184697c04de92be 100644
--- a/cmake/utils.cmake
+++ b/cmake/utils.cmake
@@ -31,6 +31,22 @@ function (version_numbers VERSION MAJOR MINOR PATCH)
   set ("${PATCH}" "${VERSION_PATCH}" PARENT_SCOPE)
 endfunction ()
 
+# ----------------------------------------------------------------------------
+## Configure public header files
+function (configure_headers out)
+  set (tmp)
+  foreach (src IN LISTS ARGN)
+    if (EXISTS "${PROJECT_SOURCE_DIR}/src/${src}.in")
+      configure_file ("${PROJECT_SOURCE_DIR}/src/${src}.in" "${PROJECT_BINARY_DIR}/include/${GFLAGS_NAMESPACE}/${src}" @ONLY)
+      list (APPEND tmp "${PROJECT_BINARY_DIR}/include/${GFLAGS_NAMESPACE}/${src}")
+    else ()
+	    configure_file ("${PROJECT_SOURCE_DIR}/src/${src}" "${PROJECT_BINARY_DIR}/include/${GFLAGS_NAMESPACE}/${src}" COPYONLY)
+      list (APPEND tmp "${PROJECT_BINARY_DIR}/include/${GFLAGS_NAMESPACE}/${src}")
+    endif ()
+  endforeach ()
+  set (${out} "${tmp}" PARENT_SCOPE)
+endfunction ()
+
 # ----------------------------------------------------------------------------
 ## Configure source files with .in suffix
 function (configure_sources out)
@@ -45,3 +61,22 @@ function (configure_sources out)
   endforeach ()
   set (${out} "${tmp}" PARENT_SCOPE)
 endfunction ()
+
+# ----------------------------------------------------------------------------
+## Add usage test
+#
+# Using PASS_REGULAR_EXPRESSION and FAIL_REGULAR_EXPRESSION would
+# do as well, but CMake/CTest does not allow us to specify an
+# expected exist status. Moreover, the execute_test.cmake script
+# sets environment variables needed by the --fromenv/--tryfromenv tests.
+macro (add_gflags_test name expected_rc expected_output unexpected_output cmd)
+  add_test (
+    NAME    ${name}
+    COMMAND "${CMAKE_COMMAND}" "-DCOMMAND:STRING=$<TARGET_FILE:${cmd}>;${ARGN}"
+                               "-DEXPECTED_RC:STRING=${expected_rc}"
+                               "-DEXPECTED_OUTPUT:STRING=${expected_output}"
+                               "-DUNEXPECTED_OUTPUT:STRING=${unexpected_output}"
+                               -P "${PROJECT_SOURCE_DIR}/test/execute_test.cmake"
+    WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/test"
+  )
+endmacro ()
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index bc16eba4ce1614ed85de9eed43c971d93fb0aba4..73099be3a061fac9d8cc42e6f8e5865b146920be 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,7 +1,5 @@
 ## gflags tests
 
-find_package (PythonInterp)
-
 # ----------------------------------------------------------------------------
 # output directories
 set (CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/Testing/bin")
@@ -16,47 +14,153 @@ include_directories ("${CMAKE_CURRENT_SOURCE_DIR}")
 link_libraries (gflags_nothreads)
 
 # ----------------------------------------------------------------------------
-# test executables
+# STRIP_FLAG_HELP: check with "strings" that help text is not in binary
+if (UNIX)
+  add_executable (strip_flags gflags_strip_flags_test.cc)
+  add_test (
+    NAME    strip_flags
+    COMMAND /bin/bash "${CMAKE_CURRENT_SOURCE_DIR}/gflags_strip_flags_test.sh"
+            "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/strip_flags"
+  )
+endif ()
+
+# ----------------------------------------------------------------------------
+# unit tests
 configure_file (gflags_unittest.cc gflags_unittest-main.cc COPYONLY)
 configure_file (gflags_unittest.cc gflags_unittest_main.cc COPYONLY)
 
-set (SRCDIR "${CMAKE_CURRENT_SOURCE_DIR}/nc")
-configure_file (gflags_nc.py.in "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nc.py" @ONLY)
+add_executable (unittest  gflags_unittest.cc)
+add_executable (unittest2 gflags_unittest-main.cc)
+add_executable (unittest3 gflags_unittest_main.cc)
+
+# First, just make sure the unittest works as-is
+add_gflags_test(unittest 0 "" "" unittest)
+
+# --help should show all flags, including flags from gflags_reporting
+add_gflags_test(help-reporting 1 "gflags_reporting.cc" "" unittest --help)
+
+# Make sure that --help prints even very long helpstrings.
+add_gflags_test(long-helpstring 1 "end of a long helpstring" "" unittest --help)
+
+# Make sure --help reflects flag changes made before flag-parsing
+add_gflags_test(changed_bool1 1 "-changed_bool1 (changed) type: bool default: true" "" unittest --help)
+add_gflags_test(changed_bool2 1 "-changed_bool2 (changed) type: bool default: false currently: true" "" unittest --help)
+# And on the command-line, too
+add_gflags_test(changeable_string_var 1 "-changeable_string_var () type: string default: \"1\" currently: \"2\"" "" unittest --changeable_string_var 2 --help)
+
+# --nohelp and --help=false should be as if we didn't say anything
+add_gflags_test(nohelp     0 "PASS" "" unittest --nohelp)
+add_gflags_test(help=false 0 "PASS" "" unittest --help=false)
+
+# --helpfull is the same as help
+add_gflags_test(helpfull 1 "gflags_reporting.cc" "" unittest --helpfull)
+
+# --helpshort should show only flags from the unittest itself
+add_gflags_test(helpshort 1 "gflags_unittest.cc" "gflags_reporting.cc" unittest --helpshort)
+
+# --helpshort should show the tldflag we created in the unittest dir
+add_gflags_test(helpshort-tldflag1 1 "tldflag1" "google.cc" unittest --helpshort)
+add_gflags_test(helpshort-tldflag2 1 "tldflag2" "google.cc" unittest --helpshort)
+
+# --helpshort should work if the main source file is suffixed with [_-]main
+add_gflags_test(helpshort-main 1 "gflags_unittest-main.cc" "gflags_reporting.cc" unittest2 --helpshort)
+add_gflags_test(helpshort_main 1 "gflags_unittest_main.cc" "gflags_reporting.cc" unittest3 --helpshort)
+
+# --helpon needs an argument
+add_gflags_test(helpon 1 "'--helpon' is missing its argument; flag description: show help on" "" unittest --helpon)
+
+if (BUILD_SHARED_LIBS)
+  # --helpon argument indicates what file we'll show args from
+  # TODO(andreas): This test fails. Why is there no help for the gflags module ?
+  add_gflags_test(helpon=gflags 1 "gflags.cc" "gflags_unittest.cc" unittest --helpon=gflags)
+  # another way of specifying the argument
+  # TODO(andreas): This test fails. Why is there no help for the gflags module ?
+  add_gflags_test(helpon_gflags 1 "gflags.cc" "gflags_unittest.cc" unittest --helpon gflags)
+endif ()
 
-add_executable (strip_flags gflags_strip_flags_test.cc)
-add_executable (unittest    gflags_unittest.cc)
-add_executable (unittest2   gflags_unittest-main.cc)
-add_executable (unittest3   gflags_unittest_main.cc)
+# test another argument
+add_gflags_test(helpon=gflags_unittest 1 "gflags_unittest.cc" "gflags.cc" unittest --helpon=gflags_unittest)
+
+# helpmatch is like helpon but takes substrings
+add_gflags_test(helpmatch_reporting 1 "gflags_reporting.cc" "gflags_unittest.cc" unittest -helpmatch reporting)
+add_gflags_test(helpmatch=unittest  1 "gflags_unittest.cc" "gflags.cc:" unittest -helpmatch=unittest)
+
+# if no flags are found with helpmatch or helpon, suggest --help
+add_gflags_test(helpmatch=nosuchsubstring 1 "No modules matched" "gflags_unittest.cc" unittest -helpmatch=nosuchsubstring)
+add_gflags_test(helpon=nosuchmodule       1 "No modules matched" "gflags_unittest.cc" unittest -helpon=nosuchmodule)
+
+# helppackage shows all the flags in the same dir as this unittest
+# --help should show all flags, including flags from google.cc
+add_gflags_test(helppackage 1 "gflags_reporting.cc" "" unittest --helppackage)
+
+# xml!
+add_gflags_test(helpxml 1 "gflags_unittest.cc</file>" "gflags_unittest.cc:" unittest --helpxml)
+
+# just print the version info and exit
+add_gflags_test(version-1 0 "gflags_unittest"      "gflags_unittest.cc" unittest --version)
+add_gflags_test(version-2 0 "version test_version" "gflags_unittest.cc" unittest --version)
+
+# --undefok is a fun flag...
+add_gflags_test(undefok-1 1 "unknown command line flag 'foo'" "" unittest --undefok= --foo --unused_bool)
+add_gflags_test(undefok-2 0 "PASS" "" unittest --undefok=foo --foo --unused_bool)
+# If you say foo is ok to be undefined, we'll accept --nofoo as well
+add_gflags_test(undefok-3 0 "PASS" "" unittest --undefok=foo --nofoo --unused_bool)
+# It's ok if the foo is in the middle
+add_gflags_test(undefok-4 0 "PASS" "" unittest --undefok=fee,fi,foo,fum --foo --unused_bool)
+# But the spelling has to be just right...
+add_gflags_test(undefok-5 1 "unknown command line flag 'foo'" "" unittest --undefok=fo --foo --unused_bool)
+add_gflags_test(undefok-6 1 "unknown command line flag 'foo'" "" unittest --undefok=foot --foo --unused_bool)
+
+# See if we can successfully load our flags from the flagfile
+add_gflags_test(flagfile.1 0 "gflags_unittest" "gflags_unittest.cc" unittest "--flagfile=${CMAKE_CURRENT_LIST_DIR}/flagfile.1")
+add_gflags_test(flagfile.2 0 "PASS" "" unittest "--flagfile=${CMAKE_CURRENT_LIST_DIR}/flagfile.2")
+add_gflags_test(flagfile.3 0 "PASS" "" unittest "--flagfile=${CMAKE_CURRENT_LIST_DIR}/flagfile.3")
+
+# Also try to load flags from the environment
+add_gflags_test(fromenv=version      0 "gflags_unittest" "gflags_unittest.cc" unittest --fromenv=version)
+add_gflags_test(tryfromenv=version   0 "gflags_unittest" "gflags_unittest.cc" unittest --tryfromenv=version)
+add_gflags_test(fromenv=help         0 "PASS" "" unittest --fromenv=help)
+add_gflags_test(tryfromenv=help      0 "PASS" "" unittest --tryfromenv=help)
+add_gflags_test(fromenv=helpfull     1 "helpfull not found in environment" "" unittest --fromenv=helpfull)
+add_gflags_test(tryfromenv=helpfull  0 "PASS" "" unittest --tryfromenv=helpfull)
+add_gflags_test(tryfromenv=undefok   0 "PASS" "" unittest --tryfromenv=undefok --foo)
+add_gflags_test(tryfromenv=weirdo    1 "unknown command line flag" "" unittest --tryfromenv=weirdo)
+add_gflags_test(tryfromenv-multiple  0 "gflags_unittest" "gflags_unittest.cc" unittest --tryfromenv=test_bool,version,unused_bool)
+add_gflags_test(fromenv=test_bool    1 "not found in environment" "" unittest --fromenv=test_bool)
+add_gflags_test(fromenv=test_bool-ok 1 "unknown command line flag" "" unittest --fromenv=test_bool,ok)
+# Here, the --version overrides the fromenv
+add_gflags_test(version-overrides-fromenv 0 "gflags_unittest" "gflags_unittest.cc" unittest --fromenv=test_bool,version,ok)
+
+# Make sure -- by itself stops argv processing
+add_gflags_test(dashdash 0 "PASS" "" unittest -- --help)
+
+# And we should die if the flag value doesn't pass the validator
+add_gflags_test(always_fail 1 "ERROR: failed validation of new value 'true' for flag 'always_fail'" "" unittest --always_fail)
+
+# And if locking in validators fails
+# TODO(andreas): Worked on Windows 7 Release configuration, but causes
+#                debugger abort() intervention in case of Debug configuration.
+#add_gflags_test(deadlock_if_cant_lock 0 "PASS" "" unittest --deadlock_if_cant_lock)
 
 # ----------------------------------------------------------------------------
 # (negative) compilation tests
-if (PYTHON_EXECUTABLE)
+if (BUILD_NEGATIVE_COMPILATION_TESTS)
+  find_package (PythonInterp)
+  if (NOT PYTHON_EXECUTABLE)
+    message (FATAL_ERROR "No Python installation found! It is required by the negative compilation tests."
+                         " Either install Python or set NEGATIVE_COMPILATION_TESTS to FALSE and try again.")
+  endif ()
+  set (SRCDIR "${CMAKE_CURRENT_SOURCE_DIR}/nc")
+  configure_file (gflags_nc.py.in "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nc.py" @ONLY)
   macro (add_nc_test name)
     add_test (
       NAME nc_${name}
       COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nc.py" ${name}
     )
   endmacro ()
-
   add_nc_test (sanity)
   add_nc_test (swapped_args)
   add_nc_test (int_instead_of_bool)
   add_nc_test (bool_in_quotes)
   add_nc_test (define_string_with_0)
-endif ()
-
-# ----------------------------------------------------------------------------
-# test commands
-add_test (
-  NAME    strip_flags
-  COMMAND /bin/bash "${CMAKE_CURRENT_SOURCE_DIR}/gflags_strip_flags_test.sh"
-          "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/strip_flags"
-)
-
-add_test (
-  NAME    unittest
-  COMMAND /bin/bash "${CMAKE_CURRENT_SOURCE_DIR}/gflags_unittest.sh"
-          "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest"
-          "${CMAKE_CURRENT_SOURCE_DIR}" # <srcdir>
-          "${TEMPDIR}/unittest"         # <tempdir>
-)
+endif ()
\ No newline at end of file
diff --git a/test/flagfile.1 b/test/flagfile.1
new file mode 100644
index 0000000000000000000000000000000000000000..e0f921769cf029b30f9f7efc85267cf7adf07e56
--- /dev/null
+++ b/test/flagfile.1
@@ -0,0 +1 @@
+--version
\ No newline at end of file
diff --git a/test/flagfile.2 b/test/flagfile.2
new file mode 100644
index 0000000000000000000000000000000000000000..864f8e8a138552a95e00b8e4d9af9268347993ed
--- /dev/null
+++ b/test/flagfile.2
@@ -0,0 +1,2 @@
+--foo=bar
+--nounused_bool
\ No newline at end of file
diff --git a/test/flagfile.3 b/test/flagfile.3
new file mode 100644
index 0000000000000000000000000000000000000000..76d92bb1e0fc77fa547420dc49f7636f936e0122
--- /dev/null
+++ b/test/flagfile.3
@@ -0,0 +1 @@
+--flagfile=flagfile.2
\ No newline at end of file
diff --git a/test/gflags_unittest.cc b/test/gflags_unittest.cc
index 4edf3df0dc0707e8cf0e0bfa93f654d901ff4ed7..a2a033a83d37f5ca30bcfe5f9aeaa3d31fa4c702 100644
--- a/test/gflags_unittest.cc
+++ b/test/gflags_unittest.cc
@@ -39,8 +39,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
+#if HAVE_UNISTD_H
+#  include <unistd.h>
 #endif     // for unlink()
 #include <vector>
 #include <string>
@@ -414,7 +414,7 @@ TEST(FlagFileTest, FilenamesOurfileFirst) {
       -1.0);
 }
 
-#ifdef HAVE_FNMATCH_H  // otherwise glob isn't supported
+#if HAVE_FNMATCH_H  // otherwise glob isn't supported
 TEST(FlagFileTest, FilenamesOurfileGlob) {
   FLAGS_test_string = "initial";
   FLAGS_test_bool = false;
@@ -1493,6 +1493,11 @@ TEST(FlagsValidator, FlagSaver) {
 }  // unnamed namespace
 
 int main(int argc, char **argv) {
+
+  // Run unit tests only if called without arguments, otherwise this program
+  // is used by an "external" usage test
+  const bool run_tests = (argc == 1);
+
   // We need to call SetArgv before parsing flags, so our "test" argv will
   // win out over this executable's real argv.  That makes running this
   // test with a real --help flag kinda annoying, unfortunately.
@@ -1521,7 +1526,11 @@ int main(int argc, char **argv) {
   ParseCommandLineFlags(&argc, &argv, true);
   MakeTmpdir(&FLAGS_test_tmpdir);
 
-  const int exit_status = RUN_ALL_TESTS();
+  int exit_status = 0;
+  if (run_tests) {
+	  fprintf(stdout, "Running the unit tests now...\n\n"); fflush(stdout);
+	  exit_status = RUN_ALL_TESTS();
+  } else fprintf(stderr, "\n\nPASS\n");
   ShutDownCommandLineFlags();
   return exit_status;
 }