LINUX.ORG.RU

Qt + CMake + stdafx

 , ,


0

1

После нескольких лет использования связки IDE Code Blocks + RAD-редактор Glade наконец перешёл на Qt. Дело в том, что во всех проектах я всегда использовал связку файлов stdafx.h + stdafx.cpp с общими заголовками, определениями и функциями. Тупо включал во все файлы кода и горя не знал — весь код в редакторе отображался без ошибок, а данные файлы всегда присутствовали в списке файлов проекта (необходимо для их редактирования). Я никогда не пользовался настоящим предкомпилированным заголовком (PCH), да и мне это не было нужно, тем более, что в последние годы использовал Ccache.

Однако перейдя на Qt, мне пришлось изрядно повозиться, не спроста я обходил его стороной более десяти лет. Вроде как во всём разобрался, НО, файлы кода отображались корректно, а в заголовочных файлах вылазила куча ошибок, так как включить stdafx.h в файл кода оказалось недостаточно, тем не менее компилировалось всё корректно. Пришлось добавить файлы stdafx.* дополнительно в target_precompile_headers, заголовочные файлы стали отображаться корректно. НО, нормально скомпилировался лишь один проект, а все остальные ругаются на переопределение функций, так как для отображения данных файлов пришлось оставить их ещё и в add_executable.

И вот главный вопрос: как мне добиться корректного отображения в редакторе своих заголовочных файлов одновременно с отображением файлов stdafx.* в списке файлов проекта? Если на то пошло, PCH как таковой мне не нужен…



Последнее исправление: NativeEngine (всего исправлений: 1)

stdafx.h

Выглядит, как что-то форточное. Выбрось каку, я на 99% уверен, что оно тебе не нужно.

И я не понял, при чём тут PCH. Никогда ими не пользовался

XMs ★★★★★
()
Последнее исправление: XMs (всего исправлений: 1)

Однако перейдя на Qt, мне пришлось изрядно повозиться, не спроста я обходил его стороной более десяти лет.

Напротив, ты должен сказать Qt Creator’у большое спасибо.

Ведь ты целых десять лет пользовался типичной майкрософтовской «bad practice» и тянул непереносимый и откровенно уродский global-state-костыль-каку «stdafx.h» в рот, узнал про которую ты наверняка из убогого студенческого курса МГУ или брошюрам по типу «C++ за 21 день», а потом и гадил этим «stdafx.h» в куче проектов.

А Qt Creator сразу ударил тебя по рукам и дал тебе шанс научиться писать код без виндузотно-помойного «stdafx.h»

EXL ★★★★★
()
Ответ на: комментарий от EXL

А Qt Creator сразу ударил тебя по рукам и дал тебе шанс научиться писать код без виндузотно-помойного «stdafx.h»

А без него — это как??? Можно ссылку на подобный проект, чтобы понять, как мне расшаривать для проекта «правильный» аналог заголовков, определений и кода stdafx?

NativeEngine
() автор топика
Ответ на: комментарий от NativeEngine

Давай так: вот есть у тебя проект. О чём он? Какую роль в нём выполняет этот stdafx.h? Хорошее правило (не универсальное, но для начала сойдёт) — каждый класс хранится в своём хедере, не больше одного на хедер. Если применить это правило на твой проект, что останется в этом stdafx.h?

XMs ★★★★★
()
Ответ на: комментарий от XMs

Если в двух словах, то в stdafx вынесено всё, что используется в разных частях проекта, например, цветной вывод в консоль. Мне даже в проекте с единственным main.cpp удобно не загаживать файл с функцией main, а вынести все отдельные функции в stdafx. Если ты не можешь помочь мне советом, как его корректно добавлять в связку Qt + CMake, я уж лучше как-нибудь сам разберусь. Всегда проклинал себя за то, что регистрировался на каком-нибудь бестолковом гейдев.ру и снова повторяю ту же ошибку. Реально проще перерыть добрую половину интернета и в итоге разобраться самому, нежели всем любопытным что-то доказывать!

NativeEngine
() автор топика
Ответ на: комментарий от NativeEngine

Если в двух словах, то в stdafx вынесено всё, что используется в разных частях проекта, например, цветной вывод в консоль

Т. е. это просто общая библиотека, а не часть WinAPI? Тогда переименуй, потому что stdafx — это часть стандартного виндового API.

Если это просто библиотека, то в чём сложность просто собрать её отдельно и прилинковать? Раз у тебя CMake, то как-то так:

…
add_library(common SHARED <сорцы либы>)
…
add_executable(app <сорцы приложения>)
target_link_libraries(app <Qt-либы> common)

На самом деле, в простых случаях можно даже отдельно не собирать, но это уже отдельная песня.


Всегда проклинал себя за то, что регистрировался на каком-нибудь бестолковом гейдев.ру и снова повторяю ту же ошибку. Реально проще перерыть добрую половину интернета и в итоге разобраться самому, нежели всем любопытным что-то доказывать!

Бесполезные эмоции тебе не помогут

XMs ★★★★★
()

Дело в том, что во всех проектах я всегда использовал связку файлов stdafx.h + stdafx.cpp с общими заголовками, определениями и функциями.

Если ты не собираешься использовать предкомпилированные заголовки, у тебя вообще не должно быть никаких помойных файлов типа stdafx.cpp + stdafx.h. Разбивай проект на отдельные cpp + h файлы и в каждом их них прописывай #include всех хедеров, которые реально в этом файле нужны.

Например, если как ты говоришь, тебе нужен цветной вывод в консоль, то в простейшем случае ты можешь сделать класс-синглетон Logger в файлах logger.cpp + logger.h. Затем везде, где тебе нужен логгер, подключаешь его через #include "logger.h". То же самое делаешь для всех остальных общих классов и функций. А не сваливаешь все классы и функции в глобальную помойку stdafx.h.

Можно ссылку на подобный проект

Да любой пример из культей. Например виджеты:

https://doc.qt.io/qt-6/qtexamplesandtutorials.html#user-interface-components

Если ты посмотришь код примеров, да хотя бы самый первый Address Book, то нигде не найдешь шлак типа stdafx.h. Это - антипаттерн. Так никто не пишет. Советую потратить время, выпилить с корнем stdafx.h и распределить его содержимое между всеми остальными файлами в проекте.

И вот главный вопрос: как мне добиться корректного отображения в редакторе своих заголовочных файлов

Они и так должны нормально отображаться, если ты перечислишь их в qt_add_executable. По CMake + Qt можешь еще почитать официальную документацию:

https://doc.qt.io/qt-6/cmake-get-started.html

archie
()
Последнее исправление: archie (всего исправлений: 1)
Ответ на: комментарий от NativeEngine

гейдев.ру

Рассадник виндузни. Вряд ли там имеет смысл спрашивать хоть что-нибудь конкретно по онтопику. Впрочем по GAPI и движкописанию там могут помочь.

archie
()
Ответ на: комментарий от NativeEngine

Всегда проклинал себя за то, что регистрировался на каком-нибудь бестолковом гейдев.ру и снова повторяю ту же ошибку.

Научись правильно описывать свою проблему. Из твоего путанного рассказа сложно понять суть. Где ссылка на проект или хотя бы куски CmakeList.txt?

Реально проще перерыть добрую половину интернета и в итоге разобраться самому, нежели всем любопытным что-то доказывать!

Звучит как

Да и пофигу на разваливающиеся костыли, подопру ещё парочкой и замотаю изолентой.

anonymous
()
Ответ на: комментарий от NativeEngine

Можно ссылку на подобный проект, чтобы понять, как мне расшаривать для проекта «правильный» аналог заголовков, определений и кода stdafx?

Никак не надо его расшаривать. Используешь класс – прописываешь в коде соответствующий заголовочник. Так сразу видно, от чего твой файл зависит.

всё, что используется в разных частях проекта

Так надо это не в один файл валить, а тоже структурировать. В библиотеку общих классов и функций. И группировать их по тематике. Хотя… если в твоём проекте не больше 30 классов, у тебя может прокатить и так.

hobbit ★★★★★
()

stdafx.h stdafx.cpp - их добавляй в add_executable своей основной цели, это ок.

все остальные ругаются на переопределение функций

Ты инклудишь stdafx.h в разных cpp файлах? stdafx.h содержит определения функций (тело функций)? Если да, то выноси их в stdafx.cpp.

stdafx.h в твоих cpp файлах инклудится первым?

rumgot ★★★★★
()
Последнее исправление: rumgot (всего исправлений: 2)

И вот главный вопрос: как мне добиться корректного отображения в редакторе

В КАКОМ РЕДАКТОРЕ?

Code Blocks? Qt Creator? Notepad?

Всегда проклинал себя за то, что регистрировался на каком-нибудь бестолковом гейдев.ру и снова повторяю ту же ошибку. Реально проще перерыть добрую половину интернета и в итоге разобраться самому, нежели всем любопытным что-то доказывать!

А ты уверен, что из вас двоих это именно гейдев.ру «бестолковый»?

LamerOk ★★★★★
()

У Qt Creator для подсветки ошибок в редакторе используется clang code model. Иногда он глючит, я тоже с таким сталкивался. Проект собирается, а в редакторе много мест отмечено как ошибочные. Возможно дело в том, что в исходниках у тебя есть вещи, которые компилятор, которым ты собираешь проект (mingw? микрософтовский?) понимает, а clang из анализатора кода - нет.

Beewek ★★
()
Ответ на: комментарий от Beewek

В догонку: список проблем clang code model. Список довольно старый, но идея ясна - если твой проект не совместим с clang, то выхода два - либо отключить clang code model, либо попытаться сделать свой проект совместимым с clang.

Beewek ★★
()
Ответ на: комментарий от Beewek

Я пользуюсь KDev вместо QtCreator, там тоже clang для подсветки используется, только он сам не видит код из включаемых файлов, он начинает выдавать правильную подсветку и всё прочее только после анализа того, какие зависимости и включаемые файлы прописаны в CMakeLists.txt.

Я давно смотрел, но вроде как QtCreator использует KDE'шный KSyntaxHighlighter, так что думаю там принцип работы скорее всего такой же.

Dr64h ★★★
()
Ответ на: комментарий от XMs

Это такой старый мелкософтовский костыль для PCH был, у них в MSVS он по умолчанию генерился вместе с созданием проекта. Сейчас его вроде переименовали в pch.h, как в других проектах сделано, которые используют PCH.

В прочем, насколько знаю, PCH сейчас признан антипаттерном.

Dr64h ★★★
()
Ответ на: комментарий от Dr64h

Просто PCH нужен только для того, чтобы ускорить сборку с очень неторопливым MSVC на такой же неторопливой винде. Зная какой плохой генерит код MSVC это даже неудивительно.

GCC и Clang с него выигрывают, но крайне мало. Недостаточно, чтобы портить весь проект.

stdafx.h, да, просто в дефолтном шаблоне всегда создавался, даже если планов PCH использовать не было. Прикольно что он начинается на std, будто это какой-то стандартный хедер. Но конечно же это не так

a1ba ★★
()
Последнее исправление: a1ba (всего исправлений: 1)

Всегда проклинал себя за то, что регистрировался на каком-нибудь бестолковом гейдев.ру и снова повторяю ту же ошибку. Реально проще перерыть добрую половину интернета и в итоге разобраться самому, нежели всем любопытным что-то доказывать!

Ты пришёл сюда за советом - так слушай советы, и будь благодарен что тебе не твои сломанные костыли чинят, а рассказывают как ходить без них.

Если в двух словах, то в stdafx вынесено всё, что используется в разных частях проекта, например, цветной вывод в консоль.

Почему это вынесено в stdafx? Должно быть вынесено в colored_console_output.{h,cpp} (а другая функциональность - в свою пару .cpp/.h), .cpp включен в сборку, а .h во все исходники где он используется. Это гарантировано будет правильно собираться и подсвечиваться, вдобавок ускорит компиляцию (во-первых потому что в каждый исходник включается только нужные определения, а не вся помойка, во-вторых, потому что изменение модуля затрагивает только код его использующий, а не весь проект) и упростить переиспользование кода (потому что в другой проект можно скопировать только нужный модуль).

Мне даже в проекте с единственным main.cpp удобно не загаживать файл с функцией main, а вынести все отдельные функции в stdafx.

Это правильно, но почему тебе тогда удобно загаживать stdafx, вместо того чтобы разнести всё по модулям?

anonymous
()
Ответ на: комментарий от NativeEngine

Если это что-то вспомтгательное то я например размещаю жто в Misc.h, Misc.cpp или в Utils.h, Utils.cpp или Tools.h, Tools.cpp

Под Windosws, в Visual Studio пишу частенько, и перввм делом, создав новый проект (хотя если изначально создавать пустой то и не будет stdafx, но если я например создал не пустой а по-шаблону, то...), удаляю из него stdafx.

А еще если проект планируется переносимым (это не обязательно высокоуровневые либы, можно и WinApi, просто для Linux свою реализацию) тогда инетрфейс и общач реализация в единой паре скажем Tools h/cpp, но будет еще пподпапки OsDependet/Windows, OsDependet/Linux.

И такой проект удобнее всего создавать в Cmake, после чего из cmake в командной строке генерировать прокет для целевой платформы: например Makefile для Linux и Visual Stdudio Solution - для Windows CMake сгенерирует решение для импорта в Visual Studio.

bonta ★★★★★
()
Ответ на: комментарий от a1ba

А пруфы будут что msvc генерит плохой код, а Винда медленнее Linux?

Так то например в ядре Linux'а до сих пор невыведены полностью проблемы гигантских блокировок, а в Window NT их не было изначально by design.

bonta ★★★★★
()
Ответ на: комментарий от bonta

А пруфы будут что msvc генерит плохой код

Да, залезь декомпилятором в бинарники сгенеренные MSVC и GCC. То что генерит MSVC с зачастую отсуствующими анроллами, инлайном, удалением ненужных бранчей не может быть быстрым.

Винда медленнее Linux

Это уже по ощущениям. Всё что обращается к ФС кажется медленнее. Бенчмарки не проводил, мне насрать, искать причины пользоваться или не пользоваться виндой мне не нужно, потому что я и так ей не пользуюсь.

a1ba ★★
()
Последнее исправление: a1ba (всего исправлений: 2)
Ответ на: комментарий от bonta

Так то например в ядре Linux’а до сих пор невыведены полностью проблемы гигантских блокировок, а в Window NT их не было изначально by design.

И к чему это приводит при сравнении производительности данных ос?

rumgot ★★★★★
()

Однако перейдя на Qt, мне пришлось изрядно повозиться, не спроста я обходил его стороной более десяти лет.

Это не Qt, а CMake. qmake простой как валенок.

s3rjke
()
Ответ на: комментарий от bonta

Так то например в ядре Linux’а до сих пор невыведены полностью проблемы гигантских блокировок, а в Window NT их не было изначально by design.

Да каэш, расскажи что там всё на асинхронщине и файберах изначально было. Магии не бывает, у NT точно такие же, местами всё ещё очень крупногранулярные, блокировки. Ядро родившееся во времена когда родилось ядро NT, вообще говоря, по другому пути и не могло пойти - ядер было мало, обычный код выполнялся долго, крупногранулярных блокировок более чем хватало для всего, включая даже сетевую подсистему и IPC, писать уберинфру для безблокировочной многопоточности в ядре было абсолютно экономически не выгодно.

anonymous
()
Ответ на: комментарий от anonymous

Ядро NT разрабатывал крутой инженер - Дейв Кетлер, и там изначально ядро разрабатывалось с поддержкой SMP (при том ещё в те времена когда многопроцессороностью вы бытовых компьютерох даже и не пахло).

А вот Ядро Линукса изначально писалось как можно проще - отсюда и до сих пор отголоски есть.

bonta ★★★★★
()
Ответ на: комментарий от bonta

Ядро NT разрабатывал крутой инженер - Дейв Кетлер

Не создавай себе кумира. Инженерами не рождаются, ими становятся набираясь опыта.

EXL ★★★★★
()
Ответ на: комментарий от rumgot

К тому что в Windows не только Firefox быстрее работает, но и во многих тестах кроссплатформенное ПО под Windows быстрее чем под Linux? Например по сравнению с Ubuntu 20.04 Windows 10 была в лучшейв 38 тестах из 55.

https://www.phoronix.com/review/ryzen-4700u-windows

p.s.1. Кстати шустрее Linux в среднем так же и FreeBSD

p.s.2. В результатах тестов рассуждают что типа возможно дело в системе управления частотой процессора и энергопотреблением - но я думаю что просто в Windows эффективнее работает планировщик процессов, эффективнее работает подсистема виртуальной памяти.

Что удивительно ведь в Linux ядро это больше монолит, а в Windows больше похоже на микроядро, хотя и там и там это не чистые концепты монолита и микроядра и гибриды. Но системы на монолитных ядра должны быть намного шустрее по идее...

bonta ★★★★★
()
Последнее исправление: bonta (всего исправлений: 1)
Ответ на: комментарий от anonymous

для безблокировочной многопоточности в ядре было абсолютно экономически не выгодно.

Как раз было очень выгодно, т.к. Microsoft старалась заложить переносимую и универсальную архитектуру, не привязанную только на x86.

По крайней мере именно так говорится в книге Helen Custer - Inside Windows NT.

Ну а так же у них сырцы же в сеть утекали, не знаю есть ли там ядро, но если есть то можно когда-нибудь поизучать на досуге :)

bonta ★★★★★
()
Ответ на: комментарий от bonta

Я в силу текущей работы очень редко использую линукс, однако во времена Ubuntu/Kubuntu 18:04-22.04 на моем рабочем компьютере и личном ноуте Kubuntu работала по производительности примерно на уровне Windows 7 если судить по офисным программам и графическому окружению. Графика скорее всего на винде лучше по причине лучших драйверов от производителей. С другой стороны опять-таки, драйвера под линукс делают на отъепись, поэтому что-то удивляться…

rumgot ★★★★★
()
Ответ на: комментарий от bonta

там изначально ядро разрабатывалось с поддержкой SMP (при том ещё в те времена когда многопроцессороностью вы бытовых компьютерох даже и не пахло).

Ты меня не слушаешь. Любое ядро разрабатывалось с поддержкой SMP, но с эффективной даже на оборудовании того времени оно разрабатываться не могло чисто по законам рынка, не говоря уже что под современное железо всё нужно было переписать с нуля. Ещё раз, NT шло по тому же пути что и Linux, не было там никакой магии и даже fine-grained lockingа когда-то не было.

Например по сравнению с Ubuntu 20.04 Windows 10 была в лучшейв 38 тестах из 55.

Давай забудем на минуту что это ламерский фороникс, сколько из этих тестов меряют параллельность в ядре? Чсх, я не видел тестов вне фороникса где винда бы выигрывала в чём-то кроме desktop responsiveness, а уж в параллельных вычислениях она значительно отставала вообще всегда. TOP500 не даст соврать.

p.s.1. Кстати шустрее Linux в среднем так же и FreeBSD

При этом во FreeBSD от giant lock начали избавляться когда в linux уже и слово уже и не помнили. Что ещё раз доказывает что измерения проведены некомпетентно.

p.s.2. В результатах тестов рассуждают что типа возможно дело в системе управления частотой процессора и энергопотреблением - но я думаю что просто в Windows эффективнее работает планировщик процессов, эффективнее работает подсистема виртуальной памяти.

Действительно, когда названа наиболее вероятная причина, самое логичное что можно сделать это забить на это и сделать своё необоснованное предположение.

anonymous
()
Ответ на: комментарий от bonta

Как раз было очень выгодно, т.к. Microsoft старалась заложить переносимую и универсальную архитектуру, не привязанную только на x86.

Ога, поэтому на 64бита там переползали с таким трудом, а под армы оно появилось для широких масс лет через 15 после линукса.

anonymous
()
Ответ на: комментарий от anonymous

На arm-ы они переползали без труда, как и на другие архитектуры. У них нет цели выпендрится типа «мы собрали ядро для такой-то архитектуры, еще до выпуска физически процессоров на ней», когда они видят рыночные перспективы тогда и портируются на новую архитектуру.

Так-то, Windows поддерживали любые успешные архитектуры в свое время: mips, powerpc, dec alpha на которые ядро NT по сути вставало почти без необходимости переписывания.

говоря уже что под современное железо всё нужно было переписать с нуля

Зачем? Для освоения новой архитектуры достаточно переписать аппаратно зависимый слой, который в хорошо спроектированной системе стремятся и минимизировать, и максимально изолировать ядро от работы с аппаратной частью непосоедсьвенно. Например в «исполнительной системе NT» непосредствено от аппаратуры завист только HAL и совмем немного диспетчер виртуальной памяти. А в самом ядре вообще нет никакого аппаратно зависимого кода, написано на Си, без asm вставок, поэтому на тех же arm, dec, alpha, x86_64 по сути раблтает один и тот же код ядра, перекомпилированный под них, но использующий разный HAL и разные кусочки по ifdef из реализации работы с TBL в диспетчере памяти.

Давай забудем на минуту что это ламерский фороникс, сколько из этих тестов меряют параллельность в ядре?

Абсолютно нормальный ресурс. Так дело не только в параллельности в ядре, я лишь конкретный пример привел где у Windows проблем не было изначально by design. А параллельность в ядре косвенно мереется в многопоточно-многопроцессных аппах, в тех же запусках бенчмарков в Файрфоксе, упомянутых в Форониксе.

И это нормально, недавно интересовался темой почему на роутерах так любят ядро 2.6, и такого рода гуглежка выводит на статью где сравнивают новшества 2.4 vs 2.6 и как раз рассуждают о обновлении многопточного кода на сколько он стал лучше на римере тесотов всего лишь на всего запуска вебсервера и кучи запросов к нему - такая же косвенная методика как и с запуском Файрфокса, тк он плодит процессы и потоки внутри.

При этом во FreeBSD от giant lock начали избавляться когда в linux уже и слово уже и не помнили. Что ещё раз доказывает что измерения проведены некомпетентно.

Это еще может говорить о том что giant lock всего лишь одна из проблем, не вкладывающая основной вклад в общую производительность. Значит в Linux есть и другие проблемы из-за которых FreeBSD и Windows забирают баллы по тестам.

И причем здесь Top-500? Все бы Windows на супер компьютеры ставили. Но при этом стоит понимать что поголовное засили Lunux в суперкомпьютерах не потому что ое технологически ьучше Windows, а только по одному факту - потому что gpl, потому что такие маширы супер дорогие, а gpl защищает от внезапных капризов ентерпрайза, ну и просто открытый код...

Самая адекватная метрика эффективночти ос это как раз дестоп и серверы, но не суперкомпьютеры.

bonta ★★★★★
()
Ответ на: комментарий от anonymous

Ога, поэтому на 64бита там переползали с таким трудом

Потому, что у них обязательным условием было сохранение двоичной совместимости со старым софтом. Линуксовый опенсорс достаточно просто пересобрать (и то не всегда, я помню, сам посылал патч одному автору, который void* к int приводил), с проприетарщиной так не получится.

Да, линукс-дистрибутивы перешли-то быстро, но вот поддержку 32-разрядных программ в 64-разрядных системах допиливали ещё долго и мучительно. Я помню, в какой-то из дебианов всего-навсего добавил архитектуру i386 и запустил аптом обновление — полсистемы, включая иксы и кеды, как корова языком слизнула, пришлось руками восстанавливать. Потом это починили, да.

hobbit ★★★★★
()
Последнее исправление: hobbit (всего исправлений: 1)
Ответ на: комментарий от bonta

Жаль царь больше сюда не заходит, некому пояснить за винду.

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

anonymous
()