1198092Srdivacky//===- Version.cpp - Clang Version Number -----------------------*- C++ -*-===//
2198092Srdivacky//
3198092Srdivacky//                     The LLVM Compiler Infrastructure
4198092Srdivacky//
5198092Srdivacky// This file is distributed under the University of Illinois Open Source
6198092Srdivacky// License. See LICENSE.TXT for details.
7198092Srdivacky//
8198092Srdivacky//===----------------------------------------------------------------------===//
9198092Srdivacky//
10198092Srdivacky// This file defines several version-related utility functions for Clang.
11198092Srdivacky//
12198092Srdivacky//===----------------------------------------------------------------------===//
13202879Srdivacky
14202879Srdivacky#include "clang/Basic/Version.h"
15226633Sdim#include "clang/Basic/LLVM.h"
16249423Sdim#include "llvm/Config/config.h"
17202879Srdivacky#include "llvm/Support/raw_ostream.h"
18249423Sdim#include <cstdlib>
19198092Srdivacky#include <cstring>
20202879Srdivacky
21249423Sdim#ifdef HAVE_SVN_VERSION_INC
22249423Sdim#  include "SVNVersion.inc"
23249423Sdim#endif
24249423Sdim
25198092Srdivackynamespace clang {
26234353Sdim
27218893Sdimstd::string getClangRepositoryPath() {
28221345Sdim#if defined(CLANG_REPOSITORY_STRING)
29221345Sdim  return CLANG_REPOSITORY_STRING;
30221345Sdim#else
31218893Sdim#ifdef SVN_REPOSITORY
32226633Sdim  StringRef URL(SVN_REPOSITORY);
33218893Sdim#else
34226633Sdim  StringRef URL("");
35218893Sdim#endif
36203955Srdivacky
37218893Sdim  // If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us
38218893Sdim  // pick up a tag in an SVN export, for example.
39251662Sdim  static StringRef SVNRepository("$URL: http://llvm.org/svn/llvm-project/cfe/tags/RELEASE_33/final/lib/Basic/Version.cpp $");
40218893Sdim  if (URL.empty()) {
41218893Sdim    URL = SVNRepository.slice(SVNRepository.find(':'),
42218893Sdim                              SVNRepository.find("/lib/Basic"));
43218893Sdim  }
44203955Srdivacky
45208600Srdivacky  // Strip off version from a build from an integration branch.
46218893Sdim  URL = URL.slice(0, URL.find("/src/tools/clang"));
47203955Srdivacky
48218893Sdim  // Trim path prefix off, assuming path came from standard cfe path.
49218893Sdim  size_t Start = URL.find("cfe/");
50226633Sdim  if (Start != StringRef::npos)
51218893Sdim    URL = URL.substr(Start + 4);
52203955Srdivacky
53218893Sdim  return URL;
54221345Sdim#endif
55198092Srdivacky}
56198092Srdivacky
57234353Sdimstd::string getLLVMRepositoryPath() {
58234353Sdim#ifdef LLVM_REPOSITORY
59234353Sdim  StringRef URL(LLVM_REPOSITORY);
60234353Sdim#else
61234353Sdim  StringRef URL("");
62234353Sdim#endif
63234353Sdim
64234353Sdim  // Trim path prefix off, assuming path came from standard llvm path.
65234353Sdim  // Leave "llvm/" prefix to distinguish the following llvm revision from the
66234353Sdim  // clang revision.
67234353Sdim  size_t Start = URL.find("llvm/");
68234353Sdim  if (Start != StringRef::npos)
69234353Sdim    URL = URL.substr(Start);
70234353Sdim
71234353Sdim  return URL;
72234353Sdim}
73234353Sdim
74203955Srdivackystd::string getClangRevision() {
75204643Srdivacky#ifdef SVN_REVISION
76218893Sdim  return SVN_REVISION;
77218893Sdim#else
78218893Sdim  return "";
79204643Srdivacky#endif
80198092Srdivacky}
81198092Srdivacky
82234353Sdimstd::string getLLVMRevision() {
83234353Sdim#ifdef LLVM_REVISION
84234353Sdim  return LLVM_REVISION;
85234353Sdim#else
86234353Sdim  return "";
87234353Sdim#endif
88234353Sdim}
89234353Sdim
90203955Srdivackystd::string getClangFullRepositoryVersion() {
91203955Srdivacky  std::string buf;
92203955Srdivacky  llvm::raw_string_ostream OS(buf);
93218893Sdim  std::string Path = getClangRepositoryPath();
94218893Sdim  std::string Revision = getClangRevision();
95234353Sdim  if (!Path.empty() || !Revision.empty()) {
96234353Sdim    OS << '(';
97218893Sdim    if (!Path.empty())
98234353Sdim      OS << Path;
99234353Sdim    if (!Revision.empty()) {
100234353Sdim      if (!Path.empty())
101234353Sdim        OS << ' ';
102234353Sdim      OS << Revision;
103234353Sdim    }
104234353Sdim    OS << ')';
105234353Sdim  }
106234353Sdim  // Support LLVM in a separate repository.
107234353Sdim  std::string LLVMRev = getLLVMRevision();
108234353Sdim  if (!LLVMRev.empty() && LLVMRev != Revision) {
109234353Sdim    OS << " (";
110234353Sdim    std::string LLVMRepo = getLLVMRepositoryPath();
111234353Sdim    if (!LLVMRepo.empty())
112234353Sdim      OS << LLVMRepo << ' ';
113234353Sdim    OS << LLVMRev << ')';
114218893Sdim  }
115204793Srdivacky  return OS.str();
116202879Srdivacky}
117234353Sdim
118203955Srdivackystd::string getClangFullVersion() {
119203955Srdivacky  std::string buf;
120203955Srdivacky  llvm::raw_string_ostream OS(buf);
121202879Srdivacky#ifdef CLANG_VENDOR
122203955Srdivacky  OS << CLANG_VENDOR;
123202879Srdivacky#endif
124234353Sdim  OS << "clang version " CLANG_VERSION_STRING " "
125234353Sdim     << getClangFullRepositoryVersion();
126218893Sdim
127209107Sed#ifdef CLANG_VENDOR_SUFFIX
128209107Sed  OS << CLANG_VENDOR_SUFFIX;
129218893Sdim#elif defined(CLANG_VENDOR)
130218893Sdim  // If vendor supplied, include the base LLVM version as well.
131218893Sdim  OS << " (based on LLVM " << PACKAGE_VERSION << ")";
132209107Sed#endif
133218893Sdim
134204793Srdivacky  return OS.str();
135202879Srdivacky}
136203955Srdivacky
137221345Sdimstd::string getClangFullCPPVersion() {
138221345Sdim  // The version string we report in __VERSION__ is just a compacted version of
139221345Sdim  // the one we report on the command line.
140221345Sdim  std::string buf;
141221345Sdim  llvm::raw_string_ostream OS(buf);
142221345Sdim#ifdef CLANG_VENDOR
143221345Sdim  OS << CLANG_VENDOR;
144221345Sdim#endif
145239462Sdim  OS << "Clang " CLANG_VERSION_STRING " " << getClangFullRepositoryVersion();
146221345Sdim  return OS.str();
147221345Sdim}
148221345Sdim
149198092Srdivacky} // end namespace clang
150