From a4c64dbc8dc17d953ef4e59b7c535e69e0428af7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20M=C3=BCller?= Date: Mon, 24 Sep 2018 16:28:16 +0200 Subject: [PATCH] Implement a search for the clang binary --- include/cppast/libclang_parser.hpp | 7 +++--- src/libclang/libclang_parser.cpp | 36 ++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/include/cppast/libclang_parser.hpp b/include/cppast/libclang_parser.hpp index 9d2f64f..6bac8c2 100644 --- a/include/cppast/libclang_parser.hpp +++ b/include/cppast/libclang_parser.hpp @@ -118,11 +118,10 @@ public: /// \effects Sets the path to the location of the `clang++` binary and the version of that /// binary. + /// If the binary is not found, it will try and search for it. + /// \returns `true` if the binary was found exactly as specified. /// \notes It will be used for preprocessing. - void set_clang_binary(std::string binary) - { - clang_binary_ = std::move(binary); - } + bool set_clang_binary(std::string binary); /// \effects Sets whether or not the preprocessed file will be written out. /// Default value is `false`. diff --git a/src/libclang/libclang_parser.cpp b/src/libclang/libclang_parser.cpp index 47bdf40..0732aef 100644 --- a/src/libclang/libclang_parser.cpp +++ b/src/libclang/libclang_parser.cpp @@ -9,6 +9,7 @@ #include #include +#include #include "cxtokenizer.hpp" #include "libclang_visitor.hpp" @@ -18,6 +19,7 @@ #include "raii_wrapper.hpp" using namespace cppast; +namespace tpl = TinyProcessLib; const std::string& detail::libclang_compile_config_access::clang_binary( const libclang_compile_config& config) @@ -240,6 +242,40 @@ libclang_compile_config::libclang_compile_config(const libclang_compilation_data } } +namespace +{ +bool is_valid_binary(const std::string& binary) +{ + tpl::Process process(binary + " -v", "", [](const char*, std::size_t) {}, + [](const char*, std::size_t) {}); + return process.get_exit_status() == 0; +} +} // namespace + +bool libclang_compile_config::set_clang_binary(std::string binary) +{ + if (is_valid_binary(binary)) + { + clang_binary_ = binary; + return true; + } + else + { + // first search in current directory, then in PATH + static const char* paths[] + = {"./clang++", "clang++", "./clang++-4.0", "clang++-4.0", "./clang++-5.0", + "clang++-5.0", "./clang++-6.0", "clang++-6.0", "./clang-7", "clang-7"}; + for (auto& p : paths) + if (is_valid_binary(p)) + { + clang_binary_ = p; + return false; + } + + throw std::invalid_argument("unable to find clang binary '" + binary + "'"); + } +} + void libclang_compile_config::do_set_flags(cpp_standard standard, compile_flags flags) { switch (standard)