diff --git a/Makefile b/Makefile index 16e6b32eba09181ad4f4d2d5ced4ef228955c114..c023ee96032ffc0ba44f7a8d05fcfd45834d950f 100644 --- a/Makefile +++ b/Makefile @@ -361,7 +361,7 @@ E = @echo Q = @ endif -VERSION = 0.13.0.0 +VERSION = 0.13.0-dev CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES)) CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS) diff --git a/build.yaml b/build.yaml index b61594519812e0626e8d1f28743761e29f3bfd14..6c42ec82694e6d34b1916ea2368f7afc3edec82b 100644 --- a/build.yaml +++ b/build.yaml @@ -2,12 +2,12 @@ '#2': It is used among other things to generate all of our project files. '#3': Please refer to the templates directory for more information. settings: - '#': The public version number of the library. - version: - major: 0 - minor: 13 - micro: 0 - build: 0 + '#1': The public version number of the library. + '#2': Master always has a "-dev" suffix + '#3': Use "-preN" suffixes to identify pre-release versions + '#4': Per-language overrides are possible with (eg) ruby_version security_connector_test + '#5': See the expand_version.py for all the quirks here + version: 0.13.0-dev filegroups: - name: census public_headers: diff --git a/setup.py b/setup.py index 80828a3b4a9aa3d9cc9ec033648bee0f9e676fb4..f8450a7677fefedc451ff8429e089efd0ce17107 100644 --- a/setup.py +++ b/setup.py @@ -54,6 +54,7 @@ sys.path.insert(0, os.path.abspath(PYTHON_STEM)) # Break import-style to ensure we can actually find our in-repo dependencies. import commands import grpc_core_dependencies +import grpc_version LICENSE = '3-clause BSD' @@ -218,7 +219,7 @@ else: setuptools.setup( name='grpcio', - version='0.12.0b8', + version=grpc_version.VERSION, license=LICENSE, ext_modules=CYTHON_EXTENSION_MODULES, packages=list(PACKAGES), diff --git a/src/core/surface/version.c b/src/core/surface/version.c index 262a13f184d86e3b253c362a53f0ec2f00d4cca6..b33c99ab19d19af59a5c3820595c6a802a515d81 100644 --- a/src/core/surface/version.c +++ b/src/core/surface/version.c @@ -36,4 +36,4 @@ #include <grpc/grpc.h> -const char *grpc_version_string(void) { return "0.13.0.0"; } +const char *grpc_version_string(void) { return "0.13.0-dev"; } diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs index 65813909deef87d48d33ee397981fd6fa0368ea3..7124ec85d36a65876f194734a64eb8fde23ecd7c 100644 --- a/src/csharp/Grpc.Core/VersionInfo.cs +++ b/src/csharp/Grpc.Core/VersionInfo.cs @@ -41,6 +41,6 @@ namespace Grpc.Core /// <summary> /// Current version of gRPC C# /// </summary> - public const string CurrentVersion = "0.13.0"; + public const string CurrentVersion = "0.13.0-dev"; } } diff --git a/src/csharp/build_packages.bat b/src/csharp/build_packages.bat index e423545ef8cd98f48b1a6bd69590673b7cbacc8d..2c4e4e514d473f817509fb4c565e52215fca45b9 100644 --- a/src/csharp/build_packages.bat +++ b/src/csharp/build_packages.bat @@ -1,7 +1,7 @@ @rem Builds gRPC NuGet packages @rem Current package versions -set VERSION=0.13.0 +set VERSION=0.13.0-dev set PROTOBUF_VERSION=3.0.0-beta2 @rem Packages that depend on prerelease packages (like Google.Protobuf) need to have prerelease suffix as well. diff --git a/src/python/grpcio/grpc_version.py b/src/python/grpcio/grpc_version.py new file mode 100644 index 0000000000000000000000000000000000000000..8a40544981fd95bc4261d95f7b81f331565636a3 --- /dev/null +++ b/src/python/grpcio/grpc_version.py @@ -0,0 +1,32 @@ +# Copyright 2015-2016, 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. + +# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!! + +VERSION='0.13.0.dev0' diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb index 89ff882916ca35acc617188f8a61471af0515744..e701d5847898bba5f287894a24fec8ec910823c6 100644 --- a/src/ruby/lib/grpc/version.rb +++ b/src/ruby/lib/grpc/version.rb @@ -29,5 +29,5 @@ # GRPC contains the General RPC module. module GRPC - VERSION = '0.13.0.0' + VERSION = '0.13.0-dev' end diff --git a/templates/Makefile.template b/templates/Makefile.template index 1a38e267a7f5611914a9e1da448821a6a0a4e795..994251421165020e3857f7beeef5eb20996529ff 100644 --- a/templates/Makefile.template +++ b/templates/Makefile.template @@ -276,7 +276,7 @@ Q = @ endif - VERSION = ${settings.version.major}.${settings.version.minor}.${settings.version.micro}.${settings.version.build} + VERSION = ${settings.core_version} CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES)) CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS) @@ -320,7 +320,7 @@ ifeq ($(SYSTEM),MINGW32) SHARED_EXT = dll SHARED_PREFIX = - SHARED_VERSION = -${settings.version.major} + SHARED_VERSION = -${settings.core_version.major} else ifeq ($(SYSTEM),Darwin) SHARED_EXT = dylib SHARED_PREFIX = lib @@ -1286,7 +1286,7 @@ ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}-imp.a $(prefix)/lib/lib${lib.name}-imp.a else ifneq ($(SYSTEM),Darwin) - $(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION).$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.so.${settings.version.major} + $(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION).$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.so.${settings.core_version.major} $(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION).$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.so endif % endif @@ -1304,7 +1304,7 @@ ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}-imp.a $(prefix)/lib/lib${lib.name}-imp.a else ifneq ($(SYSTEM),Darwin) - $(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION).$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.so.${settings.version.major} + $(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION).$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.so.${settings.core_version.major} $(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION).$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.so endif % endif @@ -1578,8 +1578,8 @@ ifeq ($(SYSTEM),Darwin) $(Q) ${ld} ${ldflags} -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION).$(SHARED_EXT) -dynamiclib -o ${out_libbase}.$(SHARED_EXT) ${common}${libs} else - $(Q) ${ld} ${ldflags} -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,lib${lib.name}.so.${settings.version.major} -o ${out_libbase}.$(SHARED_EXT) ${common}${libs} - $(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION).$(SHARED_EXT) ${out_libbase}.so.${settings.version.major} + $(Q) ${ld} ${ldflags} -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,lib${lib.name}.so.${settings.core_version.major} -o ${out_libbase}.$(SHARED_EXT) ${common}${libs} + $(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION).$(SHARED_EXT) ${out_libbase}.so.${settings.core_version.major} $(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION).$(SHARED_EXT) ${out_libbase}.so endif endif diff --git a/templates/src/core/surface/version.c.template b/templates/src/core/surface/version.c.template index 4788dc47d9f8d5227dc1aaa6d3f1982b6c696241..f2b3cfdc5893baf3ce12775ac38af41b5f433de6 100644 --- a/templates/src/core/surface/version.c.template +++ b/templates/src/core/surface/version.c.template @@ -38,5 +38,4 @@ #include <grpc/grpc.h> - const char *grpc_version_string(void) { \ - return "${settings.version.major}.${settings.version.minor}.${settings.version.micro}.${settings.version.build}"; } + const char *grpc_version_string(void) { return "${settings.core_version}"; } diff --git a/templates/src/csharp/Grpc.Core/VersionInfo.cs.template b/templates/src/csharp/Grpc.Core/VersionInfo.cs.template index 48197baf7d0d422c49779672fae69b098cc89134..578f01f07939a4018f5404104c42398b32d37d70 100644 --- a/templates/src/csharp/Grpc.Core/VersionInfo.cs.template +++ b/templates/src/csharp/Grpc.Core/VersionInfo.cs.template @@ -43,6 +43,6 @@ /// <summary> /// Current version of gRPC C# /// </summary> - public const string CurrentVersion = "${settings.version.major}.${settings.version.minor}.${settings.version.micro}"; + public const string CurrentVersion = "${settings.csharp_version}"; } } diff --git a/templates/src/csharp/build_packages.bat.template b/templates/src/csharp/build_packages.bat.template index 847653bdcfb584566b4aec9b53a80e507078b427..b855126ae60084fdb02d554a3a2b2bbb4e5602c3 100644 --- a/templates/src/csharp/build_packages.bat.template +++ b/templates/src/csharp/build_packages.bat.template @@ -3,7 +3,7 @@ @rem Builds gRPC NuGet packages @rem Current package versions - set VERSION=${settings.version.major}.${settings.version.minor}.${settings.version.micro} + set VERSION=${settings.csharp_version} set PROTOBUF_VERSION=3.0.0-beta2 @rem Packages that depend on prerelease packages (like Google.Protobuf) need to have prerelease suffix as well. diff --git a/templates/src/python/grpcio/grpc_version.py.template b/templates/src/python/grpcio/grpc_version.py.template new file mode 100644 index 0000000000000000000000000000000000000000..aaacab1a5080a02919297e3417da7ac0399d3f81 --- /dev/null +++ b/templates/src/python/grpcio/grpc_version.py.template @@ -0,0 +1,34 @@ +%YAML 1.2 +--- | + # Copyright 2015-2016, 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. + + # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!! + + VERSION='${settings.python_version.pep440()}' diff --git a/templates/src/ruby/lib/grpc/version.rb.template b/templates/src/ruby/lib/grpc/version.rb.template index 4859d2f883405cf872690a398be3d56a28a73cf8..a47d2d854894516324079693b0fa068002c40115 100644 --- a/templates/src/ruby/lib/grpc/version.rb.template +++ b/templates/src/ruby/lib/grpc/version.rb.template @@ -31,5 +31,5 @@ # GRPC contains the General RPC module. module GRPC - VERSION = '${settings.version.major}.${settings.version.minor}.${settings.version.micro}.${settings.version.build}' + VERSION = '${settings.ruby_version}' end diff --git a/templates/tools/doxygen/Doxyfile.include b/templates/tools/doxygen/Doxyfile.include index 21ef8a8ecd34f744caaa7689b6331fbf76d1b230..8b0c528c1f68f5eee14b6609d5cab25c6fe0fc92 100644 --- a/templates/tools/doxygen/Doxyfile.include +++ b/templates/tools/doxygen/Doxyfile.include @@ -57,7 +57,7 @@ PROJECT_NAME = "GRPC ${packagename}" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = ${settings.version.major}.${settings.version.minor}.${settings.version.micro}.${settings.version.build} +PROJECT_NUMBER = ${settings.core_version if packagename=='Core' else settings.cpp_version} # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/buildgen/build-cleaner.py b/tools/buildgen/build-cleaner.py index 37fedec6ad103a4c1e6dc7d81133f11d0b810df2..49a364412350c0aa6bb02e61c1b426ce9bc8fc29 100755 --- a/tools/buildgen/build-cleaner.py +++ b/tools/buildgen/build-cleaner.py @@ -38,7 +38,6 @@ import yaml TEST = (os.environ.get('TEST', 'false') == 'true') _TOP_LEVEL_KEYS = ['settings', 'proto_deps', 'filegroups', 'libs', 'targets', 'vspackages'] -_VERSION_KEYS = ['major', 'minor', 'micro', 'build'] _ELEM_KEYS = [ 'name', 'cpu_cost', @@ -83,8 +82,6 @@ for filename in sys.argv[1:]: with open(filename) as f: js = yaml.load(f) js = rebuild_as_ordered_dict(js, _TOP_LEVEL_KEYS) - js['settings']['version'] = rebuild_as_ordered_dict( - js['settings']['version'], _VERSION_KEYS) for grp in ['filegroups', 'libs', 'targets']: if grp not in js: continue js[grp] = sorted([clean_elem(x) for x in js[grp]], diff --git a/tools/buildgen/plugins/expand_version.py b/tools/buildgen/plugins/expand_version.py new file mode 100755 index 0000000000000000000000000000000000000000..9f9c7c71fa7fb5482f4b4fe19a90441273514fbb --- /dev/null +++ b/tools/buildgen/plugins/expand_version.py @@ -0,0 +1,94 @@ +# Copyright 2015, 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. + +"""Buildgen .proto files list plugin. + +This parses the list of targets from the yaml build file, and creates +a list called "protos" that contains all of the proto file names. + +""" + + +import re + +LANGUAGES = [ + 'core', + 'cpp', + 'csharp', + 'node', + 'objc', + 'php', + 'python', + 'ruby', + ] + +class Version: + + def __init__(self, s): + if '-' in s: + s, self.tag = s.split('-') + self.major, self.minor, self.patch = [int(x) for x in s.split('.')] + + def __str__(self): + """Version string in a somewhat idiomatic style for most languages""" + s = '%d.%d.%d' % (self.major, self.minor, self.patch) + if self.tag: + s += '-%s' % self.tag + return s + + def pep440(self): + """Version string in Python PEP440 style""" + s = '%d.%d.%d' % (self.major, self.minor, self.patch) + if self.tag: + # we need to translate from grpc version tags to pep440 version + # tags; this code is likely to be a little ad-hoc + if self.tag == 'dev': + s += '.dev0' + elif len(self.tag) >= 3 and self.tag[0:3] == 'pre': + s += 'rc%d' % int(self.tag[3:]) + else: + raise Exception('Don\'t know how to translate version tag "%s" to pep440' % self.tag) + return s + +def mako_plugin(dictionary): + """Expand version numbers: + - for each language, ensure there's a language_version tag in + settings (defaulting to the master version tag) + - expand version strings to major, minor, patch, and tag + """ + + settings = dictionary['settings'] + master_version = Version(settings['version']) + settings['version'] = master_version + for language in LANGUAGES: + version_tag = '%s_version' % language + if version_tag in settings: + settings[version_tag] = Version(settings[version_tag]) + else: + settings[version_tag] = master_version diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index cdb998d59cca0be82f421402d0b8f498ac09166b..5bc38a9aec9e89a32f8a40724db788d143663048 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.13.0.0 +PROJECT_NUMBER = 0.13.0-dev # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 558ec9d3947c78bd31ee9b60fe5827867a490b7e..ec71d2e9cddf717a0e00181e41b1200ccb50e740 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.13.0.0 +PROJECT_NUMBER = 0.13.0-dev # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index a3b458163cda6bb0a31034c0f07c7a855563b3fd..0f22620686cf253a5666999c5b8a86b5f469b1bf 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC Core" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.13.0.0 +PROJECT_NUMBER = 0.13.0-dev # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index e91b47c6f4b616c9ecff156e67d5ef03f58d5f2d..a3540778c1f8501f91ac4a6949df1985e062422b 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC Core" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.13.0.0 +PROJECT_NUMBER = 0.13.0-dev # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a