Как стать автором
Обновить

Комментарии 6

Доброго дня. Очень интересно. Но есть вопрос. А обязательно использовать Keil MDK, можно ли вместо него тулчейн GCC?

Доброго дня.

Да, конечно, можно и GCC — оно идет по-умолчанию, и уже сто лет как поддерживается.

Просто если хочется отладки с GCC, то нужно выбирать «поставщиков» отладки типа GDB (например, OpenOCD, StLink Utility и прочее).

А вот если хочется отладки с Keil — то «поставщиков» отладки типа UVSC (тех, что имеют префиксы uVision).

А вот чтобы миксовать их, например для GCC использовать поставщик от uVision — я не пробовал. Хотя обратное работает — когда мы отлаживаем код, скомпиленный компилятором от Keil-а в GDB.

xtensa не поддерживается LLVM/CLang, как результат парсинг и модель ломается в QtC. Для себя решил подобным хаком:


xtensa-parsing-wa.diff
diff --git a/src/tools/clangbackend/source/clangtranslationunitupdater.cpp b/src/tools/clangbackend/source/clangtranslationunitupdater.cpp
index 0383a1028f..6aedc231c4 100644
--- a/src/tools/clangbackend/source/clangtranslationunitupdater.cpp
+++ b/src/tools/clangbackend/source/clangtranslationunitupdater.cpp
@@ -106,22 +106,48 @@ void TranslationUnitUpdater::createTranslationUnitIfNeeded()
     if (!m_cxTranslationUnit) {
         m_cxTranslationUnit = CXTranslationUnit();

-        const auto args = commandLineArguments();
-        if (isVerboseModeEnabled())
-            args.print();
-
-        UnsavedFilesShallowArguments unsaved = m_in.unsavedFiles.shallowArguments();
-
-        m_parseErrorCode = clang_parseTranslationUnit2(m_cxIndex,
-                                                     nullptr,
-                                                     args.data(),
-                                                     args.count(),
-                                                     unsaved.data(),
-                                                     unsaved.count(),
-                                                     defaultParseOptions(),
-                                                     &m_cxTranslationUnit);
-
-
+        auto compilationArguments = m_in.compilationArguments;
+
+        for (int i = 0; i < 2; ++i) {
+            const auto args = CommandLineArguments(m_in.filePath.constData(),
+                                                   compilationArguments,
+                                                   isVerboseModeEnabled());
+            if (isVerboseModeEnabled())
+                args.print();
+
+            UnsavedFilesShallowArguments unsaved = m_in.unsavedFiles.shallowArguments();
+
+            m_parseErrorCode = clang_parseTranslationUnit2(m_cxIndex,
+                                                           nullptr,
+                                                           args.data(),
+                                                           args.count(),
+                                                           unsaved.data(),
+                                                           unsaved.count(),
+                                                           defaultParseOptions(),
+                                                           &m_cxTranslationUnit);
+
+
+
+            if (parseWasSuccessful()) {
+                break;
+            }
+
+            // Give a second chance without `--target=xxx` option:
+            // LLVM does not support all GCC targets, like: Microblaze, Xtensa and so on
+            // in such cases, parsing fails. By default, LLVM fallback to i386 or x86_64 targets
+            // according -m32/-m64 options.
+            int j;
+            for (j = 0; j < compilationArguments.count(); ++j) {
+                if (compilationArguments.at(j).startsWith("--target="))
+                    break;
+            }
+            if (j < compilationArguments.count()) {
+                compilationArguments.remove(j);
+            } else {
+                // `--target=` not found
+                break;
+            }
+        }

         if (parseWasSuccessful()) {
             updateIncludeFilePaths();
@@ -217,11 +243,4 @@ bool TranslationUnitUpdater::reparseWasSuccessful() const
     return m_reparseErrorCode == 0;
 }

-CommandLineArguments TranslationUnitUpdater::commandLineArguments() const
-{
-    return CommandLineArguments(m_in.filePath.constData(),
-                                m_in.compilationArguments,
-                                isVerboseModeEnabled());
-}
-
 } // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangtranslationunitupdater.h b/src/tools/clangbackend/source/clangtranslationunitupdater.h
index a0f0d0ba3b..fa535e2c69 100644
--- a/src/tools/clangbackend/source/clangtranslationunitupdater.h
+++ b/src/tools/clangbackend/source/clangtranslationunitupdater.h
@@ -85,7 +85,6 @@ public:

     TranslationUnitUpdateResult update(UpdateMode mode);

-    CommandLineArguments commandLineArguments() const;
     static uint defaultParseOptions();

 private:

Аналогичная ситуация с Microblaze (патч решает и для него). Первый нужен как часть хобби, второй был нужен (и, возможно, потребуется) по работе.


PS мне проще, я регулярно собираю QtC из исходников с master'а, поэтому наложить патч не проблема.

> xtensa не поддерживается LLVM/CLang, как результат парсинг и модель ломается в QtC

Да, у QtC шного парсера (что clang, что дефолтного) проблемы с парсингом кода для специфичных архитектур. Например, если имеются какие-нибудь особенные ключевые слова (например, для 8051 такие как 'data', 'xdata', 'sfr' и прочие), которых парсер не знает.

Я даже баг-трекер создавал с предложением расширить парсеры так, чтобы можно было из любых плагинов QtC дополнять словарь ключевых слов для текущего выбранного тулчейна (хотя-бы для встроенного не-clang парсера). Например, если используем тулчейн от Keil и архитектура 8051 — то «подключаем» ключевые слова именно для этой архитектуры и этого тулчейна и т.д. Но что-то никто не хочет с этим связываться.

Но а по поводу xtensa я что-то не понял в чем там проблема? Ведь там используется обычный GCC. Правда, я использую с xtensa (esp8266) всегда встроенный парсер вместо clang-овского, т.к. он менее глючный.
Ведь там используется обычный GCC.

так GCC не используется для построения кодовой модели. А libllvm сталкивается с тем, что не знает xtensa. Если коротко (можно поглядеть на патч) то передаётся триплет target= с указанием xstensa-что-то-там и парсер для юнита тупо завершается ошибкой. В результате юнит вообще не парсится и спользуется только базовая подстветка синтаксиса. Как бы так. WA заключается в том, что сначала попытаться парсить с переданной строкой, а потом исключать "--target" и попытаться снова. Да, будет сделано предположение, что это x86 или x86_64, но для моих целей этого оказалось достаточно.


В общем, парсер на основе clang будет ломаться всегда, если clang не знает каких-то архитектур. И то, что для сборки используется GCC, IAR или что-то ещё никакой роли не играет :)

Ах, ясно. Я почему-то думал, что clang-овский парсер более гибкий, что ему можно как-то подсунуть список ключевых слов и прочее, без указания триплетов… Но, видать — не судьба.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории