source: castxml/trunk/fuentes/src/Detect.cxx @ 6513

Last change on this file since 6513 was 6513, checked in by mabarracus, 2 years ago

Initial port to lliurex from ubuntu

File size: 7.3 KB
Line 
1/*
2  Copyright Kitware, Inc.
3
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7
8      http://www.apache.org/licenses/LICENSE-2.0
9
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15*/
16
17#include "Detect.h"
18#include "Options.h"
19#include "Utils.h"
20
21#include "llvm/ADT/SmallVector.h"
22#include "llvm/ADT/StringRef.h"
23#include "llvm/ADT/Triple.h"
24#include "llvm/Support/FileSystem.h"
25#include "llvm/Support/Host.h"
26
27#include <algorithm>
28#include <cstdlib>
29#include <iostream>
30#include <string.h>
31
32//----------------------------------------------------------------------------
33static std::string getClangBuiltinIncludeDir()
34{
35  return getClangResourceDir() + "/include";
36}
37
38//----------------------------------------------------------------------------
39static bool failedCC(const char* id,
40                     std::vector<const char*> const& args,
41                     std::string const& out,
42                     std::string const& err,
43                     std::string const& msg)
44{
45  std::cerr << "error: '--castxml-cc-" << id
46            << "' compiler command failed:\n\n";
47  for(std::vector<const char*>::const_iterator i = args.begin(),
48        e = args.end(); i != e; ++i) {
49    std::cerr << " '" << *i << "'";
50  }
51  std::cerr << "\n";
52  if(!msg.empty()) {
53    std::cerr << msg << "\n";
54  } else {
55    std::cerr << out << "\n";
56    std::cerr << err << "\n";
57  }
58  return false;
59}
60
61//----------------------------------------------------------------------------
62static void fixPredefines(Options& opts)
63{
64  // Remove any detected conflicting definition of a Clang builtin macro.
65  std::string& pd = opts.Predefines;
66  std::string::size_type beg = 0;
67  while ((beg = pd.find("#define __has", beg),
68          beg != std::string::npos)) {
69    std::string::size_type end = pd.find('\n', beg);
70    if (end != std::string::npos) {
71      pd.erase(beg, end+1 - beg);
72    } else {
73      pd.erase(beg);
74    }
75  }
76}
77
78//----------------------------------------------------------------------------
79static void setTriple(Options& opts)
80{
81  std::string const& pd = opts.Predefines;
82  llvm::Triple triple(llvm::sys::getDefaultTargetTriple());
83  if(pd.find("#define __x86_64__ 1") != pd.npos ||
84     pd.find("#define _M_X64 ") != pd.npos) {
85    triple.setArchName("x86_64");
86  } else if(pd.find("#define __amd64__ 1") != pd.npos ||
87            pd.find("#define _M_AMD64 ") != pd.npos) {
88    triple.setArchName("amd64");
89  } else if(pd.find("#define __i386__ 1") != pd.npos ||
90            pd.find("#define _M_IX86 ") != pd.npos) {
91    triple.setArchName("i386");
92  }
93  if(pd.find("#define _WIN32 1") != pd.npos) {
94    triple.setVendorName("pc");
95    triple.setOSName("windows");
96  }
97  if(pd.find("#define __MINGW32__ 1") != pd.npos) {
98    triple.setEnvironmentName("gnu");
99  }
100  opts.Triple = triple.getTriple();
101}
102
103//----------------------------------------------------------------------------
104static bool detectCC_GNU(const char* const* argBeg,
105                         const char* const* argEnd,
106                         Options& opts,
107                         const char* id,
108                         const char* ext)
109{
110  std::string const fwExplicitSuffix = " (framework directory)";
111  std::string const fwImplicitSuffix = "/Frameworks";
112  std::vector<const char*> cc_args(argBeg, argEnd);
113  std::string empty_cpp = getResourceDir() + "/empty." + ext;
114  int ret;
115  std::string out;
116  std::string err;
117  std::string msg;
118  cc_args.push_back("-E");
119  cc_args.push_back("-dM");
120  cc_args.push_back("-v");
121  cc_args.push_back(empty_cpp.c_str());
122  if(runCommand(int(cc_args.size()), &cc_args[0], ret, out, err, msg) &&
123     ret == 0) {
124    opts.Predefines = out;
125    const char* start_line = "#include <...> search starts here:";
126    if(const char* c = strstr(err.c_str(), start_line)) {
127      if((c = strchr(c, '\n'), c++)) {
128        while(*c++ == ' ') {
129          if(const char* e = strchr(c, '\n')) {
130            const char* s = c;
131            c = e + 1;
132            if(*(e - 1) == '\r') {
133              --e;
134            }
135            std::string inc(s, e-s);
136            std::replace(inc.begin(), inc.end(), '\\', '/');
137            bool fw = ((inc.size() > fwExplicitSuffix.size()) &&
138                       (inc.substr(inc.size()-fwExplicitSuffix.size()) ==
139                        fwExplicitSuffix));
140            if(fw) {
141              inc = inc.substr(0, inc.size()-fwExplicitSuffix.size());
142            } else {
143              fw = ((inc.size() > fwImplicitSuffix.size()) &&
144                    (inc.substr(inc.size()-fwImplicitSuffix.size()) ==
145                     fwImplicitSuffix));
146            }
147            // Replace the compiler builtin include directory with ours.
148            if (!fw && llvm::sys::fs::exists(inc+"/emmintrin.h")) {
149              inc = getClangBuiltinIncludeDir();
150            }
151            opts.Includes.push_back(Options::Include(inc, fw));
152          }
153        }
154      }
155    }
156    fixPredefines(opts);
157    setTriple(opts);
158    return true;
159  } else {
160    return failedCC(id, cc_args, out, err, msg);
161  }
162}
163
164//----------------------------------------------------------------------------
165static bool detectCC_MSVC(const char* const* argBeg,
166                          const char* const* argEnd,
167                          Options& opts,
168                          const char* id,
169                          const char* ext)
170{
171  std::vector<const char*> cc_args(argBeg, argEnd);
172  std::string detect_vs_cpp = getResourceDir() + "/detect_vs." + ext;
173  int ret;
174  std::string out;
175  std::string err;
176  std::string msg;
177  cc_args.push_back("-c");
178  cc_args.push_back("-FoNUL");
179  cc_args.push_back(detect_vs_cpp.c_str());
180  if(runCommand(int(cc_args.size()), &cc_args[0], ret, out, err, msg) &&
181     ret == 0) {
182    if(const char* predefs = strstr(out.c_str(), "\n#define")) {
183      opts.Predefines = predefs+1;
184    }
185    if(const char* includes_str = std::getenv("INCLUDE")) {
186      llvm::SmallVector<llvm::StringRef, 8> includes;
187      llvm::StringRef includes_ref(includes_str);
188      includes_ref.split(includes, ";", -1, false);
189      for (llvm::StringRef i: includes) {
190        if (!i.empty()) {
191          std::string inc = i;
192          std::replace(inc.begin(), inc.end(), '\\', '/');
193          opts.Includes.push_back(inc);
194        }
195      }
196    }
197    fixPredefines(opts);
198    setTriple(opts);
199    return true;
200  } else {
201    return failedCC(id, cc_args, out, err, msg);
202  }
203}
204
205//----------------------------------------------------------------------------
206bool detectCC(const char* id,
207              const char* const* argBeg,
208              const char* const* argEnd,
209              Options& opts)
210{
211  if (strcmp(id, "gnu") == 0) {
212    return detectCC_GNU(argBeg, argEnd, opts, id, "cpp");
213  } else if (strcmp(id, "gnu-c") == 0) {
214    return detectCC_GNU(argBeg, argEnd, opts, id, "c");
215  } else if (strcmp(id, "msvc") == 0) {
216    return detectCC_MSVC(argBeg, argEnd, opts, id, "cpp");
217  } else if (strcmp(id, "msvc-c") == 0) {
218    return detectCC_MSVC(argBeg, argEnd, opts, id, "c");
219  } else {
220    std::cerr << "error: '--castxml-cc-" << id << "' not known!\n";
221    return false;
222  }
223}
Note: See TracBrowser for help on using the repository browser.