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"
15226890Sdim#include "clang/Basic/LLVM.h"
16252723Sdim#include "llvm/Config/config.h"
17202879Srdivacky#include "llvm/Support/raw_ostream.h"
18252723Sdim#include <cstdlib>
19198092Srdivacky#include <cstring>
20202879Srdivacky
21252723Sdim#ifdef HAVE_SVN_VERSION_INC
22252723Sdim#  include "SVNVersion.inc"
23252723Sdim#endif
24252723Sdim
25198092Srdivackynamespace clang {
26235633Sdim
27218893Sdimstd::string getClangRepositoryPath() {
28221345Sdim#if defined(CLANG_REPOSITORY_STRING)
29221345Sdim  return CLANG_REPOSITORY_STRING;
30221345Sdim#else
31218893Sdim#ifdef SVN_REPOSITORY
32226890Sdim  StringRef URL(SVN_REPOSITORY);
33218893Sdim#else
34226890Sdim  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.
39266759Sdim  StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_34/dot1-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/");
50226890Sdim  if (Start != StringRef::npos)
51218893Sdim    URL = URL.substr(Start + 4);
52203955Srdivacky
53218893Sdim  return URL;
54221345Sdim#endif
55198092Srdivacky}
56198092Srdivacky
57235633Sdimstd::string getLLVMRepositoryPath() {
58235633Sdim#ifdef LLVM_REPOSITORY
59235633Sdim  StringRef URL(LLVM_REPOSITORY);
60235633Sdim#else
61235633Sdim  StringRef URL("");
62235633Sdim#endif
63235633Sdim
64235633Sdim  // Trim path prefix off, assuming path came from standard llvm path.
65235633Sdim  // Leave "llvm/" prefix to distinguish the following llvm revision from the
66235633Sdim  // clang revision.
67235633Sdim  size_t Start = URL.find("llvm/");
68235633Sdim  if (Start != StringRef::npos)
69235633Sdim    URL = URL.substr(Start);
70235633Sdim
71235633Sdim  return URL;
72235633Sdim}
73235633Sdim
74203955Srdivackystd::string getClangRevision() {
75204643Srdivacky#ifdef SVN_REVISION
76218893Sdim  return SVN_REVISION;
77218893Sdim#else
78218893Sdim  return "";
79204643Srdivacky#endif
80198092Srdivacky}
81198092Srdivacky
82235633Sdimstd::string getLLVMRevision() {
83235633Sdim#ifdef LLVM_REVISION
84235633Sdim  return LLVM_REVISION;
85235633Sdim#else
86235633Sdim  return "";
87235633Sdim#endif
88235633Sdim}
89235633Sdim
90203955Srdivackystd::string getClangFullRepositoryVersion() {
91203955Srdivacky  std::string buf;
92203955Srdivacky  llvm::raw_string_ostream OS(buf);
93218893Sdim  std::string Path = getClangRepositoryPath();
94218893Sdim  std::string Revision = getClangRevision();
95235633Sdim  if (!Path.empty() || !Revision.empty()) {
96235633Sdim    OS << '(';
97218893Sdim    if (!Path.empty())
98235633Sdim      OS << Path;
99235633Sdim    if (!Revision.empty()) {
100235633Sdim      if (!Path.empty())
101235633Sdim        OS << ' ';
102235633Sdim      OS << Revision;
103235633Sdim    }
104235633Sdim    OS << ')';
105235633Sdim  }
106235633Sdim  // Support LLVM in a separate repository.
107235633Sdim  std::string LLVMRev = getLLVMRevision();
108235633Sdim  if (!LLVMRev.empty() && LLVMRev != Revision) {
109235633Sdim    OS << " (";
110235633Sdim    std::string LLVMRepo = getLLVMRepositoryPath();
111235633Sdim    if (!LLVMRepo.empty())
112235633Sdim      OS << LLVMRepo << ' ';
113235633Sdim    OS << LLVMRev << ')';
114218893Sdim  }
115204793Srdivacky  return OS.str();
116202879Srdivacky}
117235633Sdim
118203955Srdivackystd::string getClangFullVersion() {
119203955Srdivacky  std::string buf;
120203955Srdivacky  llvm::raw_string_ostream OS(buf);
121202879Srdivacky#ifdef CLANG_VENDOR
122203955Srdivacky  OS << CLANG_VENDOR;
123202879Srdivacky#endif
124235633Sdim  OS << "clang version " CLANG_VERSION_STRING " "
125235633Sdim     << 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
145245431Sdim  OS << "Clang " CLANG_VERSION_STRING " " << getClangFullRepositoryVersion();
146221345Sdim  return OS.str();
147221345Sdim}
148221345Sdim
149198092Srdivacky} // end namespace clang
150