aboutsummaryrefslogtreecommitdiff
path: root/build2/cc/guess.hxx
blob: 4d5d036525f11674dcba12998fefba9c88a1b8e8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// file      : build2/cc/guess.hxx -*- C++ -*-
// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
// license   : MIT; see accompanying LICENSE file

#ifndef BUILD2_CC_GUESS_HXX
#define BUILD2_CC_GUESS_HXX

#include <build2/types.hxx>
#include <build2/utility.hxx>

#include <build2/cc/types.hxx>

namespace build2
{
  namespace cc
  {
    // Compiler id consisting of a type and optional variant. If the variant
    // is not empty, then the id is spelled out as 'type-variant', similar to
    // target triplets (this also means that the type cannot contain '-').
    //
    // Currently recognized compilers and their ids:
    //
    // gcc          GCC gcc/g++
    // clang        Vanilla Clang clang/clang++
    // clang-apple  Apple Clang clang/clang++ and the gcc/g++ "alias"
    // msvc         Microsoft cl.exe
    // icc          Intel icc/icpc
    //
    struct compiler_id
    {
      std::string type;
      std::string variant;

      bool
      empty () const {return type.empty ();}

      std::string
      string () const {return variant.empty () ? type : type + "-" + variant;}

      // Note: does not include variant.
      //
      enum value_type
      {
        gcc,
        clang,
        msvc,
        icc
      };

      value_type
      value () const;
    };

    inline ostream&
    operator<< (ostream& os, const compiler_id& id)
    {
      return os << id.string ();
    }

    // Compiler version. Here we map the various compiler version formats to
    // something that resembles the MAJOR.MINOR.PATCH-BUILD form of the
    // Semantic Versioning. While the MAJOR.MINOR part is relatively
    // straightforward, PATCH may be empty and BUILD can contain pretty much
    // anything (including spaces).
    //
    // gcc           A.B.C[ ...]         {A, B, C, ...}
    // clang         A.B.C[( |-)...]     {A, B, C, ...}
    // clang-apple   A.B[.C] ...         {A, B, C, ...}
    // icc           A.B[.C.D] ...       {A, B, C, D ...}
    // msvc          A.B.C[.D]           {A, B, C, D}
    //
    // Note that the clang-apple version is a custom Apple version and does
    // not correspond to the vanilla clang version.
    //
    struct compiler_version
    {
      std::string string;

      // Currently all the compilers that we support have numeric MAJOR,
      // MINOR, and PATCH components and it makes sense to represent them as
      // integers for easy comparison. If we meet a compiler for which this
      // doesn't hold, then we will probably just set these to 0 and let the
      // user deal with the string representation.
      //
      uint64_t major;
      uint64_t minor;
      uint64_t patch;
      std::string build;
    };

    // Compiler information.
    //
    // The signature is normally the -v/--version line that was used to guess
    // the compiler id and its version.
    //
    // The checksum is used to detect compiler changes. It is calculated in a
    // compiler-specific manner (usually the output of -v/--version) and is
    // not bulletproof (e.g., it most likely won't detect that the underlying
    // assembler or linker has changed). However, it should detect most
    // common cases, such as an upgrade to a new version or a configuration
    // change.
    //
    // Note that we assume the checksum incorporates the (default) target so
    // that if the compiler changes but only in what it targets, then the
    // checksum will still change. This is currently the case for all the
    // compilers that we support.
    //
    // The target is the compiler's traget architecture triplet. Note that
    // unlike all the preceding fields, this one takes into account the
    // compile options (e.g., -m32).
    //
    // The cc_pattern is the toolchain program pattern that could sometimes be
    // derived for some toolchains. For example, i686-w64-mingw32-*-4.9.
    //
    // The bin_pattern is the binutils program pattern that could sometimes be
    // derived for some toolchains. For example, i686-w64-mingw32-*. If the
    // pattern could not be derived, then it could contain a fallback search
    // directory, in which case it will end with a directory separator but
    // will not contain '*'.
    //
    struct compiler_info
    {
      process_path path;
      compiler_id id;
      compiler_version version;
      string signature;
      string checksum;
      string target;
      string cc_pattern;
      string bin_pattern;
    };

    // In a sense this is analagous to the language standard which we handle
    // via a virtual function in common. However, duplicating this hairy ball
    // of fur in multiple places doesn't seem wise, especially considering
    // that most of it will be the same, at least for C and C++.
    //
    compiler_info
    guess (lang,
           const path& xc,
           const strings* c_coptions,
           const strings* x_coptions);

    // Given a language, toolchain id, and optionally a pattern, return an
    // appropriate default compiler path.
    //
    // For example, for (lang::cxx, gcc, *-4.9) we will get g++-4.9.
    //
    path
    guess_default (lang, const string& cid, const string* pattern);
  }
}

#endif // BUILD2_CC_GUESS_HXX