Commit 688ea02a authored by Craig Silverstein's avatar Craig Silverstein

Thu Sep 10 12:53:04 2009 Google Inc. <opensource@google.com>

	* google-gflags: version 1.2
	* PORTABILITY: can now build and run tests under mingw (csilvers)
	* Using a string arg for a bool flag is a compile-time error (rbayardo)
	* Add --helpxml to gflags.py (salcianu)
	* Protect against a hypothetical global d'tor mutex problem (csilvers)
	* BUGFIX: can now define a flag after 'using namespace google' (hamaji)


git-svn-id: https://gflags.googlecode.com/svn/trunk@32 6586e3c6-dcc4-952a-343f-ff74eb82781d
parent de718176
Thu Sep 10 12:53:04 2009 Google Inc. <opensource@google.com>
* google-gflags: version 1.2
* PORTABILITY: can now build and run tests under mingw (csilvers)
* Using a string arg for a bool flag is a compile-time error (rbayardo)
* Add --helpxml to gflags.py (salcianu)
* Protect against a hypothetical global d'tor mutex problem (csilvers)
* BUGFIX: can now define a flag after 'using namespace google' (hamaji)
Tue Apr 14 12:35:25 2009 Google Inc. <opensource@google.com> Tue Apr 14 12:35:25 2009 Google Inc. <opensource@google.com>
* google-gflags: version 1.1 * google-gflags: version 1.1
......
...@@ -67,7 +67,7 @@ lib_LTLIBRARIES += libgflags_nothreads.la ...@@ -67,7 +67,7 @@ lib_LTLIBRARIES += libgflags_nothreads.la
libgflags_nothreads_la_SOURCES = $(GFLAGS_SOURCES) libgflags_nothreads_la_SOURCES = $(GFLAGS_SOURCES)
libgflags_nothreads_la_CXXFLAGS = -DNDEBUG -DNO_THREADS libgflags_nothreads_la_CXXFLAGS = -DNDEBUG -DNO_THREADS
TESTS += gflags_unittest$(EXEEXT) TESTS += gflags_unittest
gflags_unittest_SOURCES = $(gflagsinclude_HEADERS) src/config.h \ gflags_unittest_SOURCES = $(gflagsinclude_HEADERS) src/config.h \
src/gflags_unittest.cc src/gflags_unittest.cc
gflags_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) gflags_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
...@@ -75,14 +75,14 @@ gflags_unittest_LDFLAGS = $(PTHREAD_CFLAGS) ...@@ -75,14 +75,14 @@ gflags_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
gflags_unittest_LDADD = libgflags.la gflags_unittest_LDADD = libgflags.la
# Also make sure this works when we don't link in pthreads # Also make sure this works when we don't link in pthreads
TESTS += gflags_nothreads_unittest$(EXEEXT) TESTS += gflags_nothreads_unittest
gflags_nothreads_unittest_SOURCES = $(gflags_unittest_SOURCES) gflags_nothreads_unittest_SOURCES = $(gflags_unittest_SOURCES)
gflags_nothreads_unittest_LDADD = libgflags_nothreads.la gflags_nothreads_unittest_LDADD = libgflags_nothreads.la
# We also want to test that things work properly when the file that # We also want to test that things work properly when the file that
# holds main() has a name ending with -main or _main. To keep the # holds main() has a name ending with -main or _main. To keep the
# Makefile small :-), we test the no-threads version of these. # Makefile small :-), we test the no-threads version of these.
TESTS += gflags_unittest2$(EXEEXT) TESTS += gflags_unittest2
gflags_unittest2_SOURCES = $(gflagsinclude_HEADERS) src/config.h \ gflags_unittest2_SOURCES = $(gflagsinclude_HEADERS) src/config.h \
src/gflags_unittest-main.cc src/gflags_unittest-main.cc
gflags_unittest2_LDADD = libgflags_nothreads.la gflags_unittest2_LDADD = libgflags_nothreads.la
...@@ -91,7 +91,7 @@ src/gflags_unittest-main.cc: src/gflags_unittest.cc ...@@ -91,7 +91,7 @@ src/gflags_unittest-main.cc: src/gflags_unittest.cc
cp -p src/gflags_unittest.cc src/gflags_unittest-main.cc cp -p src/gflags_unittest.cc src/gflags_unittest-main.cc
CLEANFILES += src/gflags_unittest-main.cc CLEANFILES += src/gflags_unittest-main.cc
TESTS += gflags_unittest3$(EXEEXT) TESTS += gflags_unittest3
gflags_unittest3_SOURCES = $(gflagsinclude_HEADERS) src/config.h \ gflags_unittest3_SOURCES = $(gflagsinclude_HEADERS) src/config.h \
src/gflags_unittest_main.cc src/gflags_unittest_main.cc
gflags_unittest3_LDADD = libgflags_nothreads.la gflags_unittest3_LDADD = libgflags_nothreads.la
...@@ -109,9 +109,32 @@ dist_noinst_DATA = src/gflags_unittest_flagfile ...@@ -109,9 +109,32 @@ dist_noinst_DATA = src/gflags_unittest_flagfile
gflags_unittest_sh: gflags_unittest$(EXEEXT) \ gflags_unittest_sh: gflags_unittest$(EXEEXT) \
gflags_unittest2$(EXEEXT) \ gflags_unittest2$(EXEEXT) \
gflags_unittest3$(EXEEXT) gflags_unittest3$(EXEEXT)
bash --version >/dev/null && export SH=bash || export SH=sh; \ bash --version >/dev/null 2>&1 && export SH=bash || export SH=sh; \
$$SH "$(top_srcdir)/src/gflags_unittest.sh" "$(PWD)/gflags_unittest" \ $$SH "$(top_srcdir)/src/gflags_unittest.sh" "$(PWD)/gflags_unittest" \
"$(top_srcdir)" "$(top_srcdir)" "@TMPDIR@"
# These are negative-compilation tests. We want to make sure these
# erroneous use of the flags macros correctly fail to compile.
# Again, we just bother testing with the no-threads version of the library.
check_SCRIPTS += gflags_nc_test1
gflags_nc_test1: $(gflagsinclude_HEADERS) src/config.h src/gflags_nc.cc
! $(CXX) -DTEST_SWAPPED_ARGS $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gflags_nc_test1.o $(srcdir)/src/gflags_nc.cc && echo "Compile failed, like it was supposed to"
check_SCRIPTS += gflags_nc_test2
gflags_nc_test2: $(gflagsinclude_HEADERS) src/config.h src/gflags_nc.cc
! $(CXX) -DTEST_INT_INSTEAD_OF_BOOL $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gflags_nc_test2.o $(srcdir)/src/gflags_nc.cc && echo "Compile failed, like it was supposed to"
check_SCRIPTS += gflags_nc_test3
gflags_nc_test3: $(gflagsinclude_HEADERS) src/config.h src/gflags_nc.cc
! $(CXX) -DTEST_BOOL_IN_QUOTES $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gflags_nc_test3.o $(srcdir)/src/gflags_nc.cc && echo "Compile failed, like it was supposed to"
# This one, on the other hand, should succeed.
check_SCRIPTS += gflags_nc_test4
gflags_nc_test4: $(gflagsinclude_HEADERS) src/config.h src/gflags_nc.cc
$(CXX) -DSANITY $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gflags_nc_test4.o $(srcdir)/src/gflags_nc.cc && echo "Compile failed, like it was supposed to"
# This file isn't covered under any rule that would cause it to be distributed.
dist_noinst_DATA += src/gflags_nc.cc
# These aren't part of the c++ source, but we want them to be distributed # These aren't part of the c++ source, but we want them to be distributed
PYTHON = python/setup.py \ PYTHON = python/setup.py \
......
...@@ -158,7 +158,7 @@ am__remove_distdir = \ ...@@ -158,7 +158,7 @@ am__remove_distdir = \
{ test ! -d $(distdir) \ { test ! -d $(distdir) \
|| { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
&& rm -fr $(distdir); }; } && rm -fr $(distdir); }; }
DIST_ARCHIVES = $(distdir).tar.gz DIST_ARCHIVES = $(distdir).tar.gz $(distdir).zip
GZIP_ENV = --best GZIP_ENV = --best
distuninstallcheck_listfiles = find . -type f -print distuninstallcheck_listfiles = find . -type f -print
distcleancheck_listfiles = find . -type f -print distcleancheck_listfiles = find . -type f -print
...@@ -225,6 +225,7 @@ SED = @SED@ ...@@ -225,6 +225,7 @@ SED = @SED@
SET_MAKE = @SET_MAKE@ SET_MAKE = @SET_MAKE@
SHELL = @SHELL@ SHELL = @SHELL@
STRIP = @STRIP@ STRIP = @STRIP@
TMPDIR = @TMPDIR@
VERSION = @VERSION@ VERSION = @VERSION@
ac_ct_CC = @ac_ct_CC@ ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@ ac_ct_CXX = @ac_ct_CXX@
...@@ -314,14 +315,21 @@ lib_LTLIBRARIES = libgflags.la libgflags_nothreads.la ...@@ -314,14 +315,21 @@ lib_LTLIBRARIES = libgflags.la libgflags_nothreads.la
# We also want to test that things work properly when the file that # We also want to test that things work properly when the file that
# holds main() has a name ending with -main or _main. To keep the # holds main() has a name ending with -main or _main. To keep the
# Makefile small :-), we test the no-threads version of these. # Makefile small :-), we test the no-threads version of these.
TESTS = gflags_unittest$(EXEEXT) gflags_nothreads_unittest$(EXEEXT) \ TESTS = gflags_unittest gflags_nothreads_unittest gflags_unittest2 \
gflags_unittest2$(EXEEXT) gflags_unittest3$(EXEEXT) gflags_unittest3
TESTS_ENVIRONMENT = SRCDIR="$(top_srcdir)" TESTS_ENVIRONMENT = SRCDIR="$(top_srcdir)"
# Some buggy sh's ignore "" instead of treating it as a positional # Some buggy sh's ignore "" instead of treating it as a positional
# parameter. Since we use "" in this script, we prefer bash if we # parameter. Since we use "" in this script, we prefer bash if we
# can. If there's no bash, we fall back to sh. # can. If there's no bash, we fall back to sh.
check_SCRIPTS = gflags_unittest_sh
# These are negative-compilation tests. We want to make sure these
# erroneous use of the flags macros correctly fail to compile.
# Again, we just bother testing with the no-threads version of the library.
# This one, on the other hand, should succeed.
check_SCRIPTS = gflags_unittest_sh gflags_nc_test1 gflags_nc_test2 \
gflags_nc_test3 gflags_nc_test4
# Every time you add a unittest to check_SCRIPTS, add it here too # Every time you add a unittest to check_SCRIPTS, add it here too
noinst_SCRIPTS = src/gflags_unittest.sh noinst_SCRIPTS = src/gflags_unittest.sh
# Used for auto-generated source files # Used for auto-generated source files
...@@ -352,7 +360,9 @@ gflags_unittest3_SOURCES = $(gflagsinclude_HEADERS) src/config.h \ ...@@ -352,7 +360,9 @@ gflags_unittest3_SOURCES = $(gflagsinclude_HEADERS) src/config.h \
src/gflags_unittest_main.cc src/gflags_unittest_main.cc
gflags_unittest3_LDADD = libgflags_nothreads.la gflags_unittest3_LDADD = libgflags_nothreads.la
dist_noinst_DATA = src/gflags_unittest_flagfile
# This file isn't covered under any rule that would cause it to be distributed.
dist_noinst_DATA = src/gflags_unittest_flagfile src/gflags_nc.cc
# These aren't part of the c++ source, but we want them to be distributed # These aren't part of the c++ source, but we want them to be distributed
PYTHON = python/setup.py \ PYTHON = python/setup.py \
...@@ -862,7 +872,6 @@ dist-tarZ: distdir ...@@ -862,7 +872,6 @@ dist-tarZ: distdir
dist-shar: distdir dist-shar: distdir
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
$(am__remove_distdir) $(am__remove_distdir)
dist-zip: distdir dist-zip: distdir
-rm -f $(distdir).zip -rm -f $(distdir).zip
zip -rq $(distdir).zip $(distdir) zip -rq $(distdir).zip $(distdir)
...@@ -870,6 +879,8 @@ dist-zip: distdir ...@@ -870,6 +879,8 @@ dist-zip: distdir
dist dist-all: distdir dist dist-all: distdir
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
-rm -f $(distdir).zip
zip -rq $(distdir).zip $(distdir)
$(am__remove_distdir) $(am__remove_distdir)
# This target untars the dist file and tries a VPATH configuration. Then # This target untars the dist file and tries a VPATH configuration. Then
...@@ -1060,9 +1071,17 @@ src/gflags_unittest_main.cc: src/gflags_unittest.cc ...@@ -1060,9 +1071,17 @@ src/gflags_unittest_main.cc: src/gflags_unittest.cc
gflags_unittest_sh: gflags_unittest$(EXEEXT) \ gflags_unittest_sh: gflags_unittest$(EXEEXT) \
gflags_unittest2$(EXEEXT) \ gflags_unittest2$(EXEEXT) \
gflags_unittest3$(EXEEXT) gflags_unittest3$(EXEEXT)
bash --version >/dev/null && export SH=bash || export SH=sh; \ bash --version >/dev/null 2>&1 && export SH=bash || export SH=sh; \
$$SH "$(top_srcdir)/src/gflags_unittest.sh" "$(PWD)/gflags_unittest" \ $$SH "$(top_srcdir)/src/gflags_unittest.sh" "$(PWD)/gflags_unittest" \
"$(top_srcdir)" "$(top_srcdir)" "@TMPDIR@"
gflags_nc_test1: $(gflagsinclude_HEADERS) src/config.h src/gflags_nc.cc
! $(CXX) -DTEST_SWAPPED_ARGS $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gflags_nc_test1.o $(srcdir)/src/gflags_nc.cc && echo "Compile failed, like it was supposed to"
gflags_nc_test2: $(gflagsinclude_HEADERS) src/config.h src/gflags_nc.cc
! $(CXX) -DTEST_INT_INSTEAD_OF_BOOL $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gflags_nc_test2.o $(srcdir)/src/gflags_nc.cc && echo "Compile failed, like it was supposed to"
gflags_nc_test3: $(gflagsinclude_HEADERS) src/config.h src/gflags_nc.cc
! $(CXX) -DTEST_BOOL_IN_QUOTES $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gflags_nc_test3.o $(srcdir)/src/gflags_nc.cc && echo "Compile failed, like it was supposed to"
gflags_nc_test4: $(gflagsinclude_HEADERS) src/config.h src/gflags_nc.cc
$(CXX) -DSANITY $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gflags_nc_test4.o $(srcdir)/src/gflags_nc.cc && echo "Compile failed, like it was supposed to"
rpm: dist-gzip packages/rpm.sh packages/rpm/rpm.spec rpm: dist-gzip packages/rpm.sh packages/rpm/rpm.spec
@cd packages && ./rpm.sh ${PACKAGE} ${VERSION} @cd packages && ./rpm.sh ${PACKAGE} ${VERSION}
......
This diff is collapsed.
...@@ -4,11 +4,11 @@ ...@@ -4,11 +4,11 @@
# make sure we're interpreted by some minimal autoconf # make sure we're interpreted by some minimal autoconf
AC_PREREQ(2.57) AC_PREREQ(2.57)
AC_INIT(gflags, 1.1, opensource@google.com) AC_INIT(gflags, 1.2, opensource@google.com)
# The argument here is just something that should be in the current directory # The argument here is just something that should be in the current directory
# (for sanity checking) # (for sanity checking)
AC_CONFIG_SRCDIR(README) AC_CONFIG_SRCDIR(README)
AM_INIT_AUTOMAKE AM_INIT_AUTOMAKE([dist-zip])
AM_CONFIG_HEADER(src/config.h) AM_CONFIG_HEADER(src/config.h)
# Checks for programs. # Checks for programs.
...@@ -27,11 +27,15 @@ case $host_os in ...@@ -27,11 +27,15 @@ case $host_os in
# MinGW. Using this option means an extra link step is executed during # MinGW. Using this option means an extra link step is executed during
# "make install". # "make install".
AC_DISABLE_FAST_INSTALL AC_DISABLE_FAST_INSTALL
# /tmp is a mount-point in mingw, and hard to use. use cwd instead
TMPDIR=gflags_testdir
;; ;;
*) *)
AC_ENABLE_FAST_INSTALL AC_ENABLE_FAST_INSTALL
TMPDIR=/tmp/gflags
;; ;;
esac esac
AC_SUBST(TMPDIR)
# Uncomment this if you'll be exporting libraries (.so's) # Uncomment this if you'll be exporting libraries (.so's)
AC_PROG_LIBTOOL AC_PROG_LIBTOOL
...@@ -53,6 +57,7 @@ AC_CHECK_TYPE(u_int16_t, ac_cv_have_u_int16_t=1, ac_cv_have_u_int16_t=0) ...@@ -53,6 +57,7 @@ AC_CHECK_TYPE(u_int16_t, ac_cv_have_u_int16_t=1, ac_cv_have_u_int16_t=0)
AC_CHECK_TYPE(__int16, ac_cv_have___int16=1, ac_cv_have___int16=0) AC_CHECK_TYPE(__int16, ac_cv_have___int16=1, ac_cv_have___int16=0)
AC_CHECK_FUNCS([strtoll strtoq]) AC_CHECK_FUNCS([strtoll strtoq])
AC_CHECK_FUNCS([setenv putenv]) # MinGW has putenv but not setenv
AX_C___ATTRIBUTE__ AX_C___ATTRIBUTE__
# We only care about __attribute__ ((unused)) # We only care about __attribute__ ((unused))
......
gflags (1.2-1) unstable; urgency=low
* New upstream release.
-- Google Inc. <opensource@google.com> Thu, 10 Sep 2009 12:53:04 -0700
gflags (1.1-1) unstable; urgency=low gflags (1.1-1) unstable; urgency=low
* New upstream release. * New upstream release.
......
...@@ -47,7 +47,18 @@ mkdir "$RPM_BUILD_DIR" ...@@ -47,7 +47,18 @@ mkdir "$RPM_BUILD_DIR"
cp "$archive" "$RPM_SOURCE_DIR" cp "$archive" "$RPM_SOURCE_DIR"
rpmbuild -bb rpm/rpm.spec \ # rpmbuild -- as far as I can tell -- asks the OS what CPU it has.
# This may differ from what kind of binaries gcc produces. dpkg
# does a better job of this, so if we can run 'dpkg --print-architecture'
# to get the build CPU, we use that in preference of the rpmbuild
# default.
target=`dpkg --print-architecture 2>/dev/null` # "" if dpkg isn't found
if [ -n "$target" ]
then
target=" --target $target"
fi
rpmbuild -bb rpm/rpm.spec $target \
--define "NAME $PACKAGE" \ --define "NAME $PACKAGE" \
--define "VERSION $VERSION" \ --define "VERSION $VERSION" \
--define "_sourcedir $RPM_SOURCE_DIR" \ --define "_sourcedir $RPM_SOURCE_DIR" \
......
...@@ -32,6 +32,15 @@ The %name-devel package contains static and debug libraries and header ...@@ -32,6 +32,15 @@ The %name-devel package contains static and debug libraries and header
files for developing applications that use the %name package. files for developing applications that use the %name package.
%changelog %changelog
* Thu Sep 10 2009 <opensource@google.com>
- Change from '%configure' to something like it, but without -m32
* Mon Apr 20 2009 <opensource@google.com>
- Change build rule to use '%configure' rather than './configure'
- Change install to use DESTDIR instead of prefix for make install.
- Use wildcards for doc/ and lib/ directories
- Use {_libdir}/{_includedir}/etc instead of {prefix}/lib, etc
* Tue Dec 13 2006 <opensource@google.com> * Tue Dec 13 2006 <opensource@google.com>
- First draft - First draft
...@@ -39,12 +48,15 @@ files for developing applications that use the %name package. ...@@ -39,12 +48,15 @@ files for developing applications that use the %name package.
%setup %setup
%build %build
./configure # I can't use '% configure', because it defines -m32 which breaks the
make prefix=%prefix # build somehow on my system. But I do take as much from % configure
# (in /usr/lib/rpm/macros) as I can.
./configure --prefix=%{_prefix} --exec-prefix=%{_exec_prefix} --bindir=%{_bindir} --sbindir=%{_sbindir} --sysconfdir=%{_sysconfdir} --datadir=%{_datadir} --includedir=%{_includedir} --libdir=%{_libdir} --libexecdir=%{_libexecdir} --localstatedir=%{_localstatedir} --sharedstatedir=%{_sharedstatedir} --mandir=%{_mandir} --infodir=%{_infodir}
make
%install %install
rm -rf $RPM_BUILD_ROOT rm -rf $RPM_BUILD_ROOT
make prefix=$RPM_BUILD_ROOT%{prefix} install make DESTDIR=$RPM_BUILD_ROOT install
%clean %clean
rm -rf $RPM_BUILD_ROOT rm -rf $RPM_BUILD_ROOT
...@@ -52,28 +64,20 @@ rm -rf $RPM_BUILD_ROOT ...@@ -52,28 +64,20 @@ rm -rf $RPM_BUILD_ROOT
%files %files
%defattr(-,root,root) %defattr(-,root,root)
## Mark all installed files within /usr/share/doc/{package name} as
## documentation. This depends on the following two lines appearing in
## Makefile.am:
## docdir = $(prefix)/share/doc/$(PACKAGE)-$(VERSION)
## dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README
%docdir %{prefix}/share/doc/%{NAME}-%{VERSION} %docdir %{prefix}/share/doc/%{NAME}-%{VERSION}
%{prefix}/share/doc/%{NAME}-%{VERSION}/* %{prefix}/share/doc/%{NAME}-%{VERSION}/*
%{prefix}/lib/libgflags.so.0 %doc AUTHORS COPYING ChangeLog INSTALL NEWS README
%{prefix}/lib/libgflags.so.0.0.0 %doc doc/*
%{prefix}/lib/libgflags_nothreads.so.0
%{prefix}/lib/libgflags_nothreads.so.0.0.0 %{_libdir}/*.so.*
%{prefix}/bin/gflags_completions.sh %{_bindir}/gflags_completions.sh
%files devel %files devel
%defattr(-,root,root) %defattr(-,root,root)
%{prefix}/include/google %{_includedir}/gflags
%{prefix}/include/gflags %{_includedir}/google
%{prefix}/lib/libgflags.a %{_libdir}/*.a
%{prefix}/lib/libgflags.la %{_libdir}/*.la
%{prefix}/lib/libgflags.so %{_libdir}/*.so
%{prefix}/lib/libgflags_nothreads.a
%{prefix}/lib/libgflags_nothreads.la
%{prefix}/lib/libgflags_nothreads.so
This diff is collapsed.
This diff is collapsed.
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"Unittest for flags.py module" "Unittest for gflags.py module"
__pychecker__ = "no-local" # for unittest __pychecker__ = "no-local" # for unittest
...@@ -495,7 +495,7 @@ class FlagsUnitTest(unittest.TestCase): ...@@ -495,7 +495,7 @@ class FlagsUnitTest(unittest.TestCase):
"--testspacelist [] --x 10 " "--testspacelist [] --x 10 "
"--noexec --quack " "--noexec --quack "
"--test1 " "--test1 "
"--testget1 --no? --nodebug --nohelp --nohelpshort " "--testget1 --no? --nodebug --nohelp --nohelpshort --nohelpxml "
"--noq --notest0 --notestget2 " "--noq --notest0 --notestget2 "
"--notestget3 --notestnone") "--notestget3 --notestnone")
...@@ -520,7 +520,7 @@ class FlagsUnitTest(unittest.TestCase): ...@@ -520,7 +520,7 @@ class FlagsUnitTest(unittest.TestCase):
"--testspacelist [] --x 10 " "--testspacelist [] --x 10 "
"--debug --noexec --quack " "--debug --noexec --quack "
"--test1 " "--test1 "
"--testget1 --no? --nohelp --nohelpshort " "--testget1 --no? --nohelp --nohelpshort --nohelpxml "
"--noq --notest0 --notestget2 " "--noq --notest0 --notestget2 "
"--notestget3 --notestnone") "--notestget3 --notestnone")
...@@ -535,12 +535,25 @@ class FlagsUnitTest(unittest.TestCase): ...@@ -535,12 +535,25 @@ class FlagsUnitTest(unittest.TestCase):
except flags.DuplicateFlag, e: except flags.DuplicateFlag, e:
pass pass
# Duplicate short flag detection
try: try:
flags.DEFINE_boolean("zoom1", 0, "runhelp z1", short_name='z') flags.DEFINE_boolean("zoom1", 0, "runhelp z1", short_name='z')
flags.DEFINE_boolean("zoom2", 0, "runhelp z2", short_name='z') flags.DEFINE_boolean("zoom2", 0, "runhelp z2", short_name='z')
raise AssertionError("duplicate flag detection failed") raise AssertionError("duplicate short flag detection failed")
except flags.DuplicateFlag, e: except flags.DuplicateFlag, e:
pass self.assertTrue("The flag 'z' is defined twice. " in e.args[0])
self.assertTrue("First from" in e.args[0])
self.assertTrue(", Second from" in e.args[0])
# Duplicate mixed flag detection
try:
flags.DEFINE_boolean("short1", 0, "runhelp s1", short_name='s')
flags.DEFINE_boolean("s", 0, "runhelp s2")
raise AssertionError("duplicate mixed flag detection failed")
except flags.DuplicateFlag, e:
self.assertTrue("The flag 's' is defined twice. " in e.args[0])
self.assertTrue("First from" in e.args[0])
self.assertTrue(", Second from" in e.args[0])
# Make sure allow_override works # Make sure allow_override works
try: try:
...@@ -1165,6 +1178,7 @@ class FlagsUnitTest(unittest.TestCase): ...@@ -1165,6 +1178,7 @@ class FlagsUnitTest(unittest.TestCase):
(default: 'false') (default: 'false')
-?,--[no]help: show this help -?,--[no]help: show this help
--[no]helpshort: show usage only for this module --[no]helpshort: show usage only for this module
--[no]helpxml: like --help, but generates XML output
--kwery: <who|what|why|where|when>: ? --kwery: <who|what|why|where|when>: ?
--l: how long to be --l: how long to be
(default: '9223372032559808512') (default: '9223372032559808512')
...@@ -1407,7 +1421,9 @@ class FlagsUnitTest(unittest.TestCase): ...@@ -1407,7 +1421,9 @@ class FlagsUnitTest(unittest.TestCase):
try: try:
help_flag_help = ( help_flag_help = (
" -?,--[no]help: show this help\n" " -?,--[no]help: show this help\n"
" --[no]helpshort: show usage only for this module") " --[no]helpshort: show usage only for this module\n"
" --[no]helpxml: like --help, but generates XML output"
)
expected_help = "\n%s:\n%s" % (sys.argv[0], help_flag_help) expected_help = "\n%s:\n%s" % (sys.argv[0], help_flag_help)
...@@ -1477,18 +1493,18 @@ class FlagsUnitTest(unittest.TestCase): ...@@ -1477,18 +1493,18 @@ class FlagsUnitTest(unittest.TestCase):
self.assertEqual(flags._GetCallingModule(), sys.argv[0]) self.assertEqual(flags._GetCallingModule(), sys.argv[0])
self.assertEqual( self.assertEqual(
module_foo.GetModuleName(), module_foo.GetModuleName(),
'google3.pyglib.tests.flags_modules_for_testing.module_foo') 'test_module_foo')
self.assertEqual( self.assertEqual(
module_bar.GetModuleName(), module_bar.GetModuleName(),
'google3.pyglib.tests.flags_modules_for_testing.module_bar') 'test_module_bar')
# We execute the following exec statements for their side-effect # We execute the following exec statements for their side-effect
# (i.e., not raising an error). They emphasize the case that not # (i.e., not raising an error). They emphasize the case that not
# all code resides in one of the imported modules: Python is a # all code resides in one of the imported modules: Python is a
# really dynamic language, where we can dynamically construct some # really dynamic language, where we can dynamically construct some
# code and execute it. # code and execute it.
code = ("from google3.pyglib import flags\n" code = ("import gflags\n"
"module_name = flags._GetCallingModule()") "module_name = gflags._GetCallingModule()")
exec code exec code
# Next two exec statements executes code with a global environment # Next two exec statements executes code with a global environment
...@@ -1517,7 +1533,7 @@ class FlagsUnitTest(unittest.TestCase): ...@@ -1517,7 +1533,7 @@ class FlagsUnitTest(unittest.TestCase):
module_bar.ExecuteCode(code, global_dict) module_bar.ExecuteCode(code, global_dict)
self.assertEqual( self.assertEqual(
global_dict['module_name'], global_dict['module_name'],
'google3.pyglib.tests.flags_modules_for_testing.module_bar') 'test_module_bar')
def main(): def main():
......
...@@ -21,6 +21,12 @@ ...@@ -21,6 +21,12 @@
/* Define if you have POSIX threads libraries and header files. */ /* Define if you have POSIX threads libraries and header files. */
#undef HAVE_PTHREAD #undef HAVE_PTHREAD
/* Define to 1 if you have the `putenv' function. */
#undef HAVE_PUTENV
/* Define to 1 if you have the `setenv' function. */
#undef HAVE_SETENV
/* Define to 1 if you have the <stdint.h> header file. */ /* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H #undef HAVE_STDINT_H
......
...@@ -669,7 +669,7 @@ class FlagRegistry { ...@@ -669,7 +669,7 @@ class FlagRegistry {
}; };
FlagRegistry* FlagRegistry::global_registry_ = NULL; FlagRegistry* FlagRegistry::global_registry_ = NULL;
Mutex FlagRegistry::global_registry_lock_; Mutex FlagRegistry::global_registry_lock_(Mutex::LINKER_INITIALIZED);
FlagRegistry* FlagRegistry::GlobalRegistry() { FlagRegistry* FlagRegistry::GlobalRegistry() {
MutexLock acquire_lock(&global_registry_lock_); MutexLock acquire_lock(&global_registry_lock_);
...@@ -1037,6 +1037,25 @@ uint32 CommandLineFlagParser::ParseNewCommandLineFlags(int* argc, char*** argv, ...@@ -1037,6 +1037,25 @@ uint32 CommandLineFlagParser::ParseNewCommandLineFlags(int* argc, char*** argv,
break; // we treat this as an unrecoverable error break; // we treat this as an unrecoverable error
} else { } else {
value = (*argv)[++i]; // read next arg for value value = (*argv)[++i]; // read next arg for value
// Heuristic to detect the case where someone treats a string arg
// like a bool:
// --my_string_var --foo=bar
// We look for a flag of string type, whose value begins with a
// dash, and where the flag-name and value are separated by a
// space rather than an '='.
// To avoid false positives, we also require the word "true"
// or "false" in the help string. Without this, a valid usage
// "-lat -30.5" would trigger the warning. The common cases we
// want to solve talk about true and false as values.
if (value[0] == '-'
&& strcmp(flag->type_name(), "string") == 0
&& (strstr(flag->help(), "true")
|| strstr(flag->help(), "false"))) {
fprintf(stderr, "Did you really mean to set flag '%s'"
" to the value '%s'?\n",
flag->name(), value);
}
} }
} }
...@@ -1343,15 +1362,6 @@ bool AddFlagValidator(const void* flag_ptr, ValidateFnProto validate_fn_proto) { ...@@ -1343,15 +1362,6 @@ bool AddFlagValidator(const void* flag_ptr, ValidateFnProto validate_fn_proto) {
// values in a global destructor. // values in a global destructor.
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// TODO(csilvers): When we're ready to have this error be a fatal one,
// change this to give a compilation error (via COMPILE_ASSERT(false)).
bool FlagsTypeWarn(const char *name) {
cerr << "Flag " << name << " is of type bool, but its default"
<< " value is not a boolean. NOTE: This will soon be a"
<< " compilations error!";
return false;
}
FlagRegisterer::FlagRegisterer(const char* name, const char* type, FlagRegisterer::FlagRegisterer(const char* name, const char* type,
const char* help, const char* filename, const char* help, const char* filename,
void* current_storage, void* defvalue_storage) { void* current_storage, void* defvalue_storage) {
...@@ -1530,7 +1540,7 @@ bool GetCommandLineFlagInfo(const char* name, CommandLineFlagInfo* OUTPUT) { ...@@ -1530,7 +1540,7 @@ bool GetCommandLineFlagInfo(const char* name, CommandLineFlagInfo* OUTPUT) {
CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name) { CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name) {
CommandLineFlagInfo info; CommandLineFlagInfo info;
if (!GetCommandLineFlagInfo(name, &info)) { if (!GetCommandLineFlagInfo(name, &info)) {
fprintf(stderr, "FATAL ERROR: flag name '%s' doesn't exit", name); fprintf(stderr, "FATAL ERROR: flag name '%s' doesn't exist\n", name);
commandlineflags_exitfunc(1); // almost certainly exit() commandlineflags_exitfunc(1); // almost certainly exit()
} }
return info; return info;
......
...@@ -415,7 +415,7 @@ class FlagRegisterer { ...@@ -415,7 +415,7 @@ class FlagRegisterer {
void* current_storage, void* defvalue_storage); void* current_storage, void* defvalue_storage);
}; };
#ifndef SWIG // In swig, ignore the main flag declarations extern bool FlagsTypeWarn(const char *name);
// If your application #defines STRIP_FLAG_HELP to a non-zero value // If your application #defines STRIP_FLAG_HELP to a non-zero value
// before #including this file, we remove the help message from the // before #including this file, we remove the help message from the
...@@ -424,6 +424,10 @@ class FlagRegisterer { ...@@ -424,6 +424,10 @@ class FlagRegisterer {
extern const char kStrippedFlagHelp[]; extern const char kStrippedFlagHelp[];
@ac_google_end_namespace@
#ifndef SWIG // In swig, ignore the main flag declarations
#if defined(STRIP_FLAG_HELP) && STRIP_FLAG_HELP > 0 #if defined(STRIP_FLAG_HELP) && STRIP_FLAG_HELP > 0
// Need this construct to avoid the 'defined but not used' warning. // Need this construct to avoid the 'defined but not used' warning.
#define MAYBE_STRIPPED_HELP(txt) (false ? (txt) : kStrippedFlagHelp) #define MAYBE_STRIPPED_HELP(txt) (false ? (txt) : kStrippedFlagHelp)
...@@ -459,26 +463,30 @@ extern const char kStrippedFlagHelp[]; ...@@ -459,26 +463,30 @@ extern const char kStrippedFlagHelp[];
} \ } \
using fL##shorttype::FLAGS_##name using fL##shorttype::FLAGS_##name
// For boolean flags, we want to do the extra check that the passed-in // For DEFINE_bool, we want to do the extra check that the passed-in
// value is actually a bool, and not a string or something that can be // value is actually a bool, and not a string or something that can be
// coerced to a bool. These declarations (no definition needed!) will // coerced to a bool. These declarations (no definition needed!) will
// help us do that, and never evaluate from, which is important. // help us do that, and never evaluate From, which is important.
// We'll use 'sizeof(IsBool(val))' to distinguish. // We'll use 'sizeof(IsBool(val))' to distinguish. This code requires
// that the compiler have different sizes for bool & double. Since
// this is not guaranteed by the standard, we check it with a
// compile-time assert (msg[-1] will give a compile-time error).
namespace fLB { namespace fLB {
struct CompileAssert {};
typedef CompileAssert expected_sizeof_double_neq_sizeof_bool[
(sizeof(double) != sizeof(bool)) ? 1 : -1];
template<typename From> double IsBoolFlag(const From& from); template<typename From> double IsBoolFlag(const From& from);
bool IsBoolFlag(bool from); bool IsBoolFlag(bool from);
} } // namespace fLB
extern bool FlagsTypeWarn(const char *name);
#define DECLARE_bool(name) DECLARE_VARIABLE(bool,B, name) #define DECLARE_bool(name) DECLARE_VARIABLE(bool,B, name)
// We have extra code here to make sure 'val' is actually a boolean. #define DEFINE_bool(name,val,txt) \
#define DEFINE_bool(name,val,txt) namespace fLB { \ namespace fLB { \
const bool FLAGS_nonono##name = \ typedef CompileAssert FLAG_##name##_value_is_not_a_bool[ \
(sizeof(@ac_google_namespace@::fLB::IsBoolFlag(val)) \ (sizeof(::fLB::IsBoolFlag(val)) != sizeof(double)) ? 1 : -1]; \
== sizeof(double)) \ } \
? @ac_google_namespace@::FlagsTypeWarn(#name) : true; \ DEFINE_VARIABLE(bool,B, name, val, txt)
} \
DEFINE_VARIABLE(bool,B, name, val, txt)
#define DECLARE_int32(name) DECLARE_VARIABLE(@ac_google_namespace@::int32,I, name) #define DECLARE_int32(name) DECLARE_VARIABLE(@ac_google_namespace@::int32,I, name)
#define DEFINE_int32(name,val,txt) DEFINE_VARIABLE(@ac_google_namespace@::int32,I, name, val, txt) #define DEFINE_int32(name,val,txt) DEFINE_VARIABLE(@ac_google_namespace@::int32,I, name, val, txt)
...@@ -522,6 +530,4 @@ extern bool FlagsTypeWarn(const char *name); ...@@ -522,6 +530,4 @@ extern bool FlagsTypeWarn(const char *name);
#endif // SWIG #endif // SWIG
@ac_google_end_namespace@
#endif // GOOGLE_GFLAGS_H_ #endif // GOOGLE_GFLAGS_H_
// Copyright (c) 2009, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
// Author: Roberto Bayardo
//
// A negative compile test for commandlineflags.
#include <gflags/gflags.h>
#if defined(TEST_SWAPPED_ARGS)
DEFINE_bool(some_bool_flag,
"the default value should go here, not the description",
false);
#elif defined(TEST_INT_INSTEAD_OF_BOOL)
DEFINE_bool(some_bool_flag_2,
0,
"should have been an int32 flag but mistakenly used bool instead");
#elif defined(TEST_BOOL_IN_QUOTES)
DEFINE_bool(some_bool_flag_3,
"false",
"false in in quotes, which is wrong");
#elif defined(SANITY)
DEFINE_bool(some_bool_flag_4,
true,
"this is the correct usage of DEFINE_bool");
#endif
...@@ -57,6 +57,28 @@ using GOOGLE_NAMESPACE::FlagRegisterer; ...@@ -57,6 +57,28 @@ using GOOGLE_NAMESPACE::FlagRegisterer;
// Returns the number of elements in an array. // Returns the number of elements in an array.
#define GET_ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*(arr))) #define GET_ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*(arr)))
#if !defined(HAVE_SETENV) && defined(HAVE_PUTENV) // mingw, at least
void setenv(const char* name, const char* value, int) {
// In windows, it's impossible to set a variable to the empty string.
// We handle this by setting it to "0" and the NUL-ing out the \0.
// cf http://svn.apache.org/viewvc/stdcxx/trunk/tests/src/environ.cpp?r1=611451&r2=637508&pathrev=637508
static const char* const kFakeZero = "0";
if (*value == '\0')
value = kFakeZero;
// Apparently the semantics of putenv() is that the input
// must live forever, so we leak memory here. :-(
const int nameval_len = strlen(name) + 1 + strlen(value) + 1;
char* nameval = reinterpret_cast<char*>(malloc(nameval_len));
snprintf(nameval, nameval_len, "%s=%s", name, value);
putenv(nameval);
if (value == kFakeZero) {
nameval[nameval_len - 2] = '\0'; // works when putenv() makes no copy
if (*getenv(name) != '\0')
*getenv(name) = '\0'; // works when putenv() copies nameval
}
}
#endif
DECLARE_string(tryfromenv); // in gflags.cc DECLARE_string(tryfromenv); // in gflags.cc
DEFINE_string(test_tmpdir, "/tmp/gflags_unittest", "Dir we use for temp files"); DEFINE_string(test_tmpdir, "/tmp/gflags_unittest", "Dir we use for temp files");
...@@ -86,18 +108,6 @@ DEFINE_string(test_str3, "initial", ""); ...@@ -86,18 +108,6 @@ DEFINE_string(test_str3, "initial", "");
// This is used to test setting tryfromenv manually // This is used to test setting tryfromenv manually
DEFINE_string(test_tryfromenv, "initial", ""); DEFINE_string(test_tryfromenv, "initial", "");
// boolean flag assigned correctly with bool
DEFINE_bool(test_bool_bool, true, "");
// boolean flag assigned with string
DEFINE_bool(test_bool_string, "", "");
// boolean flag assigned with float
DEFINE_bool(test_bool_float, 1.0, "");
// boolean flag assigned with int
DEFINE_bool(test_bool_int, 1, "");
// Don't try this at home! // Don't try this at home!
static int changeable_var = 12; static int changeable_var = 12;
DEFINE_int32(changeable_var, ++changeable_var, ""); DEFINE_int32(changeable_var, ++changeable_var, "");
...@@ -249,7 +259,11 @@ vector<void (*)()> g_testlist; // the tests to run ...@@ -249,7 +259,11 @@ vector<void (*)()> g_testlist; // the tests to run
#define TEST(a, b) \ #define TEST(a, b) \
struct Test_##a##_##b { \ struct Test_##a##_##b { \
Test_##a##_##b() { g_testlist.push_back(&Run); } \ Test_##a##_##b() { g_testlist.push_back(&Run); } \
static void Run() { FlagSaver fs; RunTest(); } \ static void Run() { \
FlagSaver fs; \
fprintf(stderr, "Running test %s/%s\n", #a, #b); \
RunTest(); \
} \
static void RunTest(); \ static void RunTest(); \
}; \ }; \
static Test_##a##_##b g_test_##a##_##b; \ static Test_##a##_##b g_test_##a##_##b; \
...@@ -416,6 +430,7 @@ TEST(FlagFileTest, FilenamesOurfileFirst) { ...@@ -416,6 +430,7 @@ TEST(FlagFileTest, FilenamesOurfileFirst) {
-1.0); -1.0);
} }
#ifdef HAVE_FNMATCH_H // otherwise glob isn't supported
TEST(FlagFileTest, FilenamesOurfileGlob) { TEST(FlagFileTest, FilenamesOurfileGlob) {
FLAGS_test_string = "initial"; FLAGS_test_string = "initial";
FLAGS_test_bool = false; FLAGS_test_bool = false;
...@@ -467,6 +482,7 @@ TEST(FlagFileTest, FilenamesOurfileInBigList) { ...@@ -467,6 +482,7 @@ TEST(FlagFileTest, FilenamesOurfileInBigList) {
1, 1,
-1.0); -1.0);
} }
#endif
// Tests that a failed flag-from-string read keeps flags at default values // Tests that a failed flag-from-string read keeps flags at default values
TEST(FlagFileTest, FailReadFlagsFromString) { TEST(FlagFileTest, FailReadFlagsFromString) {
...@@ -540,8 +556,11 @@ TEST(SetFlagValueTest, OrdinaryValues) { ...@@ -540,8 +556,11 @@ TEST(SetFlagValueTest, OrdinaryValues) {
// Tests that flags can be set to exceptional values. // Tests that flags can be set to exceptional values.
// Note: apparently MINGW doesn't parse inf and nan correctly:
// http://www.mail-archive.com/bug-gnulib@gnu.org/msg09573.html
// This url says FreeBSD also has a problem, but I didn't see that.
TEST(SetFlagValueTest, ExceptionalValues) { TEST(SetFlagValueTest, ExceptionalValues) {
#ifdef isinf // on systems without isinf, inf stuff may not work at all #if defined(isinf) && !defined(__MINGW32__)
EXPECT_EQ("test_double set to inf\n", EXPECT_EQ("test_double set to inf\n",
SetCommandLineOption("test_double", "inf")); SetCommandLineOption("test_double", "inf"));
EXPECT_INF(FLAGS_test_double); EXPECT_INF(FLAGS_test_double);
...@@ -558,14 +577,14 @@ TEST(SetFlagValueTest, ExceptionalValues) { ...@@ -558,14 +577,14 @@ TEST(SetFlagValueTest, ExceptionalValues) {
SetCommandLineOption("test_double", " ")); SetCommandLineOption("test_double", " "));
EXPECT_EQ("", EXPECT_EQ("",
SetCommandLineOption("test_double", "")); SetCommandLineOption("test_double", ""));
#ifdef isinf #if defined(isinf) && !defined(__MINGW32__)
EXPECT_EQ("test_double set to -inf\n", EXPECT_EQ("test_double set to -inf\n",
SetCommandLineOption("test_double", "-inf")); SetCommandLineOption("test_double", "-inf"));
EXPECT_INF(FLAGS_test_double); EXPECT_INF(FLAGS_test_double);
EXPECT_GT(0, FLAGS_test_double); EXPECT_GT(0, FLAGS_test_double);
#endif #endif
#ifdef isnan #if defined(isnan) && !defined(__MINGW32__)
EXPECT_EQ("test_double set to nan\n", EXPECT_EQ("test_double set to nan\n",
SetCommandLineOption("test_double", "NaN")); SetCommandLineOption("test_double", "NaN"));
EXPECT_NAN(FLAGS_test_double); EXPECT_NAN(FLAGS_test_double);
...@@ -1499,7 +1518,13 @@ static int Main(int argc, char **argv) { ...@@ -1499,7 +1518,13 @@ static int Main(int argc, char **argv) {
SetUsageMessage(usage_message.c_str()); SetUsageMessage(usage_message.c_str());
ParseCommandLineFlags(&argc, &argv, true); ParseCommandLineFlags(&argc, &argv, true);
#ifdef __MINGW32__
// I had trouble creating a directory in /tmp from mingw
FLAGS_test_tmpdir = "./gflags_unittest_testdir";
mkdir(FLAGS_test_tmpdir.c_str()); // mingw has a weird one-arg mkdir
#else
mkdir(FLAGS_test_tmpdir.c_str(), 0755); mkdir(FLAGS_test_tmpdir.c_str(), 0755);
#endif
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
} }
......
...@@ -215,14 +215,6 @@ Expect $LINENO 0 "gflags_unittest" "gflags_unittest.cc" \ ...@@ -215,14 +215,6 @@ Expect $LINENO 0 "gflags_unittest" "gflags_unittest.cc" \
# Make sure -- by itself stops argv processing # Make sure -- by itself stops argv processing
Expect $LINENO 0 "PASS" "" -- --help Expect $LINENO 0 "PASS" "" -- --help
# Make sure boolean flags gives warning when type of default value is not bool
Expect $LINENO 0 "Flag test_bool_string is of type bool, but its default value is not a boolean." ""
Expect $LINENO 0 "Flag test_bool_float is of type bool, but its default value is not a boolean." ""
Expect $LINENO 0 "Flag test_bool_int is of type bool, but its default value is not a boolean." ""
# Make sure that boolean flags don't give warning when default value is bool
Expect $LINENO 0 "" "Flag test_bool_bool is of type bool, but its default value is not a boolean."
# And we should die if the flag value doesn't pas the validator # And we should die if the flag value doesn't pas the validator
Expect $LINENO 1 "ERROR: failed validation of new value 'true' for flag 'always_fail'" "" --always_fail Expect $LINENO 1 "ERROR: failed validation of new value 'true' for flag 'always_fail'" "" --always_fail
......
...@@ -38,9 +38,12 @@ ...@@ -38,9 +38,12 @@
// AC_RWLOCK // AC_RWLOCK
// The latter is defined in ../autoconf. // The latter is defined in ../autoconf.
// //
// This class is meant to be internal-only, so it's defined in the // This class is meant to be internal-only and should be wrapped by an
// global namespace. If you want to expose it, you'll want to move // internal namespace. Before you use this module, please give the
// it to the Google namespace. // name of your internal namespace for this module. Or, if you want
// to expose it, you'll want to move it to the Google namespace. We
// cannot put this class in global namespace because there can be some
// problems when we have multiple versions of Mutex in each shared object.
// //
// NOTE: by default, we have #ifdef'ed out the TryLock() method. // NOTE: by default, we have #ifdef'ed out the TryLock() method.
// This is for two reasons: // This is for two reasons:
...@@ -95,6 +98,16 @@ ...@@ -95,6 +98,16 @@
// colon-initializer) and set it to true via a function that always // colon-initializer) and set it to true via a function that always
// evaluates to true, but that the compiler can't know always // evaluates to true, but that the compiler can't know always
// evaluates to true. This should be good enough. // evaluates to true. This should be good enough.
//
// A related issue is code that could try to access the mutex
// after it's been destroyed in the global destructors (because
// the Mutex global destructor runs before some other global
// destructor, that tries to acquire the mutex). The way we
// deal with this is by taking a constructor arg that global
// mutexes should pass in, that causes the destructor to do no
// work. We still depend on the compiler not doing anything
// weird to a Mutex's memory after it is destroyed, but for a
// static global variable, that's pretty safe.
#ifndef GOOGLE_MUTEX_H_ #ifndef GOOGLE_MUTEX_H_
#define GOOGLE_MUTEX_H_ #define GOOGLE_MUTEX_H_
...@@ -132,13 +145,26 @@ ...@@ -132,13 +145,26 @@
# error Need to implement mutex.h for your architecture, or #define NO_THREADS # error Need to implement mutex.h for your architecture, or #define NO_THREADS
#endif #endif
#include <assert.h>
#include <stdlib.h> // for abort()
#define MUTEX_NAMESPACE gflags_mutex_namespace
namespace MUTEX_NAMESPACE {
class Mutex { class Mutex {
public: public:
// This is used for the single-arg constructor
enum LinkerInitialized { LINKER_INITIALIZED };
// Create a Mutex that is not held by anybody. This constructor is // Create a Mutex that is not held by anybody. This constructor is
// typically used for Mutexes allocated on the heap or the stack. // typically used for Mutexes allocated on the heap or the stack.
// See below for a recommendation for constructing global Mutex
// objects.
inline Mutex(); inline Mutex();
// This constructor should be used for global, static Mutex objects.
// It inhibits work being done by the destructor, which makes it
// safer for code that tries to acqiure this mutex in their global
// destructor.
inline Mutex(LinkerInitialized);
// Destructor // Destructor
inline ~Mutex(); inline ~Mutex();
...@@ -163,6 +189,8 @@ class Mutex { ...@@ -163,6 +189,8 @@ class Mutex {
// when we tell it to, and never makes assumptions is_safe_ is // when we tell it to, and never makes assumptions is_safe_ is
// always true. volatile is the most reliable way to do that. // always true. volatile is the most reliable way to do that.
volatile bool is_safe_; volatile bool is_safe_;
// This indicates which constructor was called.
bool destroy_;
inline void SetIsSafe() { is_safe_ = true; } inline void SetIsSafe() { is_safe_ = true; }
...@@ -185,9 +213,9 @@ class Mutex { ...@@ -185,9 +213,9 @@ class Mutex {
// In debug mode, we assert these invariants, while in non-debug mode // In debug mode, we assert these invariants, while in non-debug mode
// we do nothing, for efficiency. That's why everything is in an // we do nothing, for efficiency. That's why everything is in an
// assert. // assert.
#include <assert.h>
Mutex::Mutex() : mutex_(0) { } Mutex::Mutex() : mutex_(0) { }
Mutex::Mutex(Mutex::LinkerInitialized) : mutex_(0) { }
Mutex::~Mutex() { assert(mutex_ == 0); } Mutex::~Mutex() { assert(mutex_ == 0); }
void Mutex::Lock() { assert(--mutex_ == -1); } void Mutex::Lock() { assert(--mutex_ == -1); }
void Mutex::Unlock() { assert(mutex_++ == -1); } void Mutex::Unlock() { assert(mutex_++ == -1); }
...@@ -199,8 +227,15 @@ void Mutex::ReaderUnlock() { assert(mutex_-- > 0); } ...@@ -199,8 +227,15 @@ void Mutex::ReaderUnlock() { assert(mutex_-- > 0); }
#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__) #elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__)
Mutex::Mutex() { InitializeCriticalSection(&mutex_); SetIsSafe(); } Mutex::Mutex() : destroy_(true) {
Mutex::~Mutex() { DeleteCriticalSection(&mutex_); } InitializeCriticalSection(&mutex_);
SetIsSafe();
}
Mutex::Mutex(LinkerInitialized) : destroy_(false) {
InitializeCriticalSection(&mutex_);
SetIsSafe();
}
Mutex::~Mutex() { if (destroy_) DeleteCriticalSection(&mutex_); }
void Mutex::Lock() { if (is_safe_) EnterCriticalSection(&mutex_); } void Mutex::Lock() { if (is_safe_) EnterCriticalSection(&mutex_); }
void Mutex::Unlock() { if (is_safe_) LeaveCriticalSection(&mutex_); } void Mutex::Unlock() { if (is_safe_) LeaveCriticalSection(&mutex_); }
#ifdef GMUTEX_TRYLOCK #ifdef GMUTEX_TRYLOCK
...@@ -212,22 +247,24 @@ void Mutex::ReaderUnlock() { Unlock(); } ...@@ -212,22 +247,24 @@ void Mutex::ReaderUnlock() { Unlock(); }
#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK) #elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
#include <stdlib.h> // for abort()
#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \ #define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
if (is_safe_ && fncall(&mutex_) != 0) abort(); \ if (is_safe_ && fncall(&mutex_) != 0) abort(); \
} while (0) } while (0)
Mutex::Mutex() { Mutex::Mutex() : destroy_(true) {
SetIsSafe();
if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort();
}
Mutex::Mutex(Mutex::LinkerInitialized) : destroy_(false) {
SetIsSafe(); SetIsSafe();
if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort(); if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort();
} }
Mutex::~Mutex() { SAFE_PTHREAD(pthread_rwlock_destroy); } Mutex::~Mutex() { if (destroy_) SAFE_PTHREAD(pthread_rwlock_destroy); }
void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock); } void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock); }
void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock); } void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
#ifdef GMUTEX_TRYLOCK #ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { return is_safe_ ? bool Mutex::TryLock() { return is_safe_ ?
pthread_rwlock_trywrlock(&mutex_) == 0 : pthread_rwlock_trywrlock(&mutex_) == 0 : true; }
true; }
#endif #endif
void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock); } void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock); }
void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); } void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
...@@ -235,16 +272,19 @@ void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); } ...@@ -235,16 +272,19 @@ void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
#elif defined(HAVE_PTHREAD) #elif defined(HAVE_PTHREAD)
#include <stdlib.h> // for abort()
#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \ #define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
if (is_safe_ && fncall(&mutex_) != 0) abort(); \ if (is_safe_ && fncall(&mutex_) != 0) abort(); \
} while (0) } while (0)
Mutex::Mutex() { Mutex::Mutex() : destroy_(true) {
SetIsSafe(); SetIsSafe();
if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort(); if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort();
} }
Mutex::~Mutex() { SAFE_PTHREAD(pthread_mutex_destroy); } Mutex::Mutex(Mutex::LinkerInitialized) : destroy_(false) {
SetIsSafe();
if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort();
}
Mutex::~Mutex() { if (destroy_) SAFE_PTHREAD(pthread_mutex_destroy); }
void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); } void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); }
void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); } void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); }
#ifdef GMUTEX_TRYLOCK #ifdef GMUTEX_TRYLOCK
...@@ -300,4 +340,10 @@ class WriterMutexLock { ...@@ -300,4 +340,10 @@ class WriterMutexLock {
#define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name) #define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name)
#define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name) #define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name)
} // namespace MUTEX_NAMESPACE
using namespace MUTEX_NAMESPACE;
#undef MUTEX_NAMESPACE
#endif /* #define GOOGLE_MUTEX_H__ */ #endif /* #define GOOGLE_MUTEX_H__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment