1f4a2713aSLionel Sambuc //===- Version.cpp - Clang Version Number -----------------------*- C++ -*-===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This file defines several version-related utility functions for Clang.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc 
14f4a2713aSLionel Sambuc #include "clang/Basic/Version.h"
15f4a2713aSLionel Sambuc #include "clang/Basic/LLVM.h"
16*0a6a1f1dSLionel Sambuc #include "clang/Config/config.h"
17f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
18f4a2713aSLionel Sambuc #include <cstdlib>
19f4a2713aSLionel Sambuc #include <cstring>
20f4a2713aSLionel Sambuc 
21f4a2713aSLionel Sambuc #ifdef HAVE_SVN_VERSION_INC
22f4a2713aSLionel Sambuc #  include "SVNVersion.inc"
23f4a2713aSLionel Sambuc #endif
24f4a2713aSLionel Sambuc 
25f4a2713aSLionel Sambuc namespace clang {
26f4a2713aSLionel Sambuc 
getClangRepositoryPath()27f4a2713aSLionel Sambuc std::string getClangRepositoryPath() {
28f4a2713aSLionel Sambuc #if defined(CLANG_REPOSITORY_STRING)
29f4a2713aSLionel Sambuc   return CLANG_REPOSITORY_STRING;
30f4a2713aSLionel Sambuc #else
31f4a2713aSLionel Sambuc #ifdef SVN_REPOSITORY
32f4a2713aSLionel Sambuc   StringRef URL(SVN_REPOSITORY);
33f4a2713aSLionel Sambuc #else
34f4a2713aSLionel Sambuc   StringRef URL("");
35f4a2713aSLionel Sambuc #endif
36f4a2713aSLionel Sambuc 
37f4a2713aSLionel Sambuc   // If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us
38f4a2713aSLionel Sambuc   // pick up a tag in an SVN export, for example.
39*0a6a1f1dSLionel Sambuc   StringRef SVNRepository("$URL: http://llvm.org/svn/llvm-project/cfe/branches/release_36/lib/Basic/Version.cpp $");
40f4a2713aSLionel Sambuc   if (URL.empty()) {
41f4a2713aSLionel Sambuc     URL = SVNRepository.slice(SVNRepository.find(':'),
42f4a2713aSLionel Sambuc                               SVNRepository.find("/lib/Basic"));
43f4a2713aSLionel Sambuc   }
44f4a2713aSLionel Sambuc 
45f4a2713aSLionel Sambuc   // Strip off version from a build from an integration branch.
46f4a2713aSLionel Sambuc   URL = URL.slice(0, URL.find("/src/tools/clang"));
47f4a2713aSLionel Sambuc 
48f4a2713aSLionel Sambuc   // Trim path prefix off, assuming path came from standard cfe path.
49f4a2713aSLionel Sambuc   size_t Start = URL.find("cfe/");
50f4a2713aSLionel Sambuc   if (Start != StringRef::npos)
51f4a2713aSLionel Sambuc     URL = URL.substr(Start + 4);
52f4a2713aSLionel Sambuc 
53f4a2713aSLionel Sambuc   return URL;
54f4a2713aSLionel Sambuc #endif
55f4a2713aSLionel Sambuc }
56f4a2713aSLionel Sambuc 
getLLVMRepositoryPath()57f4a2713aSLionel Sambuc std::string getLLVMRepositoryPath() {
58f4a2713aSLionel Sambuc #ifdef LLVM_REPOSITORY
59f4a2713aSLionel Sambuc   StringRef URL(LLVM_REPOSITORY);
60f4a2713aSLionel Sambuc #else
61f4a2713aSLionel Sambuc   StringRef URL("");
62f4a2713aSLionel Sambuc #endif
63f4a2713aSLionel Sambuc 
64f4a2713aSLionel Sambuc   // Trim path prefix off, assuming path came from standard llvm path.
65f4a2713aSLionel Sambuc   // Leave "llvm/" prefix to distinguish the following llvm revision from the
66f4a2713aSLionel Sambuc   // clang revision.
67f4a2713aSLionel Sambuc   size_t Start = URL.find("llvm/");
68f4a2713aSLionel Sambuc   if (Start != StringRef::npos)
69f4a2713aSLionel Sambuc     URL = URL.substr(Start);
70f4a2713aSLionel Sambuc 
71f4a2713aSLionel Sambuc   return URL;
72f4a2713aSLionel Sambuc }
73f4a2713aSLionel Sambuc 
getClangRevision()74f4a2713aSLionel Sambuc std::string getClangRevision() {
75f4a2713aSLionel Sambuc #ifdef SVN_REVISION
76f4a2713aSLionel Sambuc   return SVN_REVISION;
77f4a2713aSLionel Sambuc #else
78f4a2713aSLionel Sambuc   return "";
79f4a2713aSLionel Sambuc #endif
80f4a2713aSLionel Sambuc }
81f4a2713aSLionel Sambuc 
getLLVMRevision()82f4a2713aSLionel Sambuc std::string getLLVMRevision() {
83f4a2713aSLionel Sambuc #ifdef LLVM_REVISION
84f4a2713aSLionel Sambuc   return LLVM_REVISION;
85f4a2713aSLionel Sambuc #else
86f4a2713aSLionel Sambuc   return "";
87f4a2713aSLionel Sambuc #endif
88f4a2713aSLionel Sambuc }
89f4a2713aSLionel Sambuc 
getClangFullRepositoryVersion()90f4a2713aSLionel Sambuc std::string getClangFullRepositoryVersion() {
91f4a2713aSLionel Sambuc   std::string buf;
92f4a2713aSLionel Sambuc   llvm::raw_string_ostream OS(buf);
93f4a2713aSLionel Sambuc   std::string Path = getClangRepositoryPath();
94f4a2713aSLionel Sambuc   std::string Revision = getClangRevision();
95f4a2713aSLionel Sambuc   if (!Path.empty() || !Revision.empty()) {
96f4a2713aSLionel Sambuc     OS << '(';
97f4a2713aSLionel Sambuc     if (!Path.empty())
98f4a2713aSLionel Sambuc       OS << Path;
99f4a2713aSLionel Sambuc     if (!Revision.empty()) {
100f4a2713aSLionel Sambuc       if (!Path.empty())
101f4a2713aSLionel Sambuc         OS << ' ';
102f4a2713aSLionel Sambuc       OS << Revision;
103f4a2713aSLionel Sambuc     }
104f4a2713aSLionel Sambuc     OS << ')';
105f4a2713aSLionel Sambuc   }
106f4a2713aSLionel Sambuc   // Support LLVM in a separate repository.
107f4a2713aSLionel Sambuc   std::string LLVMRev = getLLVMRevision();
108f4a2713aSLionel Sambuc   if (!LLVMRev.empty() && LLVMRev != Revision) {
109f4a2713aSLionel Sambuc     OS << " (";
110f4a2713aSLionel Sambuc     std::string LLVMRepo = getLLVMRepositoryPath();
111f4a2713aSLionel Sambuc     if (!LLVMRepo.empty())
112f4a2713aSLionel Sambuc       OS << LLVMRepo << ' ';
113f4a2713aSLionel Sambuc     OS << LLVMRev << ')';
114f4a2713aSLionel Sambuc   }
115f4a2713aSLionel Sambuc   return OS.str();
116f4a2713aSLionel Sambuc }
117f4a2713aSLionel Sambuc 
getClangFullVersion()118f4a2713aSLionel Sambuc std::string getClangFullVersion() {
119*0a6a1f1dSLionel Sambuc   return getClangToolFullVersion("clang");
120*0a6a1f1dSLionel Sambuc }
121*0a6a1f1dSLionel Sambuc 
getClangToolFullVersion(StringRef ToolName)122*0a6a1f1dSLionel Sambuc std::string getClangToolFullVersion(StringRef ToolName) {
123f4a2713aSLionel Sambuc   std::string buf;
124f4a2713aSLionel Sambuc   llvm::raw_string_ostream OS(buf);
125f4a2713aSLionel Sambuc #ifdef CLANG_VENDOR
126f4a2713aSLionel Sambuc   OS << CLANG_VENDOR;
127f4a2713aSLionel Sambuc #endif
128*0a6a1f1dSLionel Sambuc   OS << ToolName << " version " CLANG_VERSION_STRING " "
129f4a2713aSLionel Sambuc      << getClangFullRepositoryVersion();
130f4a2713aSLionel Sambuc 
131f4a2713aSLionel Sambuc   // If vendor supplied, include the base LLVM version as well.
132f4a2713aSLionel Sambuc #ifdef CLANG_VENDOR
133*0a6a1f1dSLionel Sambuc   OS << " (based on " << BACKEND_PACKAGE_STRING << ")";
134f4a2713aSLionel Sambuc #endif
135f4a2713aSLionel Sambuc 
136f4a2713aSLionel Sambuc   return OS.str();
137f4a2713aSLionel Sambuc }
138f4a2713aSLionel Sambuc 
getClangFullCPPVersion()139f4a2713aSLionel Sambuc std::string getClangFullCPPVersion() {
140f4a2713aSLionel Sambuc   // The version string we report in __VERSION__ is just a compacted version of
141f4a2713aSLionel Sambuc   // the one we report on the command line.
142f4a2713aSLionel Sambuc   std::string buf;
143f4a2713aSLionel Sambuc   llvm::raw_string_ostream OS(buf);
144f4a2713aSLionel Sambuc #ifdef CLANG_VENDOR
145f4a2713aSLionel Sambuc   OS << CLANG_VENDOR;
146f4a2713aSLionel Sambuc #endif
147f4a2713aSLionel Sambuc   OS << "Clang " CLANG_VERSION_STRING " " << getClangFullRepositoryVersion();
148f4a2713aSLionel Sambuc   return OS.str();
149f4a2713aSLionel Sambuc }
150f4a2713aSLionel Sambuc 
151f4a2713aSLionel Sambuc } // end namespace clang
152